Why Doesn't Javascript DOM 2 "Click" Event Work - javascript-events

My question is, Why doesn't the click event work when other events do work using the same code? Consider the following code examples from http://www.pricelearman.com/__dev (2 underscores)
For Square 2 using "click" event
function showWorkPane() {
var _workID = document.getElementById("workID");
_workID.addEventListener("click", showWorkPaneHandler, false);
}
function showWorkPaneHandler(e) {
var _workPane = document.getElementById("workPane");
e.preventDefault();
_workPane.style.display = "block";
}
Clicking on the link "Work" does not show the workPane.
For Square 3 using "mouseover" event
function showAboutPane() {
var aboutID = document.getElementById("aboutID");
aboutID.addEventListener("mouseover", showAboutPaneHandler, false);
}
function showAboutPaneHandler(e) {
e.preventDefault();
var v = document.getElementById("aboutPane");
v.style.display = "block";
}
Rolling-Over the link "ABOUT" shows the aboutPane hover effect as expected
For Square 4 using "mousedown" event
function showConnectPane() {
var connectID = document.getElementById("connectID");
connectID.addEventListener("mousedown", showConnectPaneHandler, false);
}
function showConnectPaneHandler(e) {
e.preventDefault();
var v = document.getElementById("connectPane");
v.style.display = "block";
}
Holding mouse down on the link "CONNECT" shows the connectPane as expected
What am I missing about the click event. It's counterintuitive to me that it would not follow the same pattern as the other mouse events.
I'm trying to preclude interference from the link's default action by using e.preventDefault();
I know a click event is a sequence of simple events: mousedown,mouseup,click.
Is there something blocking this sequence?
The full code can be reviewed at http://www.pricelearman.com/__dev (2 underscores). The code may not be optimum, but it is functionally correct – binding is accomplished and functions are called, etc – else the above code would not be working at all.
Thanks for your time and expertise. This is a vexing question to me. It seems so fundamental and simple. I'm new to javascript and I must be missing something.

For Square 2 using "click" event
function showWorkPane() {
var _workID = document.getElementById("workID");
_workID.addEventListener("click", showWorkPaneHandler, false);
}
function showWorkPaneHandler(e) {
var _workPane = document.getElementById("workPane");
e.preventDefault();
_workPane.style.display = "block";
}
Clicking on the link "Work" does not show the workPane.
Well what I currently can find at http://www.pricelearman.com/__dev/_js/main.js is
// Show work navigation
function showWorkPane() {
var workID = document.getElementById("workID");
workID.addEventListener("mouseover", showWorkPaneHandler, false);
// ^^^^^^^^^
}
function showWorkPaneHandler(e) {
e.preventDefault();
var v = document.getElementById("workPane");
v.style.display = "block";
}
Looks quite obvious to me why click events show no effect. There are none bound.

Related

Kendo scheduler month View double click function

I disabled the built-in pop up event. Now I want to implement a double click function on each cell of the month view.
Does anyone know how to do it?
You can add an event handler to the add event of the scheduler in the scheduler options like this:
add: (e) => {
// Place your code here.
e.preventDefault();
}
or in case you would rather not use arrow function:
add: function(e) {
// Place your code here.
e.preventDefault();
}
Calling e.preventDefault() will disable the built-in "add" event handling which is showing the popup window. You mentioned you already disabled it but this is a good way to do it if you did it in another way.
e will contain the slot's start and end time as well as the resource details, if you use resources.
You may want to associate the event with k-event class of an scheduler.
$("#scheduler").on("dblclick", '.k-event', function (e) {
var scheduler = $("#scheduler").getKendoScheduler();
var element = $(e.target).is(".k-event") ? $(e.target) : $(e.target).closest(".k-event");
var event = scheduler.occurrenceByUid(element.data("uid"));
alert("Start Date : " + event.start + ", End Date: " + event.end);
});
Demo Link
Try this it worked for me.
edit: function (e) {
e.preventDefault(); //prevent popup editing
var dataSource = this.dataSource;
var event = e.event;
if (event.isNew()) {
setTimeout(function () {
//dataSource.add(event);
editEvent(event); // your own function to call
});
}
else {
}
}

Firefox Bootstrapped Add-On Injecting before load

Is it possible to add event listeners for a document before a page has been navigated to using a Bootstrapped add-on? I would like to see what page the user wants to navigate to as well as later after the page loads to inspect the DOM. I need to run code in the HTML content context.
In the past I used a toolbar XUL and included javascript within it and it would load before the HTML page loaded.
i looked into doing stuff before DOMContentLoaded sometime ago and found out there is a document inserted observer.
order of events after running research code at bottom
readystate changes to interactive (i think multiple times, not sure)
readystate changes to complete
DOMContentLoaded event fires
load event fires (Sometimes load doesnt fire, if you might have to change addEventListener with capture arugment (3rd argument) as false or true)
apparently there should be readystate loading before all of this but i can never catch it i dont know why.
after running the code in scratchpad, browser environemnt of course, then load a new page and watch the error console it will throw these reports in this order:
ready state changed! ("interactive") Scratchpad/4:18
02:28:07.873 ready state changed! ("complete") Scratchpad/4:18
02:28:07.874 DOMContentLoaded event fired! Scratchpad/4:53
02:28:07.938 Load event fired! Scratchpad/4:45
here is the research code. it adds a the listeners and observer to see whats firing.
var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
var os = Cc['#mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
var LMObserver;
function myObserver() {
this.register();
}
myObserver.prototype = {
observe: function (subject, topic, data) {
//Cu.reportError(subject);
//Cu.reportError(data);
//i think subject is window element
subject.onreadystatechange = function () {
//loading
//interactive
//complete
Cu.reportError('ready state changed! ("' + subject.readyState + '")');
//var body = subject.documentElement.querySelector('body')
//you want to change title so you would do that here do something like: if (subject.readystate == 'complete') { subject.title = 'blah blah' }
//Cu.reportError('has body element: ' + body)
}
},
register: function () {
os.addObserver(this, 'document-element-inserted', false);
},
unregister: function () {
os.removeObserver(this, 'document-element-inserted', false);
}
};
//below this is the DOMContentLoaded thing i put this here so we can see what fires in what order
var pageLoad = function(event) {
var win = event.originalTarget.defaultView;
if (win && win.frameElement) {
return;
}
Cu.reportError('Load event fired!');
}
var pageDOMContentLoaded = function(event) {
var win = event.originalTarget.defaultView;
if (win && win.frameElement) {
return;
}
Cu.reportError('DOMContentLoaded event fired!');
}
LMObserver = new myObserver;
gBrowser.addEventListener("load", pageLoad, true);
gBrowser.addEventListener("DOMContentLoaded", pageDOMContentLoaded, true);
//gBrowser.removeEventListener("load", pageLoad, true);
//gBrowser.removeEventListener("DOMContentLoaded", pageDOMContentLoaded, true);
//LMObserver.unregister();
Here's some more indepth research on load events added with true or false as capture argument: https://github.com/Noitidart/event-listener-experiment-DOMC-and-load/blob/master/bootstrap.js

Prototype.js event observe click intercept and stop propagation

I have a page that is built around a wrapper with some very defined logic. There is a Save button on the bottom of the wrapped form that looks like this:
<form>
... my page goes here...
<input id="submitBtnSaveId" type="button" onclick="submitPage('save', 'auto', event)" value="Save">
</form>
This cannot change...
Now, I'm writing some javascript into the page that gets loaded in "...my page goes here...". The code loads great and runs as expected. It does some work around the form elements and I've even injected some on-page validation. This is where I'm stuck. I'm trying to "intercept" the onclick and stop the page from calling "submitPage()" if the validation fails. I'm using prototype.js, so I've tried all variations and combinations like this:
document.observe("dom:loaded", function() {
Element.observe('submitBtnSaveId', 'click', function (e) {
console.log('Noticed a submit taking place... please make it stop!');
//validateForm(e);
Event.stop(e);
e.stopPropagation();
e.cancelBubble = true;
console.log(e);
alert('Stop the default submit!');
return false;
}, false);
});
Nothing stops the "submitPage()" from being called! The observe actually works and triggers the console message and shows the alert for a second. Then the "submitPage()" kicks in and everything goes bye-bye. I've removed the onclick attached to the button in Firebug, and my validation and alert all work as intended, so it leads me to think that the propagation isn't really being stopped for the onclick?
What am I missing?
So based on the fact that you can't change the HTML - here's an idea.
leave your current javascript as is to catch the click event - but add this to the dom:loaded event
$('submitBtnSaveId').writeAttribute('onclick',null);
this will remove the onclick attribute so hopefully the event wont be called
so your javascript will look like this
document.observe("dom:loaded", function() {
$('submitBtnSaveId').writeAttribute('onclick',null);
Element.observe('submitBtnSaveId', 'click', function (e) {
console.log('Noticed a submit taking place... please make it stop!');
//validateForm(e);
Event.stop(e);
e.stopPropagation();
e.cancelBubble = true;
console.log(e);
alert('Stop the default submit!');
return false;
submitPage('save', 'auto', e);
//run submitPage() if all is good
}, false);
});
I took the idea presented by Geek Num 88 and extended it to fully meet my need. I didn't know about the ability to overwrite the attribute, which was great! The problem continued to be that I needed to run submitPage() if all is good, and that method's parameters and call could be different per page. That ended up being trickier than just a simple call on success. Here's my final code:
document.observe("dom:loaded", function() {
var allButtons = $$('input[type=button]');
allButtons.each(function (oneButton) {
if (oneButton.value === 'Save') {
var originalSubmit = oneButton.readAttribute('onclick');
var originalMethod = getMethodName(originalSubmit);
var originalParameters = getMethodParameters(originalSubmit);
oneButton.writeAttribute('onclick', null);
Element.observe(oneButton, 'click', function (e) {
if (validateForm(e)) {
return window[originalMethod].apply(this, originalParameters || []);
}
}, false);
}
});
});
function getMethodName(theMethod) {
return theMethod.substring(0, theMethod.indexOf('('))
}
function getMethodParameters(theMethod) {
var parameterCommaDelimited = theMethod.substring(theMethod.indexOf('(') + 1, theMethod.indexOf(')'));
var parameterArray = parameterCommaDelimited.split(",");
var finalParamArray = [];
parameterArray.forEach(function(oneParam) {
finalParamArray.push(oneParam.trim().replace("'","", 'g'));
});
return finalParamArray;
}

jqgrid setting page of grid

When a user selects a cell, I have the following code which goes to a window.location
beforeSelectRow: function (rowid, e) {
var $td = $(e.target).closest("td"),
iCol = $.jgrid.getCellIndex($td[0]);
if (this.p.colModel[iCol].name === 'FlSaved') {
var pagenum = $('#reportList').getGridParam('page');
var rownum = 200;
alert(pagenum);
alert(rownum);
window.location = "/Plt/FileUpload/" + '?id=' + encodeURIComponent(rowid) + '&pagenum=' + pagenum;
}
Note how I am passing the pagenum. The reason why I am passing the page number is because when the user finishes with what they need
to do at window.location, I need the user to go back to the grid page that they were at.
To do this, I am doing the loadComplete where I set the value of the page but does not seem to be working.
loadComplete: function (data) {
if ('#TempData["pageNum"]') {
$("#rpList").trigger("reloadGrid",[{page:pagenum}]);
}
Where is the best place of do the trigger reloadGrid at?
It's unclear for me when '#TempData["pageNum"]' will be set, when it will be cleared and whether the code will be hold in the cache of the web browser. If we forget about the questions I have one important remark to your code: if you use .trigger("reloadGrid", ...) inside of loadComplete you should place the call of trigger inside of setTimeout. It will allows to process till the end the current loadiong of the grid before starting the next loading initialized by .trigger("reloadGrid", ...). So the code could be about the following:
loadComplete: function (data) {
...
if (/*some condition*/) {
setTimeout(function () {
$(this).trigger("reloadGrid",[{page: pagenum}]);
}, 50);
}
...
}
Event the usage of 0 instead of 50 is not the same as the usage of .trigger("reloadGrid",...) without setTimeout.

In jQuery, how can I create a custom event with a default?

The Event object in jQuery has this helpful preventDefault() method that prevents the default behaviour, obviously.
This is usually used to prevent click events from performing the browser default behaviour.
It seems like it would also be useful for custom events as well.
The task I'd like to achieve with this behaviour is a separate concern but I will explain it as an example for the behaviour I'm looking for:
I have a simple plugin that creates a popup out of a div. I found it on the internet.
$(selector).pop();
I have hacked it to close when you click on anything but a child of the popup, and to prevent default click behaviour on the clicked element.
function closeInactivePop() {
var foundAny = false;
jQ.each(function (i) {
var $this = $(this);
if ($this.hasClass('active') && ! $this.data('activePop')) {
$this.removeClass('active');
foundAny = true;
}
});
return foundAny;
}
$('body').click(function(){
// If we closed any, cancel the propagation. Otherwise let it be.
if (closeInactivePop()) {
$(document).trigger('jQuery.pop.menuClosed');
return false;
}
});
(Now that I paste it I realise I could have done this a bit better, but that notwithstanding).
Now I have added a new plugin that draws a colour picker inside the popup. Except the DOM that this colour picker creates is not inside the popup; it is only inside it visually. The DOM structure is separate.
In the aforementioned hack I would prefer to in fact fire another event, one whose default behaviour is to close the popup.
function closeInactivePop() {
var foundAny = false;
jQ.each(function (i) {
var $this = $(this);
if ($this.hasClass('active') && ! $this.data('activePop')) {
$(document).trigger('jQuery.pop.menuClosed');
$this.removeClass('active');
foundAny = true;
}
});
return foundAny;
}
$('*').click(function(e) {
var $this = $(this);
// This bit is pseudocode, where the Function is the default behaviour
// for this event.
// It is helpful that $this is actually the clicked element and not the body.
$this.trigger('jQuery.pop.menuBeforeClose', function() {
// if we run default behaviour, try to close the popup, or re-trigger the click.
if (!closeInactivePop()) {
$this.trigger(e);
}
});
});
Then I could later do
$('#colour-picker').bind('jQuery.pop.menuBeforeClose', function(e) {
e.preventDefault();
});
And this would prevent the closeInactivePopup default behaviour running when the target of the original click event was the colour picker or something inside it.
Can I do this somehow, even hackily?
I doubt that there is a native way to do that. However, you can either use "triggerHandler()" instead of "trigger()", which provides the ability to return values from the event handlers. Another relatively simple solution is to pass a custom "event" object that can be used to cancel the planned action:
function Action() {
var status = true;
this.cancel = function() { status = false; };
this.status = function() { return status; };
}
$('button').click(function() {
var action = new Action();
$(this).trigger('foo', [action]);
if (action.status()) {
// ... perform default action
}
});​
In the event handler:
$('*').bind('foo', function(event, action) {
action.cancel();
});

Resources