I have just found out after half a year that an IE cannot process this script and now that my programmer is gone I'm stuck with it myself :-(
It works fine in FF
This is the code:
function updateFields(name, value) {
var elements = getElementsByClass('field_' + name);
for(var i=0; i<elements.length; i++) {
var e = elements[i];
while(e.firstChild != null) { e.removeChild(e.firstChild); }
e.appendChild(document.createTextNode(value + ' '));*
} // for i
} // updateFields()
My IE debugger complains about the line marked with *.
It says: Error: Unexpected call to method or property access.
Can anybody spend some of his/her precious time to help?
Please write answers as if I'm a four-year-old.
function getElementsByClass(cls) {
var fields = document.getElementsByTagName('*');
var r = new Array();
for(var i=0; i<fields.length; i++) {
var f = fields[i];
var a = f.getAttribute('class');
if(a == null)
a = f.className;
if(a == null)
continue;
var classes = a.split(' ');
for(var j=0; j<classes.length; j++) {
if(classes[j] == cls) {
r.push(f);
break;
} // if
} // for j
} // for i
return r;
}
Button:
<form>
<p class="center">
<input type="button" onclick="javascript:book_wire_transfer();" style="border: none; border:0;"\>
<p class="center">
<img src="http://www.-.com/images/text/arrow_left_small.png" alt="»" class="middle" />
<span class="submit">
<input class="submit" type="submit" value="Book now" />
</span>
<img src="http://www.-.com/images/text/arrow_right_small.png" alt="«" class="middle" />
</p>
</p>
</form>
There are elements that IE8 and below cannot add textNodes to, though IE9 and other browsers do.
option element(use optionelement.text)
input element(use inputelement.value)
style element(use styleelement.styleSheet.cssText)
script element(use scriptelement.text)
getElementsByClass is not a built-in function, so it probably comes from some other library you are using that is incompatible with IE8. In this case, it is probably returning something that is not a valid set of DOM nodes.
If you could post what that method does, that would help us in debugging. Otherwise, you could try using document.querySelectorAll('.field_' + name) instead and see if that fixes it; this is supported in IE8 onwards, at least if you are in standards mode.
EDIT: your custom getElementsByClass function looks OK, although without unit tests it's hard for me to be 100% sure. One way to test would be to try and replace the body of getElementsByClass with return document.querySelectorAll('.field_' + name) and see if that fixes it... In this way, the getElementsByClass function still exists, so all your other code is not broken, but it may be more correct.
well, remove the * at the end of
e.appendChild(document.createTextNode(value + ' '));*
Related
I apologize in advance, this is the first Stack Overflow question I've posted. I was tasked with creating a new ADA compliant website for my school district's technology helpdesk. I started with minimal knowledge of HTML and have been teaching myself through w3cschools. So here's my ordeal:
I need to create a page for all of our pdf and html guides. I'm trying to create a somewhat interactable menu that is very simple and will populate a link array from an onclick event, but the title="" text attribute drops everything after the first space and I've unsuccessfully tried using a replace() method since it's coming from an array and not static text.
I know I'm probably supposed to use an example, but my work day is coming to a close soon and I wanted to get this posted so I just copied a bit of my actual code.
So here's what's happening, in example 1 of var gmaildocAlt the tooltip will drop everything after Google, but will show the entire string properly with example 2. I was hoping to create a form input for the other helpdesk personnel to add links without knowing how to code, but was unable to resolve the issue of example 1 with a
var fix = gmaildocAlt.replace(/ /g, "&nb sp;")
//minus the space
//this also happens to break the entire function if I set it below the rest of the other variables
I'm sure there are a vast number of things I'm doing wrong, but I would really appreciate the smallest tip to make my tooltip display properly without requiring a replace method.
// GMAIL----------------------------
function gmailArray() {
var gmaildocLink = ['link1', 'link2'];
var gmaildocTitle = ["title1", "title2"];
var gmaildocAlt = ["Google Cheat Sheet For Gmail", "Google 10-Minute Training For Gmail"];
var gmailvidLink = [];
var gmailvidTitle = [];
var gmailvidAlt = [];
if (document.getElementById("gmailList").innerHTML == "") {
for (i = 0; i < gmaildocTitle.length; i++) {
arrayGmail = "" + gmaildocTitle[i] + "" + "<br>";
document.getElementById("gmailList").innerHTML += arrayGmail;
}
for (i = 0; i < gmailvidTitle.length; i++) {
arrayGmail1 = "";
document.getElementById("").innerHTML += arrayGmail1;
}
} else {
document.getElementById("gmailList").innerHTML = "";
}
}
<div class="fixed1">
<p id="gmail" onclick="gmailArray()" class="gl">Gmail</p>
<ul id="gmailList"></ul>
<p id="calendar" onclick="calendarArray()" class="gl">Calendar</p>
<ul id="calendarList"></ul>
</div>
Building HTML manually with strings can cause issues like this. It's better to build them one step at a time, and let the framework handle quoting and special characters - if you're using jQuery, it could be:
var $link = jQuery("<a></a>")
.attr("href", gmaildocLink[i])
.attr("title", gmaildocAlt[i])
.html(gmaildocTitle[i]);
jQuery("#gmailList").append($link).append("<br>");
Without jQuery, something like:
var link = document.createElement("a");
link.setAttribute("href", gmaildocLink[i]);
link.setAttribute("title", gmaildocAlt[i]);
link.innerHTML = gmaildocTitle[i];
document.getElementById("gmailList").innerHTML += link.outerHTML + "<br>";
If it matters to your audience, setAttribute doesn't work in IE7, and you have to access the attributes as properties of the element: link.href = "something";.
If you add ' to either side of the variable strings then it will ensure that the whole value is read as a single string. Initially, it was assuming that the space was exiting the Title attribute.
Hope the below helps!
UPDATE: If you're worried about using apostrophes in the title strings, you can use " by escaping them using a . This forces JS to read it as a character and not as part of the code structure. See the example below.
Thanks for pointing this one out guys! Sloppy code on my part.
// GMAIL----------------------------
function gmailArray() {
var gmaildocLink = ['link1', 'link2'];
var gmaildocTitle = ["title1", "title2"];
var gmaildocAlt = ["Google's Cheat Sheet For Gmail", "Google 10-Minute Training For Gmail"];
var gmailvidLink = [];
var gmailvidTitle = [];
var gmailvidAlt = [];
if (document.getElementById("gmailList").innerHTML == "") {
for (i = 0; i < gmaildocTitle.length; i++) {
var arrayGmail = "" + gmaildocTitle[i] + "" + "<br>";
document.getElementById("gmailList").innerHTML += arrayGmail;
}
for (var i = 0; i < gmailvidTitle.length; i++) {
var arrayGmail1 = "";
document.getElementById("").innerHTML += arrayGmail1;
}
} else {
document.getElementById("gmailList").innerHTML = "";
}
}
<div class="fixed1">
<p id="gmail" onclick="gmailArray()" class="gl">Gmail</p>
<ul id="gmailList"></ul>
<p id="calendar" onclick="calendarArray()" class="gl">Calendar</p>
<ul id="calendarList"></ul>
</div>
i want to add parameters to url, for that i have 2 textbox and a button, i can't figure out where am i stuck and is unable to add parameters to url
here is my code:
HTML:
Param Name: <input id="tbAddParam" type="text" /><br>
Param Value: <input id="tbAddParamValue" type="text" /><br>
<input onclick="javascript:AddParamter();" value="Add" type="button" />
JavaScript:
function AddParamter() {
var new_url = AddUrlParameter(window.location.href, document.getElementById('tbAddParam').value, document.getElementById('tbAddParamValue').value);
window.location.href = new_url;
}
function AddUrlParameter(a, b, c) {
if (b.trim() == "") {
alert("Parameter name should not be empty.");
return a;
}
if (c.trim() == "") {
alert("Parameter value should not be empty.");
return a;
}
if (a.indexOf("?") == -1) {
return a + "?" + b + "=" + c;
}
var d = a.split("?");
if (d.length >= 2) {
if (d[1].trim() == "") {
return d[0] + "?" + b + "=" + c;
}
var e = d[1].split(/[&;]/g);
for (var f = 0; f < e.length; f++) {
var g = e[f]; var h = g.split("=");
if (h.length >= 2) {
if (h[0] == b) {
alert("Url Parameter with provided name already exists! Try Updating that Url Parameter.");
return a;
}
}
}
return a + "&" + b + "=" + c;
}
}
From the comments above:
I've tested your code and works for me (if the page ends in html, jsp or .something). This was tested using Chrome v25.
Later, I've tested on IE9 and it worked after enabling the script execution for local executed pages. A message pops up when you enter to IE. In IE9, it appears on the bottom part saying Internet Explorer restricted this webpage from running scripts or ActiveX controls. and on the right there's this option Allow blocked content..
For IE backward compatibility, it seems that you should replace the d[1].trim() as stated in james emanon's answer.
As an advice, use at least two browsers to test your web pages. And yes, I highly recommend test on IE because it will give you a good(?) feedback for being so sensitive on scripting errors (it will arise so much errors that Chrome and Firefox cover for you).
When running this in IE (I tested this in IE 10), you need to allow blocked content in order for the JavaScript to run. Otherwise the JavaScript will not be allowed to run. Luiggi Mendoza suggested the same for IE 9.
It is worth noting that this works fine in Chrome and FireFox without any user confirmation allowing JavaScript to run.
IE doesn't like ".trim()". I tested in IE8 with IE8 compat mode, and your code didn't work because of trim. Though I imagine IE9 is fine (as noted by Luigi's confirmation).
use something like this instead:
strReplace=str.replace(/^\s+/,'').replace(/\s+$/,'');
You could get around it with something like:
function stripWhiteSpace(arg){
if(arg.replace(/^\s+/,'').replace(/\s+$/,'') == ""){
return true;
}
}
then just call to it and pass your param
if (stripWhiteSpace(b))
I support #rhughes's answer. But If you test this code in IE8(I was using this and your code was not working) and below, The HTML trim() wont work. As you have trim() in 3 places, you have to use the following.
if(typeof String.prototype.trim !== 'function') {
String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
}
}
or you can more easly use jQuery trim()
$.trim()
refer 1
refer 2
I need to use pure Javascript for the first time in a long while, and having gotten used to the comfy mattress of jQuery, all the important stuff is escaping me.
I need to select a bunch of divs on regular expression. So I have stuff like this;
<div id="id_123456_7890123"> .. </div>
<div id="id_123456_1120092"> .. </div>
<div id="id_555222_1200192"> .. </div>
<div id="id_123456_9882311"> .. </div>
And I'd need to create a loop that goes through all the divs with an id that begins with id_123456_. How would I go about doing that?
I used jQuery with the :regex filter plugin before, but looking at it, it doesn't seem like there's much I could salvage in a pure javascript rewrite.
In plain javascript, you could do this generic search which should work in every browser:
var divs = document.getElementsByTagName("div"), item;
for (var i = 0, len = divs.length; i < len; i++) {
item = divs[i];
if (item.id && item.id.indexOf("id_123456_") == 0) {
// item.id starts with id_123456_
}
}
Working example: http://jsfiddle.net/jfriend00/pYSCq/
HTML DOM querySelectorAll() method will work here.
document.querySelectorAll('[id^="id_"]');
Borrowed from StackOverFlow here
This works by recursively traversing the whole DOM.
It's possibly not the most efficient, but should work on every browser.
function find_by_id(el, re, s) {
s = s || [];
if (el.tagName === 'DIV' && re.exec(el.id) !== null) {
s.push(el);
}
var c = el.firstChild;
while (c) {
find_by_id(c, re, s);
c = c.nextSibling;
}
return s;
}
var d = find_by_id(document.body, /^id_123456_/);
See http://jsfiddle.net/alnitak/fgSph/
Here you are: http://jsfiddle.net/howderek/L4z9Z/
HTML:
<div id="nums">
<div id="id_123456_7890123">Hey</div>
<div id="id_123456_1120092">Hello</div>
<div id="id_555222_1200192">Sup</div>
<div id="id_123456_9882311">Boom</div>
</div>
<br/>
<br/>
<div id="result"></div>
Javascript:
divs = document.getElementsByTagName("div");
divsWith123456 = new Array();
for (var i = 0;i < divs.length;i++) {
if (divs[i].id.match("id_123456") != null) {
divsWith123456.push(divs[i]);
document.getElementById("result").innerHTML += "Found: divs[" + i + "] id contains id_123456, its content is \"" + divs[i].innerHTML + "\"<br/><br/>";
}
}
i'm pretty new to Javascript and basiclly everything related to web
coding. i have a simple problem using InnerHTML in FF, i hope you can
help me.
i'm using this code, that should generate a simple html input line,
and in IE it works fine (although when i load it i get the "should i
enable activeX msg on top), but in FF it doesn't work at all, i can
see it's on the page thorugh source, but it doesn't show anything...
<div id="mainDiv"></div>
<script type="text/javascript">
var siteBoxes = '<form action=HTMLPage.htm name="myform">';
for (var i = 0; i < arr1.length; i++) {
siteBoxes += '<INPUT TYPE="checkbox" id="box'+i+'"
VALUE="'+arr1[i]+'"/> '+arrNames[i]+'';
}
siteBoxes += '';
document.getElementById("mainDiv").innerHTML=siteBoxes;
i'm sure it's a simple solution, and i tried searching on the web, but
i'm running out of strength for that, i hope any of you kind people
can help me.
thanks in advance!!!
ok, the problem is with the array definition in the head.
i just noticed that in the error console in FF i get a msg that the arr1 is undefined, but it is, i even tried moving it to the body and it doesn't change, still undefined... and it works in IE.
could it be something with the array definition? is it different from IE and FF???
var arr1 = new Array(
"http://www.google.com",
"http://www.yahoo.com",
"http://www.cnet.com",
"http://www.google.ar/search?q="
);
again, it works great in IE, but not in FF
Somethings I noticed at first glance.
<div id="mainDiv"></div>
<script type="text/javascript">
var siteBoxes = '<form action="HTMLPage.htm" name="myform">';//put quotes around page
for (var i = 0; i < arr1.length; i++) {
siteBoxes += '<INPUT TYPE="checkbox" id="box'+i+'" VALUE="'+arr1[i]+'"\/>
'+arrNames[i]+'<br \/><br \/>';
}
siteBoxes += '<\/form>';
document.getElementById("mainDiv").innerHTML=siteBoxes;
arr1 is never declared at least from the code you present to us.
Works in Opera, IE and FF for me.
Try unescaping the output;
document.getElementById("mainDiv").innerHTML = unescape(siteBoxes);
There is something wrong with the ending quotation mark in your script tag. If I delete it and type a new one, the code works.
There must be a problem with the rest of your code because when I change it. It works fine.
<html>
<head>
</head>
<body>
<div id="mainDiv"></div>
<script type="text/javascript">
var arr1 = new Array();
var arrNames = new Array();
arr1[0] = "test";
arrNames[0] = "nameTest";
var siteBoxes = '<form action=HTMLPage.htm name="myform">';
for (var i = 0; i < arr1.length; i++) {
siteBoxes += '<INPUT TYPE="checkbox" id="box'+i+'" VALUE="'+arr1[i]+'"/> '+arrNames[i]+'<br /><br />';
}
siteBoxes += '</form>';
document.getElementById("mainDiv").innerHTML = siteBoxes;
</script>
</body>
</html>
Here's perhaps a cleaner way of implementing this (see comments in code as well):
//You can use the simple way of creating an array, and instead of having two
//arrays that represent the names and urls, just make a single array of JSON
var sitesArray = [
{siteName: "Google",siteUrl:"http://www.google.com"},
{siteName: "Yahoo",siteUrl:"http://www.yahoo.com"},
{siteName: "CNET",siteUrl:"http://www.cnet.com"},
{siteName: "Google Search",siteUrl:"http://www.google.ar/search?q="}
];
//Create an ouput array where you'll compile your html
var outputArray = [];
//Now loop through sitesArray and push the strings onto the ouputArray
for (var i=0,len=arr1.length;i < len;++i) {
outputArray.push("<input type=\"checkbox\" id=\"box",i,"\" ",
"value="\",sitesArray[i].siteUrl,"\" /> ",
sitesArray[i].siteName,"<br /><br />");
}
document.getElementById("mainDiv").innerHTML = outputArray.join("");
The primary reason for suggesting this is that string concatenation can be very slow, especially if you have lots of long strings. It's not as big an issue in Firefox, but it's definitely an issue in IE. So pushing strings onto an array, then joining them at the end will give you better performance.
Those snippes of code that you will check works fine for FF, Chrome, Safari, but seems to be a problem with IE when running jQuery clone function:
My template:
<form method="post" action="/post/add/">
{{ form.management_form }}
<div class='table'>
<table class='no_error'>
<input id="id_mypost_set-0-title" type="text" name="mypost_set-0-title" />
<input id="id_mypost_set-0-content" type="text" name="mypost_set-0-content" />
</table>
</div>
<input type="button" value="Add Other" id="add_more">
<script>
$('#add_more').click(function() {
cloneMore('div.table:last', 'mypost_set');
});
</script>
</form>
In a javascript file:
function cloneMore(selector, type) {
var newElement = $(selector).clone(true);
var total = $('#id_' + type + '-TOTAL_FORMS').val();
newElement.find(':input').each(function() {
var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
var id = 'id_' + name;
$(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
});
newElement.find('label').each(function() {
var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-');
$(this).attr('for', newFor);
});
total++;
$('#id_' + type + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
}
The problem is with the selector: "A clone of the original html piece of code works OK", but, A clone from cloned piece of code marks the selector as "undefined", in other words, the second time that I clone the table the selector doesnt work anymore for those cloned items.
Problem only for IE.
What im missing? Any hint is apreciated :)
This is a known jQuery bug, though they claim it is fixed.
One option here is to use .html(), and clone them manually. This will not clone events and saved .data, which may be an issue for you. .live can help if you have events here.
If the only thing you need is to change the names and id, a better option is to use a regular expression (this clones the events from the first element, mind you):
var name = $(this).attr('name').replace(/-\d+-/,'-' + total + '-');
this will search for -number-, and replace it, so it finds the last number on all browsers, or -0- on IE.
Here's a working demo with alerts: http://jsbin.com/evapu
As a side note - your code is a little messy. jQuery code should be inside $(document).ready (the click), you have a table with no body (no <tr>,<td> - the inputs are thrown out), and the code has some duplications.
Although it didn't help in this case, invalid DOM and not using the ready event can cause problems.
you're missing a hidden input with id 'id_' + type + '-TOTAL_FORMS'
- you're getting your total from this object and using it to modify the name and id of cloned objects.
I tried your code with this:
<input type="hidden" id="id_mypost_set-TOTAL_FORMS" value="1"/>
added right after
<form method="post" action="/post/add/">
and it works correctly, all new inputs have correct ids.
does this really work in FF ??
You code works perfectly on all browsers as stated before
Still if you could replace:
var newElement = $(selector).clone(true);
with:
var newElement = $($(selector).html());
and see if it helps.
Also, re-attach the event handler, like so.
newElement.bind(EVENT, function() {});
Or use the appropriate helper.
perhaps you can use this clone function :
/*
* Clone method
* Prevents reference problem
*/
clone: function( obj ){
if(obj == null || typeof(obj) != 'object')
return obj;
var temp = new obj.constructor();
for(var key in obj)
temp[key] = clone(obj[key]);
return temp;
}