diff --git a/js/Gruntfile.js b/js/Gruntfile.js
index f290250a..195decd6 100644
--- a/js/Gruntfile.js
+++ b/js/Gruntfile.js
@@ -15,11 +15,6 @@ module.exports = function (grunt) {
minified: "../mopidy/frontends/http/data/mopidy.min.js"
}
},
- buster: {
- test: {
- config: "buster.js"
- }
- },
concat: {
options: {
banner: "<%= meta.banner %>",
diff --git a/js/README.md b/js/README.md
new file mode 100644
index 00000000..9601b64a
--- /dev/null
+++ b/js/README.md
@@ -0,0 +1,82 @@
+Mopidy.js
+=========
+
+Mopidy.js is a JavaScript library that is installed as a part of Mopidy's HTTP
+frontend or from npm. The library makes Mopidy's core API available from the
+browser or a Node.js environment, using JSON-RPC messages over a WebSocket to
+communicate with Mopidy.
+
+
+Getting it for browser use
+--------------------------
+
+Regular and minified versions of Mopidy.js, ready for use, is installed
+together with Mopidy. When the HTTP frontend is running, the files are
+available at:
+
+- http://localhost:6680/mopidy/mopidy.js
+- http://localhost:6680/mopidy/mopidy.min.js
+
+You may need to adjust hostname and port for your local setup.
+
+In the source repo, you can find the files at:
+
+- `mopidy/frontends/http/data/mopidy.js`
+- `mopidy/frontends/http/data/mopidy.min.js`
+
+
+Getting it for Node.js use
+--------------------------
+
+If you want to use Mopidy.js from Node.js instead of a browser, you can install
+Mopidy.js using npm:
+
+ npm install mopidy
+
+After npm completes, you can import Mopidy.js using ``require()``:
+
+ var Mopidy = require("mopidy").Mopidy;
+
+
+Using the library
+-----------------
+
+See Mopidy's [HTTP frontend
+documentation](http://docs.mopidy.com/en/latest/modules/frontends/http/).
+
+
+Building from source
+--------------------
+
+1. Install [Node.js](http://nodejs.org/) and npm. There is a PPA if you're
+ running Ubuntu:
+
+ sudo apt-get install python-software-properties
+ sudo add-apt-repository ppa:chris-lea/node.js
+ sudo apt-get update
+ sudo apt-get install nodejs npm
+
+2. Enter the `js/` in Mopidy's Git repo dir and install all dependencies:
+
+ cd js/
+ npm install
+
+That's it.
+
+You can now run the tests:
+
+ npm test
+
+To run tests automatically when you save a file:
+
+ npm run-script watch
+
+To run tests, concatenate, minify the source, and update the JavaScript files
+in `mopidy/frontends/http/data/`:
+
+ npm run-script build
+
+To run other [grunt](http://gruntjs.com/) targets which isn't predefined in
+`package.json` and thus isn't available through `npm run-script`:
+
+ PATH=./node_modules/.bin:$PATH grunt foo
diff --git a/js/README.rst b/js/README.rst
deleted file mode 100644
index e8782213..00000000
--- a/js/README.rst
+++ /dev/null
@@ -1,62 +0,0 @@
-*********
-Mopidy.js
-*********
-
-This is the source for the JavaScript library that is installed as a part of
-Mopidy's HTTP frontend. The library makes Mopidy's core API available from the
-browser, using JSON-RPC messages over a WebSocket to communicate with Mopidy.
-
-
-Getting it
-==========
-
-Regular and minified versions of Mopidy.js, ready for use, is installed
-together with Mopidy. When the HTTP frontend is running, the files are
-available at:
-
-- http://localhost:6680/mopidy/mopidy.js
-- http://localhost:6680/mopidy/mopidy.min.js
-
-You may need to adjust hostname and port for your local setup.
-
-In the source repo, you can find the files at:
-
-- ``mopidy/frontends/http/data/mopidy.js``
-- ``mopidy/frontends/http/data/mopidy.min.js``
-
-
-Building from source
-====================
-
-1. Install `Node.js `_ and npm. There is a PPA if you're
- running Ubuntu::
-
- sudo apt-get install python-software-properties
- sudo add-apt-repository ppa:chris-lea/node.js
- sudo apt-get update
- sudo apt-get install nodejs npm
-
-2. Enter the ``js/`` dir and install development dependencies::
-
- cd js/
- npm install
-
-That's it.
-
-You can now run the tests::
-
- npm test
-
-To run tests automatically when you save a file::
-
- npm run-script watch
-
-To run tests, concatenate, minify the source, and update the JavaScript files
-in ``mopidy/frontends/http/data/``::
-
- npm run-script build
-
-To run other `grunt `_ targets which isn't predefined in
-``package.json`` and thus isn't available through ``npm run-script``::
-
- PATH=./node_modules/.bin:$PATH grunt foo
diff --git a/js/buster.js b/js/buster.js
index f789885a..37f41d8a 100644
--- a/js/buster.js
+++ b/js/buster.js
@@ -1,9 +1,17 @@
var config = module.exports;
-config["tests"] = {
+config.browser_tests = {
environment: "browser",
libs: ["lib/**/*.js"],
sources: ["src/**/*.js"],
testHelpers: ["test/**/*-helper.js"],
tests: ["test/**/*-test.js"]
};
+
+config.node_tests = {
+ environment: "node",
+ libs: ["lib/**/*.js"],
+ sources: ["src/**/*.js"],
+ testHelpers: ["test/**/*-helper.js"],
+ tests: ["test/**/*-test.js"]
+};
diff --git a/js/package.json b/js/package.json
index 6638c705..d3398ca0 100644
--- a/js/package.json
+++ b/js/package.json
@@ -1,6 +1,23 @@
{
"name": "mopidy",
- "version": "0.0.0",
+ "version": "0.0.1",
+ "description": "Client lib for controlling a Mopidy music server over a WebSocket",
+ "homepage": "http://www.mopidy.com/",
+ "author": {
+ "name": "Stein Magnus Jodal",
+ "email": "stein.magnus@jodal.no",
+ "url": "http://www.jodal.no"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/mopidy/mopidy.git"
+ },
+ "main": "src/mopidy.js",
+ "dependencies": {
+ "bane": "~0.4.0",
+ "faye-websocket": "~0.4.4",
+ "when": "~1.8.1"
+ },
"devDependencies": {
"buster": "~0.6.12",
"grunt": "~0.4.0",
diff --git a/js/src/mopidy.js b/js/src/mopidy.js
index 5a75a836..011aec09 100644
--- a/js/src/mopidy.js
+++ b/js/src/mopidy.js
@@ -1,4 +1,10 @@
-/*global bane:false, when:false*/
+/*global exports:false, require:false*/
+
+if (typeof module === "object" && typeof require === "function") {
+ var bane = require("bane");
+ var websocket = require("faye-websocket");
+ var when = require("when");
+}
function Mopidy(settings) {
if (!(this instanceof Mopidy)) {
@@ -20,9 +26,17 @@ function Mopidy(settings) {
}
}
+if (typeof module === "object" && typeof require === "function") {
+ Mopidy.WebSocket = websocket.Client;
+} else {
+ Mopidy.WebSocket = window.WebSocket;
+}
+
Mopidy.prototype._configure = function (settings) {
+ var currentHost = (typeof document !== "undefined" &&
+ document.location.host) || "localhost";
settings.webSocketUrl = settings.webSocketUrl ||
- "ws://" + document.location.host + "/mopidy/ws/";
+ "ws://" + currentHost + "/mopidy/ws/";
if (settings.autoConnect !== false) {
settings.autoConnect = true;
@@ -35,7 +49,7 @@ Mopidy.prototype._configure = function (settings) {
};
Mopidy.prototype._getConsole = function () {
- var console = window.console || {};
+ var console = typeof console !== "undefined" && console || {};
console.log = console.log || function () {};
console.warn = console.warn || function () {};
@@ -63,7 +77,7 @@ Mopidy.prototype._delegateEvents = function () {
Mopidy.prototype.connect = function () {
if (this._webSocket) {
- if (this._webSocket.readyState === WebSocket.OPEN) {
+ if (this._webSocket.readyState === Mopidy.WebSocket.OPEN) {
return;
} else {
this._webSocket.close();
@@ -71,7 +85,7 @@ Mopidy.prototype.connect = function () {
}
this._webSocket = this._settings.webSocket ||
- new WebSocket(this._settings.webSocketUrl);
+ new Mopidy.WebSocket(this._settings.webSocketUrl);
this._webSocket.onclose = function (close) {
this.emit("websocket:close", close);
@@ -136,17 +150,17 @@ Mopidy.prototype._send = function (message) {
var deferred = when.defer();
switch (this._webSocket.readyState) {
- case WebSocket.CONNECTING:
+ case Mopidy.WebSocket.CONNECTING:
deferred.resolver.reject({
message: "WebSocket is still connecting"
});
break;
- case WebSocket.CLOSING:
+ case Mopidy.WebSocket.CLOSING:
deferred.resolver.reject({
message: "WebSocket is closing"
});
break;
- case WebSocket.CLOSED:
+ case Mopidy.WebSocket.CLOSED:
deferred.resolver.reject({
message: "WebSocket is closed"
});
@@ -280,3 +294,7 @@ Mopidy.prototype._snakeToCamel = function (name) {
return match.toUpperCase().replace("_", "");
});
};
+
+if (typeof exports === "object") {
+ exports.Mopidy = Mopidy;
+}
diff --git a/js/test/mopidy-test.js b/js/test/mopidy-test.js
index 8842ebf4..b694fd7e 100644
--- a/js/test/mopidy-test.js
+++ b/js/test/mopidy-test.js
@@ -1,4 +1,10 @@
-/*global buster:false, assert:false, refute:false, when:false, Mopidy:false*/
+/*global require:false, assert:false, refute:false*/
+
+if (typeof module === "object" && typeof require === "function") {
+ var buster = require("buster");
+ var Mopidy = require("../src/mopidy").Mopidy;
+ var when = require("when");
+}
buster.testCase("Mopidy", {
setUp: function () {
@@ -14,10 +20,11 @@ buster.testCase("Mopidy", {
fakeWebSocket.OPEN = 1;
fakeWebSocket.CLOSING = 2;
fakeWebSocket.CLOSED = 3;
- this.realWebSocket = WebSocket;
- window.WebSocket = fakeWebSocket;
- this.webSocketConstructorStub = this.stub(window, "WebSocket");
+ this.realWebSocket = Mopidy.WebSocket;
+ Mopidy.WebSocket = fakeWebSocket;
+
+ this.webSocketConstructorStub = this.stub(Mopidy, "WebSocket");
this.webSocket = {
close: this.stub(),
@@ -27,15 +34,18 @@ buster.testCase("Mopidy", {
},
tearDown: function () {
- window.WebSocket = this.realWebSocket;
+ Mopidy.WebSocket = this.realWebSocket;
},
"constructor": {
"connects when autoConnect is true": function () {
new Mopidy({autoConnect: true});
+ var currentHost = typeof document !== "undefined" &&
+ document.location.host || "localhost";
+
assert.calledOnceWith(this.webSocketConstructorStub,
- "ws://" + document.location.host + "/mopidy/ws/");
+ "ws://" + currentHost + "/mopidy/ws/");
},
"does not connect when autoConnect is false": function () {
@@ -67,12 +77,15 @@ buster.testCase("Mopidy", {
mopidy.connect();
+ var currentHost = typeof document !== "undefined" &&
+ document.location.host || "localhost";
+
assert.calledOnceWith(this.webSocketConstructorStub,
- "ws://" + document.location.host + "/mopidy/ws/");
+ "ws://" + currentHost + "/mopidy/ws/");
},
"does nothing when the WebSocket is open": function () {
- this.webSocket.readyState = WebSocket.OPEN;
+ this.webSocket.readyState = Mopidy.WebSocket.OPEN;
var mopidy = new Mopidy({webSocket: this.webSocket});
mopidy.connect();
@@ -367,7 +380,7 @@ buster.testCase("Mopidy", {
},
"immediately rejects request if CONNECTING": function (done) {
- this.mopidy._webSocket.readyState = WebSocket.CONNECTING;
+ this.mopidy._webSocket.readyState = Mopidy.WebSocket.CONNECTING;
var promise = this.mopidy._send({method: "foo"});
@@ -381,7 +394,7 @@ buster.testCase("Mopidy", {
},
"immediately rejects request if CLOSING": function (done) {
- this.mopidy._webSocket.readyState = WebSocket.CLOSING;
+ this.mopidy._webSocket.readyState = Mopidy.WebSocket.CLOSING;
var promise = this.mopidy._send({method: "foo"});
@@ -395,7 +408,7 @@ buster.testCase("Mopidy", {
},
"immediately rejects request if CLOSED": function (done) {
- this.mopidy._webSocket.readyState = WebSocket.CLOSED;
+ this.mopidy._webSocket.readyState = Mopidy.WebSocket.CLOSED;
var promise = this.mopidy._send({method: "foo"});
diff --git a/mopidy/frontends/http/__init__.py b/mopidy/frontends/http/__init__.py
index ab8dff42..3be4993e 100644
--- a/mopidy/frontends/http/__init__.py
+++ b/mopidy/frontends/http/__init__.py
@@ -128,8 +128,8 @@ you quickly started with working on your client instead of figuring out how to
communicate with Mopidy.
-Getting the library
--------------------
+Getting the library for browser use
+-----------------------------------
Regular and minified versions of Mopidy.js, ready for use, is installed
together with Mopidy. When the HTTP frontend is running, the files are
@@ -154,6 +154,25 @@ the Git repo at:
- ``mopidy/frontends/http/data/mopidy.js``
- ``mopidy/frontends/http/data/mopidy.min.js``
+
+Getting the library for Node.js use
+-----------------------------------
+
+If you want to use Mopidy.js from Node.js instead of a browser, you can install
+Mopidy.js using npm::
+
+ npm install mopidy
+
+After npm completes, you can import Mopidy.js using ``require()``:
+
+.. code-block:: js
+
+ var Mopidy = require("mopidy").Mopidy;
+
+
+Getting the library for development on the library
+--------------------------------------------------
+
If you want to work on the Mopidy.js library itself, you'll find a complete
development setup in the ``js/`` dir in our repo. The instructions in
``js/README.rst`` will guide you on your way.
@@ -170,8 +189,8 @@ Once you got Mopidy.js loaded, you need to create an instance of the wrapper:
When you instantiate ``Mopidy()`` without arguments, it will connect to
the WebSocket at ``/mopidy/ws/`` on the current host. Thus, if you don't host
-your web client using Mopidy's web server, you'll need to pass the URL to the
-WebSocket end point:
+your web client using Mopidy's web server, or if you use Mopidy.js from a
+Node.js environment, you'll need to pass the URL to the WebSocket end point:
.. code-block:: js