I'm having a problem with a simple tabbed page.
It all works OK if I hard code the 'onclicks' in the tabs that appear at the top of the page like this:
<ul class="tabs" data-persist="true">
<li class='tablinks' onclick="openTab('view1')" id='default'>How to find Maolbhuidhe</li>
<li class='tablinks' onclick="openTab('view2')">How to get to Mull</li>
<li class='tablinks' onclick="openTab('view3')">Map of Mull</li>
<li class='tablinks' onclick="openTab('view4')">Map of Scotland</li>
</ul>
There's a JS file containing the function 'openTab', of course.
But when I try to add the onclick events via JS/jQuery after the page has loaded, I'm running into a problem. The HTML for this section now looks like this:
<ul id='toptabs' class="tabs" data-persist="true">
<li class='tablinks' id='default'>How to find Maolbhuidhe</li>
<li class='tablinks'>How to get to Mull</li>
<li class='tablinks'>Map of Mull</li>
<li class='tablinks'>Map of Scotland</li>
</ul>
The JS script I'm using to add the onclick events is:
function applyClicks() {
var toptabs = document.getElementById("toptabs");
var lnks = toptabs.getElementsByTagName("li");
for (var i=0; i<lnks.length; i++) {
var k = (i+1)
var vw = 'view' + k;
alert ('vw is: ' + vw);
lnks[i].onclick = (function() {
openTab('view' + k);
});
}
}
The problem seems to lie in providing the parameter to 'openTab()'. I've tried several variations, the one shown ends up as "openTab('view' + k)" (As seen in Inspector DOM). If I hard code it as 'view1' it works, but of course all the links are then the same, so only the first tab can be shown. It seems whatever I put in the JS function as the parameter gets treated as a literal.
What do I need to do to make the parameter 'view1', 'view2', 'view3', 'view4' (as in the hard coded version) according to the value of i ? This was the purpose of the var 'vw', which duly shows all the right values in turn as the script runs, but just shows up in the link on the page as 'vw'
I've also tried the widely recommended 'addEventListener('click', ...) etc. but I get the same problem (or something similar). It may be better to add an event listener eventually, but first I need to resolve the problem of passing the variable to the 'Click'.
Try it like this:
$('.tablinks').click(function(){
let idx = $(this).index() + 1;
//alert('view' + idx);
openTab('view' + idx);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<ul id='toptabs' class="tabs" data-persist="true">
<li class='tablinks' id='default'>How to find Maolbhuidhe</li>
<li class='tablinks'>How to get to Mull</li>
<li class='tablinks'>Map of Mull</li>
<li class='tablinks'>Map of Scotland</li>
</ul>
This is why many of us prefer writing jQuery - it's just simpler. And shorter.
An alternative way of doing it is using data attributes...
$('.tablinks').on("click", function() {
var openValue = $(this).data("open");
//openTab(openValue);
console.log(openValue);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<ul id='toptabs' class="tabs" data-persist="true">
<li class='tablinks' data-open="view1" id='default'>How to find Maolbhuidhe</li>
<li class='tablinks' data-open="view2">How to get to Mull</li>
<li class='tablinks' data-open="view3">Map of Mull</li>
<li class='tablinks' data-open="view4">Map of Scotland</li>
</ul>
Related
This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 1 year ago.
I tried using jsfiddle, it works properly there, but for whatever reason, the file didn't work when i run it on chrome. i also have other code concurrently (specifically form validation) but they are working fine, and there are no clashing var and function too. I know that i should just use other simpler way but unfortunate this is part of the requirement to use array in the dropdown
function makeAnchor() {
var div = document.createElement('div');
var options = ['ENCLOSED SPACE SANITISATION', 'EVENT HYGIENE MANAGEMENT', 'WIDE AREA SANITISATION', 'OBJECT DISINFECTION'];
for (var i = 0; i < options.length; i++) {
// Create the list item:
var a = document.createElement('a');
var ok = options[i]
a.href = "./service" + (i + 1) + ".html"
a.appendChild(document.createTextNode(ok));
div.appendChild(a);
}
return div;
}
document.getElementById('dropsc').appendChild(makeAnchor());
<!-- Nav Bar -->
<nav class="sticky-top">
<ul>
<li class="dropdown font-josefin">
<a class="dropbtn">SERVICES</a>
<div id="dropsc" class="dropdown-content">
<!-- ENCLOSED SPACE SANITISATION
EVENT HYGIENE MANAGEMENT
WIDE AREA SANITISATION
OBJECT DISINFECTION -->
</div>
</li>
<li class="font-josefin">ABOUT ME</li>
<li class="font-josefin">ENQUIRY</li>
<li class="font-josefin">ENHANCEMENTS</li>
<li class="font-josefin">DISCLAIMER</li>
</ul>
</nav>
document.getElementById('dropsc').appendChild(makeAnchor().cloneNode(true));
Try this
Web Mind Help! I have html with many lists looks like
<li>A.</li>
<li>B.</li>
<li><a class=tr href="#">C.</a></li>
<li class=tr>D.</li>
<li class=notr>E.</li>
I want select all untranslated innerText
document.querySelectorAll("li:not(.notr):not(.tr)")
Problem is if class TR not in LI i cannot filter it
li:not(.notr):not(.tr)+li>a:not(.tr) - returns empty NodeList
It seems to be a simple question but I'm confused
Like I said in the comments, the solution is to fetch this collection first, then refine the results by running another filter over that.
let rawresult = document.querySelectorAll("li:not(.notr):not(.tr)");
console.log('raw results:');
rawresult.forEach(el => console.log(el.innerText));
let refinedresult = [];
rawresult.forEach(function(el) {if (el.querySelector(".notr,.tr") == null) refinedresult.push(el);});
console.log('refined results:');
refinedresult.forEach(el => console.log(el.innerText));
<ul>
<li>A.</li>
<li>B.</li>
<li><a class=tr href="#">C.</a></li>
<li class=tr>D.</li>
<li class=notr>E.</li>
</ul>
I need to list items returned from evaluating an Xpath. I'd like to return the tweets in a list, so I can further evaluate their elements. How do I do this?
My code is:
var navigable_stream = '//*[#id="stream-items-id"]';
var FIRST_RECORD = document.evaluate(navigable_stream, document, null, XPathResult.ANY_TYPE, null).iterateNext();
console.log(FIRST_RECORD);
And the returned HTML is very long. But it has lots of tweets with different ids. Here's a picture to show what I mean:
Update
" Is there a way to match the first part of the element id i.e. 'stream-item-tweet"?"
Yes, by using referencing the partial #id as an attribute:
var tweet = document.querySelectorAll("[id^=stream-item-tweet]");
Note the ^= means that the beginning of the #id must match stream-item-tweet
Having answered the question I'd like to add that there may be a better alternative by using the class of each <li>:
var tweet = document.querySelectorAll('.js-stream-item')
Something looks invalid on the classList:
class="js-stream-item stream-item stream-item"
.stream-item is repeated twice...maybe it's best to avoid class in your circumstance.
Anyways, knowing the first way should work and maybe the second way might, tweet is now a NodeList which needs to be handled by a loop or it needs to be converted to an array so it can be processed by an array method.
Demo 2 shows how the latter is done.
Just guessing, since there's no way I can test it myself, that if that's what you can get on the console, then you could maybe use .toString() then parse and append it to the DOM.
Demo 1
Not possible to make an actual functioning Demo
var navigable_stream = '//*[#id="stream-items-id"]';
var FIRST_RECORD = document.evaluate(navigable_stream, document, null, XPathResult.ANY_TYPE, null).iterateNext();
console.log(FIRST_RECORD);
var str = FIRST_RECORD.toString();
document.getElementById('dock01').insertAdjacentHTML('beforeend', str);
<section id='dock01'></section>
Demo 2
/* Collect all elements with an #id that starts with "tweet"
|| Convert NodeList into an array
*/
var tweets = Array.from(document.querySelectorAll("[id^=tweet]"));
/* filter() the array tweets
|| if an item has data-id = "retweet"
|| add it to the new array retweets
*/
var retweets = tweets.filter(function(t) {
return t.dataset.id === "retweet";
});
console.log(retweets);
/* The lazy way to add text */
li::after {
content: attr(id);
}
/* This is just so the console results don't obscure the Demo*/
.as-console-wrapper {
width: 70%;
margin-left: 30%;
}
.as-console-row:after {
display: none !important;
}
<ol>
<li id='tweet-51515151' data-id='retweet'></li>
<li id='tweet-57885157' data-id='tweet'></li>
<li id='tweet-51677459' data-id='tweet'></li>
<li id='tweet-51890331' data-id='retweet'></li>
<li id='tweet-51515337' data-id='retweet'></li>
<li id='tweet-51593051' data-id='retweet'></li>
<li id='tweet-51333333' data-id='tweet'></li>
<li id='tweet-51534152' data-id='tweet'></li>
<li id='tweet-51599951' data-id='tweet'></li>
<li id='tweet-54785151' data-id='retweet'></li>
<li id='tweet-56785199' data-id='retweet'></li>
<li id='tweet-51557844' data-id='tweet'></li>
<li id='tweet-51510000' data-id='retweet'></li>
</ol>
I have a list which looks kind of like this:
<ul class="mylist">
<li>AAA</li>
<li>AAA</li>
<li>AAA</li>
<li>BBB</li>
<li>BBB</li>
<li>CCC</li>
</ul>
I would now like to add the first letter of the content above the content group.
Here is an example of how the result would look:
<ul class="mylist">
<li><strong>A</strong></li>
<li>AAA</li>
<li>AAA</li>
<li>AAA</li>
<li><strong>B</strong></li>
<li>BBB</li>
<li>BBB</li>
<li><strong>C</strong></li>
<li>CCC</li>
</ul>
How can I do this?
Fairly simple with jQuery - see the code comments for explanation.
// shorthand for on document load
$(function() {
// a variable to store our current first letter
var currentFirstLetter;
// for every child of mylist
$('.mylist').children().each(function() {
// take the first character of its content
var thisLetter = $(this)[0].innerHTML.substr(0,1).toLowerCase();
// if its different to our current first letter then add the required element
// and update our current first letter
if (thisLetter !== currentFirstLetter) {
$(this).before("<li><strong>" + thisLetter.toUpperCase() + "</strong></li>");
currentFirstLetter = thisLetter;
}
});
});
jsFiddle
I am making a simple web app. In one part of it, I have:
<ul class="sortable list-group">
<li id="firstTag" class="tags list-group-item">
<span id="present-count" class="badge"></span>
</li>
I have to access both the li element with id="firstTag" and the span element with id="present-count".
Anyhow, I am able to access only one, if I remove the id="firstTag", I am easily able to acess the span, anyhow, in presence of it, js gives the error: "cannot set property "innerHTML" of null" for the statement:
document.getElementById("present-count").innerHTML = something;
EDIT:
Both are being called in window.onload function with "firstTag" called before "present-count". See this fiddle: http://jsfiddle.net/poddarrishabh/2xzX6/3/
This is what I want the output to look like:
where both the "Present" text and the number can be changed.(I am using bootstrap).
$("#firstTag #present-count").html();
add jquery file to your page and try this
Sounds like you want to create a text node:
var textNode = document.createTextNode("first");
document.getElementById("firstTag").appendChild(textNode);
document.getElementById("present-count").innerHTML = "something";
Or to put the text before the span:
var textNode = document.createTextNode("first");
var present = document.getElementById("present-count");
present.innerHTML = "something";
document.getElementById("firstTag").insertBefore(textNode, present);
Here is an updated Fiddle.
If you are just trying to put some text before the present-count span, then just add another span and target that instead of the wrapping li:
<ul class="sortable list-group">
<li id="firstTag" class="tags list-group-item">
<span id="another-tag"></span>
<span id="present-count" class="badge"></span>
</li>
document.getElementById("another-tag").innerHTML = "some text";
document.getElementById("present-count").innerHTML = "some more text";
Try this code snippet
document.getElementById("firstTag").innerHTML = document
.getElementById("firstTag")
.innerHTML
+ "first";
document.getElementById("present-count").innerHTML ="something";
Hope it helps.
Try adding this
document.getElementById("firstTag").innerHTML ='<span id="present-count" class="badge">'
+ '</span>'
+ ' first';
document.getElementById("present-count").innerHTML = 'something';
DEMO
You were getting this error because with the first
document.getElementById("firstTag").innerHTML = "first"
you were replacing the <span>, and your DOM looked like
<ul class="sortable list-group">
<li id="firstTag" class="tags list-group-item">
first
</li>
</ul>
Then you couldnt find the element with id present-count because it wasnt there.