jQuery after ul list .remove() won't fill list again - javascript

When the page is loaded, there are 3 lists. First containing an active list and second and third are blank. When clicked on the active list li the second list (ul) is filled with one li element, the filling process continues to the third list automatically (on mouse click). Then when the button delete is pressed, both lists get removed and the process is supposed to work the same as described, but the second list for some reason doesn't get filled and everything goes to the third list.
I have tried methods: remove(), empty(), detach() but none of them seem to work.
Also in if statement I tried to check if (typeof ul.lenght === "undefined") but even this is not working.
Also to mention in console.log() when cheking ul.lenght property first time it returns 0 and undefined and fill the second list but after delete button is pressed it returns same value but won't fill the list.
Here is the code:
function myf() {
var orig = $("#ori li").length;
if ($("#ori li").length === 0 || typeof orig === "undefined") {
$(document).on('click', '#orglis li', function() {
$(this).remove();
$("#ori").append(this);
});
} else {
$(document).on('click', '#orglis li', function() {
$(this).remove();
$("#zam").append(this);
var lio = document.getElementById("ori").getElementsByTagName("li");
var larr = lio[0].innerText;
var arr = Array.from(document.querySelectorAll('#c>ul>li'), li => (li.textContent));
var tekst = "";
var i;
var j;
for (j = 0; j < arr.length; j++) {
arr[j] = arr[j].trim();
}
for (i = arr.length - 1; i >= 0; i--) {
tekst += larr + ", " + arr[i] + '\n';
}
document.getElementById("tare").innerHTML = tekst;
document.getElementById("imep").value = larr;
});
}
}
Here you can see demo.
EDIT: Also tried with outerHTML to set ul as before but still won't work

#freedomn-m was right about mixing onclick= and $(document).on("click" and I noticed that I had, without reason, two same functions

Related

removeClass & addClass jquery

I am relatively new to jquery and try to solve the following issue
I want to build a tree diagram, cf.
When an item in the first category is clicked, the second category (in div #category_2) pops-up. The same for the 3rd category. Every subsequent click on category 1 or 2 should remove the appended 2nd and 3rd item and append the chosen item from the 2nd and 3rd category.
Here is what I tried at the example of opening an item in category 3 (=subMenu2):
function makeType(subMenu2, root) {
if (typeof root === 'undefined') {
root = $('#category_3');
}
var ul = $("<ul></ul>");
if (root.children().length > 0) {
root.removeClass(ul)
}
root.append(ul);
for (var k = 0; k < subMenu2.length; k++) {
var li = $("<li class='category-selection-list-item is-subleaf'></li>");
ul.append(li);
var a = $("<a href='#' data-param='" + array[array_i].subMenu[submenu_i].subMenu2[k].param + "'>" + array[array_i].subMenu[submenu_i].subMenu2[k].type + "</a>");
li.append(a);
console.log(k);
}
}
Though the removeClass element stops adding further items, it does not delete previously added items. I tried to find a suitable answer in the forum, but this did not help. So, how can I fix this issue?
To remove the previously added items, you need to empty root.
if (root.children().length > 0) {
root.removeClass('ul');
root.empty();
}
addClass("className")
removeClass("className")
if you want to hide some node, just use this:
$("#someNode").hide()

Troubles appending options to select in jquery

I have some <select> that needs to be populated with dynamic values, coming from an array. My code is pretty simple, the HTML is made by just some empty HTML <select> with the same class (.js-select).
The JS is quite simple:
var $select = $(".js-select");
var ioSensors = [1,2,3]; // The data I want to display in the select
var $optionTpl = $("<option></option>");
for( i=0 ; i<ioSensors.length ; i++ ){
//also show a leading "None" option
if(i === 0){
$optionTpl.attr('value','').text('None').appendTo($select);
}
$optionTpl.attr('value', ioSensors[i]-1).text(ioSensors[i]).appendTo($select);
}
With this code I'm having all my <select> correctly updated, but the last one is populated only with the last value of the Array, not showing even the "None" option.
Can anyone help me understand where the problem is and why is it behaving like that? Thanks!
I've made a pen Here
var $optionTpl = $("<option></option>"); creates an element once, then inside the loop you just keep moving that same element and just giving it a new value.
Create multiple elements inside the loop instead
var $select = $(".js-select");
var ioSensors = [1,2,3];
for( var i = 0; i < ioSensors.length; i++ ){
var $optionTpl = $("<option></option>");
if(i === 0){
$optionTpl.val('').text('None').appendTo($select);
}
$optionTpl.val(ioSensors[i]-1).text(ioSensors[i]).appendTo($select);
}
As others have already suggested, the reason it doesn't work is because you create a single element and keep moving it around. Move the creation of the element inside the loop, for example as follows:
var $select = $(".js-select");
var ioSensors = [1,2,3]; // The data I want to display in the select
for( i=0 ; i<ioSensors.length ; i++ ){
//also show a leading "None" option
if(i === 0){
$("<option></option>").attr('value','').text('None').appendTo($select);
}
$("<option></option>").attr('value', ioSensors[i]-1).text(ioSensors[i]).appendTo($select);
}
If you're wondering why your code seem to work for all the <select>s beside the last, according to the documentation when the target of an append is more than one element, jquery will clone the element for the first N-1 targets, and just move the element for the last:
If an element selected this way is inserted into a single
location elsewhere in the DOM, it will be moved into the
target (not cloned):
...
Important: If there is more than one target element, however,
cloned copies of the inserted element will be created for each
target except for the last one.
You need to clone the element to have multiple elements
var $select = $(".js-select");
var ioSensors = [1, 2, 3]; // The data I want to display in the select
var $optionTpl = $("<option></option>");
for (i = 0; i < ioSensors.length; i++) {
//also show a leading "None" option
if (i === 0) {
$optionTpl.clone().val('').text('None').appendTo($select);
}
$optionTpl.clone().val(ioSensors[i] - 1).text(ioSensors[i]).appendTo($select);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="js-select"></select>
You can also write the same like
var $select = $(".js-select");
var ioSensors = [1, 2, 3]; // The data I want to display in the select
var $optionTpl = $("<option></option>");
$("<option />", {
value: '',
text: 'None'
}).appendTo($select);
ioSensors.forEach(function(item) {
$("<option />", {
value: item - 1,
text: item
}).appendTo($select);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="js-select"></select>
Here is a simple solution (pen of the solution):
var ioSensors = [1,2,3];
$(".js-select").each(function(){
for(var i=0;i<ioSensors.length;i++) {
if(i === 0){
$("<option value=\"\">None</option>").appendTo($(this));
}
$("<option value=\"" + ioSensors[i] + "\">" + ioSensors[i] + "</option>").appendTo($(this));
}
});

tags underneath headings disappear when clicked again w/ javascript no idea why

I have pasted the javascript below but also a link to my codepen so you can see exactly what I am talking about.
I would like the heading to be clicked and expose the text below. On another click I would like for the text to go back to hidden. Multiple headings can be opened at the same time. What is happening with my current setup is you can click once to show, click again to hide and then when you click again to show nothing shows, if you keep clicking the text and headings below are eaten/dissapear. I would prefer to do this without jquery. thanks for any help.
http://codepen.io/jrutishauser/pen/YPrrNa
var clickToShow = function () {
if (this.nextElementSibling.className === 'open'){
this.nextElementSibling.remove('open');
} else if (this.nextElementSibling.className != 'open') {
this.nextElementSibling.className = 'open';
}
};
var articleHeadings = document.getElementsByTagName('h3');
for (var index = 0; index < articleHeadings.length; index++){
articleHeadings[index].onclick = clickToShow;
}
var subArticleHeadings = document.getElementsByTagName('h4');
for (var index2 = 0; index2 < subArticleHeadings.length; index2++){
subArticleHeadings[index2].onclick = clickToShow;
}
Change this.nextElementSibling.remove('open') to this.nextElementSibling.className = ''. I believe remove() method removes the element, not the class.
You can do it like this also. This is the correct way of doing it.
var clickToShow = function () {
element=this.nextElementSibling;
if (element.className === 'open'){
element.className=element.className.replace('open','');
} else if (element.className != 'open') {
element.className = 'open';
}
};

How to reduce 180 lines of code down to 20 in Javascript?

I have a lot of click handler functions which are almost (textually and functionally) identical. I've got a menu with maybe 10 items in it; when I click on an item, the click handler simply makes one div visible, and the other 9 div's hidden. Maintaining this is difficult, and I just know there's got to be a smart and/or incomprehensible way to reduce code bloat here. Any ideas how? jQuery is Ok. The code at the moment is:
// repeat this function 10 times, once for each menu item
$(function() {
$('#menuItem0').click(function(e) {
// set 9 divs hidden, 1 visble
setItem1DivVisible(false);
// ...repeat for 2 through 9, and then
setItem0DivVisible(true);
});
});
// repeat this function 10 times, once for each div
function setItem0DivVisible(on) {
var ele = document.getElementById("Item0Div");
ele.style.display = on? "block" : "none";
}
Create 10 div with a class for marking
<div id="id1" class="Testing">....</div>
<div id="id2" class="Testing">....</div>
<div id="id3" class="Testing">....</div>
and apply the code
$('.Testing').each(function() {
$(this).click(function() {
$('.Testing').css('display', 'none');
$(this).css('display', 'block');
}
}
$(document).ready(function (){
$("div").click(function(){
// I am using background-color here, because if I use display:none; I won't
// be able to show the effect; they will all disappear
$(this).css("background-color","red");
$(this).siblings().css("background-color", "none");
});
});
Use .siblings() and it makes everything easy. Use it for your menu items with appropriate IDs. This works without any for loops or extra classes/markup in your code. And will work even if you add more divs.
Demo
Fiddle - http://jsfiddle.net/9XSJW/1/
It's hard to know without an example of the html. Assuming that there is no way to traverse from the menuItem to ItemDiv - you could use .index and .eq to match up the elements based on the order they match with the selector.
var $menuItems = $("#menuItem0, #menuItem1, #menuItem2, ...");
var $divs = $("#Item0Div, #Item1Div, #Item2Div, ...");
$menuItems.click(function(){
var idx = $(this).index();
// hide all the divs
$divs.hide()
// show the one matching the index
.eq(idx).show();
})
Try
function addClick(i) {
$('#menuItem'+i).click(function(e) {
// set nine divs hidden, 1 visble
for( var j = 0; j < 10; ++j ) {
var ele = document.getElementById("Item"+j+"Div");
ele.style.display = (i == j ? "block" : "none");
}
});
}
// One click function for all menuItem/n/ elements
$('[id^="menuItem"]').on('click', function() {
var id = this.id; // Get the ID of the clicked element
$('[id^="Item"][id$="Div"]').hide(); // Hide all Item/n/Div elements
$('#Item' + id + 'Div').show(); // Show Item/n/Div related to clicked element
});
Obviously this would be much more logical if you were using classes instead:
<elem class="menuItem" data-rel="ItemDiv-1">...</elem>
...
<elem class="ItemDiv" id="ItemDiv-1">...</elem>
$('.menuItem').on('click', function() {
var rel = $(this).data('rel'); // Get related ItemDiv ID
$('.ItemDiv').hide(); // Hide all ItemDiv elements
$('#' + rel).show(); // Show ItemDiv related to clicked element
});
Save the relevant Id's in an array - ["Item0Div", "Item1Div", ...]
Create a generic setItemDivVisible method:
function setItemDivVisible(visible, id) {
var ele = document.getElementById(id);
ele.style.display = visible ? "block" : "none";
}
And set your click handler method to be:
function(e) {
var arrayLength = myStringArray.length;
for (var i = 0; i < idsArray.length; i++) {
setItemDivVisible(idsArray[i] === this.id, idsArray[i]);
}
}
I think this will do the trick

javascript loop through li in div of paginate

Below is the code I'm using. The top part $('div.pagination... works fine, I can alert(length) and it gives me the correct value of pages in the pagination section. The bottom part appears not to work. This is for a scraper that will open each page on a forum. If I leave the loop out of it it successfully retreaves the url for page here. The length -=2 is to remove the next/previous li from the total count.
$('div.pagination').each(function() {
var length = $(this).find('li').length;
length -= 2;
});
for (var i = 0; var <= length; i++) {
var pageToOpen = 'http://someWebsite.com/index/page:' + i;
alert(pageToOpen);
page.open(pageToOpen, function (status) {
if (status == 'success') {
logAuctions();
}
}});
}
Define your var length outside (before) the.each()
Using .lentgh method you might miss the real page indexes. So I would suggest to grab the real anchor hrefs.
FIDDLE DEMO
var pages = [];
// skipping the "Next" and "Last" get all A ahchors
$('div.pagination li').slice(0,-2).find('a').each(function(){
pages.push( $(this).attr('href') );
});
$.each(pages, function(i, v){
$('<div>'+ ("http://someWebsite.com"+v) +'</div>').appendTo('#output');
});
/* WILL RESULT IN:
http://someWebsite.com/auctions/index/page:2
http://someWebsite.com/auctions/index/page:3
http://someWebsite.com/auctions/index/page:4
*/

Categories

Resources