Value of variable changing over time inside function w/o reassignment - javascript

<script>
document
.getElementById('country')
.addEventListener('change', function() {
'use strict';
var value1 = this.value;
console.log(value1);
var vis = document.querySelectorAll('.input-group-addon'),
country = document.getElementsByClassName(value1);
console.log(country.length);
// Point One
var i;
if (vis !== null) {
for (i = 0; i < vis.length; i++)
vis[i].className = 'input-group-addon inv';
console.log(country.length);
// Point Two
}
if (country !== null) {
for (i = 0; i < country.length; i++) {
country[i].className = 'input-group-addon';
// Point Three
}
}
});
</script>
This has been bothering me for a while now. I am trying to get the value of a selected value in
document.querySelectorAll('.input-group-addon')
and find matching class names in
document.getElementsByClassName(value1)
The nodelist of country is available at Point One and changes to null at Point Two.
Is there a basic logic or syntax error in my code?

and changes to null at Point Two
I assume you mean that the list is empty. The variable should not magically become null.
getElementsByClassName returns a live HTMLCollection. Meaning it will always reflect the current state of document. If you change the class name of an element, it will automatically either be added or removed from the collection.
If you don't want that, then either use querySelectorAll, which returns a collection that is not live, or convert the collection to an array.

Related

MVC Model property not updated when accessed in javascript

I have this in my cshtml file:
#for (var i = 0; i < Model.Vehicles.Count; i++){
#Html.CheckBoxFor(m => Model.Vehicles[i].Selected)}
Basically Model.Vehicles is a List of vehicles and the Selected property is a bool...
I have a button that when clicked, calls this function:
function delSel(){
var vehicles = '#Html.Raw(Json.Encode(Model.Vehicles))';
var selIDs = "";
for(var i = 0; i < vehicles.length; i ++)
{
if (vehicles[i].Selected == "true") {
selIDs = selIDs + vehicles[i].ID + ",";
}
}
document.getElementById('CRVehicleIDs').value = selIDs;
}
My problem is, eventhough the Checkbox is checked, the value of the Selected property is always equal to false... Is there a better way to get the selected items in this case?
var vehicles = '#Html.Raw(Json.Encode(Model.Vehicles))';
This will not work as you are expecting, the razor syntax is rendered server side which means the value of this will not get updated when a user clicks on the checkboxes.
What you can do however is when you create you're checkboxes, give them an ID using i variable in your for loop.
#Html.CheckBoxFor(m => Model.Vehicles[i].Selected, new { id = "checkbx_" + i })
Then you can iterate through your checkboxes with a for loop.
function delSel(){
var vehicles = #Html.Raw(Json.Encode(Model.Vehicles));
var selIDs = "";
for(var i = 0; i < vehicles.length; i ++)
{
if (document.getElementById('checkbx_' + i).checked) {
selIDs = selIDs + vehicles[i].ID + ",";
}
}
document.getElementById('CRVehicleIDs').value = selIDs;
}
You're rendering this.Model.Vehicles to JSON which is then rendered within Javascript single-quotes - this will likely result in invalid Javascript syntax when accessed in a browser because JSON object property names are also enclosed in quotes.
Remove the quotes around #Html.Raw.
You would have spotted this if you looked at the rendered HTML of the page and saw that a large chunk of it would be covered in syntax errors.
Other tips:
JavaScript is typically styled with the opening brace on the same line as the keyword (as with Java), not the line below (as C#). It's also customary to use camelCase for JavaScript objects, not TitleCase. You should be able to customize your JSON-generator to use camelCase, refer to the documentation.
Boolean properties tend to be prefixed with Is, so it would be IsSelected (or isSelected in camelCase).
This is suboptimal:
if( vehicles[i].Selected == "true" ) {
Assuming that the Selected property is rendered as Javascript boolean value, you need only act on it directly:
if( vehicles[i].Selected ) {

delete specific xml node Javascript

My xml file is like:
it contains different 'object' nodes and in different objects there are different parameters one is deleted parameter.
I want to delete the all 'object' nodes that contains the deleted parameter 1.
This is the code that deletes the node object which has a parameter node deleted =1:
x=xmlDoc.documentElement;
for(var count=0; count<5;count++){
var y=x.getElementsByTagName("deleted")[count]; //Find that nodes arent
if(y.textContent == "1") {
var z=y.parentNode; //delete the node from the parent.
x.removeChild(z);
Xml2String1= new XMLSerializer().serializeToString(x);
}
}
Your loop is incorrect:
for(var x1=0; x1<5;x1++){
var y=x.getElementsByTagName("deleted")[x1];
Your loop runs for 5 iterations without regard for the number of <deleted> elements are found. Each time through the loop you search again and get a new NodeList/HTMLCollection of the remaining <deleted> elements, but your loop counter is incremented regardless.
Try this instead:
var deletedNodesList = x.getElementsByTagName("deleted");
var nodesToDelete = [];
for (var index = 0; index < deletedNodes.length ; index += 1)
{
var node = deletedNodes[index];
if (node.textContent == "1")
{
nodesToDelete.push( node.parentNode ); //delete the node from the parent
}
}
nodesToDelete.forEach( function() { x.removeChild(this); } );
Note that, per the documentation on MDN, the NodeList is a live collection, so don't modify it while you are processing it.
PS.
I second raam86's recommendation to use sane (meaningful) variable names. Meaningful variable names make it easier to understand the code, which makes it easier to write correct code and to resolve problems in incorrect code.

using for loop and if statement to check id names with numbers

for (var i = 1; i < 81; i++){
if($(this).hasClass('member-'+i)){
('promote'+i) = true;
}
}
I have 80 droppable boxes. They each has an id called member-1, member-2, etc., when someone drags an item into the boxes, the variable will be turned to true and be passed to another function.
So far I found this is not working. I wasn't sure why. It is inside a droppable drop function.
since I have 80 boxes...I don't feel like typing them out manually.
Make promote an array, rather than 80 different variables. Then you can do:
var promote = [];
for (var i = 1; i < 81; i++){
if($(this).hasClass('member-'+i)){
promote[i] = true;
}
}
Much better would be to just see what classes do exist rather than testing for 81 different classes:
var matches, promotes = [], cls = this.className;
var regex = /member-(\d+)/g;
while (matches = regex.exec(cls)) {
// matches[1] contains the number from the member-xx class name
promotes.push(parseInt(matches[1], 10));
}
// promotes is an array that contain a list of the member-xx numbers that exist
// on this object

Javascript getElementById based on a partial string

I need to get the ID of an element but the value is dynamic with only the beginning of it is the same always.
Heres a snippet of the code.
<form class="form-poll" id="poll-1225962377536" action="/cs/Satellite">
The ID always starts with poll- then the numbers are dynamic.
How can I get the ID using just JavaScript and not jQuery?
You can use the querySelector for that:
document.querySelector('[id^="poll-"]').id;
The selector means: get an element where the attribute [id] begins with the string "poll-".
^ matches the start
* matches any position
$ matches the end
jsfiddle
Try this.
function getElementsByIdStartsWith(container, selectorTag, prefix) {
var items = [];
var myPosts = document.getElementById(container).getElementsByTagName(selectorTag);
for (var i = 0; i < myPosts.length; i++) {
//omitting undefined null check for brevity
if (myPosts[i].id.lastIndexOf(prefix, 0) === 0) {
items.push(myPosts[i]);
}
}
return items;
}
Sample HTML Markup.
<div id="posts">
<div id="post-1">post 1</div>
<div id="post-12">post 12</div>
<div id="post-123">post 123</div>
<div id="pst-123">post 123</div>
</div>
Call it like
var postedOnes = getElementsByIdStartsWith("posts", "div", "post-");
Demo here: http://jsfiddle.net/naveen/P4cFu/
querySelectorAll with modern enumeration
polls = document.querySelectorAll('[id ^= "poll-"]');
Array.prototype.forEach.call(polls, callback);
function callback(element, iterator) {
console.log(iterator, element.id);
}
The first line selects all elements in which id starts ^= with the string poll-.
The second line evokes the enumeration and a callback function.
Given that what you want is to determine the full id of the element based upon just the prefix, you're going to have to do a search of the entire DOM (or at least, a search of an entire subtree if you know of some element that is always guaranteed to contain your target element). You can do this with something like:
function findChildWithIdLike(node, prefix) {
if (node && node.id && node.id.indexOf(prefix) == 0) {
//match found
return node;
}
//no match, check child nodes
for (var index = 0; index < node.childNodes.length; index++) {
var child = node.childNodes[index];
var childResult = findChildWithIdLike(child, prefix);
if (childResult) {
return childResult;
}
}
};
Here is an example: http://jsfiddle.net/xwqKh/
Be aware that dynamic element ids like the ones you are working with are typically used to guarantee uniqueness of element ids on a single page. Meaning that it is likely that there are multiple elements that share the same prefix. Probably you want to find them all.
If you want to find all of the elements that have a given prefix, instead of just the first one, you can use something like what is demonstrated here: http://jsfiddle.net/xwqKh/1/
I'm not entirely sure I know what you're asking about, but you can use string functions to create the actual ID that you're looking for.
var base = "common";
var num = 3;
var o = document.getElementById(base + num); // will find id="common3"
If you don't know the actual ID, then you can't look up the object with getElementById, you'd have to find it some other way (by class name, by tag type, by attribute, by parent, by child, etc...).
Now that you've finally given us some of the HTML, you could use this plain JS to find all form elements that have an ID that starts with "poll-":
// get a list of all form objects that have the right type of ID
function findPollForms() {
var list = getElementsByTagName("form");
var results = [];
for (var i = 0; i < list.length; i++) {
var id = list[i].id;
if (id && id.search(/^poll-/) != -1) {
results.push(list[i]);
}
}
return(results);
}
// return the ID of the first form object that has the right type of ID
function findFirstPollFormID() {
var list = getElementsByTagName("form");
var results = [];
for (var i = 0; i < list.length; i++) {
var id = list[i].id;
if (id && id.search(/^poll-/) != -1) {
return(id);
}
}
return(null);
}
You'll probably have to either give it a constant class and call getElementsByClassName, or maybe just use getElementsByTagName, and loop through your results, checking the name.
I'd suggest looking at your underlying problem and figure out a way where you can know the ID in advance.
Maybe if you posted a little more about why you're getting this, we could find a better alternative.
You use the id property to the get the id, then the substr method to remove the first part of it, then optionally parseInt to turn it into a number:
var id = theElement.id.substr(5);
or:
var id = parseInt(theElement.id.substr(5));
<form class="form-poll" id="poll-1225962377536" action="/cs/Satellite" target="_blank">
The ID always starts with 'post-' then the numbers are dynamic.
Please check your id names, "poll" and "post" are very different.
As already answered, you can use querySelector:
var selectors = '[id^="poll-"]';
element = document.querySelector(selectors).id;
but querySelector will not find "poll" if you keep querying for "post": '[id^="post-"]'
If you need last id, you can do that:
var id_list = document.querySelectorAll('[id^="image-"]')
var last_id = id_list.length
alert(last_id)

find a href with a certain value

I have an array called "selectMe" formed by a variable wich contains a string such as: 12P, 5B, 10C, etc., this is the "href" value of a hyperlink and I need to find and add the class "selected" to the ones inside this array. To break the array I have:
function selectPrevious(selections){
// split into array
var selectMe = selections.split(", ")
for (var i = 0; i < selectMe.length; i++){
$('#theater a').search(selectMe[i]).addClass('selected');
}
}
I've tried doing find() instead of search() as well as many other iterations but still haven't been able to accomplish what I want, how can I do it?
EDIT
Using one of the answers provided here I have changed it to this:
function selectPrevious(selections){
// split into array
if(typeof selections !== "undefined"){
var selectMe = selections.split(", ");
for (var i = 0; i < selectMe.length; i++){
$('#theater a[href*='+selectMe[i]+']').addClass('selected');
}
}
}
I had to add the "if(typeof selections !== "undefined")" because otherwise it was throwing me errors on IE. Anyway, I still can't add the class "selected" to the values in the array, am I missing something? or did I do something wrong?
Your selector for find() is wrong. And there are no search() in jQuery.
Instead of $('#theater a').search(selectMe[i]) use $('#theater a[href*='+selectMe[i]+']')
try this one:
function selectPrevious(selections) {
// split into array
var selectMe = selections.split(", ")
for (var i = 0; i < selectMe.length; i++){
$('#theater').find('a[href*='+selectMe[i]+']').addClass('selected');
}
}

Categories

Resources