Convert jQuery script to standalone javascript - javascript

Is it possible for this jQuery code to run as a standalone javascript? This is the only javascript I'd like to use in my project so I'd prefer not to load the entire jquery library just for this 1k script.
//chris coyier's little dropdown select-->
$(document).ready(function() {
//build dropdown
$("<select />").appendTo("nav.primary");
// Create default option "Go to..."
$("<option />", {
"selected": "selected",
"value" : "",
"text" : "Go to..."
}).appendTo("nav select");
// Populate dropdowns with the first menu items
$("div#brdmenu ul li a").each(function() {
var el = $(this);
$("<option />", {
"value" : el.attr("href"),
"text" : el.text()
}).appendTo("nav.primary select");
});
//make responsive dropdown menu actually work
$("nav.primary select").change(function() {
window.location = $(this).find("option:selected").val();
});
});
I've tried to find previous answers but most questions are for converting to jquery and not vice-versa :)

It is obviously possible to do those things in straight javascript, but there is no way (that I am aware of) to automatically do that conversion. You will have to go through line by line and do the conversion yourself.

Here is something similar to market's answer. I'm assuming you want to get all the links in UL elements inside the brdmenu element. If you only want the first link on the LI elements, just adjust the loop that gets them.
Also, this is not a good idea. Using select elements for links went out of fashion a long time ago, users much prefer real links. Also, when navigating the options using cursor keys in IE, a change event is dispatched every time a different option is selected so users will only get to select the next option before being whisked away to that location. Much better to add a "Go" button that they press after selecting a location.
The main change is to use an ID to get the nav.primary element, which I assume is a single element that you should be getting by ID already.
function doStuff() {
function getText(el) {
return el.textContent || el.innerText;
}
var div, link, links, uls;
// Use an ID to get the nav.primary element
var navPrimary = document.getElementById('navPrimary');
// Create select element and add listener
var sel = document.createElement('select');
sel.onchange = function() {
if (this.selectedIndex > 0) { // -1 for none selected, 0 is default
window.location = this.value;
}
};
// Create default option and append to select
sel.options[0] = new Option('Go to...','');
sel.options[0].setAttribute('selected','');
// Create options for the links inside #brdmenu
div = document.getElementById('brdmenu');
uls = div.getElementsByTagName('ul');
for (var i=0, iLen=uls.length; i<iLen; i++) {
links = uls[i].getElementsByTagName('a');
for (var j=0, jLen=links.length; j<jLen; j++) {
link = links[j];
sel.appendChild(new Option(getText(link), link.href));
}
}
// Add select to page if found navPrimary element
if (navPrimary) {
navPrimary.appendChild(sel);
}
}
window.onload = doStuff;
It's only 28 lines of actual code, which is only 10 more than the original, doesn't require any supporting library and should work in any browser in use (and most that aren't).

Have a go with this.
The one thing I'm leaving out is $(document).ready, but there are a number of solutions for that available on stackoverflow. It's a surprisingly large amount of code!
But the other functionality:
// build the dropdown
var selectElement = document.createElement('select');
var primary = document.getElementsByClassName('primary')[0];
// create a default option and append it.
var opt = document.createElement('option');
var defaultOpt = opt.cloneNode(false);
defaultOpt.selected = true;
defaultOpt.value = "";
defaultOpt.text = "Go to...";
selectElement.appendChild(defaultOpt);
// populate the dropdown
var brdmenuUl = document.getElementById('brdmenu').getElementsByTagName('ul')[0];
var listItems = brdmenuUl.getElementsByTagName('li');
for(var i=0; i<listItems.length; i++){
var li = listItems[i];
var a = li.getElementsByTagName('a')[0];
var newOpt = opt.cloneNode(false);
newOpt.value = a.href;
newOpt.text = a.innerHTML;
selectElement.appendChild(newOpt);
}
// now listen for changes
if(selectElement.addEventListener){
selectElement.addEventListener('change', selectJump, false);
}
else if(selectElement.attachEvent){
selectElement.attachEvent('change', selectJump);
}
function selectJump(evt){
window.location = evt.value;
}
primary.appendChild(selectElement);​
some notes!
We're not looking specifically for nav.primary, we're just finding the first occurrence of something with class .primary. For best performance, you should add an ID to that element and use getElementById instead.
Similarly with the lists in #brdmenu, we look for the first UL, and the first A inside each LI. This isn't exactly what the jQuery does, if you are going to need to iterate more than one UL inside #brdmenu you can use another for loop.
I think that should all work though, there's a fiddle here

Related

exchanging values in a select list with jQuery

I'm trying to swap select option values with jQuery when a links clicked, at the moment its just resetting the select when the links clicked, not sure what's going wrong?:
jQuery:
$(function () {
$("#swapCurrency").click(function (e) {
var selectOne = $("#currency-from").html();
var selectTwo = $("#currency-to").html();
$("#currency-from").html(selectTwo);
$("#currency-to").html(selectOne);
return false;
});
});
JS Fiddle here: http://jsfiddle.net/tchh2/
I wrote it in a step-by-step way so it is easier to understand:
$("#swapCurrency").click(function (e) {
//get the DOM elements for the selects, store them into variables
var selectOne = $("#currency-from");
var selectTwo = $("#currency-to");
//get all the direct children of the selects (option or optgroup elements)
//and remove them from the DOM but keep events and data (detach)
//and store them into variables
//after this, both selects will be empty
var childrenOne = selectOne.children().detach();
var childrenTwo = selectTwo.children().detach();
//put the children into their new home
childrenOne.appendTo(selectTwo);
childrenTwo.appendTo(selectOne);
return false;
});
jsFiddle Demo
Your approach works with transforming DOM elements to HTML and back. The problem is you lose important information this way, like which element was selected (it is stored in a DOM property, not an HTML attribute, it just gives the starting point).
children()
detach()
appendTo()
That happens because you remove all elements from both <select> fields and put them as new again. To make it working as expected you'd better move the actual elements as follows:
$("#swapCurrency").click(function(e) {
var options = $("#currency-from > option").detach();
$("#currency-to > option").appendTo("#currency-from");
$("#currency-to").append(options);
return false;
});
DEMO: http://jsfiddle.net/tchh2/2/
You are replacing the whole HTML (every option) within the <select>. As long as each select has the same amount of options and they correspond to each other, you can use the selected index property to swap them:
$("#swapCurrency").click(function (e) {
var selOne = document.getElementById('currency-from'),
selTwo = document.getElementById('currency-to');
var selectOne = selOne.selectedIndex;
var selectTwo = selTwo.selectedIndex;
selOne.selectedIndex = selectTwo;
selTwo.selectedIndex = selectOne;
return false;
});
JSFiddle

Appending to a select leaks memory JavaScript JQuery

I have a select drop down menu, every time I refresh my page I have to re populate that select drop down. Which is resulting in a memory leak. This is the code any help would be great in refactoring the code. Also I have tried to make another method and calling it before this one, the other method would empty the options array and make it null. That did not help me.
var option = $(document.createElement("option"));
option.attr("value", List.id);
option.text(List.name);
if(List.name.length > maxSize) {
maxSize = List.name.length;
}
this.options.push(option);
//Mark the currently displayed list as the selected option
if (activeListId > 0) {
if (activeListId == List.id) {
option.attr("selected", true);
}
}
}
Toolbar.ListSelect.append(this.options);
It would be very helpful if you included more of the surrounding code so that we could know what is what, but here's my best shot at it given the current situation.
// Reference box
var $box = $('#id-of-select-box');
// Clear select box
$box.empty();
// START LOOP
// Create new option
var $option = $('<option value="'+List.id+'">"'+List.name+'"</option>');
// Append option to select box
$box.append($option);
// END LOOP
//Mark the currently displayed list as the selected option
if (activeListId > 0) {
$box.val(activeListId);
}
I whould suggest to create a new Element, then cut the provided name if exceeds thet maxSize using slice). Later we add the parameter "selected" if there is a match on activeListId and List.id. Latter we append the new option to Toolbar.ListSelect (I suposse it to be the element
var option = jQuery("<option />").attr('value', List.id);
var optionName = List.name.slice(maxSize);
option.text(optionName);
if ( activeListId && activeListId == List.id)
option.attr("selected", true);
option.appendTo(Toolbar.ListSelect)

Rangy: How can I get the span element that is created using the Highlighter module?

I am using the highlighter module available in Rangy, and it work great in creating a highlight for the text that is selected.
In terms of changes to the html, the selected text is replaced by a span tag like the following for example:
the selected text is <span class="highlight">replaced by a span tag</span> like the
What I want to do is get a reference to the span element once it has been created so I can do some other stuff with it. How can this be done?
Please note there may be other spans with or without the highlight tag elsewhere, so these cannot be used to find it.
The important part of the code I have to create the highlight for the selected text is:
var highlighter = null;
var cssApplier = null;
rangy.init();
cssApplier = rangy.createCssClassApplier("highlight", { normalize: true });
highlighter = rangy.createHighlighter(document, "TextRange");
highlighter.addClassApplier(cssApplier);
var selection = rangy.getSelection();
highlighter.highlightSelection("highlight", selection);
I was waiting for #TimDown to update his answer with working code. But as he hasn't done that then I will post some myself (which is based on his answer).
The following function will return an array of highlight elements that have been creating, assuming the selection is still valid:
function GetAllCreatedElements(selection) {
var nodes = selection.getRangeAt(0).getNodes(false, function (el) {
return el.parentNode && el.parentNode.className == "highlight";
});
var spans = [];
for (var i = 0; i < nodes.length; i++) {
spans.push(nodes[i].parentNode);
}
return spans;
}
There is no guarantee that only one <span> element will be created: if the selection crosses element boundaries, several spans could be created.
Anyway, since the selection is preserved, you could use the getNodes() method of the selection range to get the spans:
var spans = selection.getRangeAt(0).getNodes([1], function(el) {
return el.tagName == "SPAN" && el.className == "highlight";
});

Attaching change() even listeners to select/dropdown dynamically

I'm creating 3 dropdowns/select boxes on the fly and insert them in the DOM through .innerHTML.
I don't know the ID's of the dropdowns until I created them in Javascript.
To know which dropdowns have been created, I create an array where I store the ID's of the dropdowns I have created.
for(var i=0; i<course.books.length; i++)
{
output+="<label for='book_"+course.books[i].id+"'>"+ course.books[i].name +"</label>";
output+="<select id='variant"+course.books[i].id+"' name='book_"+course.books[i].id+"'>";
output+="<option value='-'>-- Select one --</option>";
for(var j=0; j<course.books[i].options.length; j++)
{
output+="<option value='"+course.books[i].options[j].id+"'>"+course.books[i].options[j].name+"</option>";
}
output+="</select>";
}
Now I have an array with 3 id's like:
dropdown1
dropdown2
dropdown3
What I want to accomplish with Javascript (without using jQuery or another framework) is to loop over these 3 dropdowns and attach a change event listener to them.
When a user changes the selection in one of these dropdown, I want to call a function called updatePrice for example.
I'm a bit stuck on the dynamic adding of event listeners here.
Now you have added your code its straight forward and you can ignore my verbose answer !!!
output+="<select id='variant"+course.books[i].id+"' name='book_"+course.books[i].id+"'>";
could become :
output+="<select onchange="updatePrice(this)" id='variant"+course.books[i].id+"' name='book_"+course.books[i].id+"'>";
This will call the updatePrice function, passing the select list that changed
However
IMO its far better (from a performance point of view for a start) to create elements in the DOM using the DOM.
var newSelect = document.createElement("select");
newSelect.id = "selectlistid"; //add some attributes
newSelect.onchange = somethingChanged; // call the somethingChanged function when a change is made
newSelect[newSelect.length] = new Option("One", "1", false, false); // add new option
document.getElementById('myDiv').appendChild(newSelect); // myDiv is the container to hold the select list
Working example here -> http://jsfiddle.net/MStgq/2/
You got the array already? Then you can do this:
function updatePrice()
{
alert(this.id + " - " + this.selectedIndex);
}
var list = ["dropdown1", "dropdown2"];
for(var i=0;i<list.length;i++)
{
document.getElementById(list[i]).onchange = updatePrice;
}
Fiddle: http://jsfiddle.net/QkLMT/3/
That won't work across browsers.
You'll want something like
for(var i = 0; i < list.length; i++)
{
$("#"+list[i]).change(updatePrice);
}
in jquery.

Adding value from one list to another depanding on button clicked

I have two multi lists. In first multi list, i got all the attributes of table by using query then now by selecting one attribute from this list, when i click on "ADD" button i want that copy of this attribute should go into another list.
What i have done is i added javascript onclick function for ADD button in that i got the selected value from first multilist. But now I am not getting how to put that value in to second multi list?
What i have done in java script function is:
var index=document.getElementById("List1").selectedIndex;
var fieldval=document.getElementById("List1").options[index].value;
document.getElementById("List2").options[0].value=fieldvalue;
But this is not working. Temporarily I am adding value at first position.
Thanks in advance.
From here:
If you want to move an element from the first list to the second:
var index=document.getElementById("List1").selectedIndex;
var elOpt = document.getElementById('List1').options[index];
var elSel = document.getElementById('List2');
try {
elSel.add(elOpt, null); // standards compliant; doesn't work in IE
}
catch(ex) {
elSel.add(elOpt); // IE only
}
If you want to add one:
var index=document.getElementById("List1").selectedIndex;
var elOpt = document.getElementById('List1').options[index];
var elSel = document.getElementById('List2');
var elOptNew = document.createElement('option');
elOptNew.text = elOpt.text;
elOptNew.value = elOpt.value;
try {
elSel.add(elOptNew, null); // standards compliant; doesn't work in IE
}
catch(ex) {
elSel.add(elOptNew); // IE only
}

Categories