Executing javascript file after ajax-loaded - javascript

How to can i run the script asd.js on data returned from ajax?
HTML
<script type="text/javascript" src="asd.js"></script>
<div class="one">
<ul id="qwe"></ul>
</div>
JavaScript
$(document).ready(function () {
$('#search').click(function () {
$.ajax({
type: "POST",
url: 'abc.php',
data: {cid: cid},
success: function (data) {
$("#qwe").html(data);
}
});
});
});
The data returned from success ajax is:
<li> <a href="images3.jpg"><img src="images/a4.jpg"/>
<span>
<div class="title"><img src="Images/a5.jpg"/></div>
</span>
</a>
</li>

I assume asd.js adds some event hooks or something that you need to apply again to the HTML elements have come back from your AJAX call. So--wrap the contents of asd.js in a function, call that function once at the end of asd.js, then call that function again after you set $('#qwe').html(data).
If you are adding event hooks or working with the DOM in some other way, the initialization functions in asd.js should be called from the $(document).ready(...) function (otherwise you have potential race conditions going on here.)
If you can't alter asd.js, then things are going to be tougher. Work out which functions are important and call them. In the worst case scenario you could try dynamically removing and adding the script tag to cause it to re-run (but that's horrible).
Edit: ok, I wanted to illustrate this more clearly. I had assumed asd.js was simply a list of operations that executed immediately upon loading the script, e.g.
// asd.js: wiring up a bunch of events
document.getElementById('...').onclick = function() { doSomething(); };
If that was the case, you would wrap it in a function like this:
// asd.js: wiring up a bunch of events
function init()
{
document.getElementById('...').onclick = function() { doSomething(); };
}
init();
Then also call init() from your response handler:
success: function (data) {
$("#qwe").html(data);
init();
}
From your comments it seems that asd.js might look more like this:
// asd.js: wiring up a bunch of events
jQuery(function() {
document.getElementById('...').onclick = function() { doSomething(); };
});
If this is the case, you would do something like this:
// asd.js: wiring up a bunch of events
jQuery(function() { init(); });
function init()
{
document.getElementById('...').onclick = function() { doSomething(); };
}
The jQuery line can be shortened:
jQuery(init);

sorry, but i cant to do edit.
* this is what asd.js cotain (if is help): *
var yoxviewPath = getYoxviewPath();
var cssLink = top.document.createElement("link");
cssLink.setAttribute("rel", "Stylesheet");
cssLink.setAttribute("type", "text/css");
cssLink.setAttribute("href", yoxviewPath + "yoxview.css");
top.document.getElementsByTagName("head")[0].appendChild(cssLink);
function LoadScript(url)
{
document.write( '<scr' + 'ipt type="text/javascript" src="' + url + '"><\/scr' + 'ipt>' ) ;
}
var jQueryIsLoaded = typeof jQuery != "undefined";
if (!jQueryIsLoaded)
LoadScript("http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js");
LoadScript(yoxviewPath + "jquery.yoxview-2.2.min.js");
function getYoxviewPath()
{
var scripts = document.getElementsByTagName("script");
var regex = /(.*\/)yoxview-init/i;
for(var i=0; i<scripts.length; i++)
{
var currentScriptSrc = scripts[i].src;
if (currentScriptSrc.match(regex))
return currentScriptSrc.match(regex)[1];
}
return null;
}
// Remove the next line's comment to apply yoxview without knowing jQuery to all containers with class 'yoxview':
LoadScript(yoxviewPath + "yoxview-nojquery.js");

Related

synchronise code in javascript, wait for event to complete

I've got a problem near that one.
Somewhere I've got a binding over a file input :
var file;
function initLoadImg(){
$('#test').on('change', function() {
file = event.target.files;
// block 1
console.log("hello");
center.html('<span id="Tamb">25°C</span>');
over = true;
});
}
And i'm triggering it with another javascript function :
var over = false;
var center;
function loadImg(){
var elem = $('<div class="widget simpleimgchart center"><div class="matable"><div class="center"></div></div></div>');
center = elem.children().children();
$("#test").trigger('click');
passIfOver();
// block 2
console.log("bye");
return elem;
}
function passIfOver() {
if (over) {
return;
} else {
setTimeout(passIfOver(), 1000);
}
}
This way, I'm able to see the "hello" before the "bye" in the console.
However I don't really like this solution, (it's not clean) and user can have to wait up to 1s before getting any feedback.
Would there be another way to ensure that the return elem is executed after the end of the callback on click?
edit : My code doesn't even work, because of the setTimeout, I lose the restraint...
edit 2 : My goal is to execute the part code 1 before the part code 2. I don't want my function loadImg() to return before the code 1 has finished to execute.
I recommend you to look at PubSub pattern (http://davidwalsh.name/pubsub-javascript).
Just move the return inside the Trigger function:
var over = false;
function loadImg(){
var elem = $('<div class="widget simpleimgchart center"><div class="matable"><div class="center"></div></div></div>');
var center = elem.children().children();
$("#test").trigger('click', function(){
center.html('<span id="Tamb">25°C</span>');
return elem;
});
}
The second argument to .trigger is a callback function everything inside it will be executed After the trigger is completed.

Javascript - On('Click') - Error - Calling On Page Load

<script>
function playController(dataObj){
alert(dataObj);
}
function playHandlers(){
var dataObj = "stef";
$('.audiocontrol').on('click', playController(dataObj));
}
$(document).ready(playHandlers);
</script>
This bit of code is firing off on page load whether I click the object or not. Why?
What you want is:
function playController(dataObj){
alert(dataObj);
}
function playHandlers(){
var dataObj = "stef";
$('.audiocontrol').on('click', function() { playController(dataObj); } );
}
$(document).ready(playHandlers);
The way your code was written, it was calling playController when you were registering it in the .on call.
jsfiddle
You're invoking the function therefore passing the result of playController. You can do something like this.
function playHandlers(){
var dataObj = "stef";
$('.audiocontrol').on('click', function() {
playController(dataObj);
});
}
This will work:
(demo here)
function playController(dataObj) {
alert(dataObj);
}
function playHandlers() {
var dataObj = "stef";
$('.audiocontrol').on('click', function () {
playController(dataObj)
});
}
$(document).ready(playHandlers);
This will load your code when the page loaded and call the function playHandlers(). You were calling it directly because you forgot to add function(){} in the on/click call.

Calling Javascript Functions by name

If I have an element on the page like this ...
<span data-function="DoSomething">Click</span>
... and i put this in my page header ...
$(document).ready(function()
{
$('[data-function]').each(function()
{
var fName = $(this).attr('data-function');
$(this).click(fName);
});
});
... what goes in place of the comment produce the desired effect of executing the function called "DoSomething".
Note:
I no the code above wont work, my question is how to make this work (translate 'DoSomething' in to DoSomething();)
Any ideas guys?
The functions should be available. Try putting them in an Object, like this:
$(document).ready(function()
{
var fns = {
DoSomething: function() {/* ... */},
DoAnotherthing: function() {/* ... */}
};
$('[data-function]').each(function()
{
var fName = $(this).attr('data-function');
$(this).click(fns[fName]);
});
});
Here's a jsfiddle, demonstrating a way to keep everything local to one namespace and assigning handlers based on the data attribute of elements.
Try calling function with window object -
$(document).ready(function() {
$('[data-function]').each(function() {
var fName = $(this).attr('data-function');
if (typeof (window[fName]) === "function") {
$(this).click(window[fName]);
}
});
}
You can use something like
$(this).click(window[fName]);
Where window would be replaced by the appropriate expression if the function DoSomething is not defined in the global scope.
Maybe a little bit clean way:
http://jsfiddle.net/whsPG/
var myfuncs = {
alert : function() {
alert("An Alert");
},
changeName: function(obj) {
$(obj).text('Other Text');
}
};
$('[data-function]').on('click', function()
{
value = $(this).data('function');
if (myfuncs.hasOwnProperty(value)) {
myfuncs[value](this);
}
});
​

JavaScript generated HTML with onClick doesn't trigger function

The script below adds items to an array when you click the link, and generates a list of items as html output. You can see an example here: http://jsfiddle.net/dqFpr/
I am trying to create a function to delete items from the list. Not a difficult task with splice(), but somehow clicking the delete link doesn't trigger the test_function() function.
Can someone tell me what I am doing wrong, or show me another way of triggering the function? Your help is really appreciated ;-)
<script language="javascript">
$(document).ready(function() {
function test_function( number ) {
/* This function is not triggered, nothing works inside here!! */
}
});
var lines = [];
function update_list( lines ) {
var thecode = '';
for(var i = 0; i < lines.length; i++) {
thecode = thecode + lines[i] + ' <a onclick="javascript:test_function('+i+')" href="#">(delete)</a><br />';
}
$('div#display').html(thecode);
}
$('a#new').click(function() {
lines.push('another line');
update_list(lines);
});
</script>
<div id="display"></div>
Add a new line
Because in the text assigned to display's innerHTML, *test_function* is just plain text that is evaluated by the HTML parser. At that point, its scope is global, not within the IIFE passed to $(document).ready(). You can fix that by making the function global:
$(document).ready(function(){
window.test_function = function (number) {
// do stuff
}
....
});
or
var test_function;
$(document).ready(function(){
test_function = function (number) {
// do stuff
}
....
});
Or whatever method you like to get access to the function. But while it is declared inside an anonymous function's scope, you can only get access to it from a function that has a closure to the variables in that scope.

function executes too soon

I'm stuck with the following problem:
I want a function to create DIV tags to hold images and a second function to create the IMG tag and insert them in the DIVs created before. Works well with "alert messages". However without alerts, the second function runs before the first finished loading the DIV tags.
I think I need some kind of callback function worked in, but I have no clue how to do this.
Here is the code:
function imageLoader ()
{
for (i=1;i<=5;i++)
{
checkPath = 'images/pic'i+'.png';
$.ajax({
url: checkPath,
type:'HEAD',
success:
function() {
//create DIVs t hold images
$('.tools').append("<div class='tooling'></div>");
}
});
}
// after creating DIVs, call function to create <img> tags
appendix();
}
Thanks for helping out.
Regards,
frequent
Since, as Kos pointed out, you can't rely on the calls to complete in order, you'll have to get a little tricky to ensure that all your ajax calls have been completed. Try something like this:
function imageLoader() {
var ajaxCounter = 0;
for (i = 1; i <= 5; i++) {
checkPath = 'images/pic'
i + '.png';
$.ajax({
url: checkPath,
type: 'HEAD',
success: function() {
//create DIVs t hold images
$('.tools').append("<div class='tooling'></div>");
ajaxCounter++;
if (ajaxCounter == 5) {
// after creating DIVs, call function to create <img> tags
appendix();
}
}
});
}
}
That should check to make sure you have the required number of ajax successes before executing the appendix() call.
I can't tell exactly what you're asking, but it looks like maybe you need to move your appendix() call into the success callback. Remember that the success callback may not be executed before the appendix call in the code you presented.
function() {
//create DIVs t hold images
$('.tools').append("<div class='tooling'></div>");
appendix();
}
Of course, you might not want this called 5 times inside your for loop. Here's one way to make it call after the last success occurs, perhaps not the cleanest:
for (i=1;i<=5;i++)
{
if(i == 5) {
var succ = function() {
//create DIVs t hold images
$('.tools').append("<div class='tooling'></div>");
appendix();
};
} else {
var succ = function() {
//create DIVs t hold images
$('.tools').append("<div class='tooling'></div>");
};
}
checkPath = 'images/pic'i+'.png';
$.ajax({
url: checkPath,
type:'HEAD',
success: succ
});
}
a) Create a variable to count how many times the success function callback has executed and run appendix only when this count equals the number of your ajax calls,
b) Register the $.ajaxComplete callback.
The elegant way to do this is to use $.when:
function imageLoader(
$.when.apply($, $.map(new Array(5), function (e, i) {
var checkPath = 'images/pic' + (i + 1) +'.png',
d = $.Deferred();
$.ajax({
url: checkPath,
type:'HEAD',
success: function () {
d.resolve($('<div class="tooling">')
.append($('<img>').attr(src, checkPath)));
},
error: function () { d.resolve(null); }
});
return d.promise();
})
.then(function () {
$('.tools').append(Array.prototype.slice(arguments));
});
}
You could set async to false in $.ajax so it blocks execution.
Or, you could check i in the success callback, and if its 5, call appendix().
function imageLoader ()
{
for (i=1;i<=5;i++)
{
checkPath = 'images/pic'i+'.png';
$.ajax({
url: checkPath,
type:'HEAD',
success:
function() {
//create DIVs t hold images
$('.tools').append("<div class='tooling'></div>",
function(){
appendix();
});
}
});
}
}

Categories