123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- /*
- Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
- Available via Academic Free License >= 2.1 OR the modified BSD license.
- see: http://dojotoolkit.org/license for details
- */
- if(!dojo._hasResource["dojox.editor.plugins.AutoUrlLink"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
- dojo._hasResource["dojox.editor.plugins.AutoUrlLink"] = true;
- dojo.provide("dojox.editor.plugins.AutoUrlLink");
- dojo.require("dojo.string");
- dojo.require("dijit._editor._Plugin");
- dojo.require("dijit.form.Button");
- dojo.declare("dojox.editor.plugins.AutoUrlLink", [dijit._editor._Plugin], {
- //summary:
- // This plugin can recognize a URL like string
- // (such as http://www.website.com) and turn it into
- // a hyperlink that points to that URL.
-
- // _template [private] String
- // The link template
- _template: "<a _djrealurl='${url}' href='${url}'>${url}</a>",
-
- setEditor: function(/*dijit.Editor*/ editor){
- // summary:
- // Called by the editor it belongs to.
- // editor:
- // The editor it belongs to.
- this.editor = editor;
- if(!dojo.isIE){
- // IE will recognize URL as a link automatically
- // No need to re-invent the wheel.
- dojo.some(editor._plugins, function(plugin){
- // Need to detect which enter key mode it is now
- if(plugin.isInstanceOf(dijit._editor.plugins.EnterKeyHandling)){
- this.blockNodeForEnter = plugin.blockNodeForEnter;
- return true;
- }
- return false;
- }, this);
- this.connect(editor, "onKeyPress", "_keyPress");
- this.connect(editor, "onClick", "_recognize");
- this.connect(editor, "onBlur", "_recognize");
- }
- },
-
- _keyPress: function(evt){
- // summary:
- // Handle the keypress event and dispatch it to the target handler
- // evt:
- // The keypress event object.
- // tags:
- // protected
- var ks = dojo.keys, v = 118, V = 86,
- kc = evt.keyCode, cc = evt.charCode;
- if(cc == ks.SPACE || (evt.ctrlKey && (cc == v || cc == V))){
- setTimeout(dojo.hitch(this, "_recognize"), 0);
- }else if(kc == ks.ENTER){
- // Handle the enter event after EnterKeyHandling finishes its job
- setTimeout(dojo.hitch(this, function(){
- this._recognize({enter: true});
- }), 0);
- }else{
- // _saved: The previous dom node when the cursor is at a new dom node.
- // When we click elsewhere, the previous dom node
- // should be examed to see if there is any URL need to be activated
- this._saved = this.editor.window.getSelection().anchorNode;
- }
- },
-
- _recognize: function(args){
- // summary:
- // Recognize the URL like strings and turn them into a link
- // tags:
- // private
- var template = this._template,
- isEnter = args ? args.enter : false,
- ed = this.editor,
- selection = ed.window.getSelection();
- if(selection){
- var node = isEnter ? this._findLastEditingNode(selection.anchorNode) :
- (this._saved || selection.anchorNode),
- bm = this._saved = selection.anchorNode,
- bmOff = selection.anchorOffset;
-
- if(node.nodeType == 3 && !this._inLink(node)){
- var linked = false, result = this._findUrls(node, bm, bmOff),
- range = ed.document.createRange(),
- item, cost = 0, isSameNode = (bm == node);
-
- item = result.shift();
- while(item){
- // Covert a URL to a link.
- range.setStart(node, item.start);
- range.setEnd(node, item.end);
- selection.removeAllRanges();
- selection.addRange(range);
- ed.execCommand("insertHTML", dojo.string.substitute(template, {url: range.toString()}));
- cost += item.end;
- item = result.shift();
- linked = true;
- }
-
- // If bm and node are the some dom node, caculate the actual bookmark offset
- // If the position of the cursor is modified (turned into a link, etc.), no
- // need to recover the cursor position
- if(isSameNode && (bmOff = bmOff - cost) <= 0){ return; }
-
- // We didn't update anything, so don't collapse selections.
- if(!linked) { return ; }
- try{
- // Try to recover the cursor position
- range.setStart(bm, 0);
- range.setEnd(bm, bmOff);
- selection.removeAllRanges();
- selection.addRange(range);
- dojo.withGlobal(ed.window, "collapse", dijit._editor.selection, []);
- }catch(e){}
- }
- }
- },
-
- _inLink: function(/*DomNode*/ node){
- // summary:
- // Check if the node is already embraced within a <a>...</a> tag.
- // node:
- // The node to be examed.
- // tags:
- // private
- var editNode = this.editor.editNode,
- result = false, tagName;
-
- node = node.parentNode;
- while(node && node !== editNode){
- tagName = node.tagName ? node.tagName.toLowerCase() : "";
- if(tagName == "a"){
- result = true;
- break;
- }
- node = node.parentNode;
- }
- return result;
- },
-
- _findLastEditingNode: function(/*DomNode*/ node){
- // summary:
- // Find the last node that was edited so that we can
- // get the last edited text.
- // node:
- // The current node that the cursor is at.
- // tags:
- // private
- var blockTagNames = dijit.range.BlockTagNames,
- editNode = this.editor.editNode, blockNode;
- if(!node){ return node; }
- if(this.blockNodeForEnter == "BR" &&
- (!(blockNode = dijit.range.getBlockAncestor(node, null, editNode).blockNode) ||
- blockNode.tagName.toUpperCase() != "LI")){
- while((node = node.previousSibling) && node.nodeType != 3){}
- }else{
- // EnterKeyHandling is under "DIV" or "P" mode or
- // it's in a LI element. Find the last editing block
- if((blockNode || (blockNode = dijit.range.getBlockAncestor(node, null, editNode).blockNode)) &&
- blockNode.tagName.toUpperCase() == "LI"){
- node = blockNode;
- }else{
- node = dijit.range.getBlockAncestor(node, null, editNode).blockNode;
- }
- // Find the last editing text node
- while((node = node.previousSibling) && !(node.tagName && node.tagName.match(blockTagNames))){}
- if(node){
- node = node.lastChild;
- while(node){
- if(node.nodeType == 3 && dojo.trim(node.nodeValue) != ""){
- break;
- }else if(node.nodeType == 1){
- node = node.lastChild;
- }else{
- node = node.previousSibling;
- }
- }
- }
- }
- return node;
- },
-
- _findUrls: function(/*DomNode*/ node, /*DomNode*/ bm, /*Number*/ bmOff){
- // summary:
- // Find the occurrace of the URL strings.
- // FF, Chrome && Safri have a behavior that when insertHTML is executed,
- // the orignal referrence to the text node will be the text node next to
- // the inserted anchor automatically. So we have to re-caculate the index of
- // the following URL occurrence.
- // value:
- // A text to be scanned.
- // tags:
- // private
- var pattern = /(http|https|ftp):\/\/[^\s]+/ig,
- list = [], baseIndex = 0,
- value = node.nodeValue, result, ch;
-
- if(node === bm && bmOff < value.length){
- // Break the text so that it may not grab extra words.
- // Such as if you type:
- // foo http://foo.com|bar (And | is where you press enter).
- // It will grab the bar word as part of the link. That's annoying/bad.
- // Also it prevents recognizing the text after the cursor.
- value = value.substr(0, bmOff);
- }
-
- while((result = pattern.exec(value)) != null){
- if(result.index == 0 || (ch = value.charAt(result.index - 1)) == " " || ch == "\xA0"){
- list.push({start: result.index - baseIndex, end: result.index + result[0].length - baseIndex});
- baseIndex = result.index + result[0].length;
- }
- }
- return list;
- }
- });
- // Register this plugin.
- dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){
- if(o.plugin){ return; }
- var name = o.args.name.toLowerCase();
- if(name === "autourllink"){
- o.plugin = new dojox.editor.plugins.AutoUrlLink();
- }
- });
- }
|