Nitrogen: changing targetID breaks lightbox - erlang

I'm using Nitrogen & lightbox. I'm looking for some guidance after spending way too long trying to understand why a working example breaks as soon as I change the targetID of a lightbox. The fragment below works if I use "name_dialog" or "share_dialog", but not if I use "compose_dialog". I've looked through the source and style sheets, but have not found where those two are defined any differently than what I'm trying to do.
In my .hrl:
...
-record (compose_dialog, { ?ELEMENT_BASE(compose_dialog_element) }).
..
In my element module:
...
reflect() -> record_info(fields, compose_dialog).
render_element(_HtmlID, _Record) ->
#lightbox { id=compose_lightbox, style="display: none;", body = [
..
show() ->
wf:wire(compose_lightbox, #show {}).

ok -- for anyone running into the same NOOB error...
What I neglected to do was add my new element on the body in webview. As a result, I had an undefined object with no ID. Adding it there (and making sure not to create duplicates) fixed this error.

Related

How do I create a message that flashes after an AJAX form returns an error?

I'm using Rails 5. I want to create a message that flashes on my page after I submit an AJAX form and an error comes back. I'm not using twitter bootstrap and would only consider using that if it doesn't screw up any of the other styling I already have. Anyway, on my view I have this
<div id="error_explanation" class="alert alert-success"></div>
and in my controller I have this
displayError('#{error_msg}')
which invokes this coffee script ...
#displayError = (msg) ->
...
$("#error_explanation").text(msg)
As you guess, right now, the message just displays in plain text . I would like it to flash and then disappear. How do I do that?
If you just need the message to fade out after a set amount of time, then change that last line of CoffeeScript to:
$("#error_explanation").text(msg).delay(3000).fadeOut()
If you need something a bit more complex (e.g. don't fade out if hovered, stacked notifications, dismiss button etc), or ready-styled - then you might want to investigate using a JS library such as toastr.
this should help get you started:
show_ajax_message = (msg, type) ->
$("#flash-message").html "<div id='flash-#{type}'>#{msg}</div>"
$("#flash-#{type}").delay(5000).slideUp 'slow'
$(document).ajaxComplete (event, request) ->
msg = request.getResponseHeader("X-Message")
type = request.getResponseHeader("X-Message-Type")
show_ajax_message msg, type
https://www.google.com/search?q=flash+messages+session+rails+ajax
Based on nothing but your coffee script, here's how:
Not familiar with CoffeeScript and its syntax, so here's plain JS code.
setTimeout(function() {
$('#visitLink').hide()
}, 2000);
That'll make the message disappear after 2 seconds.

if the original JS has many functions, how dart to initiate them?

after several rounds of research, I found there is no clear answer about the situation like below:
I have a js file called 'AAA.js', and there is simple code in side like this:
var AAA = {
listenForMenuLayer: function () {
console.log("menu initiated");
$('.nav-menu').on('click', function() { console.log("menu clicked")});
}
init: function(){
this.listenForMenuLayer();
}
};
And in the dart, I wrote like below (using 'dart:js'):
js.context['AAA'].callMethod('init');
Then, when I run it, everything looks fine, the "menu initiated" shows properly, which means the 'listenForMenuLayer' is initiated, but when click on the '.nav-menu', there is nothing happened. (I check many times, there is no spelling error or else)
My question is: Can Dart accept this kind of initiating of external JS event? or we should re-write those JS events at all, please advise, many thanks.
Updates:
I found that if we write the js code like above, the jquery will not be initiated properly, which means all the features begin with '$' will not be functional.
guys, I update it to using 'package:js/js.dart';
#JS('AAA.init')
external void aInit();
then some where, just simply call after including:
aInit();

How to query for an element inside a dom-repeat

I have been scouring the web for a clear answer on how to query for an element generated by a dom-repeat element from Dart code.
sample.html
<dom-module id="so-sample>
<style>...</style>
<template>
<template is="dom-repeat" items="[[cars]] as="car>
...
<paper-button on-click="buttonClicked">Button</paper-button>
<paper-dialog id="dialog">
<h2>Title</h2>
</paper-dialog>
</template>
</template>
sample.dart
I'll omit the boilerplate code here, such as imports or the query to my database to fill the cars property ; everything works fine.
...
#reflectable
void buttonClicked(e, [_])
{
PaperDialog infos = this.shadowRoot.querySelector("#dialog");
infos.open();
}
This generates the following error :
Uncaught TypeError: Cannot read property 'querySelector' of undefined
I have tried several 'solutions', which are not, since nothing works.
The only thing I saw on quite a lot of threads is to use Timer.run() and write my code in the callback, but that seems like a hack. Why would I need a timer ?
I understand my problem may be that the content of the dom-repeat is generated lazily, and I query the items 'before' they are added to the local DOM.
Another advice I didn't follow is to use Mutation Observers. I read in the polymer API documentation that the observeNodes method should be used instead, as it internally uses MO to handle indexing the elements, but it again seems a bit complicated just to open a dialog.
My final objective is to bind the button of each generated model to a dedicated paper-dialog to display additional information on the item.
Has anyone ever done that ? (I should hope so :p)
Thanks for your time !
Update 1:
After reading Gunter's advices, although none of them actually worked by themselves, the fact that the IDs aren't mangled inside a dom-repeat made me think and query paper-dialog instead of the id itself, and now my dialog pops up !
sample.dart:
PaperDialog infos = Polymer.dom(root).querySelector("paper-dialog");
infos.open();
I now hope that each button will call the associated dialog, since I'll bind data inside the dialog relative to the item I clicked ~
Update 2:
So, nope, the data binding didn't work as expected: All buttons were bound to the item at index 0, just as I feared. I tried several ways to query the correct paper-dialog but nothing worked. The only 'workaround' I found is to query all the paper-dialog into a list and then get the 'index-th' element from that list.
#reflectable
void buttonClicked(e, [_])
{
var model = new DomRepeatModel.fromEvent(e);
List<PaperDialog> dialogs = Polymer.dom(this.root).querySelectorAll("paper-dialog");
dialogs[model.index].open();
}
This code definitely works, but it feels kind of a waste of resources to get all the elements when you really only need one and you already know which one.
So yeah, my initial problem is solved, but I still wonder why I couldn't query the dialogs from their id:
...
<paper-dialog id="dialog-[[index]]">
...
</paper-dialog>
#reflectable
void buttonClicked(e, [_])
{
var model = new DomRepeatModel.fromEvent(e);
PaperDialog dialog = Polymer.dom(this.root).querySelector("dialog-${model.index}");
dialog.open();
}
With this code, dialog is always null, although I can find those dialogs, correctly id-ied, in the DOM tree.
You need to use Polymers DOM API with shady DOM (default). If you enable shadow DOM your code would probably work as well.
PaperDialog infos = new Polymer.dom(this).querySelector("#dialog")

.trigger('create') cannot create a listview

Here are the codes I have to dynamically create and enhance a page. The similar pattern has been working for many other kinds, such as text field, button, grid-view, etc. But I found it cannot work with a listview.
$(document).bind("pagebeforechange", function route(e, data) {
...
$content = $page.children(":jqmData(role=content)");
var markup = '<ul id="calendarList" data-role="listview"><li>HELLO</li></ul>';
$content.html(markup);
$page.trigger('create');
$.mobile.changePage($page);
});
I would always get an error message like,
Cannot read property 'jQuery16409763167318888009' of undefined
Through debugging using Chrome, I found it always fails on the line of $page.trigger('create');
I found the solution myself. It works fine if I replaced the line,
$page.trigger('create');
with,
$page.page();
$content.find( ":jqmData(role=listview)" ).listview();
However, I still don't understand why. I thought the former was a newer, simpler syntax to replace the latter. A single call of $page.trigger('create'); can enhance the entire page at one shot. Does anyone know the difference of these two?

jQueryUI and problem with sortable events

I'm working with the 'Connect list trough tabs' demo. I modified the code a little bit. I added the 'foo' class to the tabs-1 and tabs-2 elements.
I also added the following script:
$(".foo ul").sortable({
stop: function (event, ui) {
var tabId = $(this).attr('id');
var elementIndex = ui.item.index();
alert('tab id: ' + tabId + ' | element index: ' + elementIndex);
}});
It works super fine when I change the sort order of elements inside same tab, but I have the problem when I drop the element from the first tab to the second tab (or vice versa), because the element is firstly placed on the first position in tab1 (tab id = sortable1, element index = 0), and after that it is dropped to the second tab on the last position. The problem is because the sortable event is not fired for the second time.
I'm missing something but don't know what :)
Any help would be greatly appreciated.
Thank you!
EDIT:
Demo can be found on the following link: http://jqueryui.com/demos/sortable/#connect-lists-through-tabs
Did you ever find an answer to this? Because I'm currently having the same problem - trying a range of ways around it, but so far to no success.
EDIT
Scratch that, just found what I think is the most efficient way to resolve. Bind the event "DOMNodeInserted" to the <ul> list class you're using, and you can test the list item by searching its current DOM position:
$(".connectedSortable").bind("DOMNodeInserted", function() {
$('#tabs').find('li#staff-'+currentStaffId).each(function() {
listDeptID = $(this).parent().parent().attr('id');
listDeptID = listDeptID.split('-');
listDeptID = listDeptID[1];
....
In this example of mine, I have my list items with the id of staff-x with the id of that staff member, so the find returns one array element, and runs quite efficiently.
HTH
Jester.

Resources