How to create a custom ul element with polymer dart which fires on-added and on-remove event when children are added? - dart

I have been making a simple todo list as a way to learn polymer dart.
Here is my todo example.
I have limited experience in web-programming in general. My idea is to create a simple app with
One text input
2 Custom ul elements (New task ul and Done task ul)
Entering a string in text input and pressing enter creates a li item which is added to New task.
Deleting an element from New task results in addition of element to Done task.
Now I know creating a separate model and tracking the changes in an observable list seperate from html might be better approach. But as a learning exercise I would like to create a custom ul which fires a on-added and on-removed event when li item are added and removed from it respectively.
Now I have a couple of questions.
Why is there no on-added or on-remove event in ul (html)? I would like to understand what is the rational behind it.
How would one go about creating a custom UListElement which fires on-added and on-removed event when li items are added or removed from it respectively?

Because normally you won't need it. As you wrote you change the model and let Polymer update the view.
You can easily implement it yourself by overriding the attached/detached methods and fire an event.
See https://stackoverflow.com/a/22424213/217408 for how to fire custom events in Polymer.dart.

Gunter is right. You're thinking is a little old school, so I'm surprised to hear that you're new to web dev. With Polymer, you need to embrace the data-driven view model. You want to be watching the backing model properties that are driving your view, not the DOM. Something like this:
#observable List<Task> tasks;
void tasksChanged(oldValue) {
// react to changes
}

Related

Tablesorter Editable Widget change how to select a row

I'm using TableSorter to display my table with the 'editable' widget - all working fine.
Does anyone know how I can change the 'single-click' (default, I think) which will select a cell, to 'double-click'?
Content Editable is a browser rendering, and as such TableSorter has little control on how it functions.
That being said you could write your own. Don't use the ContentEditable widget at all, just bind each tbody td to a double-click event, then wrap the content in a content editable div and focus it and bind an unfocus event to it. Once unfocused, run your validation, commit the update, update ts rows and unwrap the cell.
This is not a common UI behaviour and as such I think it would be in the realm of per site rather then the scope of TableSorter, it would be hard to maintain with a small user base and take up lots of the authors time to do so for a small base.
Of course this is my personal option of it, I know the Author is very busy and I just can't see this being a very used widget.
EDIT: Mottie just came up with an other option, it's not the best since it'll run validate on each blur, but it might be a little quicker to implement.
initialized: function (table) {
$('tbody')
.on('click', '[contenteditable]', function(){
this.blur();
return false;
})
.on('dblclick', '[contenteditable]', function(){
this.focus();
});
}
http://jsfiddle.net/abkNM/4683/

Orchard CMS conditionally hide widget and suppress zone

I am trying to conditionally suppress a widget from its driver. I basically have logic that if met, should display the widget and if not, should suppress it. The widget loads properties from the current page content item, and based on some properties should display or hide. I've got all the logic working, the only part left is suppressing the actual output.
I've tried returning null from the driver, however this simply outputs an empty widget (with its wrapper). How do I completely remove the widget from view?
Finally, the zone that this widget is placed in should suppress if none of the conditional widgets display.
Is this type of flexibility possible in Orchard? Preferably from my custom module not my theme, I'm trying to separate functionality from styling.
EDIT:
Here is the context of my situation and what I am trying to accomplish. I'm sure there is a much cleaner way to do this within Orchard than how I have naively designed it the first go-around: My client's copywriters tag pages as they see fit (using the Tags module/part). I have created 2 custom content types, "Testimonials" and "Offers", both with tags themselves among other properties [these are managed by a different team of copywriters].
On most "inner pages" of the website (I'm using a layer to determine the appropriate pages), the page's sidebar gets a "Testimonial" widget and a "Offer" widget. These widgets both operate the same, although independently of each other:
They grab the tags of the current page, then pull a random [Testimonial|Offer] that has any matching tags as well. There are 4 cases that can happen given any inner page: a testimonial is displayed and the offer is hidden (testimonial tag matched, offer tag didn't), the testimonial is hidden and the offer is displayed, both the testimonial and offer displays, and finally neither displays. The first 3 use cases are working great, the 4th is what I'm having difficulty with, as the sidebar [zone] still displays even if both widgets do not (returning null from their respective drivers).
A bit of context about widgets: widgets are supposed to be pieces of contents that are visible on some or all pages of the site, and that provide information that is not directly related to the main content item on the page (if there is such a thing).
As a consequence, what you are describing should not be implemented as widgets (all that you had to do to make it work attests to that further), because they are really part of the content item. Instead, you should have implemented a part or a field. You can then simply place the shape for this part of field, using placement, by specifying a top-level zone: <place the_shape_name="/the_zone_where_you_want_it:1"/>
Unfortunately I've had to use a bit of a hack so that I could move on with the project as I'm under an aggressive deadline, but if there is a better method and/or solution I'll test as I get the chance and mark as the answer.
To get it to work, I overwrote the Widget.Wrapper.cshtml file within my theme. There, I assigned a variable to the Display(Model.Child) call, and if the result is an empty string simply return. This removes any empty widget wrapping tags. (I personally feel Orchard should behave this way by default):
var child = Display(Model.Child);
// -- NOTE: shape tracing breaks this logic!
if (string.IsNullOrWhiteSpace(child.ToString())) {
return;
}
Then simply replace the #Display(Model.Child) between the header and footer with #(child)
I then added the following method to my Layout.cshtml file.
Func<dynamic, IHtmlString> CollapsableZone = x =>
{
var display = Display(x);
string zoneName = x.ZoneName;
if (string.Equals(display.ToString(), string.Format("<div class=\"zone zone-{0}\"></div>", zoneName.HtmlClassify()), StringComparison.CurrentCultureIgnoreCase))
{
return new HtmlString(string.Empty);
}
return display;
};
Simple function that assigns the display call to a variable, checks if it is an empty zone tag, and returns. I then create variables for each zone assigned to the value of the function above. I replace all the #if (Model.ZoneName != null) with #if (!string.IsNullOrWhiteSpace(zoneVariable)), and replace the calls to #Zone(Model.ZoneName) with #(zoneVariable).
This is working for the time being. It is quite a hack and brittle solution but I've had to move on to other things.

AngularDart NgComponent using event listeners in the controller

I have an NgComponent in Angular Dart which instantiates a search box and according to the query strings it populates another div in my html template with the ng-repeat directive.
More precisely,
Query string update: there is a binding to the input text value with a field in my components' controller.
Results population: In the attach() method I added a watcher for the local field which acts as a model to the input box, and whenever it changes I add to a local list some items which then acts as a model to the ng-repeat directive in another div.
So far everything works fine. But now I want to add some event listeners inside my component, like keystroke listeners or if possible to add listeners on specific elements in my html template. I have used CSS for hover and focus events and also ng-focus and ng-blur for easy functions. But I do not think that this can be used for keystroke listeners.
The reason I want the keystroke listener is to enable results traversing using the arrow keys. While the cursor is inside the input text box I would like to move to the first result, which is in another div, with the press of Down arrow, and then continue to the other results.
Thank you
OK, It seems that I have finally found the solution.
The solution is to implement the NgShadowRootAware interface with my component and then inside the void onShadowRoot(ShadowRoot shadowRoot) method I have full access to the DOM created inside the shadow dom template.

Dart observable list that does not delete and reinsert all elements on change

We have some code that has a custom web component to display each element in an observable list. It seems that when an element is added to the list, the Web-UI infrastructure sees fit to remove all of the DOM nodes that represent elements in the list, and then re-add them along with the new element.
Not knowing much about the internal workings of the Dart-UI code, I would actually expect the addition of an element in the observable list to simply add one (or more) nodes to the DOM, without removing any of the existing nodes from the DOM.
Is it possible to achieve this sort of behavior?
There is an open issue for this: https://github.com/dart-lang/web-ui/issues/431. John wrote
fwiw, I'm working on a data-binding overhaul right now. The new
implementation includes stable lists by default.
so this should be fixed eventually.

jQuery Sortable todo List

I'm trying to build a todo list. http://d2burke.com/exp/todo/
I want my user to be able to mark items as complete, at which point the item is dropped down to the 'Complete' list, and vice versa. I also want each of these lists to be independently sortable.
I'm using a basic custom method to move the items back and forth, and I've used jQueryUI Sortable to sort them.
All of these things I've been able to accomplish; however, it doesn't seem as though the site (the DOM?) is registering that the items were moved from one list to the other. If I mark one item as 'Complete' it physically moves down...and becomes sortable in the 'Complete' list, but I'm echoing out the current positions in serialized format (because I'm going to record the order in a db) and the app doesn't seem to recognize that the item has moved.
I'd like to force the app to recalculate the list of items when an item is marked complete, or incomplete.
Help?
I looks to me like you should look at the resfresh methods of of the sortable: http://jqueryui.com/demos/sortable/
I would start with .refresh() too see if that also recalculates the positions. I assume it does but if not you might need to trigger the other one too.
There are few things that stand out that I would comment on:-
1) When you 'move' an item, you are moving more than you intend - the moved item has a 'tbody' around it - your code is very fragile, depending on parent.parent... which will be a nightmare to maintain.
2) You have various parent.parent constructs - lose these switch to '.closest()' to search up the tree to the class of item you wan to operate on.
3) You are doing things with binding/unbinding - lose them and switch to '$(document.body).on(,...)' then jquery will add/remove events automatically based on your selector - link once and forget.
Once this is done the bugs may go away - if not it will still be clearer so possible to debug properly!
Regards
ps. If it were me, I think I'd link the two list so they are sortable together, and toggle the completed flag if an item is moved from one list to the other.
This way the user has two ways of changing the status and jquery will do all the donkey work as you are simply sorting a normal linked list.

Resources