onchange happen even click on white space of selectbox - javascript

I am just trying to add and remove selectbox items using below code,
$('#moveforzero').val("0");
$('#SelectFeatures').change(function() {
var oSrc = document.getElementById('SelectFeatures');
var oDest = document.getElementById('SelectedFeatures');
var zero = document.getElementsByName('moveforzero')[0].value;
for (var i = 0; i < oSrc.options.length; i++) {
var j=parseInt(zero);
if (oSrc.options[i].selected == true) {
oSrc.options[i].disabled=true;
var NewOption = new Option();
//var selected = oSrc.options[i].value;
NewOption.text = oSrc.options[oSrc.options.selectedIndex].text;
NewOption.value = oSrc.options[oSrc.options.selectedIndex].value;
oDest.options[j] = NewOption;
document.getElementsByName('moveforzero')[0].value=j+1;
}
}
});
$('#SelectedFeatures').change(function(){
var d,f;
var minuone=document.getElementsByName('moveforzero')[0].value;
if(parseInt(minuone)>0)
{
document.getElementsByName('moveforzero')[0].value=parseInt(minuone)-1;
}
else
{
document.getElementsByName('moveforzero')[0].value="0";
}
d=$("#SelectedFeatures option:selected").text();
var len=$("#SelectedFeatures").length;
var g =$("#SelectedFeatures");
//d=selectbox.options[(selectbox.selectedIndex)].text;
var oSrc = document.getElementById('SelectFeatures');
for (var i = 0; i < oSrc.options.length; i++) {
if (oSrc.options[i].disabled==true) {
f=oSrc.options[i].text;
if(d==f)
{
oSrc.options[i].disabled=false;
for(var i = 0; i <len; i++)
{
if($("#SelectedFeatures option["+i+"].selected"))
{
jQuery("#SelectedFeatures option[value='"+d+"']").remove();
}
}
}
}
}
});
My problem is even items removing when click on white space inside the removing selectbox.
check my fiddle :http://jsfiddle.net/Manivasagam/ff5Lp0gv/18/
How to fix this?

As per my understanding, you want to remove option when you select it. Here i solve this using delegate method. refer this JSfIDDLE
$('#SelectedFeatures').delegate('option:selected', 'click',function(){
var d,f;
var minuone=document.getElementsByName('moveforzero')[0].value;
if(parseInt(minuone)>0)
{
document.getElementsByName('moveforzero')[0].value=parseInt(minuone)-1;
}
else
{
document.getElementsByName('moveforzero')[0].value="0";
}
d=$("#SelectedFeatures option:selected").text();
var len=$("#SelectedFeatures").length;
//alert(len);
var g =$("#SelectedFeatures");
//alert(d);
//d=selectbox.options[(selectbox.selectedIndex)].text;
var oSrc = document.getElementById('SelectFeatures');
for (var i = 0; i < oSrc.options.length; i++) {
if (oSrc.options[i].disabled==true) {
f=oSrc.options[i].text;
//alert(f);
if(d==f)
{
//alert("if");
oSrc.options[i].disabled=false;
for(var i = 0; i <len; i++)
{
//alert('for');
if($("#SelectedFeatures option["+i+"].selected"))
{
//alert("remove");
jQuery("#SelectedFeatures option[value='"+d+"']").remove();
}
// if(selectbox.options[i].selected)
//selectbox.remove(i);
}
}
}
}
});

How about:
option {
display: inline;
}
option:after {
content: "\A";
white-space: pre;
}
See this updated fiddle.

This is a version of the solution by #Ferret:
Add a blank <option></option> to the end of your select tag and then change the style of the last (blank) option like so:
option:last-child {
display:inline;
padding:0px;
}
You may want to change the style to only apply to that particular select's last item.
Here's the JSFiddle

Related

Remove all #div id from domtree with class .selected

How to remove all divs with id #divs with class .something with vanilla javascript.
For example:
function removeEl() {
var removeEl = document.querySelectorAll('.selected');
if (removeEl.length > 0) {
for (var i = 0; i < removeEl.length; i++) {
var elem = document.getElementById("box1");
elem.remove();
}
}
}
This will delete all div box1 but I want to delete all box1 with class .selected
Simply use:
for (var i = 0; i < removeEl.length; i++) {
removeEl[i].remove();
}
You already selected all elements which you want to remove. So it's not necessary to select it again with a given id.
function removeEl() {
var removeEl = document.querySelectorAll('.selected');
if (removeEl.length > 0) {
for (var i = 0; i < removeEl.length; i++) {
//var elem = document.getElementById("box1");
removeEl[i].parentNode.removeChild(removeEl[i]);
}
}
}

todolist double click to add class?

I am making a todo list... When the task is finished i need to be able to click it and then add a class to that item... It works but I have to double click.. Any suggestions?
list.onclick = function() {
var list = document.getElementsByTagName('li');
for (var i = 0; i < list.length; i++) {
list[i].onclick = function() {
if (!this.classList.contains("checked") || this.classList.contains("checked")) {
this.classList.add("checked");
} else {
this.classList.remove("checked");
}
}
}
}
As I understand purpose of this function is to check or uncheck list element each time user clicks on it. For this purpose, first of all we need to identify if 'class' exists or not and remove it. In other cases just add that 'class' to classList attribute.
list.onclick = function()
{
var list = document.getElementsByTagName('li');
for (var i = 0; i < list.length; i++)
{
list[i].onclick = function()
{
if (this.classList.contains("checked")
{
this.classList.remove("checked");
}
else
{
this.classList.add("checked");
}
}
}
}

CSS formatting doesn't apply to new tags created by Javascript

I wrote a bunch of JS code to add click listeners to the HTML buttons. I have some CSS that applies to the existing HTML. But the CSS doesn't appear to apply to the HTML generated by the JavaScript.
Link to JSfiddle
As you can see, line 1 has all the proper spacing. But any of the generated lines by clicking any of the three buttons lose the spacing.
Here's the CSS:
.form-block {
padding: 5px;
margin: 5px;
border: 1px solid #000;
span {
padding-right: 15px;
}
}
Thanks for the help in advance! :)
What you see are actual spaces between the elements in your original HTML/row, and then a lack of spaces between the elements in your JS generated elements.
I would either remove the spaces between the elements in your HTML, and use a left/right margin value to create that space instead, or add a space or carriage return/new line between the elements when you add them in your JS.
I removed the spaces (by inserting HTML comments) in your original HTML, and added margin-right: 1em to the input and buttons in your element row.
/*This function interprets the line position.
//input is a lpos string which is in the form of x.x.x.x
//splits it by the '.'
//returns the array with position
*/
function lposToAr(lpos) {
var ar = lpos.split('.');
for (var i = 0; i < ar.length; i++) {
ar[i] = parseInt(ar[i], 10);
}
return ar;
}
//This function turns the position array back into a string
function lposToStr(posAr) {
return posAr.join('.');
}
//This function creates a new line after clicking the NL button.
function NL(lpos, e) {
e.preventDefault();
var cLine = document.getElementsByClassName('line')[0].cloneNode(true);
var cNL = document.getElementsByClassName('new-line')[0].cloneNode(true);
var cNN = document.getElementsByClassName('new-nested')[0].cloneNode(true);
var cI = document.getElementsByClassName('input')[0].cloneNode(true);
cI.value = '';
var cNI = document.getElementsByClassName('new-input')[0].cloneNode(true);
//figure out which position
var posAr = lposToAr(lpos);
var clickNode = document.getElementsByTagName('form')[0];
for (var i = 0; i < posAr.length; i++) {
clickNode = clickNode.children;
var skipCount = 0;
for (var j = 0; j < clickNode.length - 1; j++) {
if (clickNode[j].tagName != 'DIV') {
skipCount++;
}
}
clickNode = clickNode[posAr[i] + skipCount - 1];
}
//set the last element of the posAr the total number of same level <div>+1
var siblingDivCount = 0;
for (var i = 0; i < clickNode.parentNode.children.length; i++) {
if (clickNode.parentNode.children[i].tagName == 'DIV') {
siblingDivCount++;
}
}
var newPosAr = posAr;
newPosAr[newPosAr.length - 1] = siblingDivCount + 1;
//Update the cloned items with the new line info
var newPosStr = lposToStr(newPosAr);
cLine.innerHTML = newPosStr;
cNL.addEventListener('click', function(event) {
NL(newPosStr, event);
});
cNN.addEventListener('click', function(event) {
NN(newPosStr, event);
});
//cI doesn't need to change, unless there's a bug
cNI.addEventListener('click', function(event) {
NI(newPosStr, event);
});
//Make the new Div
var newDiv = document.createElement('div');
newDiv.setAttribute('class', 'form-block');
newDiv.appendChild(cLine);
newDiv.appendChild(cNL);
newDiv.appendChild(cNN);
newDiv.appendChild(cI);
newDiv.appendChild(cNI);
//Add the new Div
clickNode.parentNode.appendChild(newDiv);
}
function NN(lpos, e) {
e.preventDefault();
var cLine = document.getElementsByClassName('line')[0].cloneNode(true);
var cNL = document.getElementsByClassName('new-line')[0].cloneNode(true);
var cNN = document.getElementsByClassName('new-nested')[0].cloneNode(true);
var cI = document.getElementsByClassName('input')[0].cloneNode(true);
cI.value = '';
var cNI = document.getElementsByClassName('new-input')[0].cloneNode(true);
var posAr = lposToAr(lpos);
var clickNode = document.getElementsByTagName('form')[0];
for (var i = 0; i < posAr.length; i++) {
clickNode = clickNode.children;
var skipCount = 0;
for (var j = 0; j < clickNode.length - 1; j++) {
if (clickNode[j].tagName != 'DIV') {
skipCount++;
}
}
clickNode = clickNode[posAr[i] + skipCount - 1];
}
var childDivCount = 0;
for (var k = 0; k < clickNode.children.length; k++) {
if (clickNode.children[k].tagName == 'DIV') {
childDivCount++;
}
}
posAr.push(childDivCount + 1);
//Update the cloned items with the new line info
var newPosStr = lposToStr(posAr);
cLine.innerHTML = newPosStr;
cNL.addEventListener('click', function(event) {
NL(newPosStr, event);
});
cNN.addEventListener('click', function(event) {
NN(newPosStr, event);
});
//cI doesn't need to change, unless there's a bug
cNI.addEventListener('click', function(event) {
NI(newPosStr, event);
});
//Make the new Div
var newDiv = document.createElement('div');
newDiv.className = 'form-block';
newDiv.appendChild(cLine);
newDiv.appendChild(cNL);
newDiv.appendChild(cNN);
newDiv.appendChild(cI);
newDiv.appendChild(cNI);
//Add the new Div
clickNode.appendChild(newDiv);
}
function NI(lpos, event) {
event.preventDefault();
//copy text box
var cI = document.getElementsByClassName('input')[0].cloneNode(true);
cI.value = '';
//find the node that has been clicked
var posAr = lposToAr(lpos);
var clickNode = document.getElementsByTagName('form')[0];
for (var i = 0; i < posAr.length; i++) {
clickNode = clickNode.children;
var skipCount = 0;
for (var j = 0; j < clickNode.length - 1; j++) {
if (clickNode[j].tagName != 'DIV') {
skipCount++;
}
}
clickNode = clickNode[posAr[i] + skipCount - 1];
}
//add the new textbox
clickNode.insertBefore(cI, clickNode.getElementsByClassName('new-input')[0]);
}
document.getElementsByClassName('new-line')[0].addEventListener('click', function(event) {
NL(document.getElementsByClassName('line')[0].innerHTML, event);
});
document.getElementsByClassName('new-nested')[0].addEventListener('click', function(event) {
NN(document.getElementsByClassName('line')[0].innerHTML, event);
});
document.getElementsByClassName('new-input')[0].addEventListener('click', function(event) {
NI(document.getElementsByClassName('line')[0].innerHTML, event);
});
/**
* Add styling to the form to make it look appealing
*/
.form-block {
padding: 5px;
margin: 5px;
border: 1px solid #000;
}
span {
padding-right: 15px;
}
.form-block button, .form-block input {
margin-right: 1em;
}
<!--
DO NOT CHANGE THE CONTENTS OF THIS BLOCK
-->
<form class='myform'>
<div class='form-block'>
<span class='line'>1</span><!--
--><button class='new-line'>New Line</button><!--
--><button class='new-nested'>New Nested Line</button><!--
--><input class='input' type='text' placeholder='Enter Value...'><!--
--><button class='new-input'>Add input</button>
</div>
</form>

How do i convert a Jquery code to Pure javascript

I am using Bootstrap.
I am not able to figure out how to put this in pure javascript.This will open a div when we click on the accordion.
$(function() {
$("#panelTicketsList .list-group-item").on("click", function() {
$("#panelTicketsList .list-group-item").removeClass('selected');
$(this).addClass('selected');
if ($('#panelTicketsList').hasClass('col-md-12')) {
$('#panelTicketsList').removeClass('col-md-12').addClass('col-md-3');
$('.panelTicketDetail').removeClass('hide');
}
});
});
jsFiddle : https://jsfiddle.net/tqdc6yyL/
var listGroupItems = document.getElementsByClassName('list-group-item');
for (j = 0; j < listGroupItems.length; j++) {
listGroupItems[j].addEventListener("click", function () {
var elements = listGroupItems;
for (i = 0; i < elements.length; i++) {
if (elements[i].className.indexOf("col-md-12") > -1) {
elements[i].className = elements[i].className.replace("col-md-12", "col-md-3");
elements[i].className = elements[i].className.replace("hide", "");
}
}
this.className = this.className + " selected";
});
}
var list = document.getElementById('panelTicketsList');
var items = document.querySelectorAll("#panelTicketsList .list-group-item");
var detail = document.querySelectorAll(".panelTicketDetail");
items.forEach(function(btn){
btn.addEventListener("click", function(){
items.forEach(function(item){ item.classList.remove("selected"); });
this.classList.add("selected");
if(list.classList.contains('col-md-12')) {
list.classList.remove('col-md-12');
list.classList.add('col-md-3');
detail.classList.add("hide");
}
});
If you have to support older browsers like IE8 or IE9, you can't use JS features like forEach or classList. Instead you should use for loop and className.
//Save DOM query in variable for reuse
var panelTicketsList = document.getElementById('panelTicketsList');
var panelTicketsDetails = document.getElementsByClassName('panelTicketDetail');
var listGroupItems = panelTicketsList.getElementsByClassName('list-group-item');
//go through all of the listGroupItems and set click listener
for (var i = 0; i < listGroupItems.length - 1; i++) {
listGroupItems[i].addEventListener("click", function() {
//On click, go through all of listGroupItems and remove selected class
for (var j = 0; j < listGroupItems.length - 1; j++) {
listGroupItems[j].className = listGroupItems[j].className.replace('selected', '');
}
//Add selected class for clicked element
listGroupItems[i].className += 'selected';
//test if main element has class col-md-12
if (panelTicketsList.className.indexOf("col-md-12") > -1) {
//replace clas col-md-12 with col-md-3
panelTicketsList.className = panelTicketsList.className.replace('col-md-12', 'col-md-3');
//go through all of the panelTicketDetails and remove hide class
for (var k = 0; k < panelTicketsDetails.length - 1; k++) {
panelTicketsDetails[k].className = panelTicketsDetails[k].className.replace('hide', '');
}
}
});
}

Getting the index of the current element and change his styles

I have a function whose destination is to work onClick event.
So, we have for example 4 Span elements and 4 Div elements.
The Spans are Tabs-buttons which I would like to "open" those Divs.
The 1st Span onClick would (open) change the style.display of the 1st Div in "block", from "none", and so on for the next Spans.
This piece of code works very well, but it changes only the design of elements.
function activateSup(s) {
var workTable = s.parentNode.parentNode.parentNode.parentNode.parentNode;
var spans = workTable.getElementsByTagName("span");
var supDivs = workTable.getElementsByClassName("supDiv");
for (var i = 0; i < spans.length; i++) {
spans[i].style.backgroundColor = "";
spans[i].style.border = "";
}
s.style.backgroundColor = "#5eac58";
s.style.border = "2px solid #336633";
}
I've tried to add the code below into my function to achieve what I want, but It does not work.
var getIndex = function(s) {
for (var index = 0; s != s.parentNode.childNodes[index]; index++);
return index;
}
for (var d = 0; d < supDivs.length; d++) {
if (getIndex == d) {
supDivs[d].style.display = "block";
}
else {
supDivs[d].style.display = "none";
}
}
I'm not exactly sure what you're trying to do, but one thing I noticed is this:
var getIndex = function(s) { /* .... */ }
for (var d = 0; d < supDivs.length; d++) {
if (getIndex == d) {
supDivs[d].style.display = "block";
}
else { /* ... */ }
}
This code is comparing getIndex to d, which means it's comparing an integer (d) to the function getIndex, instead of the result of the function call getIndex(spans[d]) (which is an integer, like d).
But what I think you're really trying to do, is getting the index of the clicked <span> so you can show the <div> with the matching index (and hide the rest). To achieve this, the code could be changed like so:
function activateSup(s) {
var workTable = s.parentNode.parentNode.parentNode.parentNode.parentNode;
var spans = workTable.getElementsByTagName("span");
var supDivs = workTable.getElementsByClassName("supDiv");
var index;
for (var i = 0; i < spans.length; i++) {
spans[i].style.backgroundColor = "";
spans[i].style.border = "";
if (s == spans[i])
index = i;
}
s.style.backgroundColor = "#5eac58";
s.style.border = "2px solid #336633";
for (var d = 0; d < supDivs.length; d++) {
if (index == d) {
supDivs[d].style.display = "block";
} else {
supDivs[d].style.display = "none";
}
}
}
Instead of the function getIndex, this just saves the correct index inside the first for loop.
There are many more improvements that could be made to this code, like rewriting it so you don't need that ugly s.parentNode.parentNode.parentNode.parentNode.parentNode and working with CSS classes instead of manually setting the style. But I'll leave that to the reader.

Categories