I'm working on a magento project, and I'm trying to load more products on the click of the more button.
I can see them loading but then it will just load a blank page after it.
I have no idea what is happening or why.
This is the code I have
var loadMore = Class.create({
initialize: function (list, href, pattern) {
var that = this;
this.list = list;
this.list.insert({ after : '<div class="more"><span id="more_button" class="more-button">More</span></div>'});
this.href = href.readAttribute('href');
this.button = $('more_button');
this.holder = new Element('div', { 'class': 'response-holder' });
this.button.observe('click', function () {
if ( !that.button.hasClassName('loading') ) {
new Ajax.Request(that.href, {
onCreate: function () {
that.button.addClassName('loading');
},
onSuccess: function(response) {
if (200 == response.status) {
that.holder.update(response.responseText).select(pattern).each(function(elem) {
that.list.insert({ bottom : elem });
}),
that.href = that.holder.select('.next-page')[0].readAttribute('href');
that.button.removeClassName('loading');
if ( !that.href ) {
that.button.up().remove();
}
}
}
});
}
});
}
});
If anyone can help me out that would be awesome!
Thanks in advance.
I've having the same problem in my magento Iphone orginal theme, but the error is because of code injection, mostly "script" tags from google analytics, clicktale and similar stuff.
what i've done to fix it was to "parse" the ajax response and modify the opening "script" tag with the html entity:
below the line 117 (aprox in iphone.js)
if (200 == response.status) {
that.holder.update(response.responseText).select(pattern).each(function(elem) {
replace with this:
str = response.responseText;
str = str.replace(/<script/gi, '<script');
that.holder.update(str).select(pattern).each(function(elem) {
Might I suggest you rewrite your code and use thiz for that? Your code is extremely hard to read.
I do not see any reason to use the onCreate event of the Ajax Request, which by the way is reserved for Ajax Responders (per spec: http://prototypejs.org/doc/latest/ajax/Ajax/Request/)
Instead, you can add this classname at the moment you enter into !that.button.hasClassName('loading') ...
if ( !that.button.hasClassName('loading') ) {
that.button.addClassName('loading');
new Ajax.Request(that.href, {
....
There is a lot more going on behind the scene, like your CSS, magento of course, but also containing and parent html elements so it is very difficult to give any sound advice. What have you done in order to debug this?
Karl..
Related
I have created a fiddle here...https://jsfiddle.net/qukhn4uk/
As you can see, I have an object for clicking on a grid image that opens a flyout and loads that person's data through ajax (you won't see the data load in the fiddle obviously but you get the idea). Everything works good here. The object that handles this is:
Stories = {
flyout: '#flyout',
closeFlyout: '#flyout .close-flyout',
storyTrigger: '.story .story-trigger',
ajaxContentContainer: '#flyout .content',
loader: '<i class="fa fa-spin fa-spinner"></i>',
body: 'body',
init: function() {
$(this.storyTrigger).click(this.showStory.bind(this));
$.ajaxSetup({cache:false});
$(document).on("click", this.closeFlyout, this.closeStory.bind(this));
},
showStory: function(e) {
e.preventDefault();
var target = $(e.target),
targetName = target.data("name");
$(this.flyout).css("transform", "translateX(-100%)");
$(this.body).css("overflow", "hidden");
$(this.ajaxContentContainer).append(this.loader);
$(this.ajaxContentContainer).load("/story/" + targetName);
},
closeStory: function() {
$(this.flyout).css("transform", "translateX(100%)");
$(this.ajaxContentContainer).empty();
$(this.body).css("overflow", "auto");
}
}
I then have another load function for opening the flyout and loading the data based on a hash in the url. This is the object that handles that...
DirectStory = {
storyDiv: '.story',
init: function() {
var self = this;
if ( window.location.hash != '' ) {
$(this.loadStory.bind(this));
}
$.ajaxSetup({cache:false});
},
loadStory: function() {
var hash = window.location.hash,
story = hash.substring(1);
targetStory = $(this.storyDiv).find("[data-name='" + story + "']");
targetStory.click();
}
}
Everything works great but there is one tiny glitch. For some reason, the DirectStory object is causing the ajaxLoader from the Stories object to load twice. Can someone help me figure out why this is happening? Thanks!
UPDATE: I have figured out that the targetStory.click() is running twice inside of the DirectStory object. I have tried to unbind it first but that does not help. Why is it running twice?
I have solved this for anyone who lands here...
The targetStory variable was finding two triggers with the way I was storing it.
I simply updated the targetStory variable to...
targetStory = $(".full-link[data-name='" + story + "']");
Ok, so I need some insight into working with History.js and jQuery.
I have it set up and working (just not quite as you'd expect).
What I have is as follows:
$(function() {
var History = window.History;
if ( !History.enabled ) {
return false;
}
// Capture all the links to push their url to the history stack and trigger the StateChange Event
$('.ajax-link').click(function(e) {
e.preventDefault();
var url = this.href; //Tells us which page to load
var id = $(this).data('passid'); //Pass ID -- the ID in which to save in our state object
e.preventDefault();
console.log('url: '+url+' id:'+id);
History.pushState({ 'passid' : id }, $(this).text(), url);
});
History.Adapter.bind(window, 'statechange', function() {
console.log('state changed');
var State = History.getState(),
id = State.data.editid; //the ID passed, if available
$.get(State.url,
{ id: State.data.passid },
function(response) {
$('#subContent').fadeOut(200, function(){
var newContent = $(response).find('#subContent').html();
$('#subContent').html(newContent);
var scripts = $('script');
scripts.each(function(i) {
jQuery.globalEval($(this).text());
});
$('#subContent').fadeIn(200);
});
});
});
}); //end dom ready
It works as you'd expect as far as changing the url, passing the ID, changing the content. My question is this:
If I press back/forward on my browser a couple times the subContent section will basically fadeIn/fadeOut multiple times.
Any insight is appreciated. Thanks
===================================================
Edit: The problem was in my calling all of my <script> and Eval them on each statechange. By adding a class="no-reload" to the history controlling script tag I was able to do:
var scripts = $('script').not('.no-reload');
This got rid of the problem and it now works as intended. Figure I will leave this here in case anyone else runs into the same issue as I did.
The problem was in my calling of all of my <script> and Eval them on each statechange. By adding a class="no-reload" to the history controlling script tag I was able to do:
var scripts = $('script').not('.no-reload');
This got rid of the problem and it now works as intended. Figure I will leave this here in case anyone else runs into the same issue as I did.
i have some links in a web page ,what i want to do :
Trigger click event on every link
When the page of every link is loaded , do something with page's DOM(fillProducts here)
What i have tried :
function start(){
$('.category a').each(function(i){
$.when($(this).trigger('click')).done(function() {
fillProducts() ;
});
})
}
Thanks
What you want to do is much more complicated than you seem to be giving it credit for. If you could scrape webpages, including AJAX content, in 7 lines of js in the console of a web browser you'd put Google out of business.
I'm guessing at what you want a bit, but I think you want to look at using a headless browser, e.g. PhantomJs. You'll then be able to scrape the target pages and write the results to a JSON file (other formats exist) and use that to fillProducts - whatever that does.
Also, are you stealing data from someone else's website? Cause that isn't cool.
Here's a solution that may work for you if they are sending their ajax requests using jQuery. If they aren't you're going to need to get devilishly hacky to accomplish what you're asking (eg overriding the XMLHttpRequest object and creating a global observer queue for ajax requests). As you haven't specified how they're sending the ajax request I hope this approach works for you.
$.ajaxSetup({
complete: function(jQXHR) {
if(interested)
//do your work
}
});
The code below will click a link, wait for the ajax request to be sent and be completed, run you fillProducts function and then click the next link. Adapting it to run all the clicks wouldn't be difficult
function start(){
var links = $('.category a');
var i = 0;
var done = function() {
$.ajaxSetup({
complete: $.noop//remove your handler
});
}
var clickNext = function() {
$(links.get(i++)).click();//click current link then increment i
}
$.ajaxSetup({
complete: function(jQXHR) {
if(i < links.length) {
fillProducts();
clickNext();
} else {
done();
}
}
});
clickNext();
}
If this doesn't work for you try hooking into the other jqXHR events before hacking up the site too much.
Edit here's a more reliable method in case they override the complete setting
(function() {
var $ajax = $.ajax;
var $observer = $({});
//observer pattern from addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjquery
var obs = window.ajaxObserver = {
subscribe: function() {
$observer.on.apply($observer, arguments);
},
unsubscribe: function() {
$observer.off.apply($observer, arguments);
},
once: function() {
$observer.one.apply($observer, arguments);
},
publish: function() {
$observer.trigger.apply($observer, arguments);
}
};
$.ajax = function() {
var $promise = $ajax.apply(null, arguments);
obs.publish("start", $promise);
return $promise;
};
})();
Now you can hook into $.ajax calls via
ajaxObserver.on("start", function($xhr) {//whenever a $.ajax call is started
$xhr.done(function(data) {
//do stuff
})
});
So you can adapt the other snippet like
function start(){
var links = $('.category a');
var i = 0;
var clickNextLink = function() {
ajaxObserver.one("start", function($xhr) {
$xhr.done(function(data) {
if(i < links.length) {
fillProducts();
clickNextLink();
} else {
done();
}
});
})
$(links.get(i++)).click();//click current link then increment i
}
clickNextLink();
}
try this:
function start(){
$('.category a').each(function(i){
$(this).click();
fillProducts() ;
})
}
I get ya now. This is like say:
when facebook loads, I want to remove the adverts by targeting specific class, and then alter the view that i actually see.
https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/
Is a plugin for firefox, this will allow you to create a javascript file, will then allow you to target a specific element or elements within the html rendered content.
IN order to catch the ajax request traffic, you just need to catcher that within your console.
I can not give you a tutorial on greasemonkey, but you can get the greasemonkey script for facebook, and use that as a guide.
http://mashable.com/2008/12/25/facebook-greasemonkey-scripts/
hope this is it
This should be quite simple but I'll be darned if I can work it out. Just trying to get a div to display while my ajax is processing and then hide once done (I've put a sleep in there purely to test its working as locally it loads so fast I'm not sure if its working or not)!
The html page has this code in the script: -
$(document).ready(function(){
$("#loadingGIF").ajaxStart(function () {
$(this).show();
});
$("#loadingGIF").ajaxStop(function () {
window.setTimeout(partB,5000)
$(this).hide();
});
function partB(){
//just because
}
var scenarioID = ${testScenarioInstance.id}
var myData = ${results as JSON}
populateFormData(myData, scenarioID);
});
There is then a div in my page like so (which I can see in the source of the page just hidden): -
<div id="loadingGIF" ><img src='${application.contextPath}/images/spinner.gif' height="50" width="50"></div>
The ready code then goes off and calls this: -
function populateFormData(results, scenarioID) {
$table = $('#formList')
for(var i in results){
var formIDX = (results[i]["forms_idx"])
var formID = (results[i]["form_id"])
appendSubTable(formIDX, scenarioID, $table, formID);
}
}
Which references this multiple times calling several AJAX posts: -
function appendSubTable(formIDX, scenarioID, $table, formID) {
var $subTable = $table.find("#" + formIDX).find('td:eq(1)').find("div").find("table")
var url = "**Trust me this bits OK ;) **"
$.post(url, {
formIDX : formIDX, scenarioID : scenarioID, formID :formID
}, function(data) {
$subTable.append(data)
}).fail(function() {
});
}
Any pointers gratefully received...
Interestingly I bunged some alerts into my ajaxstart and stop and neither show up ever so I'm missing something obvious :S When I check the console in firefox I can see that all my POSTs are completing....
You should probably add the Ajaxstart and stop global event handlers to the document node like this
$(document).ajaxStart(function () {
$("#loadingGIF").show();
});
I realized my problem, I needed to register the ajaxstart and stop to the document not the div!
So instead of this: -
$("#loadingGIF").ajaxStart(function () {
$(this).show();
});
I now have: -
$(document).ajaxStart(function () {
$("#loadingGIF").show();
});
I assume this is because its the document that the ajax is running against not the div although my understanding there may not be 100% accurate at least this works so please tell me if I've misunderstood this! :)
#jbl, thanks for this pointer I did this to also leave the notification on screen for a few more moments just to make sure everything is loaded.
I have already implemented some AJAX pagination in my Rails app by using the example code for the will_paginate plugin--which is apparently using Prototype.
But if I wanted to switch to using jQuery for future additions, I really don't want to have the Prototype stuff sitting around too (yes, I know it's possible). I haven't written a lick of JavaScript in years, let alone looked into Prototype and jQuery... so I could use some help converting this bit into jQuery-compatible syntax:
document.observe("dom:loaded", function() {
// the element in which we will observe all clicks and capture
// ones originating from pagination links
var container = $(document.body)
if (container) {
var img = new Image
img.src = '/images/spinner.gif'
function createSpinner() {
return new Element('img', { src: img.src, 'class': 'spinner' })
}
container.observe('click', function(e) {
var el = e.element()
if (el.match('.pagination a')) {
el.up('.pagination').insert(createSpinner())
new Ajax.Request(el.href, { method: 'get' })
e.stop()
}
})
}
})
Thanks in advance!
Edit: Nick Craver's answer got me 90% of the way there, so I just had to pick up enough jQuery to make the HTML element substitution. In place of the line where Nick had $.get($(this).attr("href"));, put this line:
$.get(this.href, null, function(data){ $(this).html(data); }, 'html');
You can shorten this down a bit in jQuery to:
$(function() {
$('.pagination a').live('click', function(e) {
$(this).parent('.pagination')
.append("<img src='/images/spinner.gif' class='spinner' />");
$.get($(this).attr("href"));
return false;
});
});
I'm not entirely sure about new Ajax.Request(el.href, { method: 'get' }) though, is this a script being requested? It looks like nothing's being done with the content after return.