Why does not jQuery .attr() work in IE9? - javascript

The following code is just a combination of HTML, CSS and JavaScript "injected" to an existing iFrame ('iframe_id'). Although the following code works for Firefox, Chrome and Safari, it does not work in IE9. I checked some of the related and existing answers, and most of them are related to issues in IE8 or older, which does not help in this case. Is it something related to jQuery .attr()? Does IE9 have issues with it (like older IE versions)? If yes, how can I fix it?
$("#iframe_id").attr(
"src", "data:text/html;charset=utf-8," +
"<!DOCTYPE html>"+
"<html>"+
"<head>"+
"<style>"+
"/********** CSS stuff here **********/"+
"</style>"+
"</head>"+
"<body>"+
"<!--------- HTML stuff here ---------->"+
"<script src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js\"><" + "/script>" +
"<script>"+
"/*********** jQuery stuff here *****/"+
"<" + "/script>"+
"</body>"+
"</html>"
);
In IE9, I get the typical "The webpage cannot be displayed..." error.
I already reviewed the following answers, but that did not help.
Alternative for jQuery attr() in IE?
attr() not working in IE
jquery attr() do not work in IE

For security reasons, data URIs are restricted to downloaded resources.
Data URIs cannot be used for navigation, for scripting, or to populate frame or iframe elements.
MSDN
This goes for all versions of Internet Explorer.
To get it working, you can do:
var html = "<!DOCTYPE html>"+
"<html>"+
"<head>"+
"<style>"+
"/********** CSS stuff here **********/"+
"</style>"+
"</head>"+
"<body>"+
"<!--------- HTML stuff here ---------->"+
"<script src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js\"><" + "/script>" +
"<script>"+
"/*********** jQuery stuff here *****/"+
"<" + "/script>"+
"</body>"+
"</html>";
var frame = document.getElementById('iframe_id');
frame.contentWindow.document.write(html);

.attr() works fine, the issue is data:text/html. That doesn't work in IE.
From http://caniuse.com/#feat=datauri:
Support in Internet Explorer [8] is limited to images and linked resources like CSS files, not HTML files.
Instead you can create an iFrame, then edit its document's innerHTML:
$("#iframe_id").contents().find('html').html('<div>test</test>');
Or, without jQuery
document.getElementById('iframe_id').contentWindow.document.body.innerHTML = '<div>test</test>';
Or, you could just put the HTML in a file, and set the iframe to its url.

Dynamically modifying an iframe's src is a bad idea, and doesn't play nice with IE. Just create a new iframe element.
$('body').append('<iframe src=""></iframe>');

.attr() method is bogus in IE.
(http://bugs.jquery.com/ticket/11071).
Find another way to show this HTML content in iframe

as this article states, in IE you should do the following:
iframe.contentWindow.contents = yourHtmlString;
iframe.src = 'javascript:window["contents"]';
i tried it with in my project, and it worked both in IE11 and Chrome.

Related

Simple script with onclick event works fine in Chrome but fails in Firefox

I try to create an userscript using jQuery and JavaScript, but I am having a strange problem. I would like to add a onclick event to an image. It runs fine when I use Chrome (with TamperMonkey), but nothing happens when I click if using Firefox (with GreaseMonkey). However, the script is very basic. Assuming you have previously loaded jQuery and colorbox, here is what it is:
ok = "It works."
my_table = "<img onclick='alert(ok);' src='http://i.imgur.com/KrcyfFq.png' />";
$.colorbox({html:my_table,width:'33%',height:'33%'});
Uppercase the 'c' does not change anything. I also tried adding a javascript method attribute to a tag but it does not work neither.
I really do not see why it would work in Chrome but not in Firefox. Could someone help me please?
I would do it this way :
ok = "It works."
my_table = "<img class='clickableImg' src='http://i.imgur.com/KrcyfFq.png' />";
$.colorbox({html:my_table,width:'33%',height:'33%'});
$('.clickableImg').on('click', function(){
alert(ok);
});

Why does ContentFlow fail in Firefox, IE when I try to combine it with jFlickrFeed?

Here's a working example of ContentFlow using three static images hard-coded in HTML: http://dl.dropbox.com/u/27409695/WB-Browser/example.html
It works in FF, IE8, Safari, and Chrome.
I tweaked this page a little to make it pull in a Flickr feed using jFlickrFeed. It works great in webkit browsers (Safari, Chrome), but fails in FF or IE. See below for the specific errors.
http://dl.dropbox.com/u/27409695/WB-Browser/example-jflickrfeed.html
Here is the document.ready handler I'm using:
<script>
jQuery(document).ready(function($) {
$('.flow').jflickrfeed({
limit: 3,
qstrings: {
id: '60829137#N05'
},
itemTemplate:
'<img class="item" src="{{image_b}}" />'
}, function() {
var wbFlow = new ContentFlow('wbContainer', {
circularFlow: false,
startItem: 0
});
});
});
</script>
Any idea why this isn't working?
UPDATE: Just wanted to add some info in case it might help anyone help me. Firefox and IE both seem to choke on line 1652 of contentflow_src.js. Firefox throws the following error when I attempt to move the slider: "this.items[index] is undefined"
IE says of line 1652: "'this.items[...].label' is null or not an object"
Additionally, IE complains about line 1119: "'this._activeItem.index' is null or not an object"
But, again, Chrome and Safari don't throw any errors and the scripts work flawlessly in those two browsers.
I've been working on this for a while now and I hit on a solution.
As shown above, I was creating a new CF object in the jFlickrFeed callback, but that wasn't working.
Instead, I removed the CF tag from the head of the document. And instead of making a new CF object in the callback, I dynamically load the entire ContentFlow script:
function() {
var script = document.createElement('script');
script.setAttribute('src', 'contentflow.js');
script.setAttribute('type', 'text/javascript');
document.getElementsByTagName('head')[0].appendChild(script);
});
See how it works here: http://dl.dropbox.com/u/27409695/WB-Browser/example2-jflickrfeed.html
There are problems to this approach, though. For one thing ContentFlow does a lot of its own dynamic loading (addons, stylesheets, etc). Using my method above, some those functions break (especially in Internet Explorer), requiring alterations to the contentflow.js script.
If you're interested in seeing how I altered the script, take a look here: http://dl.dropbox.com/u/27409695/WB-Browser/contentflow_src_modified.js

Script tags added via jQuery not visible in FireBug

I am adding <script type="text/javascript" src="http://somedomain/somescript.js"> to the document head via jQuery. This is the code I use:
$(document).ready(function () {
var s = document.createElement("script");
s.type = "text/javascript";
s.src = (document.location.protocol == "https:" ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
$("head").append(s);
});
While the script seems to be working perfectly, I do not see the scripts in the head when I use FireBug to inspect document head. This snippet does not show the added script(s) either:
$('script[src]').each(function(){
console.log(this.src);
});
Is this normal or am I doing something wrong here? What bothers me is the fact that I see other scripts in the head section that were lazy/dynamically loaded but not those that I added. Also wondering if it is OK to load scripts that manipulate DOM in the document ready function.
UPDATE
Replacing the code from:
$("head").append(s);
to
document.getElementsByTagName("head")[0].appendChild(s);
fixes the problem. The resulting DOM appears correctly in FireBug and jQuery correctly returns the script tags that were added static/dynamically.
You will see a request being made to the script in the NET tab but the script tag won't be visible when inspecting the DOM. This seems like a bug in FireBug.
This is a bug in Mozilla's 'jsd' debugger support. One workaround is post on the on the bug cited above:
http://code.google.com/p/fbug/issues/detail?id=1774
If jquery used eval() instead of script tag injection then you could debug this in Firebug.
Ok, I found this tip on jQuery.com:
> It should be noted that any attempts to append script elements using this
> method will fail silently:
> $('#element').append("<script></script>");
>> Not exactly. Scripts will be evaluated first, and then discarded.
>> So, if you do this:
>> $('#element').append("<script>alert('hello');</script>");
>> You'll see the alert.
This probably means that the script is evaluated but not inserted in the DOM.
Test it in Chrome as well using the Right-click "Inspect Element" option to use the full debugger (view source will not show the script's modifications). The elements HTML tab should show real-time changes to the DOM

Hide an html element using javascript only if browser is firefox

How can I hide a div with javascript if the browser is firefox only?
To check Firefox browser
//Javascript
var FIREFOX = /Firefox/i.test(navigator.userAgent);
if (FIREFOX) {
document.getElementById("divId").style.display="none";
}
<!-- HTML-->
<div id="divId" />
Just check a FF-specific JavaScript property. E.g.
var FF = (document.getBoxObjectFor != null || window.mozInnerScreenX != null);
if (FF) {
document.getElementById("divId").style.display = 'none';
}
This is called feature detection which is preferred above useragent detection. Even the jQuery $.browser API (of which you'd have used if ($.browser.mozilla) for) recommends to avoid useragent detection.
“Is the browser Firefox” is almost always the wrong question. Sure, you can start grovelling through the User-Agent string, but it's so often misleading that it's not worth touching except as a very very last resort.
It's also a woolly question, as there are many browsers that are not Firefox, but are based around the same code so are effectively the same. Is SeaMonkey Firefox? Is Flock Firefox? Is Fennec Firefox? Is Iceweasel Firefox? Is Firebird (or Phoenix!) Firefox? Is Minefield Firefox?
The better route is to determine exactly why you want to treat Firefox differently, and feature-sniff for that one thing. For example, if you want to circumvent a bug in Gecko, you could try to trigger that bug and detect the wrong response from script.
If that's not possible for some reason, a general way to sniff for the Gecko renderer would be to check for the existence of a Mozilla-only property. For example:
if ('MozBinding' in document.body.style) {
document.getElementById('hellononfirefoxers').style.display= 'none';
}
edit: if you need to do the test in <head>, before the body or target div are in the document, you could do something like:
<style type="text/css">
html.firefox #somediv { display: none }
</style>
<script type="text/javascript">
if ('MozBinding' in document.documentElement.style) {
document.documentElement.className= 'firefox';
}
</script>
if(document.body.style.MozTransform!=undefined) //firefox only
function detectBrowser(){
....
}
hDiv = .... //getElementById or etc..
if (detectBrowser() === "firefox"){
hDiv.style.display = "none"
}
You might try Rafeal Lima's CSS Browser Selector script. It adds a few classes to the HTML element for OS, browser, js support, etc. You can then use these classes as hooks for further CSS and/or JS. You might write a CSS (or jQuery) selector like html.gecko div.hide-firefox once the script has run.

Trouble programmatically adding CSS to IE

I have a bookmarklet which inserts a CSS stylesheet into the target DOM via a "link" tag (external stylesheet).
Recently, this stopped working on Amazon.com, in Internet Explorer only. It works on other sites, and with other browsers (even on Amazon.com). The technique we're using to insert the stylesheet is pretty straightforward:
document.getElementsByTagName('head')[0].appendChild(s);
Where "s" is a link object created with document.createElement. Even on Amazon, I see via the Internet Explorer Developer Toolbar DOM inspector that the element is there. However if I alert the document.styleSheets collection in JavaScript, it's not there.
As a test, I tried to use the IE-only document.createStyleSheet method passing the URL to my stylesheet as an argument. This throws the error:
Not enough storage is available to
complete this operation
Points of interest:
The documentation for document.createStyleSheet says an error will be thrown if there are more than 31 stylesheets on the page but (1) it's a different error, and (2) there are only 10 external stylesheets on the page.
My googling for the error turned up a number of dead-ends, and the only one that suggested anything stylesheet-related was this drupal post, but it refers to a character limit on inline styles, as opposed to a problem relating to external styles.
The same code, even the createStyleSheet call, works on other sites in IE.
This has reached "complete mystery" status for me.
I just tried this
javascript:(function(d) { d.createStyleSheet().cssText="* {color:blue !important;}" })(document);
and
javascript:(function(d) { d.createStyleSheet("http://myschemas.com/pub/clear.css") })(document);
from IE on amazon.com and both worked.
Maybe you need to add the !important to some items of your css to be sure they take effect now?
UPDATE:
Found a possible solution for you...
javascript:(function(c) {c[c.length-1].addImport("http://myschemas.com/pub/clear.css")})(document.styleSheets);
Hope it helps you.
Looking for an answer, I have found that the 31 stylesheets limit raise this exception when loading CSS programatically:
http://www.telerik.com/community/forums/aspnet-ajax/general-discussions/not-enough-storage-is-available-to-complete-this-operation.aspx
The original limitation is described in a Knowledge Base document (suppossed only to happen on IE8 and below, but repeatedly reported as happening in IE9):
http://support.microsoft.com/kb/262161
This is all I do, and it I have never seen it not work.
loadCss = function( name, url ) {
var head = document.getElementsByTagName('head')[0];
var link = document.createElement("link");
link.setAttribute("type", "text/css");
link.setAttribute("rel", "stylesheet");
link.setAttribute("href", url);
link.setAttribute("media", "screen");
head.appendChild(link);
};
I was doing something similar using jQuery and found that I had to do it in this order:
var $link = $('<link>');
$('head').add($link);
$link.attr({
type: 'text/css',
// ... etc ...
media: 'screen'
});
Otherwise it doesn't work in IE (IE7, haven't looked at IE8 yet).
HTH

Categories