Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('event-key', function (Y, NAME) {
2
 
3
/**
4
 * Functionality to listen for one or more specific key combinations.
5
 * @module event
6
 * @submodule event-key
7
 */
8
 
9
var ALT      = "+alt",
10
    CTRL     = "+ctrl",
11
    META     = "+meta",
12
    SHIFT    = "+shift",
13
 
14
    trim     = Y.Lang.trim,
15
 
16
    eventDef = {
17
        KEY_MAP: {
18
            enter    : 13,
19
            space    : 32,
20
            esc      : 27,
21
            backspace: 8,
22
            tab      : 9,
23
            pageup   : 33,
24
            pagedown : 34
25
        },
26
 
27
        _typeRE: /^(up|down|press):/,
28
        _keysRE: /^(?:up|down|press):|\+(alt|ctrl|meta|shift)/g,
29
 
30
        processArgs: function (args) {
31
            var spec = args.splice(3,1)[0],
32
                mods = Y.Array.hash(spec.match(/\+(?:alt|ctrl|meta|shift)\b/g) || []),
33
                config = {
34
                    type: this._typeRE.test(spec) ? RegExp.$1 : null,
35
                    mods: mods,
36
                    keys: null
37
                },
38
                // strip type and modifiers from spec, leaving only keyCodes
39
                bits = spec.replace(this._keysRE, ''),
40
                chr, uc, lc, i;
41
 
42
            if (bits) {
43
                bits = bits.split(',');
44
 
45
                config.keys = {};
46
 
47
                // FIXME: need to support '65,esc' => keypress, keydown
48
                for (i = bits.length - 1; i >= 0; --i) {
49
                    chr = trim(bits[i]);
50
 
51
                    // catch sloppy filters, trailing commas, etc 'a,,'
52
                    if (!chr) {
53
                        continue;
54
                    }
55
 
56
                    // non-numerics are single characters or key names
57
                    if (+chr == chr) {
58
                        config.keys[chr] = mods;
59
                    } else {
60
                        lc = chr.toLowerCase();
61
 
62
                        if (this.KEY_MAP[lc]) {
63
                            config.keys[this.KEY_MAP[lc]] = mods;
64
                            // FIXME: '65,enter' defaults keydown for both
65
                            if (!config.type) {
66
                                config.type = "down"; // safest
67
                            }
68
                        } else {
69
                            // FIXME: Character mapping only works for keypress
70
                            // events. Otherwise, it uses String.fromCharCode()
71
                            // from the keyCode, which is wrong.
72
                            chr = chr.charAt(0);
73
                            uc  = chr.toUpperCase();
74
 
75
                            if (mods["+shift"]) {
76
                                chr = uc;
77
                            }
78
 
79
                            // FIXME: stupid assumption that
80
                            // the keycode of the lower case == the
81
                            // charCode of the upper case
82
                            // a (key:65,char:97), A (key:65,char:65)
83
                            config.keys[chr.charCodeAt(0)] =
84
                                (chr === uc) ?
85
                                    // upper case chars get +shift free
86
                                    Y.merge(mods, { "+shift": true }) :
87
                                    mods;
88
                        }
89
                    }
90
                }
91
            }
92
 
93
            if (!config.type) {
94
                config.type = "press";
95
            }
96
 
97
            return config;
98
        },
99
 
100
        on: function (node, sub, notifier, filter) {
101
            var spec   = sub._extra,
102
                type   = "key" + spec.type,
103
                keys   = spec.keys,
104
                method = (filter) ? "delegate" : "on";
105
 
106
            // Note: without specifying any keyCodes, this becomes a
107
            // horribly inefficient alias for 'keydown' (et al), but I
108
            // can't abort this subscription for a simple
109
            // Y.on('keypress', ...);
110
            // Please use keyCodes or just subscribe directly to keydown,
111
            // keyup, or keypress
112
            sub._detach = node[method](type, function (e) {
113
                var key = keys ? keys[e.which] : spec.mods;
114
 
115
                if (key &&
116
                    (!key[ALT]   || (key[ALT]   && e.altKey)) &&
117
                    (!key[CTRL]  || (key[CTRL]  && e.ctrlKey)) &&
118
                    (!key[META]  || (key[META]  && e.metaKey)) &&
119
                    (!key[SHIFT] || (key[SHIFT] && e.shiftKey)))
120
                {
121
                    notifier.fire(e);
122
                }
123
            }, filter);
124
        },
125
 
126
        detach: function (node, sub, notifier) {
127
            sub._detach.detach();
128
        }
129
    };
130
 
131
eventDef.delegate = eventDef.on;
132
eventDef.detachDelegate = eventDef.detach;
133
 
134
/**
135
 * <p>Add a key listener.  The listener will only be notified if the
136
 * keystroke detected meets the supplied specification.  The
137
 * specification is a string that is defined as:</p>
138
 *
139
 * <dl>
140
 *   <dt>spec</dt>
141
 *   <dd><code>[{type}:]{code}[,{code}]*</code></dd>
142
 *   <dt>type</dt>
143
 *   <dd><code>"down", "up", or "press"</code></dd>
144
 *   <dt>code</dt>
145
 *   <dd><code>{keyCode|character|keyName}[+{modifier}]*</code></dd>
146
 *   <dt>modifier</dt>
147
 *   <dd><code>"shift", "ctrl", "alt", or "meta"</code></dd>
148
 *   <dt>keyName</dt>
149
 *   <dd><code>"enter", "space", "backspace", "esc", "tab", "pageup", or "pagedown"</code></dd>
150
 * </dl>
151
 *
152
 * <p>Examples:</p>
153
 * <ul>
154
 *   <li><code>Y.on("key", callback, "press:12,65+shift+ctrl", "#my-input");</code></li>
155
 *   <li><code>Y.delegate("key", preventSubmit, "#forms", "enter", "input[type=text]");</code></li>
156
 *   <li><code>Y.one("doc").on("key", viNav, "j,k,l,;");</code></li>
157
 * </ul>
158
 *
159
 * @event key
160
 * @for YUI
161
 * @param type {string} 'key'
162
 * @param fn {function} the function to execute
163
 * @param id {string|HTMLElement|collection} the element(s) to bind
164
 * @param spec {string} the keyCode and modifier specification
165
 * @param o optional context object
166
 * @param args 0..n additional arguments to provide to the listener.
167
 * @return {Event.Handle} the detach handle
168
 */
169
Y.Event.define('key', eventDef, true);
170
 
171
 
172
}, '3.18.1', {"requires": ["event-synthetic"]});