I'm trying to build a simple accordion Polymer component. I have it working so when I click on an item in the list, an open class is added to the item which shows its contents.
I don't want to be able to have multiple items open at a time, so in my click function, I essentially want to say:
$(".list-item").on("click", function() {
$("list-item").removeClass("open");
$(this).addClass("open");
}
Of course this is in jQuery and not Dart...so that doesn't help me much.
What's the above equivalent in Dart?
Here's what I have working right now (just opens each clicked item, but doesn't close others in the process).
_openedChanged: function() {
if (this.opened) {
this.toggleClass('open', true);
}
else {
this.toggleClass('open', false);
}
this.setAttribute('aria-expanded', this.opened ? 'true' : 'false');
}
To remove a class from all list-item elements in Dart, you could do:
querySelectorAll('list-item').forEach((item) => item.classes.remove('open'));
Related
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)
I am using the jquery mobile datebox at http://dev.jtsage.com/jQM-DateBox2/demos/fullopt.html
In particular I am using the calbox option at http://dev.jtsage.com/cdn/datebox/1.1.0/jqm-datebox-1.1.0.mode.calbox.js
I need to intercept the click event that is triggered when you click on a day and then do something custom (E.g. change the background color of that date). What is the best way of doing this? I tried to register a click event for the element $('div.ui-datebox-griddate.ui-corner-all.ui-btn-up-d') but that does not seem to be working.
I am using backbonejs and the relevant portion of the class in coffeescript looks something like (SimpleView extends Backbone.View):
class A extend SimpleView
....
events: {
'click div.ui-datebox-griddate.ui-corner-all.ui-btn-up-d': "clicked"
}
clicked: (event) ->
console.log 'clicked'
The above does not work and moreover this perhaps is not the best way to do what I want since it depends on internal class names to create the click event.
Thanks in advance!
Datebox triggers a custom event called "datebox" (creatively enough). The event is fired three times when a day is clicked, but more importantly, it passes a second argument to the event that has the details about the day being clicked.
Give this a shot:
....
events: {
'datebox' : 'clicked'
},
clicked: function(e, eventDetail) {
// Of the three event triggers, "method" varies, so I checked for "set"
if (eventDetail.method == "set") {
var jsDateObj = eventDetail.date;
console.log(jsDateObj);
}
}
....
I think I figured out one way to do it. Instead of creating a click on the "day" element - create one on the input date field to which the calendar is attached. From there you can get the content and use that as a filter to get to the correct calendar day element at which point you can do whatever you want using css styling. The relevant code piece is given below...
class A extend SimpleView
....
events: {
'change #mydate': "clicked"
}
clicked: (event) ->
t = $(event.target)
day = t.data('datebox').theDate.getDate()
dayFilter= "div.ui-datebox-griddate.ui-corner-all:contains('#{day}')"
$(dayFilter).filter( ->
thisDay = parseInt($(#).text())
if thisDay == day
# do your css magic here
)
I have an input box similar to this http://jqueryui.com/demos/autocomplete/#multiple with the add button. I want to add all values split by comma added to a list on enter. I can't manage to do this because the keypress with enter seems to be conflict with select event of autocomplete. The problem is that the user can add only one item. I want the user to add multiple items then press enter key to add them to the list at the same time.
The enter key event should happen only when the suggestion list of autocomplete is closed.
You can use the open and close events of autocomplete to keep track whether or not the suggestion list is currently open (storing this information somewhere - in the example below, in the "selectVisible" data):
$( "#tags" )
.bind( "keydown", function( event ) {
if ( event.keyCode === $.ui.keyCode.ENTER && !$(this).data("selectVisible") ) {
// Your code
}
...
})
.autocomplete({
open: function() {
$(this).data("selectVisible", true);
},
close: function() {
$(this).data("selectVisible", false);
},
...
});
Working example at jsFiddle.
I've used the jQuery Multiselect widget with great success before and I believe it is more intuitive to the user that they can select multiple options.
Also it handles the Enter key appropriately out of the box.
http://www.erichynds.com/jquery/jquery-ui-multiselect-widget/
Anyone know good sample code using jQuery UI's autocomplete widget that can autocomplete words in the middle of a text box, not just autocomplete of the word at the end only?
I'm using the jquery UI autocomplete widget for a component that supports entry of multiple tags. It's like like stack overflow's tag editor, but simpler: no fancy formatting in the autocomplete dropdown, no "tag" background images in the edit box. I started with the jQuery UI Autocomplete Multiple sample and modified it.
It's working OK, except autocomplete doesn't work for tags in the middle of a multi-tag string. For example, if I type C Fortran and then put the caret right after C and type +, I'd expect to see C++ in the autocomplete list but instead I see Fortran again.
Here's the code so far: http://jsfiddle.net/WCfyB/4/
This is the same problem described by autocomplete in middle of text (like Google Plus), but the problem in that question was simpler because he could rely on an empty # in the text to signal when to show the autocomplete. In my case, I can't just rely on the text-- I actually need to find out where the caret is and autocomplete for the word where the caret is.
I could build this myself using caret or another plugin, but was wondering if there was already a jQuery-UI-based sample online that I could use without re-inventing another wheel, especially if there are browser-specific corner cases to worry about. Ideally, it'd behave like this: whenever the user places the caret inside or at the end of a tag (where tags are always separated by 1+ spaces), autocomplete is shown for that tag. Know a good sample?
I don't know of any examples like this, but here's something that you could start with:
var availableTags = [ ... ];
function split(val) {
return val.split(/ \s*/);
}
function extractLast(term) {
return split(term).pop();
}
$("#tags")
.bind("keydown", function(event) {
// don't navigate away from the field on tab when selecting an item
if (event.keyCode === $.ui.keyCode.TAB
&& $(this).data("autocomplete").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function(request, response) {
var results = [],
selectionStart = this.element[0].selectionStart
term = extractLast(request.term.substring(0, selectionStart));
if (term.length > 0) {
results = $.ui.autocomplete.filter(availableTags, term);
}
response(results);
},
focus: function() {
return false; // prevent value inserted on focus
},
select: function(event, ui) {
var terms = split(this.value.substring(0, this.selectionStart));
terms.pop(); // remove the current input
terms.push(ui.item.value); // add the selected item
this.value =
$.trim(terms.join(" ") + this.value.substring(this.selectionStart)) + " ";
return false;
}
});
Example: http://jsfiddle.net/WCfyB/7/
The major caveat here is that the selectionStart method does not work in IE. You can replace those function calls with one of those plugins you mentioned in your question.
I am developing an application using Backbone.js and have run into an issue where any instance of a view, excluding the first, fails to bind a click event to the ".playVideo" when accessed from an iPad. The same code executes as I would expect on desktop browsers.
I am creating a simple carousel that can scroll left/right and when a button is clicked I trigger another event to create a video player on the page. The first two events which bind to the .leftArrow / .rightArrow class do work on the second instance of the view; however, the click .playView binding will only work on the first instance.
While debugging, I also added a new binding 'click a' and observed that the additional instances don't execute an event for that item as well.
Simplified Code
Pod = Backbone.View.extend({
events: {
'click .leftArrow' : 'previous'
,'click .rightArrow' : 'next'
,'click .playVideo' : 'loadPlayerUI'
}
,initialize:function()
{
// Do stuff
return this;
}
,render:function()
{
// Draw stuff
return this;
}
,loadPlayerUI : function(event) {
event.originalEvent.preventDefault();
console.log("Hit");
return this;
}
});
In the above example the console message will not appear for any instance of this view except the first one created.
Question
What may I be doing incorrectly?
I appreciate your help.
Thank you.