Selected option not displaying as selected after append() - javascript

I'm building a string of HTML based on JSON data. In the HTML is a <select> with its <option>s. If the <option>'s value is the same as some JSON data, it includes the selected="selected" attribute to the option tag as well. After that, the whole shebang is .append()ed to a display.
All of that seems to work fine and dandy, except that the selected option isn't selected. Checking the code in Chrome's Web Dev tools shows that the selected="selected" attribute is there. Doing a console.log() of the :selected options picks them up. However, when I drill down to a specific <option> and look at it, is shows the selected attribute as set to false.
Wha...?
I've tried using the .select() and .attr("selected","selected") jQuery methods after-the-fact to force the issue, but neither has made any difference.
Can anyone else figure out what's going on here? It might just be my squirrely ignorance, but this seems to me like it should be working.
Code for reference. dataArray is an array of objects. $display is the jQuery wrapped <table> the HTML is .append()ing to:
$orderNumberField = jQuery("#orderNumber");
_orderNumberArray = $.parseJSON( $orderNumberField.val() );
for( n in dataArray ) {
var _displayString = "";
// ... other table data cells ...
_displayString += "<td><select class='orderNumSelect'>";
_displayString += " <option value=''></option>";
for( i in _orderNumberArray ){
_displayString += "<option value='" + _orderNumberArray[i] + "'";
if( dataArray[n].orderNum == _orderNumberArray[i] ) _displayString += " selected='selected'";
_displayString += ">" + _orderNumberArray[i] + "</option>";
}
_displayString += "</select></td>";
// ... still other table data cells ...
$display.append( _displayString );
}

I'm not sure what's not working on your code,but you can try to generate the elements rather than appending text. I tested out with this code and it works fine
<script>
var dataArray=["test","testm2","Tasat3"];
function append(){
var td=document.createElement("td");
var sel=document.createElement("select");
var o=document.createElement("option");
sel.appendChild(o);
for (n in dataArray){
o=document.createElement("option");
o.value=dataArray[n];
o.text=dataArray[n];
if (n==1) o.selected=true;
sel.appendChild(o);
}
td.appendChild(sel);
document.getElementById("display").appendChild(td);
}
append();
</script>

As it turns out, the code outlined above was not at fault for the behavior I described. There is other code executing after it that resets form inputs. The jQuery selector in the other code was written too generally and was picking up the generated select fields also when it shouldn't have.
Thank you to all the commentors. I did end up rewriting the code to use DOM elements instead of generating a string, which is a little easier to read. Hooray for unintentional side effects.

Related

Insert html element into a previously dynamically inserted element?

Here is my first question here, I've been looking for an small clue on many researches but didn't found any piece of answer, hope it's not a silly thing.
I'll try to be straight: I'm working on a website dealing with xml files (data is stored in an array then displayed and fully editable).
Until now and despite some troubles I figured out, everything works fine.
I loop on my array to get all the required string then create jQuery object (such as $("<input id='xxx' value='yyy' />") that I appendTo a specific div).
At first start, I have an empty #insertXml div (written in my html).
One my xml files parsed and my array ready, I dynamcically create a #content div appended to my #insertXml, then for each index I'll have its key written in a #keyInput" div (dynamic insert, only once), then 1st value in a #lang1 div (still dynamic insert), 2nd in #lang2 div, etc.
lang1, lang2, etc are variables, so it's written:
$("<input .../>").appendTo("#"+langN);
where langN changes on each loop.
Everything works FINE!... at 1st display :/
The trouble is, when I'm using my function that creates new data.
I work first on a modal window, to retrieve user values through the listener function, then pass it to another function that pushes it in my array.
I debugged it, that works, my array is correctly updated.
Then I want to simply refresh my page, so I try, the same way I did previously for my whole data, to append a few inputs.
It works then correctly on my #keyInput div, but NOT on my #lang divs !?!?!
No matter how I try (even forgetting jQuery and using html document.xxx functions), no way.
While debugging, all my variables are OK, it just does nothing when doing the "appendTo", except once for the keyInput div.
I tried then to remove the #content div and relaunch the whole displayInit() method (heavy operation but, just to see) and same damn problem: only the #keyInput is correctly refreshed.
The only thing I've read that may be interesting, is that dynamically created elements (through script) are not registered in the DOM, so it can't be found.
BUT in that case, none of my display attempts should work, so?
In advance, THANK YOU very much for taking care about my nightmare.
Attached: my html + JS function.my DOM
function displayInsert() {
var firstLang = stripXmlExtension(paths[0]); // same keys on every language, so we grab the 1st one
var lastKeyIndex = mapXml[firstLang].key.length - 1;
var keyToInsert = mapXml[firstLang].key[lastKeyIndex]; // == last insertion
var inputKey = "<input size=35 type=text id=k" + lastKeyIndex + " value=" + stripHTML(keyToInsert.replace(/ /g, " ")) + " readonly />";
// while appending tag to the HTML content page, we add a dblclick listener that will morph the input into a textarea when double dblclicked
$(inputKey).css("margin-bottom", "15px").dblclick(function (e) {
e.preventDefault();
tempEditId = $(this).attr('id');
$(".modal-body").html("<textarea cols='65' rows='10' id='txt" + $(this).attr('id') + "'>" + $(this).val() + "</textarea>");
$("#modalEdit #btn-correct").css("display", "none");
$("#modalEdit").modal({backdrop: "static"});
}).appendTo("#keyInput");
for (var i = 0; i < paths.length; i++) {
var lang = stripXmlExtension(paths[i]);
var lastValueIndex = mapXml[lang].value.length - 1;
var valueToInsert = mapXml[lang].value[lastValueIndex]; // == last insertion
var inputValue = "<input size=35 type=text id=" + lang + "---" + lastValueIndex + " value=" + stripHTML(valueToInsert.replace(/ /g, " ")) + " readonly />";
// while appending tag to the HTML content page, we add a dblclick listener that will morph the input into a textarea when double clicked
$(inputValue).css("margin-bottom", "15px").dblclick(function (e) {
e.preventDefault();
tempEditId = $(this).attr('id');
$(".modal-body").html("<textarea cols='65' rows='10' id='txt" + $(this).attr('id') + "'>" + $(this).val() + "</textarea>");
$("#modalEdit #btn-correct").css("display", "none");
$("#modalEdit").modal({backdrop: "static"});
}).appendTo("#" + lang);
}
}
OMG, I'm ashamed.
My problem came from an input generated in a modal window that took the same id that was duplicated...
I was hoping it would be a little more complicated ^^
Solved!

changing text input to select in wordpress using jQuery

I am using a WordPress module abase to get some data from database and send them to a form. The problem is, that abase form does not allow to use select input. Because of that I am trying to convert text input to a select. I created function toSelect, to which I pass id of element and list of options (for testing I put id of element to function definition).
function toSelect(itemid,valuelist) {
var out = '';
out += '<select id="bus311mtd_2_status" style="width:50px;">';
for (i=0; i < valuelist.length; i++) {
out += '<option value="'+valuelist[i]+'">'+valuelist[i]+'</option>';
}
out += '</select>';
alert(out);
$("#bus311mtd_2_status").replaceWith(out);
//$("#bus311mtd_2_status").replaceWith('<input type="text" value="zamontowane">');
}
alert(out) gives nice select input code, but $("#bus311mtd_2_status").replaceWith(out) does not work.
Even something like: $("#bus311mtd_2_status").replaceWith('<input type="text" value="zamontowane">') doesn't work.
Element with id bus311mtd_2_status for sure exists (i.e. changing its value using document.getElementById() works fine)
Maybe jQuery doesn't work?
Your code seems to work fine for me. Perhaps it's your function call. I used:
toSelect(null, ['a', 'b', 'c']);
itemid doesn't appear to be used in the function.
Here's a fiddle with your code working:
http://jsfiddle.net/dgrundel/Lko6aftf/
Here's a slightly optimized version of the function, that uses the itemid argument:
function toSelect2(itemid,valuelist) {
var html = '<select id="' + itemid + '" style="width:50px;"><option>' +
valuelist.join('</option><option>') +
'</option></select>';
$('#' + itemid).replaceWith(html);
}
toSelect2('myInput2', ['d', 'e', 'f']);
Thank you for the answer and optimization. I used itemid initially but because of problems I temporarily replaced it with id of some existing element to make sure that the problem is somwhere else.
All the code until first alert works fine and alert(out) gives the popup window with text:
<select id="bus311mtd_2_status" style="width:50px;"><option value="ready">ready</option><option value="awaiting">awaiting</option></select>
This works as was expected. But the problem starts with the next line.
I wanted to show that even such an easy code like below doesn't work.
$("#bus311mtd_2_status").replaceWith('<input type="text" value="zamontowane">');
So it looks like the jQuery was not supported.
And I've got another observation: within script tags no empty lines are allowed (the code doesn't work if they are present).

Strange design error when sending "select" from javascript

I have two sets of code, that basically sends a drop down list to a div from Javascript.
The strange thing is that I am basically sending the same thing in both the cases. But in the first code, the select drop down is perfectly being shown, while in the second code, it is being broken.
Code 1:
document.getElementById('start_day_div').innerHTML += "<select name='start_day' id='start_day'><option value='1'>option1</option><option value='2'>option2</option></select>";
Code 2: (Basically I am sending the same data as the code 1)
document.getElementById('start_day_div').innerHTML += "<select name='start_day' id='start_day'>";
document.getElementById('start_day_div').innerHTML += "<option value='1'>option1</option>";
document.getElementById('start_day_div').innerHTML += "<option value='2'>option2</option>";
document.getElementById('start_day_div').innerHTML += "</select>";
Any idea why this is happening for the same code?
After each call to element.innerHTML += the browser will correct any incorrect html.
In your case you create the following html (which is invalid in itself as <option>'s cannot float around like that.)
<select name='start_day' id='start_day'></select>
<option value='1'>option1</option>
<option value='2'>option2</option>
If you want to do it, you need to do it in one go. If you want to format it better, concatenate with a +:
document.getElementById('start_day_div').innerHTML += "<select name='start_day' id='start_day'>"
+ "<option value='1'>option1</option>"
+ "<option value='2'>option2</option>"
+ "</select>";
<div id="start_day_div"></div>
If you are creating an incomplete select, most browsers will correct the error by closing the select html in order to render the control and make it an accessible object in the DOM with the normal select object properties etc. So afterwards the options are appended separately. If you inspect the resulting html this backs this theory up.

How to create a list with formatted items using DOM instead on HTML concatenation?

Please forgive me and let me know if my post is not right since I am brand new to this forum.
I have found most of the answer here (Create a <ul> and fill it based on a passed array), but my problem comes with .createTextNode. My users are using multiple editor boxes to build an outline. Within these boxes they can format the text (underline, color, bold, etc.). So the array items that I am passing to .createTextNode actually have HTML tags in them to format the line items. However .createTextNode makes it just plain text which in turn just spits out the tag instead of applying it when displayed via document.getElementById('foo').appendChild...
I know that I should stay away from HTML concatenation but it is looking very tempting.
Is there any way to retain the formatting of the list items when appended and displayed?
Thank you in advance for your assistance.
Try innerHTML, which will try to parse the content string as HTML structure. For example you have a P tag
<p id="asdf"></p>
<script>
document.getElementById('asdf').innerHTML = 'qwerty';
</script>
Will give you a clickable anchor
<p id="asdf">
qwerty
</p>
But be careful!!! (Notice I use three bang sign here) You must be sure there's no harmful code before you insert it. Check this example:
document.getElementById('asdf').innerHTML = '<img src="image.png" onload="alert(1)">'
You will see an alert dialog. This example is simple though, in practice it can be much more dangerous, e.g. dynamically append a cross site script into you page, aka XSS.
EDIT: here is a demo.
var options = ['Option 1','Option 2'];
function makeUL(){
var LIs = '';
for (i = 0; i < options.length; i += 1){
LIs += '<li>' + options[i] + '</li>';
}
return '<ul>' + LIs + '</ul>';
}
document.getElementById('foo').innerHTML = makeUL();
<div id="foo"></div>

jquery selector checkboxes

My page is moderately complicated and I'm fairly sure its the jquery acting weird. So i'll add the relevant content first and if anyone needs more info let me know and I'll provide it.
The premise is that there is a div which holds keyword bubbles. These bubbles have a tooltip (qTip plugin) with relevant info that you can select and deselect. Sometimes keywords have overlapping relevant info so when one is deselected all others need to be deselected at the same time. This list of bubbles is built dynamically via ajax and can continue to be added on to the page live.
The problem is that some of the check boxes don't uncheck when I click on them, but if I click on the same one in another tooltip it works... which also now lets the original one work just fine. I have no idea why some work and others dont. I figure it has to do with the way the live onlick function binding and/or selectors are written.
The following function writes the html content of the tooltip based on a json object, so just assume the content is there. The jquery code at the bottom is the function I have bound to the checkboxes.
function constructSpecializationsHTML(data){
var html = '';
for(i = 0; i < data.specializations.length; i++){
if(data.specializations[i].name != ''){
html += "<span class='is-specialization-line'>";
html += "<input class='is-specialization-checkbox' type='checkbox' name='" + data.specializations[i].name + "' checked='" + isSpecializationChecked(data.specializations[i].name) + "'/>";
html += "<span>" + data.specializations[i].name + "</span>";
html += "</span><br />";
} else {
html += "This keyword is not known in our ontology";
}
}
return html;
}
$(document).on("click", ".is-specialization-checkbox", function(){
var $checkboxs = $(".is-specialization-checkbox[name='" + $(this).attr("name") + "']")
$checkboxs.prop("checked", !$checkboxs.prop("checked"));
});
Firstly, when the click event fires the "checked" property has already been changed, meaning that the states of your checkboxes are different.
Changing
!$checkboxs.prop("checked")
To
$(this).prop("checked")
Solves that.
Secondly when you have only displayed one tooltip your select is only returning one checkbox. If you display all the tooltips before checking or unchecking it returns the correct number. My guess is that qTip isn't adding the html for the tooltip to the DOM until it is displayed.
That's why not all your similarly named checkboxes are unchecking though (At least I think that's it!)
$(document).on("click", ".is-specialization-checkbox", function(){
var $checkboxs = $(".is-specialization-checkbox[name='" + $(this).attr("name") + "']")
$checkboxs.not($(this)).prop("checked", false);
});
changed this to $(this) - that way it is the specific checkbox that was clicked that is getting excluded from the deselection.

Categories

Resources