I dynamically have to call a Javascript after a tag is rendered. Is it possible? I am doing some Ajax call which on return should repaint a DIV tag. And it is repainting successfully. I need to fire a Javascript method AFTER the DIV tag is repainted. How to do that?
Thanks
Short answer: directly it ain't possible (there is no "repaint" or "change" event on DIVs).
However using jQuery or other JS framework that supports custom events you could add an event listener on the div and fire an event in your AJAX call (i suppose it the onSuccess function; so as the last action inside fire custom event).
Even more simply you could just call the desired JavaScript method after you finish changing your DIV.
// I am doing some Ajax call
function ajax( url ) {
xmlHttp.onreadystatechange = function () {
// ...
};
// which on return should repaint a DIV tag.
div.modify();
// I need to fire a Javascript method AFTER the DIV tag is repainted.
javascriptMethod();
}
Or am I missing something here? :) Maybe you want to do the painting thing when the request is finished, but still i don't see any problem here.
Related
I will describe my problem, hopefully someone can provide a solution.
I am adding a GreaseMonkey script to an existing page, the page loads with ajax an element with an onclick:
onclick="getProperty('http:/...')"
I searched for a way to override their getProperty, which was hard on itself because I can't know what object will have this onclick before it arrives via ajax.
I can't bind my own click and unbind the previous one because there's no trigger for such a function when the content is dynamic. I tried adding my click and preventing the previous from being called by that doesn't work.
The selector I'm using looks like this:
a[onclick^='getProperty']
What I discovered was a method someone wrote for this exact problem, called waitForKeyElements. I hope someone here is already familiar with it.
What it does is check if an element matching a selector was added by ajax to the page, and if so runs a function.
This method let me workaround binding my function to override theirs:
waitForKeyElements("a[onclick^='getProperty']", updateToNewGetProperty);
function updateToNewGetProperty(ajaxLinks){
ajaxLinks.each(function(){
var oldOnclick = $(this).attr("onclick");
var UrlStartPos = oldOnclick.indexOf('\'') + 1;
var UrlEndPos = oldOnclick.indexOf('\'',UrlStartPos);
var Url = oldOnclick.substring(UrlStartPos,UrlEndPos);
$(this).attr("onclick", ""); // unbind
$(this).click(function() { // bind mine
myGetProperty(Url);
return false;
});
});
}
This works, it unbinds the previous javascript onclick and sets the jquery click.
However then I discovered that another segment of their code grabs the URL value that is inside the onclick, so I can't use the jquery click bind as that leaves the onclick empty.
I had to revert back to:
$(this).attr("onclick",$(this).attr("onclick").replace('getProperty', 'myGetProperty'));
This returns function not defined when clicking the link, I believe because the original page loads the ajax content before the greasemonkey is fully loaded. Triggering the waitForKeyElements before my function is registered.
Any help / advice would be greatly appreciated
So i have a page in my site that has a with class name 'mainContent' that automatically updates with new data every like 1 minute using AJAX .ajax(). Content in this requires some JavaScript for some functionalities. The problem now is that JavaScript does not work on the new data loaded into the DOM without whole page refresh. I have searched and found using .on() to bind the data to the DOM should work, like so:
$(document).on('click', '.mainContent',function(){
expand();
});
where expand is a JS function.
However, it only works fully on the new data but not on the data that had been added in the previous AJAX call...
You're almost there, it's just your logic. This is how this jQuery function works:
You set a container. This is the element that will hold the AJAX-crated items that you want to bind. The more specific, the better. Otherwise, you'll wire an event for your whole page, which is bad
The event. What are you listening to?
Who will fire the handler. A selector to form the phrase: when these guys inside this big guy fire this event, run this code.
Let's suppose that your mainContent gets filled with hyperlinks (I'm not sure because your question lacks on details):
$('.mainContent').on('click', 'a', function () {
//do your magic
//$(this) is the clicked link
});
This way, our phrase is: when links inside .mainContent are clicked, run this.
UPDATE
Based on the comments, I think that your problem may be on the expand function.
Let's give a try:
$('.mainContent').on('click', 'a', function () {
$(this).simpleexpand();
});
Have you try to apply your binding on the callback of the ajax function that load your new datas ?
Something like that :
$.ajax({
url: url...//Classic ajax call
}).done(function ( data ) {
//Apply your 'on' here
});
I have an html form that loads its contents through ajax and includes buttons that, when clicked, should execute a JavaScript function that is defined in the html page's script tag. SO: Button is loaded through ajax (works), but when button is clicked, it doesn't trigger the desired action and doesn't trigger a JavaScript error in Firebug. How does one get the onclick signal of a bunch of buttons loaded through ajax to bind to an already existing JavaScript function?
EDIT: I should have noted also that I am not using JQuery. I am willing to do so if it is the only way, but otherwise, I would prefer to use only native JavaScript.
EDIT2: My problem was a bit more involved, but as was stated in the chosen answer, you should be able to set the onclick event handler in the php script before sending the data through ajax. If you have a data-heavy response and want to reduce bandwidth, you might consider doing everything client-side, but I find it easier in most situations just to set the onclick attribute in the php script.
Your dynamically generated button could have an inline event bound to it. When generating the button, simply make sure it has an onclick="alreadyExistingFunc();" and the page will happily execute it.
Alternatively, when your AJAX data is finished writing itself into the document, find the new button(s) and bind the event to them:
function ajaxSuccess()
{
document.getElementById('newButtonIdHere').onClick = function() {
alreadyExistingFunc();
}
}
That should do the trick. Also note that if you ever "need" a small part of jQuery to do something (like selectors or event handling), you can almost always do it without loading the whole library.
Append/insert the HTML (retrieved AJAX response) to DOM and bind click event to it:
function alreadyExistingFunc() {
alert('button is clicked!');
}
var ajax_data ="<button id='my-button'>My Button</button>";
$('body').append(ajax_data).find('#my-button').on('click', function(e){
alreadyExistingFunc();
// some more code...
});
OR:
$('body').append(ajax_data).find('#my-button').on('click', alreadyExistingFunc);
You could also use a callback:
function getAjaxContent(callback) {
$.ajax({url: "url"}).done(function() {
callback(data);
});
}
getAjaxContent(function (data) {
//ajax content has been loaded, add the click event here
}
So, you have a page:
<html><head>
<script type="text/javascript" src="jquery.1.3.2.js"></script>
<script type="text/javascript">
$(function() {
var onajax = function(e) { alert($(e.target).text()); };
var onclick = function(e) { $(e.target).load('foobar'); };
$('#a,#b').ajaxStart(onajax).click(onclick);
});
</script></head><body>
<div id="a">foo</div>
<div id="b">bar</div>
</body></html>
Would you expect one alert or two when you clicked on 'foo'? I would expect just one, but i get two. Why does one event have multiple targets? This sure seems to violate the principle of least surprise. Am i missing something? Is there a way to distinguish, via the event object which div the load() call was made upon? That would sure be helpful...
EDIT: to clarify, the click stuff is just for the demo. having a non-generic ajaxStart handler is my goal. i want div#a to do one thing when it is the subject of an ajax event and div#b to do something different. so, fundamentally, i want to be able to tell which div the load() was called upon when i catch an ajax event. i'm beginning to think it's not possible. perhaps i should take this up with jquery-dev...
Ok, i went ahead and looked at the jQuery ajax and event code. jQuery only ever triggers ajax events globally (without a target element):
jQuery.event.trigger("ajaxStart");
No other information goes along. :(
So, when the trigger method gets such call, it looks through jQuery.cache and finds all elements that have a handler bound for that event type and jQuery.event.trigger again, but this time with that element as the target.
So, it's exactly as it appears in the demo. When one actual ajax event occurs, jQuery triggers a non-bubbling event for every element to which a handler for that event is bound.
So, i suppose i have to lobby them to send more info along with that "ajaxStart" trigger when a load() call happens.
Update: Ariel committed support for this recently. It should be in jQuery 1.4 (or whatever they decide to call the next version).
when you set ajaxStart, it's going to go off for both divs. so when you set each div to react to the ajaxStart event, every time ajax starts, they will both go off...
you should do something separate for each click handler and something generic for your ajaxStart event...
Because you have a selector with two elements, you're creating two ajaxStart handlers. ajaxStart is a global event, so as soon as you fire any ajax event, the onajax function is going to be called twice. So yes, you'd get two popups.
I've got a lightbox textbox that is displayed using an AJAX call from an ASP.NET UpdatePanel. When the lightbox is displayed, I use the focus() method of a textbox that is in the lightbox to bring focus to the textbox right away.
When in Firefox, the text box gains focus with no problem. In IE, the text box does not gain focus unless I use
setTimeout(function(){txtBx.focus()}, 500);
to make the focus method fire slightly later, after the DOM element has been loaded I'm assuming.
The problem is, immediately above that line, I'm already checking to see if the element is null/undefined, so the object already should exist if it hits that line, it just won't allow itself to gain focus right away for some reason.
Obviously setting a timer to "fix" this problem isn't the best or most elegant way to solve this. I'd like to be able to do something like the following:
var txtBx = document.getElementById('txtBx');
if (txtPassword != null) {
txtPassword.focus();
while (txtPassword.focus === false) {
txtPassword.focus();
}
}
Is there any way to tell that a text box has focus so I could do something like above?
Or am I looking at this the wrong way?
Edit
To clarify, I'm not calling the code on page load. The script is at the top of the page, however it is inside of a function that is called when ASP.NET's Asynchronous postback is complete, not when the page loads.
Because this is displayed after an Ajax update, the DOM should already be loaded, so I'm assuming that jQuery's $(document).ready() event won't be helpful here.
Try putting the javascript that sets focus at the end of the page instead of the beginning or having it fire after the page loaded event. That will help ensure that the DOM is completely loaded before setting focus.
I've used FastInit for this. JQuery $(document).ready() would also work.
You can try this:
Use the endRequest event of the PageRequestManager. That event fires once an Ajax update has finished.
Focus the textbox in the event handler
Here is some sample code:
<script type="text/javascript">
function onRequestEnd()
{
var txtBx = $get('txtBx');
txtBx.focus();
}
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onRequestEnd);
</script>
To focus the textbox initially you can use the pageLoad function (shortcut to the load event of the Application client-side object):
<script type="text/javascript">
function pageLoad()
{
var txtBx = $get('txtBx');
txtBx.focus();
}
</script>
you could try something like this [IE Specific]. (untested)
theAjaxCreatedElement.onreadystatechange = function() {
if ( this.readyState != "complete" )
return;
this.focus();
};
Another way might be to change the background color of the element with onfocus, then retrieve it with js check if it is what it should be, if not: refocus the element.
It seems that IE does not update the DOM until after the script has finished running. Thus, a loop testing for focus will not allow the DOM to update. Using setTimeout is probably the only working solution.
Your example with .focus() is a well known example, see e.g. this answer.
Have you tried adding the autofocus="autofocus" attribute to the textbox element you are calling via Ajax?
Normally, when I need certain additional JavaScript functionality to run on dynamic content, I'll simply add that JavaScript to the content being called as well.
That JavaScript will also execute after it's added to the DOM. I don't see a point in writing JavaScript to your parent file and then "listening" for changes to the DOM. Like you mentioned, setTimeout() is more of a hack than anything else for something like this :)
There are several things in IE, that does the trick:
If focusing element has different z-index - you can quickly set z-index to that of currently focused element (possibly setting hidden attribute), set focus, and then set it back to original z-index.
Try to blur() currently focused element.
If element is 'shimmed' - focus the 'shim' element.