sorry to bother some of you again. But I still haven't found a working answer to my problem.
I have a good old fashioned HTML table. Each reach has its unique ID. What I want to achieve with JavaScript is that this ID gets stored in a variable once I cklick a link on each row.
Might sound easy to you, I am new to JS and I can't figure it out to the end. Could someone help me please?
Thanks!
The Onclick event of what you are clicking on can call a function like
function RecordClick( elem ) {
mylocalVar = elem.id;
}
by saying
onclick="RecordClick(this);"
When you create your table on the server-side you put this in your HTML (as I understand your scenario):
...
<tr>
<td>
Some link name
</td>
</tr>
...
So why not do this:
<script>
var rowID = -1;
</script>
...
<tr>
<td>
Some link name
</td>
</tr>
...
This is not the best way of doing it, but it gets the job done. If you're using some library like jQuery, you could do it in a completely different way and using closures as well.
you have to take a global variable for this. U can take it into the head section like-
var idHolder;
Now in the table onclick handler u call a function like-
table onclick="extractId(obj)">
The function definition may be like this-
function extractId(var obj)
{
idHolder=obj.Id;
}
This will do ur work, in case of any problem reply.
Since the click event bubbles up the DOM, you can do this by hooking the click event of the table, and then figuring out which row was clicked. This is usually called "event delegation." Something like this (live copy):
// Hook click on the table
document.getElementById('theTable').onclick = function(e) {
var element;
// Handle IE vs. standards
e = e || window.event;
// Find out what was clicked (more IE vs. standards)
element = e.target || e.srcElement;
// Find the row
while (element && element.tagName !== "TR") {
element = element.parentNode;
}
// Found it?
if (element) {
// Yes, remember the ID and show it
targetVariable = element.id;
display("You clicked row " + targetVariable);
}
};
Off-topic: This stuff is made a lot easier if you use a library like jQuery, Prototype, YUI, Closure, or any of several others. For instance, the above code using jQuery looks like this:
$('#theTable').click(function(event) {
var target = $(event.target).closest('tr');
if (target.length > 0 ) {
targetVariable = target[0].id;
display("You clicked row " + targetVariable);
}
});
Live copy
Or using one of the new features:
$('#theTable').delegate('tr', 'click', function(event) {
targetVariable = this.id;
display("You clicked row " + targetVariable);
});
Live copy
Related
I am adding some elements dynamically to a page when making this chrome extension. It is a list added like this
var result = document.createElement("UL");
var checkoutArea = document.getElementById("shipping");
result.setAttribute("id", "resList");
if (document.getElementById("resList") === null) {
checkoutArea.appendChild(result);
}
I am also adding <'li'> child to it later. But when I am trying to add onclick function to each item, it does not work. I checked when I click on the item dynamically generated, and it seems that those items are not clicked, as this gives wrong results:
document.addEventListener('click', function(e) {
e = e || window.event;
var target = e.target || e.srcElement,
text = target.textContent || text.innerText;
console.log(text);
}, false);
a screenshot of the DOM of dynamically generated list
Also when I 'inspect' on that 'home' item, chrome is giving me that highlighted element, which is the 'save & continue' button besides. I am thinking there's an overlap, so how should add any 'onclick' function to those items?? Great thanks in advance.
You probably need to try the Event delegation pattern. The idea is that if we have a lot of elements handled in a similar way, then instead of assigning a handler to each of them – we put a single handler on their common ancestor.
Read about it on this link: http://javascript.info/event-delegation
I managed to understand Event delegation thanks to video 15 that has the name LocalStorage and Event Delegation in the course javascript30 of Wes Bos. The course is free and worthwhile. I hope this information serves you
I have multiple dynamically created buttons with the same class on my page and when I try to call a function on the click of the button, the function gets called for all of the buttons with the same class.
I want the function to be called for this click event only.
Here is my function:-
$(".js-btn-plus").click(function (e) {
var link = $(e.target);
var val = link.next('.value').text();
val++
link.next('.value').text(val);
});
Maybe generate unique ID for the button and use that as an event reference instead of the class?
.text() returns a string. Convert the string val to a number
val = Number(val) + 1
or
val = +val++
Please could you provide some sample HTML to alongside the JQuery?
From what I can see you may want to have a look at using $(this) instead of e.target
$(document).on('click', '.js-btn-plus', function() {
var val = parseInt( $(this).find('.value').text() );
val++;
$(this).find('.value').text(val);
});
Not 100% sure what it is that you're trying to achieve, there may be a better way of doing it if you could explain a little bit more and provide some HTML to go alongside your question.
Edit: Using the 'on' function allows you to dynamically bind the function events instead of having them have a listener fire when the script is loaded and executed.
My solution:
$(".js-btn-plus").click(function (e) {
var val = parseInt($(this).next('.value').text());
val++;
$(this).next('.value').text(val);
});
var tableData = document.getElementsByTagName("td");
for(var i = 0; i < tableData.length; i++){
var x = tableData[i];
x.addEventListener("click", fun1(x.textContent));
}
function fun1(y){
document.getElementById("testB").textContent = y;
}
I am trying to add a click function to every cell in a dynamically created table (i have no way of knowing how many cells are in the table or what their id would be but i only need the text contained in the cell)
I want to update a button with the content of the cell and as of right now it does not update on click and instead updates the button to the last value of the table.
I am fairly new to JavaScript and would appreciate any help you could offer.
here is the solution i used thanks to the answer provided below
var tables = document.getElementsByTagName("table");
for(var i = 0; i < tables.length; i++){
tables[i].addEventListener("click",
function(e) {
if(e.target && e.target.nodeName == "TD") {
fun1(e.target.textContent);
}
}
);
}
function fun1(y){
document.getElementById("testB").textContent = y;
}
i went with this solution because the script generating the tables is not mine and as such i do not know what the id of the table i want is and do not know how many tables it actually creates.
You almost certainly do not want to add an event handler individually to each table cell if all (or even many) of them should do the same thing when clicked.
The DOM event model was designed to support delegation, which is a much better solution in cases like this. In brief: individual cells do not respond to clicks, but some ancestor element that is considered a permanent fixture (say, the <table> they are in) detects the clicks on cells and responds to them appropriately.
Here's how to set up delegation:
document.getElementById("#mytable").addEventListener("click",
function(e) {
if(e.target && e.target.nodeName == "TD") {
fun1(e.target.textContent);
}
}
);
Of course you can choose any ancestor element you want, even <body> if that's what is required. Also note that this way of doing things means your code behaves as expected even while cells are added to or removed from the table -- you just do this once on page initialization.
x.addEventListener("click", fun1(x.textContent));
This line is your issue -- addEventListener looks for a function reference, you're just calling the function (which does not return a function). Wrap it in an anonymous function, or bind the value to the reference.
x.addEventListener("click", function() {
fun1(x.textContent)
}, false); //also a good idea to add the event bubbling boolean param
Alternatively, ES6 arrow syntax:
x.addEventListener("click", () => fun1(x.textContent), false);
I am working on HTML select Dropdown. I have two dropdowns one is for font size adjust and other is for text alignment.
When I select the fontsize from the dropdown it has to apply along with text-capitalize (bootstrap css) and If I select the font alignment all three should apply for the span element. For Example.
<div>
<span id="Title"class="text-capitalize">check</span>
</div>
Right now the code was like this
function changeFont_size () {
var select = document.getElementById('font_size');
// Bind onchange event
select.onchange = function() {
document.querySelector("#Title").className = this.value += " text-
capitalize";
};
}
function changeAlignment () {
var select = document.getElementById('text_align');
// Bind onchange event
select.onchange = function() {
document.querySelector("#Title").className = this.value;
};
}
Actually I am newbe on Javascript. Some how I am not getting.
The output result would be the combination of :
<span class="h1 left text-capitalize">Text</span>
Everything should be in pure javascript.
Thanks in advance. Kindly help me.
Here is the Link
This jsfiddle makes your code work. You need to run the code when the document is loaded, so that your onchange functions are being hooked in time.
It does not work exactly like you intended though. Your alignment classes need to be on the parent element and when you select your alignment, you disregard the previously set h1 or h2 class.
window.onload = function() {
var font_size = document.querySelector('#font_size');
// Bind onchange event
font_size.onchange = function() {
document.querySelector("#Title").className = this.options[this.selectedIndex].value += " text-capitalize";
};
var text_align = document.querySelector('#text_align');
// Bind onchange event
text_align.onchange = function() {
document.querySelector("#Title").className = this.options[this.selectedIndex].value;
};
};
You are mixing things up. There are two ways to bind events (well, two ways which are still common even with recent browsers).
The first one is to put a function call in the onsomething property of an element in the html code. Whatever is put there will be executed when the event happens.
<button onclick="alert('hi');">Click me</button>
You should pass the event object to an event handler instead of writing inline code.
<button id="helloworld" onclick="helloworld_onclick(event)">Run</button>
...
function helloworld_onclick(e) {
alert("Hello world!");
}
If you want to be able to bind events dynamically, if you want to bind multiple events to an object and if you want to keep the JavaScript outside of your HTML, the modern way to to so is with addEventListener.
document.querySelector("#helloworld").addEventListener("click", function(e) {
alert("Hello world!");
});
The event object passed (called e in my functions) contains information about what triggered the event and can be used to prevent default behavior and to control event propagation. You can't use "this" in event handlers, but the element which called the handler will be stored in e.target.
In your code, you created functions which, when called, bind events to the elements. Then you bound those functions to the elements with the html attributes.
Finally, you seem to be stuck between querySelector and getElementById. Note that querySelector(All) returns a static node/nodelist while getElement(s)By(...) returns a live node/nodelist. A static node is a copy of all the information about the element. A live node is a reference to the real element. If you modify the element, it modifies the live node, but the static node will keep the old information. You should use getElementById over querySelector for that, and because it runs faster. For code simplicity however, you might prefer always using querySelector. Just don't mix using querySelector("#something") on a line and getElementById("something") on another one, it's the best way to get confused and end up wasting time on a bug because you wrote querySelector("something") or getElementById("#something") instead.
function changeFont_size (element) {
if(element.options[element.selectedIndex].value != 'select'){
document.getElementById('Title').className = element.options[element.selectedIndex].value;
} else{
document.getElementById('Title').className = '' }
}
function changeAlignment (element) {
if(element.options[element.selectedIndex].value != 'select'){
document.getElementById('container').className = element.options[element.selectedIndex].value;
} else{
document.getElementById('container').className = '' }
}
Try this, Hope it will work
I have looked high and low and can't seem to find this anywhere. Does anyone know how to get the value of a row tapped in a listview? This can be anything from the name to the index in the object. Right now I have a function that handles the tap. I need to be able to pass a value to the new page I am loading when it transitions. I thought I could do it here:
$('#taskListTable').delegate('li', 'tap', function () {
console.log('clicked');
//Insert code here to pull a value from either an index or a name and save it
});
I thought maybe it would be good to do it in the hash? I am not sure what the standard practice is here on the web coming from native iOS dev though. Anyone have any pointers? Thanks.
This is how I am populating my listview:
$.each(tasks, function(index, task) {
$taskList.append("<li><a href='taskDetails.html'> <h3>"+task.name+"</h3><p>"+task.description+"</p></a></li>");
});
taskDetails.html needs the index of the task so I can pull the details down from the server. What is the standard practice for doing that?
To get the index of the taped list-item you can do this:
$('#taskListTable').delegate('li', 'tap', function () {
console.log('clicked');
var index = $(this).index();
});
Yup, that's it. Although this assumes that the <li> element are all siblings.
Docs for .index(): http://api.jquery.com/index
If you want to then transition to the new page:
$('#taskListTable').delegate('li', 'tap', function () {
console.log('clicked');
$.mobile.changePage($(this).find('a').attr('href'), {
data : { selectedIndex : $(this).index() }
});
});
This will get the new page and attach the selectedIndex variable as a query string parameter that is set to the index of the tapped list-item.
Also, to be able to prevent the default behavior of clicking on the link in the list-item, I would attach this event handler to the link elements:
$('#taskListTable').delegate('a', 'tap', function (event) {
event.preventDefault();
console.log('link clicked');
$.mobile.changePage($(this).attr('href'), {
data : { selectedIndex : $(this).closest('li').index() }
});
});
The "delegate" method is deprecated on new versions of jQuery.
Consider using this instead:
$('#taskListTable').on('tap', 'a', function (event) {
}
Here is another method of getting an id, especially useful if you have a database enabled app and the id you are searching for is the database's id, not the row index:
When filling the table consider this:
<ul id="taskListTable">
<li id="task400" class="tasks">Task with db id 400</li>
<li id="task295" class="tasks">Task with db id 295</li>
</ul>
$('#taskListTable').on('tap', 'li', function (event) {
variable = $(this).attr('id').substr(4);
}
That will get the database id which you can pass on to your other pages.
To get the name out, you could do:
$(this).find('h3').html()
Alternatively, you can use something in the markup like the id or a data attribute to provide a better handle than the name.
What about this approach?
$taskList.append("<li><a href='taskDetails.html?id=" + task.id + "'></a><h3>" + task.name + "</h3>...</li>");
And then retreive id parameter.
Jasper's solution is good, but if you have any other code in your event handler that edits the DOM, the "this" keyword could be pointed somewhere entirely different by the time it gets used in your code.
I've cracked my head on my keyboard a number of times because my users said "I click on item one, but that always opens the edit screen for the last item in the list." So somehow using 'this' was not the right way to go.
Also, when I tried event.target, event.currentTarget or event.originalTarget, those didn't work either. They all pointed to the jQueryMobile "page" that was visible by the time the code got to run (which wasn't even the same page where the table was located).
The safe and/or intended approach is to:
use event.originalEvent.srcElement instead of 'this'
not use .delegate(), but use .on()
bind the event using $(document).on(), not $('#table').on()
So that would result in:
$(document).on('tap','#taskListTable li',function(event){
//The properties of 'event' relate to $(document), not to '#taskListTable li',
//so avoid .currentTarget, .target etc.
//But fortunately 'event' does have one property that refers to the original
//user event.
var theOriginalTapEvent = event.originalEvent;
var theRealClickedElement = theOriginalTapEvent.srcElement;
//Note that the clicked element could be a sub-element of the li
//whose index you want. So just referencing theRealClickedItem could
//could still be getting you bad results.
var theRelevantListItem = $(theRealClickedElement).parents('li');
//Now you're ready to get the item's index or whatever.
})