Java Script : get the string equivalent of a elements ID - javascript

my naming convention
id=xxxxx //actual field shown in the screen
id=xxxxxHDN // hidden field containing the enable/disabled status of the component from the set from the controller.
Now what I am trying to do is get the satus of xxxxxHDN to be true/false ,
and accordingly set the components status to disabled /enabled .with java script..
var div = document.getElementById("hiddenFields"); // i hava some 30 hidden fields containing the
var j;
for (j=0;j<div.childNodes.length;j++)
if(div.childNodes[j].value){
alert("inside the loop");
var someElementHDN = div.childNodes[j].id; // my aim is to get the ID=xxxxxHDN
var someElementHDNToString = someElementHDN .toString(); // my aim is to get the string value "xxxxxHDN"
var toRemove = 'HDN'; // the part i wanna remove from 'someElementHDNToString' to make it an id for 'xxxxx'
var equivalantComponentIDAsString = someElementToString.replace(toRemove,'');
$('#' + equivalantComponentIDAsString ).attr('disabled', true);
}
}
Invested a lot of time manupulatiing things above , doesent seems to work . I am new to java scrcript , Where am I missing it?

If you have an element with id like 'fooHDN' and want to find another element with id 'foo', then you can do something like:
var otherElement = document.getElementById(someElement.id.replace(/HDN$/,''));
Assuming that you already have someElement and it's a DOM element.

Your posted js code has error: div does not have a "length", do you mean "div.childNodes.length"?
Anyway, since you're using jQuery already, I think it can become easier as below:
Already tested and it works fine.
$("#hiddenFields input[type='hidden'][id$='HDN']").each(
function () {
var elemId = this.id.replace(/HDN$/, '');
$('#' + elemId).attr('disabled', this.value.toLowerCase() == 'false' ? false : true);
}
);

Related

how to use $(this) with foreach in javascript using jquery

I am working on a personal project in Javascript to allow people to create a table of "dream plays" in Scrabble. Here is the link: http://psyadam.neoclaw.net/tables8.html
I am currently trying to allow the user to edit a dream play.
Here is my code:
function editRow(e)
{
var eventEl = e.srcElement || e.target,
parent = eventEl.parentNode
parent = parent.parentNode
var test = $(parent.cells[0]).text()
$('tr').each(function(){
$(this).children("td:contains(test)").each(
function()
{
pageEnd.innerHTML += "success"
$(this).addClass('selected')
}
)
})
pageEnd.innerHTML += test
//pageEnd.innerHTML += $(parent.cells[3]).text()
insertRow()
}
// insertRow assumes that the correct row in the table has the "selected" class added to it
function insertRow()
{
var Row = $('<tr>').append(
$('<td>').append('<input id="input1">'),
$('<td>').append('<select id="input2"><option value=""></option><option value="Yes">Yes</option><option value="No">No</option></select>'),
$('<td>').append('<select id="input3"><option value=""></option><option value="Natural">Natural</option><option value="1 Blank Used">1 Blank Used</option><option value="2 Blanks Used">2 Blanks Used</option></select>'),
$('<td>').append('<select id="input4"><option value=""></option><option value="vs Computer">vs Computer</option><option value="Online Game">Online Game</option><option value="Friendly Game">Friendly Game</option><option value="Club Game">Club Game</option><option value="Tournament Game">Tournament Game</option></select>'),
$('<td>').append('<input id="input5">')
)
$("#myTable tr.selected").after(Row)
}
Right now I'm just trying to get my code to insert a row into the table. I am trying to do this by using the code $(this).addClass('selected') to tag the row the user selected and then use it in my insert function to insert a row. However, nothing seems to happen. I am using pageEnd.innerHTML += "success" as a debugging tool to see if it is even getting there. Unexpectedly, it prints success twice when it should only print once, as in the test I ran every word was unique.
In any case I can't figure out why it's not working. Any help is appreciated. Thanks, ~Adam
You have two options to achieve this:
The first one as the others are suggesting i.e. by keeping a variable of outer this and then using this:
$('tr').each(function() {
var outerThis = this;
// inside another loop (not sure about children method, just an example)
$(outerThis).children("td:contains(test)").each(function() {
// do something with outerThis to operate on further
});
});
Another option to use Javascript's bind() method:
$('tr').each(function(i, trElement) {
// this == trElement
// inside another loop
$(outerThis).children("td:contains(test)").each(function(index, tdElement) {
$(this) // will be now tr element
$(tdElement) // will be td element
}.bind(this));
});
Try this:
function editRow(e) {
var eventEl = e.srcElement || e.target,
parent = eventEl.parentNode
parent = parent.parentNode
var test = $(parent.cells[0]).text()
$('tr').each(function(){
var outerThis = this;
outerThis.children("td:contains(test)").each(
function()
{
pageEnd.innerHTML += "success";
$(this).children().css('text-align', 'center');
}
)
})
pageEnd.innerHTML += test
//pageEnd.innerHTML += $(parent.cells[3]).text()
insertRow()
}
I set the outer this to a variable which you can use. Also textAlign is not a jQuery function. You need to use .css() and then specify text-align in that.

How can I remove only one attribute value and not another with jQuery?

So I have found all over stackoverflow how to remove an entire attribute, however I only want to remove the first value of an onClick attribute but not the second. All my different instances of each container have a unique function associated to them and they all share the first function in common... Once any of these containers are clicked, the first function needs to be gone but I need to retain the second without altering it at all. My code follows:
<div class="halves marginal" onClick="buildFrame(),viscalc()">
<div class="two_one marginal" onClick="buildFrame(),percentOf()">
etc etc
Once buildFrame() executes once:
function buildFrame(){
document.getElementById('screenframe').innerHTML = "<img src='img/screen.png'><iframe id='framecontent'>";
I would like to remove it from each class ( but keep percentOf(), viscalc() etc etc )
How can I remove only one attribute value and not the other?
so this is what i would do.
$("div.marginal").on("click", function(){
$(this).off("click", buildFrame);
});
that removes it from the event queue for the functions listener.
You cant do it with anon functions.
idea:
$("div.marginal").on("click", function(){
var funcs = $(this).attr("onclick").split(",");
$(this).attr("onclick", funcs[1]);
console.log("value of 'onclick'", $(this).attr("onclick"));
// or alternatively
$(this).off("click", funcs[0].substr(0,funcs[0].length-2))
//this breaks apart the onclick, turns off the click event for event0, while maintaining
// the second event.
});
the issue that i can see, from my point of view is that since it is inline, it really executes it once, so changing onclicks value might not be enough as it might not be refreshed. The above jquery though, will do what your case would want.
I think the most pin-pointed approach to this would be pass this in your buildFrame and then inside the buildFrame remove itself from the calling object.
<div class="halves marginal" onClick="buildFrame(this),viscalc()">
function buildFrame(obj){
document.getElementById('screenframe').innerHTML = "<img src='img/screen.png'><iframe id='framecontent'>";
// not sure why your not closing the iframe tag ill assume you wanted it this way
$( this ).off("click", buildFrame);
};
** EDIT **
Missed your edit where you want to remove it from all instances, this complicates it much, this solution is no longer viable.
Fairly straightforward to do with a custom selector. I think this can be done without the eval() but I'm not sure how offhand.
Here you go:
HTML
<div class="halves marginal" onClick="buildFrame();viscalc();"></div>
<div class="two_one marginal" onClick="buildFrame();percentOf();"></div>
Javascript
$.expr[':'].hasFrameMethod = function(obj){
var onClick = $(obj).attr('onClick');
return onClick != undefined ? onClick.split(';').indexOf("buildFrame()") != -1 : false;
};
function buildFrame(){
document.getElementById('screenframe').innerHTML = "<img src='img/screen.png'><iframe id='framecontent'>";
$('div:hasFrameMethod').each(function(idx, item){
htItem = $(item);
var itemClickFns = htItem.attr('onClick') != undefined ? htItem.attr('onClick').split(';') : (htItem.attr('onclick') != undefined ? htItem.attr('onclick').split(';') : "");
htItem.attr('onClick', '');
htItem.attr('onclick', '');
htItem.off("click");
// re-add any correct secondary actions
if(itemClickFns.length > 1){
var strFnClick = "function onclick(event) { ";
itemClickFns.forEach(function(elem,idx){
if(elem != "buildFrame()"){
if(elem.length > 0){
strFnClick += elem + ";";
htItem.attr('onclick', htItem.attr('onclick') + elem + ";");
}
}
});
strFnClick += "}";
// Rebind the event
htItem.prop('onclick', eval(strFnClick));
htItem.click(eval(strFnClick));
}
});
}
As long as this code loads after jQuery it should work. :)

Recursive IDs and duplicating form elements

I have the following fiddle:
http://jsfiddle.net/XpAk5/63/
The IDs increment appropriately. For the first instance. The issue is when I try to add a sport, while it duplicates, it doesn't duplicate correctly. The buttons to add are not creating themselves correctly. For instance, if I choose a sport, then fill in a position, and add another position, that's all fine (for the first instance). But when I click to add another sport, it shows 2 positions right away, and the buttons aren't duplicating correctly. I think the error is in my HTML, but not sure. Here is the JS I am using to duplicate the sport:
$('#addSport').click(function(){
//increment the value of our counter
$('#kpSport').val(Number($('#kpSport').val()) + 1);
//clone the first .item element
var newItem = $('div.kpSports').first().clone();
//recursively set our id, name, and for attributes properly
childRecursive(newItem,
// Remember, the recursive function expects to be able to pass in
// one parameter, the element.
function(e){
setCloneAttr(e, $('#kpSport').val());
});
// Clear the values recursively
childRecursive(newItem,
function(e){
clearCloneValues(e);
});
Hoping someone has an idea, perhaps I've just got my HTML elements in the wrong order? Thank you for your help! I'm hoping the fiddle is more helpful than just pasting a bunch of code here in the message.
The problem is in your clearCloneValues function. It doesn't differentiate between buttons and other for elements that you do want to clear.
Change it to:
// Sets an element's value to ''
function clearCloneValues(element){
if (element.attr('value') !== undefined && element.attr('type') !== 'button'){
element.val('');
}
}
As #PHPglue pointed out in the comments above, when new positions are added, they are incorrectly replicated (I'm assuming here) to the newly cloned for
There is a similar problem with the add years functionality.
A quick fix would be to initialize a variable with a clone of the original form fields:
var $template = $('div.kpSports').first().clone();
Then change your addSport handler to:
$('#addSport').click(function () {
//increment the value of our counter
$('#kpSport').val(Number($('#kpSport').val()) + 1);
//clone the first .item element
var newItem = $template.clone();
…
});
However, there are no event bindings for the new buttons, so that functionality is still missing for any new set of form elements.
Demo fiddle
Using even a simple, naive string based templates the code can be simplified greatly. Linked is an untested fiddle that shows how it might be done using this approach.
Demo fiddle
The code was simplified to the following:
function getClone(idx) {
var $retVal = $(templates.sport.replace(/\{\{1\}\}/g, idx));
$retVal.find('.jsPositions').append(getItemClone(idx, 0));
$retVal.find('.advtrain').append(getTrainingClone(idx, 0));
return $retVal;
}
function getItemClone(setIdx, itemIdx) {
var retVal = itemTemplate.replace(/\{\{1\}\}/g, setIdx).replace(/\{\{2\}\}/g, itemIdx);
return $(retVal);
}
function getTrainingClone(setIdx, trainingIdx) {
var retVal = trainingTemplate.replace(/\{\{1\}\}/g, setIdx).replace(/\{\{2\}\}/g, trainingIdx);
return $(retVal);
}
$('#kpSportPlayed').on('click', '.jsAddPosition', function() {
var $container = $(this).closest('.kpSports');
var containerIdx = $container.attr('data_idx');
var itemIdx = $container.find('.item').length;
$container.find('.jsPositions').append(getItemClone(containerIdx, itemIdx));
});
$('#kpSportPlayed').on('click', '.jsAddTraining', function() {
var $container = $(this).closest('.kpSports');
var containerIdx = $container.attr('data_idx');
var trainIdx = $container.find('.advtrain > div').length;
$container.find('.advtrain').append(getTrainingClone(containerIdx, trainIdx));
});
$('#addSport').click(function () {
var idx = $('.kpSports').length;
var newItem = getClone(idx);
newItem.appendTo($('#kpSportPlayed'));
});

jQuery 'not' function giving spurious results

Made a fiddle: http://jsfiddle.net/n6ub3/
I'm aware that the code has a LOT of repeating in it, its on the list to refactor once functionality is correct.
The behaviour i'm trying to achieve is if there is no selectedTab on page load, set the first tab in each group to selectedTab. If there is a selectedTab present, then use this as the default shown div.
However, as you can see from the fiddle its not working as planned!
If anyone has any ideas how to refactor this code down that'd be great also!
Change
if($('.tabs1 .tabTrigger:not(.selectedTab)')){
$('.tabs1 .tabTrigger:first').addClass('selectedTab');
}
to
if ( !$('.tabs1 .tabTrigger.selectedTab').length ) {
$('.tabs1 .tabTrigger:first').addClass('selectedTab');
}
Demo at http://jsfiddle.net/n6ub3/1/
They way you are doing it (the first code part) you are adding the .selectedTab class if there is at least one of the tabs in that group that is not selected at start .. (that means always)
Update
For a shortened version look at http://jsfiddle.net/n6ub3/7/
Your selector are doing exactly what you're writing them for.
$('.tabs3 .tabTrigger:not(.selectedTab)') is true has long as there is at least one tab that has not the selected tab (so always true in your test case).
So you should change the logic to !$('.tabs3 .tabTrigger.selectedTab').length which is true only if there are no selectedTab
WORKING DEMO with simplified code
$('.tabContent').hide();
$('.tabs').each(function(){
var search = $(this).find('div.selectedTab').length;
if( search === 0){
$(this).find('.tabTrigger').eq(0).addClass('selectedTab')
}
var selectedIndex = $(this).find('.selectedTab').index();
$(this).find('.tabContent').eq(selectedIndex).show();
});
$('.tabTrigger').click(function(){
var ind = $(this).index();
$(this).addClass('selectedTab').siblings().removeClass('selectedTab');
$(this).parent().find('.tabContent').eq(ind).fadeIn(700).siblings('.tabContent').hide();
});
That's all! You don't need all that ID's all around. Look at the demo!
With a couple of very minor changes you code can be reduced to:
$('.tabContent').hide();
$('.tabs').each(function(){
if($('.tabTrigger.selectedTab',$(this)).length < 1)
$('.tabTrigger:first').addClass('selectedTab');
});
$('.tabTrigger').click(function(){
var content = $(this).data('content');
$(this).parents('div').children('.tabContent').hide();
$(this).parents('div').children('.tabTrigger').removeClass('selectedTab');
$(this).addClass('selectedTab');
$('#' + content).show();
});
$('.tabTrigger.selectedTab').click();
Those changes are
Change the class on the surrounding div to just class="tabs.
Add a data-content attribute with the name of the associated content div
Live example: http://jsfiddle.net/gsTBQ/
Well, I'm a bit behind the times obviously; but, here's my updated version of your demo...
I have updated your fiddle as in the following fiddle: http://jsfiddle.net/4y3Xp/1/.
Basically I just tidied it up a bit, and to refactor I put everything in a separate function instead of having each of the cases in their own. This is basically just putting a new function in that does similar to what yours was doing (e.g. not modifying your HTML model), but I tried to clean it up a bit, and I also just made a function that took the tab number and did each of the items that way rather than needing a separate copy for each.
The main issue with the 'not' part of your query is that the function doesn't return a boolean; like all JQuery queries, it's returning all matching nodes. I just updated that part to return whether .selected was returning more than 0 results; if not, I go ahead and call the code to select the first panel.
Glad you got your problem resolved :)
$(document).ready(function(){
var HandleOne = function (i) {
var idxString = i.toString();
var tabName = '.tabs' + idxString;
var tabContent = tabName + ' .tabContent';
$(tabContent).hide();
var hasSelected = $(tabName + ' .tabTrigger.selectedTab').length > 0;
if (!hasSelected)
$(tabName + ' .tabTrigger:first').addClass('selectedTab');
var selectedTabId =
$(tabName + ' .tabTrigger.selectedTab').attr('id');
var selectedContentId = selectedTabId.replace('tab','content');
$('#' + selectedContentId).show();
$(tabName + ' .tabTrigger').click(function() {
$(tabName + ' .tabTrigger').removeClass('selectedTab');
$(tabName + ' .tabContent').hide();
$(this).addClass('selectedTab');
var newContentId = $(this).attr('id').replace('tab','content');
$('#' + newContentId).show();
});
}
HandleOne(1);
HandleOne(2);
HandleOne(3);
});

Having jQuery string comparison issues

I've got a fiddle going here to show what I'm trying to do.
I have a table that is generated dynamically, so the columns could appear in whatever order the user chooses. So, I'm trying to get the index of two specific headers so that I can add a CSS class to those two columns for use later.
You should use .filter() here instead (and whenever you need to restrict the element set), since your .each() return is getting thrown away, like this:
//Loop thru the headers and get the Supp elem
var suppCol = $("#my_table th").filter(function() {
return $(this).html() == "Supp";
});
//Loop thru the headers and get the Report elem
var reportCol = $("#my_table th").filter(function() {
return $(this).html() == "Report";
});
You can test the updated/working fiddle here. The alternative using .each() would look like tis:
var suppCol, reportCol;
$("#my_table th").each(function() {
var $this = $(this), html = $this.html();
if(html == "Supp") suppCol = $this;
if(html == "Report") reportCol= $this;
});
You can test that version here.

Categories

Resources