JavaScript for Mega Menu Loading Slowly - javascript

On our Magento Website we have a mega-menu which appears when the mouse hovers over a parent li element in the menu.
However, if you hover over the menu immediately as the page loads, the mega menu does not appear properly.
It's much worse if the user has a poor internet connection.
After checking the chrome inspector I see this is because the class over is not added to the parent li. If you wait a second or two and move the mouse out & back over the parent li element the over class is added and the display css property of the mega menu is changed to block.
I've found the javascript adding the over class, it's part of the theme that we are using script.js.
// CODE OMMITED FOR BREVITY
jQuery(window).load(function() {
// CODE OMMITED FOR BREVITY
if(jQuery('#nav-wide').length){
jQuery('#nav-wide li.level-top').mouseenter(function(){
jQuery(this).addClass('over');
if(mobileDevice == true){
document.addEventListener('touchstart', wideMenuListener, false);
}
});
jQuery('#nav-wide li.level-top').mouseleave(function(){
jQuery(this).removeClass('over');
});
// CODE OMMITED FOR BREVITY
}
// CODE OMMITED FOR BREVITY
});
Any idea why this javascript would take so long to load? Or how I could improve it?

I think I've figured this out.
The theme is adding the over class within the jQuery(window).load(function(){}); which loads when everything on the page has loaded i.e. when all images, objects & frames have loaded. And we are using facebook widget (frame) on most pages.
The jQuery(document).ready(function(){}); function loads when just the HTML Document is ready, which would be much sooner, almost a second in our case.
So I simply moved theme's mouseover event listener within to the jQuery(document).ready() function

Related

jQuery code not working on react page after coming back from another page

I've written a jQuery code that adds and removes css classes from the accordion based on some condition. It works fine the fist time it loads but when I click on any links on the page and go to another page from there, it doesn't work when I come back to the same page.
Is it jQuery or React?
Here's my jQuery code.
$(function(){
$(".accordion").on("click", ".accordion-header", function(e){
if(!$(this).hasClass("has-add-bg")){
$(".accordion-item").removeClass("add-bg");
$(".accordion-header").removeClass("has-add-bg");
$(this).addClass("has-add-bg");
$(this).parent().addClass("add-bg");
}else{
$(this).parent().removeClass("add-bg");
$(this).removeClass("has-add-bg");
$(".accordion-item").removeClass("add-bg");
}
})
})
I tried using state but the problem is I want to add or remove the class of only the accordion I've clicked on. Not sure how to achieve that result just with state so wrote jQuery.

jQuery bring DIV infront without reseting iframe

Point
The code I have here is from my "operating system" I'm trying to create inside a browser by putting iframes in AppWindows with PHP code as the backend or the (main program process).
Now in every GUI system you have the ability to move windows, stack one on top of each others and such, but I'm not able to do efficiently in HTML using jQuery & jQuery-UI.
I'm using draggable() and some tricks I've found on StackOverflow to be able to bring the div AppWindow on top.
The problem
The code for bringing the **AppWindow** on top works fine but the problem is the iframe inside that window gets reset, because what this code is doing is that it stacks the current div as the first div above all the others inside the parent container.
If you notice the AppWindow 1 iframe blinks when you click on that window, I don't want that.
Code (jQuery)
$(function() {
// Don't know what I'm doing with iframe here...
$('.AppWindow iframe').click(function(){
$(this).parent().child.parent().append(this);
});
$('.AppWindow').click(function(){
$(this).parent().append($(this));
});
$('.AppWindow').draggable({handle:".DragHandle"});
});
Conclusion
If there is a way of preventing this from happening feel free to write an answer below. If you have a better way such as "JavaScript OS UI Framework" or something like that you're even more free to write below.I want something like **os.js** or **windows93.net** type of thing. All I need is a working taskbar, working window and a way to easily embed a PHP page inside that window that will mimic the work of the application.
I don't think it's possible. Take a look at here.
But
why do you reorder windows by change their positions in the dom in the first place? You could simply work with z-index. A basic example where you just set an active class of the targeted frame.
$(function() {
$('.AppWindow').draggable({
handle:".DragHandle",
drag: function(event, ui){
updateActiveWindow(event.target);
}
});
$('.AppWindow').on('click', function(){
updateActiveWindow(this);
});
function updateActiveWindow(el) {
$('.AppWindow').removeClass('active');
$(el).addClass('active');
}
});
with following css changes
.AppWindow.ui-draggable-dragging,
.AppWindow.active {
z-index: 1;
}
Edit: optimized the js a bit so that the window turns active once you start dragging.

will_paginate pagination links javascript not working

I have a simple jQuery script that plays/pauses video on hover that is working correctly when I first load the page, (e.g page 1) in rails with will_paginate gem.
My problem is that when I click to the next page or any other pages in particular, the jQuery script is not working but when I viewed the page source, the javascript code is still present.
I have to reload the page in order to get it to work?
var figure = $(".video").hover( hoverVideo, hideVideo);
//video is a div class that my videos use, this is at index.html.erb
function hoverVideo(e) {
$('video',this).get(0).play();
}
function hideVideo(e) {
$('video',this).get(0).pause();
}
Your problem is that when your page is changed i believe the page refreshes with ajax and newly created elements have no events attached to them. The simplest solution is:
$(document).on('mouseenter','.video', hoverVideo ).on('mouseleave','.video',hideVideo );
This way jquery will always call mouseenter / mouseleave function but only fire your function when the element has specified class .video. So you don't worry anymore whether your newly created elements have any events attached to them or no

Element is Statement Combined With If Statment Not Responding Properly on Hover

Really need some JQuery help here. I'm about to launch my laptop out the window. I have come a long way with this piece of code an I think I am almost there but I am stuck on the last hurdle.
I am only going to include the pertinent pieces of code here because it is a very large piece.
I have a navigation menu for a mock solar system. Here is the link to the larger external piece if you want to see the whole thing. http://jsbin.com/zagiko/1/edit (please note this uses mostly CSS3).
I have a nav menu for the piece and when you click on the values in the nav menu the current script assigns a class of active. That all works perfectly. I built in a button to test the active state on click and the state changes are working. But I need it to respond to the state change on hover. I am not a JQuery person; I am learning. It almost seems like the hover isn't working because it is responding to the data loaded when the page loads instead of responding in real time. But I am just guessing.
What I need is an if statement that will respond to the live data (not on page load or when the document is ready). The if statement should basically say if this div is active then this other div can appear on hover. But if this div is not active then it cannot appear.
The current if statement I wrote is
if($("a.active").is('.uranus')){
$('#uranus .infos').hover(
function () {
$("#descriptionsp").fadeIn("2000");
})
};
The current script that runs when the site loads that sets up the menus is:
$(window).load(function(){
var e=$("body"),
t=$("#universe"),
n=$("#solar-system"),
r=function() {
e.removeClass("view-2D opening").addClass("view-3D").delay(2e3).queue(function() {
$(this).removeClass("hide-UI").addClass("set-speed");
$(this).dequeue()})
},
i=function(e){
t.removeClass().addClass(e)
};
$("#toggle-data").click(function(t){
e.toggleClass("data-open data-close");
t.preventDefault()
});
$("#toggle-controls").click(function(t){
e.toggleClass("controls-open controls-close");
t.preventDefault()
});
$("#data a").click(function(e){
var t=$(this).attr("class");
n.removeClass().addClass(t);
$(this).parent().find("a").removeClass("active");
$(this).addClass("active");
e.preventDefault()
});
Really need you help. Thanks in advance!
Right now, your block of code is only being checked when the javascript is loaded. At this time, the .uranus element is probably not active, so nothing will happen.
First of all, you want to move this block inside of document ready, otherwise your elements such as .uranus might not even exist yet.
Your logic is very close, but you need to move the if statement inside of the hover function like this:
$('#uranus .infos').hover(
function () {
if($("a.active").is('.uranus')){
$("#descriptionsp").fadeIn("2000");
}
});
This way, every time you hover on #uranus .infos, it will only execute the code if the .uranus is also .active

JQuery Mobile do X to every div with given class

I'm building a JQuery mobile site which has an image slider on 2 pages. The sliders are activated using the following JS:
$(function () {
$("#slider").excoloSlider();
});
where '#slider' is the name of the div that gets rendered as the slider.
I have this slider on the 2 pages and have given both the same id, and don't want to insert the above code into both pages. To make things easy I want to be able to make add the above code into a.js file that I'm referencing at the top of both pages.
However, the script only kicks in when one of the pages are the first page to be navigated to. So, I assume this means the code is only being called in the once, and due to the AJAX loading of the subsequent page, it isnt called when this new page loads.
So, how can I run the code to affect any/all pages which feature the slider?
I dont know how many times you have to call .excoloSlider(); function. In case you have to call it each time the page is visited, then you need to use any of these page events, pagecontainershow or pagecontainerbeforeshow.
If you use pagecontainershow, you can run .excoloSlider(); on #slider even if you have the same id in a different page. This way, you specify in which page to look for #slider.
$(document).on("pagecontainershow", function () {
var activePage = $.mobile.pageContainer.pagecontainer("getActivePage");
/* check if #slider is within active page */
var slider = activePage.find("#slider").not(".slider");
if(slider) {
slider.excoloSlider();
}
});
Update
I have added .not(".slider") selector to exclude already rendered slider. The function .excoloSlider() will be called on new sliders only.
Demo
Try to use class instead of id since id is unique, then you can change your jQuery code to:
$(function () {
$(".slider").excoloSlider();
});
Use jQuery Mobile API for the navigation system
$(window).on( "navigate", function( event, data ) {
$("#slider").excoloSlider();
});
Edit
Use pageinit
From the jQM docs:
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.

Categories

Resources