I want different buttons with id and a unique function for toggle, but i can set the variable.
var clicked = false;
var abcElements = document.querySelectorAll('.cellInput');
// Set their ids
for (var i = 0; i < abcElements.length; i++){
abcElements[i].id = 'target-' + i;
$("#target-"+i).click(function () {
if (!clicked) {
// do something
} else {
// do something
}
clicked = !clicked;
})
}
If you want to keep track of the click for each element, you cannot use a shared global variable. You can, however, toggle a class to keep track of state on each element.
$('.cellInput').on('click', function(e){
var $this = $(e.target);
if (!$this.hasClass('clicked')) {
$this.addClass('clicked');
// do something
} else {
$this.removeClass('clicked');
// do something
}
});
Related
if I want to add a class to the corresponding element of a counter, how would I do that?
I do have something like
var li_counter = 0;
$("#trigger_heritage").click(function () {
if(heritage_position>=heritage_versatz*13){
li_counter++;
$(".heritage_nav" li[li_counter]).addClass("activeheritage");
}
else{ // Something else
}
});
And I want to apply a class to that li-element of the heritage_nav-block
that has the corresponding counterposition. If the user has clicked 5 times, the 5th child-element of heritage_nav shall get the class....
Thanks!
var li_counter = 0;
$("#trigger_heritage").click(function () {
if(heritage_position>=heritage_versatz*13){
li_counter++;
$(".heritage_nav li:eq("+li_counter+")").addClass("activeheritage");
}
else{ // Something else
}
});
Maybe this will help you,
var li_counter = 0;
$("#trigger_heritage").click(function () {
if(heritage_position>=heritage_versatz*13){
li_counter++;
$(".heritage_nav").find("li:nth-child(" + li_counter + ")").addClass("activeheritage");
//if you want to add class to this div
$(".heritage_nav").addClass("your-class");
}
else{ // Something else
}
});
I have the following situation which I cannot solve. I am relatively new to js. I have a js that runs on a webpage. The script runs when a KB shortcut is pressed. After modifying a few things, it pops up an html banner in which I want to put certain messages and buttons depending on what thing the user ran a script on. For a simple case, let's say there are two potential messages that can go in this popup. I have the details in an object array:
NH_Bann = {
STC: {
active: false,
bannText: "Force Title Case: ",
id: "toTitleCaseStrong",
value: "Yes",
action: function() {
var newNameStr = toTitleCaseStrong(vname);
if (newNameStr !== name) {
//**update function
NH_Bann.STC.active = false;
}
}
},
DTC: {
active: false,
bannText: "Enable DTC? ",
id: "addDTC",
value: "Yes",
action: function() {
//**update function
NH_Bann.DTC.active = false;
}
}
}
When the script is run, there are some if statments that can change the active keys to true. After the script runs, I want to run through the objects in NH_Bann, and if the active key is true, make a message with an action button that fires the action button. The part I am having trouble with is making the buttons dynamically. From other threads, I thought I could store the buttons in an array, but maybe the onclick doesn't work that way? This is what I have:
function setupButtons() {
var ixButt = 0;
var btn = [];
for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
tempKey = Object.keys(NH_Bann)[NHix];
if (NH_Bann[tempKey].active) {
btn[ixButt] = document.getElementById(NH_Bann[tempKey].id);
btn[ixButt].onclick = function(){
NH_Bann[tempKey].action();
assembleBanner(); // makes the html for the banner
}
ixButt++;
}
}
}
I make the buttons in another piece of code which sets up the ids:
function assembleBanner() {
sidebarMessageEXT = [sidebarMessage.slice(0)];
var EXTOption = false;
for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
tempKey = Object.keys(NH_Bann)[NHix];
if (NH_Bann[tempKey].active) {
sidebarMessageEXT.push(NH_Bann[tempKey].bannText + '<input id="' + NH_Bann[tempKey].id + '" type="button" value="' + NH_Bann[tempKey].value + '">');
EXTOption = true;
}
}
if (EXTOption) {
sidebarMessageEXT = sidebarMessageEXT.join("<li>");
displayBanners(sidebarMessageEXT,severity);
setupButtons();
} else {
displayBanners(sidebarMessage,severity);
setupButtons();
}
}
The issue i'm having is that I get the two distinct messages and two buttons in the banner if both objects are active==true, but pressing them always fires the update function of the DTC object. Any suggestions? I'm open to other methods, but I need to be able to add to the object list over time and have the buttons be displayed conditionally on the status of the active key for each object. Thx!
The problem has to do with closures. In this code:
function setupButtons() {
var ixButt = 0;
var btn = [];
for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
tempKey = Object.keys(NH_Bann)[NHix];
if (NH_Bann[tempKey].active) {
btn[ixButt] = document.getElementById(NH_Bann[tempKey].id);
btn[ixButt].onclick = function(){
NH_Bann[tempKey].action();
assembleBanner(); // makes the html for the banner
}
ixButt++;
}
}
}
...tempKey is a variable that lives within the call to setupButtons. Notice that you're creating two onclick function callbacks in a loop, and both make reference to tempKey. However, they're not going to be referencing the variable's value at the time of function creation, but rather the latest value of the variable. So once the loop completes, tempKey is going to reference the last value it had.
To work around this, you can use this trick to create a new closure for each onclick that will have the correct value:
function setupButtons() {
var ixButt = 0;
var btn = [];
for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++ ) {
tempKey = Object.keys(NH_Bann)[NHix];
if (NH_Bann[tempKey].active) {
btn[ixButt] = document.getElementById(NH_Bann[tempKey].id);
btn[ixButt].onclick = (function(buttonId) {
return function() {
NH_Bann[buttonId].action();
assembleBanner(); // makes the html for the banner
}
})(tempKey);
ixButt++;
}
}
}
Essentially, this is binding the current value of tempKey to a new variable by passing it to an immediately-executing function, so both onclick functions no longer reference the variable which changes during the loop.
For a less esoteric way to do this, you could move the creation of each button into its own named function, passing the required data:
function setupButtons() {
var btn = [];
for (var NHix = 0; NHix < Object.keys(NH_Bann).length; NHix++) {
tempKey = Object.keys(NH_Bann)[NHix];
if (NH_Bann[tempKey].active) {
btn.push(setupButton(NH_Bann[tempKey]);
}
}
}
function setupButton(bannerData) {
var button = document.getElementById(bannerData.id);
button.onclick = function() {
bannerData.action();
assembleBanner();
};
return button;
}
I've tried to make my own case function, but I cannot get it to "show stuff" once I've hidden them on first click. So my question is what am I doing wrong, how can I solve it, and how should I've done it instead?
My only requirement is that multiple buttons can use the same code to show/hide the same object – hence things like oddClick won't work since that'll require unnecessary clicks to get even/odd again (I think?).
$('.boxbtn').on('click', function () {
var boxwidth = $('.box').width();
console.log(boxwidth);
console.log('-'+boxwidth+'px');
var state = 1;
if(state == 0) { // I think we are trying to compare value here.
/* alert("foo"); */
var state = 1;
console.log(state);
/*show stuff here*/
}
else {
/* alert("bar"); */
var state = 0;
console.log(state);
/*hide stuff here*/
}
});
this line 5: var state = 1; causes it to always go into "else
var state = 1; //placed on global scope
$('.boxbtn').on('click', function () {
var boxwidth = $('.box').width();
console.log(boxwidth);
console.log('-'+boxwidth+'px');
//var state = 1; removed from function scope
if(state == 0) {
/* alert("foo"); */
state = 1;
console.log(state);
/*show stuff here*/
}
else {
/* alert("bar"); */
state = 0;
console.log(state);
/*hide stuff here*/
}
});
Fiddle: http://jsfiddle.net/8ubk5c0f/
For detecting the state of your object, you should use the object properties (instead of a parallel state variable).
Using the value of boxwidth for instance.
In more simple way:
$('.boxbtn').on('click', function () {
var boxwidth = $('.box').width(); //Not sure why you want this
console.log(boxwidth);
console.log('-'+boxwidth+'px');
var btnVal=$(this).text(); //get the button text
if(btnVal=="Show Stuff") //if it is show stuff
{
$(this).text('Hide Stuff'); //change its text
alert('stuff shown');
/*show stuff here*/ //do the functionality
}
else {
$(this).text('Show Stuff'); //change back to normal
alert('stuff hidden');
/*hide stuff here*/ //hide functionality
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" class="boxbtn">Show Stuff</button>
Declare state variable outside click function.
var state = 1; // Do not write inside click function scope
var state = 0; //placed on global scope
$('.boxbtn').on('click', function () {
var boxwidth = $('.box').width();
console.log(boxwidth);
console.log('-'+boxwidth+'px');
if(state == 0) {
state=1;
console.log(state);
}
else {
state = 0;
console.log(state);
}
});
I want to change the text inside of an element for dynamically created elements. i = 2 because that's Why is it not working?
var loanName = function() {
for(var t=1; t < i; t++) {
$('body').on('keyup', '.loanNameV'+t, function () {
var loanN = $('.loanNameV'+t).val();
$('.nameLoan'+t).text(loanN);
});
}
};
$('body').on('keyup', '[class^="loanNameV"]', function () {
var numbesideclass = ($(this).attr('class').split('loanNameV'))[1];
var loanN = $(this).val();
$('.nameLoan'+numbesideclass).text(loanN);
});
Note: this code will work if you don't have another class for loanNameV elements like class="loanNameV1 anotherclass anotherclass" in this case this code will not work as expected
I am trying to remove an object and store it (in case a user wants to retrieve it later). I have tried storing the object in a variable like it says in the thread below:
How to I undo .detach()?
But the detach() does not remove the element from the DOM or store it. I am also not getting any error messages. Here is the code I am using to detach the element:
function MMtoggle(IDnum) {
var rowID = "row" + IDnum;
var jRow = '#' + rowID;
thisMMbtn = $(jRow).find(".addMMbtn");
var light = false;
var that = this;
if (light == false) {
thisMMbtn.bind("click",
function() {
var thisRow = $(this).closest(".txtContentRow");
var thisTxt = thisRow.find(".txtContent");
var cellStr = '<div class = "mmCell prep"></div>';
$(cellStr).appendTo(thisTxt);
$(this).unbind("click");
light = true;
}
);
}
else {
thisMMbtn.bind("click",
function() {
var thisRow = $(this).closest(".txtContentRow");
thisMM = thisRow.find(".mmCell");
SC[rowID].rcbin = thisMM.detach(); //here is where I detach the div and store it in an object
$(this).unbind("click");
light = false;
}
);
}
}
MMtoggle(g.num);
A fiddle of the problem is here: http://jsfiddle.net/pScJc/
(the button that detaches is the '+' button on the right. It is supposed to add a div and then detach it when clicked again.)
Looking at your code I don't think so you need detach for what you are trying to achieve.
Instead try this code.
thisMMbtn.bind("click",
function() {
var thisRow = $(this).closest(".txtContentRow");
var thisTxt = thisRow.find(".txtContent");
var $mmCell = thisTxt.find('.mmCell');
if($mmCell.length == 0){
$mmCell = $('<div class = "mmCell prep"></div>')
.appendTo(thisTxt).hide();
}
$mmCell.toggle();
//$(this).unbind("click");
}
);
Demo