I have a div element with lots of descendent's elements, all with ids in the form "word1", for a simple example: id="moviment1" or id="type1".
I need to get only the written part of these ids (moviment or type), in order to concatenate their names with a increment of 1 (id="moviment2" or id="type2").
$clone.find('*').each(function() {
var id = $(this).prop('id');
var num = parseInt( $(this).prop("id").match(/\d+/g), 10 ) +1;
$(this).prop('id', id+num);
});
The way it is, I always get ids like id="moviment12". I already tried:
var id = $(this).prop('id').replace(/\d+/g, '');
or
var id = $(this).prop('id').match(/\w+/);
But I always get errors like "cannot read property 'replace'/'match' of undefined". So, what am I doing wrong? Any other ideas? Thank you very much!
Ideally you should use a template. Traversing and modifying parsed elements makes your code slow and hard to maintain.
If you want to increment the number part of the IDs by 1 you can use the replace method callback function:
$clone.find('[id]').prop('id', function(_, id) {
// Assuming `id` is `test_25_segment`
return id.replace(/(\d+)/, function(num) {
// |
// --- is 25
return +num + 1;
// |
// --- parses the matching string into integer
});
});
Here is a demo using the above snippet.
Easiest way, you could just add those values as data-attr:
<div id="type1" data-id="1" data-text="type"></div>
So you can easily get them separated just using .data('id') and .data('text').
You may select the elements by this way:
var all = [].filter.call(document.querySelectorAll('[id*=type]'), function(el) {
return (/\btype\d+\b/).test(el.id);
});
and then you can change the ids using methods like replace()
Try this...
var onlyAlphabets = id.split(/(\d)/)[0];
Related
I have this function that I am trying to figure out/fix and can't seem to pinpoint the issue / can't figure out a way to get it working.
Basically my CMS is spitting certain hrefs that I would like to:
Part 1) change the targeted href URL
Part 2) change the button's text
Right now I only have 2 instances of this type of button, so here's what is printing out in my console:
Part 1) for this part I get the correct urls without the characters i want to strip out.
Part 2) two instances of the button's text (See All) followed by the correct variable of btnParent for the first button and then the second button and finally one instance of "Products".
My issue is, I can't figure out how to:
Part 1) send back the stripped URL to its respective button's href as an each function.
Part 2) Have the each() function print out the new text as "See All + BLAH + Products" for each instance, and then append the new text to the respective button.
Here is the code:
function viewMoreBtn() {
var btnMain = $("li:contains('See All')");
var btnText = $("li:contains('See All')").text();
var btnParent = $("li:contains('See All')").parent('ul').prev('li').text();
// PART 1 - STRIP LINK URL OF -_-// CHARACTERS
$.each(btnMain, function(i, v) {
v = $(this).find('a').attr('href').replace('-_-//', '');
console.log(v);
});
// PART 2 - ADD LABEL TO HTML TEXT OF BTN
$.each(btnMain, function(index, value) {
value = (btnText + btnParent + 'Products');
$(btnMain).text(value);
console.log(value);
});
}
viewMoreBtn();
Thank you.
jQuery objects, as return by $(...) have a each method already on them. The element is passed as the this context. You could use that further with jQuery to act on the objects in an scoped context. Basically, you have the right code, just in the wrong scope.
Part 1
btnMain.each(function() {
var $li = $(this);
var $a = $li.find('a');
var desiredUrl = $a.attr('href').replace('-_-//', '');
$a.attr('href', desiredUrl);
});
Part 2
btnMain.each(function() {
var $li = $(this);
var btnText = $li.text();
varbtnParent = $li.parent('ul').prev('li').text();
value = (btnText + btnParent + 'Products');
console.log(value);
$li.find('a').text(value);
});
See #Zequ's answer for the iteration over the each() function in the returned btnMain.
This is how $.each( obj, function( key, value ) works: you iterate over btnMain, and for each iteration of $.each(), the function assigns the index of the iteration to i and the value of btnMain at that index to v.
$.each(btnMain, function(i, v) {
//v = $(this).find('a').attr('href').replace('-_-//', '');
console.log(i); // I am the index of $.each() iterator
console.log(v); // I am the node from the btnMain array
// I don't know if this is right without seeing your HTML, but it seems like what you want
v.find('a').attr('href').replace('-_-//', '');
});
The second $.each() follows the same pattern.
If I understood correctly, you're confusing your variables.
$.each is a function for each element of the array/object being passed. It gives you a index and the element, check the reference
In part 1, you're defining v as the string you want, you're not changing the element at all,you need something like this:
$.each(btnMain, function() {
// you're saying you got the correct URLs, so the only thing you need to do is to change the element afterwards
var element = $(this).find('a');
v = element.attr('href').replace('-_-//', '');
element.attr('href', v);
});`
Also you could use btnMain.each instead of $.each
In part 2, you are changing the value variable (it's actually the element you're iterating over), to the string you want, then you follow it by trying to change btnMain's text. This is wrong, from what I understood, btnMain is an array of two elements you can't change it's text. You should change the element's value (that you are calling value). It would be something like that
$.each(btnMain, function(index, element){
// I think this is the time you want to define the btnParent, relative to the element
var btnParent = element.parent('ul').prev('li').text();
var value = (btnText + btnParent + 'Products');
element.text(value);
}
I THINK this is what you need.
Also you could append both parts into one, since both are iterating over btnMain
i'm still new in html javascript. I want to ask can i use for loop to optimize or make this dynamic
var port = [];
port[0]=$('#slcPort_0').val();
port[1]=$('#slcPort_1').val();
port[2]=$('#slcPort_2').val();
port[3]=$('#slcPort_3').val();
port[4]=$('#slcPort_4').val();
i used this code in function to retrieve data from html form
thanks
You could use:
// selects all the elements whose 'id' starts-with "slcPort_":
var port = $('[id^=slcPort_]').map(function(){
// returns the value from those elements:
return this.value;
// converts to an array:
}).get();
This isn't guaranteed to be in numerical order, though it will be in order of the appearance of those elements in the DOM.
References:
Attribute-starts-with ([attribute^=value]) selector.
get().
map().
Simply, you can do the following:
var port = Array();
for (i = 0; i < 5; i++){
port[i] = $("#slcPort_"+i).val();
}
DEMO: http://jsbin.com/yiyaruweja/1/
It might make more sense to give all those elements a class, like slcPort. Then something like
var port = [];
$.each($('.slcPort'), function(index,value) {
port[index] = $(value).val();
});
Much prettier. Plus all those elements are related anyways, so just class em up.
$.each documentation
I've multiple autogenerated forms on a page. They are named in a particular manner like:
form-0-weight, form-1-weight, form-2-weight etc.
<ul>
<li>
<input id="id_form-0-weight" type="text" name="form-0-weight">
<a class="deleteIngredient" href="">x</a>
</li>
<li>
....more forms
</li>
</ul>
The user can add and delete forms. If a form get's deleted, the remaining ones should be renamed to stay in order. e.g. "form-1-weight" gets deleted >> "form-2-weight" will be renamed to "form-1-weight".
The total number of forms is stored in a hidden field named TOTAL_FORMS.
I'm trying to achieve this with a simple for loop.
The problem is that all the forms after the deleted one get the same name.
e.g. If I delete form-2-weight, all the following forms get the name form-2-weight instead of 2, 3, 4 etc.
$(".deleteIngredient").click(function(e){
e.preventDefault();
var delete = $(this).closest('li');
name = delete.children('input').attr("name");
count = name.replace(prefix,'');
count = name.replace("-weight",'');
var formCount = parseInt($("#TOTAL_FORMS").val())-1;
delete.remove();
for (var i = parseInt(count); i<=formCount; i++){
var newName = "form-"+i+"-weight";
$("#id_form-"+(i+1)+"-weight").attr("name",newName);
}
});
I suppose it has something to do with how I select the elements inside the loop because when I use just the variable "i" instead of "newName" it works as expected.
The problem is you're not initializing i properly.
This happens because "count" doesn't contain a string that can be parsed into an integer under the conditions of parseInt, I suggest you look here:
w3Schools/parseInt
Note: If the first character cannot be converted to a number, parseInt() returns NaN.
When you assign a string to "count" you're actually inserting the string "form-i" into the variable.
What you should do is this:
count = name.replace(prefix,'');
count = count.replace("-weight",'');
You should also rename your "delete" variable to "form" or any other descriptive name, as delete is a reserved word in javascript and also an action so it doesn't really suit as a name for an object.
Don't forget to change the id attribute of the item so it'll fit the new name.
As a note, you should probably consider following through some tutorial on Javascript or jQuery, Tuts+ learn jQuery in 30 days is one i'd recommend.
My first impulse is just to solve this a different way.
Live Demo
var $ul = $('ul');
// Add a new ingredient to the end of the list
function addIngredient() {
var $currentIngredients = $ul.children();
var n = $currentIngredients.length;
var $ingredient = $('<li>', {
html: '<input type="text" /> x'
});
$ul.append($ingredient);
renameIngredientElements();
}
// Rename all ingredients according to their order
function renameIngredientElements() {
$ul.children().each(function (i, ingredient) {
var $ingredient = $(ingredient);
var $input = $ingredient.find('input');
var name = 'form-' + i + '-weight';
$input
.attr('id', 'id_' + name)
.attr('name', name);
});
}
// Delete an ingredient
function deleteIngredient($ingredient) {
$ingredient.remove();
renameIngredientElements();
}
// Bind events
$('.add-ingredient').on('click', addIngredient);
$ul.on('click', '.delete-ingredient', function (event) {
var $ingredient = $(event.currentTarget).closest('li');
deleteIngredient($ingredient);
event.preventDefault();
});
As to why your particular code is breaking, it looks like user2421955 just beat me to it.
I have an array with divs ids (in my case its all divs ID values od parent div (#area) ):
jQuery.fn.getIdArray = function () {
var ret = [];
$('[id]', this).each(function () {
ret.push(this.id);
});
return ret;
};
var array = $("#area").getIdArray();
I need to get an array field value, something like this:
var lef = $("#array".[0]).css("left");
Taking a wild swing at it (see my comment on the question):
var array = $("#area").getIdArray();
var lef=$("#" + array[0]).css("left");
That assumes that getIdArray returns an array of strings, where each string is an id value for a DOM element, and that you want to get the left value for the first of those elements.
So for instance, if the array comes back as:
["foo", "bar", "charlie"]
then the selector created by "#" + array[0] is #foo, so you end up getting the left value for the foo element.
If you have an actual JS array within your variable array just use bracket notation to access each individual ID.
// I have the # before-hand since I'm assuming you have just the ID name
var lef = $('#' + array[0]) // this will access the 1st one in the array
I think you are looking for this :
var divYouWantToChange = $("#"+array[0]);
I try to formulate this as an answer because getIdArray is not a jquery function and we don't know what it does. If you'd like to apply a custom filter to the $("#area") collection you can do so using filter. This will return a jquery object where you can get the .css("left") from.
If you'd like to save both the id's and the left property you can do so with the following code:
var objects=[];
$("#area").filter(function(){
$this=$(this);//cache the object
objects.push({id:$this.attr("id"),
left:$this.css("left")
};
});
console.log(objects);
I have a list of 8 divs: #video1, #video2, ... with each the same javascript actions to run when clicked, but with other id's (for #video1: show #image1, #preview1, ...).
Instead of writing 8 times the same code but with other id's, can I do this more efficient? Is it possible to take the sixth caracter (the number) from each #videoX as a variable when clicked, and use
this in the code?
Inside your event handler, you can extract the number, e.g. with a regular expression [MDN]:
var id = element.id.match(/\d+$/)[0];
and then use it to create the IDs of the other elements:
var image_id = "image" + id,
preview_id = "preview" + id;
Another option would be to assign data- attributes to the elements and use them to store the numerical part of the ID.
Use a class name instead. This way it's independent of the IDs completely.
<div class="videoClick" id="...">...</div>
JS:
$('.videoClick').click(function() {
...
})
yes you can:
$("div[id*='video']").click(function() {
var numid = $(this).attr("id").replace("video", "");
alert(numid);
//...use your numid value
});
Check attribute contains selector.
Try this
var ids = [#video1, #video2, #video3, #video4, #video5, #video6, #video7, #video8];
$(ids.join(",")).click(function(){
var imageId = this.id.replace("video", "image");
var previewId = this.id.replace("video", "preview");
$("#"+imageId).show();
$("#"+previewId).show();
});