I'm using Mootools Behavior - https://github.com/anutron/behavior. It works fine but behavior of elements that are ajax-loaded doesn't apply.
Here's my code:
var request = new Request.HTML({
url: get_url(),
append: $(api.get('append')),
evalScripts: true,
onSuccess: function(){
window.behavior.apply(document.body);
}
});
And it doesn't work.
(window.behavior is the main Behavior instance)
Thank in advance.
UPD. That was my own problem with static loading. The code above should work.
Maybe you should try to set the second, optional parameter on the Behavior.apply()-method.
Try window.behavior.apply(document.body, true) in your success-callback function. Elements which already have been processed will be processed again, if the second parameter "force" is set to true. That could be your problem, if not, check back and let us now please.
Instead of re-applying the behavior to the entire document, re-apply it to the new content only. I use this pattern frequently with success.
var target = $(api.get('append'));
var request = new Request.HTML({
url: get_url(),
append: target,
evalScripts: true,
onSuccess: function() {window.behavior.apply(target);}
});
Related
I am trying to use mootools ajax requests to record clicks on outgoing links. So far here is what I'm doing.
Each link looks like follows:
<div id="1">
StackOverflow
</div>
The javascript function clickRecord(id) is defined as follows:
function clickRecord(id){
var u = "record.php";
var req = new Request({
method: 'post',
url: u,
data:{'id':id},
onComplete:function(response){
}
}).send();
}
The problem I have is this. If I add a return false; to the onclick="" declaration, everything works fine, of course the problem there is that click does not take the user to the intended page. If I do not have the return false; then it seems like the ajax call is never executed.
I thought the onclick event should execute first and then only the default action should execute. Is this not the case?
There is an even stranger scenario if you use onmousedown event instead. It seems like on Firefox, if you use the onmousedown event, once you go to the new page, you cant simply navigate back to the old page, you have to refresh the old page. Else the call is not executed. This does not happen on IE.
Don't use onclick - very 1995.
Instead attach an event to the element and use event.stop(), ie:
StackOverflow
JS:
document.getElements('a').addEvents({
click: function(event) {
event.stop();
var u = 'record.php';
var req = new Request({
method: 'post',
url: u,
data: {
'id': this.get('data-id');
},
onComplete: function(response) {}
}).send();
}
});
Btw. <div id="1"> this is not valid in HTML, an ID'd needs to start with a letter.
OK. Found an answer to one of the questions:
The inline mootools request did not execute when declared through the onclick().
It seems this was caused by the script not being synchronous. So probably it returns without actually fully committing the request, and the browser then moves to another page breaking the execution. Adding a synchronous call to the script fixes the problem:
function clickRecord(id){
var u = "record.php";
var req = new Request({
async:false,
method: 'post',
url: u,
data:{'id':id},
onComplete:function(response){
}
}).send();
}
The second problem that was mentioned on the onmousedownevent, i.e. firefox not executing the ajax call if the browser navigates back is still unsolved. However I am leaving that to be as that wasn't the main question raised.
On my website I have mouse over and mouse out events set up on an HTML table. These events trigger ajax requests, and perform certain actions etc. However, i want to be able to not trigger a second request if one is already running. So, is there away to detect these requests, and therefore avoid a second. Incidentally Im using the jQuery $.ajax()
if it helps at all.
Thanks in advance
Chris
I'd try something simple like:
var requestMade = false;
function yourAjaxFunction(){
if(!requestMade)
{
requestmade = true;
$.ajax({
url: "page",
success: function(){
requestMade = false;
}
error: function(){
requestMade = false;
}
});
}
}
You can use the success: and error: settings to change the variable back to false.
I have never used the error so you may have to include some other things in it, but this is the general idea.
For this suppose I'd use ajaxStart() and ajaxStop() which would change specific variable ajaxRunning which could be checked before sending the request (maybe in ajaxStart() directly?)
Set global or local static variable to true when first ajax is about to trigger, than add if before triggering the second one ;) Than after one request is finished, set this variable to false
This is a mock of what I'm doing:
function loadPage(pn) {
$('#'+pn).live('pagecreate',function(event, ui){
$('#'+pn+'-submit').click( function() {
$.mobile.changePage({
url: 'page.php?parm=value',
type: 'post',
data: $('form#'+pn+'_form')
},'slide',false,false);
loadAjaxPages(pn);
});
});
function loadAjaxPages(page) {
// this returns the page I want, all is working
$.ajax({
url: 'page.php?parm=value',
type: 'POST',
error : function (){ document.title='error'; },
success: function (data) {
$('#display_'+page+'_page').html(data); // removed .page(), causing page to transition, but if I use .page() I can see the desired listview
}
});
}
in the ajax call return if I add the .page() (which worked in the past but I had it out side of the page function, changing the logic on how I load pages to save on loading times), make the page transition to the next page but I can see the listview is styled the way I want:
$('#display_'+page+'_page').html(data).page();
Removing .page() fixes the transition error but now the page does not style. I have tried listview('refresh') and even listview('refresh',true) but no luck.
Any thoughts on how I can get the listview to refresh?
Solution:
$.ajax({
url: 'page.php?parm=value',
type: 'POST',
error : function (){ document.title='error'; },
success: function (data) {
$('#display_'+page+'_page').html(data);
$("div#name ul").listview(); // add div wrapper w/ name attr to use the refresh
}
});
Be sure to call .listview on the ul element
If it didn't style earlier, you just call .listview(), bot the refresh function. If your firebug setup is correct, you should have seen an error message telling you that.
I didn't have time to get down to creating some code before you posted your fix, but here's a little recommendation from me:
if(data !== null){ $('#display_'+page+'_page').html(data).find("ul").listview() }
This is a bit nicer than a new global selector. Also - you don't need the div and you can provide a detailed selector if you have multiple ULs.
caution: the above code requires data !== null. If it's null - it will throw an error.
If you add items to a listview, you'll need to call the refresh() method on it to update the styles and create any nested lists that are added. For example:
$('#mylist').listview('refresh');
Note that the refresh() method only affects new nodes appended to a list. This is done for performance reasons. Any list items already enhanced will be ignored by the refresh process. This means that if you change the contents or attributes on an already enhanced list item, these won't be reflected. If you want a list item to be updated, replace it with fresh markup before calling refresh.
more info here.
I'm having a problem with, guess what, IE8. The following code, simplified for clarity, does not work at all:
alert('before get');
$.get(getActivityURL('ActionName',{
ts: new Date().getTime(), ...other params...}),
{cache:false;},
function (xml) {
alert("in get callback");
},'xml'); // End $.get()
alert('in after get');
The getActivityUrl() outputs a valid URL with request parameters.
This works correctly in FF and Chrome. However, in IE8, this doesn't even get into the $.get() callback. I get the "before" and "after" alerts, but not the "in" alert and indeed, nothing happens and the request is NOT sent. I don't really know what to think here.
The response headers are "Content-Type:application/xml; charset:iso-8859-1" as confirmed in FF.
EDIT: $.post() doesn't work, either.
IE is infamous for caching. So you need to make sure you are not getting a cached result.
You can disable caching globally by setting the cache property value to false in the ajaxStart method.
$.ajaxSetup({
cache: false
});
Or If you want to eliminate the cached result in a specific ajax call, Append a unique number to the end of the url. You may use the $.now() method to get a unique number
$.get("someurl.php?" + $.now() ,function(result) {
// do something with result
});
$.now() method return a number representing the current time.
I'm not sure if it is a problem but try to remove ";" in {cache:false}
IE doesn't like any additional stuff in {}, eg
{a:a,b:b,c:c,} will work in FF but not in IE
I think so there is Cache problem in IE.
So add Math.random(), one more parameter at the end like "&mathRandom="+Math.random();
Because IE will recognise same request as previous one so it will give data from cache instead of firing request.
$J.get(getActivityURL('ActionName'
// End $.get()
Is this correct? I mean $J... Are you using more than one JS framework or something?
have u tried:
$.ajax({
url: getActivityURL('ActionName',{ts: new Date().getTime(), ...other params...}),
data: data,
success: function (xml) {
alert("in get callback");
},
dataType: 'xml'
});
Just a guess
EDIT:
I found a interesting thread that might help you, check this out:
jQuery issue in Internet Explorer 8
I'm using the following to grab some updated HTML and insert it into a div with id "content"
var updater = new Ajax.PeriodicalUpdater('content', '/Doc?'+d.getTime(),
{
method: 'post',
frequency: 5,
});
The problem is that when the server is shut down (it's running inside of an app that is modifying and server up the data), the updater then simply clears out the content div.
Is there a way to make it so that when PeriodicalUpdater times out, gets a 404, etc. it just leaves the content unchanged? I would rather that the last available data just stay there, not be erased.
For completeness, this is my entire code:
<html>
<head>
<title></title>
<script type="text/javascript" src="/Prototype"></script>
<script type="text/javascript">
var css;
var css_data;
function load_content()
{
var d = new Date();
css = document.createElement('style');
css.setAttribute('type', 'text/css');
if(css.styleSheet) { css.styleSheet.cssText = '';} //Because IE is evil
else { css_data = document.createTextNode(''); css.appendChild(css_data); } //And everyone else is cool
document.getElementsByTagName("head")[0].appendChild(css);
var updater = new Ajax.PeriodicalUpdater({success: 'content'}, '/%doc_path%?'+d.getTime(),
{
method: 'post',
frequency: 5,
onSuccess: function(transport) {
new Ajax.Request('/%css_path%?'+d.getTime(), {
method: 'post',
onSuccess: function(transport) {
if(css.styleSheet) { css.styleSheet.cssText = transport.responseText}
else {
var new_css_data = document.createTextNode(transport.responseText);
css.replaceChild(new_css_data, css_data);
css_data = new_css_data;
}
}
});
new Ajax.Request('/%title_path%?'+d.getTime(), {
method: 'post',
onSuccess: function(transport) {
document.title = transport.responseText;
}
});
}
});
}
</script>
</head>
<body>
<div id="content"></div>
<script type="text/javascript">
load_content();
</script>
</body>
</html>
As you can see, I tried Triptych's solution...but still no go. It updates with blank data when the request fails still. Since I've got the whole thing here now, can anyone see any mistakes I'm making.
Note: Ignore the strings like %doc_path%... those are just control strings I use so that they can later be replaces programmatically with the proper path for each document...all stuff that's done on the server and really doesn't matter for this.
#Vinze
According to the documentation, onFailure is "Invoked when a request completes and its status code exists but is not in the 2xy family. This is skipped if a code-specific callback is defined, and happens before onComplete."
But if the server was stopped, wouldn't it just time out and there be no status code at all? Maybe I'm understanding that wrong...
Pass an object (not a string) as the first parameter to PeriodicalUpdater. The value keyed as 'success' will only be called on successful AJAX calls.
new Ajax.PeriodicalUpdater({success: 'content'}, '/Doc?'+d.getTime(),
{
method: 'post',
frequency: 5,
});
More on Ajax.Updater (from which PeriodicalUpdater inherits)
you can add a onFailure option in the option list as the Ajax.PeriodicalUpdater inherits the properties of Ajax.Request (http://www.prototypejs.org/api/ajax/request)
In the opposite you may be more interested in the use of "onComplete" or any of the "Request life-cycle" in the link below
How about doing it all by yourself?
Start with a function that will call the update:
function requestMoreInfo(){
new Ajax.Request('url',
{
method:'get',
parameters: "someget=here",
onSuccess: handleTheReturn
});
}
Then create a function that will handle the answer from the server:
function handleTheReturn(reply){
var newMessages = eval('(' + reply.responseText + ')');
//update your element or whatever
}
And then run it every 20(or whatever) seconds with:
new PeriodicalExecuter(requestMoreInfo, 20);
Then just add a first requestMoreInfo to your onload function and your good to go... now to solve your problem, just validate the newMessages var in the handleTheReturn function and you can do anything you want(make the server send a JSON object to know is ok, or some other codes maybe, or search for the specific errors you want to avoid!
More details on this.
Ajax.PeriodicalUpdater does not inherit from Ajax.Updater, as explained on http://www.prototypejs.org/api/ajax/periodicalupdater:
Ajax.PeriodicalUpdater is not a specialization of Ajax.Updater, despite its name.
It does forward the optional parameters to Ajax.Updater (itself a class that inherits from Ajax.Request), which does seem to imply that it is equivalent to instantiating an Ajax.Request and passing callbacks to it.
I have tested and can confirm that adding a onFailure function does not work in this case. Nor does adding onException.
Both could have been expected to work, since they are passed to the Ajax.Updater object instantiated by the Ajax.PeriodicalUpdater. However, after some debugging, it appears that Ajax.Updater never considers an unavailable server as an exception or a failure. That is, the container for success is always updated (well, emptied, in this case), even when defined as {success : 'content', failure : 'failureContent'}.
Also, according to my tests, Ajax.Updater (and Ajax.PeriodicalUpdater) calls neither onSuccess() nor onComplete() when the server does not respond.
In fact, the only callback I managed to get is on0, as follows:
new Ajax.PeriodicalUpdater('content', 'url', {
frequency: 5,
on0: function(requester, exception) {
alert("ERROR 0");
}
});
It appears that 0 is the error code for Ajax.Request (the parent class for Ajax.Updater) when the server is not reachable.
The bad news, however, is that on0() is called before the content is updated/emptied, meaning that it is impossible to replace that content with a custom one.
As far as I can tell, in the case of the server being unreachable, no optional callback at all is called after the content is updated.
This is true both for Ajax.PeriodicalUpdater and Ajax.Updater. Meaning that the only way I see to get the wanted behavior is to use Ajax.Request directly.