Detect if a div with id including number is clicked - javascript

My html code has X elements, with their ids in this form:
viewer_mX
Here, X is a number from 1 to m (m can be different each time).
I want to use javascript to get the number X of the respective element when somebody clicks one of these elements.
I realise I should probably use a class (.viewer) and and id (#x) containing the number. However, I am using a library to generate the html elements and I am stuck with this protocol and will have to make the best of it.
This is the javascript I have so far:
$(document).ready(function () {
$("#viewer>...").click(function () {
x = ...
var number = x;
});
});
What's missing in this code (indicated by 3 dots) is that viewer is not the full ID, but could be post-pended with something. I want to store whatever is after the clicked div in number, but I can't figure out which function to use for that.

Try this,
$("[id^='viewer_']").click(function () {
var number = this.id.match(/\d+$/)[0];
});

Why not use class to identify elements and then data-attribute for storing your id (data-id for example) and then get value of this data-attribute?
Otherwise I would personally use something like this
$(this).attr('id').substr("viewer_m".length);

Either split or a reg exp
var id = this.id.split("_m")[1]
or
var id = this.id.match(/\d+$/)[0];
or better yet, use a data attribute
<div data-mid="123">
and reference it
$("[data-mid]").on("click", function () {
var id = $(this).data("mid");
});

A better approach to this, as #Wax Cage mentioned, is to use classes and data attributes for better organizing. Example:
<div class="viewer" data-viewer-id="1">...</div>
$('.viewer').on('click', function() {
var viewerId = $(this).data('viewerId');
// ...
});

Related

jQuery: Remove and Re-Add Classes

I've searched quite a bit before asking this question, but I may be searching / asking the wrong question:
I want to select the last two classes of an element (that has multiple classes and an unknown amount of classes) and store that in a variable. I then want to remove those two classes and add them back at a later point (like toggleClass). The first class is known, while the second class is unknown.
For instance:
<div class="c1 c2 c3 c-unknown"></div>
I would like to select c3 and c-unknown
I've tried split() and it seems like the solution, but I couldn't quite get it to work.
I appreciate any help / guidance you can offer.
You could store them on the element itself allowing to isolate multiple instances
Following solution doesn't need classes to be in any specific order or matter how many classes are on element.
$('.c1').each(function () {
/* array of classes on elemnt*/
var classes = $(this).attr('class').split(' ');
/* remove the targeted selector from array */
classes.splice(classes.indexOf('c1'), 1);
/* remove the extra classes from element and store */
$(this).removeClass(classes.join(' ')).data('classes', classes);
});
For a specific element could also use attr(function)
$('.c1.Specific').attr('class', function(_, existingClasses){
var classes = existingClasses.split(' ');
classes.splice(classes.indexOf('c1', 1));
$(this).data('classes', classes);
return 'c1';
});
Then to re-use the stored classes
var $el = $('.c1:first');
$el.addClass( $el.data('classes').join(' '))
DEMO
Probably the easiest way to get the last two classes:
var lastTwoClasses = $('.c1').attr('class').split(/\s+/).slice(-2).join(' ');
Toggle (for example with button id="btn"):
$('#btn').click(function(){
$('.c1').toggleClass(lastTwoClasses);
});
JSFiddle
EDIT.
And yet another way:
$('.c1').each(function(){
var classes = $(this).attr('class').split(/\s+/).slice(-2).join(' ');
$(this).click(function(){
$(this).toggleClass(classes);
});
});
JSFiddle
I believe this is what you're trying to do.
var ele = document.getElementsByClassName('c1'),
classes = ele[0].className,
classArr = classes.split(' '),
spliceIndex = classArr.length - 2,
last2Classes = classArr.splice(spliceIndex, 2);
Here's a working fiddle
If you're trying to remove the classes you can use jquery or you could just use the dom element's className property and set it to whichever array has the classes you want to use. You would use the array method .toString() on either array and it will give you a string representation of the classes.
The answer here could help you to get part of the functionality you need:
Get first and last class with jQuery
Starting with that, you could use split, and removeClass like this
(sample text and css added for demo purposes):
function removeTheClasses(el) {
var classes = el.attr("class").split(/\s/);
var second_to_last = classes[classes.length - 2]; //second to last class
var last = classes[classes.length -1]; //last class
el.removeClass(second_to_last, last);
}
$('button').click(function() {
removeTheClasses($('.c1'));
});
.c-unknown {font-weight:bold}
.c3 {color:pink}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="c1 c2 c3 c-unknown">
ABC
</div>
<br/>
<button>Remove the last two classes</button>
In order to add these same classes back in (toggling), you'd have to keep a record of the recently removed classes. This would require:
pushing the values of the first & last variables to a cookie or web storage (if handling multiple elements at a time), OR
a single javascript variable above the scope of the 'removeTheClasses' function (if you're just handling one element at a time).

iterate inside a new JQuery object

I need to pass some html code as a parameter, however, before I pass it, I need to change some src attribute values.
I cannot use lastIndexOf or any of those to modify the html value since I don't know which value the src's will have.
What I'm trying to do then, is to create an object containing the html, and then alter that object only. I don't want to alter the actual webpage.
is this possible??
What I did first was this:
$('[myImages]').each(function() {
var urlImg = "../tmpFiles/fileName" + counter;
$(this).attr('src', urlImg);
counter++;
});
So finally, I had the desired code like this:
myformData = { theChartCode: $('#TheDivContainingTheHTML').html() }
However, this actually changes the image sources on the webpage, which I don't want to.
Then I thought I could create a JQuery object with the html so I could alter that object only like this:
var $jQueryObject = $($.parseHTML($('#TheDivContainingTheHTML').html()));
But now, I can't figure out how to iterate within that object in order to change the src attribute's values of the desired images.
Any help will be really appreciated ;)
There are several ways to do It. First would be creating a clone of target element and use the same on the Fly. You can do like below:
var Elem = $('#TheDivContainingTheHTML').clone();
now do whatever you want like iterate, alter,insert,remove.
var allImages =$(Elem).children("img");
Thanks Much!
Depending on when you want to change the object, solution will be different. Let's pretend you want to change it after you click another element in the page. Your code will look like that :
var clonedHTML;
$('#clickable-element').click(function() {
var $originalHTML = $(this).find('.html-block');
var $cloneHTML = $originalHTML.clone();
$cloneHTML.find('.my-image').attr('src', 'newSrcValue');
clonedHTML = $cloneHTML.clone();
return false; //Prevents click to be propagated
});
//Now you can use `clonedHTML`
The key point here is the clone method : http://api.jquery.com/clone/.
You can clone the elements:
var outerHTML = $collection.clone().attr('src', function(index) {
return "../tmpFiles/fileName" + index;
}).wrapAll('<div/>').parent().html();
You can also use the map method:
var arr = $collection.map(function(i) {
return $(this).clone().attr('src', '...').prop('outerHTML');
}).get();

Javascript array not working as expected

I'm pretty new to js/jquery. For each checkbox with the ID of check$ (where $ is a sequential number), I want to toggle the class "agree" of the surrounding span that uses the same check$ (but as a class). I don't want to have to hard-code the list of matching checkboxes, as this may vary.
Here's my code. This function works as expected:
agree = function (checkbox, span) {
$(checkbox).change(function(){
$(span).toggleClass('agree');
});
};
This is what I'm trying to pass to the above function, which does not work:
$(function() {
var elemid = 'check',
checks = Array($('[id^='+elemid+']').length);
console.log(checks);
for (i=0; i < checks; i++) {
agree('#'+elemid+checks[i], "."+elemid+checks[i]);
}
});
console.log(checks) returns [undefined × 4]. The number of elements is correct, but I don't know why it's undefined, or whether that is even significant.
The following code works as expected, but as I say, I'd rather not have to specify every matched element:
$(function() {
var checks = ["check1", "check2", "check3", "check4"];
for (i=0; i < checks.length; i++) {
agree('#'+checks[i], "."+checks[i]);
}
});
Thanks.
Edit: Thanks to Jack, I was overlooking the most simple method. I added the same class to all checkboxes and spans, and solved the problem with this:
$('input.check').change(function(){
$(this).closest('span.check').toggleClass('agree');
});
I might be totally missing something, but I'm pretty sure you are just trying to attach a change handler to each checkbox. In this case you can give them all the same class. I'm also guessing at your html structure for the span.
For reference:
http://api.jquery.com/closest/
http://docs.jquery.com/Tutorials:How_jQuery_Works
$('.yourcheckboxclass').change(function(){ //grab all elements with this class and attach this change handler
$(this).closest('span').toggleClass('agree');
});
The reason that the array is full of undefined values, is that you are just getting the number of items in the jQuery object, and create an array with that size. The jQuery object is discarded.
Put the jQuery object in the variable instead:
var elemid = 'check', checks = $('[id^='+elemid+']');
checks.each(function(){
agree(this, "."+elemid+checks[i]);
});

call to a function that changes picture every 2 seconds

i have a picture and i want to change it every 2 seconds when my mouse is on it.
so i write:
$("#profilePic").mouseover(function() {
var t = setTimeout("pictureChanger()",2000);
});
and this is the function:
function pictureChanger() {
currentPicture++;
currentPicture = currentPicture % NUM_PICTURES;
$("#profilePic").src = pictures[currentPicture];
}
it doesn't work.. however when i write $("#profilePic").src = pictures[currentPicture]; inside the function of mouseover it does replace the picture. so i guess the problem is with the function pictureChanger..
how to i fix it so that the function will replace my pictures?
thank you!
Use the .attr() function to set attributes in jquery:
$('#profilePic').attr('src', pictures[currentPicture]);
Or get the underlying DOM element from the array of matched elements by the selector:
$('#profilePic').get(0).src = pictures[currentPicture];
The first is prefered because if the selector doesn't match any DOM elements the code will break whereas with the first example it will do nothing.
Try to remove the () and the quotes of the function name in the setTimeout:
var t = setTimeout(pictureChanger,2000);

More efficient way script the heights of DIVs

Im using this script to find the height of a DIV. I am using it on more than one DIV.
Is there a more efficient way to write this code?
$(document).ready(function() {
$(".block00").height($(".subheader").height());
$(".block01").height($(".subheader").height());
$(".block02").height($(".subheader").height());
});
No need to list each one separately or make a loop as you can just list multiple items in the selector and it will return all of them.
$(document).ready(function() {
$(".block00, .block01, .block02").height($(".subheader").height());
});
or a little more efficiently:
$(document).ready(function() {
var h = $(".subheader").height();
$(".block00, .block01, .block02").height(h);
});
or, if you control the HTML source, add a common class on all the blockXX objects so you can do this:
$(document).ready(function() {
var h = $(".subheader").height();
$(".blockCommon").height(h);
});
Remember, you can have more than one class per object. Using a common class among several objects is precisely for the situation where you want to treat a number of objects the same way.
$(document).ready(function() {
var h=$(".subheader").height();
for(var i=0;i<3;i++)$(".block0"+i)height(h.height());
});
might work

Categories

Resources