Jquery / Javascript - most efficient way to build a select menu? - javascript

I'm using jquery and trying to tune my select menu builder to run much quicker.
I was using each and append, however I've since switched to a standard for loop and currently trying to convert my options from using append to concatenated string appended to my select option using .html(). I seem to be at a loss trying to convert my var option object back to an html string. Could someone please tell me what I might be doing wrong.
$.selectMenuBuilder = function(json) {
var myselect = $("#myselect");
var list = "<option value=\"\">> Select Account Number</option>";
var l= json.funding.length;
for(var i=0;i<l; i++) {
var funding = json.funding[i];
var option = $("<option value=\"" + funding.id + "\">" + funding.accountNumber + "</option>")
if(someLogic) {
option.attr("selected", "selected");
}
//Having trouble here converting option object back to html.
list += option.html();
}
list += "<option value=\"addnew\">+ New Account Number</option>";
myselect .html(list);
}

You can totally do away with using jQuery for creating the option elements (unless theres some other untold reason you're using it).
i.e. Instead of
var option = $("<option value=\"" + funding.id + "\">" + funding.accountNumber + "</option>")
if(someLogic) option.attr("selected", "selected");
You can do:
list += "<option value=\"" + funding.id + "\" "+ (someLogic?'selected':'') +">" + funding.accountNumber + "</option>"
Secondly, $(option).html() will return the innerHTML of the option element, not including the option tag name. For doing this in a cross-browser fashion, you can wrap the option in an outer element and use its innerHTML instead.
i.e.
$(option).wrap('<select/>').parent().html() will give you what you want.

If you want to keep the for loop but want something that looks a bit cleaner, try this:
function menuBuilder( json ) {
var list = [],
$select = $('#myselect'),
i = 0,
l = json.funding.length,
funding;
for ( ; i < l; i++ ) {
funding = json.funding[ i ];
list.push(
'<option '+ somelogic ? 'selected' : ''+' value='+ funding.id +'>'+
funding.accountNumber +
'</option>'
);
}
$select.append(
'<option>Select Account Number</option>'+
list.join('') +
'<option value="addnew">New Account Number</option>'
);
}

You can create elements more efficiently like this:
$.selectMenuBuilder = function (json) {
var myselect = $("#myselect");
var l = json.funding.length;
for (var i = 0; i < l; i++) {
var funding = json.funding[i];
var opt = $("<option/>", {
value: funding.id,
html: funding.accountNumber,
selected: somelogic ? true : false //Pre-select option
});
myselect.append(opt);
}
}

efficiency with pure JavaScript
example jsfiddle
selectMenuBuilder = function(json) {
var myselect = document.getElementById("myselect"),
listItem = document.createElement("option"),
l = json.funding.length,
someLogic = false; // placeholder
listItem.innerText = "> Select Account Number";
myselect.appendChild(listItem);
for (var i = 0; i < l; i++) {
var funding = json.funding[i];
var listItem = document.createElement("option");
if (someLogic) {
listItem.setAttribute("checked", "checked");
}
listItem.setAttribute("value", funding.id);
listItem.innerText = funding.accountNumber;
myselect.appendChild(listItem);
}
listItem = document.createElement("option")
listItem.setAttribute("value", "addnew");
listItem.innerText = "+ New Account Number";
myselect.appendChild(listItem);
}

Related

How to show pipe separated string into different td in dynamic html table

I have this data in array:
Pune|M, Mumbai|O
and I want to show this data into html table, so for that I did this:
var arr;
arr = obj[0][2];
var j=0;
$.each(arr, function(){
var html = "<tr><td>" + arr[j] + "</td><td><span class='ui-icon ui-icon-close' onclick='remove_locations1()'></span></td></tr>";
j = j + 1;
$('#table_display_locations1').append(html);
});
obj[0][2] contain the
Pune|M, Mumbai|O
I manage to display the data like this:
Pune|M
Mumbai|O
but I want to show in first row as Pune and M in two different td's and in second row, Mumbai and O display in two different td's.
I tried split function, but it wont work for me.
can anyone please tell how I manage my string to display the result which I want?
Help?
var j=0;
$.each(arr, function(){
var split_array = arr[j].split('|');
var split_result = '';
for (var i = 0; i < split_array.length; i++) {
var split_result = split_result + '<td>'+split_array[i]+'</td>';
}
var html = "<tr>" + split_result + "<td><span class='ui-icon ui-icon-close' onclick='remove_locations1()'></span></td></tr>";
j = j + 1;
$('#table_display_locations1').append(html);
});
First use foreach in the main array, split each entries using |,
Try the below code.
var arr=["Pune|M","Mumbai|O"];
var text="";
arr.forEach(x => { text +="<tr>"; x.split('|').forEach(y => text+="<td>"+y+"<td />"); text +="</tr>";});
document.getElementsByTagName('table')[0].innerHTML=text;
console.log(text);
<table>
</table>

javascript/php won't load data for first option in dependent dropdown

I'm having a problem with a script that is part borrowed and part my own, it is javascript and php that populates two dropdown lists, with options in the second being dependent on what the user selects in the first. For some reason, it won't load the options in the second dropdown when the initial option is selected in the first, either on page load or if it is selected manually (if the options were 'a, b, c, d, e...etc', it won't load anything for 'a').
I think it might be something to do with the javascript document ready function, but I'm afraid I know very little about javascript. This is the javascript code:
$(document).ready(function () {
$.getJSON("getOutcome.php", success = function(data)
{
var options = "";
for(var i = 0; i < data.length; i++)
{
options += "<option value ='" + data[i].toLowerCase() + "'>" + data[i] + "</option>";
}
$("#slctOutcome").append(options);
$("#slctProxy").change();
});
$("#slctOutcome").change(function()
{
$.getJSON("getProxies.php?outcome=" + $(this).val(), success = function(data)
{
var options = "";
for(var i = 0; i < data.length; i++)
{
options += "<option value ='" + data[i].toLowerCase() + "'>" + data[i] + "</option>";
}
$("#slctProxy").html("");
$("#slctProxy").append(options);
});
});
});
Change event is only fired, when selection is changed - not when filled ;-)
Try adding $("#slctOutcome").trigger("change"); at pre-last line
Have fun :-)
Try the below. Second function wasn't being called in first function.
$(document).ready(function () {
$.getJSON("getOutcome.php", success = function(data)
{
var options = "";
for(var i = 0; i < data.length; i++)
{
options += "<option value ='" + data[i].toLowerCase() + "'>" + data[i] + "</option>";
}
$("#slctOutcome").append(options);
$("#slctOutcome").change(); //<-Here
});
$("#slctOutcome").change(function()
{
$.getJSON("getProxies.php?outcome=" + $(this).val(), success = function(data)
{
var options = "";
for(var i = 0; i < data.length; i++)
{
options += "<option value ='" + data[i].toLowerCase() + "'>" + data[i] + "</option>";
}
$("#slctProxy").html("");
$("#slctProxy").append(options);
});
});
});

How to fetch the values of a dynamic select list in a global variable?

I'm trying to get the values of my dynamically filled select list in a global variable. This is how I get and fill the select list:
My dropdown.js script:
$(document).ready(function () {
$("#slctTable").change(function()
{
$.getJSON("dropdown_code/get_fields.php?table=" + $(this).val(), success = function(data)
{
var options = "";
for(var i = 0; i < data.length; i++)
{
options += "<option value='" + data[i] + "'>" + data[i] + "</option>";
}
$("#slctField").html("");
$("#slctField").append(options);
$("#slctField").change();
});
});
});
So after this I tryed this code in my main.js scgript to get the values of the select lists:
$('#slctField > option').each(function(){
console.log(this.value); // Use this.value to get the value of the option
});
var options = [];
$('#slctField > option').each(function(){
options.push(this.value);
});
console.log(options);
But when I run my scripts this the result I get back:
But when I copy and paste the code in firebug and run it. I get the result i want.So I think the select lists aren't filled yet when i try to get the values. But I'm stuck on this for a long time and I don't know what to do at the moment.
Because getJSON is asynchronous, to solve your problem you can trigger a custom event when the select is completed (at the end of getJSON success).
In my example I used this slctFieldFilled new event.
This is a different approach. Another possible solution can be based on callbacks: at the end of an asynchronous function execute the callback function, like the getJSON does.
My snippet:
$(function () {
$.getJSON('https://api.github.com/users', success = function (data) {
var options = '';
for (var i = 0; i < data.length; i++) {
options += "<option value='" + data[i].id + "'>" + data[i].id + "</option>";
}
$("#slctTable").append(options);
$("#slctTable").change();
});
$("#slctTable").on('change', function(e) {
var par1 = $(this).val();
$.getJSON("https://api.github.com/users", success = function(data) {
var options = "";
for(var i = 0; i < data.length; i++) {
options += "<option value='" + data[i].id + "'>" + data[i].id + "</option>";
}
$("#slctField").html("");
$("#slctField").append(options);
$("#slctField").change();
//
// Now, the slctField is filled, so trigger your custom event
//
$('#slctField').trigger('slctFieldFilled', options);
});
});
$("#slctField").change(function() {
var par1 = $(slctTable).val();
var par2 = $(slctField).val();
$.getJSON("https://api.github.com/users", success = function(data) {
var options = "";
for(var i = 0; i < data.length; i++) {
options += "<option value='" + data[i].id + "'>" + data[i].id + "</option>";
}
$("#slctAttribute").html("");
$("#slctAttribute").append(options);
$("#slctAttribute").change();
});
});
// listen on custom event...
$('#slctField').on('slctFieldFilled', function(e, optionVariable) {
var options = [];
$(optionVariable).each(function(index, element){
options.push(this.value);
});
$('#log').text(options);
});
});
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<select id="slctTable"></select>
<select id="slctField"></select>
<select id="slctAttribute"></select>
<p id="log"></p>
You're very correct! Your GET is asynchronous and will likely complete long after your main.js code has finished executing. You'll want to make sure your modifications to the global variable is tied to your callbacks in some way so its guaranteed to run afterwards.
var options = [];
$("#slctField").change(function()
{
$.getJSON("dropdown_code/get_attributes.php?table=" + $(slctTable).val() ,"field=" + $(slctField).val() , success = function(data)
{
...
//Option 1: Append the values inside your callback.
//Use window.options because you have another local variable options(window.XX calls any global XX)
for(var i = 0; i < data.length; i++)
{
...
window.options.push(data[i]);
}
//Option 2: Basically the same thing as 1, call a function that does the same thing at the end of your callback
populateOptions();
});
});
function populateOptions(){
$('#slctField > option').each(function(){
options.push(this.value);
});
}
There's plenty of other ways to do it as well as long as you guarantee it executes after your GET. If you have any questions, post a comment. Be careful about the scope of options since you have multiple variables named options(or consider different names so that you can't be confused later on!).

display my dropdown box in a specific area

Ok here's what I am doing. Based on some dropdown value I am craeting another dropdown value.
Is it possible to display that dropdown in some specific area as I wish based on my existing code.
if (SelectedIndex == 2 || SelectedIndex == 5 || SelectedIndex == 7) {
$("#DomContainer").remove();
var MainContainer = document.createElement("Div");
MainContainer.id = "DomContainer";
$("body").append(MainContainer);
var Options = new Array();
for(var i=1;i<=28;i++){
Options.push(i);
}
AddDropDown(Options);
}
function AddDropDown(Options) {
var selectHTML = "<label>Day:</label> ";
selectHTML += "<select>";
for (i = 0; i < Options.length; i = i + 1) {
selectHTML += "<option value='" + Options[i] + "'>" + Options[i] + "</option>";
}
selectHTML += "</select>";
document.getElementById("DomContainer").innerHTML = selectHTML;
}
For example <div id="new_drop">//Display the drop down here </div>
Simply add a second parameter to AddDropDown for passing the ID of the container to which you want to insert your dropdown list:
function AddDropDown(Options, containerId) {
...
document.getElementById(containerId).innerHTML = selectHTML;
Then call it like this:
AddDropDown(Options, "new_drop");
(if I understand you correctly)
No need to remove and append elements from the DOM, just replace the existing element contents ... here's a simplified version.
// if "SelectedIndex" is one of the values in the array provided
if ($.inArray(SelectedIndex, [2,5,7])) {
$("#DomContainer").html("<label>Day:</label> "+inject_dropdown(28));
}
// Creates and returns a new drop-down based on the "length" provided
function inject_dropdown(length){
var selectHTML = "<select>";
for( i=1; i<=length; i++ ){
selectHTML += "<option value='" + i + "'>" + i + "</option>"
}
selectHTML += "</select>"
return selectHTML;
}
Replace the $('#DomContainer') selector with whatever selector identifies the place you want the new drop-down to appear.

Table Navigation and row selection

I have an HTML table which contains about 1000 rows and 26 columns. I am using this jQuery plugin to navigate between rows and make a selection.
My first problem is that the plugin is working fine, but—even using the latest version (0.6.1)—it's very slow when working with 1000 rows.
My second problem is that I want to create a JSON object representing the selected row from the table. I wrote a function that does this, but again it's too slow on such a big table. The following code works, but I want to optimise it:
$(document).bind("keyup", function(event) {
var jsonText = "";
var i = 0;
var td_size = $("tr.selected td").size();
jsonText += "{";
for (i = 0; i < td_size; i++) {
if (i < td_size - 1) {
if (i == 0) {
// Get link URL.
jsonText += "\"" + $("thead tr th").eq(i).text() + "\":\"" + $("tr.selected td").eq(i).find("a").attr("href") + "\",";
} else {
jsonText += "\"" + $("thead tr th").eq(i).text() + "\":\"" + $("tr.selected td").eq(i).text() + "\",";
}
}
else {
jsonText += "\"" + $("thead tr th").eq(i).text() + "\":\"" + $("tr.selected td").eq(i).text() + "\"";
}
}
jsonText += "}";
$('#content').html('').append(jsonText);
});
Any suggestions please?
One thing you can do is optimize your jQuery selectors to help the Sizzler work faster...
instead of biding on keyup of all document, how about keyup of a specific tr?
$("tr.selected td").size(); // slow
$("table").find(".selected").find("td"); // probably faster
Save the selected tr outside the loop, you're asking the sizzler to find your object 26 times by looping 1000 rows!
$("thead tr th").eq(i) // on every loop element? slow, try saving the information before the keyup event, they are not going anywhere are they?
So probably something like this would be faster:
var $allTrs = $("tr");
var $allHeads = $("thead tr th");
$allTrs.bind("keyup", function(event) {
var jsonText = "";
var i = 0;
var $t = $(this),
$alltds = $t.find("td"),
td_size = $alltds.length();
jsonText += "{";
$.each($alltds, function(i){
jsonText += "\"" + $allHeads.eq(i).text() + "\":\"";
if (i == 0){ // you have a strange condition, will leave it up to u
// append link
jsonText += $(this).find("a").attr("href"); // i remove "" for better readability
}else{
// append text
jsonText += $(this).text();
}
});
jsonText += "}";
$('#content').text(jsonText); // cheaper than html
});
I have not tested this yet.
You can also create a json object directly (wouldn't affect how fast though), like this
var mynewjson = {};
Then inside a loop:
mynewjson[name] = value;

Categories