Is my jQuery load request being called twice? - javascript

I have this website: http://wearewebstars.dk/poc/index.html
If you click the top menu, then it makes an Ajax request to another page. And if you click again, a new request to another page and so on...
However, it seems, that If I click the top navigation once, then it loads the new page, and then if I click on another link in the top navigation, then it seems that it loads the page twice or something? I cant quite figure out why it does this?
If you start by clicking "Omgivelserne", and after that click "Skriv dig op", then the page "Skriv dig op", seems to be loading twice, judging from the fade transitions?
My JS for the Ajax and Transitions (Edited to only show relevant code):
var DIS = DIS || {};
// create a timeline
var tl = new TimelineMax();
(function($, DIS, window) {
var graphic = $("div.page-transition");
DIS.PageTransitionStart = {
start: function(url) {
$this = $(this);
var pageTransitionStart = new TimelineMax({
onComplete: DIS.loadPage,
onCompleteParams: [url, $this]
});
pageTransitionStart.add(TweenMax.set($("body"), {
className: "animating"
}));
pageTransitionStart.to(graphic, 0.3, {
css: {
scale: 50,
opacity: 0.5,
force3D: true
},
ease: Power1.easeOut
});
pageTransitionStart.to(graphic, 0.5, {
css: {
scale: 130,
opacity: 1,
force3D: true
},
ease: Power1.easeOut
});
//tl.add(pageTransitionStart);
},
toggleSelectedClass: function(el) {
$("#mainmenu").find("a").removeClass("selected");
el.addClass("selected");
}
};
DIS.PageTransitionEnd = {
end: function(el, url) {
var pageTransitionEnd = new TimelineMax();
pageTransitionEnd.add(TweenMax.to(el, 0.3, {
css: {
scale: 1,
opacity: 1
},
ease: Power4.easeOut
}));
pageTransitionEnd.add(TweenMax.to(el, 0.1, {
onComplete: function() {
TweenMax.set($("body"), {
className: ""
}); // then only replace with blue div with new height and width
}
}));
//tl.add(pageTransitionEnd);
}
};
DIS.TopNavigation = function() {
$(".nav a").click(function(event) {
event.preventDefault();
$url = $(this).attr("href");
DIS.PageTransitionStart.start($url);
});
};
DIS.loadPage = function(url, el) {
var div = url + "#pages-container .content";
//var title = el.attr("title").replace(/\s/g, ''); //Remove spaces from Title
$(".content").load(div, function(response, status, xhr) {
if (status == "success") {
//alert("test");
//window.location.hash = title; // Adds a hash to the URL
console.log(xhr.status);
DIS.PageTransitionEnd.end(graphic, $url);
DIS.PageTransitionStart.toggleSelectedClass(el);
DIS.init();
} else if (status == "error") {
alert("Vi kunne desværre ikke hente siden - Kontakt venligst Living Homes");
console.log(xhr.status);
console.log(xhr.responseText);
console.log(response);
return;
}
});
};
DIS.init = function() {
DIS.TopNavigation();
if ($(window).width() > 768) {
DIS.pageNavigation();
}
DIS.TextEffects();
DIS.slider();
};
}(jQuery, DIS, window));
$(function() {
DIS.init();
});

If you change the following, I assume there would be no more "double clicks". This will make sure that TopNavigation() is only fired once, and not binding two click-events to the menu links.
DIS.init = function() {
//DIS.TopNavigation();
if ($(window).width() > 768) {
DIS.pageNavigation();
}
DIS.TextEffects();
DIS.slider();
};
and
$(function() {
DIS.TopNavigation();
DIS.init();
});
Not the best thought out solution, but it's a way to confirm where the problem lies.
Edit: Once confirmed that this is indeed the problem, the next step would be to make sure that DIS.init() is only used to reset states/variables, and that it doesn't create a lot of double bindings or conflicting events.
You can handle this by adding a...
$(".nav a").unbind("click");
But if there is no specific reason to unbind & rebind, it's better to just leave it be and fix the structure instead.

Ok, So I finally figured out the problem. It seems that there was a problem with some naming conventions. I was trying to load .content into .content, and that was caused the problem. I changed the class name on the div I was loading .content into, and that solved the problem.

Related

Dragula and DOM-Autoscroller in MVC, no Angular

Trying to get DOM-Autoscroller to work with Dragula.
We have Dragula up and running. I've managed to get the syntax to Autoscroller correct, so that it doesn't break Dragula. But Autoscroller doesn't appear to be doing anything.
Our Autoscroller call is reasonably close to the example.
$(document).ready(function () {
var drake = dragula({
containers: Array.prototype.slice.call(document.querySelectorAll('[id^="checklistItems-"')),
revertOnSpill: true,
direction: 'vertical',
accepts: function (el, target, source, sibling) {
return target == source;
}
})
.on('drop', function (el, target, sibling) {
var destinationIndex = [].slice.call(el.parentElement.children).indexOf(el);
// call AJAX with element id and destination index
$.ajax(
{
url: "#Url.Action("ReorderTicketChecklist", "Tickets")",
data: { checklist_ID: el.parentElement.dataset.checklistid, checklistItem_ID: el.dataset.id, destinationNum: destinationIndex+1 },
error: function () {
alert("Something went wrong reordering the list. Please refresh and try again.");
}
})
});
var scroll = autoScroll([
//Array.prototype.slice.call(document.querySelectorAll('[id^="checklistRow-"'))
document.querySelector('#checklistRow-100')
], {
margin: 20,
pixels: 10,
scrollWhenOutside: true,
autoScroll: function () {
return this.down && drake && drake.dragging && drake.drake && drake.drake.dragging;
}
});
})
I currently have the first list hard-coded, and I can work on the syntax for the rest, later.
I guess I mostly need some advice on how to debug this. What can I do to shake the box and get some behavior out of Autoscroller, so I can track down what's wrong?

Scraping an infinite scroll page stops without scrolling

I am currently working with PhantomJS and CasperJS to scrape for links in a website. The site uses javascript to dynamically load results. The below snippet however is not getting me all the results the page contains. What I need is to scroll down to the bottom of the page, see if the spinner shows up (meaning there’s more content still to come), wait until the new content had loaded and then keep scrolling until no more new content was shown. Then store the links with class name .title in an array. Link to the webpage for scraping.
var casper = require('casper').create();
var urls = [];
function tryAndScroll(casper) {
casper.waitFor(function() {
this.page.scrollPosition = { top: this.page.scrollPosition["top"] + 4000, left: 0 };
return true;
}, function() {
var info = this.getElementInfo('.badge-post-grid-load-more');
if (info["visible"] == true) {
this.waitWhileVisible('.badge-post-grid-load-more', function () {
this.emit('results.loaded');
}, function () {
this.echo('next results not loaded');
}, 5000);
}
}, function() {
this.echo("Scrolling failed. Sorry.").exit();
}, 500);
}
casper.on('results.loaded', function () {
tryAndScroll(this);
});
casper.start('http://example.com/', function() {
this.waitUntilVisible('.title', function() {
tryAndScroll(this);
});
});
casper.then(function() {
casper.each(this.getElementsInfo('.title'), function(casper, element, j) {
var url = element["attributes"]["href"];
urls.push(url);
});
});
casper.run(function() {
this.echo(urls.length + ' links found:');
this.echo(urls.join('\n')).exit();
});
I've looked at the page. Your misconception is probably that you think the .badge-post-grid-load-more element vanishes as soon as the next elements are loaded. This is not the case. It doesn't change at all. You have to find another way to test whether new elements were put into the DOM.
You could for example retrieve the current number of elements and use waitFor to detect when the number changes.
function getNumberOfItems(casper) {
return casper.getElementsInfo(".listview .badge-grid-item").length;
}
function tryAndScroll(casper) {
casper.page.scrollPosition = { top: casper.page.scrollPosition["top"] + 4000, left: 0 };
var info = casper.getElementInfo('.badge-post-grid-load-more');
if (info.visible) {
var curItems = getNumberOfItems(casper);
casper.waitFor(function check(){
return curItems != getNumberOfItems(casper);
}, function then(){
tryAndScroll(this);
}, function onTimeout(){
this.echo("Timout reached");
}, 20000);
} else {
casper.echo("no more items");
}
}
I've also streamlined tryAndScroll a little. There were completely unnecessary functions: the first casper.waitFor wasn't waiting at all and because of that the onTimeout callback could never be invoked.

How to only run a script if the DIV is in view?

I have a script that I wrote:
jQuery(function($) {
$('.count').countTo({
from: 0,
to: '400',
speed: '3000',
refreshInterval: 50,
onComplete: function(value) {
console.debug(this);
}
});
});
I need that script only to run when the container div is visible.
<div class="container">
<div class="count"></div>
</div>
To clarify, the div will always be visible, but when the user scrolls it in to view. Any ideas?
http://www.windycitydigital.net/iconvert/ - Example, at the bottom of the page those counters automatically start. I don't want that script to initiate until the user scrolls into view of them.
Here is an example with the alert activated only when the #mydiv is in view:
This works as you asked. Make sure the window is small so #midiv is not in view from the beginning. And after you scroll down, after the entire #mydiv is visible it will activate the alert from the scroll event.
http://jsfiddle.net/u3eCG/7/
divScroll = $("#mydiv").offset().top + $("#mydiv").height();
$(window).scroll(function(){
lastLineScroll = $("body").scrollTop() + $(window).height();
if (divScroll < lastLineScroll) {
alert("Div is visible");
$(window).unbind("scroll");
}
});
What code shoud hide/show div?For example you can use this code to show div
$('.container').show(0, onContainerVisible);
function onContainerVisible(){
jQuery(function($) {
$('.count').countTo({
from: 0,
to: '400',
speed: '3000',
refreshInterval: 50,
onComplete: function(value) {
console.debug(this);
}
});
});
}
if your browser compatibility requirements support it... MutationObserver might be a good candidate here
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
you could do something like this..
function isViewed(selector) {
var viewport = $(window),
item = $(selector);
var viewTop = viewport.scrollTop(),
viewBtm = viewport.scrollTop() + viewport.height(),
itemTop = item.offset().top,
itemBtm = item.offset().top + item.height();
return ((itemTop < viewBtm) && (itemTop > viewTop));
};
var counter = setInterval(function() {countdown()}, 500);
var countdown = function() {
console.log('are you there?');
if(isViewed('#mydiv')) {
clearInterval(counter);
console.log('yes i am here.'); // call countdown here
}
};
here is a jsfiddle to demonstrate
http://jsfiddle.net/pixelchemist/aLT7w/

jQuery partially not working in firefox and opera

I'm testing my webpage in browsers and it seems that some bits are not working in firefox and opera. I assume it's caused by jQuery used on my page.
This is my website: http://freshbeer.lv/ht/index.html
At the bottom of the source code you can find all jQuery code used (mainly to call and apply plugins). I'm having trouble to determine what is wrong, as there are no errors shown in console (firefox 20.0) Main dysfunctions are
player, just compare how it works in chrome and than check it out in firefox or opera, first of all it doesn't show "..." which signifies loading, secondly once you click play on another player, both songs keep playing, where as in other browsers first song would pause, so there would be only one song playing.
advertisement should have margins on top and bottom calculated by jQuery, it doesn't in opera and firefox.
So Am I missing something? Maybe I need to apply certain code standards?
That seems to be all, however I can't be sure.
I'll put code written by me here (most likely issue is in it), note, there are several jQuery plugins included above it.
<script type="text/javascript">
//Audio Player
audiojs.events.ready(function () {
var as = audiojs.createAll();
$('audio').each(function () {
var myAudio = this;
this.addEventListener('play', function () {
$('audio').each(function () {
if (!(this === myAudio)) {
this.pause();
}
});
});
});
});
$(document).ready(function() {
//Responsive add margins
function addMargin () {
var add = $(".advert");
var addMargin = add.css("margin-left");
add.css({
"margin-top": addMargin,
"margin-bottom": addMargin
});
}
addMargin();
$(window).resize(addMargin);
//Responsive Grid
var MusicGrid = (function() {
var $musicGridContainer = $('.grid'),
init = function() {
changeMusicGrid();
initEvents();
initPlugins();
},
changeMusicGrid = function() {
var w_w = $(window).width();
if (w_w <= 765) n = 1;
else if (w_w <= 1180) n = 2;
else n = 3;
},
initEvents = function() {
$(window).on('smartresize.MusicGrid', function(event) {
changeMusicGrid();
});
},
initPlugins = function() {
$musicGridContainer.imagesLoaded(function() {
setTimeout(function() {
$musicGridContainer.masonry({
itemSelector: '.article',
columnWidth: function(containerWidth) {
return containerWidth / n;
},
isAnimated: true,
animationOptions: {
duration: 150
}
});
}, 500);
});
};
return {
init: init
};
})();
MusicGrid.init();
});
//Preload Content
function preloadCode() {
if (preloadCode.done) return;
preloadCode.done = true;
clearTimeout(t);
$(".preloader").css("display", "none");
$(".grid").css({ opacity: 0, visibility: 'visible', marginTop: 20 }).animate({ marginTop: 0, opacity: 1 }, 550);
$('.article[id^="article-"]').each(function () {
if (parseInt(this.id.replace('article-', '')) % 3 === 0) {
$('#' + this.id).css({ marginTop: 50 }).animate({ marginTop: 0 }, 350);
} else if (parseInt(this.id.replace('article-', '')) % 2 === 0) {
$('#' + this.id).css({ marginTop: 100 }).animate({ marginTop: 0 }, 400);
} else {
$('#' + this.id).css({ marginTop: 150 }).animate({ marginTop: 0 }, 450);
}
});
$(".footer").css("display", "block");
}
var t = setTimeout(preloadCode, 6000);
$(window).load(preloadCode);
</script>
1. advertisement should have margins on top and bottom calculated by jQuery, it doesn't in opera and firefox. So Am I missing something? Maybe I need to apply certain code standards?
Your element has auto margins, so, depending on the browser, .css('margin-left') might return different values, including 0.
I recommend using the JsSizes library which is a lightweight plugin that will allow you to get the actual margins in pixels.
2. player, just compare how it works in chrome and than check it out in firefox or opera, first of all it doesn't show "..." which signifies loading, secondly once you click play on another player, both songs keep playing, where as in other browsers first song would pause, so there would be only one song playing.
Firefox and Opera don't support mp3 in their audio element, so it gets replaced by a flash object. Therefore you can't listen to those DOM events anymore.
Although, according to their annotated source code, the flash object has public methods play(), pause(), and isPlaying.
I'd recommend listening a click event on the 'play-pause' button and use these functions. Like this :
var as = ''; // You're going to have to make your as variable global to access it outside of your function.
audiojs.events.ready(function () {
as = audiojs.createAll();
$('.audiojs .play-pause').click(function(){ //Listening to the click event
var thisIndex = $(this).parents('.audiojs').index('.audiojs'); // When you create several players, as is an array of instances of players. Here we're finding the DOM index of the player so it reflects its position in the as array.
$.each(as, function(index,val){ //then, for each instance of players in the as array
if ( index != thisIndex && as[index].playing ) as[index].pause(); //If the player is already playing, and its index is different than the one we just clicked on, pause it !
});
});
});

Profiling jQuery, how do I make my app more snappy?

I have some calls to jQuery functions like 14,000 times... what the hell? I don't have that many functions, really just simple stuff like appending and removing DOM elements, why do some of my event handlers call functions so many times?
Plus to compound my issues, Firebug's profiler just show's the min'd functions names... and even when I use the uncompressed library it mostly just shows init() or $.()
Does anyone have any tricks?
So I know this is a lot, but it seems really inefficient, it executes on our page newgoldleaf.com, some of the functions take almost 50ms to run... is that a long time or is it just me?
// prepare ajax for form posts
jQuery.ajaxSetup({
"beforeSend" : function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
// initializes panels and gets url hash, shows correct panel
jQuery.fn.initPanes = function() {
$("div#main_content > div:not(.message)").addClass("inactive");
var hash = window.location.hash.substr(1);
this.each(function () {
if ($(this).hasClass(hash)) {
var panelToShow = "." + $(this).attr("class");
$(panelToShow).removeClass("inactive").toggleClass("active");
}
});
// if no hash found in url, activate first menu item
if (hash == "" ) {
$(this).eq(0).activatePane();
}
};
// shows panel when user clicks sidebar links
jQuery.fn.activatePane = function(pane) {
if ($(this).hasClass("unavailable") == true) {
return false;
}
if ($(this).hasClass("active") == false) {
$("div#main_content > div:not(.message)").hide().removeClass("active").addClass("inactive");
$(this).siblings().removeClass("active");
var panelToShow = "div#main_content div." + $(this).attr("class");
// set the hash in the url
window.location.hash = $(this).attr("class");
$(this).toggleClass("active");
$(panelToShow).fadeIn("slow").removeClass("inactive").addClass("active");
};
};
jQuery.fn.functionName = function() {
};
$(document).ready(function (){
$('ul.examples li:not(img, h5, a)').hover(function (){
var bubble = $(this).find("h5.bubble")
bubble.animate({
opacity:".99",
bottom:"28px"
}, 200);
}, function (){
var bubble = $(this).find("h5.bubble")
bubble.animate({
opacity:"0",
bottom:"38px"
}, 200).animate({
bottom:"20px"
}, 0);
});
// hide/show comment form for users with javascript
$("div#comments_not_allowed").hide();
$("form#new_comment").show();
// $("body#index div.preview").slideShow();
// error and flash notice animation
$(".message").animate({
opacity: "1",
}, 2000).animate({
opacity: "0",
}, 2000).hide(500);
// home page caption bubble for blog image fade in
$("body#index h5.bubble").fadeIn("slow");
$("body#index h5.bubble").animate({
bottom: "22px",
opacity: ".99"
}, 1000);
$("form#new_comment").submit(function() {
$.post($(this).attr("action"), $(this).serialize(), null, "script");
return false;
});
$("form#new_lead").submit(function() {
$.post($(this).attr("action"), $(this).serialize(), null, "script");
return false;
});
if ($("ul.panels").length > 0 ) {
// panel animation
$("div#aside ul li").initPanes();
$("div#aside ul li").css({
cursor:"pointer"
});
$("div#aside ul li").click(function () {
$(this).activatePane();
});
};
$(document).load(function() {
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
function startAnalytics() {
var pageTracker = _gat._getTracker("UA-7434953-1");
pageTracker._initData();
pageTracker._trackPageview();
}
if (window.addEventListener) {
window.addEventListener('load', startAnalytics, false);
}
else if (window.attachEvent) {
window.attachEvent('onload', startAnalytics);
}
})
})

Categories

Resources