The Firebase key-value store looks intriguing, and would be fun to use with Dart's HTML framework.
They offer a JavaScript library for reading/writing to their model. Has anyone tried using it with Dart?
My plan (based on very little Dart knowledge) is to:
Include their library in my html
Load the js.dart package
instantiate a model through js.dart
read and write through model.
Does that seem like the right approach? Or, is there a much better way of doing it?
Thanks
You can use any Javascript library through the js package.
For Firebase you have to :
add the js package to your pubspec.yaml
dependencies:
js: any
add the the following <script> to your html page :
<script src='https://cdn.firebase.com/v0/firebase.js'></script>
<script type="application/dart" src="youDartCode.dart"></script>
<script src="packages/browser/dart.js"></script>
<script src="packages/browser/interop.js"></script>
use Firebase Javascript SDK through js package. Something like :
import 'package:js/js.dart' as js;
void main() {
final myDataRef = new js.Proxy(js.context.Firebase,
'https://xxx.firebaseio-demo.com/');
myDataRef.on('child_added', (snapshot, String previousChildName) {
final message = snapshot.val();
print("${message.name} : ${message.text}");
});
myDataRef.push(js.map({"name": 'myName', "text": 'js interop rocks'}));
}
The above Dart code is the equivalent of the following JavaScript code :
var myDataRef = new Firebase('https://xxx.firebaseio-demo.com/');
myDataRef.on('child_added', function(snapshot, previousChildName) {
var message = snapshot.val();
console.log(message.name + " : " + message.text);
}));
myDataRef.push({name: 'myName', text: 'js interop rocks'});
Basically :
when you have to instantiate a Javascript object, use new js.Proxy(js.context.MyJavascriptObjectName, arg1, arg2, arg3)),
when you have to provide a Javascript anonymous object, use js.map({'attr1', value1}, {'attr2', value2}).
There's now a wrapper for the firebase.js library in Dart here: https://github.com/firebase/firebase-dart/ (also available on pub). It uses dart:js as discussed in this thread, so inclusion of firebase.js is still required!
I got the error message "Breaking on exception: ReferenceError: ReceivePortSync is not defined" when Dart got to here.
js.scoped (() {
});
An additional line of code is needed to use Firebase with Dart. Add the line "packages/browser/interop.js"
<script type="application/dart" src="ScrollViewDemo.dart"></script>
<script src="packages/browser/dart.js"></script>
<script src="packages/browser/interop.js"></script>
<script src='https://cdn.firebase.com/v0/firebase.js'></script>
----------------- Edit Aug 15 ----------
js.scoped is no longer needed in the newer version of interopt.js
Related
I'm trying to get working jQuery UI and prototype libraries together and finally arrived to this:
<script type="text/javascript" src="/js/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="/js/scripts.js"></script>
<script type="text/javascript" src="/js/prototype.js"></script>
<script>
var jq = jQuery.noConflict();
// Code that uses other library's $ can follow here.
</script>
<script src="/js/jquery-ui.js"></script>
And call jQuery like so:
jQuery(function($){
$('#myid').[...]
});
or
jQuery('#myid').[...]
But now, I can't get rid of the following error (without calling anything):
Uncaught TypeError: proto.plugins[i].push is not a function
and comes from the jquery-ui.js file with this part:
$.ui.plugin = {
add: function( module, option, set ) {
var i,
proto = $.ui[ module ].prototype;
for ( i in set ) {
proto.plugins[ i ] = proto.plugins[ i ] || []; // Error fires here
proto.plugins[ i ].push( [ option, set[ i ] ] );
}
},
Is there a solution?
I ran into the same problem. The cause for me was my attempt to add a function to javascript's Object class.
In fact, simply extending javascript's Object is not supported at all by jQuery - and thereby its plugins.
This answer to the question of extending Object has a good solution which solved the problem with jQueryUI for me.
I am working on a Firefox Add, using the newest SDK. The problem I am having, is that when ever I try to run a custom dom function it doesn't work.
Scenario:
The firefox add-on must be able to loop through all tabs, and if the correct one is open based on the title, run a specific function, like: mydom.checkIt();
<!DOCTYPE html>
<html>
<head>
<title>My Web</title>
</head>
<body>
<script>
mydom = {};
mydom.checkIt = function (){
alert('Hi');
};
</script>
</body>
</html>
Then the add-on source code would be something like:
var tabs = require('sdk/tabs');
for (let tab of tabs)
{
if(tab.title=='My Web')
{
tab.activate();
}
}
tabs.on('activate', function(tab) {
tab.attach({
contentScript: "if(typeof(mydom)!=='undefined')mydom.checkIt();else console.log('no defined');"
});
});
But this doesn't work and it says always: "no defined"
Any ideas?
You have to get into the dom js scope with unsafeWindow or wrappedJSObject. So contentWindow.wrappedJSOBject.checkIt() works from bootstrap addon (not sure about sdk)
Warning though, this may not be e10s friendly and we should find a way to support that
After building a Google Dart web app in Dart Editor (the Pub Build (Generates JS) option) the folder layout is like this. My app imports both dart:html and dart:async but It seems I can upload everything but the $sdk folder to my server and the app will run fine in both Dartium and in other browsers. Is there some reason I need to upload the $sdk folder, and what is it for? Tried googling but I see no answer, thanks in advance!
Edit: Here's a working example of my project from DartEditor 1.5.8 and below is the code for it.
hexclock.dart:
import 'dart:html';
import 'dart:async';
DateTime theTime;
String theHour, theMinute, theSecond;
Timer theTimer;
void main() {
theTimer = new Timer.periodic(new Duration(seconds: 1), getTime);
}
void updateColours(){
String bgcol = "#" + theHour + theMinute + theSecond;
querySelector("body").style.backgroundColor = bgcol;
}
void printTime() {
querySelector("#hour").text = theHour;
querySelector("#minute").text = theMinute;
querySelector("#second").text = theSecond;
}
void getTimeInit(){
theTime = new DateTime.now();
theHour = "${checkZero(theTime.hour)}";
theMinute = "${checkZero(theTime.minute)}";
theSecond = "${checkZero(theTime.second)}";
printTime();
updateColours();
}
void getTime(Timer t){
theTime = new DateTime.now();
theHour = "${checkZero(theTime.hour)}";
theMinute = "${checkZero(theTime.minute)}";
theSecond = "${checkZero(theTime.second)}";
querySelector("#title").style.opacity = "0";
querySelector("#clock").style.opacity = "1";
printTime();
updateColours();
}
String checkZero(int anInt){
if (anInt < 10)
return "0${anInt}";
else
return "${anInt}";
}
hexclock.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>HexClock</title>
<script async type="application/dart" src="hexclock.dart"></script>
<script async src="packages/browser/dart.js"></script>
<link href='http://fonts.googleapis.com/css?family=Droid+Sans+Mono' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="hexclock.css">
</head>
<body>
<div id="title" class="centre">hexclock</div>
<div id="clock" class="centre">#<span id="hour"> </span><span id="minute"> </span><span id="second"> </span></div>
</body>
</html>
pubspec.yaml:
name: HexClock
description: A sample web application
dependencies:
browser: any
In the pub source code I found this:
// "$sdk" is a pseudo-package that allows the dart2js transformer to find
// the Dart core libraries without hitting the file system directly. This
// ensures they work with source maps.
var libPath = path.join(sdk.rootDirectory, "lib");
var sdkSources = listDir(libPath, recursive: true)
.where((file) => path.extension(file) == ".dart")
.map((file) {
var idPath = path.join("lib",
path.relative(file, from: sdk.rootDirectory));
return new AssetId('\$sdk', path.toUri(idPath).toString());
});
I don't know if this matches exactly what you're seeing, but my guess is that it's related. This would in theory allow client-side debugging even through SDK functions, which could be very useful.
Basically the entire build folder is intended to be deployed.
There are some redundant files like the *.dart.pecompiled.js which are only necessary for CSP environments (Chrome App for example).
I think there was a recent change so that these files are not generated anymore.
There might be other things redundant too but I haven't seen any information about it yet.
You could try with a Dart 1.6 release (stable should be out) and check if this was dropped or if there has to be another explanation.
I use always bleeding_edge which is currently 1.7+.
Another explanation is that this is only created when you build in debug mode.
DartEditor does this by default.
Try pub build from the command line to see if it is still generated.
How can i use google earth API with backbone.js+jquery mobile ?
I have created application using backbone.js, underscore.js and jQuery Mobile.
For google earth API, I am using sample code listed at https://developers.google.com/earth/documentation/#using_the_google_earth_api
My template rendering, and all other pages are working fine But when i load google earth API in one tag, it's not loading and in js console i get message: "ERR_INVALID_DIV ".
Google.earth module never calls back initCallback, It's always calls failureCallback when google.earth.createInstance is invoked.
I explain some sample code of mine application as under, so based on that may be you get my code structure and it helps you to solve my issue.
my js code as under,
myjs1.js
var ge;
function init() {
google.earth.createInstance('map3d', initCB, failureCB);
}
function initCB(instance) {
console.log(' init call back call ');
ge = instance;
ge.getWindow().setVisibility(true);
}
function failureCB(errorCode) {
console.log(errorCode);
}
Now my Backbone code as under,
myjs2.js
WebApp.MyPage= Backbone.View.extend({
initialize:function (result) {
this.template =_.template($('#myPage').html());
},
render:function (eventName) {
var self = this;
mydata = object dict of my data;
$(self.el).html(self.template({mydata:mydata}));
google.load("earth", "1");
init();
google.setOnLoadCallback(init);
}
Now my HTML code like as under,
<script type="text/template" id="myPage">
<div data-role="page">
<div data-role="content">
<div id="map3d" style="height: 400px; width: 600px;"></div>
</div>
</div>
</script>
myhtml.html
Is there any way to fix this?
Any help appreciated.
The Earth API works with the Google Earth Plugin, which is available only on Windows and Mac OSX. It is not available on mobile devices, sorry!
If you're testing on your Mac or Windows system, you should be able to get it working. The error code ERR_INVALID_DIV sounds like it isn't finding the map3d div. I would put a debugger; statement in the code just before the google.earth.createInstance() call, and then look around in the DOM inspector and see if map3d is in the DOM. It should be coming in from your template if that part is working.
But this won't help you when you try to load your site on a mobile device, because you won't have the Earth plugin available there.
So I was using trigger.io to create a page where there's a custom menu at the bottom and each button loads an external HTML page into main container. I had to hack around to make this work so I was wondering if there's a better way of doing it.
I started using the $('.main').load('pages/test.html') and it doesn't work. Instead I had to do:
forge.file.getLocal('pages/test.html', function (file) {
forge.file.string(file, function (str) {
$('.main').html(str);
});
});
which is kinda messy.
Also if the str HTML content as a img tag, the img doesn't show since the src attribute gets messed up. So I had to do another hack:
forge.file.getLocal('pages/test.html', function (file) {
forge.file.string(file, function (str) {
var $main = $('.main');
$main.html(str);
//Hack to resolve img src
var imgPath;
$main.find('img').each(function () {
var $this = $(this);
// First 8 chars is "file:///"
imgPath = $this.prop('src').substr(8);
forge.file.getLocal(imgPath, function (file) {
$this.prop('src', file.uri);
});
});
});
});
Any better way of purely loading an external HTML page without all the hassle?
Thanks!
Testing with forge platform v1.4 (at the time of writing, v1.4.18) on Android 4.1 and iOS (both the iPhone simulator and an iPad), I seem to be able to use jQuery's load method without any extra effort. Here's the structure for my testcase:
src/
index.html
face.png
pages/
hello.html
Here's the contents of index.html
<!DOCTYPE html>
<html>
<head>
<script src="js/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
$(function () {
$('.content').load('pages/hello.html');
});
</script>
</head>
<body>
<div class="content">
</div>
</body>
</html>
And pages/hello.html:
<b>hello world</b><img src="face.png">
Which resulted in this just after app launch:
One gotcha I can see with this approach is that the src attribute for the img tag had to be relative to index.html. If you're still having problems then a more specific testcase and/or details of forge platform version used as well as what devices/simulators you tested on might be useful.