This is how it looks for jQuery.
How can I achieve the same thing with Mootools?
$(window).on("navigate", function (event, data) {
var direction = data.state.direction;
if (direction == 'back') {
// do something
}
if (direction == 'forward') {
// do something else
}
});
In jQuery, this is a wrapper around onhashchange and popstate, it's not even standard jQuery but jQuery mobile etc.
There is no such wrapper out of the box in mootools-core but you can make one.
eg Cpojer wrote history.js - http://mootools.net/forge/p/history - there were a lot others.
if you want to go native, you can.
window.addEvent('hashchange', function(e){
console.log(e);
alert('hi');
});
etc etc.
Related
lately I have been studing nightmare module I think it's very simple and useful but I have question.
how to use callback when I click ajax button
MyCode
var Nightmare = require('nightmare'),
nightmare = Nightmare();
nightmare
.goto('https://motul.lubricantadvisor.com/Default.aspx?data=1&lang=ENG&lang=eng')
.click('input[title="Cars"]')
.wait(1000)
.evaluate(function () {
//return $('#ctl00_ContentPlaceHolder1_lstModel option');
var links = document.querySelectorAll('#ctl00_ContentPlaceHolder1_lstMake option');
return [].map.call(links, function (e) {
return {value: e.value, name: e.text};
});
})
.end()
.then(function (items) {
console.log(items);
});
there is wait method. most people use wait methed I searched googling
.wait(1000)
I don't use wait method. because If it's network disconnect or slow. It's not good code
Could you help me callback method??
Thanks. So I have motify the code but It's doesn't work
var Nightmare = require('nightmare'),
nightmare = Nightmare();
nightmare
.goto('https://motul.lubricantadvisor.com/Default.aspx?data=1&lang=ENG&lang=eng')
.click('input[title="Cars"]')
.wait('#result > #ctl00_ContentPlaceHolder1_lstMake option')
.evaluate(function () {
$(document).ajaxSuccess(function () {
var links = document.querySelectorAll('#ctl00_ContentPlaceHolder1_lstMake option');
return [].map.call(links, function (e) {
return {value: e.value, name: e.text};
});
});
})
.end()
.then(function (items) {
console.log(items);
});
There are many ways to solve this. The easiest would be the following.
Suppose when an Ajax request finishes, it always changes something on the page. Most of these changes can be easily detected when waiting for specific elements to appear which can be matched by CSS selectors.
Let's say you click something and the result is written into the element matched by "#result". If there wasn't such an element before the click then you can wait until the existence of this element:
.click("button")
.wait("#result")
// TODO: do something with the result
You can also use CSS selectors to count things. For example, let's say there are ten elements that can be matched with "#result > a". If a click adds 10 more, then you can wait for the 20th using:
.click("button")
.wait("#result > a:nth-of-type(20)")
// TODO: do something with the result
The world of CSS selectors is pretty big.
Of course, you could use evaluate to add a general Ajax event handler like $(document).ajaxSuccess(fn) to be notified whenever some callback finished, but the source code of a page changes all the time. It would be easier to maintain your code if you would look for the results that can be seen in the DOM.
Use this, ajax callback..
$.ajax(url,{dataType: "json", type: "POST" })
.then(function successCallback( data ) { //successCallback
console.log(data);
}, function errorCallback(err) { //errorCallback
console.log(err);
});
// console.log(2);
});
$('.collapse').each(function() {
var title= $(this).siblings('.accordion-heading').find('a');
$(this).on('show hide', function (e) {
if(!$(this).is(e.target))return;
title.parent().toggleClass('active', 300);
title.parent().hasClass('active') ? $('input.party').prop('value', '') : $('input.party').val(title.siblings('.delete').prop('id'));
var id = title.siblings('.delete').prop('id');
var data = {id: id};
$.post("times.php", data, function(result) {
if(title.parent().hasClass('active')){
$('.times').html('');
} else {
$('.times').html($.parseJSON(result));
}
})
})
})
So I am adding a new accordion-group to my html by adding a new party and I wan't all this to work on the newly added elements as well. I didn't find topics that could help me since it is a bit more specific than any random each function (I think).
This future elements thing is new to me, so I would appreciate some explanations or a good link to a place other that the jquery website which I already checked.
Thank you for your time!
Basically what I want to do this replace $(this).on('show hide', function (e) { with something like $(document).on('show hide', $(this), function (e) {. What I just wrote doesn't work though.
If it is just about the event handler, then you can use event delegation to capture the event on dynamically created elements as well.
There is not reason why you have to use .each here, so just omit it:
$(document.body).on('show hide', '.collapse', function() {
var title = $(this).siblings('.accordion-heading').find('a');
if(!$(this).is(e.target))return;
// rest of the code...
});
this will apply on any new objects matching selector
jQuery(document).on('show hide', '.accordion-heading a', function(event){
...
});
I have a Twitter bootstrap carousel .on(slid) event that is fired after clicking a element that targets a particular slide, and an .on(slid) event that is fired after clicking a different element (close button). However once the second event occurs, it continues to fire even with the first on(slid) event. I thought preventDefault() would fix this but it doesn't. I even tried a more complete function (shown below, from Herb Caudill) to do this, but no go.
Using (this) to tie the scope of the event to the function didn't work. I am fairly new at this, so I am thinking there may be a fundamental concept here that I'm not grasping.
Here's a simplified version of my code:
// Intended to prevent event bubble up or any usage after this is called.
eventCancel = function (e)
{
if (!e)
if (window.event) e = window.event;
else return;
if (e.cancelBubble != null) e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
if (e.preventDefault) e.preventDefault();
if (window.event) e.returnValue = false;
if (e.cancel != null) e.cancel = true;
}
$('.recentContent').click(function(){
var $lastIndex = $('#splashCarousel .carousel-inner').children().last().getIndex();
$('#splashCarousel').carousel($lastIndex); //slide to specific index
$('#splashCarousel').carousel('pause');
$('#splashCarousel').on('slid', function (e) {
alert("open");
//do stuff
return eventCancel(e);
})
});
$('.closeX').click(function(){
var $lastItem = $('#splashCarousel .carousel-inner').children().last();
$('#splashCarousel').carousel(0);
$('#splashCarousel').on('slid', function (e) {
alert("close");
//do other stuff
return eventCancel(e);
})
});
and here's an even simpler fiddle trying preventDefault: http://jsfiddle.net/chardwick/a5Dpe/
What might I being doing wrong?
Thanks!
Edit: I see some discussion elsewhere on SO about nesting events, both that they shouldn't be done, and that sometimes they have to. Either way I still seem to get multiple event firings. Using live() for event delegation looks promising. Still could use some feedback though, as it's all starting to muddle for me.
I use the following code to run my form ajax requests but when i use the live selector on a button i can see the ajax response fire 1 time, then if i re-try it 2 times, 3 times, 4 times and so on...
I use .live because i also have a feature to add a post and that appears instantly so the user can remove it without refreshing the page...
Then this leads to the above problem... using .click could solve this but it's not the ideal solution i'm looking for...
jQuery.fn.postAjax = function(success_callback, show_confirm) {
this.submit(function(e) {
e.preventDefault();
if (show_confirm == true) {
if (confirm('Are you sure you want to delete this item? You can\'t undo this.')) {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
} else {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
return false;
})
return this;
};
$(document).ready(function() {
$(".delete_button").live('click', function() {
$(this).parent().postAjax(function(data) {
if (data.error == true) {
} else {
}
}, true);
});
});
EDIT: temporary solution is to change
this.submit(function(e) {
to
this.unbind('submit').bind('submit',function(e) {
the problem is how can i protect it for real because people who know how to use Firebug or the same tool on other browsers can easily alter my Javascript code and re-create the problem
If you don't want a new click event bound every time you click the button you need to unbind the event before re-binding it or you end up with multiple bindings.
To unbind events bound with live() you can use die(). I think the syntax using die() with live() is similar to this (untested):
$(document).ready(function(){
$('.delete_button').die('click').live('click', function(){
$(this).parent().postAjax(function(data){
if (data.error == true){
}else{
}
}, true);
});
});
However, if you are using jQuery 1.7 or later use on() instead of live() as live() has been deprecated since 1.7 and has many drawbacks.
See documentation for all the details.
To use on() you can bind like this (I'm assuming the delete_button is a dynamically added element) :
$(document).ready(function(){
$(document).off('click', '.delete_button').on('click', '.delete_button', function(){
$(this).parent().postAjax(function(data){
if (data.error == true){
}else{
}
}, true);
});
});
If you are using an earlier version of jQuery you can use undelegate() or unbind() and delegate() instead. I believe the syntax would be similar to on() above.
Edit (29-Aug-2012)
the problem is how can i protect it for real because people who know
how to use Firebug or the same tool on other browsers can easily alter
my Javascript code and re-create the problem
You can some-what protect your scripts but you cannot prevent anyone from executing their own custom scripts against your site.
To at least protect your own scripts to some degree you can:
Write any script in an external js file and include a reference to that in your site
Minify your files for release
Write any script in an external js file and include a reference to that in your site
That will make your html clean and leave no trace of the scripts. A user can off course see the script reference and follow that for that you can minify the files for release.
To include a reference to a script file:
<script type="text/javascript" src="/scripts/myscript.js"></script>
<script type="text/javascript" src="/scripts/myscript.min.js"></script>
Minify your files for release
Minifying your script files will remove any redundant spacing and shorten function names to letters and so no. Similar to the minified version of JQuery. The code still works but it is meaningless. Off course, the hard-core user could follow meaningless named code and eventually figure out what you are doing. However, unless you are worth hacking into I doubt anyone would bother on the average site.
Personally I have not gone through the minification process but here are some resources:
Wikipedia - Minification (programming)
Combine, minify and compress JavaScript files to load ASP.NET pages faster
How to minify (not obfuscate) your JavaScript using PHP
Edit (01-Sep-2012)
In response to adeneo's comment regarding the use of one().
I know you already found a solution to your problem by unbinding and rebinding to the submit event.
I believe though it is worth to include a mentioning of one() in this answer for completeness as binding an event with one() only executes the event ones and then unbinds itself again.
As your click event, when triggered, re-loads and rebinds itself anyway one() as an alternative to unbinding and re-binding would make sense too.
The syntax for that would be similar to on(), keeping the dynamic element in mind.
// Syntax should be right but not tested.
$(document).ready(function() {
$(document).one('click', '.delete_button', function() {
$(this).parent().postAjax(function(data) {
if (data.error == true) {} else {}
}, true);
});
});
Related Resources
live()
die()
on()
off()
unbind()
delegate()
undelegate()
one()
EDIT AGAIN !!!! :
jQuery.fn.postAjax = function(show_confirm, success_callback) {
this.off('submit').on('submit', function(e) { //this is the problem, binding the submit function multiple times
e.preventDefault();
if (show_confirm) {
if (confirm('Are you sure you want to delete this item? You can\'t undo this.')) {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
} else {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
});
return this;
};
$(document).ready(function() {
$(this).on('click', '.delete_button', function(e) {
$(e.target.form).postAjax(true, function(data) {
if (data.error) {
} else {
}
});
});
});
jQuery.fn.postAjax = function(success_callback, show_confirm) {
this.bind( 'submit.confirmCallback', //give your function a namespace to avoid removing other callbacks
function(e) {
$(this).unbind('submit.confirmCallback');
e.preventDefault();
if (show_confirm === true) {
if (confirm('Are you sure you want to delete this item? You can\'t undo this.')) {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
} else {
$.post(this.action, $(this).serialize(), $.proxy(success_callback, this));
}
return false;
})
return this;
};
$(document).ready(function() {
$(".delete_button").live('click', function() {
$(this).parent().postAjax(function(data) {
if (data.error == true) {
} else {
}
}, true);
});
});
As for the "people could use Firebug to alter my javascript" argument, it does not hold : people can also see the request that is sent by your $.post(...), and send it twice.
You do not have control over what happens in the browser, and should protect your server side treatment, rather than hoping that "it won't show twice in the browser, so it will prevent my database from being corrupt".
I have:
$('.image.txt_over').hover(function(){
$(".screen", this).stop().animate({top:'165px'},{queue:false,duration:300});
$(this).fadeTo("slow", 1);
}, function() {
$(".screen", this).stop().animate({top:'226px'},{queue:false,duration:460});
});
and I am trying to keep the jquery hover effect once a new set of images are refreshed via Ajax. Currently the jquery is killed once the Ajax refreshes.
I think I need .delegate() or .live() but cant seem to get either to work. Still learning jquery.
Try this:
$('body').delegate('.image.txt_over', 'mouseover mouseout', function(event) {
if (event.type == 'mouseover') {
$(".screen", this).stop().animate({top:'165px'},{queue:false,duration:300});
$(this).fadeTo("slow", 1);
} else {
$(".screen", this).stop().animate({top:'226px'},{queue:false,duration:460});
}
});