jQuery DOM - Inserting multiple nodes in li (menu) - javascript

I know there are dozens of similar topics but I am so dumb I can't learn anything from it.
Other words: My code is just mean and doesn't work with any fixes published online. ;)
My HTML:
<ul id="main_menu">
<li class="menu-item">Link 1</li>
<li class="menu-item">Link 2</li>
<li class="menu-item">Link 3</li>
<li class="menu-item">Link 4</li>
</ul>
and how the LI should look after JS does its magic:
...
<span data-title="Link 1">Link 1</span>
...
JS/JQ mission:
add class="roll-link" to every A
add SPAN right after A tag
add data-title="xxx" attribute to SPAN with A value (text exactly the same as the A)
close SPAN tag before A closing tag
My JS try:
var menuLis = document.querySelectorAll("ul.main_menu li"); //It's an Array right?
for(var i=0; i<menuLis.length; i++) {
this.nextChild.setAttribute('class', 'rollink');
var span = document.createElement('span');
this.nextChild.nextSibling.insertBefore(span); //Auto-closing </span> may be an issue...
span.setAttribute('data-title', hrefvalue[i]); //but how to get value?
}
It may be total crap but I have completely no experience in JS/JQ, only had few hours of basic training online...
Thanks for reading and even bigger thanks for trying to help.
Greets!

it should be as simple using jQuery(because you tagged it with jQuery)
jQuery(function ($) {
$('#main_menu li a').addClass('roll-link').wrapInner(function () {
return $('<span />', {
'data-title': $.trim($(this).html())
});
})
})
Demo: Fiddle
See
selectors
addClass()
wrapInner()
dom ready
To make your code work, first the main_menu is an id, not a class so you need to use id selector, then try
var as = document.querySelectorAll("#main_menu li a");
for (var i = 0; i < as.length; i++) {
as[i].className = 'rollink';
var span = document.createElement('span');
span.setAttribute('data-title', as[i].innerHTML);
span.appendChild(as[i].firstChild);
as[i].appendChild(span)
}
Demo: Fiddle

$('#main_menu > li > a').each(function () {
var text = $(this).addClass('roll-link').contents().first();
text.wrap($('<span>').attr('data-title', text.text()));
});
DEMO: http://jsfiddle.net/Bw723/

Here is your solution with pure Javascript.
//get the li elements
var menuLis = document.getElementById("main_menu").getElementsByTagName('li');
for(var i=0; i<menuLis.length; i++) {
menuLis[i].firstChild.setAttribute('class', 'rollink');
var span = document.createElement('span');
span.setAttribute('data-title', menuLis[i].innerHTML);
//If you want to get href of a then use this one.
//span.setAttribute('data-title', menuLis[i].href);
//appending the span into a
menuLis[i].firstChild.appendChild(span);
}
DEMO

Related

get number of li and assign it to function

I have a ul as navigation with a few li elements.
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
Although I got the same amount of div elements, that I can target with .scrollTo( "number of div" ), starting by 0. I could do it on my own this way:
$("ul li:nth-child(1)").on('click', function(){
sliderInstance.goTo(0);
});
$("ul li:nth-child(2)").on('click', function(){
sliderInstance.goTo(1);
});
$("ul li:nth-child(3)").on('click', function(){
sliderInstance.goTo(2);
});
$("ul li:nth-child(4)").on('click', function(){
sliderInstance.goTo(3);
});
But that seems to be neither smart nor efficient. Imagen I have about twenty div and li elements. Is there a good tweak combining .size(), .length() or something else I am not aware of?
Just for diversity:
var $li = $('ul li').on('click', function (event) {
sliderInstance.goTo($li.index(this));
})
i would use onclick event
<ul id="navigation">
<li onclick="scrollTo('#yourTargetAnchor1')"></li>
<li onclick="scrollTo('#yourTargetAnchor2')"></li>
<li onclick="scrollTo('#yourTargetAnchor3')"></li>
<li onclick="scrollTo('#yourTargetAnchor4')"></li>
</ul>
you can also generate it, but in most cases a hardcoded navigation is not too bad. to generate it i would do like this:
var navArr = $('#navigation').children().length;
for (var i = 0; i < navArr; i++) {
$('#navigation').children()[i].click(function(){
scrollTo('#yourTargerAnchor'+i);}}
not tested but should do the job. hope i could help ;)

Issue with adding UL markup for LI

This sounds simple, and it should be, but it doesn't seem to be so cut and dry...
I have a list of li elements..
<li>Text here</li>
<li>Text here</li>
<li>Text here</li>
What I want to do is find the 1st one, add <ul> before it. Find the last one, add </ul>
It sounds simple but stay with me...
First I tried this:
$('li').each(function(i,obj) {
var x = $(this);
if(x.prev().prop('tagName')!=='LI') x.before('<ul>')
if(x.next().prop('tagName')!=='LI') x.after('</ul>')
});
Which evolved into this:
$('li').each(function(i,obj) {
var x = $(this);
$.fn.outerHTML = function(){
var x = $(this);
x.wrap('<p/>')
var html = x.parent().html();
x.unwrap();
return(html);
}
alert(x.outerHTML());
if(x.prev().prop('tagName')!=='LI') x.html('<ul>'+x.outerHTML())
if(x.next().prop('tagName')!=='LI') x.html(x.outerHTML()+'</ul>')
});
The 1st code places an empty UL before the 1st LI (closing tag and all)
The 2nd wraps only the 1st LI.
It goes down the list 1, 2, 3 and seems to report back properly... something (possibly jQuery) seems to be altering my code somewhere along the way. Can anyone shed some insight here?
Fiddle to fiddle with: http://jsfiddle.net/yr67N/
Update:
As you can see from the code, the lis must be grouped together. wrapAll won't work here.
Just tried this on your fiddle and it appears to work:
var collectedLi = [];
$('li').each(function(){
collectedLi.push(this);
if(!$(this).next().is('li')){
$(collectedLi).wrapAll('<ul/>');
collectedLi = []
}
});
For every li it will check if the next element is also an li, if not it will wrap the current collection in a ul and then empty the collection to continue the loop.
Just realized that the above code will also wrap already wrapped li tags, here is a solution that will handle this:
var collectedLi = [];
$('li').each(function(){
collectedLi.push(this);
if(!$(this).next().is('li')){
if(!$(this).parent().is('ul')){
$(collectedLi).wrapAll('<ul/>');
}
collectedLi = []
}
});
How about:
$('li').wrapAll('<ul/>');
Fiddle
var ul,
tname;
$('li').each(function(i, el){
tname = $(el).prev().prop('tagName');
if(String(tname) !== 'UL'){
ul = $('<ul></ul>');
$(el).before(ul[0]);
}
$(this).appendTo(ul);
});
fiddle

Using an eventlistener instead of onclick

I have a ul that when each li is clicked, the text in its nested span gets sent to an input. I was advised to replace my (many) onclicks- one on each li in the list with an eventlistener on the ul. could use advice on how to do this neatly with same functionality.
html:
<ul>
<li onclick="myfunction(this)"><img src="img1"><span>Some text</span></li>
<li onclick="myfunction(this)"><img src="img2"><span>Some other text</span></li>
</ul>
<input id="field_jd6brw">
Javascript:
function myfunction(li){
document.getElementById("field_jd6brw").value = li.childNodes[1].textContent;
}
simply use jquery :
$("ul li").click(function (){
$("#field_jd6brw").val($(this).text());
});
If you need to stick to plain-vanilla JavaScript, you can use something like this:
function myfunction(){
document.getElementById("field_jd6brw").value = this.children[1].innerHTML;
}
var aLi = document.querySelectorAll('ul li');
for (var i=0, len = aLi.length; i<len; i++) {
aLi[i].addEventListener('click', myfunction, false);
}
Demo: http://jsfiddle.net/Q6Tm5/
This code selects all LI within a UL (use more specific selectors, like ID of UL if needed) and then loops thru each LI element adding the event listener.
Note that this code won't work in old versions of IE - you either need to add IE-specific code or switch to jQuery

Whether particular li with a specific text exists inside a ul using JQUERY

I have a code
like
<ul id="uploadedfiles">
<li>
A_001
</li>
<li>
B_001
</li>
</ul>
Now i want to insert a new li but i want to check that something that whether a li with a text say A_ exist in that ul. If it exists than remove the older and add the new li.
Say if i add C_001 it is added with no issue
But if i add A_002 then it replace the A_001 with A_002.
Please provide the code for the same if possible.
Any help is appreciated!
Added:
The real data in li have text like control20_a.jpg , control21_b.jpg .....
Then when adding a new li say control20_c.jpg the code must replace control20_a.jpg. But add a new li if it does not exists
This is probably not very idiomatic jQuery, but it seems to do the job.
Working Example
var add = function(entry) {
var match = $('#uploadedfiles li:contains(' + entry.slice(0, entry.indexOf('_')) + ')');
if (match.length > 0) {
match.text(entry);
} else {
$('#uploadedfiles').append($('<li>' + entry + '</li>'));
}
}
I would add a class to the li (like <li class="a"> and <li class="b">
When adding the new LI i would strip the first char of the name and find the LI
If no li, I would create it else change the innerHTML for the new one.
Good luck
UPDATE:
if the elements are from 001 to 002 etc you could do
$("ul li").each(function() {
var firstChar = $(this).text().substring(0,1);
var removeElms = $("ul li:contains('"+firstChar+"'):not(:last)");
removeElms.remove();
});

jQuery Find and List all LI elements within a UL within a specific DIV

I have 3 Columns of ULs each a Dynamic UL container that can have anywhere from 0-9 LI containers (eventually more). All my LI elements have an attribute "rel" which I am trying to ultimately find that attribute and use it for something else on all LI elements within that parent DIV. I do eventually want to find more based on each but for not the very least the rel.. Any Ideas how I can achieve that with jQuery? Example:
<ul id="column1">
<li rel="1">Info</li>
<li rel="2">Info</li>
<li rel="3">Info</li>
</ul>
<ul id="column2">
<li rel="4">Info</li>
<li rel="5">Info</li>
<li rel="6">Info</li>
</ul>
<ul id="column3">
<li rel="7">Info</li>
<li rel="8">Info</li>
<li rel="9">Info</li>
</ul>
these elements are all sortable as well. So when I get a list of them I want to also keep them in the order they were found from top to bottom of each column.
I have tried find(), parent(), and similar, maybe I am approaching it wrong. But its still worth mentioning to help come up with an idea
Are you thinking about something like this?
$('ul li').each(function(i)
{
$(this).attr('rel'); // This is your rel value
});
var column1RelArray = [];
$('#column1 li').each(function(){
column1RelArray.push($(this).attr('rel'));
});
or fp style
var column1RelArray = $('#column1 li').map(function(){
return $(this).attr('rel');
});
html
<ul class="answerList" id="oneAnswer">
<li class="answer" value="false">info1</li>
<li class="answer" value="false">info2</li>
<li class="answer" value="false">info3</li>
</ul>
Get index,text,value
js
$('#oneAnswer li').each(function (i) {
var index = $(this).index();
var text = $(this).text();
var value = $(this).attr('value');
alert('Index is: ' + index + ' and text is ' + text + ' and Value ' + value);
});
$('li[rel=7]').siblings().andSelf();
// or:
$('li[rel=7]').parent().children();
Now that you added that comment explaining that you want to "form an array of rels per column", you should do this:
var rels = [];
$('ul').each(function() {
var localRels = [];
$(this).find('li').each(function(){
localRels.push( $(this).attr('rel') );
});
rels.push(localRels);
});

Categories

Resources