I need to pass row parameters to my onclick function.
this is my code:
function renderHostTableRowJob (dataTable) {
for (var i in dataTable) {
var notification = dataTable[i];
var row = document.createElement("tr");
var cell = document.createElement("td");
cell.innerText = notification["Name"];
row.appendChild(cell);
var cell = document.createElement("td");
cell.innerText = notification["State"];
row.appendChild(cell);
var cell = document.createElement("td");
cell.innerText = (notification["NotificationReceived"] === true) ? "Received" : "Missing";
row.appendChild(cell);
row.onclick = function() {alert(notification["Name"]);};
$("#" + notification["Client"] + "_TableJobDetails > #" + notification["Client"] + notification["HostFormated"] + "_TableBodyJobDetails")[0].appendChild(row);
}
}
At the moment all my row.onclick = function() {alert(notification["Name"]);}; are returning the value for the last iteration in my loop...
QUESTION: How can I send my values to the click event on each iteration?
thanks
Capture notification as a parameter to an anonymous function. Since it looks like you’re using jQuery, you can use jQuery.each, which will simplify your iteration and as a side effect capture it:
$.each(dataTable, function(index, notification) {
// ...
});
By the way, if you are using jQuery, you can write your code more concisely:
var row = $('<tr>').click(function() {
alert(notification.Name);
});
$('<td>').text(notification.Name).appendTo(row);
$('<td>').text(notification.State).appendTo(row);
$('<td>').text(notification.NotificationReceived ? 'Received' : 'Missing').appendTo(row);
row.appendTo('#' + notification.Client + '_TableJobDetails > ' +
'#' + notification.Client + notification.HostFormated + '_TableBodyJobDetails');
Further, if your IDs are unique (as they should be), you need not specify the whole hierarchy; just use
row.appendTo('#' + notification.Client + notification.HostFormated + '_TableBodyJobDetails');
Also, while it is a larger change in your code, consider using delegation with on.
I got it working with the code below:
row.onclick = (function() {
var details = notification;
return function() {
showModalJobDetails(details);
}
})();
Related
I'm using w2ui version 2 and I have
let row = '';
let cell = '';
let grid = new w2grid({
name: 'grid'
...
...
,onClick: function (event) {
event.onComplete = function () {
row = event.detail.recid;
cell = event.detail.column;
console.log("onClick cell : " + cell );
}
}
...
...
}
in my code and it is working fine, but the code below is not working.
,onContextMenuClick: function (event) {
event.onComplete = function () {
row = event.detail.recid;
cell = event.detail.column;
console.log("onClick onContextMenuClick : " + cell);
}
}
boot is the part of same grid code.
How can I get selected cell onContextMenuClick. So I can add some specific Context Menu events to my w2ui grid.
I did try looping all sub objects of event
const keys = Object.keys(event);
for (let i = 0; i < keys.length; i++) {
console.log("onContextMenuClick event : " + keys[i] + ': ' + event[keys[i]]);
}
so I can find is there any data about cell, no luck.
var sel = grid.getSelection()[0];
only returns recid not any thing about cell.
thanks
So I was in the presumption that this function
button.onclick = exampleFunk;
would give me a handler on each button when I click them, but it doesn't. When replacing it with:
button.onclick = alert("bananas");
I'm getting alerts at page onload. The problem is already solved with this:
button.setAttribute("onclick", "removeIssue(this)");
Out of curiousity... What's going on?
edited layout of post
EDIT
var issues = [];
window.onload = function () {
//alert("venster geladen");
issuesToList()
}
function issuesToList(data) {
/*alert(
"array length is " + data.issues.length + "\n" +
"total_count is " + data.total_count + "\n" +
"limit is " + data.limit + "\n" +
"offset is " + data.offset + "\n" + ""
);*/
for (i = 0; i < data.issues.length; i++) {
issue = data.issues[i];
createIssue(issue);
}
}
function createIssue(issue){
var id = issue.id;
var tracker = issue.tracker;
var status = issue.status;
var priority = issue.priority;
var subject = issue.subject;
var description = issue.description;
var assignee = issue.assignee;
var watchers = issue.watchers;
var ticket = new Issue(id, tracker, status, priority, subject, description, assignee, watchers);
issues.push(ticket);
var button = document.createElement("button");
button.innerHTML = "-";
button.onclick = function (){ alert("bananas")};
//button.setAttribute("onclick", "removeIssue(this)");
var item = document.createElement("div");
item.setAttribute("id", id);
item.appendChild(button);
item.innerHTML += " " + subject;
var container = document.getElementById("container");
container.appendChild(item);
}
function removeIssue(e){
var key = e.parentNode.getAttribute("id");
var count = issues.length;
if(confirm("Confirm to delete")){
for(i=0; i<count; i++){
if (issues[i].id == key ){
issues.splice(i,1);
var element = document.getElementById(key);
element.parentNode.removeChild(element);
}
}
}
}
function Issue(id, tracker, status, priority, subject, description, assignee, watchers){
this.id = id;
this.tracker = tracker;
this.status = status;
this.priority = priority;
this.subject = subject;
this.description = description;
this.assignee = assignee;
this.watchers = watchers;
}
EDIT
<body>
<h1>List of Issues</h1>
<div id="container"></div>
<script src="http://www.redmine.org/issues.json?limit=10&callback=issuesToList"></script>
</body>
You need to mask the alert in a function:
button.onclick = function (){ alert("bananas")};
As such:
var btn = document.createElement("BUTTON");
var t = document.createTextNode("CLICK ME");
btn.appendChild(t);
btn.onclick = function() {alert("bananas")};
document.body.appendChild(btn);
Whats going on?
You alert() is executed on page load because its a function call. When the execution of your script reaches that line your assignment
button.onclick = alert("bananas");
is actually executing the alert statement and not assigning it to button.onclick
You can bind arguments to the function so that it returns with the function you want it to call using your arguments (with additional arguments passed later added on to the end). This way doesn't require writing extraneous code (when all you want to do is call a single function) and looks a lot sleeker. See the following example:
button.onclick = alert.bind(window, "bananas");
An unrelated example of how it works in your own code is like this:
var alert2 = alert.bind(window, 'Predefined arg');
alert2(); // 'Predefined arg'
alert2('Unused'); // 'Predefined arg'
For IE, this requires IE9 as a minimum. See MDN for more information.
EDIT: I've looked closer at your code and there was one significant change that was needed for it to work... You cannot add onto the innerHTML when you've added JavaScript properties to a child element. Changing the innerHTML of the parent element will convert your element into HTML, which won't have the onclick property you made before. Use element.appendChild(document.createTextNode('My text')) to add text dynamically.
See a functioning example here: http://jsfiddle.net/2ftmh0gh/2/
Sorry if this seems a bit easy. I'm still relatively new to Javascript.
I am generating a list of checkboxes. On the onClick of a checkbox, i want to make it pop up its associated text. ie. Checkbox named "one" should then display "one". In my example it only displays "two".
However the click() callback method only ever calls the text of the last added checkbox. Does the 'v' variable in here not get assigned per checkbox? It seems like the'v' is behaving like a global variable.
this.view = document.createElement("div");
var tbody = document.createElement("tbody");
var popupValues = {"A", "B"};
for (var i=0;i<this.popupValues.length;i++) {
var v = popupValues[i];
var tr = document.createElement('tr');
var tdCheck = document.createElement('td');
var ChkBx = document.createElement('input')
ChkBx.type = 'checkbox';
tdCheck.appendChild(ChkBx);
var self = this;
$(ChkBx).live('change', function(){
if($(this).is(':checked')){
alert('checked' + v);
} else {
alert('un-checked' + v);
}
});
var td = document.createElement("td");
td.appendChild(document.createTextNode('' + v));
tr.appendChild(tdCheck);
tr.appendChild(td);
tbody.appendChild(tr);
}
table.appendChild(tbody);
document.appendChild(table)
Here is jsfiddle :
http://jsfiddle.net/n5GZW/2/
Anyone know what I am doing wrong?
UPDATE: updated JSFiddle
"Does the 'v' variable in here not get assigned per checkbox?"
Well, it's assigned, but not declared for each checkbox.
In Javascript variables only have function scope. Even if you try to create a new variable in each iteration of the loop, it's only a single variable declared at the function level, shared by all iterations. The declaration is hoisted to the function level, only the assignment happens inside the loop.
You can use an immediatey executed function expression to create another scope inside the loop, where you can create a new variable for each iteration:
for (var i=0;i<this.popupValues.length;i++) {
(function(v){
// code of the loop goes in here
// v is a new variable for each iteration
}(popupValues[i]));
}
you can do
var table = document.createElement("table");
var tbody = document.createElement("tbody");
var popupValues = [
"one", "two"
];
for (var i = 0; i < popupValues.length; i++) {
var v = popupValues[i];
var tr = document.createElement('tr');
var tdCheck = document.createElement('td');
var ChkBx = document.createElement('input');
ChkBx.type = 'checkbox';
ChkBx.value=v;
tdCheck.appendChild(ChkBx);
var td = document.createElement("td");
td.appendChild(document.createTextNode('' + v));
tr.appendChild(tdCheck);
tr.appendChild(td);
tbody.appendChild(tr);
var self = this;
$(ChkBx).click('change', function () {
if ($(this).is(':checked')) {
alert('check ' + $(this).val());
} else {
alert('un-checked');
}
});
}
table.appendChild(tbody);
document.body.appendChild(table)
http://jsfiddle.net/n5GZW/4/
add ChkBx.value=v; to get value like $(this).val() on click
You could've searched in SO for event binding in for loop.
Here is one solution:
Try this:
this.view = document.createElement("div");
var tbody = document.createElement("tbody");
var popupValues = {"A", "B"};
for (var i=0;i<this.popupValues.length;i++) {
var v = popupValues[i];
var tr = document.createElement('tr');
var tdCheck = document.createElement('td');
var ChkBx = document.createElement('input')
ChkBx.type = 'checkbox';
tdCheck.appendChild(ChkBx);
var self = this;
(function(val) {
$(ChkBx).on('change', function(){
if($(this).is(':checked')){
alert('checked' + val);
} else {
alert('un-checked' + val);
}
});
})(v);
var td = document.createElement("td");
td.appendChild(document.createTextNode('' + v));
tr.appendChild(tdCheck);
tr.appendChild(td);
tbody.appendChild(tr);
}
table.appendChild(tbody);
document.appendChild(table);
My system fatches data every 500 ms and my screen is full of html tables apart from each other . And every cell has unique key attribute. I am caching all of them anyway.
I have a global JavaScript object(_cellColorTimeouts) which contains settimeout functions for cellElements of tableRows that I mentioned above. After caching of cells, system creates timeout functions which is to wipe css out for spesific cell (in 3000ms).
In code block below uiElementKey_X and uiElementKey_Y are exact same but cached like are different. Adding unique suffix into table id makes them different. This proccess is done for row and cell items aswell.
example of _cellColorTimeouts data is
//array object keys are names of unique cell items.
_cellColorTimeouts = [uiElementKey_X_1, uiElementKey_X_2, uiElementKey_X_3,
uiElementKey_Y_1, uiElementKey_X_2, uiElementKey_Y_3];
.
. //does somethings to change cell colour
.
//after 3 seconds i need to clear css of this cell without looping the dom so i do it via cached dom.
if (_cellColorTimeouts.hasOwnProperty(uiElementKey) && _cellColorTimeouts[uiElementKey] != null) {
clearTimeout(_cellColorTimeouts[uiElementKey]);
_cellColorTimeouts[uiElementKey] = null;
}
_cellColorTimeouts[uiElementKey] = setTimeout(function () {
clearColourOfCell(cell);
}, 3000);
}
function clearColourOfCell(cell) {
cell.style.backgroundColor = cell.rowBGColour;
cell.style.color = "black";
_cellColorTimeouts[cell.uiElementKey] == null;
clearTimeout(_cellColorTimeouts[cell.uiElementKey]);
}
So the problem is settimeout function is not working for the first table but second is totally fine. I have checked is there any settimeout function return id from global, yes it has. For the first table somehow it does not work. I know this question is too unique for my case but any idea will be preciated?
---- EDIT ---- FULL FUNCTION UNCUT VERSION -----
function setWidgetData(widgetId, rowId, colId, value, colIndex) {
"use strict";
// check colIndex
if (colIndex === undefined || colIndex === null) {
colIndex = 0;
}
// loop on ui tables
var uiTables = _widgetUIElements[widgetId];
//var timeout;
for (var tableId in uiTables) {
var uiTable = uiTables[tableId];
var uiElementKey = tableId + "#" + rowId + "#" + colId + "#" + colIndex;
var cellCachedObject = uiTable[uiElementKey];
// check cell
if (cellCachedObject == undefined) {
//console.log("cell is undefined : " + "widgetId : " + widgetId + " - " + "rowId : " + rowId + " - " + "colId : " + colId + " - " + "colIndex : " + colIndex);
}
else {
// get cell
var cell = cellCachedObject["domElement"];
// set sell value
var cellValue = value;
// is value numeric? it means we will make some conversions on value
if (isNumeric(cellValue)) {
var canPaint = false;
// check cell entity
switch (cellCachedObject["entity"]) {
// date-time?
case "DATETIME":
// convert unix date time to readable date time
cellValue = new Date(fixDecimalSeparator(cellValue) * 1000);
cellValue = fixDateTimeDigits((cellValue.getDate())) + "/" + fixDateTimeDigits((cellValue.getMonth() + 1)) + " " + fixDateTimeDigits(cellValue.getHours()) + ":" + fixDateTimeDigits(cellValue.getMinutes());
break;
// date?
case "DATE":
// convert unix date time to readable date time
cellValue = new Date(fixDecimalSeparator(cellValue) * 1000);
cellValue = fixDateTimeDigits((cellValue.getDate())) + "/" + fixDateTimeDigits((cellValue.getMonth() + 1));
break;
// numeric?
case "NR":
// fix "," character in value
cellValue = fixDecimalSeparator(cellValue);
//just format the presicion
cellValue = number_format(cellValue, cellCachedObject["precision"], '.', ',');
canPaint = true;
break;
// other?
default:
// fix "," character in value
cellValue = fixDecimalSeparator(cellValue);
// if cell is number, no entity conversion
// entity convertion
cellValue = entityConverter(cellCachedObject["entity"], cellCachedObject["entityTo"], cellValue);
cellValue = new Number(cellValue).toFixed(cellCachedObject["precision"]);
// if widget currency is not USD. it means user selected currency from currency list or default user currency
if (cellCachedObject["isConvertable"]) {
// this scoop is not active with the new xml. if FOREX1 widget entity is RECIPCUR but never should not be
if (cellCachedObject["widgetIsFOREX1"]) {
cellValue = _currencyConverter.convertTrend(cellValue, cellCachedObject.currencyValueType, cellCachedObject["currencyTo"], cellCachedObject["rowId"], cellValue);
}
else {
cellValue = _currencyConverter.convert(cellValue, cellCachedObject["currency"], null, cellCachedObject["precision"]);
}
}
canPaint = true;
}
// if it is not date time
if (canPaint) {
// get current value of cell
var currentValue = cell.getAttribute("currentValue");
// check current value of cell make them coloured.
if (currentValue !== undefined) {
// new value is bigger than old value
var newVal = parseFloat(value);
var oldVal = parseFloat(currentValue);
var rowBGColour = cellCachedObject["rowBGColor"];
cell.rowBGColour = rowBGColour;
cell.uiElementKey = uiElementKey;
if (newVal > oldVal) {
//cell.css({ "background-color": "Green", "color": "White" });
cell.style.backgroundColor = "green";
cell.style.color = "white";
}
// new value is smaller than old value
if (newVal < oldVal) {
//cell.css({ "background-color": "Red", "color": "White" });
cell.style.backgroundColor = "red";
cell.style.color = "white";
}
if (_cellColorTimeouts.hasOwnProperty(uiElementKey) && _cellColorTimeouts[uiElementKey] != null) {
clearTimeout(_cellColorTimeouts[uiElementKey]);
_cellColorTimeouts[uiElementKey] = null;
}
_cellColorTimeouts[uiElementKey] = setTimeout(function () {
return function () {
clearColourOfCell(cell);
};
} (cell), 3000);
newVal = oldVal = rowBGColour = null;
}
currentValue = null;
}
canPaint = null;
// set new value as a current value
cell.setAttribute("currentValue", value);
}
cell.innerHTML = '';
cell.innerHTML = cellValue;
cellValue = null;
}
uiTable = uiElementKey = cellCachedObject = null;
}
uiTables = null;
}
You didn't post enough code for me to know for sure that this is the problem, but it's a good bet:
_cellColorTimeouts[uiElementKey] = setTimeout(function () {
return function() {
clearColourOfCell(cell);
};
}(cell), 3000);
By setting up the timeout handler like that, you ensure that the handler has its own private copy of that "cell" variable, so that no matter how "cell" is changed before the handler is finally invoked, that copy will retain the correct value.
I am trying to dynamically make divs that are clickable. I have inserted a test function. The test function runs even though the div has not been clicked.
function displayResults(responseTxt)
{
var results = document.getElementById("results");
jsonObj = eval ("(" + responseTxt + ")");
var length = jsonObj.response.artists.length;
results.innerHTML = "Please click on an artist for more details: "
for ( var i = 0; i < length; i++)
{
var entry = document.createElement("div");
var field = document.createElement("fieldset");
entry.id = i;
entry.innerHTML = i + 1 + ". " + jsonObj.response.artists[i].name;
field.appendChild(entry);
results.appendChild(field);
//entry.addEventListener("click", idSearch(jsonObj.response.artists[i].id), false);
entry.addEventListener("click", test(), false);
}
} // end function displayResults
function test()
{
document.getElementById("results").innerHTML = "tested";
}
You are calling the test() function and passing its return value to .addEventListener(). Remove the parentheses:
entry.addEventListener("click", test, false);
So that you pass the function itself to .addEventListener().
That answers the question as asked, but to anticipate your next problem, for the line you've got commented out you'd do this:
entry.addEventListener("click",
function() {
idSearch(jsonObj.response.artists[i].id);
}, false);
That is, create an anonymous function to pass to .addEventListener() where the anonymous function knows how to call your idSearch() function with parameters. Except that won't work because when the event is actually triggered i will have the value from the end of the loop. You need to add an extra function/closure so that the individual values of i are accessible:
for ( var i = 0; i < length; i++)
{
var entry = document.createElement("div");
var field = document.createElement("fieldset");
entry.id = i;
entry.innerHTML = i + 1 + ". " + jsonObj.response.artists[i].name;
field.appendChild(entry);
results.appendChild(field);
// add immediately-invoked anonymous function here:
(function(i) {
entry.addEventListener("click",
function() {
idSearch(jsonObj.response.artists[i].id);
}, false);
})(i);
}
That way the i in jsonObj.response.artists[i].id is actually going to be the parameter i from the anonymous function which is the individual value of i from the loop at the time each iteration ran.