having trouble with document.getElementById for dynamic client id - javascript

Do you have to do anything special while passing in a dynamically created string as a clientID for document.getElementById?
I have a asp:gridview control that has a textbox column and a checkbox column. I added an onclick event to the checkboxes to set the textbox value of that row to the max value of all checked rows +1. I pass in the IDs of the grid and the controls of the row that was selected. I can getElementByID fine for these controls, but When I dynamically build the IDs of the other controls, I keep getting null, even though I know that the IDs are correct. My code is bellow.
function SetPriority(cbID, tbID, gridID) {
var cb = document.getElementById(cbID);
if (cb.checked) {
var tb = document.getElementById(tbID);
var grid = document.getElementById(gridID);
var maxv = 0;
for (var i = 0; i < grid.rows.length; i++) {
var indexID = 102 + i;
var cbClientID = 'LeaveInfo_pnlMain_wgbLeaveSummary_gridSubmitted_ct' + indexID + '_chkGroup';
var tbClientID = 'LeaveInfo_pnlMain_wgbLeaveSummary_gridSubmitted_ct' + indexID + '_txtPriority';
console.log("row" + i);
//just for example of how it should be working
console.log(cbID);
var cbx = document.getElementById(cbID);
console.log(cbx);
//get row checkbox
console.log(cbClientID);
var thisCB = document.getElementById(cbClientID);
console.log(thisCB);
//get row textbox
var thisTB = document.getElementById(tbClientID);
console.log(thisTB);
if (thisCB) {
if (thisCB.type == "checkbox") {
if (thisCB.checked) {
if (thisTB.value > maxv)
maxv = thisTB.value;
}
}
}
}
tb.value = parseInt(maxv) + 1;
}
}
Here is how its showing up in the console, where you can see the IDs for the first row are the same
For Those wondering about How I am calling the function, I am adding it on to a checkbox in a .net gridview control on row databind. It renders as follows:
<input id="LeaveInfo_pnlMain_wgbLeaveSummary_gridSubmitted_ctl02_chkGroup" type="checkbox" name="LeaveInfo$pnlMain$wgbLeaveSummary$gridSubmitted$ctl02$chkGroup" onclick="javascript:SetPriority('LeaveInfo_pnlMain_wgbLeaveSummary_gridSubmitted_ctl02_chkGroup','LeaveInfo_pnlMain_wgbLeaveSummary_gridSubmitted_ctl02_txtPriority','LeaveInfo_pnlMain_wgbLeaveSummary_gridSubmitted');">
The vb .net code to add the function is this...(on-_RowDataBound)
Dim chk As CheckBox = CType(e.Row.FindControl("chkGroup"), CheckBox)
Dim tb As TextBox = CType(e.Row.FindControl("txtPriority"), TextBox)
chk.Attributes.Add("onclick", String.Format("javascript:SetPriority('{0}','{1}','{2}');", chk.ClientID, tb.ClientID, gridSubmitted.ClientID))

No, you don't have to do anything special when dynamically building a string. A string in javascript is the same string whether it was built dynamically or specified directly in your code. If document.getElementById() is not working, then one of the following is likely the cause:
Your string isn't what you think it is so it doesn't match the target id.
Your DOM id isn't what you think it is.
You have multiple elements with the same id (not likely here because you won't get null)
You are calling getElementById() before the DOM is ready or before the desired elements have been added to the DOM.
In this case, it seems more likely that 1) or 2) are the issues here, but you don't show us any context to know whether 4) could be the problem.

Not 100% sure, but I think it could be a context issue. Try this:
function ( id ) {
var ID = document.getElementById;
this.id = id;
this.newvar = ID.call( document, this.id );
...
}
Also, this question may help you — it has a good explanation on context and assigning a var to getElementById Why can't I directly assign document.getElementById to a different function?

I couldnt figure out why my IDs that seemed identical were not. I will leave this question open for anyone to add insight on how to remedy this. I ended up just getting my elements by cell and not by ID.
function SetPriority(cbID, tbID, gridID) {
var cb = document.getElementById(cbID);
if (cb.checked) {
var tb = document.getElementById(tbID);
var grid = document.getElementById(gridID);
var maxv = 0;
if (grid.rows.length > 0) {
for (row = 1; row < grid.rows.length; row++) {
var thisCB = grid.rows[row].cells[5].childNodes[1];
if (thisCB == cb) {
continue;
}
var thisTB = grid.rows[row].cells[6].childNodes[1];
if (thisCB.type == "checkbox") {
if (thisCB.checked) {
if (thisTB.value > maxv)
maxv = thisTB.value;
}
}
}
}
tb.value = parseInt(maxv) + 1;
}
}

Related

RadComboBox custom text needs to have Outlook behavior

We have a customized Telerik RadComboBox that builds a text string of names separated by semicolons in the textbox field of the combobox by selecting names from the dropdown. We want to improve this and replicate a behavior similar to Outlook where individual names can be selected and deleted from the textbox. The selected names are stored in a hidden input field. Another hidden field carries a CSV list of IDs. Both hidden fields are treated like arrays, and their values have a one-to-one relationship by index. The approach we are considering is to wrap some kind of tag around each name, like a span, so that when a user selects a particular name the whole name will be highlighted and can then somehow be detected. Could this be done by using an ItemTemplate?
The OnClientSelectedIndexChanged event fires the javascript shown, and appends the list of names to the textbox.
function RecipientSelectedIndexChanged(sender, args) {
var combo = $find('<%= rcbRecipients.ClientID%>');
var userid = combo.get_selectedItem().get_value();
var name = combo.get_selectedItem()._text;
var listID = $get("<%= hdnRecipientIdList.ClientID%>").value;
var listName = $get("<%= hdnRecipientNameList.ClientID%>").value;
var listIDArray = new Array();
var listNameArray = new Array();
if (listID != '') {
listIDArray = listID.split(',');
listNameArray = listName.split('; ');
}
listNameArray.pop();
for (var i = 0; i < listNameArray.length; i++) {
listNameArray[i] = listNameArray[i] + '; ';
}
var x = listIDArray.indexOf(name);
if (x == -1) {
listIDArray.push(userid);
listNameArray.push(name + '; ');
listID = listIDArray.toString();
var y = listNameArray.join('');
listName = y;
}
$get("<%= hdnRecipientIdList.ClientID%>").value = listID;
$get("<%= hdnRecipientNameList.ClientID%>").value = listName;
combo.trackChanges();
var item = combo.findItemByText(name);
item.hide();
combo.set_text(listName);
combo.commitChanges();
combo.showDropDown();
}

search for element within element by tagname

After being stuck for a few hours on this problem, i think it is time for call for help on this.
Situation
I have a XML file which i need to filter and group. I've managed to filter it with the :Contains part. I've also determined the nodes on which i need to group (the getGroups function gives those back to me). Now i want to create a new XML with the filtered values and grouped by the returned keys.
Code
var XMLElement = document.createElement("DataElementsCalc");
jQuery(xml).find("DataElements " + topNodes + filter).each( function() {
var dataSetTemp = this.parentNode;
if(calculation1 != "")
{
var groupKeys = getGroups(dataSetTemp,calculation1);
var tempXML = XMLElement;
jQuery(groupKeys).each(function (key,value) {
var tempValue = 'a' + value.toLowerCase().replace(/\W/g, '');
if(tempXML.getElementsByTagName(tempValue).length > 0)
{
tempXML = tempXML.getElementsByTagName(tempValue);
}
else
{
var Node = document.createElement(tempValue);
tempXML.appendChild(Node);
tempXML = Node;
}
});
var Node = document.createElement("InfoSet");
var x = dataSetTemp.childNodes;
for (i=0; i < x.length; i++)
{
if(x[i].nodeType == 1)
{
var tempElement = document.createElement(x[i].nodeName);
tempElement.innerHTML = x[i].childNodes[0].nodeValue;
Node.appendChild(tempElement);
}
}
tempXML.appendChild(Node);
}
});
Explanation
As said in the situation, i already filtered the XML and have the groupNames from the getGroups function. There are a few other things i need to explain for this code:
tempValue is being build as a a + value.toLowerCase().replace(/\W/g, '');. This is being done because i possible get dates into the groupKeys. This way the node name is getting a working name (i received errors on other ways).
I want to create a new XML which is leveled by the groups. If a group already exists, i want to create a new element in it, not get a new group with the same name. (my problem at the moment).
Problem
As mentioned above, the groups aren't checked properly. Firstly: tempXML.getElementsByTagName(tempValue).length returns the error that the function tempXML.getElementsByTagName does not exists. Secondly: If i change this to document.getElemetsByTagName I get a lot of the same nodes in my XML file.
Effect
The grouping effect doesn't work as it should. I get OR an error, OR a lot of the same nodes in my DataElementsCalc.
Questions
How can i solve this? How do create nodes beneath specific nodes (for if there is a group A beneath group 1 as well as beneath group 2)?
Tried
Change tempXML to document on different places (all getElementsByTagName, at the same time or not). Looked for another way to create a XML which is easier to handle (haven't found one, yet)
As mentioned by myself in the comments of the question:
I also don't see anything in the source code for this (maybe this is the reason why it doesn't work??)
I tried to place the XMLElement into an existing element on my webpage (like this:
var XMLElement = document.createElement("DataElementsCalc");
jQuery('.basicData').append(XMLElement);
in which basicData is a class of an existing element).
Now i do get a list of all elements ordered on the groups i wanted.
Final version
var XMLElement = jQuery("<DataElementsCalc/>");
jQuery('.basicData').append(XMLElement);
jQuery(xml).find("DataElements " + topNodes + filter).each( function()
{
aantalElementsTotal++;
var dataSetTemp = this.parentNode;
if(calculation1 != "")
{
var groupKeys = getGroups(dataSetTemp,calculation1);
var tempXML = XMLElement;
var groupId = '';
jQuery(groupKeys).each(function (key,value) {
var tempValue = 'a' + value.toLowerCase().replace(/\W/g, '');
groupId += 'a' + value.toLowerCase().replace(/\W/g, '');
if(jQuery("#" + groupId).length > 0)
{
tempXML = jQuery("#" + groupId);
}
else
{
var Node = jQuery("<"+tempValue+"/>");
jQuery(Node).attr('id', groupId);
jQuery(tempXML).append(Node);
tempXML = Node;
}
});
var Node = jQuery("<InfoSet/>");
var x = dataSetTemp.childNodes;
for (i=0; i < x.length; i++)
{
if(x[i].nodeType == 1)
{
var tempElement = jQuery("<"+x[i].nodeName+"/>");
jQuery(tempElement).text(x[i].childNodes[0].nodeValue);
jQuery(Node).append(tempElement);
}
}
jQuery(tempXML).append(Node);
}
});

Trouble with changing the text of an element based off of a text form .val()

My app dynamically creates and deleted new elements based on the + / - buttons.
Inside the dynamically created elements are text forms. I want whatever the user types into the text form to be displayed in another dynamically created element.
$('.LName').keyup(function(event) {
var crazy = {};
for (var x = 1; x < i; x++) {
crazy[x] = function() {
$('#sideChange'+ x).keyup(function(event) {
var value = $(this).val();
$('.sLoan'+ x).text(value);
})
}
}
for (var p = 1; p < i; p++) {
crazy[p]();
}
});
For example, I accomplished this for changing the text in the previous element by including the function in the html onkeyup attribute, but I don't know how to accurately target other elements.
var changeTitle = function() {
var loanTitle = $(this).val();
var code = $("input[type='text'][name='loanName']").keyCode || $("input[type='text'][name='loanName']").which;
var length = loanTitle.length;
console.log(length);
if(length < 1 || code == 8) {
$(this).prev().text('Loan');
}
else {
$(this).prev().text(loanTitle);
}
};
What youll probably want to do is data bind the two elements with some sort of ID you generate. In the fiddle below, I just use an incrementing number. When the keyup happens, I grab that elements data-id and use it to find its "mirrored" input.
$('.mirror[data-id="'+id+'"]').val(text);
Your question was a bit vague but I think this is what you were asking for.
http://jsfiddle.net/swoogie/f8cd4voz/

Select Part of a Attribute - JQuery

I need to get the number only from an attribute (The number is dynamic). The button/anchor looks like this:
Delete Dish
The part I need to dissect is this bit 'bc_inventorybundle_menu_product_0' I only want the number, for use in another function (Delete a LI with an ID of menuitem0_dish)
The code I use for selecting ID's elsewhere is:
function getNum(element, attrPrefix) {
//set prefix, get number
var prefix = attrPrefix;
var num = element.attr("id").substring((prefix.length));
return num;
}
It works great on ID's but I cant seem to get it to work for Attributes instead of ID's
So User clicks delete button bc_inventorybundle_menu_product_0 then jQuery removes the < li id="menuitem0_dish">
I can't add an ID to the button so I have to use the attribute of the button. As I'm sure you can tell I'm a complete noob when it comes to JS/JQuery.
EDIT
Having read all the answers I feel I may need to elaborate a little.
I think the biggest issue is registering when the Button/Anchor is clicked.
What I currently have is this, which I know must be wrong:
$(document).on('click', 'data("field")', function(event) {
deleteDish(this);
});
function getbutNum(element, attrPrefix) {
//set prefix, get number
var prefix = attrPrefix;
var butnum = element.data("field").substring(prefix.length); //Changed as per suggestions
return butnum;
}
function deleteDish(field) {
var numbut = getbutNum();
//Delete the UL/LI
console.log("Num But" + numbut);
}
Asides from all else this gives me an error of 'unrecognized expression: data("field")'
Have you tried selecting your actual data attribute:
var num = element.attr("data-field").substring(prefix.length);
Or:
var num = element.data("field").substring(prefix.length);
EDIT
First add a class to your anchor element (I'm going under the assumption that you have more than one of these):
Delete Dish
Then:
$(".delete-dish").on("click", function (e) {
e.preventDefault();
var fieldData = $(this).data("field"),
num = fieldData.substring(fieldData.lastIndexOf("_") + 1);
console.log("Num But" + num);
});
Here is a fiddle to demonstrate
Using the attribute name that contains your input should work:
function getNum(element, attrPrefix) {
//set prefix, get number
var prefix = attrPrefix;
var num = element.attr("data-field").substring((prefix.length));
return num;
}
http://jsfiddle.net/zf3hmo4q/
Considering you want to parse attributes with "data-*" name:
function getNum(element, dataName, dataPrefix) {
var num = element.data(dataName).replace(dataPrefix, "");
return num;
}
console.log(getNum($(".btn"), "field", "bc_inventorybundle_menu_product_"));
Maybe something like this?
var getNumberFromAttribute = function(id, field) {
var field = $(id).data(field);
var parts = field.split("_");
return parts[parts.length - 1]
}
Here's a jsfiddle http://jsfiddle.net/o6go79cL/
UPDATE
You could just pass in the element. The only purpose of the id was to select the object. So you could also just do:
var getNumberFromAttribute = function(elm, field) {
var field = $(elm).data(field);
var parts = field.split("_");
return parts[parts.length - 1]
}
number = getNumberFromAttribute(anchorTag, "field");

function to change argument to another sign

I dynamically create this list element and information a user has typed in shows up in it when a button is clicked 'info' is text and shuld show as it is but 'grade' is a number that i want to convert to another sign with the function changeNumber() but I am new to javascript and cant figure out how to make this function, can anyone give a suggestion or point me in the right direction?
var list = $("#filmlista");
var list_array = new Array();
function updateFilmList()
{
document.getElementById("name").value = '';
document.getElementById("star").value = 0;
var listan = list_array[0][0];
var grade = list_array[0][1];
var element = '<li class="lista">' + list + '<span class="grade">'+ changeNumber(grade) +'</span></li>';
list.append(element);
}
should I use innerHTML? not shure I understand how it works? and how do I use the replace method if I have to replace many different numbers to the amount of signs the number is?
for example if the number is 5 it should show up as: *****, if number is 3 show up as: *** and so on
Here's some code that should do the trick:
Add this function into your script.
function changeNumber(number) {
var finalProduct = "";
for (var i = 0; i < number; i++) {
finalProduct += "*";
}
return finalProduct;
}
Replace the updateFilmsList with this code.
document.getElementById("name").value = '';
document.getElementById("star").value = 0;
var listan = list_array[0][0];
var grade = changeNumber(list_array[0][1]);
var element = '<li class="lista">' + list + '<span class="grade">'+ grade +'</span></li>';
list.append(element);
It looks like you're trying to do something like PHP's str_repeat. In that case, take a look at str_repeat from PHPJS
There are options other than a loop:
function charString(n, c) {
n = n? ++n : 0;
return new Array(n).join(c);
}
charString(3, '*'); // ***
You can use innerHTML to set the text content of an element provided none of the text might be mistaken for markup. Otherwise, set the textContent (W3C compliant) or innerText (IE proprietary but widely implemented) property as appropriate.

Categories

Resources