SAPUI5: How to bind a click event to horizontal layout? - javascript

Hi I'm developing my view in JS and I'm stuck in binding a click handler for my horizontal layout element. I've tried using Jquery
$("#myHorizontalLayout").bind("click",function(){window.alert()});
Which didn't work then I tried using attachPress with the element which obviously didn't exist. Please help.
Update:
The JS view is the default view of the application.

When on/bind does not work, it could be that the HTML of the control has actually not been created yet at this point in time. But even if you delay the binding, the re-rendering (re-creation of the HTML after changes) would remove your listener, at least when bound on the control itself.
A proper way of doing this is using the generic attachBrowserEvent function available on every control (here: on the layout) which internally handles all the rendering/rerendering stuff, see this example:
http://jsbin.com/hijutunefi/1/edit?html,output
attachBrowserEvent works for any browser event, as it attaches a new browser event listener to the root node of the control. For the most common browser events UI5 does event delegation, so for the "click" event and several others addEventDelegate can also be used, as pointed out by aborjinik.
Alternatively, listening on the <body> level with normal jQuery mechanisms should in general also work.

Which didn't work then I tried using attachPress with the element which obviously didn't exist. Please help.
Does this means that the element on which you are attaching event handler doesn't exists at this point? If this is the case you can hook the handler to some container, upper in the DOM hierarchy which you are sure that exists and filter the click events.
Example:
$("body").on("click", "#myHorizontalLayout", function(){
alert("Hey, you!");
});

As of jQuery 1.7, the .on() method is the preferred method for
attaching event handlers to a document. For earlier versions, the
.bind() method is used for attaching an event handler directly to
elements. Handlers are attached to the currently selected elements in
the jQuery object, so those elements must exist at the point the call
to .bind() occurs.
Reference here
So try replacing bind with on and let me know if it works or not.

Related

AJAX/PHP can't update created DIV [duplicate]

How to attach all events after manipulating the dom using ajax response. I have a ajax request which get a html response which is basically a fragment of html. that fragment HTML have many buttons. I want to refresh the dom so previously declared and attached events be applied into that fragment too. I dont want to keep on adding each events for each button using jquery on(). how else to do it?
You can use delegated event handling which is set up ahead of time and can be made to apply to newly added DOM elements. Delegated event handling is done with .on() and generally takes the form of:
$("static parent selector").on('click', 'selector for dynamic element', fn);
There is no clean way to just run your event installing code again and have it only apply to newly added DOM elements. You would have to put that code in a function and code it such that it never adds an event handler more than once and then you could call that function again after adding items to the DOM. Or, you could make the function take an argument for a parent object and only add event handlers in the newly added DOM hierarchy.
Here's another relevant answer about delegated event handling: Does jQuery.on() work for elements that are added after the event handler is created?

Can't modify properties of element using jquery .on()

I'm currently trying to write what I feel like should be a very simple chrome addon using jquery. I have a tool I use for work that our IT department has stopped supporting Chrome with, because they have enough on their plate troubleshooting IE. Their solution however, was simply to remove the old onClick functions and added the property disabled="diabled" to all of our buttons.
My simple work around for this is using jquery to remove the disabled properly and append the onClick functionality. I've gotten this to work in a few instances, but the problem I'm running into is with new instances of buttons created using ajax forms.
Here's the code I'm currently trying to work with:
function restoreFunctionality() {
$("#RestoreDefaultsButton").removeProp("disabled").attr("onClick", "OnRestoreDeviceClientClick()");
}
RestoreFunctionality();
Now, this works fine for the initial load, however I'd also like this to work for every button that is to be created in the future. To do this, I added:
$("#RestoreDefaultsButton").on("restoreFunctionality", function(event) {
$("#RestoreDefaultsButton").removeProp("disabled").attr("onClick", "OnRestoreDeviceClientClick()");
});
This, however, does not work for me but also does not provide any sort of console error message telling me why it won't work. I can't seem to find an example of what I want. I see examples in the jquery doc where it can be called by clicking somewhere or something like that, however what I want is for it to just simply "work". Just look for new instances of that button ID and make the changes.
Is on() not the function I want to use in jquery 1.11.1? Am I somehow using this incorrectly? Any guidance to point me in the right direction would help.
Edit for clarification:
I am not trying to edit the same button multiple times in multiple locations. I am trying and willing to create code individually for each button that comes up, given I know the ID of each one.
Here is an example of something I have that is currently working:
The line of code for the button reads:
<input type="button" name="RestoreDefaultsButton" value="Submit"
id="RestoreDefaultsButton" disabled="disabled" class="aspNetDisabled InlineButtonStyle">
The code that I am using and that actually works just fine is now:
$("body").on("click", "#RestoreDefaultsButton", restoreDefaultFunctionality());
and restoreDefaultFunctionality() is simply:
$("#RestoreDefaultsButton").removeProp("disabled").attr("onClick", "OnRestoreDeviceClientClick()");
Again, the above code works just fine. What I seem to have trouble with is that not all of my buttons are present on load, I may click a link that loads a model on the same page/url with a form that has additional buttons. That button might read:
<input type="button" name="OpenToolkitButton" value="Submit" id="OpenToolkitButton" disabled="disabled" class="aspNetDisabled InlineButtonStyle">
Which is almost exactly the same as the original example, it's just been loaded after the script ran for the first time.
What I am looking for is a solution to make all individually specified buttons that I need, when they occur, to have that disabled removed and a specific onclick function added.
It appears that you have several things wrong and you are using .on() incorrectly.
First, ids in your document must be unique. You cannot have multiple DOM elements with the same id. That is both illegal HTML and will not correctly work with selectors. So, if you're trying to detect future "#RestoreDefaultsButton" objects in addition to the one you already have, you will have to change that because you can't have more than one and still have selector code work correctly. Usually, you want to use a class name instead of an id when you want to find multiple objects of the same type.
Second, your use of .on() is simply not correct. .on() allows you to register a callback function that will be called when a certain DOM event is triggered. So, when you do this:
$("#RestoreDefaultsButton").on("restoreFunctionality", fn);
You are asking for jQuery to call your function when the single "#RestoreDefaultsButton" object triggers the "restoreFunctionality" DOM event. Since "restoreFunctionality" is not a built-in DOM event, the only way that could ever trigger is if you triggered the event yourself.
The usual solution to modifying newly created objects that are inserted into the DOM is to go find the code that creates those objects and insert a function call (to call your own function that can find and "patch up" the newly created DOM objects right AFTER the newly created DOM objects have been created.
The newest browser versions allow you to register a callback to be notified when certain types of objects are added to the DOM so you could get notified automatically. These notifications are call MutationObservers (doc here). Unfortunately, those events are only implemented in the latest browsers (IE11) so you generally can't solely rely on them for a general web page.
Your click handler assignment could probably be solved with delegated event handling. In delegated event handling for dynamically created objects, you find a persistent object (that is not dynamically created) that will be in the parent chain of your dynamically created element and you bind the click event handler to that parent. Since click events "bubble" up the parent chain, the click event will be seen by the parent. Using the delegated form of .on() that works like this:
$("static parent selector").on("click", "dynamic element selector", fn);
You can then handle the event without worrying about the timing of when the dynamic element is created/destroyed, etc...
You can read more about delegated event handling in these references:
Does jQuery.on() work for elements that are added after the event handler is created?
jQuery .live() vs .on() method for adding a click event after loading dynamic html
jQuery .on does not work but .live does
Are you triggering the "restoreFunctionality" event after your ajax forms are built?
$("#RestoreDefaultsButton").trigger("restoreFunctionality");
Forces it to be synchronous if you have more to do after the call and before you finish the function
$("#RestoreDefaultsButton").triggerHandler("restoreFunctionality");

convert all jquery scripts to live scripts

I have lot of jquery scripts which dont handle elements loaded or created on the fly, of course I can convert all my scrits and add the them the .live() function. However was wondering if there is any option or trick that could automatically simulate the live function in all the scripts without modifying them one by one manually.
Thanks for the comments , live is depreciated, so I restate my question with the .on() function.
There is not one trick that will make all existing event handler code work with dynamically loaded elements without updating each event handler unless you want to replace some jQuery methods with methods that work differently than jQuery has documented (not recommended). You would have to replace all jQuery event handling methods that you are currently using with methods that forced delegated event handling into them. This would be a bad way to do this. Not only would you be hacking jQuery into something that would be different than it is documented and opening yourself up to compatibility issues with other code, but you'd be forced into the most inefficient use of delegated event handling (which is why .live() was removed in the first place). Do not do this. Fix your code to use the proper method of delegated event handling. It's not hard at all.
.live() has been deprecated and even removed from the latest versions of jQuery. You should not use it. There is a form of .on() that will allow you to use delegated event handling for dynamically loaded objects. You can see how to use the proper form of .on() for dynamically loaded elements in this post: jQuery .live() vs .on() method for adding a click event after loading dynamic html.
The "proper" way to use .on() for dynamic elements is like this:
$('#parent').on("click", "#child", function() {});
where you select the closest parent to the dynamic element that is not itself dynamically loaded and bind the event handler to that element.
.live() was removed because it put all delegated event handlers on the document object somewhat analogous to this:
$(document).on("click", "#child", function() {});
If, however, you used a number of delegated event handlers like this, performance could start to bog down. That's because when you do it this way and you click anywhere in the document and that click bubbles up to the document, it has to compare every single selector in every single .live() event handler you had to the current clicked object. Since selector comparisons are not always fast, this could really bog down the processing of events.
When you place the event handler on an object closer to the actual object, you end up with far event handlers there and thus far fewer selectors to compare to and processing of the events works faster.
Here's a reference on some differences between static event handlers and delegated event handlers and some useful notes on them: JQuery Event Handlers - What's the "Best" method

Is it bad to bind behaviours to document unconditionally?

The pagination controls on a page I am working on were being bound conditionally on there being more than 1 page. I don't like to see the following code in my projects,
if (pages > 1) {
$('.some_class').bind('event', function() {});
}
because I feel it represents a disorganized coding style. I would put it on the same level as sprinkling return statements here and there rather than using control. I feel like binding events to globally available objects has no place in the local scope of a function call. So what I usually do is make two javascript files, for example: pagination.js and pagination-controls.js. In the one I have logic about building the html and displaying the the pagination controls. In the other I have statements like the following:
$(document).on('click', '.pagination .next', function() {});
Which fires regardless of whether there is a $('.pagination .next') element anywhere on the page. I like the way that feels: the website has behaviours and it only knows about ids and classes, not about instance variables in some local scope somewhere.
EDIT: this is definitely bad practice, as mentioned below. However:
As of jQuery 1.7, the .on() method is the preferred method for
attaching event handlers to a document.
and the discussion on direct and delegated events is relevant. In particular I think the following describes my usage:
By picking an element that is guaranteed to be present at the time the
delegated event handler is attached, you can use delegated events to
avoid the need to frequently attach and remove event handlers. This
element could be the container element of a view in a
Model-View-Controller design, for example, or document if the event
handler wants to monitor all bubbling events in the document.
EDIT: So I guess now I'm wondering "is it bad to prefer binding behaviours to parent elements unconditionally over binding based on logic?" That's perhaps just a question of style, and my original question has been answered so I think I will accept the answer.
Yes, this is causing significant unnecessary overhead, and it is a "bad practice".
Binding your event handling to the top-level document object means that every single click that occurs on any element anywhere in your page will bubble up to the document object, where the event's target is checked to see if it matches .pagination .next.
In fact, the documentation itself recommends against your usage:
Attaching many delegated event handlers near the top of the document tree can degrade performance. Each time the event occurs, jQuery must compare all selectors of all attached events of that type to every element in the path from the event target up to the top of the document. For best performance, attach delegated events at a document location as close as possible to the target elements. Avoid excessive use of document or document.body for delegated events on large documents.
So, you're misusing on. It's for binding directly to elements or to parent elements which may have dynamically created children, and you are meant to bind to the closest possible parent element. Binding to the document is certainly not meant to be the only way you handle events in your page.

Trigger Real Event with jQuery

It seems that jQuery's trigger() only runs event handlers that were bound with jQuery. I have some modules that use native browser event binding. Using the code from https://stackoverflow.com/a/2676527 works for me, but I'm wondering if there's something built in to jQuery that will do this?
Update from comments: apparently it works for click events on buttons. But not for change events on select boxes: http://jsfiddle.net/qxpXV/2/
For the record: hacking the other library to do its bindings with jQuery does make trigger() work, but I don't really want to do that.
You can do this by manually firing/dispatching an event (depending on the browser, fireEvent/dispatchEvent) directly on the DOM element. Code from this answer will handle the event dispatching, you'll just need to execute it against a DOM element and not the jQuery wrapper.

Categories

Resources