How to translate Protoype "Ajax.Responders.register" to jQuery - javascript

I have to translate some prototype code to jquery and and I don't know how to translate this part :
Ajax.Responders.register({
onCreate: function() {
$('working').show();
window.onbeforeunload = check_working;
},
onComplete: function() {
$('working').hide();
window.onbeforeunload = null;
}
});
In fact I found some pages which deal with this problem (Prototype - Are there AJAX start/stop events to global trigger an AJAX modal wait message? for instance) but I did this :
jQuery(document).ajaxSend(function() {
jQuery('#working').show();
window.onbeforeunload = check_working;
});
jQuery(document).ajaxStop(function() {
jQuery('#working').hide();
window.onbeforeunload = null;
});
And I don't know why but I never enter into the ajax.start and stop (I tried with console.log by doing the same things that I did with the previous version which works). And I have no error.
Do you have any ideas how to fix it ?
Thank you in advance.

Related

How to make function execute only once in JS / JQuery

i have a structure like this :
// App.js
var APP = {
viewIndex: function(){
EVT.doSomething();
},
// Another function below
}
// Event.js
var EVT = {
doSomething: function(){
deleteField();
function deleteField(){
$("body").on("click", "#btn", function(){
console.log("Clicked");
})
}
}
}
my project is SPA wannabe, so when i want to change the page, it must execute some function inside App.js, but my problem is, when i call APP.viewIndex() (when i go to Index, go back, and go to index again(without refreshing page) ), the function inside EVT -> doSomething() is execute twice, so i have no idea how to prevent it,
in my console i got this :
Clicked
Clicked
*sorry if my explanation is a bit complicated
hope you guys can help me out of this problem :D
thanks
Use a property to remember if you already called deleteField().
var EVT = {
didSomething: false,
doSomething: function(){
if (!this.didSomething) {
deleteField();
this.didSomething = true;
}
function deleteField(){
$("body").on("click", "#btn", function(){
console.log("Clicked");
})
}
}
}

JavaScript multipage form onbeforeunload issue

I am putting together a quiz system using the multipage form jQuery script and I would like to be able to warn the user if tries to close the page. I managed to do this just fine using the code below:
$(document).ready(function($) {
window.onbeforeunload = function(){
return 'Sure you want to close the page?';
};
});
My problem is that when I try to submit the form and post the results I get the warning asking me if I want to navigate away from this page. This is the code:
$('#quizForm').formwizard({
validationEnabled: true,
focusFirstInput : true,
formOptions: {
beforeSubmit: window.onbeforeunload = null,
resetForm: true
}
});
What am I doing wrong?
LE: I created this fiddle maybe someone can help me out, I am running out of ideas.
http://jsfiddle.net/awLYY/5/
first, you don't need to wait for the DOM to be ready in order to attach an onbeforeunload handler.
second, since the onbeforeunload is a function, you can choose wither to return a string or return nothing in case you're submitting some data to the server
var isFormBeingSubmitted = false;
window.onbeforeunload = function() {
if( isFormBeingSubmitted ) {
return;
}
return 'Sure you want to close the page?';
};
// now before you submit your form, just enable the isFormBeingSubmitted
$('#quizForm').formwizard({
validationEnabled: true,
focusFirstInput : true,
formOptions: {
beforeSubmit: function() {
isFormBeingSubmitted = true;
return true;
},
resetForm: true
}
});
To answer my own question, all I had to do was to add to the formwizard options:
formPluginEnabled: true
Now everything is working fine. Thanks

automatic clicks on links and doing something with every page's DOM

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

prototype AJAX loading blank page onSuccess

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..

Backbone.Marionette: Defer view close until beforeClose animation is complete

I'm trying to set animations on rendering and closing an ItemView with Backbone.Marionette. For rendering a view, this is fairly simple:
MyItemView = Backbone.Marionette.View.extend({
...
onRender: function() {
this.$el.hide().fadeIn();
}
...
});
This will have my view fade in when I render it. But let's say I want to fade out my view upon close.
beforeClose: function() {
this.$el.fadeOut(); // doesn't do anything....
}
This won't work, because the item closes immediately after calling this.beforeClose(), so the animation doesn't have time to complete.
Is there any way, using Marionette as it stands, to accomplish a closing animation?
Alternatively, this is the workaround I've been using:
_.extend(Backbone.Marionette.ItemView.prototype, {
close: function(callback) {
if (this.beforeClose) {
// if beforeClose returns false, wait for beforeClose to resolve before closing
// Before close calls `run` parameter to continue with closing element
var dfd = $.Deferred(), run = dfd.resolve, self = this;
if(this.beforeClose(run) === false) {
dfd.done(function() {
self._closeView(); // call _closeView, making sure our context is still `this`
});
return true;
}
}
// Run close immediately if beforeClose does not return false
this._closeView();
},
// The standard ItemView.close method.
_closeView: function() {
this.remove();
if (this.onClose) { this.onClose(); }
this.trigger('close');
this.unbindAll();
this.unbind();
}
});
Now I can do this:
beforeClose: function(run) {
this.$el.fadeOut(run); // continue closing view after fadeOut is complete
return false;
},
I'm new to using Marionette, so I'm not sure if this is the best solution. If this is the best way, I'll submit a pull request, though I'll want to put a bit more thought into how this could work with other types of views.
This could potentially be used for other purposes, such as asking for confirmation on close (see this issue), or running any kind of asynchronous request.
Thoughts?
Overriding the close method is the one way to do this, but you can write it bit shorter, as you can call the Marionettes close method instead of duplicating it:
_.extend(Backbone.Marionette.ItemView.prototype, {
close: function(callback) {
var close = Backbone.Marionette.Region.prototype.close;
if (this.beforeClose) {
// if beforeClose returns false, wait for beforeClose to resolve before closing
// Before close calls `run` parameter to continue with closing element
var dfd = $.Deferred(), run = dfd.resolve, self = this;
if(this.beforeClose(run) === false) {
dfd.done(function() {
close.call(self);
});
return true;
}
}
// Run close immediately if beforeClose does not return false
close.call(this);
},
});
Another idea is to overide the remove method of your view. So you fade out the element of the view and then remove it from the DOM
remove: function(){
this.$el.fadeOut(function(){
$(this).remove();
});
}

Categories

Resources