Changing the onclick of every <li> element in a <ol> - javascript

I have a jQueryUI sortable list of li-Buttons with following markup:
<ol id="tracks" class="ui-sortable">
<li class="pl_clipEntry ui-widget-content ui-draggable ui-draggable-handle">
<span class="pl_slot_1_clipNumber_6">6. </span>
<span class="pl_clipName">
<button class="pl_entry" onclick="emitCommand('goto: clip id: 6')">Clip Copy 3.mov</button>
</span>
<span class="pl_clipLength">(00min17sec)</span>
</li>
</ol>
These Items are dragged from another list, where their onclick has its good use
Now everytime the list is sorted (or a new item is inserted), i want to overwrite the onclick, so that the items in THIS list have a different function (in fact, it's going to be a playlist, that's why the onclick-command can't be the same as in the file-list)
i can't figure out how exactly to do this.
This is called on every list-update:
function updatePlaylist () {
var list = $("#tracks");
list.children(':not(.placeholder)').each(function(index) {
console.log($(this).childNodes[1].text()); // to check if it works
//$(this).children[1].attr("onclick","play_clip:" + index);
});
};
so, in plain: i want to set the onclick of each li > span > button to "play_clip6" etc.
i've tried it with children[1] and childnodes[1], but they all print undefined.
i suppose it's something about the scope of "this", or some other thing i've overlooked.. but shouldn't this work? i'm stuck :(
thanks

I think what you are missing is the parameter for the referenced element in the each function.
HTML
<ol id="tracks">
<li>Track 1 <span style="color:red;">sp1</span> <span style="color:blue;">Play 1</span>
</li>
<li>Track 2 <span style="color:red;">sp1</span> <span style="color:blue;">Play 2</span>
</li>
<li>Track 3 <span style="color:red;">sp1</span> <span style="color:blue;">Play 3</span>
</li>
<li>Track 4 <span style="color:red;">sp1</span> <span style="color:blue;">Play 4</span>
</li>
<li class="placeholder">Move Track Here</li>
</ol>
<button id="changeIt">Change The Click Event</button>
JS
$(function () {
$("#tracks").children(":not(.placeholder)").each(function (index, elem) {
var cElem = $(elem).children().eq(1);
$(cElem).click(function () {
alert("before: " + $(cElem).text());
});
});
});
$("#changeIt").click(function () {
$("#tracks").children(":not(.placeholder)").each(function (index, elem) {
var cElem = $(elem).children().eq(1);
$(cElem).attr('onclick', '').unbind('click');
$(cElem).click(function () {
alert("after: " + $(cElem).text());
});
});
});
Edit for selecting button inside
HTML
<ol id="tracks">
<li>Track 1 <span style="color:red;">sp1</span> <span style="color:blue;"><button>Play 1</button></span>
</li>
<li>Track 2 <span style="color:red;">sp1</span> <span style="color:blue;"><button>Play 2</button></span>
</li>
<li>Track 3 <span style="color:red;">sp1</span> <span style="color:blue;"><button>Play 3</button></span>
</li>
<li>Track 4 <span style="color:red;">sp1</span> <span style="color:blue;"><button>Play 4</button></span>
</li>
<li class="placeholder">Move Track Here</li>
</ol>
<button id="changeIt">Change The Click Event</button>
JS
$(function () {
$("#tracks").children(":not(.placeholder)").each(function (index, elem) {
var cElem = $(elem).children().eq(1).children().eq(0);
$(cElem).click(function () {
alert("before: " + $(cElem).text());
});
});
});
$("#changeIt").click(function () {
$("#tracks").children(":not(.placeholder)").each(function (index, elem) {
var cElem = $(elem).children().eq(1).children().eq(0);
$(cElem).attr('onclick', '').unbind('click');
$(cElem).click(function () {
alert("after: " + $(cElem).text());
});
});
});

Related

Javascript indexOf a list for a targeted event in a unordered list giving the wrong index

I am trying to get the index number of a 'li' element of a 'ul' from the html.
To do this I change the 'ul' into a list to get his children with:
[...ul.children]
However when I target any of the children I get a -1 as index instead of the correct index.
How to fix?
Is this due to the fact that the list items it's not empty and has a div or other elements inside?
Here is my javascript and my html:
const ul = document.querySelector('ul');
ul.addEventListener('click', myFunc);
function myFunc(e) {
const indexToShow = [...ul.children].indexOf(e.target);
console.log(indexToShow);
console.log(e.target);
}
<ul class="calendar-list">
<li class="list-item">
<div class="fight-link">
<span class="date">1 Dec 2022</span>
<span class="fighters-name">JAY</span>
</div>
</li>
<li class="list-item">
<div class="fight-link">
<span class="date">2 Dec 2022</span>
<span class="fighters-name">Jo</span>
</div>
</li>
<li class="list-item">
<div class="fight-link">
<span class="date">3 Dec 2022</span>
<span class="fighters-name">Bob</span>
</div>
</li>
</ul>
The click evennt triggers on the span, but you're comparing against the li.
So you'll need to search for the li using closest() to match the elements:
const ul = document.querySelector('ul');
ul.addEventListener('click', myFunc);
function myFunc(e) {
const indexToShow = [...ul.children].indexOf(e.target.closest('li'));
console.log(indexToShow);
}
<ul class="calendar-list">
<li class="list-item">
<div class="fight-link">
<span class="date">1 Dec 2022</span>
<span class="fighters-name">JAY</span>
</div>
</li>
<li class="list-item">
<div class="fight-link">
<span class="date">2 Dec 2022</span>
<span class="fighters-name">Jo</span>
</div>
</li>
<li class="list-item">
<div class="fight-link">
<span class="date">3 Dec 2022</span>
<span class="fighters-name">Bob</span>
</div>
</li>
</ul>
here is how you can achive this
const ul = document.querySelector('ul');
ul.addEventListener('click', myFunc);
function myFunc(e) {
const indexToShow = [...ul.children].indexOf(e.path[2]);
console.log(indexToShow);
console.log(e.target);
}

Menu nav li active remove

I want to assign "active" class to the menu. The active clip is throwing but not deleting. I do not understand why you did not delete. Thank you in advance to those who can help.
There is no error, it surprises me that it does not delete this way
<ul id="avia-menu" class="menu av-main-nav">
<li id="menu-item" class="menu-item">
<a href="home">
<span class="avia-bullet"></span>
<span class="avia-menu-text">Home</span>
<span class="avia-menu-fx">
<span class="avia-arrow-wrap">
<span class="avia-arrow"></span>
</span>
</span>
</a>
</li>
<li id="menu-item" class="menu-item">
<a href="about">
<span class="avia-bullet"></span>
<span class="avia-menu-text">About</span>
<span class="avia-menu-fx">
<span class="avia-arrow-wrap">
<span class="avia-arrow"></span>
</span>
</span>
</a>
</li>
<li id="menu-item" class="menu-item">
<a href="contact">
<span class="avia-bullet"></span>
<span class="avia-menu-text">Contact</span>
<span class="avia-menu-fx">
<span class="avia-arrow-wrap">
<span class="avia-arrow"></span>
</span>
</span>
</a>
</li>
</ul>
function updateMenu(url) {
const active = document.querySelector('#menu-item.active');
if (active !== null) {
active.classList.remove('active');
}
const links = Array.from(document.querySelectorAll('#menu-item'));
links.forEach(function (li) {
let anchor = li.querySelector("a");
if (url.indexOf(anchor.href) > -1) {
li.classList.add("active");
}
});
}
updateMenu(window.location.href);
You can simplify your function by consolidating your .add("active") and .remove("active") calls inside your loop. This saves you a query and avoids unsetting and resetting a class on the same element unnecessarily.
You also don't need the Array.from() call.
function updateMenu(url) {
const links = document.querySelectorAll('#menu-item');
links.forEach(li => {
let anchor = li.querySelector("a");
if (url.indexOf(anchor.href) > -1) {
li.classList.add("active");
} else {
li.classList.remove("active");
}
});
}
updateMenu(window.location.href);

Swap "ul li" dynamically

I have my ul : li list with a span named as badge which contains the total number of unread messages. So i want to shuffle all the li items with the highest number on top of the list and lowest or none to the last. I tried many solutions but still can`t get it. Another point is the count gets update live so the list should also shuffle live. Here is the code that i tried till now.
My HTML Code
<li>
<span class="badge" style="display:none" id="61_T">0</span>
</li>
<li>
<span class="badge" style="display:none" id="62_T">5</span>
</li>
<li>
<span class="badge" style="display:none" id="63_T">10</span>
</li>
<li>
<span class="badge" style="display:none" id="64_T">0</span>
</li>
Here is my JS Code
var prev_index = 0;
var curr_index = 0;
var curr_val = 0;
var prev_val = 0;
var lists = $('#items li');
var msg_count = [];
$('#items li').each(function(){
var current_index = $(this).index();
var count = $(this).find('.badge').text();
msg_count.push([current_index,count]);
});
updateli();
function updateli(){
$.each(msg_count,function(key,value){
var str = value.join('-');
var sep = str.split('-');
curr_index = sep[0];
curr_val = parseInt(sep[1]);
if(curr_val > prev_val){
$("#items li:eq("+curr_index+")").siblings().eq(curr_index).after(lists.siblings(':eq('+prev_index+')'));
}
prev_index = curr_index;
prev_val = curr_val;
});
}
What i did here is created an array with li index and unread count number. After than looped the array and used jQuery function to swap the elements but nothing seems to work. Any help will really appreciated. Thanks in advance.
This sorts the list without using JQuery
function sortItems(containerSelector, itemSelector, countSelector, asc) {
let container = document.querySelector(containerSelector);
let items = [].slice.call(container.querySelectorAll(itemSelector));
items.sort(function(currItem, nextItem) {
var currCountElement = currItem.querySelector(countSelector);
var nextCountElement = nextItem.querySelector(countSelector);
if(!currCountElement) return 1;
if(!nextCountElement) return -1;
var currCount = parseInt(currCountElement.textContent || -1);
var nextCount = parseInt(nextCountElement.textContent || -1);
var order = currCount - nextCount;
return asc?-order:order;
});
items.forEach(function(item) { container.appendChild(item)});
}
// demo code
[].slice.call(document.querySelectorAll('.sortButton')).forEach(function(button) {
button.addEventListener('click', function(e) { sortItems('.items', 'li', '.badge', this.classList.contains('-desc')) });
});
<ul class="items">
<li>
2
<span class="badge" style="display:none" id="61_T">2</span>
</li>
<li>
5
<span class="badge" style="display:none" id="62_T">5</span>
</li>
<li>
10
<span class="badge" style="display:none" id="63_T">10</span>
</li>
<li>
1
<span class="badge" style="display:none" id="63_T">1</span>
</li>
<li>
0
<span class="badge" style="display:none" id="64_T">0</span>
</li>
<li>
none
<span class="badge" style="display:none" id="64_T"></span>
</li>
<li>
no badge
</li>
</ul>
<button class="sortButton">asc</button>
<button class="sortButton -desc">desc</button>
Edit: made it a method
try the code below please.jquery return a array-like object so you can sort elements by sort(..) method,and then replace all the li.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>
<span class="badge" id="61_T">0</span>
</li>
<li>
<span class="badge" id="62_T">5</span>
</li>
<li>
<span class="badge" id="63_T">10</span>
</li>
<li>
<span class="badge" id="64_T">0</span>
</li>
</ul>
<script>
var badges = $('.badge').parent().sort(function (a, b) {
return parseInt($(b).find('span').text()) - parseInt($(a).find('span').text());
});
badges.closest('ul').empty().append(badges);
</script>

Dynamic context menu in jqGrid

How do I get Dynamic context menu in jqGrid? I need to display 'menu1' for even rows and 'menu2' for odd rows? I tried to use contextmenu plugin but do not know how to implement dynamic switch between 2 context menues. Thanks.
If you need really bind just 'menu1' for even rows and 'menu2' for odd rows you can implement binding to grid rows inside of loadComplete. For example if you has
<div class="contextMenu" id="myMenu1" style="display:none">
<ul style="width: 200px">
<li id="edit1">
<span class="ui-icon ui-icon-pencil" style="float:left"></span>
<span style="font-size:11px; font-family:Verdana">Edit Row 1</span>
</li>
<li id="del1">
<span class="ui-icon ui-icon-trash" style="float:left"></span>
<span style="font-size:11px; font-family:Verdana">Delete Row 1</span>
</li>
</ul>
</div>
<div class="contextMenu" id="myMenu2" style="display:none">
<ul style="width: 200px">
<li id="edit2">
<span class="ui-icon ui-icon-pencil" style="float:left"></span>
<span style="font-size:11px; font-family:Verdana">Edit Row 2</span>
</li>
<li id="del2">
<span class="ui-icon ui-icon-trash" style="float:left"></span>
<span style="font-size:11px; font-family:Verdana">Delete Row 2</span>
</li>
</ul>
</div>
you can make the binding so
loadComplete: function () {
$("tr:even", this).contextMenu('myMenu1', {
bindings: {
'edit1': function(trigger) {
alert ("Edit (menu1) id=" + trigger.id);
},
'del1': function(trigger) {
alert ("Delete (menu1) id=" + trigger.id);
}
}
});
$("tr:odd", this).contextMenu('myMenu2', {
bindings: {
'edit2': function(trigger) {
alert ("Edit (menu2) id=" + trigger.id);
},
'del2': function(trigger) {
alert ("Delete (menu2) id=" + trigger.id);
}
}
});
}
See the demo.
Ok so you already have the contextmenu to work but need to define if the row is even or odd.
Try the following:
afterInsertRow: function(rowId, rowData, rowElm) {
var trElement = $('#' + rowid);
if(trElement.is(':even'))
// even contextMenu
else
// odd contextMenu
}

jQuery Higlight items that are more than one in ul

I am trying to highlight items that are more than one in a list with different colours with jQuery. Is below achievable easily?
For example. Take the ul below
<ul id="inul">
<li id="s0" class="list">
<span id="ip0">127.0.0.1</span>
<span id="ua0">SonyEricssonK800iv/R1KG Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1</span>
</li>
<li id="s1" class="list">
<span id="ip1">127.0.0.1</span>
<span id="ua1">Nokia3120classic/2.0 (09.41) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokia3120classic/UC Browser7.6.1.82/69/352 UNTRUSTED/1.0</span>
</li>
<li id="s2" class="list">
<span id="ip2">127.0.0.1</span>
<span id="ua2">SonyEricssonW580i/R8BE Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1</span>
</li>
<li id="s3" class="list">
<span id="ip3">127.0.0.1</span>
<span id="ua3">SonyEricssonK800iv/R1KG Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1</span>
</li>
<li id="s4" class="list">
<span id="ip4">127.0.0.1</span>
<span id="ua4">Nokia3120classic/2.0 (09.41) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokia3120classic/UC Browser7.6.1.82/69/352 UNTRUSTED/1.0</span>
</li>
<li id="s5" class="list">
<span id="ip5">127.0.0.2</span>
<span id="ua5">SonyEricssonW580i/R8BE Browser/NetFront/3.3 Profile/MIDP-2.0 Configuration/CLDC-1.1</span>
</li>
</ul>
There are two of each browser user agent and 4 of same ip (127.0.0.1) and 1 127.0.0.2.
What i am hoping to achieve is that identical spans would be colored with same color while assigning different color to each identical set.
Just to be clear, end result should look like image below
UPDATE With the help of WSkid I ahve manged to achive what i want. See update http://pastebin.ca/2058058 or working version at http://jsfiddle.net/mUGVR/15/
The following is terribly in efficient and hacky, but it might start you down the right road of storing a hash-like map and keeping a count to add your needed styles:
Working fiddle http://jsfiddle.net/mUGVR/.
var ipList={};
var ipCount=0;
var userList={};
var userCount=0;
$('li.list').each(function(i){
var spans = $(this).children();
spans[0] = $(spans[0]);
spans[1] = $(spans[1]);
if(ipList[spans[0].text()]!=null)
{
spans[0].addClass('ip'+ipList[spans[0].text()]);
}
else
{
ipList[spans[0].text()] = ipCount;
spans[0].addClass('ip'+ipCount);
ipCount++;
}
if(userList[spans[1].text()]!=null)
{
spans[1].addClass('user'+userList[spans[1].text()]);
}
else
{
userList[spans[1].text()] = userCount;
spans[1].addClass('user'+userCount);
userCount++;
}
});
With css:
.ip0 {background:yellow;}
.user0{background:cyan;}
.user1{background:green;}
.user2{background:red;}
Like this? Fiddle: http://jsfiddle.net/8A5dY/1
// highlights ips
$('li span:first-child').filter(function() {
return ($(this).text() == '127.0.0.1');
}).css('background', 'yellow');
var colorMap = [];
var currentColor = 0;
$('li span:nth-child(2)').each(function() {
var text = $(this).text();
var color = colorMap[text] ||
['lightblue', 'red', 'blue', 'green'][currentColor++];
colorMap[text] = color;
$(this).css('background', color);
});

Categories