How to add an onclick event listener to all input fields using Polymer.dart - dart

I want to add an onclick and an onchange event to all input fields inside a Polymer template.
Is there a way to add the events at once by code to all of them?
I want to avoid adding onclick and onchange attributes to the input fields one by one.
I think it must be possible, but I'm messing around with the code and I can't get it.
Thanks in advance

This is quite similar to Listen to events on ElementList with no explicit accessor. You might need a different selector but your question doesn't contain enough information to know what that might be. Maybe:
List<StreamSubscription> _clickSubscriptions = <StreamSubscription>[];
List<StreamSubscription> _changeSubscriptions = <StreamSubscription>[];
this.shadowRoot.querySelectorAll("input")
.forEach((e) {
_clickSubscriptions.add(e.on["on-click"].listen((event) {
print("Event Triggered");
}));
_changeSubscriptions.add(e.on["on-change"].listen((event) {
print("Event Triggered");
}));
});
to cancel the subscription use
_clickSubscriptions.forEach((s) => s.cancel());
_changeSubscriptions.forEach((s) => s.cancel());
See also How can you assign mutliple listeners to a single StreamSubscription?

Related

How to remove "on-click" from a custom Polymer component

I have a custom button component done in Polymer Dart:
<div id="buttonDiv">
<my-button id="traceButton"
mode="icon" faicon="fa-comment-o"
toolTip="Print a simple comment"
disabled="false" on-click="{{ traceSomething }}">
</my-button>
</div>
I'm trying to copy/paste this button somewhere else. So a user defines it somwhere, and I basically move it by way of getting $['buttonDiv'].children then inserting it somewhere else. The problem is that {{ traceSomething }} is now irrelevant since it's not part of the new parent. I get errors saying that the parent object, which is another polymer component doesn't have an instance getter "traceSomething".
My question is, is there a way to remove "traceSomething" before I insert it somwhere else? I tried removing the "onClick" event listeners, but the buttons still wants to call that function upon click. Also, I've tried adding a preventDefault, etc, like in: In Dart, if I listen to a click event with two listeners, how do I know which happens first?
But, no luck.
I'm not sure what you mean by copy/past. Do you clone the element, or do you just append it to some other elements children.
Anyway, I don't think you can remove the event listener if it was added declaratively. If you add it imperatively it is easy to remove and readd later.
import 'dart:async';
...
StreamSubscription subsc;
#override
attached() {
super.attached();
subscr = onClick.listen((e) => (this.parentNode as ShadowRoot).host.traceSomething(e));
}
#override
detached() {
super.detached();
if(subscr != null) {
subscr.cancel();
}
}
See also https://stackoverflow.com/a/22168745/217408 about accessing the parent of a Polymer element (for Dart Polymer <= 0.16.x)

jQuery UI dialog binding keydown doesn't always work

I'm writing my own ESC handler because I need to do other actions when ESC is pressed, specifically I need to manage where focus goes for keyboard-only users. I have it working for all menus and some dialogs (both of which are using jQueryUI) but I'm having problems with dialogs that open on top of other dialogs (confirmation dialogs).
I'm using a Backbone View and adding my keydown handler on dialogcreate. this.$el.on('dialogcreate', this.bindKeydownEvent);
My handler:
bindKeydownEvent: function(ev, ui) {
var self = this;
this.$el.dialog().on('keydown', function(evt) {
if(evt.keyCode === $.ui.keyCode.ESCAPE) {
self.$el.dialog("close");
if(self.options.closeFocusEl) {
$(self.options.closeFocusEl).focus();
}
evt.stopPropagation();
}
});
}
I've checked and this.$el.dialog() is the correct dialog when the second dialog calls this.bindKeydownEvent but for some reason the keydown handler is not being triggered no matter what I press in the dialog (Tab, Space, Enter, random letters, etc).
Any idea what I'm doing wrong or have a better way I could bind the keydown event?
EDIT:
I just noticed that this is also happening in some first-level dialogs. It looks like the only difference is the way we get the template and therefore create the interior of the dialog. In our Alert and Confirmation dialog classes, we define the template as an attribute on the object like this: template: _.template("<div><%= o.content %></div>"). In other views (in which the keydown binding works) we build the child elements and add them to the DOM of the dialog, set the template in the initialize function
this.options.template = 'navigation/CreateNewDialog.template';
or set it when we call the dialog
var closeConv = new views.CloseConversationDialogView({
confirm: this.closeConversationConfirmed,
content: i18n.t("closeConversationInput"),
template: "conversation/CloseConversationDialog.template"
});
closeConv.render();
Is there a reason that creating the template inline as an attribute on the view would not bind keydown correctly?
To understand why your event handler isn't being triggered you need first understand how event delegation works.
The key to event delegation in that events bubble up the DOM. So when you bind your event using this.$el.dialog().on('keydown',..., what you basically doing is listening to any keydown event that is triggered on your $el or it's descendants. In this case being that your second dialog isn't a descendant of your $el it's events won't bubble up to it and therefore don't trigger your handler.
To work around this you can either bind directly to your second dialog, or instead bind to a exisitng higher level element like the document. For example
$(document).on('keydown', '.myDialog', function() {...
The only thing my original attempt was missing was "widget". The widget method, according to api.jqueryui.com,
Returns a jQuery object containing the generated wrapper.
I don't see any documentation on what exactly $('.selector').dialog() returns but apparently it is not the same as $('.selector').dialog("widget"). I also changed on('keydown'... to just use the jQuery keydown instead.
bindKeydownEvent: function(ev, ui) {
var self = this;
this.$el.dialog("widget").keydown(function(evt) {
if(evt.keyCode === $.ui.keyCode.ESCAPE) {
self.$el.dialog("close");
if(self.options.closeFocusEl) {
$(self.options.closeFocusEl).focus();
}
evt.stopPropagation();
}
});
}

JQuery passing arguments for On Change for an item added to DOM via AJAX

I have multiple HTML fragments that are inserted into my DOM as the result of AJAX call-backs.
Each of these fragments will contain a text box whose class is "quantity".
What I want to do is to create an "on change" event handler that fires whenever one of these textbox's text value is changed. However, when that event is fired/handled, I need to know WHICH specific textbox was updated.
Okay, using jQuery, I have the following that fires in my "Lists.initHandlers" method:
$(document).on('change', $('#divABC').find(".quantity"), List.quantityChanged);
And my "List.quantityChanged" event handler happily fires when I update the quanity.
The problem is that when I reference "this" within the event handler, I get the whole document, and not the element that triggered the event.
I have tried to capture the element using syntax similar to:
$(document).on('change', $('#divABC').find(".quantity"), {ctrl: this}, List.quantityChanged);
but when I attempt this, the handler is never fired (even when I change the signature to expect an argument).
Any guidance here would be most appreciated.
Thanks
Griff
Try this:
$('.quantity').live('change', function(){
alert('New value: ' + $(this).val());
});
Pass this to your function:
$(document).on('change', $('#divABC').find(".quantity"), function () {
List.quantityChanged(this);
});

Why isn't the keydown event firing?

I'm trying to attach an event handler to the keyDown event in a canvas element. Here is a simplified version of my code.
class CanvasFun{
CanvasElement canvas;
CanvasFun(this.canvas){
print("Game is loading!");
this.canvas.onKeyDown.listen(handleInput);
}
void handleInput(e)
{
//breakpoint is never hit
print(e.keyCode);
}
}
I've removed some of the drawing code. In my main function I simply query the canvas element and pass it to my CanvasFun constructor.
I've also tried doing it this way:
void main() {
var canvas = query("#Game");
canvas.onKeyDown.listen(handleInput);
var canvasFun = new CanvasFun(canvas);
}
void handleInput(e)
{
print(e.keyCode);
}
The reason why the event is not firing is because the focus is on the document (or some other element like an input, for example). And in fact, canvas element even when focused does not fire an event. Some elements do, like input elements.
The solution is to listen to key down events from the document or window:
window.onKeyDown.listen(handleInput);
document.onKeyDown.listen(handleInput); // You already noticed this worked.
John McCutchan has written a nice Dart package to help handle keyboard input. You can read more about it here: http://dartgamedevs.org/blog/2012/12/11/keyboard-input/
Note that this library helps you handle input "correctly". You do not want to do any "work" in the input handling, instead you simply want to register that a key was pressed. You can check the state of any key presses inside of your requestAnimationFrame callback.
Hope that helps!
There exists a workaround to get the canvas-element accept KeyboardEvents:
Problems handling KeyboardEvents on DartFlash
Once you add the tabindex-attribute to your canvas-element, it can get the focus and then it will receive KeyboardEvents.
It looks like I can get it to work if I register the event on the document rather than the canvas element.
document.onKeyDown.listen(handleInput);

jQuery AutoComplete Trigger Change Event

How do you trigger jQuery UI's AutoComplete change event handler programmatically?
Hookup
$("#CompanyList").autocomplete({
source: context.companies,
change: handleCompanyChanged
});
Misc Attempts Thus Far
$("#CompanyList").change();
$("#CompanyList").trigger("change");
$("#CompanyList").triggerHandler("change");
Based on other answers it should work:
How to trigger jQuery change event in code
jQuery Autocomplete and on change Problem
JQuery Autocomplete help
The change event fires as expected when I manually interact with the AutoComplete input via browser; however I would like to programmatically trigger the change event in some cases.
What am I missing?
Here you go. It's a little messy but it works.
$(function () {
var companyList = $("#CompanyList").autocomplete({
change: function() {
alert('changed');
}
});
companyList.autocomplete('option','change').call(companyList);
});
this will work,too
$("#CompanyList").autocomplete({
source : yourSource,
change : yourChangeHandler
})
// deprecated
//$("#CompanyList").data("autocomplete")._trigger("change")
// use this now
$("#CompanyList").data("ui-autocomplete")._trigger("change")
It's better to use the select event instead. The change event is bound to keydown as Wil said. So if you want to listen to change on selection use select like that.
$("#yourcomponent").autocomplete({
select: function(event, ui) {
console.log(ui);
}
});
They are binding to keydown in the autocomplete source, so triggering the keydown will case it to update.
$("#CompanyList").trigger('keydown');
They aren't binding to the 'change' event because that only triggers at the DOM level when the form field loses focus. The autocomplete needs to respond faster than 'lost focus' so it has to bind to a key event.
Doing this:
companyList.autocomplete('option','change').call(companyList);
Will cause a bug if the user retypes the exact option that was there before.
Here is a relatively clean solution for others looking up this topic:
// run when eventlistener is triggered
$("#CompanyList").on( "autocompletechange", function(event,ui) {
// post value to console for validation
console.log($(this).val());
});
Per api.jqueryui.com/autocomplete/, this binds a function to the eventlistener. It is triggered both when the user selects a value from the autocomplete list and when they manually type in a value. The trigger fires when the field loses focus.
The simplest, most robust way is to use the internal ._trigger() to fire the autocomplete change event.
$("#CompanyList").autocomplete({
source : yourSource,
change : yourChangeHandler
})
$("#CompanyList").data("ui-autocomplete")._trigger("change");
Note, jQuery UI 1.9 changed from .data("autocomplete") to .data("ui-autocomplete"). You may also see some people using .data("uiAutocomplete") which indeed works in 1.9 and 1.10, but "ui-autocomplete" is the official preferred form. See http://jqueryui.com/upgrade-guide/1.9/#changed-naming-convention-for-data-keys for jQuery UI namespaecing on data keys.
You have to manually bind the event, rather than supply it as a property of the initialization object, to make it available to trigger.
$("#CompanyList").autocomplete({
source: context.companies
}).bind( 'autocompletechange', handleCompanyChanged );
then
$("#CompanyList").trigger("autocompletechange");
It's a bit of a workaround, but I'm in favor of workarounds that improve the semantic uniformity of the library!
The programmatically trigger to call the autocomplete.change event is via a namespaced trigger on the source select element.
$("#CompanyList").trigger("blur.autocomplete");
Within version 1.8 of jquery UI..
.bind( "blur.autocomplete", function( event ) {
if ( self.options.disabled ) {
return;
}
clearTimeout( self.searching );
// clicks on the menu (or a button to trigger a search) will cause a blur event
self.closing = setTimeout(function() {
self.close( event );
self._change( event );
}, 150 );
});
I was trying to do the same, but without keeping a variable of autocomplete. I walk throught this calling change handler programatically on the select event, you only need to worry about the actual value of input.
$("#CompanyList").autocomplete({
source: context.companies,
change: handleCompanyChanged,
select: function(event,ui){
$("#CompanyList").trigger('blur');
$("#CompanyList").val(ui.item.value);
handleCompanyChanged();
}
});
Well it works for me just binding a keypress event to the search input, like this:
... Instantiate your autofill here...
$("#CompanyList").bind("keypress", function(){
if (nowDoing==1) {
nowDoing = 0;
$('#form_459174').clearForm();
}
});
$('#search').autocomplete( { source: items } );
$('#search:focus').autocomplete('search', $('#search').val() );
This seems to be the only one that worked for me.
This post is pretty old, but for thoses who got here in 2016. None of the example here worked for me. Using keyup instead of autocompletechange did the job. Using jquery-ui 10.4
$("#CompanyList").on("keyup", function (event, ui) {
console.log($(this).val());
});
Hope this help!
Another solution than the previous ones:
//With trigger
$("#CompanyList").trigger("keydown");
//With the autocomplete API
$("#CompanyList").autocomplete("search");
jQuery UI Autocomplete API
https://jsfiddle.net/mwneepop/

Resources