Javascript Dynamically Created Event Handlers Disappear once another is added - javascript

I have an ordered list that I want to have items disappear from when clicked.
I have the following javascript code:
<script>
let halls = new Set();
function rm() {
halls.delete((this.id).substring(0,this.id.length-4));
document.getElementById(this.id).remove();
}
function setEventHandler(obj, name, fn) {
if (typeof obj == "string") {
obj = document.getElementById(obj);
}
if (obj.addEventListener) {
return(obj.addEventListener(name, fn));
} else if (obj.attachEvent) {
return(obj.attachEvent("on" + name, function() {return(fn.call(obj));}));
}
}
function addHall() {
let oldSize = halls.size;
let chosen = document.getElementById("hall2").value;
halls.add(chosen);
if (oldSize != halls.size) {
document.getElementById("fillHall").innerHTML += `<li id="${chosen}List" name="${chosen}" >${chosen}</li>`;
setEventHandler(chosen + "List", "click", rm);
}
};
document.getElementById("hall2").onchange = addHall;
</script>
Is there something I'm doing wrong?? How do I keep the event handler that will remove the list item?
I know my code is sloppy :/ sorry
Thanks

Related

How can I write my listener function somewhere else if it uses local variables?

I am a beginner in Javascript development and I have to do the classical to-do app. It has to be object-oriented and my program has two classes: Task and Tag.
A task contains some tags.
When the user clicks on a tag, he can modify its name. First, I did wrote an anonymous callback function which was listening to the modification form submission and it worked well. But, I have to create a named function declared somewhere else instead of my existing listener. However, I need to access to some of the properties of my object (which is edited) and I have absolutely no idea how to do a thing like that.
Here is a small part of my code:
module.Tag = class Tag {
constructor(name = 'untitled', parent = null) {
this.name = name;
this.parentTask = parent;
}
//Method which displays the tag name
display_name() {
return $('<li>').addClass('tag').text(this.name);
}
//Method which displays the tag
display() {
let tag_item = this.display_name();
let field = $('<input>').prop('type', 'text').prop('value', this.name);
let button = $('<button>').addClass('validationButton').prop('type', 'submit').text('✓');
let removeButton = $('<button>').addClass('removeButton').text('X');
let form = $('<form>').append(field).append(button).append(removeButton);
let in_edit = false;
tag_item.click((event) => {
event.stopPropagation();
event.preventDefault();
let target = $(event.target);
if (target.is('li') && !in_edit) {
tag_item.empty();
tag_item.append(form);
in_edit = true;
}
if (target.is('button') && target.prop('type') === 'submit') {
if(field.val() !== '') {
this.name = field.val();
module.StorageManager.storeTasks();
}
tag_item.empty();
tag_item.text(this.name);
field.val(this.name);
in_edit = false;
}
if (target.is('button') && target.hasClass('removeButton')) {
if(confirm('Voulez-vous vraiment supprimer ce tag ?')) {
tag_item.remove();
this.removeTagFromParent();
module.StorageManager.storeTasks();
}
}
});
return tag_item;
}
//Method which removes the tag from the parent task
removeTagFromParent() {
this.parentTask.removeTag(this);
}
};
My listener is in the display method and it uses Tag.name property and some of the variables created in the method body. I can't see how to write this function somewhere else and Google didn't help me.
I hope my problem is clear, English is not my native language.
Some advices?
You can extract your anonymouse function to be another class method. It is an event handler so in order to correctly access the defined object you'll have to bind it correctly.
Here is an example of the modified script:
module.Tag = class Tag {
constructor(name = 'untitled', parent = null) {
this.name = name;
this.parentTask = parent;
}
//Method which displays the tag name
display_name() {
return $('<li>').addClass('tag').text(this.name);
}
//Method which displays the tag
display() {
let tag_item = this.display_name();
let field = $('<input>').prop('type', 'text').prop('value', this.name);
let button = $('<button>').addClass('validationButton').prop('type', 'submit').text('✓');
let removeButton = $('<button>').addClass('removeButton').text('X');
let form = $('<form>').append(field).append(button).append(removeButton);
let in_edit = false;
tag_item.click(this.handleClick.bind(this));
// this is where you invoke the function and
//bind it to the context of the class
return tag_item;
}
//Method which removes the tag from the parent task
removeTagFromParent() {
this.parentTask.removeTag(this);
}
// extracted method defined here:
handleClick(event) {
let tag_item = this.display_name();
let field = $('').prop('type', 'text').prop('value', this.name);
event.stopPropagation();
event.preventDefault();
let target = $(event.target);
if (target.is('li') && !in_edit) {
tag_item.empty();
tag_item.append(form);
in_edit = true;
}
if (target.is('button') && target.prop('type') === 'submit') {
if(field.val() !== '') {
this.name = field.val();
module.StorageManager.storeTasks();
}
tag_item.empty();
tag_item.text(this.name);
field.val(this.name);
in_edit = false;
}
if (target.is('button') && target.hasClass('removeButton')) {
if(confirm('Voulez-vous vraiment supprimer ce tag ?')) {
tag_item.remove();
this.removeTagFromParent();
module.StorageManager.storeTasks();
}
}
}
};

No function call onClick

I have an object with a function inside of it but i can't get the function to execute on click
This is the fiddle https://jsfiddle.net/tgxu7rpv/23/
and this is the code
$(document).ready(function () {
MyObject = {
ae: function(clicked_id) {
var items = JSON.parse(localStorage.getItem('entry'));
if (items == null || typeof items !== 'object') {
items = [];
}
var entry = {
'num': clicked_id
};
items.push(entry);
localStorage.setItem('entry', JSON.stringify(items));
alert(localStorage.getItem('entry'));
var fromStorage = localStorage.getItem('entry');
for (var data in fromStorage) {
alert("Value" + fromStorage[data]);
}
}
};
$(document).on('click', '.btn-primary', function(){
$('.table tbody').append('<tr class="child"><td>one</td><td><button id="num" onClick="MyObject.ae(this.id);" type="button" class="invite ">Invite</button></td></tr>');
});
});
I can't call the function onClick="MyObject.ae(this.id);"
This issue is a result of one of the default settings in JSFiddle.
You'll need to change one of the javascript settings.
Change the LOAD TYPE setting from:
to:
And that should do the trick!

Modified code is not correct for the getvalue and setvalue

My code was working fine but they wanted to change my code....
they wanted to attach setValue and getValue added directly to
footballPanel instead of sports grid,
but after adding it the code is not working fine...
can you tell me why its not working....
providing my modified code below...
the UI action here I am performing is there are two radio buttons,
when I click each radio button two different grids open
in one of the grid we add value, when i switch back to another radio
button the values in another grid disappears but it should not
disappear...
after I modified the code the values disappear, can you tell me why?
Only part of modified code here
else {
this.setDisabled(true);
this.addCls("sports-item-disabled");
if (sportsGrid.store.getCount() > 0) {
var footballPanel = sportsGrid.up('panel');
footballPanel.holdValue = footballPanel.getValue();
footballPanel.setValue();
sportsGrid.addCls("sports-item-disabled");
}
}
Whole modified code:
sportsContainerHandler: function(radioGroup, newValue, oldValue, options) {
var sportsCustomParams = options.sportsCustomParams;
var uiPage = this.up('football-ux-sports-ui-page');
var SportsDefinition = metamodelsHelper.getSportsDefinition(
uiPage, sportsCustomParams.SportsHandlerDefinitionId);
var sportsFieldParam = SportsDefinition.params['sportsMultiFieldName'];
var sportsGrid = uiPage.queryById(sportsFieldParam.defaultValue).grid;
if (newValue[radioGroup.name] == 'sportss') {
this.setDisabled(false);
this.removeCls("sports-item-disabled");
if (sportsGrid.holdValue) {
var footballPanel = sportsGrid.up('panel');
footballPanel.setValue(sportsGrid.holdValue);
}
} else {
this.setDisabled(true);
this.addCls("sports-item-disabled");
**if (sportsGrid.store.getCount() > 0) {
var footballPanel = sportsGrid.up('panel');
footballPanel.holdValue = footballPanel.getValue();
footballPanel.setValue();
sportsGrid.addCls("sports-item-disabled");
}**
}
},
Working code without modification
sportsContainerHandler: function(radioGroup, newValue, oldValue, options) {
var sportsCustomParams = options.sportsCustomParams;
var uiPage = this.up('football-ux-sports-ui-page');
var SportsDefinition = metamodelsHelper.getSportsDefinition(
uiPage, sportsCustomParams.SportsHandlerDefinitionId);
var sportsFieldParam = SportsDefinition.params['sportsMultiFieldName'];
var sportsGrid = uiPage.queryById(sportsFieldParam.defaultValue).grid;
if (newValue[radioGroup.name] == 'sportss') {
this.setDisabled(false);
this.removeCls("sports-item-disabled");
if (sportsGrid.holdValue) {
var footballPanel = sportsGrid.up('panel');
footballPanel.setValue(sportsGrid.holdValue);
}
} else {
this.setDisabled(true);
this.addCls("sports-item-disabled");
if (sportsGrid.store.getCount() > 0) {
sportsGrid.holdValue = sportsGrid.store.data.items;
sportsGrid.store.loadData([]);
sportsGrid.addCls("sports-item-disabled");
}
}
},
getValue() is not a method of ExtJS Panel class.
The change in your code, from sportsGrid (Ext.grid.Panel) to footbalPanel (Ext.panel.Panel) won't work, because they are from different classes and therefore have different properties and methods.
If you want this code to work, you'll need to implement getValue() and setValue(). For example, something like:
On FootballPanel class:
getValue: function () {
return this.down('grid').store.data.items;
},
setValue: function (newValue) {
if (!newValue)
newValue = new Array();
this.down('grid').store.loadData(newValue);
},
And use your modified code:
sportsContainerHandler: function(radioGroup, newValue, oldValue, options) {
var sportsCustomParams = options.sportsCustomParams;
var uiPage = this.up('football-ux-sports-ui-page');
var SportsDefinition = metamodelsHelper.getSportsDefinition(
uiPage, sportsCustomParams.SportsHandlerDefinitionId);
var sportsFieldParam = SportsDefinition.params['sportsMultiFieldName'];
var sportsGrid = uiPage.queryById(sportsFieldParam.defaultValue).grid;
if (newValue[radioGroup.name] == 'sportss') {
this.setDisabled(false);
this.removeCls("sports-item-disabled");
if (sportsGrid.holdValue) {
var footballPanel = sportsGrid.up('panel');
footballPanel.setValue(sportsGrid.holdValue);
}
} else {
this.setDisabled(true);
this.addCls("sports-item-disabled");
if (sportsGrid.store.getCount() > 0) {
var footballPanel = sportsGrid.up('panel');
footballPanel.holdValue = footballPanel.getValue();
footballPanel.setValue([]);
sportsGrid.addCls("sports-item-disabled");
}
}
},

Listen for keyup on all input fields

Im trying to capture the keyup on all input fields on a page.
My current code is:
var els = document.querySelectorAll('input');
for (var i = 0; i < els.length; i += 1) {
addEvent('keyup', els[i], makeHandler(els[i]));
}
function makeHandler(field) {
console.log(field.value);
}
function addEvent(evnt, elem, func) {
if (elem.addEventListener) {
elem.addEventListener(evnt,func,false);
} else if (elem.attachEvent) {
elem.attachEvent("on"+evnt, function(e) {
e = e || window.event;
if (!e.preventDefault) {
e.preventDefault = preventDefaultOnIE;
}
func.call(this, e);
});
} else { // No much to do
elem[evnt] = func;
}
}
But for some reason its only capturing the value on page load, not once i begin to type in any of the fields.
Any ideas what I'm doing wrong?
The problem is with your makeHandler function. makeHandler(els[i]) is being evaluated and the return value (undefined, in this case) is being passed to addEvent as a handler. Try:
function makeHandler(field) {
return function() {
console.log(field.value);
};
}
This way, makeHandler(els[i]) will return a function that addEvent can then attach to keyup.
Alternatively, you could also just use:
function makeHandler() {
console.log(this.value); // 'this' will be the field that the event occurred on
}
and then use:
addEvent('keyup', els[i], makeHandler);
Side-note
I noticed a slight error in your code:
else { // No much to do
elem[evnt] = func;
}
I think you really want to set elem["on" + evnt] instead.
I like to embed the script in a function so I can minimize it in my IDE and turn it on and off globally. In other words, give it a name.
attachKeyupListenerToInputElements();
function attachKeyupListenerToInputElements(){
var inputs = doc.querySelectorAll('input');
for (var i = 0; i < inputs.length; i += 1) {
inputs[i].addEventListener("keyup", keyupHandler);
}
function keyupHandler() {
console.log(this.value);
}
}
Is this what you are looking for:
<script>
$(document).ready(function () {
$("input").keyup(function () {
alert("keyup");
});
});
</script>

AddEventListener function won't execute

The iFrameOn function runs on page load, and up until it is supposed to execute the iBold function is works fine. I've gone through and debugged as much as possible, and everything seems fine. When I output every variable to the console, the values are correct. It's just that one line (iBold(targetiFrame);) that won't run. I'm not sure what's going on.
function iFrameOn() {
var iFrames = document.querySelectorAll('form > iframe'); //Get all iframes in forms
var bolds = new Array(), italics = new Array(), underlines = new Array(), targetiFrame;
var getRT = document.getElementsByClassName('richText');
for (var rtIndex = 0; rtIndex < getRT.length;rtIndex++) { //Rich text event listeners
var rtid = getRT[rtIndex].id;
if (getRT[rtIndex].className == "richText bold") { //Bold text event listener
console.log('The id is: '+rtid);
bolds.push(rtid);
console.log('The bolds array contains: '+bolds);
} else if (getRT[rtIndex].className == 'richText underline') { //Underline text event listener
underlines.push(getRT[rtIndex]);
} else if (getRT[rtIndex].className == 'richText italic') { //Italic text event listener
italics.push(getRT[rtIndex]);
}
}
bolds.forEach(function(e, i, a) { //e = a[i]
console.log('e is '+e);
document.getElementById(e).addEventListener('click', function() {
console.log(e+' was clicked!');
targetiFrame = document.getElementById(e).getAttribute('data-pstid');
iBold(targetiFrame);
}, false);
});
}
function iBold(target) {
if (target == 0) {
document.getElementById('richTextField').contentDocument.execCommand('bold', false, null);
document.getElementById('richTextField').contentWindow.focus();
} else {
document.getElementById(target).contentDocument.execCommand('bold', false, null);
document.getElementById(target).contentWindow.focus();
}
}
I apparently had another iBold function in another js file

Categories

Resources