using jquery next to find "nested" sibling - javascript

Perhaps there is a simple solution to this, but I am not able to figure it out.
I have a bunch of images sitting like this:
<div class='image-bar'>
<span>
<img class='my-image' src='blah1' id='1'>
</span>
<span>
<img class='my-image' src='blah2' id='2'>
</span>
<span>
<img class='my-image' src='blah3' id='3'>
</span>
</div>
Given the id of an image, I need to find the next and previous image to it, using jQuery.
Using 2 as example I tried following to get next image:
$('.image-bar').find('.my-image[id="2"]').next();
I think until my 'attribute equals' selector I am correct, but since the image with id 3 is not exactly a sibling, the next() is not working. How can I handle this? Any pointers are greatly appreciated!

This wont' work because the elements are wrapped in spans, you need to go relative to the parents of the images instead.
var next = $('.image-bar').find('.my-image[id=2]').parent().next().find('img');
var prev = $('.image-bar').find('.my-image[id=2]').parent().prev().find('img');
EDIT
Assuming you may have more images to deal with and are interested in the same functionality, you can do the following:
var elementId = "2";
var next = $('.image-bar').find('.my-image[id=' + elementId + ']').parent().next().find('img');
var prev = $('.image-bar').find('.my-image[id=' + elementId + ']').parent().prev().find('img');

If you have the id names in sequence I have another solution
var imgArray = $(".my-image"); // this will have an array with all images
Find image with id = 2
var id = 2;
imageArray[id-1]; // returns image with id 2
Find next image
imageArray[id];
Find previous image
imageArray[id-2];
NB: you need to check if the array index exists.
Fiddle here
var imgArray = $(".my-image"); // this will have an array with all images
console.log( getImage(2/* image id */, "next"));
function getImage(id, pos) {
var returnImage;
if(pos === "next") {
returnImage = imgArray[id] ? imgArray[id] : "";
}
else if(pos === "prev") {
returnImage = imgArray[id - 2 ] ? imgArray[id - 2] : "";
}
else {
returnImage = imgArray[id-1] ? imgArray[id-1] : "";
}
return returnImage;
}

Try using .filter() , .index() , .slice()
var imgs = $(".image-bar img");
var curr = imgs.filter("#2");
var i = curr.index(imgs.selector);
var prev = imgs.slice(i - 1, i);
var next = imgs.slice(i + 1, i + 2);
console.log("curr:"+curr[0].id
, "curr index:" + i
, "prev:" + prev[0].id
, "next:" + next[0].id);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div class='image-bar'>
<span>
<img class='my-image' src='blah1' id='1'>
</span>
<span>
<img class='my-image' src='blah2' id='2'>
</span>
<span>
<img class='my-image' src='blah3' id='3'>
</span>
</div>

Related

Alternative for document.getElelementById() for several IDs/elements

I know that document.getElementById() won't work with several ids. So I tried this:
document.getElementsByClassName("circle");
But that also doesn't work at all. But if I use just the document.getElementById() it works with that one id. Here is my code:
let toggle = () => {
let circle = document.getElementsByClassName("circle");
let hidden = circle.getAttribute("hidden");
if (hidden) {
circle.removeAttribute("hidden");
} else {
circle.setAttribute("hidden", "hidden");
}
}
document.getElementsByClassName() returns a NodeList, and to convert it to an array of elements, use Array.from(). this will return an array containing all of the elements with the class name circle
Here is an example, which changes each element with the circle class:
const items = document.getElementsByClassName('circle')
const output = Array.from(items)
function change() {
output.forEach(i => {
var current = i.innerText.split(' ')
current[1] = 'hate'
current = current[0] + ' ' + current[1] + ' ' + current[2]
i.innerText = current
})
}
<p class="circle"> I love cats! </p>
<p class="circle"> I love dogs! </p>
<p class="square">I love green!</p>
<p class="circle"> I love waffles! </p>
<p class="circle"> I love javascript! </p>
<p class="square">I love tea!</p>
<button onclick="change()">Change</button>
You can try this.
const selectedIds = document.querySelectorAll('#id1, #id12, #id3');
console.log(selectedIds);
//Will log [element#id1, element#id2, element#id3]
Then you can do something like this:
for(const element of selectedIds){
//Do something with element
//Example:
element.style.color = "red"
}

Simpler Javascript counter

I need some help with the click event, I'm trying to have an individual counter that is incremented by the click event that I have on the img. I've tried many variations, I want to resolve this without using jQuery.
<script async>
var count = 0;
var clickerCount = document.getElementsByClassName('clicker');
var cat = {
count : 0,
counter: function(){
this.count++;
clickerCount.textContent = "Kitten Click Count :" + this.count;
console.log("counter function working");
console.log(cat.count);
}
};
function modifyNum(){
cat.counter();
console.log("modifyNum function working");
}
</script>
</head>
<body>
<div style="display:inline">
<div>
<img src="http://placekitten.com/200/296" id="cat0" onclick="modifyNum();">
<p id='clicker'>Kitten Click Count :</p>
</div>
<div>
<img src="http://placekitten.com/200/296" id='cat1' onclick="modifyNum();">
<p id='clicker'>Kitten Click Count :</p>
</div>
</div>
For a start, you are using id='clicker' in two places (IDs are supposed to be unique), and then using document.getElementsByClassName, which returns nothing because you used an ID and not a class.
Once you do change it to a class, document.getElementsByClassName will return an array of elements. You'll have to use clickerCount[0] and so on, or loop through the array.
This example should work. I've separated the HTML from the Javascript because it looks clearer for me. You can use it as an example to expand / create your own in your own way.
Hope it help
HTML:
<div style="display:inline">
<div>
<img src="http://placekitten.com/200/296" id="1" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-1">0</span>
</div>
<div>
<img src="http://placekitten.com/200/296" id="2" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-2">0</span>
</div>
</div>
JS:
var imagesCountable = document.getElementsByClassName("countable");
var counters = [];
for (var i = 0; i < imagesCountable.length; i++) {
counters[imagesCountable[i].id] = 0;
imagesCountable[i].onclick = function(e) {
document.getElementById("counter-for-" + e.currentTarget.id)
.innerHTML = ++counters[e.currentTarget.id];
}
}
var imagesCountable = document.getElementsByClassName("countable");
var counters = [];
for (var i = 0; i < imagesCountable.length; i++) {
counters[imagesCountable[i].id] = 0;
imagesCountable[i].onclick = function(e) {
var cElem = document.getElementById("counter-for-" + e.currentTarget.id);
cElem.innerHTML = ++counters[e.currentTarget.id];
}
}
<div style="display:inline">
<div>
<img src="http://placekitten.com/200/296" id="1" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-1">0</span>
</div>
<div>
<img src="http://placekitten.com/200/296" id="2" class="countable">
<span>Kitten Click Count :</span><span id="counter-for-2">0</span>
</div>
</div>
I have solved this problem in this JSFiddle!
If you can hardcode the IDs then it's easier in my point o view to just manipulate things by ID.
<div>
<img src="http://placekitten.com/200/296" id="cat0" onclick="counter(0);">
<p id='clicker0'>Kitten Click Count :</p>
<input type="hidden" id="counter0" value="0">
</div>
function counter(id) {
var cnt = parseInt(document.getElementById("counter" + id).value);
cnt++;
document.getElementById("counter" + id).value = cnt;
document.getElementById('clicker' + id).innerHTML = 'Kitten Click Count :' + cnt;
}
It's not the same approach but I find it easy to understand.
Hope it helps.
Ok, so first off you have two elements with the id of 'clicker'. You probably meant for those to be classes and ids. So when you call modifynum() it cant locate those because the class doesn't exists. Second, your JS is loading before your HTML elements. So when the JS gets to this line:
var clickerCount = document.getElementsByClassName('clicker');
It is going to find nothing, even if you correct the class names. So you want to move your JS to the footer of your HTML document, or wrap the code in a method that is called on pageLoad().
I think that should take care of it. Your object, for the most part, looks correct.

Display random image with fitting link

I'm using the below code to show random images which works fine. How can I add to this code so that each image gets it's own link? I.e. if "knife.png" is randomly picked I want it to have a link that takes the user to "products/knife.html" and so on.
Thanks for any help!
<div id="box">
<img id="image" /></div>
<script type='text/javascript'>
var images = [
"images/knife.png",
"images/fork.png",
"images/spoon.png",
"images/chopsticks.png",];
function randImg() {
var size = images.length
var x = Math.floor(size * Math.random())
document.getElementById('image').src = images[x];
}
randImg();
Generalize your list of images so that that it can be multi-purposed - you can add additional information later. Then surround the image by an anchor tag (<a>) and use the following.
<div id="box">
<a name="imagelink"><img id="image" /></a>
</div>
<script type='text/javascript'>
var images = ["knife","fork","spoon","chopsticks",];
function randImg() {
var size = images.length
var x = Math.floor(size * Math.random())
document.getElementById('image').src = "images/"+images[x]+".png";
document.getElementById('imagelink').href="products/"+images[x]+".html";
}
</script>
randImg();
Try doing something like this example. Like all these other guys have said, it's better to store this info in a database or something, but to answer your question, put the values you need into an object in the array and reference the properties of the object instead of just having a string array.
<div id="box">
<a id="a"><img id="image" /></a>
</div>
<script type='text/javascript'>
var images =
[
imageUrlPair = { ImgSrc:"http://www.dansdata.com/images/bigknife/bigknife1280.jpg", Href:"http://reluctantgourmet.com/tools/cutlery/item/267-chefs-knife-choosing-the-right-cutlery" },
imageUrlPair = { ImgSrc:"http://www.hometownsevier.com/wp-content/uploads/2011/01/fork.jpg", Href:"http://eofdreams.com/fork.html" },
imageUrlPair = { ImgSrc:"http://upload.wikimedia.org/wikipedia/commons/9/92/Soup_Spoon.jpg", Href:"http://commons.wikimedia.org/wiki/File:Soup_Spoon.jpg" },
imageUrlPair = { ImgSrc:"http://upload.wikimedia.org/wikipedia/commons/6/61/Ouashi.jpg", Href:"http://commons.wikimedia.org/wiki/Chopsticks" },
]
function randImg() {
var size = images.length;
var x = Math.floor(size * Math.random());
var randomItem = images[x];
document.getElementById('image').src = randomItem.ImgSrc;
document.getElementById('a').href = randomItem.Href;
}
randImg();
</script>
Surround the img with an a
<img id="image" />
Then add
document.getElementById("link").href = images[x].replace(".png",".html");
The .replace is a bit crude, but you get the idea.
You can use a convention based approach. In this case the convention is that each product, will have an associated image at "/image/[product]/.png" and a page at "products/[product].html"
<div id="box">
<a id="link"><img id="image" /></a></div>
<script type='text/javascript'>
var products = [
"knife",
"fork",
"spoon",
"chopsticks",];
function randImg() {
var size = images.length
var x = Math.floor(size * Math.random())
document.getElementById('image').src = "/images/" + products[x] + ".png";
document.getElementById('link').setAttribute("href", "products/" + products[x] + ".html");
}
randImg();
this is a very naive approach that won't scale very well. for example, if you have a list of products that changes frequently, or, you need to keep track of the number of available units. a more robust approach would be to store information about your products in a database, and a page that displays the data about a given product (a product detail page), and then use a data access technology to fetch a list of products for display in a product list page (similar to what you have here, except the list of products isn't hardcoded) and then each product would link to the product detail page.

How to get the html element from jquery object

I have a html like follows.
<tr class="meta-info" id="${page.id}">
<td>
<div class="pull-left">
<font size="1">
Like
</font>
</div>
<div class="pull-right" style="font-size:1">
<span class="badge"><i class="icon-thumbs-up"></i>1</span>
</div>
</td>
</tr>
I am trying to increase the number of likes when ever the user cliks on Like hyperlink.
Here is my jquery code. I want to know how i can get the html element from the jquery object.
$(".like").click(function(event){
var parentTr = $(event.target).closest("tr");
if(parentTr.length){
var pageId = parentTr.attr("id");
var spanEle = parentTr.get(0)+" div span:first-child"; ------(1)
var lastNumber = parseInt(spanEle.text());
spanEle.text(lastNumber+1);
}
});
I don't know if i am doing right on line which is marked 1.
I think you need to add an extra <span> tag so that you can replace the count without touching the adjacent icon
<span class="badge"><i class="icon-thumbs-up"></i>
<span class="like-count">1</span>
</span>
then you can address it
$(".like").click(function() {
var spanEle = $(this).closest('tr').find('.like-count').first();
if (spanEle.length) {
var newCount = parseInt(spanEle.text());
spanEle.text(newCount + 1);
}
});
In an event handler, the this reference is event.target. You may be able to handle the element doesn't exist case neater than that too but that way's safe.
JSFiddle demo: http://jsfiddle.net/rupw/VfCvK/
Try this...
$(".like").click(function(event) {
var parentTr = $(event.target).closest("tr");
if (parentTr.length) {
var pageId = parentTr.attr("id");
var spanEle = parentTr.first('.badge');
var lastNumber = parseInt(spanEle.text(), 10);
spanEle.text(lastNumber + 1);
}
});
If the span element always has that classname then it will find the first (only?) one and return an int value of the text within.
Try: Fiddle
var lastNumber = parseInt(parentTr.find('.pull-right span').text(), 10);
You code will look like:
$(".like").click(function(event) {
var parentTr = $(event.target).closest("tr");
if (parentTr.length) {
var pageId = parentTr.attr("id");
var spanEle = parentTr.find('.pull-right span');
var lastNumber = parseInt(spanEle.text(), 10);
spanEle.text(lastNumber + 1);
}
});
Update: If you wish to keep the <i> tag then use:
spanEle.html(spanEle.html().replace(lastNumber, lastNumber + 1));
insteadof : spanEle.text(lastNumber + 1);
Sample

How to get child element by ID in JavaScript?

I have following html:
<div id="note">
<textarea id="textid" class="textclass">Text</textarea>
</div>
How can I get textarea element? I can't use document.getElementById("textid") for it
I'm doing it like this now:
var note = document.getElementById("note");
var notetext = note.querySelector('#textid');
but it doesn't work in IE(8)
How else I can do it? jQuery is ok
Thanks
If jQuery is okay, you can use find(). It's basically equivalent to the way you are doing it right now.
$('#note').find('#textid');
You can also use jQuery selectors to basically achieve the same thing:
$('#note #textid');
Using these methods to get something that already has an ID is kind of strange, but I'm supplying these assuming it's not really how you plan on using it.
On a side note, you should know ID's should be unique in your webpage. If you plan on having multiple elements with the same "ID" consider using a specific class name.
Update 2020.03.10
It's a breeze to use native JS for this:
document.querySelector('#note #textid');
If you want to first find #note then #textid you have to check the first querySelector result. If it fails to match, chaining is no longer possible :(
var parent = document.querySelector('#note');
var child = parent ? parent.querySelector('#textid') : null;
Here is a pure JavaScript solution (without jQuery)
var _Utils = function ()
{
this.findChildById = function (element, childID, isSearchInnerDescendant) // isSearchInnerDescendant <= true for search in inner childern
{
var retElement = null;
var lstChildren = isSearchInnerDescendant ? Utils.getAllDescendant(element) : element.childNodes;
for (var i = 0; i < lstChildren.length; i++)
{
if (lstChildren[i].id == childID)
{
retElement = lstChildren[i];
break;
}
}
return retElement;
}
this.getAllDescendant = function (element, lstChildrenNodes)
{
lstChildrenNodes = lstChildrenNodes ? lstChildrenNodes : [];
var lstChildren = element.childNodes;
for (var i = 0; i < lstChildren.length; i++)
{
if (lstChildren[i].nodeType == 1) // 1 is 'ELEMENT_NODE'
{
lstChildrenNodes.push(lstChildren[i]);
lstChildrenNodes = Utils.getAllDescendant(lstChildren[i], lstChildrenNodes);
}
}
return lstChildrenNodes;
}
}
var Utils = new _Utils;
Example of use:
var myDiv = document.createElement("div");
myDiv.innerHTML = "<table id='tableToolbar'>" +
"<tr>" +
"<td>" +
"<div id='divIdToSearch'>" +
"</div>" +
"</td>" +
"</tr>" +
"</table>";
var divToSearch = Utils.findChildById(myDiv, "divIdToSearch", true);
(Dwell in atom)
<div id="note">
<textarea id="textid" class="textclass">Text</textarea>
</div>
<script type="text/javascript">
var note = document.getElementById('textid').value;
alert(note);
</script>
Using jQuery
$('#note textarea');
or just
$('#textid');
$(selectedDOM).find();
function looking for all dom objects inside the selected DOM.
i.e.
<div id="mainDiv">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
<div id="innerDiv">
link
<p>Paragraph 3</p>
</div>
</div>
here if you write;
$("#mainDiv").find("p");
you will get tree p elements together. On the other side,
$("#mainDiv").children("p");
Function searching in the just children DOMs of the selected DOM object. So, by this code you will get just paragraph 1 and paragraph 2. It is so beneficial to prevent browser doing unnecessary progress.

Categories

Resources