How to access dynamically-generated page content via jQuery? - javascript

I have a SharePoint web part page with a list view that is grouped and defaulted to "collapsed" (much like a basic toggle). SharePoint generates its own JavaScript to handle the initial click action, which then expands the page area and dynamically writes new content to that area. The problem is that jQuery cannot access the new content immediately following the click (it needs to finish loading). My thoughts are to add a 2nd jQuery click function to the toggle link and somehow wait for the new content to be added before anything else happens, but I'm not sure how to determine when the dynamic content finishes loading...
//bind a 2nd additional onclick handler via jquery to these items
$('td.ms-gb').children('a').click(function()
{
//give the clicked item a border for visual identification
$(this).css("border","1px solid cyan");
//delay this function until the sharepoint onclick handler finishes loading new content
$('TD.ms-vb-icon').children('a').each(function(index)
{
//give each item a border for visual identification
$(this).css("border","1px solid red");
//perform more jquery on each item
}
);
}
);

A common technique to address this kind of issues is to use
setTimeout(function, timeoutInMs)
and try to find new content in function, if fail restart a timeout until you find the content
Here's a jsFiddle to illustrate:
http://jsfiddle.net/Dhww2/

The only thing I can think of is to set another click handler that registers with $.ajaxSuccess() http://api.jquery.com/ajaxSuccess/ and responds after the first AJAX request (after the click) finishes
It's hackish, but if the code that is fetching the dynamic content doesn't have a callback, there aren't many options.

What are you going to do with loaded contnent? Just style and catch another clicks?
In such case use stylesheets for custom styling and jQuery's live function to catch (click) events of further loaded elements.
Update for comment
$('TD.ms-vb-icon a').live('click', function(ev) {
$(this).attr('name','value');
}
May not work if your click tracking code registers earlier. If so try with mouseover event.

Related

Ruby on Rails - JavaScript in dynamically generated partials

I know putting JavaScript in partials is a bad idea because the page will have to load up a new script every time a new partial is loaded. I am aware of and have read this question, but its answer did not work for me (putting the script into app/javascripts/application.js). I think it is because I am working with partials that are dynamically generated onto the page. I think the dynamically generated partial does not react to the script loaded up on the initial page.
For example, I have a "Rule" div with a select input that has a script to do something when the select input is changed. This works for every Rule div that is generated on page load. But then there is also a "+" or "ADD" button which will dynamically generate more Rule divs which do not respond to the script, unless that script is in the partial.
Is there a good way to keep the script out of the partial when the partial is dynamically generated?
JQuery sets listeners on page load (i.e. $(selector).on(etc.)), so it doesn't listen for events on dynamically added elements. There is a way around it, though. You need to use what is called a delegate.
$(document).ready( function() {
$('body').on('change', 'input.selector', function(e) {
// do something
});
});
I'm not sure what your event (here I put change) or selector for the select you are using (here I put input.selector), but if you replace those with the appropriate information, it should work even with dynamically added elements.
You can use JQuery to execute the code only after the document has loaded onto the DOM:
$( document ).ready(function() {
//Call your functions here
});
That way, your JS will have access to whatever is on the page, because you are ensuring that it is fully loaded.
If your divs are not in place on document ready, you can use event delegation, as suggested by ptd. Basically what this means is that you install a handler on a parent div (which will be present on document ready) which says, "hey, when you click on this dynamic div inside of me, call this function".
$('div#master').on('click', 'div.dynamic', function(event) {
console.log("action here")
var $dynamicDiv = $(event.currentTarget) //The current Target is the thing you clicked on, not the parent.
});
If you are adding elements to the DOM using AJAX calls, but want to keep your JavaScript in your assets folder only, here's a quick and clean way to accomplish this.
// /app/assets/javascript/foo.js
// On intial page load
$(document).ready(function() {
yourJavaScriptForPartials();
});
// After a subdomain field is loaded via AJAX
$(document).ajaxComplete(function() {
yourJavaScriptForPartials();
});
function yourJavaScriptForPartials() {
// Insert your javascript here.
};
Now, any JavaScript you put in the yourJavaScriptForPartials() function will be available both to the initially loaded DOM, and to any DOM elements added via AJAX. For reference, here is the JQuery page for the ajaxComplete event listener.

Timeout for javascript execution

jQuery(document).click(function () {
jQuery('.close-news').css('display', function(){return jQuery('#colorbox').css('display');});
});
I have this script, which make my link appear\dissappear depends on state of #colorbox block. But somewhy link appear\dissappear not immediatelly, but after 2 click.
Basically i have to click one more time in random area to make my script work
I guess its because my html code isnt update fast enought to make . So how do i add some timeout for this script?
It seems you are using Colorbox in Drupal.
There can be a callback function that gets executed once the Colorbox is shown up.
After Debugging your site, seems that there is a cbox_complete custom event firing up.
If thats the case, you can attach a function to this event.
In the function, you can toggle the display of your .close-news li element, similar to what you are doing on document click in the question

How to trigger (possibly)overridden event?

I created jQuery UI Dialog and after the dialog is displayed, wherever a user clicks, the dialog is closed. I achieved this by adding click event to the body tag.
$("body").click(function() {
$("#myDialog").dialog("close").dialog("destroy");
});
It works fine except inside of 3rd party Grid API I'm using and found out this Grid API source code, it defined onclick event like below:
this.obj.onclick = function(e){
console.log("grid API clicked");
this.grid._doClick(e||window.event);
if (this.grid._sclE) {
this.grid.editCell(e||window.event);
}
(e||event).cancelBubble=true;
};
When I clicked inside the Grid, the log msg "grid API clicked" is shown in my firebug but my body click event is not triggered so I think the event is not bubbling up to the body click event as specified in the line (e||event).cancelBubble=true;
If I set this to false, the click on the Grid does not work and not wanting to change code in the 3rd party API.
So, it there any workaround to make body click work?
Maybe simplistic and not the best way to do it, but if you're happy to edit the Grid API source then add this to it...
$("body").click();
It will trigger the click event defined on the body element. If that doesn't work then there's something else going on.

script not working on Ajax-loaded Content

I have a jquery powered voting system, and the items on other pages are loaded via ajax, but on ajax-loaded contents the jquery voting needs the page to be refreshed for the vote to be processed.
http://ohmygosh.vr.lt/
I think the problem is within the actions in this file (?) But i'm not really sure. I don't have any code to start since I don't even know where to start. How do I fix this Problem?
Seems that you are using a SmartAjax to load the page content. What SmartAjax does is that it changes the page url (using pushState or hash), loads data and REPLACES the content of #posts div with the loaded content.
The problem is that you are listening click events from DOM elements which are later deleted and replaced with new DOM elements. Thus, the click events from the ajax loaded content are not listened. live() doesn't help in this case.
To fix this, you have at least these two options:
1) Use jQuery's delegate() to attach the handler and use #posts div as the root element, since it remains after the new content is loaded.
Something like this should work:
$('#posts').delegate(':input', 'click', function() {
var value = $(this).val();
alert('You have clicked thumbs up/down, value: ' + value);
return false;
});
2) Add click listener to the loaded items after data loading is completed.
Notice: Starting jQuery 1.7 you should use on() instead of delegate()

jQuery .load() not working when called from loaded content

My primary navigation [Our Clients, Our Culture, Our People] uses .load() to pull the content and display it in a div on the same page w/o refresh.
I would like for links within the new content to do the same, just display whatever content is being referenced in this same div. However, when they're clicked it goes directly to the new page.
$(function(){
$("a.aboutContent").click(function (e) {
e.preventDefault();
$("#aboutContainer").load($(this).attr("href"));
});
});
So, when Our People is clicked, it pulls ourpeople.htm in to the #aboutContainer div. If you click on a link inside of ourpeople.htm, I'd simply like for that content to display in the same #aboutContainer div. I'm assigning the aboutContent class to links in the subpages as well, but it still isn't working.
You will need to use .live() to listen to clicks from everything, including new DOM elements:
$(function(){
$("a.aboutContent").live('click', function (e) {
e.preventDefault();
$("#aboutContainer").load($(this).attr("href"));
});
});
The reason for doing this is, jQuery code runs when the page is ready - it will attach a click handler to every dom anchor with the class aboutContent - when you load new content, those elements where not there when the page was ready, so never have a click handler attached to them.
Using .live() takes care of that for you. Alternatively, you could place your code in a function, and run that function when the new content is loaded, that way when it runs, it will attach a click handler and the DOM elements will be there, trouble with this is, you would have to mark elements as already having a click handler, or you would end up adding x number of click handlers to some elements.
Probably you can return false from click handler to prevent browser to exeucte HREF on its own.
Like,
$(function(){
$("a.aboutContent").click(function (e) {
e.preventDefault();
$("#aboutContainer").load($(this).attr("href"));
return false;
});
});
Otherwise I would suggest to call some javascript function on href using href="javascript:clickhandler('')"

Categories