I'm looking over some pretty extensive code for a web page that is generated from XML/XSL and then has Javascript generate the layout on the fly. What I am having troubles with is that it seems IE (v.10 specifically) is showing that elements are Empty Text Nodes if there is no value, and then regular text (no editable field) if there is a value.
This seems to change the behavior of to be just straight un-editable text.
From what I can see, the first step is for the Javascript to generate elements via the DOM
input = document.createElement("input");
input.setAttribute("id", "blah");
input.setAttribute("type", "text");
Then it will append it to the parent.
Then what seems to happen is that a function is executed that runs through the page again and inserts any values that these fields have.
input.value = "Hello World";
Chrome and Firefox will display the input fields properly with their fields populated, but IE10 will only show the value as if it was just plain text.
I've never worked with this sort of web page generation and hoping someone might be able to help me figure this out so I can troubleshoot this. Changing the way this works (at the time) is not an option so I'm trying to correct it so that IE is happy too.
Thanks
This specific code sequence works in all browsers I've tried it in (Chrome, IE, Firefox):
var elem = document.createElement("input");
elem.type = "text";
elem.id = "test";
document.body.appendChild(elem);
elem.value = "This is some text";
If your exact code is deviating from this, then you should examine the differences or post your exact sequence of code that demonstrates the problem in IE so we have a better idea how to debug or advise.
You can see a working demo of this in any browser you want to try it in here: http://jsfiddle.net/jfriend00/z2FpP/
Things to watch out for in your code:
Is any code setting .innerHTML of a parent which could be wiping out or resetting the child elements.
Is any code setting .innerHTML of the input field itself. This should not be done. Code should use .value to set the text of the input field.
Are there any code errors when the code runs in IE? Check the error console or debug console (hit F12 in IE to get to the debugger where you can see the error console).
Are there any other attributes being set in the input field that might make it read-only instead of editable?
Related
I'm surprised I'm having trouble with this and unable to find an answer. I'm trying to get the text in a contenteditable, from the start of the contenteditable to the users cursor/caret.
Here's a jsFiddle of what I've attempted (click around the contenteditable and watch console.log).
I get the caret location and then I attempt to get the content:
I tried using textContent of the contenteditable which works but if there's content like foo<br>bar it outputs foobar when ideally it should output foo\r\nbar (Note: This is for a chrome extension I have no control over the content of the contenteditable).
innerText works as expected outputting foo\r\nbar, but as can be seen in the jsFiddle once the html in contenteditable gets a little complex the caret position doesn't seem to match the location in innerText and I have trouble outputting up to the caret.
Found some code using the Range interface and modified it to meet my needs in this jsFiddle but had the same problem with <br> as textContent did.
Note: The user will continue typing as I get the content, so looking for something that doesn't break this flow.
Just looking for direction, any quick tips on what I should try?
In your fiddle I replaced the JavaScript content with:
document.querySelector("#edit").addEventListener("click", function(){
var target = document.querySelector('#edit');
var sel = document.getSelection();
if(!sel.toString()) {
var range = document.getSelection().getRangeAt(0);
var container = range.startContainer;
var offset = range.startOffset;
range.setStart(target, 0);
//do your stuff with sel.toString()
console.log(sel.toString());
//restore the range
range.setStart(container, offset);
}
});
Hope this helps.
Edit: since you said
Note: The user will continue typing as I get the content, so looking for something that doesn't break this flow.
I thought that the click event was just an example; getting the text while user is typing implies:
the entry point can't be click event but probably a setInterval function
while user is typing there is no selections, only the caret
To solve the reported bug is enough changing the code as I did, anyway this is only an example to get the result you are interested in; than you have to work on it to achieve the desired behavior for all the possible case of your real scenario.
I was following the code found in here to create a secure login page. The trouble is, it can't create the hidden input element.
function formhash(form, password) {
// Create a new element input, this will be out hashed password field.
var p = document.createElement("input");
// Add the new element to our form.
form.appendChild(p);
p.name = "p";
p.type = "hidden"
p.value = hex_sha512(password.value);
// Make sure the plaintext password doesn't get sent.
password.value = "";
// Finally submit the form.
form.submit();
}
I have read through saying that it only works for IE and not for gecko. Is this true or I just missing something?
Update:
The formhash function works when I place the javascript into the login page. When it is move to an external file, the problem starts again.
#asprin Noted. The reason I place php is because the code was based on php implementation
#Henrik Will do that. Thanks
#RenePot Yup, it was called on the process_login.php page
#MarkGarcia Thanks for the suggestion. Notice it say's that the function wasn't declare
#WernerVesterås Not sure but I think after.
#Quentin Thanks for the suggestion. Will do that :D
Likely, form is simply not set to what you think it is, a jsfiddle.net would probably help us and you debug. I set a working version up at http://jsfiddle.net/JPTyj/ Comment out hidden to actually see it work. Note that you will not the the hidden input field in "view source" in the browser as it is dynamically added to the dom! Use firebug or the chrome dev tools to see it.
Also, most likely you will want to use a library to make it easier for you to develop platform independent code instead of writing bare javascript.
In IE8 (at least), you need to set the type attribute before appending it using setAttribute():
var p = document.createElement("input");
p.setAttribute("type", "hidden");
form.appendChild(p);
http://jsfiddle.net/BePGD/ Tested in IE7, IE8, Chrome.
I wrote some JavaScript to allow editing a list of items within an HTML form, including adding and removing items. Got it working in Firefox. When trying it in Internet Explorer, I found that any added items were not being submitted with the form.
Long story short... lots of simplification, debugging, figured out what line is triggering IE to ignore the new form input. So the behavior problem is solved.
But now I must ask: Why? Is this an IE bug?
Here is the simplified code:
<html>
<head>
<title>Test</title>
<script type="text/javascript">
function add() {
div = document.getElementById("mylist");
// *** Adding text here works perfectly fine. ***
div.innerHTML += " ";
e = document.createElement("input");
e.setAttribute("type", "text");
e.setAttribute("name", "field3");
e.setAttribute("value", "--NEWVALUE--");
div.appendChild(e);
// *** Adding text here works perfectly fine in Firefox, but for
// Internet Explorer it causes field3 to not be submitted. ***
//div.innerHTML += " ";
}
</script>
</head>
<body>
<form action="" method="get">
<div id="mylist">
<input type="text" name="field1" value="value1" />
<input type="text" name="field2" value="value2" />
</div>
<a href="javascript:" onclick="add()" />Add</a>
<input type="submit" value="Submit" />
</form>
</body>
</html>
To try it out, do the obvious: load in IE, click Add, click Submit, look what's in the address bar. If you uncomment the last line in add(), IE will suddenly stop reporting field3. It works fine either way in Firefox.
Any ideas? A curious mind wants to know. (And how would I add text there if needed, in a portable fashion, so IE is happy?)
Is this an IE bug?
Seems so. When you create an <input> element through DOM methods, IE doesn't quite pick up the ‘name’ attribute. It's sort-of-there in that the element does submit, but if you try to get an ‘innerHTML’ representation of the element it mysteriously vanishes. This doesn't happen if you create the element by writing directly to innerHTML.
Also if you use DOM Level 0 form navigation methods, like ‘myform.elements.x.value’, access through the ‘elements’ array may not work (similarly the direct ‘myform.x’ access some people misguidedly use). In any case these days you might prefer getElementById().
So either use innerHTML or use DOM methods; best not to mix them when creating form fields.
This is documented (see ‘Remarks’) and finally fixed in IE8.
In any case, never do:
div.innerHTML+= '...';
This is only syntactical sugar for:
div.innerHTML= div.innerHTML+'...';
In other words it has to serialise the entire child HTML content of the element, then do the string concatenation, then re-parse the new string back into the element, throwing away all the original content. That means you lose anything that can't be serialised: as well as IE's bogus half-created ‘name’ attributes that also means any JavaScript event handlers, DOM Listeners or other custom properties you have attached to each child element. Also, the unnecessary serialise/parse cycle is slow.
IE is very picky about changing some built-in properties at runtime. For example, the name of an input element cannot be changed while set.
Two things I would try if I were you:
Instead of using setAttribute(), try setting the name, type and value properties explicitly:
e.name = "text";
If this doesn't work, you may have to include all these attributes into the document.createElement() call:
var e = document.createElement("<input type='text' name='field'>");
this may actually throw an exception in some browsers. So the best cross browser way to go would be:
.
var e;
try {
e = document.createElement("<input type='text' name='field'>");
} catch (ex) {
e = document.createElement("input");
e.type = 'text';
e.name = 'field';
}
e.value = 'value';
Thank you bobince and levik for your answers. Using those, and some more experimentation, here are my conclusions:
Yes it is an IE bug.
IE 8 fixes the bug according to Microsoft: "Internet Explorer 8 and later can set the NAME attribute at run time on elements dynamically created with the createElement method."
The bug is this: Calling e.setAttribute("name", "field3") only kind-of sets the name. It will work if nothing else happens to the element, but if requested to serialize, the name is not serialized. So when I said innerHTML += " " that forced a serialization, which lost the name, so it was not recovered upon deserialization. No name, no inclusion in form submission.
Workaround #1: e = document.createElement("<input name='field3' />") would work, even when faced with serialization.
Workaround #2: Rather than adding text using innerHTML +=, I can append a text element like this: div.appendChild(document.createTextNode(" "));. I had figured there must be a better way of adding text, and now I know it :-).
Cheers,--jsf
I'm trying to dynamically add some textboxes (input type=text) to a page in javascript and prefill them. The textboxes are coming up, but they are coming up empty. What is the proper way to pre-fill a textbox. Ideally I'd love to use the trick of creating a child div, setting the innerhtml property, and then adding that div to the parent main div but that didn't work. Then I thought I'd use the dom but setting textboxname.value before or after insertion won't work and doing txttextbox.setattribute('value','somevalue') won't work either. Works fine in firefox. What gives? This has to be possible? Here is my code. I know I'm only using string literals, but these will be replaced with the results of a web service call eventually. Below is some code. Oh and how do you format code to show up as you type it? I thought it said to indent four spaces, and I did that but the code is still on one line. Sorry about that.
var table=document.createElement('table');
var tbody=document.createElement('tbody');
var row=document.createElement('tr');
row.appendChild(document.createElement('td').appendChild(document.createTextNode('E-mail')));
var txtEmail=document.createElement('input');
row.appendChild(document.createElement('td').appendChild(txtEmail));
tbody.appendChild(row);
table.appendChild(tbody);
//document.getElementById('additionalEmails').innerHTML="";
document.getElementById('additionalEmails').appendChild(table);
txtEmail.value = 'my text'
Does not work?
You can also use Prototype to do this easily:
document.body.insert(new Element("input", { type: "text", size:20, value:'hello world' }))
I've encountered problems similar to this in the past, and while my memory is a bit fuzzy on why it was happening exactly, I think you may need to make sure the element is actually added to the DOM before modifying its value. e.g:
var txtEmail=document.createElement('input');
document.getElementById('someElementThatAlreadyExists').appendChild(txtEmail);
txtEmail.value = 'sample text';
I ended up solving this problem by injecting the html directly into a page via a child div. That did work, it's just that I am blind and the software I use to read the screen for some stupid reason failed to see the text in the textbox. Go figure. Thanks for the tip on prototype though, if I ever decide not to cheat and add the eleements to the dom directly, I'll do it that way.
I am trying to make a div, that when you click it turns into an input box, and focuses it. I am using prototype to achieve this. This works in both Chrome and Firefox, but not in IE. IE refuses to focus the newly added input field, even if I set a 1 second timeout.
Basically the code works like this:
var viewElement = new Element("div").update("text");
var editElement = new Element("input", {"type":"text"});
root.update(viewElement);
// pseudo shortcut for the sake of information:
viewElementOnClick = function(event) {
root.update(editElement);
editElement.focus();
}
The above example is a shortened version of the actual code, the actual code works fine except the focus bit in IE.
Are there limitations on the focus function in IE? Do I need to place the input in a form?
My guess is that IE hasn't updated the DOM yet when you make the call to focus(). Sometimes browsers will wait until a script has finished executing before updating the DOM.
I would try doing the update, then doing
setTimeout("setFocus", 0);
function setFocus()
{
editElement.focus();
}
Your other option would be to have both items present in the DOM at all times and just swap the style.display on them depending on what you need hidden/shown at a given time.
What version IE? What's your DocType set to? is it strict, standards or quirks mode? Any javascript errors appearing (check the status bar bottom left for a little yellow warning sign) ? Enable error announcing for all errors via Tools > Options > Advanced.
Oisin
The question is already answered by 17 of 26. I just want to point out, that Prototype has native mechanism for this: Function.defer()