I would like to add the condition, that the function is only triggered if both
addEventListener('change', SwitchG) Events are True (=both have changed).
The code which I use currently activates the function already when one of the two has changed.
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG () {
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
You need another variable, which checks if both have been changed and only executes the handler function if both changes already happened:
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
var countChanges = 0; // <-- this tracks changes
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG () {
countChanges += 1; // <-- count up
if (countChanges >= 2) {
countChanges = 0; // <-- reset (if needed)
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
}
A more robust implementation however, also tracks the elements which changed and ensures a repeating change event from a single element won't succeed to run the handler.
For example with this utility:
function ChangedCounter (minChanges) {
var elements = new Set();
return {
changed(element) {
elements.add(element);
},
clear() {
elements.clear();
},
isReady() {
return elements.size >= minChanges;
}
};
}
You'd write it like this:
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
var countChanges = ChangedCounter(2);
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG (e) {
countChanges.changed(e.target);
if (countChanges.isReady()) {
countChanges.clear();
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
}
You could create a "state" to store when the both has changed. I've created two variables, halloState and hallo1State. The snippet below shows how it could be done:
var hallo = document.getElementById("S131_01");
var hallo1 = document.getElementById("S130_01");
var halloState = false;
var hallo1State = false;
hallo.addEventListener('change', SwitchG);
hallo1.addEventListener('change', SwitchG);
function SwitchG (e) {
if(e.target.id === "S131_01") halloState = true;
else if(e.target.id === "S130_01") hallo1State = true;
if(halloState && hallo1State){
var test1 = document.getElementById("submit");
test1.classList.add("css");
}
}
.css {
background-color:red;
}
<input id="S131_01" type="text"/>
<input id="S130_01" type="text"/>
<button id="submit">Submit</button>
Related
Here I have declared a function "driverDetailsValidation" within the event listener. I want to call it from outside the event listener. This is the code which I have used but it doesn't work
driverType.onchange = function(e) {
var isWithoutDriver = (driverType.value == "without driver");
if(!isWithoutDriver){
driverDetailsValidation();
}
}
const driver_fields = document.getElementsByClassName("driver_fields");
form.addEventListener("submit", (event) => {
validity = true;
function driverDetailsValidation() {
for (let i = 0; i < driver_fields.length; i++) {
if (driver_fields[i].value == "") {
driver_fields[i].style.border = "2px solid rgb(228, 29, 22)";
driver_fields[i].style.backgroundColor = "rgba(238, 156, 156, 0.788)";
//fields[i].placeholder = "This Field is Compulsory!";
validity = false;
}
}
}
}
You could declare a variable outside the event listener and assign the function to it inside the listener. Then, you can call the function from the variable like this:
var fct;
document.querySelector("div").addEventListener("click", function() {
fct = function() {
alert("Working");
}
});
setInterval(function() {
if (fct != null) {
fct();
fct = null;
}
}, 0);
<div>
Click me
</div>
But it doesn't really make sense, I think.
I want to attach an event to a button and if user clicks, an alert should appear. But here, even if the user doesnt click, the alert appears.
Js File :
var init = function (m) {
_m = m;
var actionButton = document.getElementById("action");
if (actionButton) {
var buttonId = "action";
if (actionButton.attachEvent) {
actionButton.attachEvent("onclick", _onActionClick(buttonId));
}
}
var _onActionClick = function (buttonId) {
alert("3");
}
Here, I get alert 3.
But, with this code, I do not get alert 3.
var init = function (m) {
_m = m;
var actionButton = document.getElementById("action");
if (actionButton) {
var buttonId = "action";
if (actionButton.attachEvent) {
actionButton.attachEvent("onclick", _onActionClick);
}
}
var _onActionClick = function (){
alert("3");
}
Can someone, let me know where am I going wrong ?
onclick needs a function. You're using the return value of _onActionClick(buttonId) which is undefined
// no good!
actionButton.attachEvent("onclick", _onActionClick(buttonId));
Try using an actual function
actionButton.attachEvent("onclick", function(event) {
_onActionClick(buttonId)
})
Or you can define _onActionClick in curried form
var _onActionClick = function(buttonId) {
return function(event) {
console.log(buttonId, event)
}
}
// now when you call _onActionClick(buttonId) it will return a function ...
actionButton.attachEvent("onclick", _onActionClick("action"))
var asign = function(id){
return document.getElementById(id) ;
} ;
var f_name = asign('fname').value ;
var validate = function (a) {
this.a = a ;
if(!a){
alert("Somthing is require");
} else if(a.length<6){
alert("characters should be minimum 6") ;
}
}
asign('submit').addEventListener('click',validate(f_name),false) ;
validate function invoke in page refresh and after click the button nothing happen validate function nothing happen
You need pass reference to function as a argument in addEventListener but not call it,
1.you can wrap your code to function like this
asign('submit').addEventListener('click', function () {
validate();
}, false);
2.or use .bind
asign('submit').addEventListener('click', validate.bind({}), false);
Example
var asign = function(id) {
return document.getElementById(id);
};
var validate = function () {
var a = asign('fname').value;
if (!a) {
alert("Somthing is require");
} else if (a.length < 6) {
alert("characters should be minimum 6");
}
}
asign('submit').addEventListener('click', validate.bind({}), false);
<input id="fname">
<button id="submit">submit</button>
I have running script which moves the tr elements from one container to another on double click. But i have below mentioned issues:
1) If we do are very quick double-click on elements than it moves but its values doesn't come, it shows empty tags.
2) I want to change the background color on double click and it color should remove when we click outside or another elements.
<script>
$(function () {
function initTabelMgmt() {
selectInvitees();
moveSelectedInvitees();
deleteInvitees();
//scrollOpen();
}
var tmContainer = $("div.cv-tm-body");
var toggleAssignBtn = tmContainer.find('.cv-move-items button');
/*
function scrollOpen() {
var position = $('div.cv-item li.open').first().position();
var offsetTop = $('div.cv-tm-col-r .cv-helper-grid-overflow').scrollTop();
var unitHeight = $('div.cv-item li.open').first().height();
var containerHeight = $('div.cv-tm-col-r .cv-helper-grid-overflow').height();
var scrollAmount = offsetTop + position.top;
if ((offsetTop - position.top) <= 0 && (offsetTop - position.top) >= (-containerHeight + unitHeight)) {
//do nothing
} else {
$('div.cv-tm-col-r .cv-helper-grid-overflow').animate({
scrollTop: scrollAmount
});
}
};
*/
// scrollOpen end
function selectInvitees() {
//select items from invitee list
var startIndex, endIndex;
var dbclick = false;
tmContainer.find("table.cv-invitees").on('click', 'tr', function (e) {
var row = $(this);
setTimeout(function () {
//singleclick functionality start.
if (dbclick == false) {
if (!row.is('.assigned')) {
toggleAssignBtn.removeClass('is-disabled');
if (e.shiftKey) {
row.parents('.cv-invitees').find('tr').removeClass('selected');
endIndex = row.parents('.cv-invitees').find('tr').index(this);
var range = row.closest('table').find('tr').slice(Math.min(startIndex, endIndex), Math.max(startIndex, endIndex) + 1).not('.assigned');
range.addClass('selected');
} else if (e.ctrlKey) {
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.toggleClass('selected');
} else {
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.parents('.cv-invitees').find('tr').not(this).removeClass('selected');
row.toggleClass('selected');
}
}
}
}, 200)
})
.dblclick(function () {
dbclick = true
//doubleclick functionality start.
toggleAssignBtn.addClass('is-disabled');
function moveSelectedInviteesDBClick() {
var row = tmContainer.find("table.cv-invitees tr.selected");
if (!row.is('.assigned')) {
var allOpenSeat = $('.cv-item .open');
var numberOpen = allOpenSeat.length;
var name = row.find("td").eq(0).text();;
var company = row.find("td").eq(1).text();
var addedInvitees = [];
allOpenSeat.each(function (index) {
if (index < 1) {
var openSeat = $(this);
openSeat.find('.name').text(name);
if (company != '') {
openSeat.find('.company').addClass('show').text(company);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
openSeat.removeClass('open');
}
row.remove();
});
}
} // moveSelectedInviteesDBClick
moveSelectedInviteesDBClick();
setTimeout(function () {
dbclick = false
}, 300)
});
} // selectInvitees end
function moveSelectedInvitees() {
//move invitees from left to right
tmContainer.find('button.cvf-moveright').click(function () {
var selectedItem = $('.cv-invitees .selected');
var allOpenSeat = $('.cv-item .open');
var numberSelected = selectedItem.length;
var numberOpen = allOpenSeat.length;
var errorMsg = tmContainer.prev('.cv-alert-error');
if (numberSelected > numberOpen) {
errorMsg.removeClass('is-hidden');
} else {
var name;
var company;
var invitee = [];
var selectedInvitees = [];
var count = 0;
selectedItem.each(function () {
var $this = $(this);
name = $this.find("td").eq(0).text();
company = $this.find("td").eq(1).text();
invitee = [name, company];
selectedInvitees.push(invitee);
count = count + 1;
i = 0;
$this.remove();
});
var addedInvitees = [];
var items = $('div.cv-item li');
var seatItems = $('div.cv-order li');
allOpenSeat.each(function (index) {
if (index < count) {
var openSeat = $(this);
openSeat.find('.name').text(selectedInvitees[index][0]);
if (selectedInvitees[index][1] != '') {
openSeat.find('.company').addClass('show').text(selectedInvitees[index][1]);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
//selectedInvitees.shift();
openSeat.removeClass('open');
}
});
selectedInvitees = [];
}
toggleAssignBtn.addClass('is-disabled');
});
} // moveSelectedInvitees end
function deleteInvitees() {
//move invitees from left to right
tmContainer.find('div.cv-tm-col-r .cv-icon-remove').click(function () {
//delete seat assignment
var icon = $(this);
var idx = $('.ui-sortable li').index(icon.parent());
icon.parent().fadeTo(0, 0).addClass('open').find('.name').text('Open').end().fadeTo(750, 1);
icon.parent().find('.company').removeClass('show').text('');
// icon.parent().find('.entitystub').text('00000000-0000-0000-0000-000000000000');
// icon.parent().find('.entitytype').text('0');
// icon.parent().find('.pipe').remove();
// icon.hide();
// var testSeat = $('.seat-numbers li').get(idx);
//var seatStub = j$.trim(j$(testSeat).find('.seatstub').text());
//var input = { 'seatStub': seatStub };
//AssignSeats(input, "/Subscribers/WS/SeatAssignmentService.asmx/DeleteRegistrant");
});
}
initTabelMgmt();
}); // document.ready end
</script>
Your code looks pretty nice. You should also use in order to register from jQuery a single click event the native method .click(...). So please change the following line
tmContainer.find("table.cv-invitees").on('click', 'tr', function (e) {
To:
tmContainer.find("table.cv-invitees").click(function (e) {
and everything should work fine. For some strange reasons the function
$("#someelement").on("click", ...);
does not work always, only sometimes. JQuery officially recommends you to use the native functions for predefined events (such as onclick, onkeyup, onchange etc.) because of this strange behavior.
Edit:
If dblick does not work now, then make 2 lines please, like this:
tmContainer.find("table.cv-invitees").click(function (e) {
// [...]
;
tmContainer.find("table.cv-invitees").dbclick(function (e) {
// [...]
Edit2:
If it does not work, too, then please remove the single click event listener when you are in the .click() closure. Because if this happens, jQuery´s behavior is to treat it always as a single click. So, in other words dblick() will never be triggered, because .click() will always happens before. And then jQuery won´t count up to 2 fast clicks. Expect the unexpected^^
Edit3: This is the full code, which should hopefully work now as it is:
$(function ()
{
function initTabelMgmt()
{
selectInvitees();
moveSelectedInvitees();
deleteInvitees();
//scrollOpen();
}
var tmContainer = $("div.cv-tm-body");
var toggleAssignBtn = tmContainer.find('.cv-move-items button');
var iClickCounter = 0;
var dtFirstClick, dtSecondClick;
/*
function scrollOpen() {
var position = $('div.cv-item li.open').first().position();
var offsetTop = $('div.cv-tm-col-r .cv-helper-grid-overflow').scrollTop();
var unitHeight = $('div.cv-item li.open').first().height();
var containerHeight = $('div.cv-tm-col-r .cv-helper-grid-overflow').height();
var scrollAmount = offsetTop + position.top;
if ((offsetTop - position.top) <= 0 && (offsetTop - position.top) >= (-containerHeight + unitHeight)) {
//do nothing
} else {
$('div.cv-tm-col-r .cv-helper-grid-overflow').animate({
scrollTop: scrollAmount
});
}
};
*/
// scrollOpen end
function selectInvitees()
{
//select items from invitee list
var startIndex, endIndex;
var dbclick = false;
tmContainer.find("table.cv-invitees").click(function(e)
{
iClickCounter++;
if (iClickCounter === 1)
{
dtFirstClick = new Date();
var row = $(this);
window.setTimeout(function ()
{
//singleclick functionality start.
if (dbclick == false)
{
if (!row.is('.assigned'))
{
toggleAssignBtn.removeClass('is-disabled');
if (e.shiftKey)
{
row.parents('.cv-invitees').find('tr').removeClass('selected');
endIndex = row.parents('.cv-invitees').find('tr').index(this);
var range = row.closest('table').find('tr').slice(Math.min(startIndex, endIndex), Math.max(startIndex, endIndex) + 1).not('.assigned');
range.addClass('selected');
}
else if (e.ctrlKey)
{
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.toggleClass('selected');
}
else
{
startIndex = row.parents('.cv-invitees').find('tr').index(this);
row.parents('.cv-invitees').find('tr').not(this).removeClass('selected');
row.toggleClass('selected');
}
}
}
},
200);
}
else if (iClickCounter === 2)
{
dtSecondClick = new Date();
}
else if (iClickCounter === 3)
{
if (dtSecondClick.getTime() - dtFirstClick.getTime() < 1000)
{
return;
}
iClickCounter = 0;
dbclick = true
//doubleclick functionality start.
toggleAssignBtn.addClass('is-disabled');
function moveSelectedInviteesDBClick()
{
var row = tmContainer.find("table.cv-invitees tr.selected");
if (!row.is('.assigned'))
{
var allOpenSeat = $('.cv-item .open');
var numberOpen = allOpenSeat.length;
var name = row.find("td").eq(0).text();;
var company = row.find("td").eq(1).text();
var addedInvitees = [];
allOpenSeat.each(function (index)
{
if (index < 1)
{
var openSeat = $(this);
openSeat.find('.name').text(name);
if (company != '') {
openSeat.find('.company').addClass('show').text(company);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
openSeat.removeClass('open');
}
row.remove();
}
);
}
}
// moveSelectedInviteesDBClick
moveSelectedInviteesDBClick();
window.setTimeout(function ()
{
dbclick = false
}, 300);
}
}
);
} // selectInvitees end
function moveSelectedInvitees()
{
//move invitees from left to right
tmContainer.find('button.cvf-moveright').click(function ()
{
var selectedItem = $('.cv-invitees .selected');
var allOpenSeat = $('.cv-item .open');
var numberSelected = selectedItem.length;
var numberOpen = allOpenSeat.length;
var errorMsg = tmContainer.prev('.cv-alert-error');
if (numberSelected > numberOpen) {
errorMsg.removeClass('is-hidden');
}
else
{
var name;
var company;
var invitee = [];
var selectedInvitees = [];
var count = 0;
selectedItem.each(function () {
var $this = $(this);
name = $this.find("td").eq(0).text();
company = $this.find("td").eq(1).text();
invitee = [name, company];
selectedInvitees.push(invitee);
count = count + 1;
i = 0;
$this.remove();
});
var addedInvitees = [];
var items = $('div.cv-item li');
var seatItems = $('div.cv-order li');
allOpenSeat.each(function (index)
{
if (index < count)
{
var openSeat = $(this);
openSeat.find('.name').text(selectedInvitees[index][0]);
if (selectedInvitees[index][1] != '')
{
openSeat.find('.company').addClass('show').text(selectedInvitees[index][1]);
}
var seatAssignment = new Object();
seatAssignment.company = "";
addedInvitees.push(seatAssignment);
//selectedInvitees.shift();
openSeat.removeClass('open');
}
}
);
selectedInvitees = [];
}
toggleAssignBtn.addClass('is-disabled');
}
);
} // moveSelectedInvitees end
function deleteInvitees()
{
//move invitees from left to right
tmContainer.find('div.cv-tm-col-r .cv-icon-remove').click(function ()
{
//delete seat assignment
var icon = $(this);
var idx = $('.ui-sortable li').index(icon.parent());
icon.parent().fadeTo(0, 0).addClass('open').find('.name').text('Open').end().fadeTo(750, 1);
icon.parent().find('.company').removeClass('show').text('');
// icon.parent().find('.entitystub').text('00000000-0000-0000-0000-000000000000');
// icon.parent().find('.entitytype').text('0');
// icon.parent().find('.pipe').remove();
// icon.hide();
// var testSeat = $('.seat-numbers li').get(idx);
//var seatStub = j$.trim(j$(testSeat).find('.seatstub').text());
//var input = { 'seatStub': seatStub };
//AssignSeats(input, "/Subscribers/WS/SeatAssignmentService.asmx/DeleteRegistrant");
}
);
}
initTabelMgmt();
}
); // document.ready end
I guess that you interpret in your special case a double click as 3 times clicked at the same table entry. And if a user do so and if the time difference between first and second click is longer than one second, a double click will be fired. I think should be the solution to deal with this special case.
Edit 4: Please test, if it is possible to click on 3 different table column and get also double click fired. I think this is an disadvantage on how my code handles the double click. So, you need to know from which table column you have already 1 to 3 clicks set. How can we do this? Basically, there are 3 possibilities to do this:
(HTML5 only:) Make data attribute on each tr and the value for this data attribute
should be the clicks already clicke on this tr.
Define a global object key/value pair object, which holds the
event-ID (but I don´t know how to get this back by jQuery driven
events) as the key and the amount of clicks already done as the
value. And then if you are on the next click, you can decide what is
to do now for this tr. This is my favorite alternative!
Last but not least: Only register the click event on every tr and
make for each click-registering an own global area, so that we just
avoid the actual problem. You can do this e. g. by making an JS
Object which hold a member variable as the iclickCounter and you
make a new object of this class, each time a new click event is
registered. But this alternative need a lot more code and is main-memory-hungry.
All of thes possible options need a wrap around your click event, e. g. a loop, that iterates over all tr elements in the given table. You did this already partially by calling the jQuery-function .find(..). This executes the closure on every found html element. So, in your case on all tr elements in the searched table. But what you need to do is to make the workaround of one of my options given above.
i am trying to bind an event to a dynamically created div.
function GameField(playerNumber) {
this.fields = new Array();
this.player = playerNumber;
this.isPlayerActive = false;
this.currentRound = 0;
}
GameField.prototype.InitField = function(fieldNumber) {
var newField = document.createElement("div");
if (fieldNumber == 0 || fieldNumber == 6 || fieldNumber == 8 || fieldNumber == 17)
newField.className = 'gameCellSmall borderFull gameText gameTextAlign';
else
newField.className = 'gameCellSmall borderWithoutTop gameText gameTextAlign';
newField.onclick = function() { this.DivClick('a'); }
this.fields[fieldNumber] = newField;
return newField;
}
GameField.prototype.DivClick = function(fieldNumber) {
alert('Nummer: ' + fieldNumber);
}
Everything works perfectly, but when you click on one of the created divs, i end up with the following error message: Error: Object doesn't support this property or method.
If i replace the onclick function with this, then it works:
newField.onclick = function() { alert('Nummer: ' + fieldNumber); }
How can i get the onclick event to fire my DivClick function instead?
The problem is that the onclick event handler gets executed with the this value pointing to the DOM element that triggered the event, so that's why executing this.DivClick fails.
You need to enforce the context, in order to use instance methods within the event handler, for example, you could store a reference to the current instance:
GameField.prototype.InitField = function(fieldNumber) {
var newField = document.createElement("div");
//...
var instance = this;
newField.onclick = function() { instance.DivClick('a'); }
//...
}
That is the way
function DivClick (fieldNumber) {
alert('Nummer: ' + fieldNumber);
}
{ this.DivClick('a'); } - should be replaced to { DivClick('a'); }