JS menu stops working when navigating to a different page - javascript

I'm having some issues with my JS menu. When the page loads the menu work great, and as expected. You click the option, then it displays the menu items.
However, once I click one of the menu items and navigate to a different page the menu stops working! When you click on the icon, the menu no longer appears. The page just sits there. When i look try debug in chrome it no longer "hits" the code.
I have noticed that if i refresh that page, the menu works again as expected :/
My JS code is below, what am I missing for this kind of issue to arise?
I have created a pen for this - http://codepen.io/alr3id/pen/bwdKxL
function MyMenus(jQuery) {
$(".p-menu-icon").on("click", function(event) {
var e = $(this).next(".p-menu");
e.hasClass("p-menu_open") || $(document).trigger("click"),
$(".p-modal-bg").toggleClass("p-modal-bg_active"),
e.toggleClass("p-menu_open"),
event.stopPropagation()
});
// Removes the menu open class.
$(document).on("click", function(t) {
var e = $(t.target)
, i = 1 === e.closest("p-menu").length;
i || ($(".p-menu.p-menu_open").removeClass("p-menu_open"),
$(".p-modal-bg").removeClass("p-modal-bg_active"))
});
}
// Load
$(document).ready(MyMenus);
Below is the HTML for the Menu
<nav class="p">
<div class="p-modal-bg"></div>
<div class="p-property">
<a class="p-property-name" href="/">
Logo Here
</a>
</div>
<div class="p-user">
<a class="p-menu-icon">
<div class="icon icon-navigator-toggle"></div>
</a>
<div class="p-menu p-menu_navigator">
<a class="p-menu-item p-menu-item_dashboard" href="/">Dashboard</a>
<a class="p-menu-item p-menu-item_orders" href="/orders">My orders</a>
<a class="p-menu-item p-menu-item_back-bar" href="/products">Products</a>
</div>
<a class="p-menu-icon p-menu-icon_account">
<div class="p-user-avatar_container">
<img alt="Example user" class="gravatar" src="{image here}">
</div>
</a>
<div class="p-menu p-menu_account">
<div class="p-menu-item_account-details">
<div class="p-user-avatar_container">
<img alt="Example user" class="gravatar" src="https://secure.gravatar.com/avatar/{image here}">
</div>
<div class="p-account-details-name">
Example User
</div>
<div class="p-account-details-email">example#example.com</div>
</div>
<a class="p-menu-item p-menu-item_settings" href="account">Account settings</a>
<a class="p-menu-item p-menu-item_messages" href="#">Messages</a>
<a class="p-menu-item p-menu-item_logout" href="#">Sign out</a>
</div>
</div>
</nav>

Well, this is something I didn't even consider, it turns out this issue is down to Rails and Turbolinks!
Due to the way Turbolinks loads pages it screws up
$(document).ready
to fix this you need to use...
$(document).on "turbolinks:load"
http://guides.rubyonrails.org/working_with_javascript_in_rails.html#turbolinks

Have you imported the JS file you are using in this page (new page where it stuck) too ? Try adding the code on another file also or move your js code to another js file and import it on that page.

Since it works at freshly loaded page the code itself shouldn't be a problem.
What comes to mind are class changes. Open up your browser's inspector and check if there are any class name changes that would resolve in loosing a listener.
Also try putting some console.log() inside each function so you are sure that both events aren't getting fired one after another.

Related

Vue/Buefy - Hide dropdown on router-link click / SPA

I am having some issues using Buefy and Vue. I have a simple SPA (Single Page Application), that uses vue-router. I have a dropdown that looks like this:
<b-dropdown class="user-dropdown" v-model="navigation" position="is-bottom-left">
<a class="navbar-item" slot="trigger">
<span class="tag is-rounded has-text-weight-semibold avatar">OB</span>
</a>
<div class="columns is-marginless">
<div class="column has-text-centered">
<router-link to="home">
<b-icon class="is-large is-size-4" icon="ion-ionic ion-ios-search"></b-icon>
</router-link>
</div>
<div class="column has-text-centered">
<router-link to="dashboard">
<b-icon class="is-large is-size-4" icon="ion-ionic ion-ios-contact"></b-icon>
</router-link>
</div>
</div>
</b-dropdown>
Getting the dropdown to show works fine. It also hides if I click anywhere on the page, outside of the visible dropdown.
My problem is, that I have a single page application, so when I "change" page (click a link), the dropdown is still visible when the page changes.
Example:
On below page:
www.example.com/#/home
I click on the dropdown, which opens, and then click on the dashboard link, which gives me:
www.example.com/#/dashboard
But the dropdown is still visible.
Anyone know how I can do, so the dropdown will toggle when I click on the links inside it?
Update:
I use the Vue Dev tools in Chrome, and I can see that when I click on the dropdown so it toggles to active, I see this:
name:"active-change"
type:"$emit"
source:"<BDropdown>"
payload:Array[1]
0:true
And when I click anywhere on the page, to close the dropdown, it looks like this:
name:"active-change"
type:"$emit"
source:"<BDropdown>"
payload:Array[1]
0:false
Whatever the drop-down is watching for state isn't changing, because in a SPA it's just javascript. I don't know about the specifics regarding Buefy, but you'll have to set the state variable on router load, or watch some kind of variable to tell the menu that something in another part of your app is different.

jquery load() causes a tags to lose their href value

<div class="page">
Click!
</div>
<script>
$("a").click(function(){
$(".page").load($(this).attr("href"));
window.history.pushState("", "", '/'+$(this).attr("href"));
return false;
});
</script>
<!-- in another-page.php -->
Click here!
<!-- what the another-page.php looks like once it's been loaded by jquery -->
<a href>Click here!</a>
and then clicking on a link will load a page in a <div class="page"> BUT, I noticed at the top of the page, where there is a <h1>Title</h1> it lost the color i had defined h1 a {...} and then when inspecting element, instead of being the above h1, a thing, it was <h1><a href>Title</a></h1>
Something else is wrong here.
The issue I described occurs when you use <a href=/> not <a href="/">. I didn't test to check and see if the same occurs when using <a href=another-page.php> but found that, quoting the forward slash fixed the problem.

Phonegap+JQuery Mobile: How to fire a popup from the Android menu button?

I created this snippet in a simple Phonegap 3.1 app, based on the JQuery Mobile popup documentation:
<div data-role="popup" id="popupMenu" data-theme="e">
<ul data-role="listview" data-inset="true" style="min-width:210px;" data-theme="e">
<li>Help</li>
<li>About</li>
</ul>
</div>
<a href="#popupMenu" data-rel="popup" data-role="button">
Click for menu
</a>
Clicking the button brings up the menu.
I also have this snippet in an external .js file:
$(document).ready( function() {
document.addEventListener("menubutton", onMenuKeyDown, false);
})
function onMenuKeyDown() {
alert("Menu key pressed!");
// what goes here?
}
Pressing the menu button brings up the alert, so I know the listener is working. Now, I want to add some code to the onMenuKeyDown() function so it will bring up the menu loaded by the button in the first snippet. The code needs to be equivalent to clicking
Click here
How would I do that?
Thanks.
Well, I found a way to do this. It works, but it seems kind of hacky. Suggestions for other ways to do this are welcome.
First, make the original link invisible and give it an ID:
<a href="#popupMenu" style="display: none;" id="hammerTime" data-rel="popup" data-role="button" >
Can't touch this!
</a>
Then have the menu button click the invisible link:
function onMenuKeyDown() {
// alert("Menu key pressed!");
$("#hammerTime").click()
}
Hopefully someone else will find this useful along the way.

JQueryMobile: stopPropagation() makes blank page flash on href click

I'm developing a RhoMobile appand I've been having lot of trouble with page transitions.
At the end, I just decided to turn them off for a better user experience. Every button click works perfectly, except for one where I have a button inside a Collapsible element.
For the click event on the button not to get interpreted as a click on the collapsible, I use this js code, which I suspect is causing trouble:
$(document).on('pagebeforeshow', '#index',function(e){
$('.details').bind('click', function (e) {
e.stopPropagation();
e.stopImmediatePropagation();
});
});
And in the HTML:
<div data-role="page" id="index">
Here go headers & navbar and other stuff
</div>
<div data-role="content">
<div data-role="collapsible-set" class="uurbon-block">
<div data-role="collapsible" data-collapsed="false">
<h3 data-position="inline"><p class='alignleft'>Collapsible title</p><div style="clear: both;"></div>
<span style="float:right;" class="button-span">
<a href="some_url.html" data-role="button" data-mini="true" data-inline='true' data-icon="star" data-iconpos="left" class="details" data-transition="none">
Button
</a>
</span>
</h3>
</div>
</div>
</div>
This will cause a blank page to be shown for 1-2 secs before transitioning. I'd be looking for a fix, but if not, i'd be happy with that page just beeing black (my app background is black also, so this blink wouldnt be so noticeable).
Note: I have alredy tried setting body background color in css, won't work.
Thanks for your ideas!
As pointed by Omar, if you want to put a button inside a collapsible and prevent the collapsible from capturing the click while also handling the page in the same browser, the correct way to do this is (Take notice that this may only apply to RhoMobile, but its worth a try on other jquerymobile-based frameworks):
and avoid RhoMobile trying to open this in a new browser is by using:
javascript:
$(document).on('pagebeforeshow', '#index',function(e){
$('.details').bind('click', function (e) {
e.stopPropagation();
$.mobile.changePage("your_page");
});
});
HTML:
Button
Notice the href="javascript:;". I had this first set to "#" and also "", but that didn't work.

jQuery back button does not work properly after refresh

On my jQuery mobile app;
On menu.html and inside body I do something like this to go help.html;
....
$(document).off('pageinit', '#menupage').on('pageinit', '#menupage', function() {
$(document).off('click', '#help').on('click', '#help', function(){
$.mobile.changePage("help.html", {
reloadPage: true,
transition: "flip",
reverse: false
});
});
}
....
<li><a id="help" href="#" role="link" data-role="none">
<div class="img help"></div>
<div class="menuTitle langMenuItem3">Help</div>
<div class="arrow"></div>
</a></li>
Then on the help.html page I have a back button like this to go back to menu.html:
<header data-role="header">
<a href="#" data-rel="back" class="button" data-role="none">
<div class="arrow_reverse"></div><span class="langBack">Terug</span>
</a>
<div class="pageTitle">Over deze app</div>
</header>
My problem is this works under normal conditions, BUT if I make a refresh on menu.html, then go to help.html and then go back to menu again, menu.html does not load properly, I can see the page visually loaded ok but on firebug I see that some necessary javascripts inside tags does not hit anymore, It never hits any javascripts anywhere on menu.html anymore, just loads the previous html from cache thats all. Also the page title of menu.html does not change correctly and stays as "Help" after that point.
my full menu.html looks like this;
http://jsfiddle.net/M5CYZ/
Any ideas?
Do it this way.
Give back button an ID
<a href="#" id="backbtn" class="button">
<div class="arrow_reverse"></div><span class="langBack">Terug</span>
</a>
and then add the below code in help.html
$('#backbutton').off('click').on('click', function () {
$.mobile.changePage("menu.html", {
reloadPage: true,
transition: "flip",
reverse: true
});
});
This is a wild guess but according to your code this is a normal behaviour.
jQuery Moible event pageinit will trigger only once during the initial page load and unless page is refreshed (manually, with rel="external" or in your case reloadPage="true") it will never trigger again.
If you want javascript to execute again each time page is visited then use pagebeforeshow event instead. As seen in your example, removing pageinit and adding it back will not help you.
If you want to find more, read my other answer/article about page events: jQuery Mobile: document ready vs page events
And here's an example to prove my point: http://jsfiddle.net/Gajotres/Q3Usv/
$(document).on('pageinit', '#index', function(){
alert('Pageinit');
});
$(document).on('pagebeforeshow', '#index', function(){
alert('Pagebeforeshow');
});

Categories