Vanilla Javascript Error IE only - javascript

I won't bother you with too much "blahblahblah" as most of you will know the following script all too well. A lot of questions popped up around this topic after Google let this beast out to play in the wild.
var elements = [
"script1.js",
"script2.js"
];
var downloadJSAtOnload = function(elements) {
if (toString.call(elements) !== "[object Array]") {
return false
}
var i, element;
for (i = 0; i < elements.length; i++) {
element = document.createElement("script");
element.src = elements[i];
document.body.appendChild(element)
}
return true
};
if (window.addEventListener) {
window.addEventListener("load", function() {
downloadJSAtOnload(elements)
}
, false)
} else {
if (window.attachEvent) {
window.attachEvent("onload", function() {
downloadJSAtOnload(elements)
})
} else {
window.onload = function() {
downloadJSAtOnload(elements)
}
}
};
This script is doing what it has to do in all browsers but IE10 and 11 from what I can see. I tested with browserstack and real machines with the same result.
May be it is due to minification of the script so I will also give you the minified version of the above script, as we are using it in our live environment:
var elements=["script1.js","script2.js"],downloadJSAtOnload=function(n){if("[object Array]"!==toString.call(n))return!1;var t,e;for(t=0;t<n.length;t++)e=document.createElement("script"),e.src=n[t],document.body.appendChild(e);return!0};window.addEventListener?window.addEventListener("load",function(){downloadJSAtOnload(elements)},!1):window.attachEvent?window.attachEvent("onload",function(){downloadJSAtOnload(elements)}):window.onload=function(){downloadJSAtOnload(elements)};
Anything I was doing wrong here? As it is indeed doing its thing in FF, Chrome, Safari and Opera I was expecting IE (you can call me a fool, now) to behave... at least once.

Seems the Error is on "[object Array]"!==toString.call(n).
The IE can't referer to the function toString() directly when using .call( something ). You can use following code to fix your Problem:
not minifed
if( Object.prototype.toString.call(elements) !== "[object Array]") {
return false;
}
minified
if("[object Array]"!==Object.prototype.toString.call(n)) return !1;
See more Informations about the toString()-Function here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString under "Using toString() to detect object class".

Related

Internet Explorer string comparison

This function is working correctly in Firefox but not IE 11. I believe the culprit is:
event = String(data.model.attributes.eventToRaise);
I know through a bunch of logging (which I removed for presentation here) that I'm getting into the first else branch correctly, but that the comparison to 'AAA' and 'BBB' aren't working correctly in IE. Logging the contents of 'event' in Firefox shows me a string but in IE console it's a pointer. I've tried a few different things (.toString(), "" + event), all of which worked in FF but not IE.
The context is Backbone with Marionette, this function is being called on click events from different places, and the code is supposed to determine which event originated the call.
showPanel: function (data) {
event = String(data.model.attributes.eventToRaise);
if (event === this.lastEvent) {
//do something
}
else {
var view = NaN;
if (event === 'AAA') {
//whatever
}
else if (event === 'BBB') {
//whatever else
}
this.lastEvent = event;
}
edit: 'var event = String(data.model.attributes.eventToRaise);' solved the issue
You could try the following:
showPanel: function (data) {
event = new String(data.model.attributes.eventToRaise);
if (event === this.lastEvent) {
//do something
}
else {
var view = NaN;
if (event.indexOf("AAA")) {
//whatever
}
else if (event.indexOf("BBB")) {
//whatever else
}
this.lastEvent = event;
}
var event = data.model.attributes.eventToRaise;
solved the issue.

open javascript library to do the same thing as symbolset

I was planning on creating my own symbol font for use on my website and I had initially intended on using ligatures and OT but support is spotty at best, and non-existant for older browsers, especially IE (I know, big surprise). I then started taking a close look at how SymbolSet works. It's actually pretty clever and while it would be easy for me to change a couple array variables and be done with it, the javascript is proprietary and I can't use it without permission. I'd love to be able to create my own symbol fonts a la SymbolSet but I'd need an open javascript file to let me do this. Are there any open jQuery plug-ins or javascript libraries that do this?
I have found this http://labs.adamdscott.com/ligatures/ligaturejs.html. Basically it walks the dom, and replaces the known letter combinations with ligatures. I've modified the script to use native ligature support when available:
// ligature.js v1.0
// http://code.google.com/p/ligature-js/
// with modifications by sabof
var ligature = (function() {
var testDiv = document.createElement('div'),
nativeLigatureSupport = testDiv.style.textRendering !== undefined;
if (nativeLigatureSupport) {
return function (node, extended) {
if (!node) {
ligature(document.body, extended);
} else {
node.style.textRendering = 'optimizeLegibility';
}
}
}
return function(node, extended) {
if (!node) {
ligature(document.body, extended);
} else {
if (node.nodeType == 3 && node.parentNode.nodeName != 'SCRIPT') {
node.nodeValue = node.nodeValue
.replace(/ffl/g, 'ffl')
.replace(/ffi/g, 'ffi')
.replace(/fl/g, 'fl')
.replace(/fi/g, 'fi')
.replace(/ff/g, 'ff')
.replace(/ij/g, 'ij')
.replace(/IJ/g, 'IJ');
if (extended) {
node.nodeValue = node.nodeValue
.replace(/ae/g, 'æ')
.replace(/A[Ee]/g, 'Æ')
.replace(/oe/g, 'œ')
.replace(/O[Ee]/g, 'Œ')
.replace(/ue/g, 'ᵫ')
.replace(/st/g, 'st');
}
}
if (node.childNodes) {
for (var i=0; i < node.childNodes.length; i++) {
ligature(node.childNodes.item(i), extended);
}
}
}
};
}());

NicEdit Error in Chrome

I'm using the NicEdit WYSIWYG plugin on my site.
It's come to my attention that when NicEdit is instantiated in Chrome, the following Javascript error is generated:
Uncaught TypeError: Object has no method 'createRange'
This doesn't stop the plugin from working, but I would like to prevent this if possible. Here is the offending method:
getRng : function() {
var s = this.getSel();
if(!s) { return null; }
return (s.rangeCount > 0) ? s.getRangeAt(0) : s.createRange();
}
NicEdit seems to be pretty much dead as a project, which is why I am asking this question here instead of over at the NicEdit forums. I am hoping that someone knows of a 'quickfix' to this problem. In all other respects NicEdit works well for me, so I am reluctant to change over to a different WYISWYG plugin just yet...
Thanks (in advance) for your help.
The problem is that the implementation of the selection object for Webkit does not define a createRange( ) method. That method seems to be specific to Internet Explorer. For Webkit and Gecko DOM implementations, the createRange( ) method is defined on the document object. With this knowledge, the fix for getRng( ) becomes:
getRng : function() {
var s = this.getSel();
var rng;
if(!s) { return null; }
if (s.rangeCount > 0) {
rng = s.getRangeAt(0);
} else if ( typeof s.createRange === 'undefined' ) {
rng = document.createRange();
} else {
rng = s.createRange();
}
return rng;
},
I encountered this as I was evaluating a number of rich text editors for an upcoming project and had to create a sample page with nicEdit.
The version at https://github.com/danishkhan/NicEdit contains this and other bugfixes.
This particular fix: https://github.com/danishkhan/NicEdit/commit/efa6a1e8867b745b841157e919a0055cb626d2c4
Same code, written in nicEdit current design:
getRng : function() {
var s = this.getSel();
if(!s) { return null; }
return (s.rangeCount > 0) ? s.getRangeAt(0) : (typeof s.createRange == 'undefined') ? document.createRange() : s.createRange();
},

javascript function overloading

Can I do the following?
function contains(element) {
// if the element is a Vertex object, do this
if (element instanceof Vertex) {
var vertex = element;
for ( var index in self.verticies) {
if (self.verticies[index].id == vertex.id) {
return true;
}
}
return false;
}
// else if the element is an Edge object, do this
else if (element instanceof Edge) {
var edge = element;
for ( var index in self.verticies) {
if (self.verticies[index].id == edge.id) {
return true;
}
}
return false;
} else {
// shouldn't come here
return false;
}
};
Basically... I want to be able to call contains() and pass it either a Vertex object or an Edge object but I don't want to have duplicate code. Is this the right way to do it? Furthermore, am I handling the assignment var vertex = element / var edge = element correctly? I want to assign element to another Vertex/Edge object and use that for my look up.
Let me know if I need to clarify.
Thanks,
Hristo
Your code should work fine.
Note, however, that there is no point (other than clarity, which is a good thing) in writing var edge = element.
Javascript variables are untyped; there is no difference between edge and element.
Also, you should probably throw an exception instead of
// shouldn't come here
return false;
Finally, why are you searching self.verticies for an Edge?
Note, by the way, that you still have duplicate code.
You can rewrite your function like this:
function contains(element) {
var searchSet;
// if the element is a Vertex object, do this
if (element instanceof Vertex)
searchSet = self.verticies;
else if (element instanceof Edge)
searchSet = self.edges;
else
throw Error("Unexpected argument");
for (var i = 0; i < searchSet.length; i++) {
if (searchSet[i].id == element.id)
return true;
}
return false;
}
Here's an approach that has a couple of advantages:
Smaller functions (no big if/else if chain)
Produces an appropriate error for missing functions without any additional coding
See what you think:
function contains(element) {
window['contains_' + typeof element](element);
};
contains_string = function(element) {
alert('string: ' + element);
};
contains('hi!'); // produces alert
contains(3); // error: 'undefined is not a function'
​It has some downsides too.
The error message isn't terribly informative (not much worse than default behavior though)
You 'pollute' the 'window' object here a little (it'd work better as part of an object)
etc

JS: How to make document.getElementById cross-browser?

document.getElementById doesn't seem to work across all browsers (I mean some old ones) and I am sure there are developers who are not aware of this.
What solutions would you suggest to make it cross-browser?
Thanks
If document.getElementById doesn't work then either:
You're doing it wrong (invalid HTML, trying to access names instead of IDs, etc)
or
You're working with Netscape 4.x and Internet Explorer 4.x
There are three ways to deal with browsers of this era.
Tell people to upgrade. They are unmaintained, security hole ridden nightmares for user and author alike.
Build on stuff that works and make sure your JS checks for the existence of getElementById and friends before trying to use them ( if (!document.getElementById) { return false; /* Insufficient DOM to bother with JS here */ } )
Learn about document.all and document.layers
Are you sure its not this kind of problem? Have a look its interesting, I didn't know that before.
However, to complement what is already suggested by David Dorward, you write a function like below.
function getElement (id) {
if (document.getElementById) {
return document.getElementById(id);
}
else if (document.all) {
return window.document.all[id];
}
else if (document.layers) {
return window.document.layers[id];
}
}
getElemID(obj){
if(document.getElementByID){
return document.getElementByID(obj);
}
else if (document.all){
return document.all[obj];
}
else if (document.layers){
return document.layers[obj];
}
else {
alert("Could not find support");
return false;
}
}
function getDOM() {
if (document.getElementById) {
return document.getElementById; 
}
var window_document = window.document || {};
var elements = window_document.all || window_document.layers;
if(elements) {
return function(x) { return elements[x]; }
}
// everything failed
throw new InternalError('No means to "getElementById"');
}
... then
var getElementById;
try {
getElementById = getDOM();
} catch(err) {
alert(err);
}
// implicit 0K
var oHTMLElement = getElementById('#main');

Categories