You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by js...@apache.org on 2009/03/19 12:24:20 UTC
svn commit: r755931 [1/9] - in
/camel/trunk/components/camel-web/src/main/webapp/js/bespin: ./ client/
cmd/ editor/ mobwrite/ page/ page/dashboard/ page/editor/ page/index/
syntax/ user/ util/
Author: jstrachan
Date: Thu Mar 19 11:24:18 2009
New Revision: 755931
URL: http://svn.apache.org/viewvc?rev=755931&view=rev
Log:
added Bespin support for editing routes for CAMEL-1355 - which includes adding Bespin & Dojo JS libraries. Sorry for the big commit :)
Added:
camel/trunk/components/camel-web/src/main/webapp/js/bespin/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/bespin.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/filesystem.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/server.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/session.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/settings.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/status.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commandline.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commands.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/dashboardcommands.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/editorcommands.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/Component.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/actions.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/clipboard.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/cursor.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/editor.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/embed.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/events.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/filelist.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/model.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/quickopen.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/themes.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/toolbar.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/undo.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/events.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/mobwrite/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/mobwrite/core.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/mobwrite/diff.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/mobwrite/form.js
camel/trunk/components/camel-web/src/main/webapp/js/bespin/mobwrite/integrate.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/dashboard/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/dashboard/components.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/dashboard/dependencies.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/dashboard/events.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/dashboard/init.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/editor/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/editor/dependencies.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/editor/init.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/index/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/index/dependencies.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/page/index/init.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/syntax/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/syntax/arduino.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/syntax/css.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/syntax/html.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/syntax/javascript.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/syntax/php.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/syntax/syntax.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/user/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/user/dependencies.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/user/register.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/user/utils.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/util/
camel/trunk/components/camel-web/src/main/webapp/js/bespin/util/canvas.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/util/keys.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/util/mousewheelevent.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/util/navigate.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/util/path.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/util/tokenobject.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/util/urlbar.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/util/util.js (with props)
camel/trunk/components/camel-web/src/main/webapp/js/bespin/util/webpieces.js (with props)
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/bespin.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/bespin.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/bespin.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/bespin.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,113 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is Bespin.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Bespin Team (bespin@mozilla.com)
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// = Bespin =
+//
+// This is the root of it all. The {{{ bespin }}} namespace.
+// All of the JavaScript for Bespin will be placed in this namespace later.
+//
+// {{{ bespin.versionNumber }}} is the core version of the Bespin system
+// {{{ bespin.apiVersion }}} is the version number of the API (to ensure that the
+// client and server are talking the same language)
+// {{{ bespin.displayVersion }}} is a function that sets innerHTML on the element given, with the Bespin version info
+//
+// {{{ bespin.publish }}} maps onto dojo.publish but lets us abstract away for the future
+// {{{ bespin.subscribe }}} maps onto dojo.subscribe but lets us abstract away for the future
+// {{{ bespin.unsubscribe }}} maps onto dojo.unsubscribe but lets us abstract away for the future
+//
+// {{{ bespin.register }}} is the way to attach components into the bespin system for others to get out
+// {{{ bespin.get }}} allows you to get registered components out
+// {{{ bespin.withComponent }}} maps onto dojo.subscribe but lets us abstract away for the future
+
+dojo.provide("bespin.bespin");
+
+dojo.mixin(bespin, {
+ // BEGIN VERSION BLOCK
+ versionNumber: 'tip',
+ versionCodename: 'DEVELOPMENT MODE',
+ apiVersion: 'dev',
+ // END VERSION BLOCK
+
+ defaultTabSize: 4,
+ userSettingsProject: "BespinSettings",
+
+ // == Methods for tying to the event bus
+
+ // ** {{{ publish }}} **
+ //
+ // Given a topic and a set of parameters, publish onto the bus
+ publish: function(topic, args) {
+ dojo.publish(topic, dojo.isArray(args) ? args : [ args || {} ]);
+ },
+
+ // ** {{{ subscribe }}} **
+ //
+ // Given a topic and a function, subscribe to the event
+ subscribe: dojo.subscribe,
+
+ // ** {{{ unsubscribe }}} **
+ //
+ // Unsubscribe the functions from the topic
+ unsubscribe: dojo.unsubscribe,
+
+ // == Methods for registering components with the main system
+ registeredComponents: {},
+
+ // ** {{{ register }}} **
+ //
+ // Given an id and an object, register it inside of Bespin
+ register: function(id, object) {
+ bespin.publish("bespin:component:register", { id: id, object: object });
+
+ this.registeredComponents[id] = object;
+
+ return object;
+ },
+
+ // ** {{{ get }}} **
+ //
+ // Given an id return the component
+ get: function(id) {
+ return this.registeredComponents[id];
+ },
+
+ // ** {{{ withComponent }}} **
+ //
+ // Given an id, and function to run, execute it if the component is available
+ withComponent: function(id, func) {
+ var component = this.get(id);
+ if (component) {
+ return func(component);
+ }
+ },
+
+ // ** {{{ displayVersion }}} **
+ //
+ // Given an HTML element
+ displayVersion: function(el) {
+ var el = dojo.byId(el) || dojo.byId("version");
+ if (!el) return;
+ el.innerHTML = '<a href="https://wiki.mozilla.org/Labs/Bespin/ReleaseNotes" title="Read the release notes">Version <span class="versionnumber">' + this.versionNumber + '</span> "' + this.versionCodename + '"</a>';
+ }
+});
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/bespin.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/filesystem.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/filesystem.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/filesystem.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/filesystem.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,225 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is Bespin.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Bespin Team (bespin@mozilla.com)
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// = FileSystem =
+//
+// This abstracts the remote Web Service file system, and in the future
+// local file systems too.
+//
+// It ties into the {{{bespin.client.Server}}} object for remote access
+
+dojo.provide("bespin.client.filesystem");
+
+dojo.declare("bespin.client.FileSystem", null, {
+ constructor: function(server) {
+ this.server = server || bespin.get('server');
+ },
+
+ // ** {{{ bespin.client.FileSystem.newFile(project, path, callback) }}}
+ //
+ // Create a new file in the file system using:
+ //
+ // * {{{project}}} is the name of the project to create the file in
+ // * {{{path}}} is the full path to save the file into
+ // * {{{onSuccess}}} is a callback to fire if the file is created
+ newFile: function(project, path, onSuccess) {
+ this.whenFileDoesNotExist(project, path, {
+ execute: function() {
+ bespin.get('editSession').startSession(project, path || "new.txt");
+ onSuccess();
+ },
+ elseFailed: function() {
+ bespin.publish("bespin:cmdline:showinfo", { msg: 'The file ' + path + ' already exists my friend.'});
+ }
+ });
+ },
+
+ // ** {{{ bespin.client.FileSystem.loadFile(project, path, callback) }}}
+ //
+ // Load the file in the given project and path and get going
+ //
+ // * {{{project}}} is the name of the project that houses the file
+ // * {{{path}}} is the full path to load the file into
+ // * {{{onSuccess}}} is a callback to fire if the file is loaded
+ // * {{{dontStartSession}}} is a flag to turn off starting a session. Used in the config loading for example
+ loadFile: function(project, path, onSuccess, dontStartSession) {
+ if (!dontStartSession) bespin.get('editSession').startSession(project, path);
+
+ this.server.loadFile(project, path, function(content) {
+ if (/\n$/.test(content)) content = content.substr(0, content.length - 1);
+
+ onSuccess({
+ name: path,
+ content: content,
+ timestamp: new Date().getTime()
+ });
+ });
+ },
+
+ // ** {{{ bespin.client.FileSystem.forceOpenFile(project, path, content) }}}
+ //
+ // With the given project and path, open a file if existing, else create a new one
+ //
+ // * {{{project}}} is the name of the project to create the file in
+ // * {{{path}}} is the full path to save the file into
+ // * {{{content}}} is the template initial content to put in the new file (if new)
+ forceOpenFile: function(project, path, content) {
+ this.whenFileDoesNotExist(project, path, {
+ execute: function() {
+ if (!content) content = " ";
+ bespin.publish("bespin:editor:newfile", {
+ project: project,
+ newfilename: path,
+ content: content
+ });
+ },
+ elseFailed: function() {
+ bespin.publish("bespin:editor:openfile", {
+ project: project,
+ filename: path
+ });
+ }
+ });
+ },
+
+ // ** {{{ FileSystem.projects(callback) }}}
+ //
+ // Return a JSON representation of the projects that the user has access too
+ //
+ // * {{{callback}}} is a callback that fires given the project list
+ projects: function(callback) {
+ this.server.projects(callback);
+ },
+
+ // ** {{{ bespin.client.FileSystem.fileNames(callback) }}}
+ //
+ // Return a JSON representation of the files at the root of the given project
+ //
+ // * {{{callback}}} is a callback that fires given the files
+ fileNames: function(project, callback) {
+ this.server.list(project, '', callback);
+ },
+
+ // ** {{{ bespin.client.FileSystem.saveFile(project, file) }}}
+ //
+ // Save a file to the given project
+ //
+ // * {{{project}}} is the name of the project to save into
+ // * {{{file}}} is the file object that contains the path and content to save
+ saveFile: function(project, file) {
+ // Unix files should always have a trailing new-line; add if not present
+ if (/\n$/.test(file.content)) file.content += "\n";
+
+ this.server.saveFile(project, file.name, file.content, file.lastOp);
+ },
+
+ // ** {{{ bespin.client.FileSystem.removeFile(project, path, onSuccess, onFailure) }}}
+ //
+ // Create a directory
+ //
+ // * {{{project}}} is the name of the directory to create
+ // * {{{path}}} is the full path to the directory to create
+ // * {{{onSuccess}}} is the callback to fire if the make works
+ // * {{{onFailure}}} is the callback to fire if the make fails
+ makeDirectory: function(project, path, onSuccess, onFailure) {
+ this.server.makeDirectory(project, path, onSuccess, onFailure);
+ },
+
+ // ** {{{ bespin.client.FileSystem.makeDirectory(project, path, onSuccess, onFailure) }}}
+ //
+ // Remove a directory
+ //
+ // * {{{project}}} is the name of the directory to remove
+ // * {{{path}}} is the full path to the directory to delete
+ // * {{{onSuccess}}} is the callback to fire if the remove works
+ // * {{{onFailure}}} is the callback to fire if the remove fails
+ removeDirectory: function(project, path, onSuccess, onFailure) {
+ this.server.removeFile(project, path, onSuccess, onFailure);
+ },
+
+ // ** {{{ bespin.client.FileSystem.removeFile(project, path, onSuccess, onFailure) }}}
+ //
+ // Remove the file from the file system
+ //
+ // * {{{project}}} is the name of the project to delete the file from
+ // * {{{path}}} is the full path to the file to delete
+ // * {{{onSuccess}}} is the callback to fire if the remove works
+ // * {{{onFailure}}} is the callback to fire if the remove fails
+ removeFile: function(project, path, onSuccess, onFailure) {
+ this.server.removeFile(project, path, onSuccess, onFailure);
+ },
+
+ // ** {{{ bespin.client.FileSystem.removeFile(project, path, onSuccess, onFailure) }}}
+ //
+ // Close the open session for the file
+ //
+ // * {{{project}}} is the name of the project to close the file from
+ // * {{{path}}} is the full path to the file to close
+ // * {{{callback}}} is the callback to fire when closed
+ closeFile: function(project, path, callback) {
+ this.server.closeFile(project, path, callback);
+ },
+
+ // ** {{{ bespin.client.FileSystem.whenFileExists(project, path, callbacks) }}}
+ //
+ // Check to see if the file exists and then run the appropriate callback
+ //
+ // * {{{project}}} is the name of the project
+ // * {{{path}}} is the full path to the file
+ // * {{{callbacks}}} is the pair of callbacks:
+ // execute (file exists)
+ // elseFailed (file does not exist)
+ whenFileExists: function(project, path, callbacks) {
+ this.server.list(project, bespin.util.path.directory(path), function(files) {
+ if (files && dojo.some(files, function(file){ return (file.name == path); })) {
+ callbacks['execute']();
+ } else {
+ if (callbacks['elseFailed']) callbacks['elseFailed']();
+ }
+ }, function(xhr) {
+ if (callbacks['elseFailed']) callbacks['elseFailed'](xhr);
+ });
+ },
+
+ // ** {{{ bespin.client.FileSystem.whenFileDoesNotExist(project, path, callbacks) }}}
+ //
+ // The opposite of {{{ bespin.client.FileSystem.whenFileExists() }}}
+ //
+ // * {{{project}}} is the name of the project
+ // * {{{path}}} is the full path to the file
+ // * {{{callbacks}}} is the pair of callbacks:
+ // execute (file does not exist)
+ // elseFailed (file exists)
+ whenFileDoesNotExist: function(project, path, callbacks) {
+ this.server.list(project, bespin.util.path.directory(path), function(files) {
+ if (!files || !dojo.some(files, function(file){ return (file.name == path); })) {
+ callbacks['execute']();
+ } else {
+ if (callbacks['elseFailed']) callbacks['elseFailed']();
+ }
+ }, function(xhr) {
+ callbacks['execute'](); // the list failed which means it didn't exist
+ });
+ }
+});
\ No newline at end of file
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/filesystem.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/server.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/server.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/server.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/server.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,522 @@
+dojo.provide("bespin.client.server");
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is Bespin.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Bespin Team (bespin@mozilla.com)
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// = Server =
+//
+// The Server object implements the [[https://wiki.mozilla.org/BespinServerAPI|Bespin Server API]]
+// giving the client access to the backend store. The {{{FileSystem}}} object uses this to talk back.
+
+dojo.declare("bespin.client.Server", null, {
+ // ** {{{ initialize(base) }}}
+ //
+ // Object creation initialization
+ //
+ // * {{{base}}} is the base server URL to access
+ constructor: function(base) {
+ this.SERVER_BASE_URL = base || '';
+ },
+
+ // == Helpers ==
+
+ // ** {{{ request(method, url, payload, callbackOptions) }}}
+ //
+ // The core way to access the backend system.
+ // Similar to the Prototype Ajax.Request wrapper
+ //
+ // * {{{method}}} is the HTTP method (GET|POST|PUT|DELETE)
+ // * {{{url}}} is the sub url to hit (after the base url)
+ // * {{{payload}}} is what to send up for POST requests
+ // * {{{options}}} is how you pass in various callbacks.
+ // options['evalJSON'] = true or false to auto eval
+ // options['call'] = the main callback
+ // options['log'] = just log the following
+ // options['onFailure'] = call for general failures
+ // options['on' + STATUS CODE] = call for specific failures
+ request: function(method, url, payload, options) {
+ var xhr = new XMLHttpRequest();
+
+ if (location.href.indexOf("file:") == 0){ // if developing and using this locally only!
+ try {
+ if (netscape.security.PrivilegeManager.enablePrivilege) {
+ netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
+ }
+ } catch (ex) {
+ }
+ }
+
+ if (options) { // do it async (best)
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState == 4) {
+ if (xhr.status && xhr.status != 0 && (xhr.status >= 200 && xhr.status < 300)) {
+ var response = xhr.responseText;
+
+ if (options['evalJSON'] && response) {
+ try {
+ response = dojo.fromJson(response);
+ } catch (syntaxException) {
+ console.log("Couldn't eval the JSON: " + response + " (SyntaxError: " + syntaxException + ")");
+ }
+ }
+
+ if (dojo.isFunction(options['call'])) {
+ options['call'](response, xhr);
+ } else if (options['log']) {
+ console.log(options['log']);
+ }
+ } else {
+ var onStatus = 'on' + xhr.status;
+ if (options[onStatus]) {
+ options[onStatus](xhr);
+ } else if (options['onFailure']) {
+ options['onFailure'](xhr);
+ }
+ }
+ }
+ };
+ xhr.open(method, this.SERVER_BASE_URL + url, true); // url must have leading /
+ xhr.setRequestHeader("Content-Type", 'application/x-www-form-urlencoded');
+ if (options.headers) {
+ for (var key in options.headers) {
+ if (options.headers.hasOwnProperty(key)) {
+ xhr.setRequestHeader(key, options.headers[key]);
+ }
+ }
+ }
+ xhr.send(payload);
+ } else {
+ var fullUrl = this.SERVER_BASE_URL + url;
+ console.log("Are you sure you want to do a synchronous Ajax call? Really? " + fullUrl);
+ xhr.open(method, fullUrl, false);
+ xhr.send(payload);
+ return xhr.responseText;
+ }
+ },
+
+ // == USER ==
+
+ // ** {{{ login(user, pass, token, callback, notloggedin) }}}
+ //
+ // Try to login to the backend system.
+ //
+ // * {{{user}}} is the username
+ // * {{{pass}}} is the password
+ // * {{{onSuccess}}} fires when the user is logged in
+ // * {{{onFailure}}} fires when the user failed to login
+ login: function(user, pass, token, onSuccess, onFailure) {
+ var url = "/register/login/" + user;
+ this.request('POST', url, "password=" + escape(pass), {
+ call: onSuccess,
+ on401: onFailure,
+ log: 'Login complete.',
+ headers: { 'DoubleSubmitCookie':token }
+ });
+ },
+
+ // ** {{{ signup(user, pass, email, callback, notloggedin, userconflict) }}}
+ //
+ // Signup / Register the user to the backend system
+ //
+ // * {{{user}}} is the username
+ // * {{{pass}}} is the password
+ // * {{{email}}} is the email
+ // * {{{onSuccess}}} fires when the user is logged in
+ // * {{{notloggedin}}} fires when not logged in
+ // * {{{userconflict}}} fires when the username exists
+ signup: function(user, pass, email, onSuccess, notloggedin, userconflict) {
+ var url = "/register/new/" + user;
+ this.request('POST', url,
+ "password=" + escape(pass) + "&email=" + escape(email), {
+ call: onSuccess, on401: notloggedin, on409: userconflict,
+ log: 'Login complete.'
+ });
+ },
+
+ // ** {{{ logout(callback) }}}
+ //
+ // Logout from the backend
+ //
+ // * {{{callback}}} fires after the logout attempt
+ logout: function(callback) {
+ var url = "/register/logout/";
+ this.request('POST', url, null, { log: 'Logout complete.', call: callback });
+ },
+
+ // ** {{{ currentuser(callback, notloggedin) }}}
+ //
+ // Return info on the current logged in user
+ //
+ // * {{{callback}}} fires after the user attempt
+ // * {{{notloggedin}}} fires if the user isn't logged in
+ currentuser: function(callback, notloggedin) {
+ var url = "/register/userinfo/";
+ return this.request('GET', url, null,
+ { call: callback, on401: notloggedin, evalJSON: true });
+ },
+
+ // == FILES ==
+
+ // ** {{{ list(project, path, onSuccess, onFailure) }}}
+ //
+ // List the path in the given project
+ //
+ // * {{{project}}} is the project to list
+ // * {{{path}}} is the path to list out
+ // * {{{onSuccess}}} fires if the list returns something
+ // * {{{onFailure}}} fires if there is an error getting a list from the server
+ list: function(project, path, onSuccess, onFailure) {
+ var project = project || '';
+ var url = bespin.util.path.combine('/file/list/', project, path || '/');
+ var opts = { call: onSuccess, evalJSON: true, log: "Listing files in: " + url };
+ if (dojo.isFunction(onFailure)) opts.onFailure = onFailure;
+
+ this.request('GET', url, null, opts);
+ },
+
+ // ** {{{ projects(callback) }}}
+ //
+ // Return the list of projects that you have access too
+ //
+ // * {{{callback}}} gets fired with the project list
+ projects: function(callback) {
+ this.request('GET', '/file/list/', null, { call: callback, evalJSON: true });
+ },
+
+ // ** {{{ saveFile(project, path, contents, lastOp) }}}
+ //
+ // Save the given file
+ //
+ // * {{{project}}} is the project to save
+ // * {{{path}}} is the path to save to
+ // * {{{callback}}} fires after the save returns
+ // * {{{lastOp}}} contains the last edit operation
+ saveFile: function(project, path, contents, lastOp) {
+ if (!project || !path) return;
+
+ var url = bespin.util.path.combine('/file/at', project, (path || ''));
+ if (lastOp) url += "?lastEdit=" + lastOp;
+
+ this.request('PUT', url, contents, { log: 'Saved file.' });
+ },
+
+ // ** {{{ loadFile(project, path, contents) }}}
+ //
+ // Load the given file
+ //
+ // * {{{project}}} is the project to load from
+ // * {{{path}}} is the path to load
+ // * {{{callback}}} fires after the file is loaded
+ loadFile: function(project, path, callback) {
+ var project = project || '';
+ var path = path || '';
+ var url = bespin.util.path.combine('/file/at', project, path);
+
+ this.request('GET', url, null, { call: callback });
+ },
+
+ // ** {{{ removeFile(project, path, onSuccess, onFailure) }}}
+ //
+ // Remove the given file
+ //
+ // * {{{project}}} is the project to remove from
+ // * {{{path}}} is the path to remove
+ // * {{{onSuccess}}} fires if the deletion works
+ // * {{{onFailure}}} fires if the deletion failed
+ removeFile: function(project, path, onSuccess, onFailure) {
+ var project = project || '';
+ var path = path || '';
+ var url = bespin.util.path.combine('/file/at', project, path);
+ var opts = { call: onSuccess };
+ if (dojo.isFunction(onFailure)) opts.onFailure = onFailure;
+
+ this.request('DELETE', url, null, opts);
+ },
+
+ // ** {{{ makeDirectory(project, path, onSuccess, onFailure) }}}
+ //
+ // Create a new directory
+ //
+ // * {{{project}}} is the project to save
+ // * {{{path}}} is the path to save to
+ // * {{{onSuccess}}} fires if the deletion works
+ // * {{{onFailure}}} fires if the deletion failed
+ makeDirectory: function(project, path, onSuccess, onFailure) {
+ if (!project) return;
+
+ var url = bespin.util.path.combineAsDirectory('/file/at', project, (path || ''));
+ var opts = {};
+ if (dojo.isFunction(onSuccess)) {
+ opts.call = onSuccess;
+ } else {
+ opts['log'] = "Made a directory: [project=" + project + ", path=" + path + "]";
+ }
+ if (dojo.isFunction(onFailure)) opts.onFailure = onFailure;
+
+ this.request('PUT', url, null, opts);
+ },
+
+ // ** {{{ removeDirectory(project, path, onSuccess, onFailure) }}}
+ //
+ // Removed a directory
+ //
+ // * {{{project}}} is the project to save
+ // * {{{path}}} is the path to save to
+ // * {{{onSuccess}}} fires if the deletion works
+ // * {{{onFailure}}} fires if the deletion failed
+ removeDirectory: function(project, path, onSuccess, onFailure) {
+ if (!project) return;
+ if (!path) path = '';
+
+ var url = bespin.util.path.combineAsDirectory('/file/at', project, path);
+ var opts = {};
+ if (dojo.isFunction(onSuccess)) {
+ opts.call = onSuccess;
+ } else {
+ opts['log'] = "Removed directory: [project=" + project + ", path=" + path + "]";
+ }
+ if (dojo.isFunction(onFailure)) opts.onFailure = onFailure;
+
+ this.request('DELETE', url, null, opts);
+ },
+
+ // ** {{{ listOpen(callback) }}}
+ //
+ // Returns JSON with the key of filename, and the value of an array of usernames:
+ // { "foo.txt": ["ben"], "SomeAjaxApp/foo.txt": ["dion"] }
+ //
+ // * {{{callback}}} fires after listing the open files
+ listOpen: function(callback) {
+ this.request('GET', '/file/listopen/', null, {
+ call: callback, evalJSON: true, log: 'List open files.'
+ });
+ },
+
+ // ** {{{ closeFile(project, path, callback) }}}
+ //
+ // Close the given file (remove from open sessions)
+ //
+ // * {{{project}}} is the project to close from
+ // * {{{path}}} is the path to close
+ // * {{{callback}}} fires after the file is closed
+ closeFile: function(project, path, callback) {
+ var path = path || '';
+ var url = bespin.util.path.combine('/file/close', project, path);
+ this.request('POST', url, null, { call: callback });
+ },
+
+ // ** {{{ searchFiles(project, searchstring, callback) }}}
+ //
+ // Search for files within the given project
+ //
+ // * {{{project}}} is the project to look from
+ // * {{{searchstring}}} to compare files with
+ // * {{{callback}}} fires after the file is closed
+ searchFiles: function(project, searchkey, callback) {
+ var url = bespin.util.path.combine('/file/search', project+'?q='+escape(searchkey));
+ var opts = { call: callback, evalJSON: true, log: "Listing searchfiles for: " + project + ", searchkey: " + searchkey};
+ this.request('GET', url, null, opts);
+ },
+
+ // == EDIT ==
+
+ // ** {{{ editActions(project, path, callback) }}}
+ //
+ // Get the list of edit actions
+ //
+ // * {{{project}}} is the project to edit from
+ // * {{{path}}} is the path to edit
+ // * {{{callback}}} fires after the edit is done
+ editActions: function(project, path, callback) {
+ var path = path || '';
+ var url = bespin.util.path.combine('/edit/list', project, path);
+ this.request('GET', url, null, { call: callback, log: "Edit Actions Complete." });
+ },
+
+ // ** {{{ editAfterActions(project, path, callback) }}}
+ //
+ // Get the list of edit after actions
+ //
+ // * {{{project}}} is the project to edit from
+ // * {{{path}}} is the path to edit
+ // * {{{callback}}} fires after the edit is done
+ editAfterActions: function(project, path, index, callback) {
+ var path = path || '';
+ var url = bespin.util.path.combine('/edit/recent', index, project, path);
+ this.request('GET', url, null, { call: callback, log: "Edit After Actions Complete." });
+ },
+
+ // ** {{{ doAction(project, path, actions) }}}
+ //
+ // Store actions to the edit queue
+ //
+ // * {{{project}}} is the project
+ // * {{{path}}} is the path
+ // * {{{actions}}} contain the actions to store
+ doAction: function(project, path, actions) {
+ var path = path || '';
+ var url = bespin.util.path.combine('/edit', project, path);
+
+ var sp = "[" + actions.join(",") + "]";
+
+ this.request('PUT', url, sp, { call: function(){} });
+ },
+
+ // == PROJECTS ==
+ //
+ // still needed: owners, authorize, deauthorize
+
+ // ** {{{ exportProject(project, archivetype) }}}
+ //
+ // Export the project as either a zip file or tar + gz
+ //
+ // * {{{project}}} is the project to export
+ // * {{{archivetype}}} is either zip | tgz
+ exportProject: function(project, archivetype) {
+ if (bespin.util.include(['zip','tgz','tar.gz'], archivetype)) {
+// console.log('/project/export', project + "." + archivetype);
+ var iframe = document.createElement("iframe");
+ iframe.src = bespin.util.path.combine('/project/export', project + "." + archivetype);
+ iframe.style.display = 'none';
+ iframe.style.height = iframe.style.width = "0";
+ document.getElementsByTagName("body")[0].appendChild(iframe);
+ }
+ },
+
+ // ** {{{ importProject(project, url, opts) }}}
+ //
+ // Import the given file into the given project
+ //
+ // * {{{project}}} is the project to export
+ // * {{{url}}} is the URL to the file to import
+ // * {{{archivetype}}} is either zip | tgz
+ importProject: function(project, url, opts) {
+ if (opts) { // wrap the import success call in an event to say that the import is complete
+ var userCall = opts.call;
+ opts.call = function(text, xhr) {
+ userCall(text, xhr);
+ bespin.publish("bespin:project:imported", {
+ project: project,
+ url: url
+ });
+ };
+ }
+
+ this.request('POST', '/project/fromurl/' + project, url, opts || {});
+ },
+
+ // ** {{{ renameProject(currentProject, newProject) }}}
+ //
+ // Import the given file into the given project
+ //
+ // * {{{currentProject}}} is the current name of the project
+ // * {{{newProject}}} is the new name
+ renameProject: function(currentProject, newProject, opts) {
+ if (!opts) opts = { log: "Renaming project from " + currentProject + " to " + newProject };
+ if (currentProject && newProject) {
+ this.request('POST', '/project/rename/' + currentProject + "/", newProject, opts);
+ }
+ },
+
+ // == SETTINGS ==
+ //
+ //
+ // * GET /settings/ to list all settings for currently logged in user as json dict
+ // * GET /settings/[setting] to get the value for a single setting as json string
+ // * POST /settings/ with HTTP POST DATA (in standard form post syntax) to set the value for a collection of settings (all values are strings)
+ // * DELETE /settings/[setting] to delete a single setting
+
+ listSettings: function(callback) {
+ if (typeof callback == "function") {
+ this.request('GET', '/settings/', null, { call: callback, evalJSON: true });
+ }
+ },
+
+ getSetting: function(name, callback) {
+ if (typeof callback == "function") {
+ this.request('GET', '/settings/' + name, null, { call: callback });
+ }
+ },
+
+ setSetting: function(name, value, callback) {
+ var settings = {};
+ settings[name] = value;
+ this.setSettings(settings, (callback || function(){}));
+ },
+
+ setSettings: function(settings, callback) {
+ this.request('POST', '/settings/', dojo.objectToQuery(settings), { call: (callback || function(){}) });
+ },
+
+ unsetSetting: function(name, callback) {
+ this.request('DELETE', '/settings/' + name, null, { call: (callback || function(){}) });
+ },
+
+ // ** {{{ follows(opts) }}}
+ // Get a list of the users the current user is following
+ followers: function(opts) {
+ this.request('GET', '/network/followers/', null, opts || {});
+ },
+
+ // ** {{{ follows(opts) }}}
+ // Get a list of the users the current user is following
+ follow: function(users, opts) {
+ this.request('POST', '/network/follow/', dojo.toJson(users), opts || {});
+ },
+
+ // ** {{{ follows(opts) }}}
+ // Get a list of the users the current user is following
+ unfollow: function(users, opts) {
+ this.request('POST', '/network/unfollow/', dojo.toJson(users), opts || {});
+ },
+
+ // ** {{{ groupListAll() }}}
+ // Get a list of the users the current user is following
+ groupListAll: function(opts) {
+ this.request('GET', '/group/list/all/', null, opts || {});
+ },
+
+ // ** {{{ groupList() }}}
+ // Get a list of the users the current user is following
+ groupList: function(group, opts) {
+ this.request('GET', '/group/list/' + group + '/', null, opts || {});
+ },
+
+ // ** {{{ groupRemoveAll() }}}
+ // Get a list of the users the current user is following
+ groupRemoveAll: function(group, opts) {
+ this.request('POST', '/group/remove/all/' + group + '/', null, opts || {});
+ },
+
+ // ** {{{ groupAdd() }}}
+ // Get a list of the users the current user is following
+ groupAdd: function(group, users, opts) {
+ this.request('POST', '/group/remove/' + group + '/', dojo.toJson(users), opts || {});
+ },
+
+ // ** {{{ groupRemove() }}}
+ // Get a list of the users the current user is following
+ groupRemove: function(group, users, opts) {
+ this.request('POST', '/group/add/' + group + '/', dojo.toJson(users), opts || {});
+ }
+});
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/server.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/session.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/session.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/session.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/session.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,77 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is Bespin.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Bespin Team (bespin@mozilla.com)
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// = Session =
+//
+// This session module provides functionality that both stores session information
+// and handle collaboration.
+//
+// This module includes:
+//
+// * {{{ bespin.client.session.EditSession }}}: Wraps a file edit session
+// * {{{ bespin.client.session.SyncHelper }}}: Deals with syncing edits back to the server
+
+dojo.provide("bespin.client.session");
+
+// ** {{{ bespin.client.session.EditSession }}} **
+//
+// EditSession represents a file edit session with the Bespin back-end server. It is responsible for
+// sending changes to the server as well as receiving changes from the server and mutating the document
+// model with received changes.
+
+dojo.declare("bespin.client.session.EditSession", null, {
+ constructor: function(editor) {
+ this.editor = editor;
+ this.collaborate = false;
+ },
+
+ setUserinfo: function(userinfo) {
+ this.username = userinfo.username;
+ this.amountUsed = userinfo.amountUsed;
+ this.quota = userinfo.quota;
+ },
+
+ checkSameFile: function(project, path) {
+ return ((this.project == project) && (this.path == path));
+ },
+
+ startSession: function(project, path, username) {
+ this.project = project;
+ this.path = path;
+ if (!this.username) this.username = username;
+
+ if (this.collaborate) {
+ // Extreme suckage: This starts a sync session with the server.
+ // All it's really doing is talking to a sync service which is totally
+ // separate from the file storage API. They need merging, and then we
+ // should be able to ditch whatever loads the text into the editor
+ mobwrite.share(bespin.get('editSession'));
+ }
+ },
+
+ stopSession: function() {
+ this.project = undefined;
+ this.path = undefined;
+ }
+});
\ No newline at end of file
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/session.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/settings.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/settings.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/settings.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/settings.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,561 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is Bespin.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Bespin Team (bespin@mozilla.com)
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+dojo.provide("bespin.client.settings");
+
+// = Settings =
+//
+// This settings module provides a base implementation to store settings for users.
+// It also contains various "stores" to save that data, including:
+//
+// * {{{bespin.client.settings.Core}}} : Core interface to settings. User code always goes through here.
+// * {{{bespin.client.settings.Server}}} : The main store. Saves back to the Bespin Server API
+// * {{{bespin.client.settings.InMemory}}} : In memory settings that are used primarily for debugging
+// * {{{bespin.client.settings.Cookie}}} : Store in a cookie using cookie-jar
+// * {{{bespin.client.settings.URL}}} : Intercept settings in the URL. Often used to override
+// * {{{bespin.client.settings.DB}}} : Commented out for now, but a way to store settings locally
+// * {{{bespin.client.settings.Events}}} : Custom events that the settings store can intercept and send
+
+// ** {{{ bespin.client.settings.Core }}} **
+//
+// Handles load/save of user settings.
+// TODO: tie into the sessions servlet; eliminate Gears dependency
+
+dojo.declare("bespin.client.settings.Core", null, {
+ constructor: function(store) {
+ this.browserOverrides = {};
+ this.fromURL = new bespin.client.settings.URL();
+ this.customEvents = new bespin.client.settings.Events(this);
+
+ this.loadStore(store); // Load up the correct settings store
+ },
+
+ loadSession: function() {
+ var path = this.fromURL.get('path') || this.get('_path');
+ var project = this.fromURL.get('project') || this.get('_project');
+
+ bespin.publish("bespin:settings:init", { // -- time to init my friends
+ path: path,
+ project: project
+ });
+ },
+
+ defaultSettings: function() {
+ return {
+ 'tabsize': '2',
+ 'fontsize': '10',
+ 'autocomplete': 'off',
+ 'collaborate': 'off',
+ 'syntax': 'auto'
+ };
+ },
+
+ isOn: function(value) {
+ return value == 'on' || value == 'true';
+ },
+
+ isOff: function(value) {
+ return value == 'off' || value == 'false';
+ },
+
+ isSettingOn: function(key) {
+ return this.isOn(this.get(key));
+ },
+
+ isSettingOff: function(key) {
+ return this.isOff(this.get(key));
+ },
+
+ // ** {{{ Settings.loadStore() }}} **
+ //
+ // This is where we choose which store to load
+ loadStore: function(store) {
+ this.store = new (store || bespin.client.settings.Server)(this);
+
+// this.store = new Bespin.Settings.Cookie(this);
+
+// TODO: ignore gears for now:
+// this.store = (window['google']) ? new Bespin.Settings.DB : new Bespin.Settings.InMemory;
+// this.store = new Bespin.Settings.InMemory;
+ },
+
+ toList: function() {
+ var settings = [];
+ var storeSettings = this.store.settings;
+ for (var prop in storeSettings) {
+ if (storeSettings.hasOwnProperty(prop)) {
+ settings.push({ 'key': prop, 'value': storeSettings[prop] });
+ }
+ }
+ return settings;
+ },
+
+ set: function(key, value) {
+ this.store.set(key, value);
+
+ bespin.publish("bespin:settings:set:" + key, { value: value });
+ },
+
+ get: function(key) {
+ var fromURL = this.fromURL.get(key); // short circuit
+ if (fromURL) return fromURL;
+
+ return this.store.get(key);
+ },
+
+ unset: function(key) {
+ this.store.unset(key);
+ },
+
+ list: function() {
+ if (typeof this.store['list'] == "function") {
+ return this.store.list();
+ } else {
+ return this.toList();
+ }
+ }
+
+});
+
+// ** {{{ bespin.client.settings.InMemory }}} **
+//
+// Debugging in memory settings (die when browser is closed)
+
+dojo.declare("bespin.client.settings.InMemory", null, {
+ constructor: function(parent) {
+ this.parent = parent;
+
+ this.settings = this.parent.defaultSettings();
+
+ bespin.publish("bespin:settings:loaded");
+ },
+
+ set: function(key, value) {
+ this.settings[key] = value;
+ },
+
+ get: function(key) {
+ return this.settings[key];
+ },
+
+ unset: function(key) {
+ delete this.settings[key];
+ }
+});
+
+// ** {{{ bespin.client.settings.Cookie }}} **
+//
+// Save the settings in a cookie
+
+dojo.declare("bespin.client.settings.Cookie", null, {
+ constructor: function(parent) {
+ var expirationInHours = 1;
+ this.cookieSettings = {
+ expires: expirationInHours / 24,
+ path: '/'
+ };
+
+ var settings = dojo.fromJson(dojo.cookie("settings"));
+
+ if (settings) {
+ this.settings = settings;
+ } else {
+ this.settings = {
+ 'tabsize': '2',
+ 'fontsize': '10',
+ 'autocomplete': 'off',
+ 'collaborate': 'off',
+ '_username': 'dion'
+ };
+ dojo.cookie("settings", dojo.toJson(this.settings), this.cookieSettings);
+ }
+ bespin.publish("bespin:settings:loaded");
+ },
+
+ set: function(key, value) {
+ this.settings[key] = value;
+ dojo.cookie("settings", dojo.toJson(this.settings), this.cookieSettings);
+ },
+
+ get: function(key) {
+ return this.settings[key];
+ },
+
+ unset: function(key) {
+ delete this.settings[key];
+ dojo.cookie("settings", dojo.toJson(this.settings), this.cookieSettings);
+ }
+});
+
+// ** {{{ bespin.client.settings.Server }}} **
+//
+// The real grand-daddy that implements uses {{{Server}}} to access the backend
+
+dojo.declare("bespin.client.settings.Server", null, {
+ constructor: function(parent) {
+ this.parent = parent;
+ this.server = bespin.get('server');
+
+ // TODO: seed the settings
+ this.server.listSettings(dojo.hitch(this, function(settings) {
+ this.settings = settings;
+ if (settings['tabsize'] === undefined) {
+ this.settings = this.parent.defaultSettings();
+ this.server.setSettings(this.settings);
+ }
+ bespin.publish("bespin:settings:loaded");
+ }));
+ },
+
+ set: function(key, value) {
+ this.settings[key] = value;
+ this.server.setSetting(key, value);
+ },
+
+ get: function(key) {
+ return this.settings[key];
+ },
+
+ unset: function(key) {
+ delete this.settings[key];
+ this.unsetSetting(key);
+ }
+});
+
+
+// ** {{{ bespin.client.settings.DB }}} **
+//
+// Taken out for now to allow us to not require gears_db.js (and Gears itself).
+// Experimental ability to save locally in the SQLite database.
+// The plan is to migrate to ActiveRecord.js or something like it to abstract on top
+// of various stores (HTML5, Gears, globalStorage, etc.)
+
+/*
+// turn off for now so we can take gears_db.js out
+
+Bespin.Settings.DB = Class.create({
+ initialize: function(parent) {
+ this.parent = parent;
+ this.db = new GearsDB('wideboy');
+
+ //this.db.run('drop table settings');
+ this.db.run('create table if not exists settings (' +
+ 'id integer primary key,' +
+ 'key varchar(255) unique not null,' +
+ 'value varchar(255) not null,' +
+ 'timestamp int not null)');
+
+ this.db.run('CREATE INDEX IF NOT EXISTS settings_id_index ON settings (id)');
+ bespin.publish("bespin:settings:loaded");
+ },
+
+ set: function(key, value) {
+ this.db.forceRow('settings', { 'key': key, 'value': value, timestamp: new Date().getTime() }, 'key');
+ },
+
+ get: function(key) {
+ var rs = this.db.run('select distinct value from settings where key = ?', [ key ]);
+ try {
+ if (rs && rs.isValidRow()) {
+ return rs.field(0);
+ }
+ } catch (e) {
+ console.log(e.message);
+ } finally {
+ rs.close();
+ }
+ },
+
+ unset: function(key) {
+ this.db.run('delete from settings where key = ?', [ key ]);
+ },
+
+ list: function() {
+ // TODO: Need to override with browser settings
+ return this.db.selectRows('settings', '1=1');
+ },
+
+ // -- Private-y
+ seed: function() {
+ this.db.run('delete from settings');
+
+ // TODO: loop through the settings
+ this.db.run('insert into settings (key, value, timestamp) values (?, ?, ?)', ['keybindings', 'emacs', 1183878000000]);
+ this.db.run('insert into settings (key, value, timestamp) values (?, ?, ?)', ['tabsize', '2', 1183878000000]);
+ this.db.run('insert into settings (key, value, timestamp) values (?, ?, ?)', ['fontsize', '10', 1183878000000]);
+ this.db.run('insert into settings (key, value, timestamp) values (?, ?, ?)', ['autocomplete', 'off', 1183878000000]);
+ }
+});
+*/
+
+// ** {{{ bespin.client.settings.URL }}} **
+//
+// Grab the setting from the URL, either via # or ?
+
+dojo.declare("bespin.client.settings.URL", null, {
+ constructor: function(queryString) {
+ this.results = dojo.queryToObject(this.stripHash(queryString || window.location.hash));
+ },
+
+ get: function(key) {
+ return this.results[key];
+ },
+
+ set: function(key, value) {
+ this.results[key] = value;
+ },
+
+ stripHash: function(url) {
+ var tobe = url.split('');
+ tobe.shift();
+ return tobe.join('');
+ }
+});
+
+// ** {{{ bespin.client.settings.Events }}} **
+//
+// Custom Event holder for the Settings work.
+// It deals with both settings themselves, and other events that
+// settings need to watch and look for
+
+dojo.declare("bespin.client.settings.Events", null, {
+ constructor: function(settings) {
+ var editSession = bespin.get('editSession');
+ var editor = bespin.get('editor');
+
+ // ** {{{ Event: bespin:settings:set }}} **
+ //
+ // Watch for someone wanting to do a set operation
+ bespin.subscribe("bespin:settings:set", function(event) {
+ var key = event.key;
+ var value = event.value;
+
+ settings.set(key, value);
+ });
+
+ // ** {{{ Event: bespin:editor:openfile:opensuccess }}} **
+ //
+ // Change the session settings when a new file is opened
+ bespin.subscribe("bespin:editor:openfile:opensuccess", function(event) {
+ var file = event.file;
+
+ editSession.path = file.name;
+
+ settings.set('_project', editSession.project);
+ settings.set('_path', editSession.path);
+ settings.set('_username', editSession.username);
+
+ if (editSession.syncHelper) editSession.syncHelper.syncWithServer();
+ });
+
+ // ** {{{ Event: bespin:editor:openfile:opensuccess }}} **
+ //
+ // Change the syntax highlighter when a new file is opened
+ bespin.subscribe("bespin:editor:openfile:opensuccess", function(event) {
+ var file = event.file;
+ var split = file.name.split('.');
+ var type = split[split.length - 1];
+
+ if (type) {
+ bespin.publish("bespin:settings:syntax", { language: type });
+ }
+ });
+
+ // ** {{{ Event: bespin:settings:set:syntax }}} **
+ //
+ // When the syntax setting is changed, tell the syntax system to change
+ bespin.subscribe("bespin:settings:set:syntax", function(event) {
+ bespin.publish("bespin:settings:syntax", { language: event.value, fromCommand: true });
+ });
+
+ // ** {{{ Event: bespin:settings:syntax }}} **
+ //
+ // Given a new syntax command, change the editor.language
+ bespin.subscribe("bespin:settings:syntax", function(event) {
+ var language = event.language;
+ var fromCommand = event.fromCommand;
+ var syntaxSetting = settings.get('syntax') || "off";
+
+ if (language == editor.language) return; // already set to be that language
+
+ if (bespin.util.include(['auto', 'on'], language)) {
+ var split = window.location.hash.split('.');
+ var type = split[split.length - 1];
+ if (type) editor.language = type;
+ } else if (bespin.util.include(['auto', 'on'], syntaxSetting) || fromCommand) {
+ editor.language = language;
+ } else if (syntaxSetting == 'off') {
+ editor.language = 'off';
+ }
+ });
+
+ // ** {{{ Event: bespin:settings:set:collaborate }}} **
+ //
+ // Turn on the collaboration system if set to be on
+ bespin.subscribe("bespin:settings:set:collaborate", function(event) {
+ editSession.collaborate = settings.isOn(event.value);
+ });
+
+ // ** {{{ Event: bespin:settings:set:fontsize }}} **
+ //
+ // Change the font size for the editor
+ bespin.subscribe("bespin:settings:set:fontsize", function(event) {
+ var fontsize = parseInt(event.value);
+ editor.theme.lineNumberFont = fontsize + "pt Monaco, Lucida Console, monospace";
+ });
+
+ // ** {{{ Event: bespin:settings:set:theme }}} **
+ //
+ // Change the Theme object used by the editor
+ bespin.subscribe("bespin:settings:set:theme", function(event) {
+ var theme = event.value;
+
+ if (theme) {
+ var themeSettings = bespin.themes[theme];
+
+ if (themeSettings) {
+ if (themeSettings != editor.theme) {
+ editor.theme = themeSettings;
+ }
+ } else {
+ bespin.publish("bespin:cmdline:showinfo", {
+ msg: "Sorry old chap. No theme called '" + theme + "'. Fancy making it?"
+ });
+ }
+ }
+ });
+
+ // ** {{{ Event: bespin:settings:set:keybindings }}} **
+ //
+ // Add in emacs key bindings
+ bespin.subscribe("bespin:settings:set:keybindings", function(event) {
+ var value = event.value;
+
+ if (value == "emacs") {
+ bespin.publish("bespin:editor:bindkey", {
+ modifiers: "ctrl",
+ key: "b",
+ action: "moveCursorLeft"
+ });
+
+ bespin.publish("bespin:editor:bindkey", {
+ modifiers: "ctrl",
+ key: "f",
+ action: "moveCursorRight"
+ });
+
+ bespin.publish("bespin:editor:bindkey", {
+ modifiers: "ctrl",
+ key: "p",
+ action: "moveCursorUp"
+ });
+
+ bespin.publish("bespin:editor:bindkey", {
+ modifiers: "ctrl",
+ key: "n",
+ action: "moveCursorDown"
+ });
+
+ bespin.publish("bespin:editor:bindkey", {
+ modifiers: "ctrl",
+ key: "a",
+ action: "moveToLineStart"
+ });
+
+ bespin.publish("bespin:editor:bindkey", {
+ modifiers: "ctrl",
+ key: "e",
+ action: "moveToLineEnd"
+ });
+ }
+ });
+
+ // ** {{{ Event: bespin:settings:set:cursorblink }}} **
+ //
+ // The frequency of the cursor blink in milliseconds (defaults to 250)
+ bespin.subscribe("bespin:settings:set:cursorblink", function(event) {
+ var ms = parseInt(event.value); // get the number of milliseconds
+
+ if (ms) {
+ editor.ui.toggleCursorFrequency = ms;
+ }
+ });
+
+ // ** {{{ Event: bespin:settings:init }}} **
+ //
+ // If we are opening up a new file
+ bespin.subscribe("bespin:settings:init", function(event) {
+ var path = event.path;
+ var project = event.project;
+
+ // TODO: use the action and don't run a command itself
+ var newfile = settings.fromURL.get('new');
+ if (!newfile) { // scratch file
+ if (project && (editSession.project != project)) {
+ bespin.publish("bespin:project:set", { project: project });
+ }
+
+ if (path) {
+ bespin.publish("bespin:editor:openfile", { filename: path });
+ }
+ }
+ });
+
+ // ** {{{ Event: bespin:settings:init }}} **
+ //
+ // Setup the theme
+ bespin.subscribe("bespin:settings:init", function(event) {
+ bespin.publish("bespin:settings:set:theme", {
+ value: settings.get('theme')
+ });
+ });
+
+ // ** {{{ Event: bespin:settings:init }}} **
+ //
+ // Setup the special keybindings
+ bespin.subscribe("bespin:settings:init", function(event) {
+ bespin.publish("bespin:settings:set:keybindings", {
+ value: settings.get('keybindings')
+ });
+ });
+
+ // ** {{{ Event: bespin:settings:init }}} **
+ //
+ // Check for auto load
+ bespin.subscribe("bespin:settings:init", function(event) {
+ if (settings.isOn(settings.get('autoconfig'))) {
+ bespin.publish("bespin:editor:config:run");
+ }
+ });
+
+ // ** {{{ Event: bespin:settings:init }}} **
+ //
+ // Setup the font size that the user has configured
+ bespin.subscribe("bespin:settings:init", function(event) {
+ bespin.publish("bespin:settings:set:fontsize", {
+ value: settings.get('fontsize')
+ });
+ });
+ }
+});
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/settings.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/status.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/status.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/status.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/status.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,68 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is Bespin.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Bespin Team (bespin@mozilla.com)
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+dojo.provide("bespin.client.status");
+
+// = StatusChecker =
+//
+// This is currently just a mock to randomly share status messages.
+// In the future the server will serve up interesting data.
+// For now, it is turned off.
+
+dojo.declare("bespin.client.settings.StatusChecker", null, {
+ constructor: function() {
+ this.interval = 0;
+ this.statusMessages = [
+ "Bob is editing the file brick.html",
+ "Emily is creating a new tag called 'v3.4'",
+ "Jessica is saving the file kidly.html",
+ "John is idle. Lazy git!",
+ "Mickey has checked in a set of 4 files to project 'Bank'",
+ "Don has created the function 'doCalculation' in class 'Bank'",
+ "Benji is deleting the function 'doCalculation' in class 'Bank'"
+ ];
+ },
+
+ start: function() {
+ this.interval = setInterval(dojo.hitch(this, "updateStatus"), 12000);
+ },
+
+ stop: function() {
+ clearInterval(this.interval);
+ },
+
+ updateStatus: function() {
+ var randomMessage = this.randomStatus();
+ this.setStatus(randomMessage);
+ },
+
+ randomStatus: function() {
+ var random = Math.floor(Math.random() * this.statusMessages.length);
+ return this.statusMessages[random];
+ },
+
+ setStatus: function(message) {
+ dojo.byId('message').innerHTML = message;
+ }
+});
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/client/status.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commandline.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commandline.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commandline.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commandline.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,512 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The Original Code is Bespin.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Bespin Team (bespin@mozilla.com)
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// = Command Line =
+//
+// This command line module provides everything that the command line interface needs:
+//
+// * {{{bespin.cmd.commandline.Interface}}} : The base class itself. The actually interface.
+// * {{{bespin.cmd.commandline.KeyBindings}}} : Handling the special key handling in the command line
+// * {{{bespin.cmd.commandline.History}}} : Handle command line history
+// * {{{bespin.cmd.commandline.SimpleHistoryStore}}} : Simple one session storage of history
+// * {{{bespin.cmd.commandline.Events}}} : The custom events that the command line needs to handle
+
+dojo.provide("bespin.cmd.commandline");
+
+// ** {{{ bespin.cmd.commandline.Interface }}} **
+//
+// The core command line driver. It executes commands, stores them, and handles completion
+
+dojo.declare("bespin.cmd.commandline.Interface", null, {
+ constructor: function(commandLine, initCommands) {
+ this.commandLine = dojo.byId(commandLine);
+
+ if (bespin.get('files')) this.files = bespin.get('files');
+ if (bespin.get('settings')) this.settings = bespin.get('settings');
+ if (bespin.get('editor')) this.editor = bespin.get('editor');
+
+ this.inCommandLine = false;
+ this.suppressInfo = false; // When true, info bar popups will not be shown
+ this.commands = {};
+ this.aliases = {};
+
+ this.commandLineKeyBindings = new bespin.cmd.commandline.KeyBindings(this);
+ this.commandLineHistory = new bespin.cmd.commandline.History(this);
+ this.customEvents = new bespin.cmd.commandline.Events(this);
+
+ if (initCommands) this.addCommands(initCommands); // initialize the commands for the cli
+ },
+
+ executeCommand: function(value) {
+ var data = value.split(/\s+/);
+ var commandname = data.shift();
+
+ var command;
+ var argstr = data.join(' ');
+
+ if (this.commands[commandname]) {
+ command = this.commands[commandname];
+ } else if (this.aliases[commandname]) {
+ var alias = this.aliases[commandname].split(' ');
+ var aliascmd = alias.shift();
+ if (alias.length > 0) {
+ argstr = alias.join(' ') + ' ' + argstr;
+ }
+ command = this.commands[aliascmd];
+ } else {
+ this.showInfo("Sorry, no command '" + commandname + "'. Maybe try to run » help", true);
+ return;
+ }
+
+ bespin.publish("bespin:cmdline:executed", { command: command, args: argstr });
+
+ command.execute(this, this.getArgs(argstr.split(' '), command));
+ this.commandLine.value = ''; // clear after the command
+ },
+
+ addCommand: function(command) {
+ // -- Allow for the default [ ] takes style by expanding it to something bigger
+ if (command.takes && dojo.isArray(command.takes)) {
+ command = this.normalizeTakes(command);
+ }
+
+ // -- Add bindings
+ if (command.withKey) {
+ var args = bespin.util.keys.fillArguments(command.withKey);
+
+ args.action = "bespin:cmdline:execute;name=" + command.name;
+ bespin.publish("bespin:editor:bindkey", args);
+ }
+
+ this.commands[command.name] = command;
+
+ if (command['aliases']) {
+ dojo.forEach(command['aliases'], function(alias) {
+ this.aliases[alias] = command.name;
+ }, this);
+ }
+ },
+
+ addCommands: function(commands) {
+ dojo.forEach(commands, dojo.hitch(this, function(command) {
+ if (dojo.isString(command)) command = bespin.cmd.commands.get(command);
+ this.addCommand(command);
+ }));
+
+ },
+
+ hasCommand: function(commandname) {
+ if (this.commands[commandname]) { // yup, there she blows. shortcut
+ return true;
+ }
+
+ for (command in this.commands) { // try the aliases
+ if (this.commands[command]['aliases']) {
+ if (bespin.util.include(this.commands[command]['aliases'], commandname)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+
+ showUsage: function(command, autohide) {
+ var usage = command.usage || "no usage information found for " + command.name;
+ this.showInfo("Usage: " + command.name + " " + usage, autohide);
+ },
+
+ showInfo: function(html, autohide) {
+ if (this.suppressInfo) return; // bypass
+
+ this.hideInfo();
+
+ dojo.byId('info').innerHTML = html;
+ dojo.style('info', 'display', 'block');
+ dojo.connect(dojo.byId('info'), "onclick", this, "hideInfo");
+
+ if (autohide) {
+ this.infoTimeout = setTimeout(dojo.hitch(this, function() {
+ this.hideInfo();
+ }), 4600);
+ }
+ },
+
+ hideInfo: function() {
+ dojo.style('info', 'display', 'none');
+ if (this.infoTimeout) clearTimeout(this.infoTimeout);
+ },
+
+ findCompletions: function(value) {
+ var matches = [];
+
+ if (value.length > 0) {
+ for (var command in this.commands) {
+ if (command.indexOf(value) == 0) {
+ matches.push(command);
+ }
+ }
+
+ for (var alias in this.aliases) {
+ if (alias.indexOf(value) == 0) {
+ matches.push(alias);
+ }
+ }
+ }
+
+ return matches;
+ },
+
+ complete: function(value) {
+ var matches = this.findCompletions(value);
+ if (matches.length == 1) {
+ var commandLineValue = matches[0];
+
+ var command = this.commands[matches[0]];
+
+ if (command) {
+ if (this.commandTakesArgs(command)) {
+ commandLineValue += ' ';
+ }
+
+ if (command['completeText']) {
+ this.showInfo(command['completeText']);
+ }
+
+ if (command['complete']) {
+ this.showInfo(command.complete(this, value));
+ }
+ } else { // an alias
+ this.showInfo(commandLineValue + " is an alias for: " + this.aliases[commandLineValue]);
+ commandLineValue += ' ';
+ }
+ this.commandLine.value = commandLineValue;
+ }
+ },
+
+ commandTakesArgs: function(command) {
+ return command.takes != undefined;
+ },
+
+ // ** {{{ getArgs }}} **
+ //
+ // Calculate the args object to be passed into the command.
+ // If it only takes one argument just send in that data, but if it wants more, split it all up for the command and send in an object.
+
+ getArgs: function(fromUser, command) {
+ if (!command.takes) return undefined;
+
+ var args;
+ var userString = fromUser.join(' ');
+
+ if (command.takes && command.takes.order.length < 2) { // One argument, so just return that
+ args = userString;
+ } else {
+ args = new bespin.util.TokenObject(userString, { params: command.takes.order.join(' ') });
+ args.rawinput = userString;
+ }
+ return args;
+ },
+
+ normalizeTakes: function(command) {
+ // TODO: handle shorts that are the same! :)
+ var takes = command.takes;
+ command.takes = {
+ order: takes
+ };
+
+ dojo.forEach(takes, function(item) {
+ command.takes[item] = {
+ "short": item[0]
+ };
+ });
+
+ return command;
+ },
+
+ handleCommandLineFocus: function(e) {
+ if (this.inCommandLine) return true; // in the command line!
+
+ if (e.keyChar == 'j' && e.ctrlKey) { // send to command line
+ this.commandLine.focus();
+
+ dojo.stopEvent(e);
+ return true;
+ }
+ }
+
+});
+
+// ** {{{ bespin.cmd.commandline.KeyBindings }}} **
+//
+// Handle key bindings for the command line
+
+dojo.declare("bespin.cmd.commandline.KeyBindings", null, {
+ constructor: function(cl) {
+ // -- Tie to the commandLine element itself
+ dojo.connect(cl.commandLine, "onfocus", cl, function() {
+ bespin.publish("bespin:cmdline:focus");
+
+ this.inCommandLine = true;
+ dojo.byId('promptimg').src = 'images/icn_command_on.png';
+ });
+ dojo.connect(cl.commandLine, "onblur", cl, function() {
+ this.inCommandLine = false;
+ dojo.byId('promptimg').src = 'images/icn_command.png';
+ });
+
+ dojo.connect(cl.commandLine, "onkeyup", cl, function(e) {
+ var command;
+ if (e.keyChar >= "A".charCodeAt() && e.keyChar < "Z".charCodeAt()) { // only real letters
+ var completions = this.findCompletions(dojo.byId('command').value);
+ var commandString = completions[0];
+ if (completions.length > 0) {
+ var isAutoComplete = bespin.get('settings').isSettingOn('autocomplete');
+ if (isAutoComplete && completions.length == 1) { // if only one just set the value
+ command = this.commands[commandString] || this.commands[this.aliases[commandString]];
+
+ var spacing = (this.commandTakesArgs(command)) ? ' ' : '';
+ dojo.byId('command').value = commandString + spacing;
+
+ if (command['completeText']) {
+ this.showInfo(command['completeText']);
+ } else {
+ this.hideInfo();
+ }
+ } else if (completions.length == 1) {
+ if (completions[0] != dojo.byId('command').value) {
+ this.showInfo(completions.join(', '));
+ } else {
+ command = this.commands[completions[0]] || this.commands[this.aliases[completions[0]]];
+
+ if (this.commandTakesArgs(command)) {
+ this.complete(dojo.byId('command').value); // make it complete
+ } else {
+ this.hideInfo();
+ }
+ }
+ } else {
+ this.showInfo(completions.join(', '));
+ }
+ }
+ }
+ });
+
+ dojo.connect(cl.commandLine, "onkeypress", cl, function(e) {
+ if (e.keyChar == 'j' && e.ctrlKey) { // send back
+ dojo.stopEvent(e);
+
+ dojo.byId('command').blur();
+
+ bespin.publish("bespin:cmdline:blur");
+
+ return false;
+ } else if ((e.keyChar == 'n' && e.ctrlKey) || e.keyCode == dojo.keys.DOWN_ARROW) {
+ this.commandLineHistory.setNext();
+ return false;
+ } else if ((e.keyChar == 'p' && e.ctrlKey) || e.keyCode == dojo.keys.UP_ARROW) {
+ this.commandLineHistory.setPrevious();
+ return false;
+ } else if (e.keyCode == dojo.keys.ENTER) {
+ this.executeCommand(dojo.byId('command').value);
+
+ return false;
+ } else if (e.keyCode == dojo.keys.TAB) {
+ dojo.stopEvent(e);
+
+ this.complete(dojo.byId('command').value);
+ return false;
+ } else if (e.keyCode == dojo.keys.ESCAPE) {
+ this.hideInfo();
+ }
+ });
+ }
+});
+
+// ** {{{ bespin.cmd.commandline.History }}} **
+//
+// Store command line history so you can go back and forth
+
+dojo.declare("bespin.cmd.commandline.History", null, {
+ constructor: function(cl) {
+ this.commandLine = cl;
+ this.history = [];
+ this.pointer = 0;
+ this.store = new bespin.cmd.commandline.SimpleHistoryStore();
+ this.seed();
+ },
+
+ // TODO: get from the database
+ seed: function() {
+ this.history = this.store.seed();
+ },
+
+ add: function(command) {
+ command = dojo.trim(command);
+ if (this.last() != command) {
+ this.store.add(command);
+ this.history.push(command);
+ this.pointer = this.history.length - 1;
+ }
+ },
+
+ next: function() {
+ if (this.pointer < this.history.length) {
+ return this.history[this.pointer++];
+ }
+ },
+
+ previous: function() {
+ if (this.pointer > 0) {
+ return this.history[this.pointer--];
+ }
+ },
+
+ last: function() {
+ return this.history[this.history.length - 1];
+ },
+
+ first: function() {
+ return this.history[0];
+ },
+
+ set: function(command) {
+ this.commandLine.commandLine.value = command;
+ },
+
+ setNext: function() {
+ var next = this.next();
+ if (next) {
+ this.set(next);
+ }
+ },
+
+ setPrevious: function() {
+ var prev = this.previous();
+ if (prev) {
+ this.set(prev);
+ }
+ }
+});
+
+// ** {{{ bespin.cmd.commandline.SimpleHistoryStore }}} **
+//
+// A simple store that keeps the commands in memory.
+// In the future we would want to store the history cross session.
+
+dojo.declare("bespin.cmd.commandline.SimpleHistoryStore", null, {
+ constructor: function() {
+ this.commands = [];
+ },
+
+ seed: function() {
+ this.add('ls');
+ this.add('clear');
+ this.add('status');
+
+ return dojo.clone(this.commands);
+ },
+
+ add: function(command) {
+ this.commands.push(command);
+ }
+});
+
+// ** {{{ bespin.cmd.commandline.Events }}} **
+//
+// The custom events that the commandline participates in
+
+dojo.declare("bespin.cmd.commandline.Events", null, {
+ constructor: function(commandline) {
+ // ** {{{ Event: bespin:cmdline:showinfo }}} **
+ //
+ // Observe when others want to show the info bar for the command line
+ bespin.subscribe("bespin:cmdline:showinfo", function(event) {
+ var msg = event.msg;
+ var autohide = event.autohide;
+ if (msg) commandline.showInfo(msg, autohide);
+ });
+
+ // ** {{{ Event: bespin:cmdline:suppressinfo }}} **
+ //
+ // Turn on info bar suppression
+ bespin.subscribe("bespin:cmdline:suppressinfo", function(event) {
+ commandline.suppressInfo = true;
+ });
+
+ // ** {{{ Event: bespin:cmdline:unsuppressinfo }}} **
+ //
+ // Turn off info bar suppression
+ bespin.subscribe("bespin:cmdline:unsuppressinfo", function(event) {
+ commandline.suppressInfo = false;
+ });
+
+ // ** {{{ Event: bespin:cmdline:executed }}} **
+ //
+ // Once the command has been executed, do something.
+ // In this case, save it for the history
+ bespin.subscribe("bespin:cmdline:executed", function(event) {
+ commandline.commandLineHistory.add(event.command.name + " " + event.args); // only add to the history when a valid command
+ });
+
+ // ** {{{ Event: bespin:cmdline:executed }}} **
+ //
+ // Once the command has been executed, do something.
+ bespin.subscribe("bespin:cmdline:execute", function(event) {
+ var command = event.name;
+ var args = event.args;
+ if (command && args) { // if we have a command and some args
+ command += " " + args;
+ }
+
+ if (command) commandline.executeCommand(command);
+ });
+
+ // -- Files
+ // ** {{{ Event: bespin:editor:openfile:openfail }}} **
+ //
+ // If an open file action failed, tell the user.
+ bespin.subscribe("bespin:editor:openfile:openfail", function(event) {
+ commandline.showInfo('Could not open file: ' + event.filename + "<br/><br/><em>(maybe try » list)</em>");
+ });
+
+ // ** {{{ Event: bespin:editor:openfile:opensuccess }}} **
+ //
+ // The open file action worked, so tell the user
+ bespin.subscribe("bespin:editor:openfile:opensuccess", function(event) {
+ commandline.showInfo('Loaded file: ' + event.file.name, true);
+ });
+
+ // -- Projects
+ // ** {{{ Event: bespin:project:set }}} **
+ //
+ // When the project changes, alert the user
+ bespin.subscribe("bespin:project:set", function(event) {
+ var project = event.project;
+
+ bespin.get('editSession').project = project;
+ if (!event.suppressPopup) commandline.showInfo('Changed project to ' + project, true);
+ });
+
+ }
+});
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commandline.js
------------------------------------------------------------------------------
svn:eol-style = native