Basic JS + WebDev help - javascript

I have a little Problem. I have seven <select>'s. The go from left to right counting up.
<select id="sel_1" onchange="evalonsubmit('sel_1',1);">
<select id="sel_2" onchange="evalonsubmit('sel_2',2);">
That goes from 1 to 7 in this way.
The logic is easy. On click check if the value is -1 if it is disable everything on the right and set it to -1. if it is not -1 then enable the the right of the clicked one (+1 so to say)
And that's the code:
function evalonsubmit(ID, n)
{
var ElementID = document.getElementById(ID);
if(ElementID.value = -1) {
for (var i = n + 1; i <= 7; i++){
var newID = "sel_" + i;
var newValue = document.getElementById();
newValue.disable = true;
newValue.value = -1
}
} else {
var newID = "sel_"+(n+1)
var newValue = document.getElementById();
newValue.disable = false;
}
}
Can somebody kind JS hacker help me?

I just fixed some simple mistakes in your code ..
function evalonsubmit(ID, n)
{
var ElementID = document.getElementById(ID);
if (ElementID.value == -1){
for (var i=n+1; i <= 7; i++){
var newID = "sel_" + i;
var newValue = document.getElementById(newID);
newValue.disable = true;
newValue.value = -1
}
} else {
var newID = "sel_"+(n+1)
var newValue = document.getElementById(newID);
newValue.disable = false;
}
}

Not quite sure what you want, but it probably should be:
if (ElementID.value == -1){
// ^--- two = , otherwise you assign the value
and
var newID = "sel_" + i;
var newValue = document.getElementById(newID);
// pass parameter ---^
Same in the else branch.
Besides that, I would give your variables more meaningful names. E.g. ElementID lets you assume that the value is an ID. But it is not. It is a DOM element. Same for newValue.

You're missing the parameter in a couple of your calls to document.getElementById, and the property for disabling a <select> is disabled, not disable. You also have = where you need ==.
function evalonsubmit(ID, n)
{
var ElementID = document.getElementById(ID);
if (ElementID.value == -1){
for (var i=n+1; i <= 7; i++){
var newID = "sel_" + i;
var newValue = document.getElementById(newID);
newValue.disabled = true;
newValue.value = -1;
}
} else {
var newID = "sel_"+(n+1);
var newValue = document.getElementById(newID);
newValue.disabled = false;
}
}

Why not do this:
HTML:
<div class="wrapper">
<select onchange="evalonsubmit(this);" />
<select onchange="evalonsubmit(this);" />
<select onchange="evalonsubmit(this);" />
</div>
JS:
function nextElement(current)
{
do
current = current.nextSibling;
while (current && current.nodeType != 1);
return current;
}
function evalonsubmit(elem)
{
if(elem.value == -1)
while(elem = nextElement(elem)) {
elem.disabled = true;
elem.value = -1
}
else if(elem = nextElement(elem))
elem.disabled = false;
}
That removes the need for ids on the <select> elements, as following elements can be grabbed with .nextSibling. The nextElement() function is to avoid grabbing text nodes.

Related

How to optimise RadComboBox clearItems function

I have a MultiSelectDropDown, that is, several RadComboBox controls are used in a combined way. For example, I can have a dropdown for regions, another for depots and another for user. The idea is to change the content of lower levels dynamically whenever items are selected or unselected on a higher level. The problem is that in the case when many items are selected, this becomes brutally slow due to some Telerik functions, but I do not understand why. This is a chunk from the client-side of the MultiSelectDropDown prototype:
changeLowerLevels: function (valueIndex, values, value) {
if (!this.canChange) return;
//Get selected values from combobox
var combo = $find(this.ddlIDs[valueIndex - 1]);
var cbItems = combo.get_checkedItems();
var selectedItems = [];
var change = null;
var counter = 0;
if (cbItems.length) this.filterString = "";
for (var i = 0; i < cbItems.length; i++) {
counter++;
if (this.filterString == "") this.filterString = cbItems[i].get_text();
selectedItems.push(cbItems[i].get_value());
}
if (counter > 1) this.filterString += " with " + (counter - 1) + " other" + ((counter > 2) ? "s" : "");
if (JSON.stringify(selectedItems) === JSON.stringify(this.selectedItems[valueIndex - 1]) || selectedItems == [])
return;
this.selectedItems[valueIndex - 1] = selectedItems;
var controlObject = this;
var combo = $find(this.ddlIDs[valueIndex]);
var comboItems = combo.get_items();
if(!this.disabled) combo.enable();
combo.clearItems();
if (valueIndex == 1) this.twoLevelCache = values;
var val = values;
//break if all items are found
var nrOfSelectedItems = this.selectedItems[valueIndex - 1].length;
var nrOfFoundItems = 0;
var index = 0;
var indexes = [];
var found = false;
while (nrOfFoundItems < nrOfSelectedItems && val[index] !== undefined) {
found = (this.selectedItems[valueIndex - 1].indexOf(val[index].Value) != -1);
if (!(found))
index++;
else {
indexes.push(index)
nrOfFoundItems++;
index++;
}
}
//separators from valuesIndex - 1 level
var controlObject = this;
for (var i = 0; i < indexes.length; i++) {
var separator = new Telerik.Web.UI.RadComboBoxItem();
separator.set_text("<span><a class=\"checkAll tt-multi-uncheck-icon\" index=\"" + index + "\">U</a>" + $find(this.ddlIDs[valueIndex - 1]).findItemByValue(val[indexes[i]].Value).get_text() + "</span>");
separator.set_value("");
separator.set_isSeparator(true);
comboItems.add(separator);
this.twoLevelCache.push(val[indexes[i]].Levels);
//valuesIndex level
var valuesArray = val;
var comboItem = new Telerik.Web.UI.RadComboBoxItem();
for (var depot in valuesArray[indexes[i]].Levels) {
comboItem = new Telerik.Web.UI.RadComboBoxItem();
comboItem.set_text(valuesArray[indexes[i]].Levels[depot].Name);
comboItem.set_value(valuesArray[indexes[i]].Levels[depot].Value);
comboItems.add(comboItem);
comboItem = null;
}
$('#' + this.ddlIDs[valueIndex] + '_DropDown a.checkAll').unbind().on("click", function () {
checkAllLowerItems(this, controlObject.ddlIDs[valueIndex]);
});
}
combo.set_emptyMessage(this.allText);
//$("#" + this.ddlIDs[valueIndex]).html(returnValue);
if (this.ddlIDs.length > valueIndex + 1) {
var paramToPass = (((val == undefined) || (val[index] === undefined)) ? ("") : (val[index]));
if (this.allText.length > 0)
this.changeLowerLevels(valueIndex + 1, paramToPass, "");
else {
if (paramToPass !== "")
paramToPass = paramToPass.Levels;
if ((val[index] == undefined) || (val[index].Levels[0] === undefined) || (val[index].Levels[0].Value === "")) {
this.changeLowerLevels(valueIndex + 1, paramToPass, "");
}
else {
this.changeLowerLevels(valueIndex + 1, paramToPass, val[index].Levels[0].Value);
}
}
}
else {
if (this.allText.length > 0)
this.selectedItems[valueIndex] = "";
else
if ((val[index] == undefined) || (val[index].Levels[0] === undefined) || (val[index].Levels[0].Value === "")) {
this.selectedItems[valueIndex] = "";
}
else {
this.selectedItems[valueIndex] = val[index].Levels[0].Value;
}
}
this.setText();
}
combo.clearItems() is extremeley slow. I have take a look on how it is implemented:
function (){var f=this._parent._getControl();?if(f._checkBoxes){f._checkedIndicesJson="[]";?f._checkedIndices=[];?var g=f.get_items();?for(var d=0,e=g.get_count();?d<e;?d++){var c=f.get_items().getItem(d);?c.set_checked(false);?}f.updateClientState();?}a.RadComboBoxItemCollection.callBaseMethod(this,"clear");?}
How can I make sure that this Javascript function speeds up?
I have finally solved the problem by rewriting Telerik client-side functionalities. It was a long and difficult debugging, but it yielded a large performance boost in the most difficult circumstances. From ~30 000 milliseconds, to ~300. Let's see the parts of the optimization:
The actual rewrite
/* Overriding Telerik functions Start */
var overridenTelerikControls = false;
function overrideTelerikFunctionalities() {
if (!overridenTelerikControls) {
overridenTelerikControls = true;
Telerik.Web.UI.RadComboBox.prototype.clearItems = function (isMultiSelectDropDown) {
this.get_items().clear(isMultiSelectDropDown);
this._itemData = null;
};
Telerik.Web.UI.RadComboBoxItemCollection.prototype.clear = function (isMultiSelectDropDown){
var f=this._parent._getControl();
if(f._checkBoxes){
f._checkedIndicesJson="[]";
f._checkedIndices=[];
var g = f.get_items();
for(var d=0,e=g.get_count();d<e;d++){
var c=f.get_items().getItem(d);
c.set_checked(false, isMultiSelectDropDown);
}
if (isMultiSelectDropDown) {
f._updateComboBoxText();
if (f._checkAllCheckBoxElement != null) {
f._updateCheckAllState();
}
}
f.updateClientState();
}
Telerik.Web.UI.RadComboBoxItemCollection.callBaseMethod(this, "clear");
};
Telerik.Web.UI.RadComboBoxItem.prototype.set_checked = function (d, isMultiSelectDropDown){
if(!this.get_enabled()){
return;
}
this._setChecked(d);
var c=this.get_comboBox();
if(c){
if(d){
c._registerCheckedIndex(this.get_index());
}else{
c._unregisterCheckedIndex(this.get_index());
}
if (!isMultiSelectDropDown) {
c._updateComboBoxText();
}
if((!isMultiSelectDropDown) && (c._checkAllCheckBoxElement!=null)){
c._updateCheckAllState();
}
}
};
}
}
/* Overriding Telerik functions End*/
My approach was to keep the old way of their working by default, but if an isMultiSelectDropDown parameter is passed, then work in the optimized manners. So we have a switch materialized as a parameter and we can turn it on/off. The main difference was that the old way was to change the label text showing the selected elements each time a checkbox is checked/unchecked. The main improvement was to do this change after all the checkboxes were checked/unchecked. This extremely simple idea was the driving force behind the boost of performance.
Actual usage
overrideTelerikFunctionalities();
combo.clearItems(true);
This was the functionalities were overriden if they were not already and the parameter was true, therefore the new approach was chosen.
Test, test, test

Interactive Quiz: How to keep input values when hidden?

I've created an interactive quiz and created functions that showed the next question and goes back to the previous questions. My problem is that when it changes questions, the information I input in is erased. For example Question 1 and 2, I would write in an animal and then I go onto Question 3, but when I go back to Question 1 and 2, the animals I wrote in are gone. Same with the radio choices. Sorry if code is tedious, I'm just starting. Any tips on how I can fix that?
Quiz link: https://repl.it/GSiI/latest
function initialize()
{
questionList = document.getElementsByClassName("questions");
quizOutput = document.getElementById("showQuiz");
beginBtn = document.getElementById("initiate");
button = document.getElementById("button");
next = document.getElementById("next");
previous = document.getElementById("previous");
questionIndex = 0;
totalQuestions = questionList.length - 1;
}
function beginQuiz()
{
currentQuestion = questionList.item(questionIndex).innerHTML;
button.style.visibility = "visible";
quizOutput.innerHTML = currentQuestion;
beginBtn.style.display = "none";
quizOutput.style.display = "block";
}
function changeQuestion(factor)
{
if(factor == -1 && questionIndex > 0)
{
questionIndex--;
currentQuestion = questionList.item(questionIndex).innerHTML;
quizOutput.innerHTML = currentQuestion;
}
if(factor == 1 && questionIndex < totalQuestions)
{
questionIndex++;
currentQuestion = questionList.item(questionIndex).innerHTML;
quizOutput.innerHTML = currentQuestion;
}
}
function writeNumber(el, num)
{
input = document.getElementById(el);
if(input.value.length < 2)
{
input.value += num;
}
}
function clearAnswer(el)
{
document.getElementById(el).value = "";
}
function takeValues()
{
var x = document.getElementById("frm1");
var text = "";
var i;
for (i = 0; i < x.length ;i++)
{
text += x.elements[i].value + "<br>";
}
document.getElementById("demo").innerHTML = text;
}
Its because every time you load a different question, you are actually removing the DOM elements without saving them. When you return to the previous questions, you aren't loading their values from anywhere. You need to build a state into your app for it to work.
I will suggest using javascript FormData object to get entries of input values .
First removing all the "form" elements from your html but keep their inner elements.
Then make "showQuiz" div into a form element.
Then create 1 single form ( I set this form to have id "form1") to contain all the questions and the submit button .
Then modify the javascript function changeQuestion as follow:
function changeQuestion(factor)
{
var myform = document.getElementById("showQuiz");
var fdata = new FormData(myform);
var storeForm = document.getElementById("form1");
var sdata = new FormData(storeForm);
for (var pair of fdata.entries()) {
var elem = document.getElementsByName(pair[0])[0];
storeForm.elements[pair[0]].value = pair[1];
}
if(factor == -1 && questionIndex > 0)
{
questionIndex--;
currentQuestion = questionList.item(questionIndex).innerHTML;
quizOutput.innerHTML = currentQuestion;
}
if(factor == 1 && questionIndex < totalQuestions)
{
questionIndex++;
currentQuestion = questionList.item(questionIndex).innerHTML;
quizOutput.innerHTML = currentQuestion;
}
myform = document.getElementById("showQuiz");
storeForm = document.getElementById("form1");
fdata = new FormData(myform);
sdata = new FormData(storeForm);
for (var pair of sdata.entries()) {
var fld = myform.elements[pair[0]];
if (fld)
fld.value = pair[1];
}
}

why dosn't this onchange work

I am trying to work out a simple problem in js. I can't figure out why my speed method is not being called. I've inserted console.log() to check if every other method works and turns out it does. I've inserted code from html and js. It is a selection list, if i select a different value, speed method should be called, but it never does. Any help is appreciated.
(function() {
"use strict";
window.onload = function() {
document.getElementById("startbutton").onclick = displayWords;
document.getElementById("stopbutton").onclick = stop;
document.getElementById("speedMenu").onchange = speed;
};
var timer = null;
var speed = 171;
var count = 0;
function displayWords() {
console.log(" displayWords is called");
document.getElementById("stopbutton").disabled = false;
document.getElementById("startbutton").disabled = true;
document.getElementById("stopbutton").classList.remove("buttonBehaviour");
document.getElementById("startbutton").classList.add("buttonBehaviour");
document.getElementById("input").disabled = true;
timer = setInterval(display,speed,punctuation());
}
function stop() {
console.log(" stop is called");
document.getElementById("startbutton").disabled = false;
document.getElementById("stopbutton").disabled = true;
document.getElementById("stopbutton").classList.add("buttonBehaviour");
document.getElementById("startbutton").classList.remove("buttonBehaviour");
document.getElementById("display").innerHTML = "";
clearInterval(timer);
document.getElementById("input").disabled = false;
count = 0;
}
function speed() {
console.log(" speed is called");
var value = document.getElementById("speedMenu").options[document.getElementById("speedMenu")].value;
console.log(value);
clearInterval(timer);
var list = punctuation();
for(var i = 0; i < count ;i++) {
list.shift();
}
timer = setInterval(display,value,list);
}
function punctuation () {
console.log(" pun is called");
var words = document.getElementById("input").value.split(/[ \t\n]+/);
var list = [];
for (var i = 0; i < words.length; i++) {
var word = words[i];
var lastChar = word.charAt(word.length - 1);
if(lastChar === "," || lastChar === "." || lastChar === "!" || lastChar === "?" || lastChar === ";" || lastChar === ":") {
word = word.substring(0,word.length - 1);
list.push(word);
list.push(word);
} else {
list.push(word);
}
};
return list;
}
function display(words) {
count++;
console.log(" display is called");
document.getElementById("display").innerHTML = words.shift();
if(document.getElementById("med").checked) {
document.getElementById("display").style.fontSize = "36pt";
} else if(document.getElementById("big").checked) {
document.getElementById("display").style.fontSize = "48pt";
} else if(document.getElementById("bigger").checked) {
document.getElementById("display").style.fontSize = "60pt";
}
if( words.length == 0) {
clearInterval(timer);
}
}
}) ();
HTML code is following for the tag and method
<select id = "speedMenu">
<option value = "500">50 wpm</option>
<option value = "200">300 wpm</option>
<option value = "171" selected="selected">350 wpm</option>
<option value = "150">400 wpm</option>
<option value = "133">450 wpm</option>
<option value = "120">500 wpm</option>
</select>
You have a variable named speed and a function named speed. You have a name collision.
This is the minimal example of your code:
window.onload = function () {
console.log(speed);
};
var speed = 171;
function speed(){
}

Multiplying variables and showing result in a box

I'm having a problem when trying to multiply the totalPallets by the price-per-pallet ($25) and then showing that in the productSubTotal box. With the code as it is right now, the quatity total shows but when I try to get the price result, it doesn't show the operation. Also, if I try changing anythung from the code, the whole thing breaks down. I'll be thankful if anyone could help me. Thanks
// UTILITY FUNCTIONS
function IsNumeric(n) {
return !isNaN(n);
}
function calcTotalPallets() {
var totalPallets = 0;
$(".num-pallets-input").each(function() {
var thisValue = parseInt($(this).val());
if ( (IsNumeric(thisValue)) && (thisValue != '') ) {
totalPallets += parseInt(thisValue);
};
});
$("#quantitytotal").val(totalPallets);
}
function calcProdSubTotal() {
var prodSubTotal = 0;
$(".totalprice").each(function() {
var valString = parseInt(totalPallets) * multiplier;
prodSubTotal += parseInt(valString);
});
$("#product-subtotal").val(CommaFormatted(prodSubTotal));
};
// "The Math" is performed pretty much whenever anything happens in the quanity inputs
$('.num-pallets-input').bind("focus blur change keyup", function(){
// Caching the selector for efficiency
var $el = $(this);
// Grab the new quantity the user entered
var numPallets = CleanNumber($el.val());
var totalPallets = CleanNumber($el.val());
var prodSubTotal = CleanNumber($el.val());
// Find the pricing
var multiplier = $el
.parent().parent()
.find("td.price-per-pallet span")
.text();
};
// Calcuate the overal totals
calcProdSubTotal();
calcTotalPallets();
});
function CommaFormatted(amount) {
var delimiter = ",";
var i = parseInt(amount);
if(isNaN(i)) { return ''; }
i = Math.abs(i);
var minus = '';
if (i < 0) { minus = '-'; }
var n = new String(i);
var a = [];
while(n.length > 3)
{
var nn = n.substr(n.length-3);
a.unshift(nn);
n = n.substr(0,n.length-3);
}
if (n.length > 0) { a.unshift(n); }
n = a.join(delimiter);
amount = "$" + minus + n;
return amount;
}
});

javascript function for calculating

I meet a trouble with a function. actually I need to make this function to perform a calculation on some text fields. When I worked on a single line no problems. But recently, someone asked to make a table with multiple lines (one line can be added dynamically) so, I do the following function so that it can not only duplicate line but id change all the fields concerned, so I add class to these fields. therefore I proceed as follows:
function clone(line) {
newLine = line.cloneNode(true);
line.parentNode.appendChild(newLine);
var tab = document.getElementsByClassName('libelle_debours')
var i = -1;
while (tab[++i]) {
tab[i].setAttribute("id", "_" + i);
};
var cab = document.getElementsByClassName('ht_no_tva')
var j = -1;
while (cab[++j]) {
cab[j].setAttribute("id", "_" + j);
};
var dab = document.getElementsByClassName('ht_tva')
var k = -1;
while (dab[++k]) {
dab[k].setAttribute("id", "_" + k);
};
var eab = document.getElementsByClassName('taux')
var l = -1;
while (eab[++l]) {
eab[l].setAttribute("id", "_" + l);
};
var fab = document.getElementsByClassName('tva')
var m = -1;
while (fab[++m]) {
fab[m].setAttribute("id", "_" + m);
};
}
function delRow() {
var current = window.event.srcElement;
//here we will delete the line
while ((current = current.parentElement) && current.tagName != "TR");
current.parentElement.removeChild(current);
}
The problem in fact is the second function that is used to make the calculation:
function calcdebours() {
var taux = document.getElementById('debours_taux_tva').value;
var ht_no_tva = document.getElementById('debours_montant_ht_no_tva').value;
var ht_tva = document.getElementById('debours_montant_ht_tva').value;
var tva = Math.round((((ht_tva) * (taux)) / 100) * 100) / 100;;
if (taux == '') {
taux = 0;
}
if (ht_no_tva == '') {
ht_no_tva = 0;
}
if (ht_tva == '') {
ht_tva = 0;
}
document.getElementById('debours_montant_tva').value = tva;
document.getElementById('debours_montant_ttc').value = (tva) + parseFloat(ht_tva) + parseFloat(ht_no_tva)
}
function
montant_debours() {
var ttc = document.getElementById('debours_montant_ttc').value;
var ttc2 = document.getElementById('debours_montant_ttc2').value;
if (ttc == '') {
var ttc = 0;
} else {
var ttc = document.getElementById('debours_montant_ttc').value;
}
if (ttc2 == '') {
var ttc2 = 0;
} else {
var ttc2 = document.getElementById('debours_montant_ttc2').value;
}
tx = parseFloat(ttc) + parseFloat(ttc2);
document.getElementById('ttc_cheque').value = Math.round(tx * 100) / 100;
}
As Id are not the same, do I have to create as many functions
there are lines?
Is it possible to fit a single function to process each line?
If so can you tell me how?
If I'm not mistaken you can use for loop and append increment to the end of element's id. Like this:
trs = document.getElementById('container Id').getElementsByTagName('tr');
For (var i = 1, i <= trs.length; i++)
{
var el = document.getElementById('debours_montant_ttc' + i);
}

Categories

Resources