Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

english documentation

  • Loading branch information...
commit 14f864480304f8b8ac347088ebe2acf77371f7fe 1 parent aa5bf5f
@molily authored
Showing with 395 additions and 123 deletions.
  1. +137 −10 README
  2. +130 −56 copylink.js
  3. +1 −0  selectionmenu.html
  4. +127 −57 selectionmenu.js
View
147 README
@@ -1,10 +1,137 @@
-Kleines Framework-unabhängiges JavaScript, welches beim Markieren von Text
-ein Kontextmenü anzeigt. Idee und Umsetzung ähnelt der auf nytimes.com.
-Das Script ist jedoch einfacher und universell einsetzbarer.
-
-Das Script nutzt DOM-Ranges bzw. TextRanges im IE. Es fügt ein Inline-Element
-ans Ende des markierten Textes ein. Das kann Links enthalten, z.B. um Wörter
-nachzuschlagen oder Begriffe zu suchen.
-
-Autor: Mathias Schäfer (molily) <zapperlott@gmail.com>
-Lizenz: Public Domain
+Deutsche Beschreibung:
+----------------------
+
+SelectionMenu und CopyLink sind kleine, framework-unabhängige JavaScript.
+
+SelectionMenu zeigt beim Markieren von Text ein Kontextmenü an. Die Idee und
+Umsetzung ähnelt der auf nytimes.com. Das Script ist jedoch einfacher und universell
+einsetzbar.
+
+CopyLink fügt eine Quellenreferenz ein, wenn der Benutzer Text markiert und in die
+Zwischenablage kopiert. Wenn beispielsweise »Franz jagt im komplett verwahrlosten Taxi«
+kopiert wird, so wird die URL der aktuellen Webseite an den kopierten Text angehangen:
+
+»Franz jagt im komplett verwahrlosten Taxi
+Quelle: http://example.net/article1234«
+
+Beide Scripte verwenden W3C DOM Range
+<http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html> in modernen Browsern sowie
+Microsoft TextRanges <http://msdn.microsoft.com/en-us/library/ms535872(v=vs.85).aspx>
+für ältere Internet-Explorer-Versionen.
+
+Ausführliche Dokumentation:
+http://molily.de/weblog/selectionmenu-copylink
+
+Autor: Mathias Schäfer (molily) <zapperlott@gmail.com>
+Lizenz: Public Domain
+
+
+English Description:
+--------------------
+
+SelectionMenu and CopyLink are small self-contained, framework-agnostic scripts
+which demonstrate the abilities of the JavaScript APIs DOM Range and Microsoft
+Text Ranges.
+
+SelectionMenu shows a context menu when the user selects some text on the page.
+This menu may offer a search feature, dictionary lookup, post to Facebook or similar.
+The idea and the implementation resembles the selection context menu on nytimes.com,
+but the script is way simpler and easy to integrate.
+
+CopyLink inserts a source reference when the user copys a piece of text into the
+clipboard. For example, if the user selects the text “The quick brown fox” and copys
+it, the URL of the current page will be appended:
+
+“The quick brown fox
+Source: http://example.net/article1234”
+
+Both scripts are using W3C DOM Range
+<http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html> in modern browsers
+and Microsoft TextRanges <http://msdn.microsoft.com/en-us/library/ms535872(v=vs.85).aspx>
+as a fallback for older Internet Explorer versions.
+
+Author: Mathias Schäfer (molily) <zapperlott@gmail.com>
+License: Public Domain
+
+
+SelectionMenu Usage:
+--------------------
+
+Create an instance of SelectionMenu by calling “new SelectionMenu”.
+
+Pass an object literal with the following options:
+ container (DOM element):
+ The element where the copy event is observed. Normally that's
+ the main text container.
+ menuHTML (string):
+ A string of HTML for the menu e.g. a list of links.
+ handler (function):
+ A handler function which is called when the user clicks on the menu.
+ Use the passed click event to access the click link and respond to
+ the user's action.
+ minimalSelection (number, optional):
+ Only display the menu if the selected text has at least this length.
+ Defaults to 5 characters.
+ id (string, optional):
+ The ID of the menu element which is inserted. Defaults to “selection-menu”.
+
+Example:
+--------
+
+This observes copy events at the element with the ID “article”. It inserts a menu
+with two links which both have IDs to recognize them. In the handler function, the
+selected text is read. Depending on the clicked link, the selected text is
+looked up on Google or Bing.
+
+new SelectionMenu({
+ container : document.getElementById('article'),
+ menuHTML : '<a id="selection-menu-google">Google Search</a><a id="selection-menu-bing">Bing Search</a>',
+ handler : function (e) {
+ var target = e.target || e.srcElement,
+ id = target.id,
+ selectedText = this.selectedText,
+ query = encodeURI(selectedText.replace(/\s/g, '+')),
+ searchURI;
+
+ if (id == 'selection-menu-google') {
+ searchURI = 'http://www.google.com/search?ie=utf-8&q=';
+ } else if (id == 'selection-menu-bing') {
+ searchURI = 'http://www.bing.com/search?q=';
+ }
+
+ location.href = searchURI + query;
+ }
+});
+
+
+CopyLink Usage:
+---------------
+
+Create an instance of SelectionMenu by calling “new CopyLink”.
+
+Pass an object literal with the following options:
+ container (DOM element):
+ The element where the copy event is observed. Normally that's
+ the main text container.
+ handler (function, optional):
+ A handler function which is called when the user copys some text.
+ This function should return a string which is appended to the
+ copied text.
+ Defaults to '<br>Source: ' + location.href, e.g. “Source:” and the
+ URL of the current document.
+ minimalSelection (number, optional):
+ Only append a source reference if the selected text has at least this length.
+ Defaults to 20 characters.
+
+Example:
+--------
+
+This observes copy events at the element with the ID “article”. It appends the
+string “Source: <URL>” when the user copys text which is longer than 20 characters.
+
+new CopyLink({
+ container : document.getElementById('article'),
+ handler : function () {
+ return '<br>Source: ' + location.href;
+ }
+});
View
186 copylink.js
@@ -1,21 +1,34 @@
/*
CopyLink 1.0
http://github.com/molily/selectionmenu
-von molily (zapperlott@gmail.com, http://molily.de/)
-Lizenz: Public Domain / Kopieren, Verteilen und Aendern ohne Einschraenkungen erlaubt
+by molily (zapperlott@gmail.com, http://molily.de/)
+
+EN: CopyLink automatically inserts a source reference when the user copies text from a page
+DE: CopyLink fügt automatisch eine Quellenreferenz ein, wenn der Benutzer Text von einer Seite kopiert
+
+EN: License: Public Domain
+EN: You're allowed to copy, distribute and change the code without restrictions
+
+DE: Lizenz: Public Domain
+DE: Kopieren, Verteilen und Aendern ohne Einschraenkungen erlaubt
*/
-// Erzeuge einen privaten Scope durch eine anonyme Funktion,
-// speichere den Rückgabwert in einer globalen Variable
+// EN: Create a private scope using an anonymous function,
+// EN: save the return value in a global variable.
+// DE: Erzeuge einen privaten Scope durch eine anonyme Funktion,
+// DE: speichere den Rückgabwert in einer globalen Variable
var CopyLink = (function (window, document) {
- var id = 'copylink';
+ // EN: The element which is inserted when copying
+ // DE: Das Element, welche beim Kopieren eingefügt wird
var span = null;
- // Geteilte private Helferfunktionen
+ // EN: Shared private helper functions
+ // DE: Geteilte private Helferfunktionen
function addEvent (obj, type, fn) {
- // Fähigkeitenweiche DOM Events / Microsoft
+ // EN: Feature dection DOM Events / Microsoft
+ // DE: Fähigkeitenweiche DOM Events / Microsoft
if (obj.addEventListener) {
obj.addEventListener(type, fn, false);
} else if (obj.attachEvent) {
@@ -25,47 +38,61 @@ var CopyLink = (function (window, document) {
}
}
- // Mache addEvent als statische Methode öffentlich
- // (hefte die Methode an den Konstruktor, der zurückgegeben wird)
+ // EN: Publish addEvent as a static method
+ // EN: (attach it to the constructor object)
+ // DE: Mache addEvent als statische Methode öffentlich
+ // DE: (hefte die Methode an den Konstruktor, der zurückgegeben wird)
CopyLink.addEvent = addEvent;
function getSelection () {
- // Fähigkeitenweiche HTML5 / Microsoft
+ // EN: Feature dection HTML5 / Microsoft
+ // DE: Fähigkeitenweiche HTML5 / Microsoft
if (window.getSelection) {
return window.getSelection();
} else if (document.selection && document.selection.createRange) {
return document.selection.createRange();
} else {
- // Keine Browser-Unterstützung für die benötigten Features
+ // EN: No browser support available for the required features
+ // DE: Keine Browser-Unterstützung für die benötigten Features
return false;
}
}
function getSelectedText (selection) {
- // Fähigkeitenweiche HTML5 / Microsoft
+ // EN : Feature detection HTML5 / Microsoft
+ // DE: Fähigkeitenweiche HTML5 / Microsoft
return selection.toString ? selection.toString() : selection.text;
}
function removeSpan () {
+ // EN: Is the element attached to the DOM tree?
+ // DE: Ist das Element in den DOM-Baum gehängt?
var parent = span.parentNode;
if (parent) {
- // Entferne span aus dem DOM-Baum
+ // EN: Remove the element from DOM (the element object remains
+ // EN: in memory and will be reused later)
+ // DE: Entferne das element aus dem DOM-Baum (Element bleibt im Speicher erhalten
+ // DE: und wird später wiederverwendet)
parent.removeChild(span);
}
}
- // Konstruktorfunktion
+ // EN: Main constructor function
+ // DE: Konstruktorfunktion
function CopyLink (options) {
var instance = this;
- // Kopiere Einstellungen aus dem options-Objekt herüber zur Instanz
+ // EN: Copy members from the options object to the instance
+ // DE: Kopiere Einstellungen aus dem options-Objekt herüber zur Instanz
+ instance.id = options.id || 'copylink';
instance.minimalSelection = options.minimalSelection || 20;
instance.container = options.container;
instance.handler = options.handler || function () {
return '<br>Source: ' + location.href;
};
- // Initialisiere
+ // EN: Initialisation
+ // DE: Initialisiere
instance.create();
instance.setupEvents();
}
@@ -75,13 +102,13 @@ var CopyLink = (function (window, document) {
create : function () {
var instance = this;
- // Erzeuge den Menü-Container, wenn noch nicht passiert
+ // EN: Create the container for the inserted text if necessary
+ // DE: Erzeuge den Container für den eingefügten Text, sofern noch nicht passiert
if (span) {
return;
}
-
span = document.createElement('span');
- span.id = id;
+ span.id = instance.id;
span.style.cssText = 'position: absolute; left: -9999px;';
},
@@ -95,49 +122,61 @@ var CopyLink = (function (window, document) {
insert : function () {
var instance = this;
- // Hole Selection bzw. TextRange (IE)
+ // EN: Get a Selection object or a TextRange (IE)
+ // DE: Hole Selection bzw. TextRange (IE)
var selection = getSelection();
if (!selection) {
- // Keine Browser-Unterstützung für die benötigten Features
+ // EN: No browser support available for the required features
+ // DE: Keine Browser-Unterstützung für die benötigten Features
return;
}
- // Hole markierten Text
+ // EN: Get the selected text
+ // DE: Hole markierten Text
var selectedText = getSelectedText(selection);
- // Breche ab, wenn der markierte Text zu kurz ist
+ // EN: Abort if the selected text is too short
+ // DE: Breche ab, wenn der markierte Text zu kurz ist
if (selectedText.length < instance.minimalSelection) {
return;
}
- // Fähigkeitenweiche DOM Range / Microsoft
+ // EN : Feature detection DOM Range / Microsoft
+ // DE: Fähigkeitenweiche DOM Range / Microsoft
if (selection.getRangeAt) {
- // Hole Range, die zur Selection gehört
- var range = selection.getRangeAt(0);
+ // EN: W3C DOM Range approach
+ // DE: Lösungsansatz mit W3C DOM Range
- // Erzeuge neue, leere Range
- var newRange = document.createRange();
+ // EN: Get the first Range of the current Selection
+ // DE: Hole Range, die zur Selection gehört
+ var range = selection.getRangeAt(0);
- // Hole Start- und Endknoten der Auswahl
+ // EN: Get the start and end nodes of the selection
+ // DE: Hole Start- und Endknoten der Auswahl
var startNode = range.startContainer;
var endNode = range.endContainer;
if (!(startNode && endNode && startNode.compareDocumentPosition)) {
+ // EN: Abort if we got bogus values or we can't compare their document position
+ // DE: Breche ab, wenn die Knoten nicht brauchbar sind
return;
}
- // Korrektur: Wenn von hinten nach vorne markiert wurde, drehe Start und Ende um
+ // EN: If the start node succeeds the end node in the DOM tree, flip them
+ // DE: Wenn von hinten nach vorne markiert wurde, drehe Start und Ende um
if (startNode.compareDocumentPosition(endNode) & 2) {
startNode = endNode;
endNode = range.startContainer;
}
- // Hole Start- und End-Offset
+ // EN: Get the start and end offset
+ // DE: Hole Start- und End-Offset
var startOffset = range.startOffset;
var endOffset = range.endOffset;
- // Korrektur: Falls der Endknoten ein Element ist, nehme das Ende des letzten Textknoten
+ // EN: If the end node is an element, use its last text node as the end offset
+ // DE: Falls der Endknoten ein Element ist, nehme das Ende des letzten Textknoten
if (endNode.nodeType == 1) {
var endNode = endNode.lastChild;
if (!endNode || endNode.nodeType != 3) {
@@ -146,71 +185,106 @@ var CopyLink = (function (window, document) {
endOffset = endNode.data.length;
}
- // Verschiebe Anfang der neuen Range an das Ende der Auswahl
+ // EN: Create a new empty Range
+ // DE: Erzeuge neue, leere Range
+ var newRange = document.createRange();
+
+ // EN: Move the beginning of the new Range to the end of the selection
+ // DE: Verschiebe Anfang der neuen Range an das Ende der Auswahl
newRange.setStart(endNode, endOffset);
- // Befülle Menü-Span
- span.innerHTML = instance.handler();
+ // EN: Fill the span containing the source reference
+ // DE: Befülle das span-Element mit der Quellenreferenz
+ span.innerHTML = instance.handler.call(instance);
- // Füge das span-Element in die neue Range ein
+ // EN: Inject the span element into the new Range
+ // DE: Füge das span-Element in die neue Range ein
newRange.insertNode(span);
- // Erweitere Range nach vorne, um die ursprüngliche einzuschließen
+ // EN: Enlarge the Range forward to enclose the original Range
+ // DE: Erweitere Range nach vorne, um die ursprüngliche einzuschließen
- // Schließe span in die Auswahl ein
+ // EN: Include the span into the selection
+ // DE: Schließe span in die Auswahl ein
range.setEndAfter(span);
- // Selektiere Range
+ // EN: Now select the whole text in the new range.
+ // EN: This text is copied to the clipboard.
+ // DE: Markiere den Text der Range, damit dieser in
+ // DE: die Zwischenablage kopiert wird
selection.removeAllRanges();
selection.addRange(range);
window.setTimeout(function () {
- // Entferne span wieder aus der Auswahl
+ // EN: Remove the span from the selection
+ // DE: Entferne span wieder aus der Auswahl
range.setEndBefore(span);
- // Selektiere Range (stelle ursprüngliche Auswahl wieder her)
- selection.removeAllRanges();
+ // EN: Restore the original range and its text selection
+ // DE: Stelle die ursprüngliche Range und damit die ursprüngliche Textauswahl wieder her
+ if (selection.removeRange) {
+ selection.removeRange(range);
+ } else {
+ selection.removeAllRanges();
+ }
selection.addRange(range);
- // Entferne span wieder aus dem DOM
+ // EN: Remove the span from the DOM tree
+ // DE: Entferne span wieder aus dem DOM
removeSpan();
}, 0);
} else if (selection.duplicate) {
- // Kopiere TextRange
+ // EN: Microsoft TextRange approach
+ // DE: Lösungsansatz mit Microsoft TextRanges
+
+ // EN: Create a copy the the TextRange
+ // DE: Kopiere TextRange
var newRange = selection.duplicate();
- // Verschiebe Anfang der neuen Range an das Ende der Auswahl
+ // EN: Move the start of the new range to the end of the selection
+ // DE: Verschiebe den Anfang der neuen Range an das Ende der Auswahl
newRange.setEndPoint('StartToEnd', selection);
- // Befülle Menü-Span
- span.innerHTML = instance.handler();
+ // EN: Fill the span containing the source reference
+ // DE: Befülle das span-Element mit der Quellenreferenz
+ span.innerHTML = instance.handler.call(instance);
- // Fülle die neue Range mit dem span
+ // EN: Insert the span into the new range
+ // DE: Fülle die neue Range mit dem span
newRange.pasteHTML(span.outerHTML);
- // Schließe eingefügte Range in die Auswahl ein
+ // EN: Add the new TextRange to the current selection
+ // DE: Schließe eingefügte TextRange in die Auswahl ein
selection.setEndPoint('EndToEnd', newRange);
- // Selektiere den Inhalt der Range
+ // EN: Select the text of the TextRange
+ // EN: This text is copied to the clipboard.
+ // DE: Markiere den Textinhalt der TextRange, damit dieser in
+ // DE: die Zwischenablage kopiert wird
selection.select();
- // Da das Befüllen nicht über das DOM, sondern über serialisierten HTML-Code erfolgt,
- // stelle die Referenz wieder her
+ // EN: Since we're using outerHTML to insert the span element,
+ // EN: we have to restore the span reference
+ // DE: Da das Befüllen nicht über das DOM, sondern über serialisierten HTML-Code erfolgt,
+ // DE: stelle die Referenz wieder her
span = document.getElementById(id);
- // Entferne span wieder aus dem DOM
+ // EN: Remove the span from the DOM tree
+ // DE: Entferne span wieder aus dem DOM
window.setTimeout(removeSpan, 0);
- } else {
- // Keine Browser-Unterstützung für die benötigten Features
- return;
}
+ // EN: No browser support available for the required features
+ // DE: Keine Browser-Unterstützung für die benötigten Features
+
}
};
+ // EN: Return the constructor function
+ // DE: Gib den Konstruktor zurück
return CopyLink;
})(window, document);
View
1  selectionmenu.html
@@ -22,6 +22,7 @@
new SelectionMenu({
container : document.getElementById('article'),
+ id : 'selection-menu',
menuHTML : '<a id="selection-menu-google">Google-Suche</a><a id="selection-menu-bing">Bing-Suche</a>',
handler : function (e) {
var target = e.target || e.srcElement,
View
184 selectionmenu.js
@@ -1,21 +1,34 @@
/*
SelectionMenu 1.0
http://github.com/molily/selectionmenu
-von molily (zapperlott@gmail.com, http://molily.de/)
-Lizenz: Public Domain / Kopieren, Verteilen und Aendern ohne Einschraenkungen erlaubt
+by molily (zapperlott@gmail.com, http://molily.de/)
+
+EN: SelectionMenu displays a context menu when the user selects some text on the page
+DE: SelectionMenu blendet ein Kontextmenü beim Markieren von Text ein
+
+EN: License: Public Domain
+EN: You're allowed to copy, distribute and change the code without restrictions
+
+DE: Lizenz: Public Domain
+DE: Kopieren, Verteilen und Aendern ohne Einschraenkungen erlaubt
*/
-// Erzeuge einen privaten Scope durch eine anonyme Funktion,
-// speichere den Rückgabwert in einer globalen Variable
+// EN: Create a private scope using an anonymous function,
+// EN: save the return value in a global variable.
+// DE: Erzeuge einen privaten Scope durch eine anonyme Funktion,
+// DE: speichere den Rückgabwert in einer globalen Variable
var SelectionMenu = (function (window, document) {
- var id = 'selection-menu';
+ // EN: The menu element which is inserted when selecting text
+ // DE: Das Menü-Element, welche beim Markieren eingefügt wird
var span = null;
- // Geteilte private Helferfunktionen
+ // EN: Shared private helper functions
+ // DE: Geteilte private Helferfunktionen
function addEvent (obj, type, fn) {
- // Fähigkeitenweiche DOM Events / Microsoft
+ // EN: Feature dection DOM Events / Microsoft
+ // DE: Fähigkeitenweiche DOM Events / Microsoft
if (obj.addEventListener) {
obj.addEventListener(type, fn, false);
} else if (obj.attachEvent) {
@@ -25,51 +38,63 @@ var SelectionMenu = (function (window, document) {
}
}
- // Mache addEvent als statische Methode öffentlich
- // (hefte die Methode an den Konstruktor, der zurückgegeben wird)
+ // EN: Publish addEvent as a static method
+ // EN: (attach it to the constructor object)
+ // DE: Mache addEvent als statische Methode öffentlich
+ // DE: (hefte die Methode an den Konstruktor, der zurückgegeben wird)
SelectionMenu.addEvent = addEvent;
function getSelection () {
- // Fähigkeitenweiche HTML5 / Microsoft
+ // EN: Feature dection HTML5 / Microsoft
+ // DE: Fähigkeitenweiche HTML5 / Microsoft
if (window.getSelection) {
return window.getSelection();
} else if (document.selection && document.selection.createRange) {
return document.selection.createRange();
} else {
- // Keine Browser-Unterstützung für die benötigten Features
+ // EN: No browser support available for the required features
+ // DE: Keine Browser-Unterstützung für die benötigten Features
return false;
}
}
function getSelectedText (selection) {
- // Fähigkeitenweiche HTML5 / Microsoft
+ // EN: Feature detection HTML5 / Microsoft
+ // DE: Fähigkeitenweiche HTML5 / Microsoft
return selection.toString ? selection.toString() : selection.text;
}
+
function contains (a, b) {
- // Fähigkeitenweiche DOM Core / Microsoft
+ // EN: Feature detection DOM Core / Microsoft
+ // DE: Fähigkeitenweiche DOM Core / Microsoft
return a.compareDocumentPosition ? !!(a.compareDocumentPosition(b) & 16) : a.contains(b);
}
function mouseOnMenu (e) {
// Greife auf das Zielelement des Ereignisses zu
- // Fähigkeitenweiche DOM Events / Microsoft
+ // EN: Feature detection DOM Events / Microsoft
+ // DE: Fähigkeitenweiche DOM Events / Microsoft
var target = e.target || e.srcElement;
// Ist das Zielelement das Menü oder darin enthalten?
return target == span || contains(span, target);
}
- // Konstruktorfunktion
+ // EN: Main constructor function
+ // DE: Konstruktorfunktion
function SelectionMenu (options) {
var instance = this;
- // Kopiere Einstellungen aus dem options-Objekt herüber zur Instanz
+ // EN: Copy members from the options object to the instance
+ // DE: Kopiere Einstellungen aus dem options-Objekt herüber zur Instanz
+ instance.id = options.id || 'selection-menu';
instance.menuHTML = options.menuHTML;
instance.minimalSelection = options.minimalSelection || 5;
instance.container = options.container;
instance.handler = options.handler;
- // Initialisiere
+ // EN: Initialisation
+ // DE: Initialisiere
instance.create();
instance.setupEvents();
}
@@ -79,13 +104,14 @@ var SelectionMenu = (function (window, document) {
create : function () {
var instance = this;
- // Erzeuge den Menü-Container, wenn noch nicht passiert
+ // EN: Create the menu container if necessary
+ // DE: Erzeuge den Menü-Container, sofern noch nicht passiert
if (span) {
return;
}
span = document.createElement('span');
- span.id = id;
+ span.id = instance.id;
},
setupEvents : function () {
@@ -93,17 +119,19 @@ var SelectionMenu = (function (window, document) {
var instance = this;
var container = instance.container;
- // Verstecke beim Mousedown
+ // EN: Hide the menu on mouse down
+ // DE: Verstecke beim Mousedown
addEvent(container, 'mousedown', function (e) {
instance.hide(e);
});
- // Füge ein beim Mouseup (wenn Text ausgewählt wurde)
+ // EN: Insert the menu on mouseup given some text is selected
+ // DE: Füge das Menü beim Mouseup ein, wenn Text ausgewählt wurde
addEvent(container, 'mouseup', function (e) {
instance.insert(e);
- // Prüfe nach einer Verzögerung, ob in die vorhandene Auswahl
- // angeklickt wurde und die Auswahl damit aufgehoben wurde
+ // EN: After a delay, check if the text was deselected
+ // DE: Prüfe nach einer Verzögerung, ob die Auswahl damit aufgehoben wurde
window.setTimeout(function () {
instance.hideIfNoSelection();
}, 0);
@@ -116,26 +144,32 @@ var SelectionMenu = (function (window, document) {
setupMenuEvents : function () {
var instance = this;
- // Registiere Handlerfunktion für den Klick auf das Menü
+ // EN: Register the handler for clicks on the menu
+ // DE: Registiere Handlerfunktion für den Klick auf das Menü
addEvent(span, 'click', function (e) {
instance.handler.call(instance, e);
return false;
});
- // Verhindere das Markieren des Menüs im IE
+ // EN: Prevent IE to select the text of the menu
+ // DE: Verhindere das Markieren des Menüs im IE
span.unselectable = true;
},
hide : function (e) {
+ // EN: Abort if an event object was passed and the click hit the menu itself
// Breche ab, wenn Event-Objekt übergeben wurde und der Klick beim Menü passierte
if (e && mouseOnMenu(e)) {
return;
}
- // Ist das Element in den DOM-Baum gehängt?
+ // EN: Is the element attached to the DOM tree?
+ // DE: Ist das Element in den DOM-Baum gehängt?
var parent = span.parentNode;
if (parent) {
- // Entferne es aus dem DOM-Baum (Element bleibt im Speicher erhalten
- // und wird später wiederverwendet)
+ // EN: Remove the element from DOM (the element object remains
+ // EN: in memory and will be reused later)
+ // DE: Entferne das element aus dem DOM-Baum (Element bleibt im Speicher erhalten
+ // DE: und wird später wiederverwendet)
parent.removeChild(span);
}
},
@@ -155,55 +189,68 @@ var SelectionMenu = (function (window, document) {
insert : function (e) {
var instance = this;
- // Breche ab, wenn das Mausereignis beim Menü passierte
+ // EN: Abort if the mouse event occured at the menu itself
+ // DE: Breche ab, wenn das Mausereignis beim Menü passierte
if (mouseOnMenu(e)) {
return;
}
- // Hole Selection bzw. TextRange (IE)
+ // EN: Get a Selection object or a TextRange (IE)
+ // DE: Hole Selection bzw. TextRange (IE)
var selection = getSelection();
if (!selection) {
- // Keine Browser-Unterstützung für die benötigten Features
+ // EN: No browser support available for the required features
+ // DE: Keine Browser-Unterstützung für die benötigten Features
return;
}
- // Hole markierten Text
+ // EN: Get the selected text
+ // DE: Hole markierten Text
var selectedText = getSelectedText(selection);
instance.selectedText = selectedText;
- // Breche ab, wenn der markierte Text zu kurz ist
+ // EN: Abort if the selected text is too short
+ // DE: Breche ab, wenn der markierte Text zu kurz ist
if (selectedText.length < instance.minimalSelection) {
instance.hide(e);
return;
}
- // Fähigkeitenweiche DOM Range / Microsoft
+ // EN : Feature detection DOM Range / Microsoft
+ // DE: Fähigkeitenweiche DOM Range / Microsoft
if (selection.getRangeAt) {
- // Hole Range, die zur Selection gehört
- var range = selection.getRangeAt(0);
+ // EN: W3C DOM Range approach
+ // DE: Lösungsansatz mit W3C DOM Range
- // Erzeuge neue, leere Range
- var newRange = document.createRange();
+ // EN: Get the first Range of the current Selection
+ // DE: Hole Range, die zur Selection gehört
+ var range = selection.getRangeAt(0);
- // Hole Start- und Endknoten der Auswahl
+ // EN: Get the start and end nodes of the selection
+ // DE: Hole Start- und Endknoten der Auswahl
var startNode = range.startContainer;
var endNode = range.endContainer;
if (!(startNode && endNode && startNode.compareDocumentPosition)) {
+ // EN: Abort if we got bogus values or we can't compare their document position
+ // DE: Breche ab, wenn die Knoten nicht brauchbar sind
return;
}
- // Korrektur: Wenn von hinten nach vorne markiert wurde, drehe Start und Ende um
+ // EN: If the start node succeeds the end node in the DOM tree, flip them
+ // DE: Wenn von hinten nach vorne markiert wurde, drehe Start und Ende um
if (startNode.compareDocumentPosition(endNode) & 2) {
startNode = endNode;
endNode = range.startContainer;
}
- // Hole End-Offset
+ // EN: Get the end offset
+ // DE: Hole End-Offset
var endOffset = range.endOffset;
- // Korrektur: Falls der Endknoten ein Element ist, nehme das Ende des letzten Textknoten
+ // EN: If the end node is an element, use its last text node as the end offset
+ // DE: Falls der Endknoten ein Element ist, nehme das Ende des letzten Textknoten
if (endNode.nodeType == 1) {
var endNode = endNode.lastChild;
if (!endNode || endNode.nodeType != 3) {
@@ -212,16 +259,25 @@ var SelectionMenu = (function (window, document) {
endOffset = endNode.data.length;
}
- // Verschiebe Anfang der neuen Range an das Ende der Auswahl
+ // EN: Create a new empty Range
+ // DE: Erzeuge neue, leere Range
+ var newRange = document.createRange();
+
+ // EN: Move the beginning of the new Range to the end of the selection
+ // DE: Verschiebe Anfang der neuen Range an das Ende der Auswahl
newRange.setStart(endNode, endOffset);
- // Befülle Menü-Span
+ // EN: Fill the menu span
+ // DE: Befülle das Menü-span
span.innerHTML = instance.menuHTML;
- // Füge das span-Element in die neue Range ein
+ // EN: Inject the span element into the new Range
+ // DE: Füge das span-Element in die neue Range ein
newRange.insertNode(span);
- // Korrigiere Auswahl, verhindere das Markieren des Menüs
+ // EN: Adjust the selection by removing and adding the range.
+ // EN: This prevents the selection of the menu text.
+ // DE: Korrigiere Auswahl, verhindere das Markieren des Menüs
if (selection.removeRange) {
selection.removeRange(range);
} else {
@@ -231,33 +287,46 @@ var SelectionMenu = (function (window, document) {
} else if (selection.duplicate) {
- // Kopiere TextRange
+ // EN: Microsoft TextRange approach
+ // DE: Lösungsansatz mit Microsoft TextRanges
+
+ // EN: Create a copy the the TextRange
+ // DE: Kopiere TextRange
var newRange = selection.duplicate();
- // Verschiebe Anfang der neuen Range an das Ende der Auswahl
+ // EN: Move the start of the new range to the end of the selection
+ // DE: Verschiebe den Anfang der neuen Range an das Ende der Auswahl
newRange.setEndPoint('StartToEnd', selection);
- // Befülle Menü-Span
+ // EN: Fill the menu span
+ // DE: Befülle das Menü-span
span.innerHTML = instance.menuHTML;
- // Füge das span-Element in die neue Range ein
+ // EN: Insert the span into the new range
+ // DE: Fülle die neue Range mit dem span
newRange.pasteHTML(span.outerHTML);
- // Korrigiere Auswahl und setze sie auf die ursprüngliche Auswahl zurück,
- // sodass das Menü nicht selektiert ist
+ // EN: Restore the selection so that the original text is selected
+ // EN: and not the menu
+ // DE: Korrigiere Auswahl und setze sie auf die ursprüngliche Auswahl zurück,
+ // DE: sodass das Menü nicht selektiert ist
selection.select();
- // Da das Befüllen nicht über das DOM, sondern über serialisierten HTML-Code erfolgt,
- // stelle die Referenz und das Event-Handling wieder her
+ // EN: Since we're using outerHTML to insert the span element,
+ // EN: we have to restore the span reference and the event handling
+ // DE: Da das Befüllen nicht über das DOM, sondern über serialisierten HTML-Code erfolgt,
+ // DE: stelle die Referenz und das Event-Handling wieder her
span = document.getElementById(id);
instance.setupMenuEvents();
} else {
- // Keine Browser-Unterstützung für die benötigten Features
+ // EN: No browser support available for the required features
+ // DE: Keine Browser-Unterstützung für die benötigten Features
return;
}
- // Positioniere Menü
+ // EN: Menu positioning
+ // DE: Positioniere Menü
instance.position();
},
@@ -266,7 +335,8 @@ var SelectionMenu = (function (window, document) {
}
};
- // Gebe Konstruktor zurück
+ // EN: Return the constructor function
+ // DE: Gib den Konstruktor zurück
return SelectionMenu;
})(window, document);
Please sign in to comment.
Something went wrong with that request. Please try again.