Listening to JS CustomEvent in Dart - dart

I know that my question is not new, but all solutions I've found here and in the Internet are not working :( Or, I'm doing something completely wrong.
I need to create a communication between Dart and JS, and I would love to use events, as the idea seems to be neat and simple.
So, I tried this tutorial: https://dart.academy/easy-dart-js-interopt/
My JS code:
var customEvent = new CustomEvent("fromJavascriptToDart");
window.onload = document.dispatchEvent(customEvent);
document.addEventListener("fromJavascriptToDart", test, false);
function test() {
console.log("Listening");
}
The event is dispatched, as I see Listening in console log.
But when it comes to dart, nothing is working.
I've tried the following methods and everything failed:
document.on['fromJavascriptToDart'].listen((CustomEvent event) {
print("HEY! I'M LISTENING!");
});
window.on["fromJavascriptToDart"].listen((e) => print( "HEY! I'M LISTENING!"));
window.on['foo'].add((e) => print(e.detail)); //This is not working, as there is no add method in Stream Event anymore
#Listen('fromJavascriptToDart')
void eventTest(){
print("HEY! I'M LISTENING!");
}
Any help is mostly appreciated.

DartPad example
document.on['fromJavascriptToDart'].listen((CustomEvent event) {
print("HEY! I'M LISTENING!");
});
Works fine.
#Listen() is Polymer specific
add doesn't exist (listen as show above should be used)
the event doesn't seem to reach window, but I'm sure this will behave the same in pure JS.

Related

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();

Event typeahead:rendered not working on twitter typeahead

I'm using the twitter typeahead library. Version: 0.10.4
I have been able to bind events to the "opened", "selected" events but nothing happens when I bind the event "rendered", although it is in the documentation.
Has any of you guys come across this issue?
Here is the code I'm using:
typeAhead.on('typeahead:selected', function(e, suggestion) {
alert(0);return; // Shows the alert
})
typeAhead.on('typeahead:rendered', function() {
// Nothing happens
});
had the same issue, debugging I've found out this line
typeAhead.data().ttTypeahead.dropdown.datasets[0].onSync('rendered', function(){
console.log('rendered');
});
it's working for me and I aint found any better than this, without modifying typeahead libraries.
if you have more datasets, just change to a for loop.
I'm having troubles with this event too. I'm using version 0.11.1 and as far as I can see I think there's a kind of bug when passing arguments to the callback function:
if you use this handler:
function(obj, matches) {
console.log(matches);
}
you seem to get only one (the first one, of the several matched suggestions.
if you use this handler:
function(obj, match1, match2) {
console.log(match1);
console.log(match2);
}
you get two, and so on.
Actually all suggestions are passed as this handler prove:
function() {
console.log(arguments);
}
skipping the first slot, the remaining are the current suggestions, so I think this is a bug of the plugin.

dart - "There is no such getter 'function' in" issues

I'm starting learning dart, I've installed the Dart Editor normally on a Linux system, but the problem comes up when I start to code a simple snippet of code for instance this:
import 'dart:html';
void main() {
querySelector('#status').innerHtml = "Hola mundo";
var button = new ButtonElement();
button.text = "Haz click";
button.on.click.add( (e){
var div = new Element.html("<div>puto</div>");
document.body.elements.add(div);
});
document.body.elements.add(button);
}
I get three warnings with the same messages: "There is no such getter 'function' in..." in three different parts of the code:
I got this code in a book, so the code is correct, How do I resolve this problem? thanks
edit: I cannot run this code with these warnings as you could expect.
The book is probably out of date from the current library APIs.
Try changing elements to children, e.g. document.body.children.add(elem2); is an example in the DOM section of Dart: Up and Running.
See the api
https://api.dartlang.org/apidocs/channels/stable/#dart-dom-html.Element#id_onClick
ElementStream<MouseEvent> get onClick
Stream of click events handled by this Element.
This syntax is outdated
// button.on.click.add( (e){
button.onClick.listen(callback);
// or button.on['my-custom-event'].litsen();

Why do I lose draggable after drag?

I just migrated to backbone and have a strange behaviour.
I attach draggable to an element which is created by a script, thus not directly available in DOM.
EDIT:
The element that is created is .nav, $("#viewer") as container is already in the DOM.
In plain jQuery i used .on and mousemove event for this and it worked.
With backbone I use the same in the initialize method:
initialize: function(options) {
this.viewer = $("#viewer");
this.viewer.on("mousemove", '.nav', function() {
$(this).draggable();
});
This seems to work, but only one time.
After dragging the element one time, I can't drag it anymore.
Are there conflicts with the events? Am I missing something?
You have to refer to $('#viewer') after you've called render(). initialize is called before render, and so the DOM element doesn't exist.
Also, use this.$('#viewer'), and it will grab the element (after render) even if it hasn't been appended to your page's DOM.
myView = new ExampleView({ model: myModel });
$(body).append(myView.render().el);
myView.onRender();
// -------------
// Now on your view:
onRender: function() {
this.viewer = this.$('#viewer');
this.viewer.on("mousemove", '.nav', function() {
$(this).draggable();
});
},
UPDATE
You can also, to make such things simpler, customize Backbone to automatically call the onRender() function after rendering, by triggering an event or something.
Marionette.js (a Backbone.js extension) has this built in and I use it all the time.
The solution finally was pretty easy:
make sure you dont use outdated versions of backbone.js and underscore!!
After i updated the versions to latest I made it work with:
render: function() {
this.viewer.on("mouseover", '.nav', function() {
if (!$(this).data("init")) {
$(this).data("init", true);
$(this).draggable();
}
});
Probably still not very elegant but i couldnt made the suggested onRender method from dc2 work.

Getting error on $.mobile.changePage(): Uncaught TypeError: Cannot call method 'trigger' of undefined

I have a JQM apps and I am incorporating Backbone.
Since my initial javascript code is huge, I am only extracting what I believe is problematic.
I am following the advices and calls steps cited here:
jqm-config.js from http://coenraets.org/blog/2012/03/using-backbone-js-with-jquery-mobile/
http://jquerymobile.com/test/docs/pages/backbone-require.html
I have a major problem, and this is the behaviour, the problem comes from this code:
var r = Backbone.Router.extend
router: ...
"page": "pageDisplay"
...
pageDisplay: function(){
c = new AView(); // Backbone.View ...fetch() data...
$(c.el).page(); // Call to JQM to add its extra stuff; seems done correctly
$.mobile.changePage( "#" + c.id, {changeHash: false}); // line 50
}
When following the links of <a href="#page" >, I come as expected to the
page "#page" properly processed. But once there, if I click a refresh, which is indirectly reprocessed by the same router rule, I end up with the following error:
Uncaught TypeError: Cannot call method 'trigger' of undefined
I downloaded the jquery mobile development code and observed this:
// JQM1.1.2 - Line #3772 Show a specific page in the page container.
$.mobile.changePage = function( toPage, options ) {
if ( isPageTransitioning ) {
pageTransitionQueue.unshift(arguments );
return;
}
var settings = $.extend( {}, $.mobile.changePage.defaults, options);
// Make sure we have a pageContainer to work with.
settings.pageContainer = settings.pageContainer || $.mobile.pageContainer;
// Make sure we have a fromPage.
settings.fromPage = settings.fromPage || $.mobile.activePage;
// Line #3788
var mpc = settings.pageContainer, // Line #3789
pbcEvent = new $.Event("pagebeforechange" ),
triggerData = { toPage: toPage, options: settings };
// Let listeners know we're about to change the current page.
mpc.trigger( pbcEvent, triggerData ); // Line #3794
The Uncaught TypeError is caused by Line #3794, because mpc is undefined.
So, from JQM, In the Chrome inspector, I can see also that settings.fromPage is undefined and settings.pageContainer is undefined. I kind of imagine, that JQM cannot make an assumption on the fromPage, and therefore, cannot proceed on my refresh. All the options I have tried on the $mobile.changePage() have not succeed. I am out of ideas.
UPDATE/ Online site with the minimum to reproduce the problem:
apartindex, access the website with the bug
Any help will be appreciated.
The dextoInit function that calls the router code is called in $(document).ready() which does not guarantee that the jQuery mobile page has actually been set up successfully. But the router code calls $.mobile.changePage which depends on jQuery Mobile being initialized.
Putting it into mobileinit or pageinit should work.
(Unfortunately I can't modify the code and test it easily.)
Although, this fix it for the moment, it does have drawbacks. See below.
$(document).bind("pageinit", function(){
console.log('bindtomobileinit: event pageinit received');
if ( !window.AppNode.router ){
window.AppNode.router = new AppNode.singletons.router();
console.log("mobileRouter.js: Starting b history");
console.log('mobileRouter.js: About to launch Backbone history');
Backbone.history.start();
}
});
Registering to pageinit has a weird effect of being fired twice. I see that 2 nodes have been added to the Dom: the default "loading" jquery mobile div (related to pageinit:1), and my data-role page (pageinit:2). So on a "refresh browser click", my situation leaves me waiting for a first pageinit, creating an unexpected jquery mobile dom element (a default page created to display the waiting JQM circle animation), which trigger the router creation, and allows the Backbone.history call which then deal with my "" home page. The second pageinit do not interfere with the settings since I execute it only once.
I am really disappointed by this setup. I will leave this question for now, since it does sort of work.
I've found the source of the problem to be jquery-mobile version 1.3.0. When I fall back to either JSM 1.2.0 or 1.2.1, the "Uncaught TypeError: Cannot call method 'trigger' of undefined" problem goes away.
BTW, I am not using Backbone.
I had fixed this problem by using method append(), but not html()
$('body').append(view.render().$el);
I was able to resolve this issue by changing the page data property from "data-role" to "data-mobile-page" as what is referenced in line 4042 of jqm 1.3.2
fromPage.data( "mobile-page" )._trigger( "beforehide", null, { nextPage: toPage } );
Setting
$.mobile.autoInitializePage = true;
In your jquery mobile config file, some place like:
$(document).on("mobileinit", function () {...});
May help.

Resources