3

I have a couple of lines of code in JQuery:

     var central = $('#townid option:contains("Central")');
     if (central.length){
        central.insertAfter('select option:first-child');
     }

How can I rewrite it without using JQuery library just with JavaScript?

1
  • 5
    It's when you try to do things like that that you really appreciate jQuery... Commented Mar 7, 2011 at 12:14

1 Answer 1

6

A correct translation would be something like:

var selects = document.getElementsByTagName('select'),
    options = document.getElementById('townid').getElementsByTagName('option'),
    options = Array.prototype.slice.call(options), //2 lines only for readability
    tmp = document.createDocumentFragment();

for(var i = 0, l = options.length; i < l; i++) {
    var option = options[i],
        text = option.innerText || option.textContent;
    if(text.indexOf('Central') > -1) {
        tmp.appendChild(option);
    }
}

for(var i = 0, l = selects.length; i < l; i++) {
    var select = selects[i],
         opts = select.getElementsByTagName('option');
    if(opts.length > 1) {
        select.insertBefore(tmp.cloneNode(true), opts[1]);
    }
    else {
        select.appendChild(tmp.cloneNode(true));
    }
}

DEMO

This could be simplified a lot depending on the markup (and optimized depending on the browser (e.g. support for querySelectorAll)). E.g. if you know that there will always only be one option that contains "Central" and whether there exists only one select element or not.

Here is a stripped down version for one select element, known size of the list (i.e. > 1) and only one option that contains Central. So basically just reordering the option:

var options = document.getElementById('townid').getElementsByTagName('option');

for (var i = 0, l = options.length; i < l; i++) {
    var option = options[i],
        text = option.innerText || option.textContent;
    if (text.indexOf('Central') > -1) {
        if (i > 1) {
            option.parentNode.insertBefore(option, options[1]);
        }
        break;
    }
}

DEMO

Update:

If the option's text should be exactly Central, compare the text normally:

if(text === 'Central')
Sign up to request clarification or add additional context in comments.

14 Comments

+1 for teaching me something new: stackoverflow.com/questions/2125714/…
@mplungjan: :) It was necessary because adding the option to the DocumentFragment also removes it from the NodeList (as it is live) and messed up with the loop index.
I thought it was because you cannot slice a dom nodelist because it is not an array...
@Felix This syntax one is also new to me: var option = options[i], text = option.innerText || option.textContent; or is it a typo?
@mplungjan: I only use the slice to convert the NodeList to an array. The content of the array does not change, no matter where I add the options in the DOM, but the NodeList does. If I would iterate over the NodeList, then after moving one of the options to the DocumentFragment, the NodeList has one element less and so the iteration is messed up. It is like removing elements from an array while looping over it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.