Click event only fires when element is placed in header - javascript

I've got a single-page app UI with a custom navigation script. The script works perfectly in a minimally styled test page, but when I bring it into the actual app UI, it starts getting wonky and the click events are not firing consistently the way that I'd expect them to.
I have click events bound to each of the links, but the events only seem to fire when the element is placed in the header.
The HTML
<header>
<a data-role="navigation" data-target-view="mainView">Home</a>
<a data-role="navigation" data-target-view="settings">Settings</a>
<a id="headerLink" data-role="navigation" data-target-view="detailsView">Details</a>
</header>
<section data-role="page">
<section id="mainView" data-role="view">
<section class="pageContent">
</section>
<footer class="pageFooter">
<a id="footerLink" data-role="navigation" data-target-view="detailsView">Details</a>
</footer>
</section>
<section id="detailsView" data-role="view">
<section class="pageContent">
</section>
<footer class="pageFooter">
</footer>
</section>
<section id="settings" data-role="view">
<section class="pageContent">
</section>
<footer class="pageFooter">
</footer>
</section>
</section>
Handler Registration
$(document).ready(function(){
$("[data-role='navigation']")
.unbind("click.cgt_pathfinder")
.bind("click.cgt_pathfinder",function(event){
alert("Triggered");
});
});
I've stripped out the actual navigation logic just to make this easier to follow.
The Issue
When I load the page, I've got a breakpoint set on my handler registration, and I can see all the elements retrieved by $("[data-role='navigation']"). I see 4 elements: The three links in the <header>, and the one solitary link in the .pageFooter section of #mainView.
You'll notice that (save for the ID attribute and their location on the page), #headerLink and #footerLink are identical.
When I click #footerLink, nothing happens. I know the element was picked up when I registered my event handler, so it should issue the "Triggered" alert message, but it doesn't.
I've also tried moving #footerLink around the document (pulling it up one layer at a time and testing at each stop. The event did not fire until the link was in the <header>
When I click #headerLink, the event fires exactly as expected. In this example, I receive the "Triggered" message, and in the actual app, I see a successful navigation event.
So, the question is: "What am I missing?" There's something different about #footerLink that's preventing the event from firing, but I'm at a loss.

Possibly typo and unbalanced tag
<section data-role="page">
<section id="mainView data-role="view"> // No (") for id
<section class="pageContent">
</section>
Near bottom of markup
</settings> // No opening tag for settings
</section>
Working jsfiddle

I have checked your case. But it is working fine for me.
Please replace your jQuery function with this:
$(document).ready(function(){
$("[data-role='navigation']").unbind("click.cgt_pathfinder").bind("click.cgt_pathfinder",function(event){
alert("Triggered = "+$(this).text());
});
});

Does your code dynamically update the #footerLink element ?
If this element gets added to the page by your code (e.g : through a $('.pageFooter').append(html)), you will need to bind back the click action to this new element.
Is there any other code (yours or some plugin's) which could alter the click event handlers in your page, but not in your header ?

Related

How to scroll to element after click event and new page load with Vanilla JavaScript

I will try to summarize this in a Requirements fashioned way, I hope this simplifies the question.
When clicking on an anchor tag, the web page navigates the user to a new page, where upon page load, the page is scrolled to the element which corresponds to the aforementioned anchor tag, which was previously clicked.
As you will see in the code I am trying to make use of the CSS scroll-behaviour property.
https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior
So far I have tried out the code bellow, however when I run it I get an error message in the developer console stating:
TypeError: Cannot read property 'offsetTop' of undefined
Hence, I surmise that the window.onload function is not really fired on the page which I would like to load but the very same page on which I am located when clicking the anchor tag. How can I change the code so it would count for page intended.
HTML of Page A (where the anchor tag is located):
<a id="ship-it" href="services.html" class="services">
<div id="image-container_4">
<div id="image_4">
<div id="overlay_4"></div>
<h2 class="h2">We pack it and ship it</h2>
<img id=imageB src="/images/shipping.jpg" alt="">
</div>
</div>
</a>
HTML of Page B (where the target element is located):
<section id="manufacturing-section" class="section">
<img src="/images/manufacturingMelting2.jpg" alt="Magnetic Particle Inspection">
<div id="manufacturing-container">
<h2> <span>Manufacturing</span> <br> We provide high quality, low cost solutions to meet your requirements.</h2>
<p>
soemthing something something, DarkSide...
</p>
</div>
</section>
JS / CSS:
function scrollIt(element) {
window.scrollTo({
'behavior': 'smooth',
'left': 0,
'top': element.offsetTop
});
}
const serviceAnchor = document.querySelectorAll('.services');
//'serviceAnchor' is located on page A
const sections = document.querySelectorAll('.section');
// 'sections' is located on page B and represents the element the page should scroll to when the page has loaded after the corresponding anchor tag was clicked
serviceAnchor[0].addEventListener('click', () => {
window.onload = scrollIt(sections[0]);
});
serviceAnchor[1].addEventListener('click', () => {
window.onload = scrollIt(sections[1]);
});
serviceAnchor[2].addEventListener('click', () => {
window.onload = scrollIt(sections[2]);
});
serviceAnchor[3].addEventListener('click', () => {
window.onload = scrollIt(sections[3]);
});
The reason you're getting the error is it's impossible to run javascript across page loads. Assuming you're using a traditional site and not a single-page app, when the browser loads a new page, all javascript on the current page is stopped.
Browsers already support jumping to an element on page load using the www.site.com#myElementId syntax. If you want smooth scrolling, you'll need to pass the id of element to scroll in the url, or some other way like caching its id in localstorage, then run your smooth scrolling js on the pageload of the other page.
You can't navigate to a different page and then ask the browser to launch a piece of JavaScript. That would be a huge security issue, since I could make you click into a link to, let's say, my-bank.com then do a bit of JavaScript do access your secret cookies or local storage and hack into your account.
The only thing you can do is link to anchors inside the linked page, and the default scroll behavior (no smooth scrolling, for most browsers, since it's the least computationally and resources intensive) will be used:
<!-- not possible -->
<a onclick="navigateThenDoSomething()">Some link</a>
<!-- possible -->
Some link
If you own the target page, however, you can hide a target section in the query string then do a bit of magic in the target page's onload to smoothly scroll to your section:
<!-- source-page.html -->
Some link
// script running at target-page.html
const url = new URL(window.location);
const section = url.searchParams.get('section');
if (section) {
// scroll smoothly to `section` using
}
Since .scrollTo JS method with options has the same browser compatibility as scroll-behavior CSS property, and you're OK with that, you might get rid of your JS code and set:
html, body, .or-other-scrolling-container {scroll-behavior:smooth}
and use anchor links.
So HTML of Page A would be e.g.:
<a id="ship-it" href="services.html#manufacturing" class="services">
<div id="image-container_4">
<div id="image_4">
<div id="overlay_4"></div>
<h2 class="h2">We pack it and ship it</h2>
<img id=imageB src="/images/shipping.jpg" alt="">
</div>
</div>
</a>
And HTML of Page B (please note <a name="#manufacturing"> tag):
<a name="manufacturing"></a>
<section id="manufacturing-section" class="section">
<img src="/images/manufacturingMelting2.jpg" alt="Magnetic Particle Inspection">
<div id="manufacturing-container">
<h2>
<span>Manufacturing</span><br>
We provide high quality, low cost solutions to meet your requirements.
</h2>
<p>something something something, DarkSide...</p>
</div>
</section>
Working example:
html {scroll-behavior:smooth}
.long {height:100vh; background:#efc}
<a id="ship-it" href="#manufacturing" class="services">
<div id="image-container_4">
<div id="image_4">
<div id="overlay_4"></div>
<h2 class="h2">We pack it and ship it</h2>
<img id=imageB src="https://picsum.photos/50/50" alt="">
</div>
</div>
</a>
<section class="long">Placeholder to enable scroll</section>
<a name="manufacturing"></a>
<section id="manufacturing-section" class="section">
<img src="https://picsum.photos/400/220" alt="Magnetic Particle Inspection">
<div id="manufacturing-container">
<h2>
<span>Manufacturing</span><br>
We provide high quality, low cost solutions to meet your requirements.
</h2>
<p>something something something, DarkSide...</p>
</div>
</section>
Hope it helps.

ngInfiniteScroll Triggered Once Upon Page Loading

I am using ngInfiniteScroll on my webpage to allow for infinite scrolling. I have it working except for one thing. When the page initially loads, ngInfiniteScroll seems to get triggered and I don't know why.
I attach ngInfiniteScroll to a link which appears at the bottom of the last post.
Here is what my code looks like:
<div style="height: 100px">
<post post-item="item" feed-items="items.feed" feed-name="feedName" ng-repeat="item in items.feed"></post>
<a infinite-scroll="nextPosts()" href ng-click="nextPosts()" class="show-more">Show more</a>
</div>

jQuery Mobile multiple pages causing problems when calling a panel

I have an HTML document with multiple pages using jQuery Mobile's data-role="page". I am trying to call a panel on the second page but am receiving the error
cannot read property 'nodeType' of undefined
The error occurs when I try to transition to the second page. My basic page structure is as follows:
<body>
<div data-role="page" id="page1">
Enter Page 2
</div>
<div data-role="page" id="page2">
<h3> tthis is page 2 </h3>
<input type="button" id="myButton"> My Button </input>
<div data-role="panel" id="myPanel">
<p> Panel content </p>
</div>
</div>
</body>
The panel is being called through a function, but I still receive the same error when I comment out the function.
$(document).ready(function() {
$('#myButton').on('click', function() {
$('#myPanel').panel('open')
})
})
The panel works if it is on the first page and if I define it on the first page and open it on the second, it still opens on the first. It is there when I hit the back button. I am using jQuery Mobile too is that has an effect on anything.
Why am I receiving this error? Is there a simple solution or do I need hack my way around this by creating the panel dynamically? Thanks.
First off, never use .ready() in jQuery Mobile.
Important: Use $(document).bind('pageinit'), not $(document).ready()
The first thing you learn in jQuery is to call code inside the $(document).ready() function so everything will execute as soon as the DOM is loaded. However, in jQuery Mobile, Ajax is used to load the contents of each page into the DOM as you navigate, and the DOM ready handler only executes for the first page. To execute code whenever a new page is loaded and created, you can bind to the pageinit event. This event is explained in detail at the bottom of this page.
Source: http://jquerymobile.com/demos/1.2.0/docs/api/events.html
Secondly, each page should have its' own panel with a different id, and the div containing the panel should be a direct child of data-role=page.
Panel markup/structure:
<div data-role="panel" id="id" data-position="left" data-display="push" data-theme="b">
<!-- Contents -->
</div>
Opening a panel:
Statically by using anchor/button:
Open
Dynamically:
$.mobile.activePage.find('[data-role=panel]').panel('open');
// Or
$('#panel_id').panel('open');
Closing a panel:
(in case data-dismissible is set to false)
Statically by using anchor/button (Note: It should be placed inside Panel div):
Close
Dynamically:
$.mobile.activePage.find('[data-role=panel]').panel('close');
// Or
$('#panel_id').panel('close');
Demo

Toggle does not work on the same element that show works on

I am trying to use JQuery toggle, so when a user clicks the info icon, the hidden div containing item information is shown / hidden. For some reason it is not working for me.
While trying to debug, I noticed that show(), correctly shows the target element that I would like to toggle. However, when I replace show() with toggle(), it does not work and does not return any error.
I was wondering if someone can help me identify the cause of this problem.
My Markup
<div class="option">
<div class="prod-text">Toy Whistle </div>
<div>
<img class="info-icon" src="Info-icon.png">
</div>
<div class="option-info" style="display:none;">
<div>
<div class="price-text">Price: $100</div>
<div class="prod-id-text">Item Number: 231912</div>
<div class="quantity-text">Quantity: 72</div>
</div>
</div>
</div>
JQuery (does not work)
$(".info-icon").click(function(){
$(this).parent().parent().find('.option-info').toggle();
});
JQuery (works!)
$(".info-icon").click(function(){
$(this).parent().parent().find('.option-info').show();
});
Many thanks in advance!
Perhaps the click event handler is getting bound twice, and thus fire twice for each click. The show() would work fine in this case, but the toggle() would show and then immediately hide the element each time you click. Try this:
$(".info-icon").click(function(){
console.log('click handler fired');
$(this).parent().parent().find('.option-info').toggle();
});
And run this with Web Inspector or Firebug enabled to see how many messages are logged for each click.

Content is being loaded successfully via ajax. but not showing

I am playing around with djax when I click an anchor tag the url changes and when I view the page source it also changes but the page itself did not change its contents even if I view the page source it has change up any ideas why?
Here's a snippet of the markup
<body>
<div id="resultContent" class='updatable'></div>
<ul>
<li><a id="thankyou" href="views/thankyou.jsp?menuId=2"
targets="resultContent">Thank You Message</a></li>
</ul>
</body>
When I click that the url changes but the result is not showing but when I view the page source it displays the proper markup(or should I say the markup of thankyou.jsp)
here is the code that Is js code
jQuery(document).ready(function($) {
$('body').djax('.updatable');
});
I've had the exact same problem as you and discovered your question while I was looking for an answer. It may be too late for you but according to your markup I believe you ran into the same problem as me which is actually on the issue-list of the plugins Github site (at least right now).
You need to place your updateable div inside a wrapping div. For some reason exchanging content seems not to work for direct children of body. See https://github.com/beezee/djax/issues/22
So your HTML should look like this
<body>
<div id="djaxWrap>
<div id="resultContent" class='updatable'></div>
<ul>
<li><a id="thankyou" href="views/thankyou.jsp?menuId=2"
targets="resultContent">Thank You Message</a></li>
</ul>
</div>
</body>
While jQuery remains the same
jQuery(document).ready(function($) {
$('body').djax('.updatable');
});

Categories