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 [2/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/
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commands.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commands.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commands.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commands.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,1049 @@
+/* ***** 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.cmd.commands");
+
+// = Commands =
+//
+// This array stores all of the default commands.
+
+// ** {{{bespin.cmd.commands.store}}} **
+//
+// The core store to hold commands that others share.
+bespin.cmd.commands.store = {};
+
+// ** {{{bespin.cmd.commands.add}}} **
+//
+// Add the command to the store which has a name -> command hash
+bespin.cmd.commands.add = function(command) {
+ bespin.cmd.commands.store[command.name] = command;
+};
+
+// ** {{{bespin.cmd.commands.get}}} **
+//
+// Return a command from the store
+bespin.cmd.commands.get = function(commandname) {
+ return bespin.cmd.commands.store[commandname];
+};
+
+// ** {{{Command: bespin.cmd.commands.toArgArray}}} **
+// Helper for when you have a command that needs to get a hold of it's params
+// as an array for processing
+bespin.cmd.commands.toArgArray = function(args) {
+ if (args == null) {
+ return [];
+ }
+ else {
+ var spliten = args.split(" ");
+ if (spliten.length == 1 && spliten[0] == "") {
+ return [];
+ }
+ else {
+ return spliten;
+ }
+ }
+};
+
+// == Start adding commands to the store ==
+//
+
+// ** {{{Command: help}}} **
+bespin.cmd.commands.add({
+ name: 'help',
+ takes: ['search'],
+ preview: 'show commands',
+ description: 'The <u>help</u> gives you access to the various commands in the Bespin system.<br/><br/>You can narrow the search of a command by adding an optional search params.<br/><br/>If you pass in the magic <em>hidden</em> parameter, you will find subtle hidden commands.<br/><br/>Finally, pass in the full name of a command and you can get the full description, which you just did to see this!',
+ completeText: 'optionally, narrow down the search',
+ execute: function(self, extra) {
+ var commands = [];
+ var command, name;
+
+ if (self.commands[extra]) { // caught a real command
+ commands.push("<u>Help for the command: <em>" + extra + "</em></u><br/>");
+ command = self.commands[extra];
+ commands.push(command['description'] ? command.description : command.preview);
+ } else {
+ var showHidden = false;
+ commands.push("<u>Commands Available</u><br/>");
+
+ if (extra) {
+ if (extra == "hidden") { // sneaky, sneaky.
+ extra = "";
+ showHidden = true;
+ }
+ commands.push("<em>(starting with</em> " + extra + " <em>)</em><br/>");
+ }
+
+ var tobesorted = [];
+ for (name in self.commands) {
+ tobesorted.push(name);
+ }
+
+ var sorted = tobesorted.sort();
+
+ for (var i = 0; i < sorted.length; i++) {
+ name = sorted[i];
+ command = self.commands[name];
+
+ if (!showHidden && command.hidden) continue;
+ if (extra && name.indexOf(extra) != 0) continue;
+
+ var args = (command.takes) ? ' [' + command.takes.order.join('] [') + ']' : '';
+ commands.push('<b>' + name + args + '</b>: ' + command.preview);
+ }
+ }
+ self.showInfo("<div style='font-size: 0.80em'>" + commands.join("<br/>") + "</div>");
+ }
+});
+
+// ** {{{Command: set}}} **
+bespin.cmd.commands.add({
+ name: 'set',
+ takes: ['key', 'value'],
+ preview: 'define and show settings',
+ completeText: 'optionally, add a key and/or a value, else you will see all settings',
+ // complete: function(self, value) {
+ // console.log(self);
+ // console.log(value);
+ // return value;
+ // },
+ execute: function(self, setting) {
+ var output;
+
+ if (!setting.key) { // -- show all
+ var settings = self.settings.list();
+
+ output = "<u>Your Settings</u><br/><br/>";
+ for (var x = 0; x < settings.length; x++) {
+ if (settings[x].key[0] != '_') {
+ output += settings[x].key + ": " + settings[x].value + "<br/>";
+ }
+ }
+ } else {
+ var key = setting.key;
+ if (setting.value === undefined) { // show it
+ var value = self.settings.get(key);
+ if (value) {
+ output = "<u>Your setting</u><br/><br/>";
+ output += key + ": " + value;
+ } else {
+ output = "You do not have a setting for <em>" + key + "</em>";
+ }
+ } else {
+ output = "<u>Saving setting</u><br/><br/>";
+ output += key + ": " + setting.value;
+ self.settings.set(key, setting.value);
+ }
+ }
+ self.showInfo(output);
+ }
+});
+
+// ** {{{Command: files (ls, list)}}} **
+bespin.cmd.commands.add({
+ name: 'files',
+ aliases: ['ls', 'list'],
+ takes: ['project'],
+ preview: 'show files',
+ completeText: 'optionally, add the project name of your choice',
+ execute: function(self, project) {
+ if (!project) {
+ bespin.withComponent('editSession', function(editSession) {
+ project = editSession.project;
+ });
+ }
+
+ if (!project) {
+ self.showInfo("You need to pass in a project");
+ return;
+ }
+
+ self.files.fileNames(project, function(fileNames) {
+ var files = "<u>Files in project: " + project + "</u><br/><br/>";
+ for (var x = 0; x < fileNames.length; x++) {
+ files += fileNames[x].name + "<br/>";
+ }
+ self.showInfo(files);
+ });
+ }
+});
+
+// ** {{{Command: status}}} **
+bespin.cmd.commands.add({
+ name: 'status',
+ preview: 'get info on the current project and file',
+ execute: function(self) {
+ bespin.publish("bespin:session:status");
+ }
+});
+
+// ** {{{Command: project}}} **
+bespin.cmd.commands.add({
+ name: 'project',
+ takes: ['projectname'],
+ preview: 'show the current project, or set to a new one',
+ completeText: 'optionally, add the project name to change to that project',
+ execute: function(self, projectname) {
+ if (projectname) {
+ bespin.publish("bespin:project:set", { project: projectname });
+ } else {
+ self.executeCommand('status');
+ }
+ }
+});
+
+// ** {{{Command: projects}}} **
+bespin.cmd.commands.add({
+ name: 'projects',
+ preview: 'show projects',
+ execute: function(self, extra) {
+ self.files.projects(function(projectNames) {
+ var projects = "<u>Your projects</u><br/><br/>";
+ for (var x = 0; x < projectNames.length; x++) {
+ projects += projectNames[x].name + "<br/>";
+ }
+ self.showInfo(projects);
+ });
+ }
+});
+
+// ** {{{Command: createproject}}} **
+bespin.cmd.commands.add({
+ name: 'createproject',
+ takes: ['projectname'],
+ preview: 'create a new project',
+ usage: '[newprojectname]',
+ execute: function(self, projectname) {
+ if (!projectname) {
+ self.showUsage(this);
+ return;
+ }
+ bespin.publish("bespin:project:create", { project: projectname });
+ }
+});
+
+// ** {{{Command: createproject}}} **
+bespin.cmd.commands.add({
+ name: 'deleteproject',
+ takes: ['projectname'],
+ preview: 'delete a new project',
+ usage: '[newprojectname]',
+ execute: function(self, projectname) {
+ if (!projectname) {
+ self.showUsage(this);
+ return;
+ }
+ bespin.publish("bespin:project:delete", { project: projectname });
+ }
+});
+
+// ** {{{Command: renameproject}}} **
+bespin.cmd.commands.add({
+ name: 'renameproject',
+ takes: ['currentProject', 'newProject'],
+ preview: 'rename a project',
+ usage: '[currentProject], [newProject]',
+ execute: function(self, args) {
+ if (!args.currentProject || !args.newProject) {
+ self.showUsage(this);
+ return;
+ }
+ bespin.publish("bespin:project:rename", { currentProject: args.currentProject, newProject: args.newProject });
+ }
+});
+
+// ** {{{Command: mkdir}}} **
+bespin.cmd.commands.add({
+ name: 'mkdir',
+ takes: ['path', 'projectname'],
+ preview: 'create a new directory in the given project',
+ usage: '[path] [projectname]',
+ execute: function(self, args) {
+ if (!args.path) {
+ self.showUsage(this);
+ return;
+ }
+
+ var opts = { path: args.path };
+ if (args.projectname) opts.project = args.projectname;
+
+ bespin.publish("bespin:directory:create", opts);
+ }
+});
+
+// ** {{{Command: save}}} **
+bespin.cmd.commands.add({
+ name: 'save',
+ takes: ['filename'],
+ preview: 'save the current contents',
+ completeText: 'add the filename to save as, or use the current file',
+ withKey: "CMD S",
+ execute: function(self, filename) {
+ bespin.publish("bespin:editor:savefile", {
+ filename: filename
+ });
+ }
+});
+
+// ** {{{Command: load (open)}}} **
+bespin.cmd.commands.add({
+ name: 'load',
+ aliases: ['open'],
+ takes: ['filename'],
+ preview: 'load up the contents of the file',
+ completeText: 'add the filename to open',
+ execute: function(self, filename) {
+ bespin.publish("bespin:editor:openfile", {
+ filename: filename
+ });
+ }
+});
+
+// ** {{{Command: preview}}} **
+bespin.cmd.commands.add({
+ name: 'preview',
+ takes: ['filename'],
+ preview: 'view the file in a new browser window',
+ completeText: 'add the filename to view or use the current file',
+ execute: function(self, filename) {
+ bespin.publish("bespin:editor:preview", {
+ filename: filename
+ });
+ }
+});
+
+// ** {{{Command: editconfig}}} **
+bespin.cmd.commands.add({
+ name: 'editconfig',
+ aliases: ['config'],
+ preview: 'load up the config file',
+ execute: function(self) {
+ bespin.publish("bespin:editor:config:edit");
+ }
+});
+
+// ** {{{Command: runconfig}}} **
+bespin.cmd.commands.add({
+ name: 'runconfig',
+ preview: 'run your config file',
+ execute: function(self) {
+ bespin.publish("bespin:editor:config:run");
+ }
+});
+
+// ** {{{Command: cmdload}}} **
+bespin.cmd.commands.add({
+ name: 'cmdload',
+ takes: ['commandname'],
+ preview: 'load up a new command',
+ completeText: 'command name to load (required)',
+ usage: '[commandname]: Command name required.',
+ execute: function(self, commandname) {
+ if (!commandname) {
+ self.showUsage(this);
+ return;
+ }
+ bespin.publish("bespin:commands:load", { commandname: commandname });
+ }
+});
+
+// ** {{{Command: cmdedit}}} **
+bespin.cmd.commands.add({
+ name: 'cmdedit',
+ takes: ['commandname'],
+ aliases: ['cmdadd'],
+ preview: 'edit the given command (force if doesn\'t exist',
+ completeText: 'command name to edit (required)',
+ usage: '[commandname]: Command name required.',
+ execute: function(self, commandname) {
+ if (!commandname) {
+ self.showUsage(this);
+ return;
+ }
+
+ bespin.publish("bespin:commands:edit", { commandname: commandname });
+ }
+});
+
+// ** {{{Command: cmdlist}}} **
+bespin.cmd.commands.add({
+ name: 'cmdlist',
+ preview: 'list my custom commands',
+ execute: function(self) {
+ bespin.publish("bespin:commands:list");
+ }
+});
+
+// ** {{{Command: cmdrm}}} **
+bespin.cmd.commands.add({
+ name: 'cmdrm',
+ takes: ['commandname'],
+ preview: 'delete a custom command',
+ completeText: 'command name to delete (required)',
+ usage: '[commandname]: Command name required.',
+ execute: function(self, commandname) {
+ if (!commandname) {
+ self.showUsage(this);
+ return;
+ }
+
+ bespin.publish("bespin:commands:delete", { commandname: commandname });
+ }
+});
+
+// ** {{{Command: newfile}}} **
+bespin.cmd.commands.add({
+ name: 'newfile',
+ //aliases: ['new'],
+ takes: ['filename', 'project'],
+ preview: 'create a new buffer for file',
+ completeText: 'optionally, name the new filename first, and then the name of the project second',
+ withKey: "CTRL SHIFT N",
+ execute: function(self, args) {
+ if (args.filename) {
+ args.newfilename = args.filename;
+ delete args.filename;
+ }
+ bespin.publish("bespin:editor:newfile", args || {});
+ }
+});
+
+// ** {{{Command: rm (remove, del)}}} **
+bespin.cmd.commands.add({
+ name: 'rm',
+ aliases: ['remove', 'del'],
+ takes: ['filename'],
+ preview: 'remove the file',
+ completeText: 'add the filename to remove',
+ execute: function(self, filename) {
+ var project = bespin.get('editSession').project;
+ if (!project) {
+ self.showInfo("rm only works with the project is set.");
+ return;
+ }
+
+ if (!filename) {
+ self.showInfo("give me a filename or directory to delete");
+ return;
+ }
+
+ self.files.removeFile(project, filename, function() {
+ if (bespin.get('editSession').checkSameFile(project, filename)) self.editor.model.clear(); // only clear if deleting the same file
+
+ self.showInfo('Removed file: ' + filename, true);
+ }, function(xhr) {
+ self.showInfo("Wasn't able to remove the file <b>" + filename + "</b><br/><em>Error</em> (probably doesn't exist): " + xhr.responseText);
+ });
+ }
+});
+
+// ** {{{Command: closefile}}} **
+bespin.cmd.commands.add({
+ name: 'closefile',
+ takes: ['filename', 'project'],
+ preview: 'close the file (may lose edits)',
+ completeText: 'add the filename to close (defaults to this file).<br>also, optional project name.',
+ execute: function(self, args) {
+ bespin.publish("bespin:editor:closefile", args);
+ }
+});
+
+// ** {{{Command: dashboard}}} **
+bespin.cmd.commands.add({
+ name: 'dashboard',
+ preview: 'navigate to the file',
+ execute: function(self) {
+ bespin.util.navigate.dashboard();
+ }
+});
+
+// ** {{{Command: version}}} **
+bespin.cmd.commands.add({
+ name: 'version',
+ takes: ['command'],
+ preview: 'show the version for Bespin or a command',
+ completeText: 'optionally, a command name',
+ execute: function(self, command) {
+ var bespinVersion = 'Your Bespin is at version ' + bespin.versionNumber + ', Code name: "' + bespin.versionCodename + '"';
+ var version;
+ if (command) {
+ var theCommand = self.commands[command];
+ if (!theCommand) {
+ version = "It appears that there is no command named '" + command + "', but " + bespinVersion;
+ } else {
+ version = (theCommand.version)
+ ? "The command named '" + command + "' is at version " + theCommand.version
+ : "The command named '" + command + "' is a core command in Bespin version " + bespin.versionNumber;
+ }
+ }
+ else {
+ version = bespinVersion;
+ }
+ self.showInfo(version);
+ }
+});
+
+// ** {{{Command: clear}}} **
+bespin.cmd.commands.add({
+ name: 'clear',
+ aliases: ['cls'],
+ preview: 'clear the file',
+ execute: function(self) {
+ self.editor.model.clear();
+ }
+});
+
+// ** {{{Command: goto}}} **
+bespin.cmd.commands.add({
+ name: 'goto',
+ takes: ['linenumber'],
+ preview: 'move it! make the editor head to your line number.',
+ completeText: 'add the line number to move to',
+ execute: function(self, linenumber) {
+ if (linenumber) {
+ var linenumAsInt = parseInt(linenumber, 10) - 1; // parse the line number as a decimal
+
+ self.editor.moveCursor({ row: linenumAsInt, col: 0 });
+
+ // If the line that we are moving to is off screen, center it, else just move in place
+ if ( (linenumAsInt < self.editor.ui.firstVisibleRow) || (linenumAsInt >= self.editor.ui.firstVisibleRow+self.editor.ui.visibleRows) ) {
+ bespin.publish("bespin:editor:doaction", {
+ action: 'moveCursorRowToCenter'
+ });
+ }
+ }
+ }
+});
+
+// ** {{{Command: replace}}} **
+bespin.cmd.commands.add({
+ name: 'replace',
+ takes: ['search', 'replace'],
+ preview: 's/foo/bar/g',
+ completeText: 'add the search regex, and then the replacement text',
+ execute: function(self, args) {
+ self.editor.model.replace(args.search, args.replace);
+ }
+});
+
+// ** {{{Command: login}}} **
+bespin.cmd.commands.add({
+ name: 'login',
+ // aliases: ['user'],
+ // takes: ['username', 'password'],
+ hidden: true,
+ takes: {
+ order: ['username', 'password'],
+ username: {
+ "short": 'u'
+ },
+ password: {
+ "short": 'p',
+ optional: true
+ }
+ },
+ preview: 'login to the service',
+ completeText: 'pass in your username and password',
+ execute: function(self, args) {
+ if (!args) { // short circuit if no username
+ self.executeCommand("status");
+ return;
+ }
+ bespin.get('editSession').username = args.user; // TODO: normalize syncing
+ bespin.get('server').login(args.user, args.pass);
+ }
+});
+
+// ** {{{Command: logout}}} **
+bespin.cmd.commands.add({
+ name: 'logout',
+ preview: 'log out',
+ execute: function(self) {
+ delete bespin.get('editSession').username;
+ bespin.get('server').logout(function() {
+ window.location.href="/";
+ });
+ }
+});
+
+// ** {{{Command: bespin}}} **
+bespin.cmd.commands.add({
+ name: 'bespin',
+ preview: 'has',
+ hidden: true,
+ messages: [
+ "really wants you to trick it out in some way.",
+ "is your Web editor.",
+ "would love to be like Emacs on the Web.",
+ "is written on the Web platform, so you can tweak it."
+ ],
+ execute: function(self) {
+ self.showInfo("Bespin " + this.messages[Math.floor(Math.random() * this.messages.length)]);
+ }
+});
+
+// ** {{{Command: action}}} **
+bespin.cmd.commands.add({
+ name: 'action',
+ takes: ['actionname'],
+ preview: 'execute any editor action',
+ hidden: true,
+ execute: function(self, actionname) {
+ bespin.publish("bespin:editor:doaction", {
+ action: actionname
+ });
+ }
+});
+
+// ** {{{Command: sort}}} **
+bespin.cmd.commands.add({
+ name: 'sort',
+ takes: ['direction'],
+ preview: 'sort the current buffer',
+ completeText: 'optionally, sort descending',
+ execute: function(self, direction) {
+ var buffer = self.editor.model.getDocument().split(/\n/);
+ buffer.sort();
+ if (direction && /^desc/.test(direction.toLowerCase())) buffer.reverse();
+ self.editor.model.insertDocument(buffer.join("\n"));
+ }
+});
+
+// ** {{{Command: quota}}} **
+bespin.cmd.commands.add({
+ name: 'quota',
+ preview: 'show your quota info',
+ megabytes: function(bytes) {
+ return (bytes / 1024 / 1024).toFixed(2);
+ },
+ execute: function(self) {
+ var editSession = bespin.get('editSession');
+ self.showInfo("You have " + this.megabytes(editSession.quota - editSession.amountUsed) + " MB free space to put some great code!<br><br> <em style='font-size: smaller'>Used " + this.megabytes(editSession.amountUsed) + " MB out of your " + this.megabytes(editSession.quota) + " MB quota</em>");
+ }
+});
+
+// ** {{{Command: export}}} **
+bespin.cmd.commands.add({
+ name: 'export',
+ takes: ['project', 'archivetype'],
+ preview: 'export the given project with an archivetype of zip or tgz',
+ completeText: 'project name, archivetype (zip | tgz, defaults to zip)',
+ execute: function(self, args) {
+ var project = args.project || bespin.get('editSession').project;
+
+ var type = args.archivetype;
+ if (!bespin.util.include(['zip','tgz','tar.gz'], type)) {
+ type = 'zip';
+ }
+
+ bespin.get('server').exportProject(project, type); // try to do it via the iframe
+ }
+});
+
+// ** {{{Command: import}}} **
+bespin.cmd.commands.add({
+ name: 'import',
+ takes: ['url', 'project'],
+ preview: 'import the given url as a project.<br>If a project name isn\'t given it will use the filename',
+ completeText: 'url (to an archive zip | tgz), optional project name',
+ usage: "[url of archive] [projectname]<br><br><em>(projectname optional. Will be taken from the URL if not provided)</em>",
+ // ** {{{calculateProjectName}}}
+ //
+ // Given a URL, work out the project name as a default
+ // For example, given http://foo.com/path/to/myproject.zip
+ // return "myproject"
+ calculateProjectName: function(url) {
+ var split = url.split('/');
+ var projectMaker = split[split.length - 1].split(".");
+ projectMaker.pop();
+ return projectMaker.join("_");
+ },
+ // ** {{{isURL}}}
+ //
+ // Test the given string to return if it is a URL.
+ // In this context it has to be http(s) only
+ isURL: function(url) {
+ return (url && (/^http(:|s:)/.test(url)));
+ },
+ // ** {{{execute}}}
+ //
+ // Can be called in three ways:
+ //
+ // * import http://foo.com/path/to/archive.zip
+ // * import http://foo.com/path/to/archive.zip projectName
+ // * import projectName http://foo.com/path/to/archive.zip
+ execute: function(self, args) {
+ var project, url;
+
+ // Fail fast. Nothing given?
+ if (!args.url) {
+ self.showUsage(this);
+ return;
+ // * checking - import http://foo.com/path/to/archive.zip
+ } else if (!args.project && this.isURL(args.url)) {
+ args.project = this.calculateProjectName(args.url);
+ // * Oops, project and url are the wrong way around. That's fine
+ } else if (this.isURL(args.project)) {
+ project = args.project;
+ url = args.url;
+ args.project = url;
+ args.url = project;
+ // * Make sure that a URL came along at some point
+ } else if (!this.isURL(args.url)) {
+ self.showUsage(this);
+ return;
+ }
+
+ project = args.project;
+ url = args.url;
+
+ self.showInfo("About to import " + project + " from:<br><br>" + url + "<br><br><em>It can take awhile to download the project, so be patient!</em>");
+
+ bespin.publish("bespin:project:import", { project: project, url: url });
+ }
+});
+
+// ** {{{Command: trim}}} **
+bespin.cmd.commands.add({
+ name: 'trim',
+ takes: ['side'], // left, right, both
+ preview: 'trim trailing or leading whitespace',
+ completeText: 'optionally, give a side of left, right, or both (defaults to right)',
+ execute: function(self, side) {
+ self.editor.model.changeEachRow(function(row) {
+ if (!side) side = "right";
+
+ if (bespin.util.include(["left", "both"], side)) {
+ while (row[0] == ' ') {
+ row.shift();
+ }
+ }
+
+ if (bespin.util.include(["right", "both"], side)) {
+ var i = row.length - 1;
+
+ while (row[i] == ' ') {
+ delete row[i];
+ i--;
+ }
+ }
+ return bespin.util.shrinkArray(row);
+ });
+ }
+});
+
+// ** {{{Command: bindkey}}} **
+bespin.cmd.commands.add({
+ name: 'bindkey',
+ takes: ['modifiers', 'key', 'action'],
+ preview: 'Bind a key to an action',
+ completeText: 'give modifier(s), key, and action name',
+ hidden: true,
+ execute: function(self, args) {
+ if (args.modifiers == "none") args.modifiers = '';
+
+ bespin.publish("bespin:editor:bindkey", args);
+ }
+});
+
+// ** {{{Command: insert}}} **
+bespin.cmd.commands.add({
+ name: 'insert',
+ takes: ['text'],
+ preview: 'insert the given text at this point.',
+ hidden: true,
+ execute: function(self, text) {
+ self.editor.model.insertChunk(self.editor.cursorPosition, text);
+ }
+});
+
+// ** {{{Command: typingtest}}} **
+bespin.cmd.commands.add({
+ name: 'typingtest',
+ preview: 'type in the alphabet a few times',
+ hidden: true,
+ execute: function(self) {
+ var start = Date.now();
+
+ for (var i = 0; i < 3; i++) {
+ dojo.forEach(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'], function(c) {
+ var args = { pos: bespin.editor.utils.copyPos(self.editor.cursorPosition) };
+ args.newchar = c;
+ self.editor.ui.actions.insertCharacter(args);
+ });
+ }
+
+ var stop = Date.now();
+
+ self.showInfo("It took " + (stop - start) + " milliseconds to do this");
+ }
+});
+
+// ** {{{Command: template}}} **
+bespin.cmd.commands.add({
+ name: 'template',
+ takes: ['type'],
+ preview: 'insert templates',
+ completeText: 'pass in the template name',
+ templates: { 'in': "for (var key in object) {\n\n}"},
+ execute: function(cmdline, type) {
+ cmdline.editor.model.insertChunk(cmdline.editor.cursorPosition, this.templates[type]);
+ }
+});
+
+// ** {{{Command: alias}}} **
+bespin.cmd.commands.add({
+ name: 'alias',
+ takes: ['alias', 'command'],
+ preview: 'define and show aliases for commands',
+ completeText: 'optionally, add your alias name, and then the command name',
+ execute: function(self, args) {
+ var output;
+ if (!args.alias) { // -- show all
+ output = "<u>Your Aliases</u><br/><br/>";
+ for (var x in self.aliases) {
+ output += x + ": " + self.aliases[x] + "<br/>";
+ }
+ } else {
+ if (args.command === undefined) { // show it
+ output = "<u>Your alias</u><br/><br/>";
+ var alias = self.aliases[args.alias];
+ if (alias) {
+ output += args.alias + ": " + self.aliases[args.alias];
+ } else {
+ output += "No alias set for " + args.alias;
+ }
+ } else { // save a new alias
+ var key = args.alias;
+ var value = args.command;
+ var aliascmd = value.split(' ')[0];
+
+ output = "<u>Saving setting</u><br/><br/>";
+ if (self.commands[key]) {
+ output += "Sorry, there is already a command with the name: " + key;
+ } else if (self.commands[aliascmd]) {
+ output += key + ": " + value;
+ self.aliases[key] = value;
+ } else if (self.aliases[aliascmd]) { // TODO: have the symlink to the alias not the end point
+ output += key + ": " + self.aliases[value] + " (" + value + " was an alias itself)";
+ self.aliases[key] = value;
+ } else {
+ output += "Sorry, no command or alias with that name.";
+ }
+ }
+ }
+ self.showInfo(output);
+ }
+});
+
+// ** {{{Command: history}}} **
+bespin.cmd.commands.add({
+ name: 'history',
+ preview: 'show history of the commands',
+ execute: function(self) {
+ self.showInfo('<u>Command History</u><br/><br/>' + self.commandLineHistory.history.join('<br/>'));
+ }
+});
+
+// ** {{{Command: use}}} **
+bespin.cmd.commands.add({
+ name: 'use',
+ takes: ['type'],
+ preview: 'use patterns to bring in code',
+ completeText: '"sound" will add sound support',
+ libnames: {
+ 'jquery': 'jquery.min.js'
+ },
+ execute: function(self, type) {
+ if (type == 'sound') {
+ self.editor.model.insertChunk({ row: 3, col: 0 },
+ ' <script type="text/javascript" src="soundmanager2.js"></script>\n');
+ self.editor.model.insertChunk({ row: 4, col: 0 },
+ " <script>\n var sound; \n soundManager.onload = function() {\n sound = soundManager.createSound('mySound','/path/to/mysoundfile.mp3');\n }\n </script>\n");
+ } else if (type == 'js') {
+ var jslib = 'http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js';
+ var script = '<script type="text/javascript" src="' + jslib + '"></script>\n';
+ self.editor.model.insertChunk({ row: 3, col: 0 }, script);
+ }
+ }
+});
+
+// ** {{{Command: follow}}} **
+bespin.cmd.commands.add({
+ name: 'follow',
+ takes: ['username ...'],
+ preview: 'add to the list of users we are following, or (with no args) list the current set',
+ completeText: 'username(s) of person(s) to follow',
+ usage: "[username] ...<br><br><em>(username optional. Will list current followed users if not provided)</em>",
+ // ** {{{execute}}}
+ execute: function(self, args) {
+ var usernames = bespin.cmd.commands.toArgArray(args);
+
+ if (usernames.length == 0) {
+ bespin.publish("bespin:network:followers");
+ }
+ else {
+ bespin.publish("bespin:network:follow", [ usernames ]);
+ }
+ }
+});
+
+// ** {{{Command: unfollow}}} **
+bespin.cmd.commands.add({
+ name: 'unfollow',
+ takes: ['username ...'],
+ preview: 'remove from the list of users we are following',
+ completeText: 'username(s) of person(s) to stop following',
+ usage: "[username] ...<br><br><em>The username(s) to stop following</em>",
+ // ** {{{execute}}}
+ execute: function(self, args) {
+ var usernames = bespin.cmd.commands.toArgArray(args);
+
+ if (usernames.length == 0) {
+ self.showInfo('Please specify the users to cease following');
+ }
+ else {
+ bespin.publish("bespin:network:unfollow", [ usernames ]);
+ }
+ }
+});
+
+// ** {{{Command: group}}} **
+bespin.cmd.commands.add({
+ name: 'group',
+ preview: 'Collect the people you follow into groups, and display the existing groups',
+ // ** {{{execute}}}
+ execute: function(self, args) {
+ args = bespin.cmd.commands.toArgArray(args);
+
+ if (args.length == 0) {
+ bespin.publish("bespin:groups:list:all");
+ }
+ else if (args.length == 1) {
+ bespin.publish("bespin:groups:list", [ args[0] ]);
+ }
+ else if (args.length == 2) {
+ if (args[1] == "-r" || args[1] == "--remove") {
+ bespin.publish("bespin:groups:remove:all", [ args[0] ]);
+ }
+ else {
+ self.showInfo('Syntax error - You must specify what you want to do with your group.');
+ }
+ }
+ else if (args.length > 2) {
+ var group = args.shift();
+ var command = args.shift();
+ if (command == "-a" || command == "--add") {
+ bespin.publish("bespin:groups:add", [ group, args ]);
+ }
+ else if (command == "-r" || command == "--remove") {
+ args.shift();
+ bespin.publish("bespin:groups:remove", [ group, args ]);
+ }
+ else {
+ self.showInfo('Syntax error - To manipulate a group you must use add/remove');
+ }
+ }
+ }
+});
+
+// ** {{{Command: test}}} **
+bespin.cmd.commands.add({
+ name: 'test',
+ preview: 'Run some automated end to end tests',
+ script: [
+ { send:"echo Starting", expect:/^Starting$/ },
+ { send:"follow", expect:/sds/ },
+ { send:"echo Finished", expect:/^Finished$/ }
+ ],
+ // ** {{{_setup}}}
+ _setup: function(self, onComplete) {
+ this.originalShowInfo = self.showInfo;
+ var that = this;
+ bespin.get('server').request('POST', '/test/setup/', null, {
+ call:onComplete,
+ onFailure:function(xhr) {
+ that._cleanup(self, "_setup() failed. Maybe due to: " + xhr.responseText);
+ }
+ });
+ },
+ // ** {{{_cleanup}}}
+ _cleanup: function(self, reason) {
+ self.showInfo = this.originalShowInfo;
+ self.showInfo(reason);
+ bespin.get('server').request('POST', '/test/cleanup/', null, {
+ call:function() {
+ console.log("Server cleanup completed")
+ },
+ onFailure:function(xhr) {
+ self.showInfo("_setup() failed. Maybe due to: " + xhr.responseText);
+ }
+ });
+ },
+ // ** {{{_runNextElement}}}
+ _runNextElement: function(self, script, index) {
+ console.log("_runNextElement", index);
+ if (index >= script.length) {
+ this._cleanup(self, "Finished running tests");
+ return;
+ }
+ var element = script[index];
+ var that = this;
+ self.showInfo = function(html, autohide) {
+ var info = dojo.byId('info')
+ info.innerHTML = html;
+ var text = info.textContent;
+ if (element.expect.test(text)) {
+ that._runNextElement(self, script, index + 1);
+ }
+ else {
+ console.error("Test failure at index:", index);
+ console.log("Command: ", element.send);
+ console.log("Expected: ", element.expect.source);
+ console.log("Received:", text);
+ that._cleanup(self, "Test failure at index: " + index + "<br/>Command: '" + element.send + "'<br/>Expected: /" + element.expect.source + "/<br/>Received: '" + text + "'");
+ }
+ };
+ self.executeCommand(element.send);
+ },
+ // ** {{{execute}}}
+ execute: function(self) {
+ var that = this;
+ this._setup(self, function() {
+ that._runNextElement(self, that.script, 0);
+ });
+ }
+});
+
+// ** {{{Command: echo}}} **
+bespin.cmd.commands.add({
+ name: 'echo',
+ takes: ['message ...'],
+ preview: 'A test echo command',
+ // ** {{{execute}}}
+ execute: function(self, args) {
+ self.showInfo(args);
+ }
+});
+
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/commands.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/dashboardcommands.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/dashboardcommands.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/dashboardcommands.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/dashboardcommands.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,36 @@
+/* ***** 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.cmd.dashboardcommands");
+
+// = Dashboard Commands =
+//
+// This array stores all of the dashboard commands.
+
+bespin.cmd.dashboardcommands.Commands = [
+ 'help', 'files', 'set', 'project', 'projects', 'version', 'bespin',
+ 'import', 'export', 'alias', 'history', 'mkdir', 'newfile',
+ 'createproject', 'deleteproject', 'renameproject', 'status',
+ 'follow', 'unfollow', 'group', 'test', 'echo'
+];
\ No newline at end of file
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/dashboardcommands.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/editorcommands.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/editorcommands.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/editorcommands.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/editorcommands.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,37 @@
+/* ***** 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.cmd.editorcommands");
+
+// = Editor Commands =
+//
+// This array stores all of the editor commands.
+
+(function() {
+ var keys = [];
+ for (var i in bespin.cmd.commands.store){
+ keys.push(i);
+ }
+ bespin.cmd.editorcommands.Commands = keys;
+})();
\ No newline at end of file
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/cmd/editorcommands.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/Component.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/Component.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/Component.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/Component.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,94 @@
+dojo.provide("bespin.editor.Component");
+
+dojo.require("bespin.bespin");
+
+dojo.require("bespin.util.canvas");
+dojo.require("bespin.util.keys");
+dojo.require("bespin.util.navigate");
+dojo.require("bespin.util.path");
+dojo.require("bespin.util.tokenobject");
+dojo.require("bespin.util.util");
+dojo.require("bespin.util.mousewheelevent");
+dojo.require("bespin.util.urlbar");
+
+dojo.require("bespin.client.filesystem");
+dojo.require("bespin.client.settings");
+dojo.require("bespin.client.status");
+dojo.require("bespin.client.server");
+dojo.require("bespin.client.session");
+
+dojo.require("bespin.editor.actions");
+dojo.require("bespin.editor.clipboard");
+dojo.require("bespin.editor.cursor");
+dojo.require("bespin.editor.editor");
+dojo.require("bespin.editor.events");
+dojo.require("bespin.editor.model");
+dojo.require("bespin.editor.toolbar");
+dojo.require("bespin.editor.themes");
+dojo.require("bespin.editor.undo");
+
+dojo.require("bespin.syntax.syntax");
+dojo.require("bespin.syntax.javascript");
+dojo.require("bespin.syntax.css");
+dojo.require("bespin.syntax.html");
+dojo.require("bespin.syntax.php");
+
+dojo.require("bespin.cmd.commandline");
+dojo.require("bespin.cmd.commands");
+dojo.require("bespin.cmd.editorcommands");
+
+dojo.require("th.helpers"); // -- Thunderhead... hooooo
+dojo.require("th.css");
+dojo.require("th.th");
+dojo.require("th.models");
+dojo.require("th.borders");
+dojo.require("th.components");
+
+dojo.declare("bespin.editor.Component", null, {
+ constructor: function(container, opts) {
+ opts.actsAsComponent = true;
+
+ var initialcontent;
+ if (opts.loadfromdiv) {
+ initialcontent = dojo.byId(container).innerHTML
+ }
+
+ this.editor = bespin.register('editor', opts.editor || new bespin.editor.API(container, opts));
+ this.editSession = bespin.register('editSession', opts.editSession || new bespin.client.session.EditSession(this.editor));
+ this.server = bespin.register('server', opts.server || new bespin.client.Server());
+ this.files = bespin.register('files', opts.files || new bespin.client.FileSystem());
+ bespin.register('settings', opts.settings || new bespin.client.settings.Core(bespin.client.settings.InMemory));
+
+ dojo.connect(window, 'resize', opts.resize || dojo.hitch(this, function() {
+ this.editor.paint();
+ }));
+
+ if (opts.loadfromdiv && initialcontent) {
+ this.setContent(initialcontent);
+ }
+
+ if (opts.syntax) { // -- turn on syntax highlighting
+ bespin.publish("bespin:settings:syntax", { language: opts.syntax });
+ }
+
+ if (!opts.dontstealfocus) {
+ this.editor.canvas.focus();
+ }
+ },
+
+ getContent: function() {
+ return this.editor.model.getDocument();
+ },
+
+ setContent: function(content) {
+ return this.editor.model.insertDocument(content);
+ },
+
+ set: function(key, value) {
+ bespin.publish("bespin:settings:set", {
+ key: key,
+ value: value
+ });
+ }
+});
+
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/Component.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/actions.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/actions.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/actions.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/actions.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,639 @@
+/* ***** 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.editor.actions");
+
+// = Actions =
+//
+// The editor can run various actions. They are defined here and you can add or change them dynamically. Cool huh?
+//
+// An action mutates the model or editor state in some way. The only way the editor state or model should be manipulated is via
+// the execution of actions.
+//
+// Actions integrate with the undo manager by including instructions for how to undo (and redo) the action. These instructions
+// take the form of a hash containing the necessary state for undo/redo. A key "action" corresponds to the function name of the
+// action that should be executed to undo or redo the operation and the remaining keys correspond to state necessary to perform
+// the action. See below for various examples.
+
+dojo.declare("bespin.editor.Actions", null, {
+ constructor: function(editor) {
+ this.editor = editor;
+ this.ignoreRepaints = false;
+ },
+
+ // this is a generic helper method used by various cursor-moving methods
+ handleCursorSelection: function(args) {
+ if (args.event.shiftKey) {
+ if (!this.editor.selection) this.editor.setSelection({ startPos: bespin.editor.utils.copyPos(args.pos) });
+ this.editor.setSelection({ startPos: this.editor.selection.startPos, endPos: bespin.editor.utils.copyPos(this.editor.cursorManager.getScreenPosition())});
+ } else {
+ this.editor.setSelection(undefined);
+ }
+ },
+
+ moveCursor: function(moveType, args) {
+ var posData = this.editor.cursorManager[moveType]();
+ this.handleCursorSelection(args);
+ this.repaint();
+ args.pos = posData.newPos;
+ return args;
+ },
+
+ moveCursorLeft: function(args) {
+ return this.moveCursor("moveLeft", args);
+ },
+
+ moveCursorRight: function(args) {
+ return this.moveCursor("moveRight", args);
+ },
+
+ moveCursorUp: function(args) {
+ return this.moveCursor("moveUp", args);
+ },
+
+ moveCursorDown: function(args) {
+ return this.moveCursor("moveDown", args);
+ },
+
+ moveToLineStart: function(args) {
+ return this.moveCursor("moveToLineStart", args);
+ },
+
+ moveToLineEnd: function(args) {
+ return this.moveCursor("moveToLineEnd", args);
+ },
+
+ moveToFileTop: function(args) {
+ return this.moveCursor("moveToTop", args);
+ },
+
+ moveToFileBottom: function(args) {
+ return this.moveCursor("moveToBottom", args);
+ },
+
+ movePageUp: function(args) {
+ return this.moveCursor("movePageUp", args);
+ },
+
+ movePageDown: function(args) {
+ return this.moveCursor("movePageDown", args);
+ },
+
+ moveWordLeft: function(args) {
+ return this.moveCursor("smartMoveLeft", args);
+ },
+
+ moveWordRight: function(args) {
+ return this.moveCursor("smartMoveRight", args);
+ },
+
+ deleteWordLeft: function (args) {
+ this.deleteChunk({
+ endPos: args.pos,
+ pos: this.moveCursor("smartMoveLeft", args).pos
+ });
+ return args;
+ },
+
+ deleteWordRight: function (args) {
+ this.deleteChunk({
+ pos: args.pos,
+ endPos: this.moveCursor("smartMoveRight", args).pos
+ });
+ return args;
+ },
+
+ undo: function() {
+ this.editor.undoManager.undo();
+ },
+
+ redo: function() {
+ this.editor.undoManager.redo();
+ },
+
+ selectAll: function(args) {
+ // do nothing with an empty doc
+ if (this.editor.model.getMaxCols == 0) return;
+
+ args.startPos = { col: 0, row: 0 };
+ args.endPos = { col: this.editor.model.getRowLength(this.editor.model.getRowCount() - 1), row: this.editor.model.getRowCount() - 1 };
+
+ this.select(args);
+ },
+
+ select: function(args) {
+ if (args.startPos) {
+ this.editor.setSelection({ startPos: args.startPos, endPos: args.endPos });
+ this.editor.cursorManager.moveCursor(args.endPos);
+ } else {
+ this.editor.setSelection(undefined);
+ }
+ },
+
+ insertTab: function(args) {
+ var settings = bespin.get('settings');
+
+ if (this.editor.getSelection() && !args.undoInsertTab) {
+ this.indent(args);
+ return;
+ }
+
+ var tabWidth = args.tabWidth;
+ var tab = args.tab;
+
+ if (!tab || !tabWidth) {
+ var realTabs = (settings.get('tabsize') == 'tabs');
+ if (realTabs) {
+ // do something tabby
+ tab = "\t";
+ tabWidth = 1;
+ } else {
+ var tabWidth = parseInt(settings.get('tabsize') || bespin.defaultTabSize); // TODO: global needs fixing
+ var tabWidthCount = tabWidth;
+ var tab = "";
+ while (tabWidthCount-- > 0) {
+ tab += " ";
+ }
+ }
+ }
+
+ this.editor.model.insertCharacters({row: args.modelPos.row, col: args.modelPos.col}, tab);
+ this.editor.cursorManager.moveCursor({row: args.modelPos.row, col: args.modelPos.col + tabWidth});
+
+ var linetext = this.editor.model.getRowArray(args.modelPos.row).join("");
+ // linetext = linetext.replace(/\t/g, "TAB");
+ // console.log(linetext);
+
+ this.repaint();
+
+ // undo/redo
+ args.action = "insertTab";
+ var redoOperation = args;
+ var undoArgs = { action: "removeTab", queued: args.queued, modelPos: bespin.editor.utils.copyPos(args.modelPos),
+ pos: bespin.editor.utils.copyPos(args.pos), tab: tab, tabWidth: tabWidth };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+ },
+
+ // this function can only be called by editor.undoManager for undo insertTab in the case of beeing nothing selected
+ removeTab: function(args) {
+ var tabWidth = args.tabWidth;
+
+ this.editor.model.deleteCharacters({row: args.pos.row, col: args.pos.col}, tabWidth);
+ this.editor.cursorManager.moveCursor({row: args.pos.row, col: args.pos.col});
+
+ this.repaint();
+
+ args.action = "removeTab";
+ var redoOperation = args;
+ var undoArgs = { action: "insertTab", undoInsertTab: true, queued: args.queued, pos: bespin.editor.utils.copyPos(args.pos),
+ modelPos: bespin.editor.utils.copyPos(args.modelPos), tab: args.tab, tabWidth: args.tabWidth };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+ },
+
+ // TODO: this is likely now broken
+ indent: function(args) {
+ var historyIndent = args.historyIndent || false;
+ if (!historyIndent) {
+ var newHistoryIndent = [];
+ }
+ var selection = args.selection || this.editor.getSelection();
+ var fakeSelection = args.fakeSelection || false;
+ var startRow = selection.startPos.row;
+ var endRow = selection.endPos.row;
+ var tabWidth = parseInt(_settings.get('tabsize') || bespin.defaultTabSize); // TODO: global needs fixing
+ var tabWidthCount = tabWidth;
+ var tab = "";
+ while (tabWidthCount-- > 0) {
+ tab += " ";
+ }
+
+ for (var y = startRow; y <= endRow; y++) {
+ if (!historyIndent) {
+ var row = this.editor.model.getRowArray(y).join("");
+ var match = /^(\s+).*/.exec(row);
+ var leadingWhitespaceLength = 0;
+ if (match && match.length == 2) {
+ leadingWhitespaceLength = match[1].length;
+ }
+ var charsToInsert = (leadingWhitespaceLength % tabWidth ? tabWidth - (leadingWhitespaceLength % tabWidth) : tabWidth);
+ this.editor.model.insertCharacters({row: y, col: 0}, tab.substring(0, charsToInsert));
+ newHistoryIndent.push(charsToInsert);
+ } else {
+ this.editor.model.insertCharacters({row: y, col: 0}, tab.substring(0, historyIndent[y - startRow]));
+ }
+ }
+
+ if (!fakeSelection) {
+ selection.startPos.col += (historyIndent ? historyIndent[0] : tab.length);
+ selection.endPos.col += (historyIndent ? historyIndent[historyIndent.length-1] : tab.length);
+ this.editor.setSelection(selection);
+ }
+ args.pos.col += (historyIndent ? historyIndent[historyIndent.length-1] : tab.length);
+ this.editor.cursorManager.moveCursor({ col: args.pos.col });
+ historyIndent = historyIndent ? historyIndent : newHistoryIndent;
+ this.repaint();
+
+ // undo/redo
+ args.action = "indent";
+ args.selection = selection;
+ var redoOperation = args;
+ var undoArgs = { action: "unindent", queued: args.queued, selection: selection, fakeSelection: fakeSelection, historyIndent: historyIndent, pos: bespin.editor.utils.copyPos(args.pos) };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+ },
+
+ unindent: function(args) {
+ var historyIndent = args.historyIndent || false;
+ if (!historyIndent) {
+ var newHistoryIndent = [];
+ }
+ var selection = args.selection || this.editor.getSelection();
+ var fakeSelection = args.fakeSelection || false;
+ if (!selection) {
+ fakeSelection = true;
+ selection = {startPos: {row: args.pos.row, col: args.pos.col}, endPos: {row: args.pos.row, col: args.pos.col}};
+ }
+ var startRow = selection.startPos.row;
+ var endRow = selection.endPos.row;
+ var tabWidth = parseInt(_settings.get('tabsize') || bespin.defaultTabSize); // TODO: global needs fixing
+
+ for (var y = startRow; y <= endRow; y++) {
+ if (historyIndent) {
+ var charsToDelete = historyIndent[y - startRow];
+ } else {
+ var row = this.editor.model.getRowArray(y).join("");
+ var match = /^(\s+).*/.exec(row);
+ var leadingWhitespaceLength = 0;
+ if (match && match.length == 2) {
+ leadingWhitespaceLength = match[1].length;
+ }
+ var charsToDelete = leadingWhitespaceLength >= tabWidth ? (leadingWhitespaceLength % tabWidth ? leadingWhitespaceLength % tabWidth : tabWidth) : leadingWhitespaceLength;
+ newHistoryIndent.push(charsToDelete);
+ }
+
+ if (charsToDelete) {
+ this.editor.model.deleteCharacters({row: y, col: 0}, charsToDelete);
+ }
+ if (y == startRow) {
+ selection.startPos.col = Math.max(0, selection.startPos.col - charsToDelete);
+ }
+ if (y == endRow) {
+ selection.endPos.col = Math.max(0, selection.endPos.col - charsToDelete);
+ }
+ if (y == args.pos.row) {
+ args.pos.col = Math.max(0, args.pos.col - charsToDelete);
+ }
+ }
+ this.editor.cursorManager.moveCursor({ col: args.pos.col });
+
+ if (!fakeSelection) {
+ this.editor.setSelection(selection);
+ }
+ historyIndent = historyIndent ? historyIndent : newHistoryIndent;
+ this.repaint();
+
+ // undo/redo
+ args.action = "unindent";
+ args.selection = selection;
+ var redoOperation = args;
+ var undoArgs = { action: "indent", queued: args.queued, selection: selection, fakeSelection: fakeSelection, historyIndent: historyIndent, pos: bespin.editor.utils.copyPos(args.pos) };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+ },
+
+ // NOTE: Actually, clipboard.js is taking care of this unless EditorOnly mode is set
+ cutSelection: function(args) {
+ this.copySelection(args);
+ this.deleteSelection(args);
+ },
+
+ // NOTE: Actually, clipboard.js is taking care of this unless EditorOnly mode is set
+ copySelection: function(args) {
+ var selectionObject = this.editor.getSelection();
+ if (selectionObject) {
+ var selectionText = this.editor.model.getChunk(selectionObject);
+ if (selectionText) {
+ bespin.editor.clipboard.Manual.copy(selectionText);
+ }
+ }
+ },
+
+ deleteSelectionAndInsertChunk: function(args) {
+ var oldqueued = args.queued;
+
+ args.queued = true;
+ var selection = this.editor.getSelection();
+ var chunk = this.deleteSelection(args);
+ args.pos = bespin.editor.utils.copyPos(this.editor.getCursorPos());
+ var endPos = this.insertChunk(args);
+
+ args.queued = oldqueued;
+
+ // undo/redo
+ args.action = "deleteSelectionAndInsertChunk";
+ args.selection = selection;
+ var redoOperation = args;
+ var undoArgs = {
+ action: "deleteChunkAndInsertChunkAndSelect",
+ pos: bespin.editor.utils.copyPos(args.pos),
+ endPos: endPos,
+ queued: args.queued,
+ chunk: chunk
+ };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+ },
+
+ deleteChunkAndInsertChunkAndSelect: function(args) {
+ var oldqueued = args.queued;
+
+ args.queued = true;
+ this.deleteChunk(args);
+ this.insertChunkAndSelect(args);
+
+ args.queued = oldqueued;
+
+ // undo/redo
+ args.action = "deleteChunkAndInsertChunkAndSelect";
+ var redoOperation = args;
+ var undoArgs = {
+ action: "deleteSelectionAndInsertChunk",
+ pos: bespin.editor.utils.copyPos(args.pos),
+ queued: args.queued,
+ selection: args.selection
+ };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+ },
+
+ // NOTE: Actually, clipboard.js is taking care of this unless EditorOnly mode is set
+ pasteFromClipboard: function(args) {
+ var clipboard = (args.clipboard) ? args.clipboard : bespin.editor.clipboard.Manual.data();
+ if (clipboard === undefined) return; // darn it clipboard!
+ args.chunk = clipboard;
+ this.insertChunk(args);
+ },
+
+ insertChunk: function(args) {
+ if (this.editor.selection) {
+ this.deleteSelectionAndInsertChunk(args);
+ } else {
+ var pos = this.editor.model.insertChunk(bespin.editor.utils.copyPos(this.editor.cursorManager.getScreenPosition()), args.chunk);
+ this.editor.cursorManager.moveCursor(pos);
+ this.repaint();
+
+ // undo/redo
+ args.action = "insertChunk";
+ var redoOperation = args;
+ var undoArgs = { action: "deleteChunk", pos: bespin.editor.utils.copyPos(args.pos), queued: args.queued, endPos: pos };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+
+ return pos;
+ }
+ },
+
+ deleteChunk: function(args) {
+ var chunk = this.editor.model.deleteChunk({ startPos: args.pos, endPos: args.endPos });
+ this.editor.cursorManager.moveCursor(args.pos);
+ this.repaint();
+
+ // undo/redo
+ args.action = "deleteChunk";
+ var redoOperation = args;
+ var undoArgs = { action: "insertChunk", pos: bespin.editor.utils.copyPos(args.pos), queued: args.queued, chunk: chunk };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+ },
+
+ //deleteLine: function(args) {
+ // this.editor.lines.splice(args.pos.row);
+ // if (args.pos.row >= this.editor.lines.length) this.editor.cursorManager.moveCursor({ row: args.pos.row - 1, col: args.pos.col });
+ // this.repaint();
+ //},
+
+ joinLine: function(args) {
+ if (args.joinDirection == "up") {
+ if (args.pos.row == 0) return;
+
+ var newcol = this.editor.ui.getRowScreenLength(args.pos.row - 1);
+ this.editor.model.joinRow(args.pos.row - 1);
+ this.editor.cursorManager.moveCursor({ row: args.pos.row - 1, col: newcol });
+ } else {
+ if (args.pos.row >= this.editor.model.getRowCount() - 1) return;
+
+ this.editor.model.joinRow(args.pos.row);
+ }
+
+ // undo/redo
+ args.action = "joinLine";
+ var redoOperation = args;
+ var undoArgs = { action: "newline", pos: bespin.editor.utils.copyPos(this.editor.getCursorPos()), queued: args.queued };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+
+ this.repaint();
+ },
+
+ killLine: function(args) {
+ // select the current row
+ this.editor.setSelection({ startPos: { row: args.pos.row, col: 0 }, endPos: { row: args.pos.row + 1, col: 0 } });
+ this.cutSelection(args); // cut (will save and redo will work)
+ },
+
+ deleteSelection: function(args) {
+ if (!this.editor.selection) return;
+ var selection = this.editor.getSelection();
+ var startPos = bespin.editor.utils.copyPos(selection.startPos);
+ var chunk = this.editor.model.getChunk(selection);
+ this.editor.model.deleteChunk(selection);
+
+ // undo/redo
+ args.action = "deleteSelection";
+ var redoOperation = args;
+ var undoArgs = { action: "insertChunkAndSelect", pos: bespin.editor.utils.copyPos(startPos), queued: args.queued, chunk: chunk };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+
+ // setting the selection to undefined has to happen *after* we enqueue the undoOp otherwise replay breaks
+ this.editor.setSelection(undefined);
+ this.editor.cursorManager.moveCursor(startPos);
+ this.repaint();
+
+ return chunk;
+ },
+
+ insertChunkAndSelect: function(args) {
+ var endPos = this.editor.model.insertChunk(args.pos, args.chunk);
+
+ args.action = "insertChunkAndSelect";
+ var redoOperation = args;
+ var undoArgs = { action: "deleteSelection", pos: bespin.editor.utils.copyPos(endPos), queued: args.queued };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+
+ // setting the selection to undefined has to happen *after* we enqueue the undoOp otherwise replay breaks
+ this.editor.setSelection({ startPos: args.pos, endPos: endPos });
+ this.editor.cursorManager.moveCursor(endPos);
+ this.repaint();
+ },
+
+ backspace: function(args) {
+ if (this.editor.selection) {
+ this.deleteSelection(args);
+ } else {
+ if (args.pos.col > 0) {
+ this.editor.cursorManager.moveCursor({ col: Math.max(0, args.pos.col - 1) });
+ args.pos.col -= 1;
+ this.deleteCharacter(args);
+ } else {
+ args.joinDirection = "up";
+ this.joinLine(args);
+ }
+ }
+ },
+
+ deleteKey: function(args) {
+ if (this.editor.selection) {
+ this.deleteSelection(args);
+ } else {
+ if (args.pos.col < this.editor.model.getRowLength(args.pos.row)) {
+ this.deleteCharacter(args);
+ } else {
+ args.joinDirection = "down";
+ this.joinLine(args);
+ }
+ }
+ },
+
+ deleteCharacter: function(args) {
+ if (args.pos.col < this.editor.ui.getRowScreenLength(args.pos.row)) {
+ var deleted = this.editor.model.deleteCharacters(args.pos, 1);
+ this.repaint();
+
+ // undo/redo
+ args.action = "deleteCharacter";
+ var redoOperation = args;
+ var undoArgs = { action: "insertCharacter", pos: bespin.editor.utils.copyPos(args.pos), queued: args.queued, newchar: deleted };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+ }
+ },
+
+ newline: function(args) {
+ var autoindentAmount = bespin.get('settings').get('autoindent') ? bespin.util.leadingSpaces(this.editor.model.getRowArray(args.pos.row)) : 0;
+ this.editor.model.splitRow(args.pos, autoindentAmount);
+ this.editor.cursorManager.moveCursor({ row: this.editor.cursorManager.getScreenPosition().row + 1, col: autoindentAmount });
+
+ // undo/redo
+ args.action = "newline";
+ var redoOperation = args;
+ var undoArgs = { action: "joinLine", joinDirection: "up", pos: bespin.editor.utils.copyPos(this.editor.cursorManager.getScreenPosition()), queued: args.queued };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+
+ this.repaint();
+ },
+
+ // it seems kinda silly, but when you have a region selected and you insert a character, I have a separate action that is invoked.
+ // this is because it's really two operations: deleting the selected region and then inserting a character. Each of these two
+ // actions adds an operation to the undo queue. So I have two choices for
+ deleteSelectionAndInsertCharacter: function(args) {
+ var oldqueued = args.queued;
+
+ args.queued = true;
+ var chunk = this.deleteSelection(args);
+ args.pos = bespin.editor.utils.copyPos(this.editor.getCursorPos());
+ this.insertCharacter(args);
+
+ args.queued = oldqueued;
+
+ // undo/redo
+ args.action = "deleteSelectionAndInsertCharacter";
+ var redoOperation = args;
+ var undoArgs = {
+ action: "deleteCharacterAndInsertChunkAndSelect",
+ pos: bespin.editor.utils.copyPos(args.pos),
+ queued: args.queued,
+ chunk: chunk
+ };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+ },
+
+ deleteCharacterAndInsertChunkAndSelect: function(args) {
+ var oldqueued = args.queued;
+
+ args.queued = true;
+ this.deleteCharacter(args);
+ this.insertChunkAndSelect(args);
+
+ args.queued = oldqueued;
+
+ // undo/redo
+ args.action = "deleteCharacterAndInsertChunkAndSelect";
+ var redoOperation = args;
+ var undoArgs = { action: "deleteSelectionAndInsertCharacter", pos: bespin.editor.utils.copyPos(args.pos), queued: args.queued };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+ },
+
+ insertCharacter: function(args) {
+ if (this.editor.selection) {
+ this.deleteSelectionAndInsertCharacter(args);
+ } else {
+ this.editor.model.insertCharacters(args.pos, args.newchar);
+ this.editor.cursorManager.moveRight();
+ this.repaint();
+
+ // undo/redo
+ args.action = "insertCharacter";
+ var redoOperation = args;
+ var undoArgs = { action: "deleteCharacter", pos: bespin.editor.utils.copyPos(args.pos), queued: args.queued };
+ var undoOperation = undoArgs;
+ this.editor.undoManager.addUndoOperation(new bespin.editor.UndoItem(undoOperation, redoOperation));
+ }
+ },
+
+ moveCursorRowToCenter: function(args) {
+ var saveCursorRow = this.editor.getCursorPos().row;
+ var halfRows = Math.floor(this.editor.ui.visibleRows / 2);
+ if (saveCursorRow > (this.editor.ui.firstVisibleRow + halfRows)) { // bottom half, so move down
+ this.editor.cursorManager.moveCursor({ row: this.editor.getCursorPos().row + halfRows });
+ } else { // top half, so move up
+ this.editor.cursorManager.moveCursor({ row: this.editor.getCursorPos().row - halfRows });
+ }
+ this.editor.ui.ensureCursorVisible();
+ this.editor.cursorManager.moveCursor({ row: saveCursorRow });
+ },
+
+ repaint: function() {
+ if (!this.ignoreRepaints) {
+ this.editor.ui.ensureCursorVisible();
+ this.editor.paint();
+ }
+ }
+});
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/actions.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/clipboard.js
URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/clipboard.js?rev=755931&view=auto
==============================================================================
--- camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/clipboard.js (added)
+++ camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/clipboard.js Thu Mar 19 11:24:18 2009
@@ -0,0 +1,337 @@
+/* ***** 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.editor.clipboard");
+
+// = Clipboard =
+//
+// Handle clipboard operations.
+// If using WebKit (I know, feature detection would be nicer, but e.clipboardData is deep) use DOMEvents
+// Else try the bad tricks.
+
+// ** {{{ bespin.editor.clipboard }}} **
+//
+// The factory that is used to install, and setup the adapter that does the work
+
+dojo.mixin(bespin.editor.clipboard, {
+ // ** {{{ install }}} **
+ //
+ // Given a clipboard adapter implementation, save it, an call install() on it
+ install: function(editor, newImpl) {
+ if (this.uses && typeof this.uses['uninstall'] == "function") this.uses.uninstall();
+ this.uses = newImpl;
+ this.uses.install(editor);
+ },
+
+ // ** {{{ setup }}} **
+ //
+ // Do the first setup. Right now checks for WebKit and inits a DOMEvents solution if that is true
+ // else install the default.
+ setup: function(editor) {
+ if (dojo.isWebKit) {
+ this.install(editor, new bespin.editor.clipboard.DOMEvents());
+ } else {
+ this.install(editor, new bespin.editor.clipboard.HiddenWorld());
+ }
+ }
+});
+
+// ** {{{ bespin.editor.clipboard.DOMEvents }}} **
+//
+// This adapter configures the DOMEvents that only WebKit seems to do well right now.
+// There is trickery involved here. The before event changes focus to the hidden
+// copynpaster text input, and then the real event does its thing and we focus back
+
+dojo.declare("bespin.editor.clipboard.DOMEvents", null, {
+ install: function(editor) {
+
+ // * Configure the hidden copynpaster element
+ var copynpaster = dojo.create("input", {
+ type: 'text',
+ id: 'copynpaster',
+ style: "position: absolute; z-index: -400; top: -100px; left: -100px; width: 0; height: 0; border: none;"
+ }, dojo.body());
+
+ // Copy
+ this.beforecopyHandle = dojo.connect(document, "beforecopy", function(e) {
+ e.preventDefault();
+ copynpaster.focus();
+ });
+
+ this.copyHandle = dojo.connect(document, "copy", function(e) {
+ var selectionText = editor.getSelectionAsText();
+
+ if (selectionText && selectionText != '') {
+ e.preventDefault();
+ e.clipboardData.setData('text/plain', selectionText);
+ }
+
+ dojo.byId('canvas').focus();
+ });
+
+ // Cut
+ this.beforecutHandle = dojo.connect(document, "beforecut", function(e) {
+ e.preventDefault();
+ copynpaster.focus();
+ });
+
+ this.cutHandle = dojo.connect(document, "cut", function(e) {
+ var selectionObject = editor.getSelection();
+
+ if (selectionObject) {
+ var selectionText = editor.model.getChunk(selectionObject);
+
+ if (selectionText && selectionText != '') {
+ e.preventDefault();
+ e.clipboardData.setData('text/plain', selectionText);
+ editor.ui.actions.deleteSelection(selectionObject);
+ }
+ }
+
+ dojo.byId('canvas').focus();
+ });
+
+ // Paste
+ this.beforepasteHandle = dojo.connect(document, "beforepaste", function(e) {
+ e.preventDefault();
+ copynpaster.focus();
+ });
+
+ this.pasteHandle = dojo.connect(document, "paste", function(e) {
+ e.preventDefault();
+ var args = bespin.editor.utils.buildArgs();
+ args.chunk = e.clipboardData.getData('text/plain');
+ if (args.chunk) editor.ui.actions.insertChunk(args);
+
+ dojo.byId('canvas').focus();
+ copynpaster.value = '';
+ });
+
+ dojo.connect(document, "dom:loaded", dojo.hitch(this, function() {
+ this.keydownHandle = dojo.connect(copynpaster, "keydown", function(e) {
+ e.stopPropagation();
+ });
+
+ this.keypressHandle = dojo.connect(copynpaster, "keypress", function(e) {
+ e.stopPropagation();
+ });
+ }));
+ },
+
+ uninstall: function() {
+ dojo.disconnect(this.keypressHandle);
+ dojo.disconnect(this.keydownHandle);
+ dojo.disconnect(this.beforepasteHandle);
+ dojo.disconnect(this.pasteHandle);
+ dojo.disconnect(this.beforecutHandle);
+ dojo.disconnect(this.cutHandle);
+ dojo.disconnect(this.beforecopyHandle);
+ dojo.disconnect(this.copyHandle);
+ }
+});
+
+// ** {{{ bespin.editor.clipboard.HiddenWorld }}} **
+//
+// Exclusively grab the C, X, and V key combos and use a hidden textarea to move data around
+
+dojo.declare("bespin.editor.clipboard.HiddenWorld", null, {
+ install: function(editor) {
+
+ // * Configure the hidden copynpaster element
+ var copynpaster = dojo.create("textarea", {
+ tabIndex: '-1',
+ autocomplete: 'off',
+ id: 'copynpaster',
+ style: "position: absolute; z-index: -400; top: -100px; left: -100px; width: 0; height: 0; border: none;"
+ }, dojo.body());
+
+ var grabAndGo = function(text) {
+ copynpaster.value = text;
+ focusSelectAndGo();
+ };
+
+ var focusSelectAndGo = function() {
+ copynpaster.focus();
+ copynpaster.select();
+ setTimeout(function() {
+ dojo.byId('canvas').focus();
+ }, 0);
+ };
+
+ this.keyDown = dojo.connect(document, "keydown", function(e) {
+ if ((bespin.util.isMac() && e.metaKey) || e.ctrlKey) {
+ // Copy
+ if (e.keyCode == 67 /*c*/) {
+ // place the selection into the textarea
+ var selectionText = editor.getSelectionAsText();
+
+ if (selectionText && selectionText != '') {
+ grabAndGo(selectionText);
+ }
+
+ // Cut
+ } else if (e.keyCode == 88 /*x*/) {
+ // place the selection into the textarea
+ var selectionObject = editor.getSelection();
+
+ if (selectionObject) {
+ var selectionText = editor.model.getChunk(selectionObject);
+
+ if (selectionText && selectionText != '') {
+ grabAndGo(selectionText);
+ editor.ui.actions.deleteSelection(selectionObject);
+ }
+ }
+
+ // Paste
+ } else if (e.keyCode == 86 /*v*/) {
+ if (e.target == dojo.byId("command")) return; // let the paste happen in the command
+
+ focusSelectAndGo();
+
+ setTimeout(function() { // wait just a TOUCH to make sure that it is selected
+ var args = bespin.editor.utils.buildArgs();
+ args.chunk = copynpaster.value;
+ if (args.chunk) editor.ui.actions.insertChunk(args);
+ }, 1);
+ }
+ }
+ });
+ },
+
+ uninstall: function() {
+ dojo.disconnect(this.keyDown);
+ }
+});
+
+// ** {{{ bespin.editor.clipboard.EditorOnly }}} **
+//
+// Turn on the key combinations to access the Bespin.Clipboard.Manual class which basically only works
+// with the editor only. Not in favour.
+
+dojo.declare("bespin.editor.clipboard.EditorOnly", null, {
+ install: function() {
+ var copyArgs = bespin.util.keys.fillArguments("CMD C");
+ copyArgs.action = "copySelection";
+ bespin.publish("bespin:editor:bindkey", copyArgs);
+
+ var pasteArgs = bespin.util.keys.fillArguments("CMD V");
+ pasteArgs.action = "pasteFromClipboard";
+ bespin.publish("bespin:editor:bindkey", pasteArgs);
+
+ var cutArgs = bespin.util.keys.fillArguments("CMD X");
+ cutArgs.action = "cutSelection";
+ bespin.publish("bespin:editor:bindkey", cutArgs);
+ }
+});
+
+// ** {{{ Bespin.Clipboard.Manual }}} **
+//
+// The ugly hack that tries to use XUL to get work done, but will probably fall through to in-app copy/paste only
+bespin.editor.clipboard.Manual = function() {
+ var clipdata;
+
+ return {
+ copy: function(copytext) {
+ try {
+ if (netscape.security.PrivilegeManager.enablePrivilege) {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ } else {
+ clipdata = copytext;
+ return;
+ }
+ } catch (ex) {
+ clipdata = copytext;
+ return;
+ }
+
+ var str = Components.classes["@mozilla.org/supports-string;1"].
+ createInstance(Components.interfaces.nsISupportsString);
+ str.data = copytext;
+
+ var trans = Components.classes["@mozilla.org/widget/transferable;1"].
+ createInstance(Components.interfaces.nsITransferable);
+ if (!trans) return false;
+
+ trans.addDataFlavor("text/unicode");
+ trans.setTransferData("text/unicode", str, copytext.length * 2);
+
+ var clipid = Components.interfaces.nsIClipboard;
+ var clip = Components.classes["@mozilla.org/widget/clipboard;1"].getService(clipid);
+ if (!clip) return false;
+
+ clip.setData(trans, null, clipid.kGlobalClipboard);
+
+ /*
+ // Flash doesn't work anymore :(
+ if (inElement.createTextRange) {
+ var range = inElement.createTextRange();
+ if (range && BodyLoaded==1)
+ range.execCommand('Copy');
+ } else {
+ var flashcopier = 'flashcopier';
+ if (!document.getElementById(flashcopier)) {
+ var divholder = document.createElement('div');
+ divholder.id = flashcopier;
+ document.body.appendChild(divholder);
+ }
+ document.getElementById(flashcopier).innerHTML = '';
+
+ var divinfo = '<embed src="_clipboard.swf" FlashVars="clipboard='+escape(inElement.value)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
+ document.getElementById(flashcopier).innerHTML = divinfo;
+ }
+ */
+ },
+
+ data: function() {
+ try {
+ if (netscape.security.PrivilegeManager.enablePrivilege) {
+ netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+ } else {
+ return clipdata;
+ }
+ } catch (ex) {
+ return clipdata;
+ }
+
+ var clip = Components.classes["@mozilla.org/widget/clipboard;1"].getService(Components.interfaces.nsIClipboard);
+ if (!clip) return false;
+
+ var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
+ if (!trans) return false;
+ trans.addDataFlavor("text/unicode");
+
+ clip.getData(trans, clip.kGlobalClipboard);
+
+ var str = {};
+ var strLength = {};
+ var pastetext = "";
+
+ trans.getTransferData("text/unicode", str, strLength);
+ if (str) str = str.value.QueryInterface(Components.interfaces.nsISupportsString);
+ if (str) pastetext = str.data.substring(0, strLength.value / 2);
+ return pastetext;
+ }
+ };
+}();
Propchange: camel/trunk/components/camel-web/src/main/webapp/js/bespin/editor/clipboard.js
------------------------------------------------------------------------------
svn:eol-style = native