caret_navigation.js 4.58 KB
Newer Older
1 2 3
(function(define, undefined) {
    'use strict';
    define(['jquery', 'underscore', 'annotator_1.2.9'], function($, _, Annotator) {
4 5 6 7 8
    /**
     * The CaretNavigation Plugin which allows notes creation when users use
     * caret navigation to select the text.
     * Use `Ctrl + SPACE` or `Ctrl + ENTER` to open the editor.
     **/
9
        Annotator.Plugin.CaretNavigation = function() {
10 11
        // Call the Annotator.Plugin constructor this sets up the element and
        // options properties.
12 13 14
            _.bindAll(this, 'onKeyUp');
            Annotator.Plugin.apply(this, arguments);
        };
15

16 17 18 19
        $.extend(Annotator.Plugin.CaretNavigation.prototype, new Annotator.Plugin(), {
            pluginInit: function() {
                $(document).on('keyup', this.onKeyUp);
            },
20

21 22 23
            destroy: function() {
                $(document).off('keyup', this.onKeyUp);
            },
24

25
            isShortcut: function(event) {
26
            // Character ']' has keyCode 221
27 28
                return event.keyCode === 221 && event.ctrlKey && event.shiftKey;
            },
29

30 31 32
            hasSelection: function(ranges) {
                return (ranges || []).length;
            },
33

34 35 36
            saveSelection: function() {
                this.savedRange = Annotator.Util.getGlobal().getSelection().getRangeAt(0);
            },
37

38 39 40 41
            restoreSelection: function() {
                if (this.savedRange) {
                    var browserRange = new Annotator.Range.BrowserRange(this.savedRange),
                        normedRange = browserRange.normalize().limit(this.annotator.wrapper[0]);
42

43 44 45 46
                    Annotator.Util.readRangeViaSelection(normedRange);
                    this.savedRange = null;
                }
            },
47

48 49 50 51
            onKeyUp: function(event) {
                var annotator = this.annotator,
                    self = this,
                    isAnnotator, annotation, highlights, position, save, cancel, cleanup;
52 53

            // Do nothing if not a shortcut.
54 55 56
                if (!this.isShortcut(event)) {
                    return true;
                }
57
            // Get the currently selected ranges.
58
                annotator.selectedRanges = annotator.getSelectedRanges();
59
            // Do nothing if there is no selection
60 61 62
                if (!this.hasSelection(annotator.selectedRanges)) {
                    return true;
                }
63

64 65 66
                isAnnotator = _.some(annotator.selectedRanges, function(range) {
                    return annotator.isAnnotator(range.commonAncestor);
                });
67 68

            // Do nothing if we are in Annotator.
69 70 71
                if (isAnnotator) {
                    return true;
                }
72 73
            // Show a temporary highlight so the user can see what they selected
            // Also extract the quotation and serialize the ranges
74 75 76 77 78 79 80 81 82
                annotation = annotator.setupAnnotation(annotator.createAnnotation());
                highlights = $(annotation.highlights).addClass('annotator-hl-temporary');

                if (annotator.adder.is(':visible')) {
                    position = annotator.adder.position();
                    annotator.adder.hide();
                } else {
                    position = highlights.last().position();
                }
83 84 85

            // Subscribe to the editor events
            // Make the highlights permanent if the annotation is saved
86 87 88
                save = function() {
                    cleanup();
                    highlights.removeClass('annotator-hl-temporary');
89
                // Fire annotationCreated events so that plugins can react to them
90 91
                    annotator.publish('annotationCreated', [annotation]);
                };
92 93

            // Remove the highlights if the edit is cancelled
94 95 96 97 98
                cancel = function() {
                    self.restoreSelection();
                    cleanup();
                    annotator.deleteAnnotation(annotation);
                };
99 100

            // Don't leak handlers at the end
101 102 103 104 105
                cleanup = function() {
                    annotator.unsubscribe('annotationEditorHidden', cancel);
                    annotator.unsubscribe('annotationEditorSubmit', save);
                    self.savedRange = null;
                };
106

107 108
                annotator.subscribe('annotationEditorHidden', cancel);
                annotator.subscribe('annotationEditorSubmit', save);
109

110
                this.saveSelection();
111
            // Display the editor.
112 113 114 115
                annotator.showEditor(annotation, position);
                event.preventDefault();
            }
        });
116 117
    });
}).call(this, define || RequireJS.define);