diff options
author | Rogan Creswick <creswick@galois.com> | 2012-03-30 17:07:02 -0700 |
---|---|---|
committer | Rogan Creswick <creswick@galois.com> | 2012-03-30 17:07:02 -0700 |
commit | f6ab6622aab00fe7c2f4c3dc41f786ebbe0f0d73 (patch) | |
tree | 870111038542cd27153e1396ebdc063573249689 /contexts/data/lib/closure-library/closure/goog/editor/.svn/text-base/link.js.svn-base |
initial revision
Diffstat (limited to 'contexts/data/lib/closure-library/closure/goog/editor/.svn/text-base/link.js.svn-base')
-rw-r--r-- | contexts/data/lib/closure-library/closure/goog/editor/.svn/text-base/link.js.svn-base | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/contexts/data/lib/closure-library/closure/goog/editor/.svn/text-base/link.js.svn-base b/contexts/data/lib/closure-library/closure/goog/editor/.svn/text-base/link.js.svn-base new file mode 100644 index 0000000..f93bf33 --- /dev/null +++ b/contexts/data/lib/closure-library/closure/goog/editor/.svn/text-base/link.js.svn-base @@ -0,0 +1,315 @@ +// Copyright 2007 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview A utility class for managing editable links. + * + * @author nicksantos@google.com (Nick Santos) + */ + +goog.provide('goog.editor.Link'); + +goog.require('goog.dom'); +goog.require('goog.dom.NodeType'); +goog.require('goog.dom.Range'); +goog.require('goog.editor.BrowserFeature'); +goog.require('goog.editor.Command'); +goog.require('goog.editor.node'); +goog.require('goog.editor.range'); +goog.require('goog.string'); +goog.require('goog.string.Unicode'); +goog.require('goog.uri.utils'); + + + +/** + * Wrap an editable link. + * @param {HTMLAnchorElement} anchor The anchor element. + * @param {boolean} isNew Whether this is a new link. + * @constructor + */ +goog.editor.Link = function(anchor, isNew) { + /** + * The link DOM element. + * @type {HTMLAnchorElement} + * @private + */ + this.anchor_ = anchor; + + /** + * Whether this link represents a link just added to the document. + * @type {boolean} + * @private + */ + this.isNew_ = isNew; +}; + + +/** + * @return {HTMLAnchorElement} The anchor element. + */ +goog.editor.Link.prototype.getAnchor = function() { + return this.anchor_; +}; + + +/** + * @return {string} The inner text for the anchor. + */ +goog.editor.Link.prototype.getCurrentText = function() { + if (!this.currentText_) { + this.currentText_ = goog.dom.getRawTextContent(this.getAnchor()); + } + return this.currentText_; +}; + + +/** + * @return {boolean} Whether the link is new. + */ +goog.editor.Link.prototype.isNew = function() { + return this.isNew_; +}; + + +/** + * Set the url without affecting the isNew() status of the link. + * @param {string} url A URL. + */ +goog.editor.Link.prototype.initializeUrl = function(url) { + this.getAnchor().href = url; +}; + + +/** + * Removes the link, leaving its contents in the document. Note that this + * object will no longer be usable/useful after this call. + */ +goog.editor.Link.prototype.removeLink = function() { + goog.dom.flattenElement(this.anchor_); + this.anchor_ = null; +}; + + +/** + * Change the link. + * @param {string} newText New text for the link. If the link contains all its + * text in one descendent, newText will only replace the text in that + * one node. Otherwise, we'll change the innerHTML of the whole + * link to newText. + * @param {string} newUrl A new URL. + */ +goog.editor.Link.prototype.setTextAndUrl = function(newText, newUrl) { + var anchor = this.getAnchor(); + anchor.href = newUrl; + + // If the text did not change, don't update link text. + var currentText = this.getCurrentText(); + if (newText != currentText) { + var leaf = goog.editor.node.getLeftMostLeaf(anchor); + if (leaf.nodeType == goog.dom.NodeType.TEXT) { + leaf = leaf.parentNode; + } + + if (goog.dom.getRawTextContent(leaf) != currentText) { + leaf = anchor; + } + + goog.dom.removeChildren(leaf); + + var domHelper = goog.dom.getDomHelper(leaf); + goog.dom.appendChild(leaf, domHelper.createTextNode(newText)); + + // The text changed, so force getCurrentText to recompute. + this.currentText_ = null; + } + + this.isNew_ = false; +}; + + +/** + * Places the cursor to the right of the anchor. + * Note that this is different from goog.editor.range's placeCursorNextTo + * in that it specifically handles the placement of a cursor in browsers + * that trap you in links, by adding a space when necessary and placing the + * cursor after that space. + */ +goog.editor.Link.prototype.placeCursorRightOf = function() { + var anchor = this.getAnchor(); + // If the browser gets stuck in a link if we place the cursor next to it, + // we'll place the cursor after a space instead. + if (goog.editor.BrowserFeature.GETS_STUCK_IN_LINKS) { + var spaceNode; + var nextSibling = anchor.nextSibling; + + // Check if there is already a space after the link. Only handle the + // simple case - the next node is a text node that starts with a space. + if (nextSibling && + nextSibling.nodeType == goog.dom.NodeType.TEXT && + (goog.string.startsWith(nextSibling.data, goog.string.Unicode.NBSP) || + goog.string.startsWith(nextSibling.data, ' '))) { + spaceNode = nextSibling; + } else { + // If there isn't an obvious space to use, create one after the link. + var dh = goog.dom.getDomHelper(anchor); + spaceNode = dh.createTextNode(goog.string.Unicode.NBSP); + goog.dom.insertSiblingAfter(spaceNode, anchor); + } + + // Move the selection after the space. + var range = goog.dom.Range.createCaret(spaceNode, 1); + range.select(); + } else { + goog.editor.range.placeCursorNextTo(anchor, false); + } +}; + + +/** + * Updates the cursor position and link bubble for this link. + * @param {goog.editor.Field} field The field in which the link is created. + * @param {string} url The link url. + * @private + */ +goog.editor.Link.prototype.updateLinkDisplay_ = function(field, url) { + this.initializeUrl(url); + this.placeCursorRightOf(); + field.execCommand(goog.editor.Command.UPDATE_LINK_BUBBLE); +}; + + +/** + * After link creation, finish creating the link depending on the type + * of link being created. + * @param {goog.editor.Field} field The field where this link is being created. + */ +goog.editor.Link.prototype.finishLinkCreation = function(field) { + var text = this.getCurrentText(); + if (goog.editor.Link.isLikelyUrl(text)) { + if (text.search(/:/) < 0) { + text = 'http://' + goog.string.trimLeft(text); + } + this.updateLinkDisplay_(field, text); + } else if (goog.editor.Link.isLikelyEmailAddress(text)) { + text = 'mailto:' + text; + this.updateLinkDisplay_(field, text); + } else { + field.execCommand(goog.editor.Command.MODAL_LINK_EDITOR, this); + } +}; + + +/** + * Initialize a new link. + * @param {HTMLAnchorElement} anchor The anchor element. + * @param {string} url The initial URL. + * @param {string=} opt_target The target. + * @return {goog.editor.Link} The link. + */ +goog.editor.Link.createNewLink = function(anchor, url, opt_target) { + var link = new goog.editor.Link(anchor, true); + link.initializeUrl(url); + + if (opt_target) { + anchor.target = opt_target; + } + + return link; +}; + + +/** + * Returns true if str could be a URL, false otherwise + * + * Ex: TR_Util.isLikelyUrl_("http://www.google.com") == true + * TR_Util.isLikelyUrl_("www.google.com") == true + * + * @param {string} str String to check if it looks like a URL. + * @return {boolean} Whether str could be a URL. + */ +goog.editor.Link.isLikelyUrl = function(str) { + // Whitespace means this isn't a domain. + if (/\s/.test(str)) { + return false; + } + + if (goog.editor.Link.isLikelyEmailAddress(str)) { + return false; + } + + // Add a scheme if the url doesn't have one - this helps the parser. + var addedScheme = false; + if (!/^[^:\/?#.]+:/.test(str)) { + str = 'http://' + str; + addedScheme = true; + } + + // Parse the domain. + var parts = goog.uri.utils.split(str); + + // Relax the rules for special schemes. + var scheme = parts[goog.uri.utils.ComponentIndex.SCHEME]; + if (goog.array.indexOf(['mailto', 'aim'], scheme) != -1) { + return true; + } + + // Require domains to contain a '.', unless the domain is fully qualified. + var domain = parts[goog.uri.utils.ComponentIndex.DOMAIN]; + if (!domain || (addedScheme && domain.indexOf('.') == -1)) { + return false; + } + + // Require http and ftp paths to start with '/'. + var path = parts[goog.uri.utils.ComponentIndex.PATH]; + return !path || path.indexOf('/') == 0; +}; + + +/** + * Regular expression that matches strings that could be an email address. + * @type {RegExp} + * @private + */ +goog.editor.Link.LIKELY_EMAIL_ADDRESS_ = new RegExp( + '^' + // Test from start of string + '[\\w-]+(\\.[\\w-]+)*' + // Dot-delimited alphanumerics and dashes (name) + '\\@' + // @ + '([\\w-]+\\.)+' + // Alphanumerics, dashes and dots (domain) + '(\\d+|\\w\\w+)$', // Domain ends in at least one number or 2 letters + 'i'); + + +/** + * Returns true if str could be an email address, false otherwise + * + * Ex: goog.editor.Link.isLikelyEmailAddress_("some word") == false + * goog.editor.Link.isLikelyEmailAddress_("foo@foo.com") == true + * + * @param {string} str String to test for being email address. + * @return {boolean} Whether "str" looks like an email address. + */ +goog.editor.Link.isLikelyEmailAddress = function(str) { + return goog.editor.Link.LIKELY_EMAIL_ADDRESS_.test(str); +}; + + +/** + * Determines whether or not a url is an email link. + * @param {string} url A url. + * @return {boolean} Whether the url is a mailto link. + */ +goog.editor.Link.isMailto = function(url) { + return !!url && goog.string.startsWith(url, 'mailto:'); +}; |