How do I dynamically apply scripts and css rules to an iframe? - javascript

I have an iframe that I dynamically set the source of. Upon retrieving the content to be displayed in this iframe, I need to be able to do a few modifications to its DOM, apply a few CSS rules, and then display it.
I tried two things (Assume the id of the iframe is content)
$("#content").attr("src", urlToFetch);
$("#content").load(function() { doSomething(); });
$("#content").attr("src", urlToFetch);
$("#content").ready(function() { doSomething(); });
The first one displays the page, then applies the changes and re-renders it. The second one applies the changes, displays the changed page, but re-renders to the original page.
Any idea how I can make it to behave the way I want?

You could try using the jQuery frameReady plugin.
http://code.google.com/p/chamilo/source/browse/main/inc/lib/javascript/jquery.frameready.js?spec=svn.classic.39a2ef8dd8332b3680a10b24c922d8676c991aeb&repo=classic&r=39a2ef8dd8332b3680a10b24c922d8676c991aeb
http://huuah.com/jquery-and-iframe-manipulation/

Related

Duplicating IDs Jquery

So, I have done some research, and it's pretty clear that id should be unique in the DOM. This is my issue, and I am curious what the best solution to it is:
I am using jQueryUI tabs as well as a custom menu and ajax to load specific pages into a content pane without re-rendering the browser. From some of these sub pages, a user can open a popup (done with a jQueryUI dialog) to edit customer information. Because these load a server side page, in each place that this form would be generated, it uses the same ids.
I have found that there are a number of ways to close a dialog without removing it from the DOM. This causes confusion later when it, or another form is opened elsewhere, and now there are conflicting ids present in the DOM. I am working on tracking down all the ways to close a dialog, and making sure to replace them with .dailog("destroy").remove() to make sure that they are erased from the DOM, but I want to be sure the solution here is fool proof in the event that someone one gets left on the page.
My two immediate thoughts:
1.) Generate a random string to append to each form element's id when the form is rendered, fully preserving uniqueness of the id.
2.) Use more specified selectors when getting the form data, i.e. scoping it to the popup that was created, the page that it was created from, and then the tab that it is under, and not worrying as much about id uniqueness.
The first feels ugly, and in theory you COULD randomly duplicate the string and still run into an issue. The later just feels bulky and ugly to me. Is there an option I am missing? What is best practice when it comes to dealing with IDs that can be duplicated in this way?
Thanks,
Eric
You may use classes if you need "similar" objects. Id's purpose is to identify object uniquely.
By the way, classes are widely used, for example, in Bootstrap.
UPDATE: I think your "second" approach is bad, as you eventually can change the layout, but, in this way, you should track every change, and remember WHERE to change your selectors (possibly, it will be multiple places).
Before inserting the new element into the list, you could check if there is already an element existing on the page with that id. If it does exist than delete it.
Like:
if($("#"+your_id).length!==0)
$("#"+your_id).remove();
//insert the new element
But if you need that element as well, i would suggest that you use classes to group elements used for same purposes.
Here is what you can do to distinguish between the different dialogs when you try to close them:
1) Change each dialog id into a class, so that your dialogs can share the same class. Using the same id is not recommended.
2) You can create a click listener for the button that closes the correct dialog by using the event callback parameter. See the working snippet below.
var closeButtons, i, closeButtonsLen;
closeButtons = document.getElementsByClassName('close');
for (i = 0, closeButtonsLen = closeButtons.length; i < closeButtonsLen; i += 1) {
closeButtons[i].addEventListener('click', function (e) {
e.target.parentNode.setAttribute('hidden', true); // if you want to hide the dialog
});
}
<div class="dialog"><button class="close">first x</button></div>
<div class="dialog"><button class="close">second x</button></div>
<div class="dialog"><button class="close">third x</button></div>
You can replace e.target.parentNode.setAttribute('hidden', true); with whatever you need to do. e.target.parentNode gets the dialog element.

JQuery fails to find elements in iFrame after initial load

I have page specific html loading into an iFrame which contains objects that I'm trying to reference with jquery. When the page loads initially the elements are found as expected, but if I go to a new page and return or refresh the page the elements are no longer found consistently (fails more often then not) until I clear the cache and reload the page.
I've tried different combinations of querySelectorAll and getElementsByClassName but they only work consistently that first time in. It would seem like a race condition but why would it work the first time?
Does this problem sound familiar to anyone?
It did turn out to be a race condition where the dynamic elements were not yet available for reference. In my case the iFrame element was created using ExtJS so it needed this additional listener so I could take action after the load (putting this delay in afterrender came from another post that I'll need to find and give credit to);
afterrender: function (cmp) {
var element = cmp.getEl();
element.on('load', function () {
renderer.onIFrameReady();
});
}

using jQuery to change, only the elements that were loaded via ajax

For each checkbox on the web page, I replace it with a slider that I borrowed from jsfiddle.net/gnQUe/170/
This is done by going through the elements when the document is loaded.
Now the problem is that when more content is loaded via ajax, the new checkboxes are not transformed.
To solve the problem, I used AjaxComplete event to go through all the elements again and replace the checkboxes with sliders.
Now the problem happens that elements that were already replaced, get two sliders. To avoid that I check if the checkbox is hidden and next element is div of class "slider-frame", then don't process the re-process the element.
But I have a lot of other such controls as well, and I am presume I am not the only one that has this problem. Is there another easy way around it?
There exists jQuery live/on( http://api.jquery.com/on/ ) event but it requires an event as an argument? whereas I would like to change the look of my controls when they are rendered.
Another example of the same problem is to extend some controls that are loaded via ajax with jQuerys autocomplete plugin.
Is there a better way to accomplish this other than changing some attributes on the element.
To summarize, on document load I would like to process every element in DOM, but when more elements are loaded via ajax then I want to change only the new elements.
I would assume that when the element's are transformed into a slider, a class is added to them. So just add a not clause.
$(".MySelector").not(".SomeClassThatSliderAddsToElement").slider({});
So in the case of your code do something like this
$('.slider-button').not(".sliderloaded").addClass("sliderloaded").toggle(function(){
$(this).addClass('on').html('YES');
$('#slider').val(true);
},function(){
$(this).removeClass('on').html('NO');
$('#slider').val(false);
});
Since you said you do not want to add anything else, how about you change the toggle function to click.
$(document).on("click", ".slider-button", function(){
var elem = $(this);
elem.toggleClass("on");
var state = elem.hasClass("on");
elem.text(state?"YES":"NO");
elem.parent().next().val(state);
});
Running fiddle: http://jsfiddle.net/d9uFs/

How to make style of an element dependent on another element's style

I need to set some special style for an element if some other element is visible (which is indicated by a special css class and can change dynamically). I need to do this because the page rendering and it's behavior is fully controlled by some framework's code and I don't want to change it. I can put any content anywhere in the body of the page. Is there a non-hacking way to do it?
My only idea was to use some plug-in like "watch" for jquery, but it's very ugly.
try using the properychange/attributemodified event
$("object-in-question").bind("DOMAttrModified propertychange", function(e) {
if($(this).is(":visible")).... etc
});
http://jsbin.com/abece4

How can I apply prototype's toggle to content loaded via JSON, IE problem only

I use PHP and javascript via prototype.
i have a threaded comments page that on open
by default via javascript call to a PHP file data returned via JSON, only parent comments are retrieved in the db. (in short only parent comments are fetched from db and displayed)
then the parents are loaded and formatted to be shown on the page with a link to get and display its child comments, link example:
<span id="moreparent8351" onclick="insertChildDiv('parent8351')">1 Replies and more</span>
the span link above calls the javascript function "insertChildDiv()" that basically gets comments whose parent_id=parent8351, also using a PHP file that returns data via JSON to the javascript that dynamically inserts this child comments nested under its parent comment.
then the span link above using prototype transforms into:
<span id="moreparent8351" onclick="$('childparent8351').toggle()">1 Replies and more</span>
now here is the problem, this inserted content inside this div with id=childparent8351 wont respond to the hide/show toggle ONLY in IE v6,v7 and v8. other browsers work fine.
it looks like IE cannot apply the hide/show toggle to a dynamically inserted content.
I tried hardcoding the inserted content that i see in fogbugz to the page and testing it again on IE, guess what? toggle works!
I dont want to fetch all the comments both parent and child and then hide the child comments, that is a waste of resources on something that we are not sure is important or to be read by the users.
Is there a workaround? if there is none, then i hope this post will help others on their design stage for something similar.
Element.toggle() should work fine with dynamically generated content. Your problem most likely lies within the method you use to generate this content.
You stated:
then the span link above using
prototype transforms into:
<span id="moreparent8351" onclick="$('childparent8351').toggle()">1 Replies and more</span>
How exactly are you changing the onclick attribute of the span element?
First of all, I definately would not recommend changing an onclick event on-the-fly. It is probably better to use one function that checks the current state of what you are trying to do and executes the appropriate code.
Be sure not to "transform" your span element, including the onclick attribute using innerHTML. Chances are the DOM is still trying to reference a function that you have just removed. If updating your onclick attribute at all, do it like this:
var element = $('moreparent8351');
// this automatically removes previous onclick handlers set in this manner
element.onclick = function() { // do stuff };
...or, when you want to it the Prototype way:
var element = $('moreparent8351');
// OPTIONAL: remove previous handler, if set
element.stopObserving('click', my_cool_function());
// attach new handler
element.observe('click', function() { // do stuff });

Categories