I have a complicated DOM structure with divs, uls, li, and span elements.
On this elements can be a jquery click event which do some logic.
If the application goes offline I have to disable the click events on this elements.
It is possible to add a generic click event which executes first, where I can check that the application is offline and if it's than stop the propagation?
I can have click events on each part of the dom structure.
(Refactoring the DOM is not an option.)
EDIT:
<div>
<div>
<ul>
<li>
<div>
<span>
</span>
</div>
</li>
<li>
</li>
<ul>
</div>
I found event listeners on the spans and on the LI-s too.
Maybe you can solve this with an simpler approach if you're able to categorize which elements can't have interaction while offline.
For example, let's say that all controls that are disabled in offline mode have a class called .requires-connection attached to it, like:
<li id="save-stuff" class="requires-connection">
<i class="icon-save"></i><span>Save Changes</span>
</li>
If you add an .offline-mode class to your <body> when you detect that no connection to your server is available, you can globally disable the interaction in the relevant UI controls (and in it's children as well) with:
body.offline-mode .requires-connection {
pointer-events:none !important;
opacity:0.7 !important;
}
Alternative Solution
If the above won't work in your context, you might just need to be aware of how those events are fired. How they bubble up and, for handlers in the same element, that jQuery fires then in the order that they're registered.
After being aware of that, you can just create a custom event handling workflow by creating custom events that might do your checks to preventDefault and/or stopPropagation when needed.
If you don't have much control on the order that the event handlers are registered you can use some techniques from this post;
I think you'd be better not allowing the use of an input control, than allowing and then trying to control the event propagation.
If you asked for my suggestion, I would say disable buttons that are not applicable when user is offline and re-enable them when user is back online.
For example you may group certain controls that should work while online as follows:
<fieldset id="online-applicable-controls">
<button>a button [applicable when online]</button>
<button>another button [applicable when online]</button>
<!-- more buttons probably -->
</fieldset>
And the script to enable/disable the above group of buttons as applicable will be:
var onlineApplicableControls = document.getElementById("online-applicable-controls");
document.addEventListener("online", enableOnlineControls);
document.addEventListener("offline", disableOnlineControls);
function disableOnlineControls() {
onlineApplicableControls.disabled = true;
}
function enableOnlineControls() {
onlineApplicableControls.disabled = false;
}
Note, since the above script accesses a DOM element, you should execute it on DOMContentLoaded. Using JQuery, that translates to $(document).ready(function(){ /* place the script here */ });
Related
i have a link with ui-sref attribute and also a jQuery touch event, but the problem is that when i click on this element the jQuery handler is running but the ui-sref not.
Jquery:
$('#fa-bar, #mobile-nav li').on('touchstart', function( e ) {
e.stopPropagation();
$('#mobile-nav').toggleClass('toggle-mobile-nav');
$('#mobile-nav').toggleClass('prevent-scroll');
});
Html:
<li ui-sref="state" ui-sref-active="nav-active"><a>Link</a></li>
See the docs and this example:
However, stopEvent also calls an event object method, event.stopPropagation, which keeps the event from bubbling any further up into the DOM. Note that the table itself has an onclick event handler that ought to display a message when the table is clicked. But the stopEvent method has stopped propagation, and so after the data in the table is updated, the event phase is effectively ended, and an alert box is displayed to confirm this.
This is pure javascript and also applies for AngularJS. Your call to e.stopPropagation() prevents ui-router from getting the event. This is sometimes handy if you want to add an URL to something (so you can still use open-in-new-tab feature of your browser), but want a different behavior on normal clicks.
Use latest or atleast 0.3.2 for ui-router
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.2/angular-ui-router.min.js"></script>
I'm using the Knockout webmail tutorial as a template for a Single Page Application I'm working on.
However I'm having trouble implementing the click binder, I've had this sort of thing working before but his time the click events are being hijacked.
My view model has a function:
var self = this;
self.goToItem = function(item) { location.hash = "#/Item/" + item.id };
which is standard.
<h2>Saved Items</h2>
<div data-bind="foreach: savedItems">
<div data-bind="click: $root.goToItem">
<p data-bind="text: name"></p>
</div>
</div>
I've tried the:
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>
but, tellingly, this came back empty although the foreach has data to loop over.
The problem now is that the mousevent click is now caught by jQuery, I haven't had to delve into this before, but I am sure knockout runs without jQuery. At the moment the only jQuery I use is for the Ajax calls.
So where do I go to inspect the events on DOM objects, preferably in Chrome?
How can jQuery butt in?
Have you tried to use clickBubble binding?
Preventing the event from bubbling
By default, Knockout will allow the click event to continue to bubble up to any higher level event handlers. For example, if your element and a parent of that element are both handling the click event, then the click handler for both elements will be triggered. If necessary, you can prevent the event from bubbling by including an additional binding that is named clickBubble and passing false to it, as in this example:
<div data-bind="click: myDivHandler">
<button data-bind="click: myButtonHandler, clickBubble: false">
Click me
</button>
</div>
Normally, in this case myButtonHandler would be called first, then the click event would bubble up to myDivHandler. However, the clickBubble binding that we added with a value of false prevents the event from making it past myButtonHandler.
More details about click binding is here http://knockoutjs.com/documentation/click-binding.html
If I replaced
click: $root.goToItem
with
click: goToItem
it works again.
It seems the jQuery event firing was a red herring, I compared it to a working system and it started off in jQuery. I had to brush up on my DOM debugging, which is no bad thing.
Is the $root superflous, it took someone else to point this out to me. I was sure that in a foreach loop you could only access the $root functions via $root.
I found that prototype.js library provides Event handling mechanism, but I can't figure out what's wrong with the following code snippet:
<div>
<div id="foo">Bla-bla</div>
</div>
<script type="text/javascript">
function onFooKeyup(e)
{
var element = e.element();
if (e.keyCode == Event.KEY_ESC)
element.innerHTML="TEST";
}
//document.observe('keydown', onFooKeyup);
$('foo').observe('keydown', onFooKeyup);
</script>
Basically I want to change content (or do styling, etc.) of certain div block when user press escape button. The problem is that observing the foo id doesn't lead to any action, while observing the document (commented line) indeed trigger the change. If I replace my foo div block with input tag, e.g.
<div><input type="text" id="foo" /></div>
then the events will be triggered correctly. Is it a bug?
This is because the event has not originated inside the <div> element, so you can't observe it (listen to it) there. In the case of the <div> block with an <input> tag, the event is actually originated inside that element (if the input has user focus, I think, but it's not relevant here). So no, it's not a bug.
Just catch the keyboard event at document level, because the key events will originate on different elements (different browsers manage this on different ways) but they will all bubble up to the document (unless you stop the event's propagation).
Man, I think the only error is because you are saying to jQuery to look for a tag named 'foo', and then bind the 'keypress' event to it. If you want it to search for your id 'foo' you should do the following
$('#foo').observe ....
I am using Javascript to make some changes to how a page displays depending on what the user inputs in the form. This works fine and dandy, except for on one element. That is because this element is changing via ajax depending on what the user selects earlier in the form.
I am using document.observe('dom:loaded', function() { to run my JS code, so obviously this one elements JS isnt working because the elements are added in after the dom loaded. What's the best way to run JS on this page element after they are loaded in?
Thanks!
You can handle events on the parent element, then when the event triggers you use the target property of the event object to find out in which child element the event was fired, for instance if you wanted to know when a button added dynamically was clicked you could do:
document.getElementById("parent").click = function(event){
if(event.target.id=="myButton"){
//handle click
}
}
<div id="parent">
<input type="button" id="myButton" /> <!-- added dinamycally -->
</div>
This is making use of Event bubbling
Assume I get a table element with ID="emTab", how do I call JS to click it?
Thanks.
document.getElementById("emTab").onclick = function() {
// your code goes here
};
See element.onclick
To trigger click event
document.getElementById("emTab").click();
See element.click
The click method is intended to be
used with INPUT elements of type
button, checkbox, radio, reset or
submit. Gecko does not implement the
click method on other elements that
might be expected to respond to
mouse–clicks such as links (A
elements), nor will it necessarily
fire the click event of other
elements.
Non–Gecko DOMs may behave differently.
When a click is used with elements
that support it (e.g. one of the INPUT
types listed above), it also fires the
element's click event which will
bubble up to elements higher up the
document tree (or event chain) and
fire their click events too. However,
bubbling of a click event will not
cause an A element to initiate
navigation as if a real mouse-click
had been received.
Cross browser way
If you can use jQuery then it would be
$("#emTab").trigger("click");
Firing events cross-browser - http://jehiah.cz/archive/firing-javascript-events-properly
its simple using JQuery
$('#emTab').click(functionToCall);
while in JS
document.getElementById('emTab').onclick = function() {};
for details on DOM events:
http://www.howtocreate.co.uk/tutorials/javascript/domevents