I am in deep trouble with my new requirement.
Suppose there is a form opened in Firefox & IE [Form contains some list of question and a textbox for asking question]. Now if i add some new question [in the Firefox], it needed to be displayed within a few second in the other browsers too [without refreshing the page].
I have tried to call a ajax page using setTimeout. But the problem is i can't use the innerhtml after getting the response from Ajax page. Think about the situation when a user tried to add something on a different browser when the innerHTML inside the ajax call overwrite the page . Please suggest a solution. :(
EDIT:
var auto_refresh = setInterval( function (){
$.post("something.php", { proj_id: $('#proj_id').val() }, function (data) {
if(data) { //alert(data); $('#autoRef').html(data).fadeIn("slow"); } },"html");
},
1000);
Related
I'm learning javascript by creating a program which requests an API and dispays various properties (price in this example) to html. I have a few questions about my code and some problems I've been facing.
1). I have a bunch of $.getJSON functions corresponding to each value that I want to retrieve. I put them all in a a single 2 min. timer. When the page FIRST loads, however, some of the html elements fail to load at all. But if I refresh the page, they sometimes do load. If I refresh again, they might not load at all again. Every time I refresh, there's like a 10% chance of that particular function not inserting the content in the element. If it does load and I leave the page open, it will correctly function (update its value and html element every 2 mins and add/remove the green and red classes). If it doesn't load and I leave the page open, it will correctly function in 2 mins when the 2nd api request is made. I have already tested that the variables have some value (are not null) before and after each $('#price').text('$' + price);.
Here's an example of a function that does that:
var tempPrice;
var myVar = setInterval(myTimer, 1200000);
myTimer();
function myTimer() {
$.getJSON(link, function (json) {
$.each(json, function (index, value) {
if (value.id == "price") {
var price = value.price_eur;
if (!tempPrice) {
$('#price').text('$' + price);
tempPrice = parseFloat(price);
}
if (parseFloat(price) !== tempPrice) {
$('#price').text('$' + price).removeClass();
if (parseFloat(price) > tempPrice) {
setTimeout(function () {
$('#price').addClass("green");
}, 1);
} else {
setTimeout(function () {
$('#price').addClass("red");
}, 1);
}
tempPrice = parseFloat(price);
}
}
});
});
// Many more $.getJSON functions below...
}
If I run this function alone on either jsfiddle or my dev server (flask), it works fine. It only breaks down when I use it in conjunction with more api requests. If I remember correctly, I didn't have this problem before when I used to have a separate timer for each $.getJSON function and put each in its own <script> tag directly in html.
2) I know I can loop through the json instead of using $.each. How else can I improve the code?
1
As for the problem you're having with the inconsistent behavior of the initial page loading, it's because you are executing JavaScript before giving the browser the time to load the page fully first. You can solve this simply by waiting for the page the load, and then executing your code.
Example in jQuery:
$(document).ready(function() {
// Page is loaded, execute code...
});
2
To help you improve the way you're handling the supplied JSON data, a sample of the data would be useful.
I have to use jQuery mobile on an application that uses Prototype JS. After an Ajax response (initiated using prototype) new elements are brought into the page so jQuery mobile doesn't recognize them and no classes are applied to these.
I want to execute a jQuery function after this ajax event. (I'm also unsure if it'd be correct to use jquery's .on('pageinit') in this instance.
onSuccess: function(transport) {
try {
if (transport.responseText.isJSON()) {
var response = transport.responseText.evalJSON();
var needUpdate = true;
if (response.error) {
alert(response.message);
needUpdate = false;
}
if(response.ajaxExpired && response.ajaxRedirect) {
setLocation(response.ajaxRedirect);
needUpdate = false;
}
if (needUpdate){
if (response.content){
$(categoryContainer).update(response.content);
}
if (response.messages){
$(messagesContainer).update(response.messages);
}
}
} else {
$(categoryContainer).update(transport.responseText);
}
}
catch (e) {
$(categoryContainer).update(transport.responseText);
}
}
});
I've been struggling for several hours with this. and I've found questions regarding Ajax requests made by jQuery, but nothing when prototype is handling the ajax requests. I know it's not the most optimal way to do it but in this instance is fully justified.
Any help is greatly appreciated.
Ok, I thought I'd post the solution to my own dilemma in case someone else runs into the same issue in the future.
What I needed to do was to invoke jQueryMobile at the end of my Ajax response. From their website: http://demos.jquerymobile.com/1.0.1/docs/pages/page-scripting.html
If you generate new markup client-side or load in content via Ajax and inject it into a page, you can trigger the create event to handle the auto-initialization for all the plugins contained within the new markup. This can be triggered on any element (even the page div itself), saving you the task of manually initializing each plugin (listview button, select, etc.).
For example, if a block of HTML markup (say a login form) was loaded in through Ajax, trigger the create event to automatically transform all the widgets it contains (inputs and buttons in this case) into the enhanced versions.
So in this case I did:
$jq('#myElement').trigger( "create" );
($jq = it's my jquery alias in nonConflict mode, as prototype is using $)
I have the code below to poll application variables in ASP. The code below works the first time meaning when I first start the page, if the Application("NFC")= 1 , The IF statement in the setinterval function will catch it, display the alert and then reload the page. The issue is now that the page is running, if another page sets the Application variable back to 1 again, the if statement below will no longer trigger. If I refresh the page manually, it will work again once.
I placed in the Head and the Body and the same results.
Does anyone know why this is happening and what I can do to get this working?
This code is to minimize accessing a database. I am currently accessing the database every 20 seconds now and this will allow me to only access the database if the application variable has changed, polling the variable every 5 seconds.
Any help is greatly appreciated.
Thank you JOHN...
<%
If request.querystring("R") = "reset" then
Application("NFC") = 0
response.redirect("test2.asp")
end if
%>
<script type="text/javascript">
setInterval(function(){
if('<%= Application("NFC")%>'== '1'){
alert('NFC has changed. This alert is for testing and is not needed in final code');
self.location='test2.asp?R=reset';
}
}, 5000);
</script>
basically any ajax routine will do, jQuery is more robust than this modern browser example:
server.asp:
<%= Application("NFC")%>
client.js:
function aGet(turl, callback) {
var XHRt = new XMLHttpRequest();
XHRt.onload= callback;
XHRt.open("GET", turl, true);
XHRt.send("");
}
aGet("server.asp", function(e){
alert(e.target.responseText);
});
once you see how, it's simple, but it's hard to search for. that's got to be about the simplest back-end code ever...
kudos on using the under-used yet awesome RAM cache that is the Application object: if used correctly, it can enable great real-time apps dues to the negligible cost of pinging that simple server page.
I've got PJax up and running on my test site - it works a treat. However it relies heavily on a lot of javascript widgets and hence leaks memory.
Since I don't have time right now to re-write every widget, I thought that a simple solution would be to do a normal page load after, say 20 pjax page transitions. A simple plan....but it doesn't seem to be possible.
$.pjax.disable();
....still fetches the content via AJAX, but doesn't change the page.
$(document).pjax();.
...doesn't change the behaviour
$.pjax.handleClick = function (event, container, options) { return; };
...doesn't change the behaviour
$.pjax.state.timeout = 0;
...doesn't change the behaviour
delete $.pjax;
...breaks navigation
$.pjax.defaults.timeout=0;
...doesn't change the behaviour
How do I suspend pjax?
If you add a listener for pjax:beforeSend, you can capture the requested URL, set location.href yourself and return false to cancel the pjax behavior. That is how I'm doing it with the following code:
var pageLoadCounter = 0;
var MAX_PAGE_LOADS = 20;
$(".pjaxContainer").on("pjax:beforeSend", function (e, xhr, settings) {
if (++pageLoadCounter > MAX_PAGE_LOADS) {
// URI can be found at https://github.com/medialize/URI.js
var uri = URI(settings.url);
// Remove _pjax from query string before reloading
uri.removeSearch("_pjax");
location.href = uri.toString();
return false;
}
});
I've discovered that changing the id of the pjax container div gives me the desired result - although this seems like a bit of a kludge. It would also be possible by changing the timeout of the ajax request to 0 - but I still need to work out how to do this.
I did ask on the PJax github page about this but so far have not received a response.
Right then, I'm coming to the end of a rewrite of our JavaScript system, we're moving from Prototype to jQuery. We have a load of AJAX requests that fire when a certain element events occur, the one in the example below is a new event on a calendar, but it happens elsewhere too.
The problem I'm getting is when an event is fired sometimes two AJAX requests are made. The first one returns the correct value but (as you can see) it still says processing, it never returns the success message my JavaScript requires. The second request returns the correct result AND terminates correctly.
The problem I have is our jQuery screen blocker is set up to prevent user input during heavy AJAX requests, obviously because there an AJAX request still live the screen never unlocks. If I were to refresh this screen all will work as desired.
Can anyone shed any light on why this behavior is occuring.
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request.png
EDIT
"requests that fire when a certain element events occur" - this is the key phrase, I think. Please provide some info on how you set your events. Maybe it fires twice because you have multiple handlers set? – Igor Zinov'yev
Ok, the thing is when I hit refresh the problem usually resolves itself, so not sure how that could be a handler issue, here's the event handler we typically use for a change of a select box.
$("#my_select","#context").change(function(){
// uz_ajax is a wrapper function, keeps most of the same functionality as $.ajax()
uz_ajax({
target:"#my_target",
data:{
module:'my_module',
controller:'my_controller',
action:'my_action',
id:$(this).val(),
ajax:''
}
});
});
The problem I have is I have no idea how to replicate the problem, so I do not know if the event is being fired multiple times or whether the AJAX is requesting twice.
EDIT 2
If you are reloading the elements that
are bound then the change events could
be triggered recursively... We really
need to see more code (what do you do
on success of the ajax call etc) –
redsquare
Thanks redsquare, upon a successful AJAX request I usually apply the response (usually HTML of <option>s) to the target. I never trigger a change from the element that fired the AJAX, but I sometimes trigger a change on the target element, to allow for cascading AJAX requests. If this were the problem, surely this would happen all the time? My wrapper function uz_ajax is below:
var ajax_count = 0;
var ajax_response = null;
function uz_ajax(options) {
// set default options
var defaults = {
async: true,
type: "GET",
data: {},
url: "/",
cache: false,
force_change: true,
highlight: true,
action: "normal",
dataType: "html",
selected: {
value: null,
disabled: false
}
};
// merge the passed options with the defaults
var options = $.extend(defaults, options);
// start the jQuery ajax method
$.ajax({
async: options.async,
type: options.type,
url: options.url,
data: options.data,
beforeSend: function() {
// we only want to block the screen on the first pass
if(++ajax_count==1) {
$.blockUI({message:'Loading data, please wait'});
}
},
success: function(responseText) {
if(options.target!==undefined) {
// if target isn't an array, make it one
if(!$.isArray(options.target)) {
options.target = new Array(options.target);
}
var targets = options.target;
for ( var i in targets ) {
console_info("uz_ajax() --> Applying contents to "+targets[i]);
switch(options.action) {
case "normal":
if($(targets[i]).is("input")) {
$(targets[i]).val(trim(responseText));
} else {
$(targets[i]).html(trim(responseText));
}
break;
case "selected":
// preserve the current target value (e.g. list of options), but
// set the selected value to the ajax response
console_warn("Changing selected value of "+targets[i]+" to '"+responseText+"'");
// trim the response so we don't get any smarty induced errors such as ' 7'
$(targets[i]).val(trim(responseText));
break;
}
// set selected value
if(options.selected.value!=null) {
$(targets[i]).val(options.selected.value);
}
// highlight the target
// we don't want to highlight the target if it's a hidden input, as this will force a .show(
if($(targets[i]).attr('type')!='hidden' && options.highlight===true) {
$(targets[i]).effect("highlight",{},2000);
}
// force the target to change
if(options.force_change===true) {
$(targets[i]).trigger("change");
}
/* rebind certain elements that do not use conventional events */
/* We probably need to get all of these rebinds in a single function */
createDatePickers(targets[i]);
}
} else {
ajax_response = responseText;
console_warn("uz_ajax -> no targets specified");
// Well... we have no element to target, we need to return the value instead
// of course if we return here we're going
// we probably also need to check the ajax count as this will be the last executed part before we return
}
},
complete: function () {
/* if all ajax requests have completed, unblock screen */
if(--ajax_count===0) {
$.unblockUI();
/* could use this callBack to return a value *dun dun duuuuun* */
if (options.ajaxComplete) {
options.ajaxComplete(ajax_response);
}
}
},
cache: options.cache,
dataType: options.dataType
});
}
another way to stop multiple ajax
requests is to heck jQuery.active
prior to the call. jQuery keeps an
internal count of 'live' ajax requests
using this property. – redsquare
I'll look into this.
EDIT 3
So this is the result of the $('element').data(), but I can't understand what it's trying to say, does this mean there are two binds to it. If so how do I find out what these binds are and why do they both not fire when the event is fired.
alt text http://archive.ilmv.co.uk/images/firebug-jquery-data-events.png
EDIT 4
Here's another screenshot of the problem, this time in a different place in the system. The green arrow is the element thats triggers the three ajax requests, not in firebug how there's six, and that they pair up and share timestamps down to the millisecond?
The top three are the ones that have not completed, the bottom three have return the correct result.
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v2.png
EDIT 5
The image below demonstrates what happens when a select box is changed, it fires three different ajax requests.
I've managed to do a bit more debugging and I can tell you the following:
The problem occurs regardless of how many ajax requests the initial element calls
The problem occurs regardless of what plugins are used
This event is definitely only being fired once
My uz_ajax wrapper function is only being fired once per target (see the firebug console, "Line 29: uz_ajax()".
I've added console.info on each of the jquery $.ajax() callbacks to see what's firing and when, notice how the only callback to fire is beforeSend().
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v3.png
EDIT 6
Right then, after #redsquare suggested via Twitter about using console.trace() to find out "where the second event is firing from" is, like I've always maintained I'm sure there isn't two events firing so I put the trace in the $.ajax() method, here's what happened:
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v4.png
As you can see I get the duplicate ajax request problem even though the $.ajax() method has only fired once, again the timestamps are identical. Have I come across a bug with jQuery?
EDIT 7
It happens on StackOverflow too!
alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v5.png
Have you tried using a .click() instead? I have had issues with irregular activity using .change() in javascript. Give that a try.
Right, so I've come to a conclusion, I'm pretty sure that my problem is an issue with Firebug, as I've tested it the app on FF without Firebug turned on and it works as it should do.
This isn't the first time something JavaScript related has led me on a merry dance when the symptoms thrown by the problem don't offer any reasonable hint to the solution, but there we have it.
Massive thanks to #redsquare, who's helped massively both here, but via twitter and the jQuery IRC channel, many thanks dude!
Try to add return false to your onchange function.
This will stop jQuery from bubbling the event.
You should make sure that $("#my_select","#context").change(function(){ is only called once.
I have tried this:
$(selector).unbind().on(eventname,function(){
$.ajax({
//ajax code here
});
});
It worked.