Failure in changing node content + JavaScript - javascript

I wrote this code for create menu with div tag
HTML:
<div id="firstMenuList">
<div id="firstMenu">choose▼</div>
<div id="menulist" class="menulist"></div>
</div>
JavaScript:
<script>
function ccc() {
var id="firstMenu";
var ar=new Array("hi","there","hello","world");
var node=document.createElement("div");
var parent=document.getElementById("menulist");
var nodeData="";
for (var i=0;i<ar.length;i++)
{
var node=document.createElement("div");
node.setAttribute("id",id+""+i);
node.setAttribute("class","menulist");
node.setAttribute("onclick","select("+id+""+i+")");
node.style.top=((i+1)*100)+3+"%";
node.innerHTML=ar[i];
parent.appendChild(node);
}
}
function select(id)
{
var p=document.getElementById(id);<-this doesn't work on elements that created dynamically
p.style.backgroundColor="red";
var t = p.innerHTML;
}
</script>
This code creates the menu, but when I click on the menu items code breaks.
The error is:
"parent is null"

To pass the id to the function you need to ensure that you put quotes around the id:
node.setAttribute("onclick","select('"+id+i+"')");
// note the single quotes ----------^--------^
Demo: http://jsfiddle.net/QK5Wh/1/
But you don't need to use the id to get the element when you can pass a direct reference to the element itself:
node.setAttribute("onclick","select(this)");
And then:
function select(p) {
p.style.backgroundColor="red";
var t = p.innerHTML;
}
Demo: http://jsfiddle.net/QK5Wh/

I'll suggest to avoid the inline event binding. Here is a working example:
http://jsfiddle.net/H4S2f/1/
function ccc() {
var id="firstMenu";
var cls="firstMenuList";
var ar=new Array("hi","there","hello","world");
var node=document.createElement("div");
var parent=document.getElementById("menulist");
var nodeData="";
for (var i=0;i<ar.length;i++)
{
var node=document.createElement("div");
node.setAttribute("id",id+""+i);
node.setAttribute("class","menulist");
(function(i) {
node.addEventListener("click", function() {
select(id+""+i)
});
})(i);
node.style.top=((i+1)*100)+3+"%";
node.innerHTML=ar[i];
parent.appendChild(node);
}
}
function select(id)
{
var p=document.getElementById(id);
p.style.backgroundColor="red";
var t = p.innerHTML;
}
ccc();

Related

jquery create and return DOM element on click

I have button that creates a div on click. I want to return this created div when I click a button. But the following code actually returns this button.
var create = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
return content
})
var test = create.trigger('click')
console.log(test)
Result is:
init [div#create, context: document, selector: '#create']
Is this not possible to do this this way or am I missing something?
No, it is not possible. You can add a function which will be executed in your event handler to do something with the object you create in the listener:
var create = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
doSomething(content)
})
create.trigger('click')
function doSomething(test) {
console.log(test)
}
There is no other way and it is because the handler function assigned with .on() method is called when the browser triggers an event (or you use .trigger() method) and the return statement is used only to force calling event.stopPropagation() and event.preventDefault() methods (you have to return false in the handler or just assign false instead of a function as an event handler - check the documentation, section The event handler and its environment) and not to return any value when you trigger an event manually.
You can also use an external variable to store the data "generated" in your event handler:
const divs = []
var create = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
divs.push(content)
doSomething()
})
create.trigger('click')
function doSomething() {
console.dir(divs)
}
You're calling a variable ("create") which stores the event listener on the button. This is what it looks like:
var test = $('#create').on('click', function(e){
var content = $('<div class="foo"/>')
return content
}).trigger('click')
console.log(test)
This is the solution:
jQuery
var create = function() {
return $('<div class="foo"/>');
};
var createEl = $('#create');
createEl.on('click', function() {
console.log(create());
// <div class="foo"></div>
});
createEl.trigger("click");
JavaScript
var create = function() {
var el = document.createElement('div');
el.className = "foo";
// Add other attributes if you'd like
return el;
};
var createEl = document.querySelector('#create');
createEl.addEventListener("click", function() {
console.log(create());
// <div class="foo"></div>
});
createEl.click();
(jQuery) Live example
var create = function() {
return $('<div class="foo"/>');
};
var createEl = $('#create');
createEl.on('click', function() {
console.log(create());
// <div class="foo"></div>
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<button id="create">Create</button>
(JavaScript) Live example
var create = function() {
var el = document.createElement('div');
el.className = "foo";
// Add other attributes if you'd like
return el;
};
var createEl = document.querySelector('#create');
createEl.addEventListener("click", function() {
console.log(create());
// <div class="foo"></div>
});
createEl.trigger("click");
var create = function() {
var el = document.createElement('div');
el.className = "foo";
// Add other attributes if you'd like
return el;
};
var createEl = document.querySelector('#create');
createEl.addEventListener("click", function() {
console.log(create());
// <div class="foo"></div>
});
<button id="create">Create</button>

Update text from variable using a common function javascript

I want to make a common function that can be call in html so I can update the value from variable.
function getActivityPoint(activityName) {
document.getElementsByClassName('share_points')[0].innerHTML = activityName;
}
my variable
var ap = {
'movie_review':'20',
}
And in HTML I would like to do this.
<div class="share_points" onload="getActivityPoint(ap.movie_review)">-</div>
<div class="share_points" onload="getActivityPoint(ap.game_review)">-</div>
.............
The inline onload event does not work for a div.
You may change your code in order to change your divs, using data attributes, like:
<div class="share_points" data-load="movie_review">-</div>
and on window load you can do your work:
window.addEventListener("load", function(event) {
document.querySelectorAll('.share_points').forEach(ele => getActivityPoint(ele, ap[ele.dataset.load]));
});
function getActivityPoint(ele, activityName) {
ele.textContent = activityName;
}
var ap = {
'movie_review':'20',
'game_review': 10
}
/****************
For Compatibility issue you may write:
window.addEventListener("load", function (event) {
Array.prototype.slice.call(document.querySelectorAll('.share_points')).forEach(function (ele) {
getActivityPoint(ele, ap[ele.dataset.load]);
});
});
For IE < 9 the solution is:
window.addEventListener("load", function (event) {
var divs = document.querySelectorAll('.share_points');
for (i = 0; i < divs.length; i++) {
getActivityPoint(divs[i], ap[divs[i].dataset.load]);
}
});
*/
<div class="share_points" data-load="movie_review">-</div>
<div class="share_points" data-load="game_review">-</div>
You can do:
var ap = {
'movie_review': '20',
'game_review': '100'
},
share_points = document.getElementsByClassName('share_points');
window.addEventListener('load', function() {
Array.prototype.forEach.call(share_points, function(el) {
el.innerHTML = ap[el.dataset.review];
});
});
<div class="share_points" data-review="movie_review">-</div>
<div class="share_points" data-review="game_review">-</div>

How to get all related javascript to an html element

Is there a way to get all javascript associated with an html element by class name returned in an array? Any suggestion as to how one would achieve doing this? Are there any node packages that would allow me to do something like this?
For example:
HTML
<div class="click_me">Click Me</div>
JS
$('.click_me').on('click', function() { alert ('hi') });
I would want something like (psuedo-code either on the client or server side):
function meta() {
let js = [];
js = getAllJavascriptByClassName('click_me');
console.log(js[0]);
}
Output of meta()
$('.click_me').on('click', function() { alert ('hi') });
This will pull out all event handlers of all elements of given class.
But these handlers must be attached using jquery.
function getAllEventHandlersByClassName(className) {
var elements = $('.' + className);
var results = [];
for (var i = 0; i < elements.length; i++) {
var eventHandlers = $._data(elements[i], "events");
for (var j in eventHandlers) {
var handlers = [];
var event = j;
eventHandlers[event].forEach(function(handlerObj) {
handlers.push(handlerObj.handler.toString());
});
var result = {};
result[event] = handlers;
results.push(result);
}
}
return results;
}
// demo
$('.target').on('click',function(event){
alert('firstClick handler')
});
$('.target').on('click',function(event){
alert('secondClick handler')
});
$('.target').on('mousedown',function(event){
alert('firstClick handler')
});
console.log(getAllEventHandlersByClassName('target'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='target'> </div>
You can use getEventListeners() which is part of the chrome devtools but for employing client side, there's an possible-duplicate question that partially answers this: How to find event listeners on a DOM node when debugging or from the JavaScript code? which basically shows (in the second voted answer) that depending on how the events are set (javascript attribute, eventListener, jquery, other lib) there are different ways to retrieve the functions.
The Visual Event 2 program mentioned in the first question seems to be more of a library doing what the second answer is suggesting so maybe this will solve your problem.
If you are interested only in jQuery solution I may suggest you (I assume there is only one event per type, but you need to cycle on all instances):
function getAllJavascriptByClassName(className) {
var elem = $('.' + className);
var result = [];
$('.' + className).each(function(index, element) {
var resultObjs = jQuery._data(element, "events");
var partialResult = [];
var x = Object.keys(resultObjs).forEach(function(currentValue, index, array) {
partialResult.push(resultObjs[currentValue][0].handler.toString());
});
result.push(partialResult);
});
return result;
}
function meta() {
let js = [];
js = getAllJavascriptByClassName('click_me');
console.log(JSON.stringify(js, null, 4));
}
$(function () {
$('.click_me').on('click', function (e) {
alert('Click event: hi')
});
$('.click_me:last').on('keypress', function (e) {
alert('Keypress event: hi')
});
meta();
});
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<div class="click_me">Click Me</div>
<div class="click_me">Click Me</div>
I would personally override addEventListener at the right places (meaning at the very top) with some safe guards.
UNfortunately jquery event handlers appear to be quite hard to read...
var element = document.getElementById("zou");
element.addEventListener("click", function(e) {
console.log("clicked from addevent");
});
element.addEventListener("mouseup", function(e) {
console.log("mouseup from addevent");
});
$(element).on("mousedown", function(e) {
console.log("mousedown from $")
});
console.log(element.getListeners());
<script>
window.eventStorage = {};
(function() {
var old = HTMLElement.prototype.addEventListener;
HTMLElement.prototype.addEventListener = function(a, b, c) {
if (!window.eventStorage[this]) {
window.eventStorage[this] = [];
}
var val = {
"event": a,
"callback": b
};
var alreadyRegistered = false;
var arr = window.eventStorage[this];
for (var i = 0; i < arr.length; ++i) {
if (arr.event == a && arr.callback == b) {
alreadyRegistered = true;
break;
}
}
if (!alreadyRegistered) {
arr.push(val);
}
old.call(this, a, b, c);
}
HTMLElement.prototype.getListeners = function() {
return window.eventStorage[this] || {};
}
}());
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="zou">click on me</div>

Javascript Dynamically invoke shortcut keys combination function to shortcutjs plugin

Am getting key Combination from the server. Based on that am assigning key Combination to function dynamically. The below code is working for last iteration in loop. how below code is work for all iterations.
In my page i have two buttons save and cancel the below code is working for last iteration in for loop, It means btnCanel button triggers if i press key for save function.Any suggestions. hope understand my question.
$(document).ready(function fn() {
var keyCombination = new Object();
keyCombination['btnAdd'] = "Alt+S";
keyCombination['btnCancel'] = "Alt+C";
for (var k in keyCombination) {
if (keyCombination.hasOwnProperty(k)) {
shortcut.add(String(keyCombination[k]), function () {
var btnAdd = document.getElementById(String(k));
btnAdd.focus();
btnAdd.click();
});
}
}
});
if i give like this means it is working
shortcut.add("Alt+S", function () {
var btnAdd = document.getElementById('btnAdd ');
btnAdd .focus();
btnAdd .click();
});
shortcut.add("Alt+C", function () {
var btnCancel = document.getElementById('btnCancel');
btnCancel.focus();
btnCancel.click();
});
but if i try to add dynamically its overriding help me this issue.
Thanks in Advance.
I created a separate function outside the document.ready function like this now its working fine.
$(document).ready(function fn() {
var keyCombination = new Object();
keyCombination['btnAdd'] = "Alt+S";
keyCombination['btnCancel'] = "Alt+C";
for (var k in keyCombination) {
if (keyCombination.hasOwnProperty(k)) {
Set_KeyCombinations(k, keyCombination);
}
}
});
function Set_KeyCombinations(k, keyCombination) {
shortcut.add(String(keyCombination[k]), function () {
var eleId = document.getElementById(String(k));
if (eleId) {
if ($('#' + String(k).trim()).css('display') !== 'none' && eleId.getAttribute("disabled") !== "disabled") {
eleId.click();
eleId.focus();
}
}
});
}
Try this:
var keyCombinations = [ "Ctrl+Shift+X" , "Ctrl+Shift+Y" ];
for(var i=0; i<keyCombinations.length; i++){
(function(shorcutCombination){
shortcut.add(shorcutCombination,function() {
alert("i am " + shorcutCombination);
});
})(keyCombinations[i]);
}
The idea is that you need to preserve the value of keyCombinations[i]
as i increases in the loop. Tested this here: Openjs

Issue adding event with addEventListener to Input in documentFragment

I am creating a div using createDocumentFragment(). In the Div is a table with a list of input. When you click on any of the checkboxes I want to trigger the alert('Yes'). when I add the event it does not add it to the input but with Firefox it seems to call the alert when it is added to the table.
Can someone explain what I am doing wrong?
function deptFilter(rPattern)
{
var lclData = JSON.parse(rPattern);
var loc = document.getElementById('show2');
var arrayKeys = Object.keys(lclData);
var outputData;
var LCL_List
var LCLTables;
var LCLtd;
var LCLtr;
var LCLInput;
var LCLDiv;
var LCL_List = document.createDocumentFragment(document.createElement('DIV'));
LCL_List.id = 'LCLTable';
for(var x = 0; x < arrayKeys.length; x++)
{
LCLDiv = LCL_List.appendChild(document.createElement('DIV'));
LCLTables = LCLDiv.appendChild(document.createElement('TABLE'));
for(var y = 0; y < lclData[arrayKeys[x]].length; y++)
{
LCLtr = LCLTables.appendChild(document.createElement('TR'));
LCLtd = LCLtr.appendChild(document.createElement('TD'));
LCLInput = LCLtd.appendChild(document.createElement('INPUT'));
LCLInput.id = lclData[arrayKeys[x]][y]['Name'];
LCLInput.type='checkbox';
LCLInput.addEventListener("click", alert("Yes"));
}
}
loc.appendChild(LCL_List);
}
When you install an event handler like this:
LCLInput.addEventListener("click", alert("Yes"));
You're executing alert() immediately and then passing the return value from that to addEventListener(). This is obviously NOT what you want. Instead, you need to pass a function reference to addEventListener and that function will then call your alert() sometime later:
LCLInput.addEventListener("click", function(e) {
alert("Yes");
});
Or you can define a named function and pass just its name:
function handleClick(e) {
alert("Yes");
}
LCLInput.addEventListener("click", handleClick);
This is the way to add event listner:
LCLInput.addEventListener("click", function() {
alert("Yes");
});

Categories