Using jQuery to update content within an iFrame live & on-the-fly...? - javascript

I'm using an iframe to display a website next to a form. I want to update certain content within that iframe live based upon the value of the various input fields.
This is what I'm trying to do (working outside of an iframe): http://jsfiddle.net/YkKUS/
The textarea will be outside of the iframe and the content that'll be updated will be inside the iframe.
Here is my code adapted to work with my iframe:
$('.liveDemoFrame').load( function(){ // load the iframe
$(this.contentDocument).find('h1').html($('textarea').val());
$('textarea').keyup(function() {
$(this.contentDocument).find('h1').html($(this).val()); // this line is screwing something up?!?
});
});
The 5th line is causing me some problems. The iframe DOES actually update successfully with the content of my textarea but only when I refresh the page. It's not updating it live & on-the-fly which is the only reason I'm doing this!
Thanks!

I did this in the parent page and it seemed to work:
$(document).ready(function(){
$('#textarea').bind('keyup', function() {
var iframedoc = $('#iframe').get(0).contentDocument;
$(iframedoc).find('h1').html($(this).val());
});
});

There might be some kinks with jQuery, or you might be doing it incorrectly. Either way, it could be easiest to actually run half of your code within the iframe; then you can call iframe.contentWindow.getHtml(), or iframe.contentWindow.setHtml(), if you can. Also IIRC, the contentDocument was not standard either; some browsers require contentWindow.document or similar.
However, the main culprit would be this:
$('.liveDemoFrame').load( function(){
$(this.contentDocument).find('h1').html($('textarea').val());
$('textarea').keyup(function() {
// here this refers to textarea dom element, not iframe
$(this.contentDocument).find('h1').html($(this).val());
});
});
Fix could be like
$('.liveDemoFrame').load( function(){
var iframeDocument = $(this.contentDocument);
iframeDocument.find('h1').html($('textarea').val());
$('textarea').keyup(function() {
// here this refers to textarea dom element, not iframe
iframeDocument.find('h1').html($(this).val());
});
});

You can't do stuff in the iframe from outside of it, that would be a massive security hole

Related

editing a Div that is around an iframe via jquery from within said iframe

I'm sure this sounds a little odd, but here's the background...
We utilize a company that loads their chat program, so we can support our customers, into our page. This is done via javascript and jquery, and creates a structure like this:
<div id="myid" style="...; right: 0px;..."><div><iframe></iframe></div></div>
There's a WHOLE lot more to that, but those are the important parts. Now the tool allows us to put custom scripting, which will be placed in the iframe. My goal is to just remove the "right: 0px", which I have done via the below code, but I don't want to put that code on every page that this tool integrates with. I would like to load it into the tool, and have it run when the iframe and divs are created.
working code on parent:
$(document).ready(function() {
function checkPos() {
$('#myId').each(function() {
var oldstyle = $('#myId').attr('style');
var newstyle = oldstyle.replace(' right: 0px;','');
$('#myId').attr('style', newstyle);
});
setTimeout(checkPos, 100);
};
$(document).ready(function() {
setTimeout(checkPos, 100);
});
});
Once placed in the code include method they provide, I have trouble having it wait until the div tag actually has the "right: 0px;" in its style tag. the only thing I need to run is the three lines in the $('#myId').each(function()
Basically, I need help with having the script in the iframe target the div that the iframe is nested in.
Assuming that whatever tool your using actually lets you pass in a custom script to the content rendered in the iframe (seems fishy to me), a better way of modifying the style in jquery is to use the css function:
$('#myId').css('right', '0px');
Notice I removed the $.each function as well. You are targeting an element with an id, so there isn't any need to iterate.
Edit:
Anyways, back to the problem of delaying execution to when the target, #myId, actually exists. If they are really injecting your javascript into their page (again, seems fishy), then attaching the above code to the $(document).ready() event should do the trick, as long as this listener is attached to their document.
If all else fails, try to use the waitUntilExists plugin, here:
Source:
https://gist.github.com/buu700/4200601
Relevant question:
How to wait until an element exists?

Check if iframe is loaded inside $(document).ready

I want to check if iframe is loaded with the following code:
$(document).ready(function() {
jQuery('#iframeID').ready(somefunction);
}
It seems that 'somefunction' is called before iframe is loaded (the iframe is empty - just empty html-head-body).
Any idea why this happens?
Thank you.
Try this instead.
$('#iframeID').load(function() {
callback(this);
});
While dealing with iFrames, it is good enough to use load() event instead of $(document).ready() event.
This is because you're checking if the iFrame is ready, not the document inside.
$(document.getElementById('myframe').contentWindow.document).ready(someFunction);
should do the trick.
I have tried:
$("#frameName").ready(function() {
// Write you frame on load javascript code here
} );
and it did not work for me.
this did:
$("#frameName").load( function() {
//code goes here
} );
Even though the event does not fire as quickly - it waits until images and css have loaded also.

How to get Anchor Links to work in Jquery Mobile?

Jquery Mobile has decided to treat anchor links as page requests of sort. However, this isn't good if you have a load of blog posts which have anchor links to the same page (ie href="#specs").
Is there a way to disable jquery mobile's anchor link usage on a specific page which I know I won't be using it on so I can use anchor links as they were intended, to drop down to a part of the page?
I only need a solution for anchor links on the same page (ie: href="#specs").
thanks
You could try adding a data-ajax="false" on the anchor tag.
Linking without Ajax
Links that point to other domains or that have rel="external",
data-ajax="false" or target attributes will not be loaded with Ajax.
Instead, these links will cause a full page refresh with no animated
transition. Both attributes (rel="external" and data-ajax="false")
have the same effect, but a different semantic meaning: rel="external"
should be used when linking to another site or domain, while
data-ajax="false" is useful for simply opting a page within your
domain from being loaded via Ajax. Because of security restrictions,
the framework always opts links to external domains out of the Ajax
behavior.
Reference - http://jquerymobile.com/demos/1.0.1/docs/pages/page-links.html
If you are like me, converting an existing site and you don't want to go through every page right now. You can add one line of code to your header and all of your header and all of your existing internal anchor links will get the data-ajax="false" tag added.
Of course, this assumes you are including your own javascript file up in the header already. If you are not you would have to touch every page anyway. But I have a single javascript file that is included in every page already so I added this line...
$("a").each(function () { if(this.href.indexOf("#")>=0) $(this).attr("data-ajax",false); });
This goes in your $(document).ready() block. If you don't have that block yet, here is the entire block.
$(document).ready(function() {
$("a").each(function () { if(this.href.indexOf("#")>=0) $(this).attr("data-ajax",false); });
});
Hope this helps. It is the same solution user700284 offers but in an automated way.
You can add the following code to the end of your page:
<script type="text/javascript">
$('a.native-anchor').bind('click', function(ev) {
var target = $( $(this).attr('href') ).get(0).offsetTop;
$.mobile.silentScroll(target);
return false;
});
</script>
And add the class "native-anchor" to your anchor links.
It is not a total sollution, because the back button of your browser will move you to the previous page and not to the position of the link, but it is better than the links not working at all.
I found this sollution here: jQuery Mobile Anchor Linking
$(document).bind("mobileinit", function () {
$.mobile.ajaxEnabled = false;
});
First you have to place this code into a custom.js file
$(document).bind('mobileinit', function () {
$.mobile.loader.prototype.options.disabled = true;
$.mobile.ajaxEnabled = false;
$.mobile.linkBindingEnabled = false;
$.mobile.loadingMessage = false;
});
Then add this file into your webpage before the jquery mobile js is loaded. becuase 'mobilinit' event is triggered immediately
Thank you
this solution worked for me
<script>
$(document).ready(function() {
$("a").each(function() {
if (this.href.indexOf("index.php") >= 0) $(this).attr("data-ajax", false);
});
});
</script>
I replaced # with index.php which is my document root.
But, it doesn't work for form button i.e input type="submit"
// On page load on mobiles only, look for the specific a tag you want to take control over,
// alternatively you can still target all 'a' tags
$('a[href*="#component"]').each(function () {
// then set data-ajax to false,
$(this).attr("data-ajax", false);
// at this point you can add the class to your target a tags.
// You can do it elsewhere but because for this example my
// 'a' tags are automatically generated so I just add the class here
$(this).addClass('in-pagelink');
// then target the class and bind to a click event
$('a.in-pagelink').bind('click', function (ev) {
// here I redirect the page with window.location.assign
// as opposed to window.location.href. I find that it works better
window.location.assign(this.href);
// then I close my navigation menu
closeAll();
});
});

Define an event on iFrame element with jQuery

I try to define a live event on img tags store on a iFrame. For example, I would like obtain a simple javascript alert box when I click a image on my iFrame.
Do you know how i can define the events for the iFrame, because I would like to put a thing like $('img').live("click",function().... but only for the elements on iFrame.
Please note: img tags are dynamically added on my iFrame after page load.
Thanks for your help.
Nicolas
You can do it if you
make sure that the page in the iframe has its own copy of jQuery loaded [ed.: only really necessary for jQuery operations internal to the frame's page itself]
from the outer document, work into the iframe document like this:
$('#iframeId').contents().find('img') // ...
The other solutions here are largely myopic, as what you are trying to do is fairly complicated in the underlying javascript.
I'd suggest using jquery context as well - and I'd strongly suggest waiting for the iframe to totally load or else none of the previous suggestions could work anyway...
$("#frame").ready(function () { //wait for the frame to load
$('img', frames['frame'].document).bind("click",function(){
alert('I clicked this img!');
});
});
This should generally work UNLESS you update the iframe or refresh it, in which case all the event bindings will fail... and worse yet the .live events don't appear to be supported in iframes - at least not for me.
$("iframe").contents().find("img")
This will target images within the iFrame. But be aware that jquery will only traverse the iFrame if it is not a violation of the browser's (or jquery's) cross-site policy.
That means if the iframe is google.com, you can't touch the inner DOM.
jQuery.bind() won't work with external documents. At least in jQuery 1.6.2.
However you can bind to DOM events:
$("iframe").contents().find("img").onclick = function() { // do your staff here };
If you do not have full list of images at the moment, you can use events propogation:
$("iframe").contents().find("body").onclick = function() { // do your staff here };
It will work event with custom events:
$("iframe").contents().find("body").onmyevent = function() { // do your staff here };
One more thing to remember... frame content is loaded asynchronously. So bind your handlers AFTER your iframe content is loaded:
var $iframe = $("iframe");
$iframe.bind("load", null, funcion(e) {
$iframe.contents().find("body").onclick = function() { // do your staff here };
});
For more complicated cases handle your images clicks inside iframe, and trigger your custom events that you can later handle on the body level. Especially if you have totally dynamic content and want to bind to 'live' events inside iframe.
you can fire event innner like this:
parent.$('#dlg').trigger('onTitle');
then hold event like this:
$('#dlg').bind('onTitle', function(){ alert(); });
this worked for me. NB: make sure you have referenced jquery library on the iframe page as well.
$(document).ready(function(){
$('#iframeid').load(function(){ //make sure that all elements finish loading
$('#iframeid').contents().find('img').live({
click: function(){
alert('clicked img');
}
});
});
});

Calling Javascript in a page after it's been loaded by jQuery GET

Imagine a normal page calling javscript in head. The trouble is some of the content isnt loaded untill i click on a link. Subsequently when this link loads the content it wont work. This is because i guess the javascript has already been run and therefor doesnt attach itself to those elements called later on. There is only standard html being called.
So for example this is the code which calls my external html.
$.get('content.inc.php', {id:id}, function(data){
$('#feature').children().fadeTo('fast', 0).parent().slideUp('slow', function(){
$(this).html(data).slideDown('slow');
});
});
If the html i was calling for example and H1 tag was already in the page the cufon would work. However because i am loading the content via the above method H1 tags will not be changed with my chosen font.This is only an example. The same will apply for any javascript.
I was wonering whether there is a way around this without calling the the javascript as well the html when its received from the above function
If you want to attach events to elements on the page that are dynamically created take a look at the "live" keyword.
$('H1').live("click", function() { alert('it works!'); });
Hope this is what you were looking for.
Does Cufon.refresh() do what you want?
As you said Cufon was just an example, I'd also suggest a more general:
$.get(url, options, function(html, status) {
var dom = $(html);
// call your function to manipulate the new elements and attach
// event handlers etc:
enhance(dom);
// insert DOM into page and animate:
dom.hide();
$target_element.append(dom); // <-- append/prepend/replace whatever.
dom.show(); // <-- replace with custom animation
});
You can attach event handlers to the data that you get via the get() inside of the callback function. For example
$.get('content.inc.php', {id:id}, function(data){
$('#feature').children().fadeTo('fast', 0).parent().slideUp('slow', function(){
$(this).html(data).find('a').click(function(e) {
// specify an event handler for <a> elements in returned data
}).end().slideDown('slow');
});
});
live() may also be an option for you, depending on what events you want to bind to (since live() uses event delegation, not all events are supported).
Andy try this. It will call the Cufon code after each AJAX request is complete and before the html is actually added to the page.
$.get('content.inc.php', {id:id}, function(data){
$('#feature').children().fadeTo('fast', 0).parent().slideUp('slow', function(){
$(this).html(data);
Cufon.replace('h1');
$(this).slideDown('slow');
});
});
JavaScript is not executed because of a security reason OR beccause jQuery is just setting this element's innerHTML to some text (which is not interpreted as a JavScript) if it's contained. So the security is the beside effect.
How to solve it?
try to find all SCRIPT tags in Your response and execute them as fallows:
var scripts = myelement.getElementsByTagName("SCRIPT");
var i = 0;
for (i = 0; i < scripts.length; i++)
eval(scripts[i].innerHTML);

Categories

Resources