syn-rails 3.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +7 -0
- data/Rakefile +1 -0
- data/lib/syn-rails.rb +11 -0
- data/lib/syn-rails/version.rb +5 -0
- data/syn-rails.gemspec +21 -0
- data/vendor/assets/javascripts/syn.js +2491 -0
- data/vendor/assets/javascripts/syn/browsers.js +321 -0
- data/vendor/assets/javascripts/syn/drag.js +321 -0
- data/vendor/assets/javascripts/syn/key.js +1055 -0
- data/vendor/assets/javascripts/syn/mouse.js +284 -0
- data/vendor/assets/javascripts/syn/synthetic.js +830 -0
- metadata +58 -0
| @@ -0,0 +1,1055 @@ | |
| 1 | 
            +
            (function(){
         | 
| 2 | 
            +
            	Syn.key.browsers = {
         | 
| 3 | 
            +
            		webkit : {
         | 
| 4 | 
            +
            			'prevent':
         | 
| 5 | 
            +
            			 {"keyup":[],"keydown":["char","keypress"],"keypress":["char"]},
         | 
| 6 | 
            +
            			'character':
         | 
| 7 | 
            +
            			 {"keydown":[0,"key"],"keypress":["char","char"],"keyup":[0,"key"]},
         | 
| 8 | 
            +
            			'specialChars':
         | 
| 9 | 
            +
            			 {"keydown":[0,"char"],"keyup":[0,"char"]},
         | 
| 10 | 
            +
            			'navigation':
         | 
| 11 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 12 | 
            +
            			'special':
         | 
| 13 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 14 | 
            +
            			'tab':
         | 
| 15 | 
            +
            			 {"keydown":[0,"char"],"keyup":[0,"char"]},
         | 
| 16 | 
            +
            			'pause-break':
         | 
| 17 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 18 | 
            +
            			'caps':
         | 
| 19 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 20 | 
            +
            			'escape':
         | 
| 21 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 22 | 
            +
            			'num-lock':
         | 
| 23 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 24 | 
            +
            			'scroll-lock':
         | 
| 25 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 26 | 
            +
            			'print':
         | 
| 27 | 
            +
            			 {"keyup":[0,"key"]},
         | 
| 28 | 
            +
            			'function':
         | 
| 29 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 30 | 
            +
            			'\r':
         | 
| 31 | 
            +
            			 {"keydown":[0,"key"],"keypress":["char","key"],"keyup":[0,"key"]}
         | 
| 32 | 
            +
            		},
         | 
| 33 | 
            +
            		gecko : {
         | 
| 34 | 
            +
            			'prevent':
         | 
| 35 | 
            +
            			 {"keyup":[],"keydown":["char"],"keypress":["char"]},
         | 
| 36 | 
            +
            			'character':
         | 
| 37 | 
            +
            			 {"keydown":[0,"key"],"keypress":["char",0],"keyup":[0,"key"]},
         | 
| 38 | 
            +
            			'specialChars':
         | 
| 39 | 
            +
            			 {"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]},
         | 
| 40 | 
            +
            			'navigation':
         | 
| 41 | 
            +
            			 {"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]},
         | 
| 42 | 
            +
            			'special':
         | 
| 43 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 44 | 
            +
            			'\t':
         | 
| 45 | 
            +
            			 {"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]},
         | 
| 46 | 
            +
            			'pause-break':
         | 
| 47 | 
            +
            			 {"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]},
         | 
| 48 | 
            +
            			'caps':
         | 
| 49 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 50 | 
            +
            			'escape':
         | 
| 51 | 
            +
            			 {"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]},
         | 
| 52 | 
            +
            			'num-lock':
         | 
| 53 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 54 | 
            +
            			'scroll-lock':
         | 
| 55 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 56 | 
            +
            			'print':
         | 
| 57 | 
            +
            			 {"keyup":[0,"key"]},
         | 
| 58 | 
            +
            			'function':
         | 
| 59 | 
            +
            			 {"keydown":[0,"key"],"keyup":[0,"key"]},
         | 
| 60 | 
            +
            			'\r':
         | 
| 61 | 
            +
            			 {"keydown":[0,"key"],"keypress":[0,"key"],"keyup":[0,"key"]}
         | 
| 62 | 
            +
            		},
         | 
| 63 | 
            +
            		msie : {
         | 
| 64 | 
            +
            			'prevent':{"keyup":[],"keydown":["char","keypress"],"keypress":["char"]},
         | 
| 65 | 
            +
            			'character':{"keydown":[null,"key"],"keypress":[null,"char"],"keyup":[null,"key"]},
         | 
| 66 | 
            +
            			'specialChars':{"keydown":[null,"char"],"keyup":[null,"char"]},
         | 
| 67 | 
            +
            			'navigation':{"keydown":[null,"key"],"keyup":[null,"key"]},
         | 
| 68 | 
            +
            			'special':{"keydown":[null,"key"],"keyup":[null,"key"]},
         | 
| 69 | 
            +
            			'tab':{"keydown":[null,"char"],"keyup":[null,"char"]},
         | 
| 70 | 
            +
            			'pause-break':{"keydown":[null,"key"],"keyup":[null,"key"]},
         | 
| 71 | 
            +
            			'caps':{"keydown":[null,"key"],"keyup":[null,"key"]},
         | 
| 72 | 
            +
            			'escape':{"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]},
         | 
| 73 | 
            +
            			'num-lock':{"keydown":[null,"key"],"keyup":[null,"key"]},
         | 
| 74 | 
            +
            			'scroll-lock':{"keydown":[null,"key"],"keyup":[null,"key"]},
         | 
| 75 | 
            +
            			'print':{"keyup":[null,"key"]},
         | 
| 76 | 
            +
            			'function':{"keydown":[null,"key"],"keyup":[null,"key"]},
         | 
| 77 | 
            +
            			'\r':{"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]}	
         | 
| 78 | 
            +
            		},
         | 
| 79 | 
            +
            		opera : {
         | 
| 80 | 
            +
            			'prevent':
         | 
| 81 | 
            +
            			 {"keyup":[],"keydown":[],"keypress":["char"]},
         | 
| 82 | 
            +
            			'character':
         | 
| 83 | 
            +
            			 {"keydown":[null,"key"],"keypress":[null,"char"],"keyup":[null,"key"]},
         | 
| 84 | 
            +
            			'specialChars':
         | 
| 85 | 
            +
            			 {"keydown":[null,"char"],"keypress":[null,"char"],"keyup":[null,"char"]},
         | 
| 86 | 
            +
            			'navigation':
         | 
| 87 | 
            +
            			 {"keydown":[null,"key"],"keypress":[null,"key"]},
         | 
| 88 | 
            +
            			'special':
         | 
| 89 | 
            +
            			 {"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]},
         | 
| 90 | 
            +
            			'tab':
         | 
| 91 | 
            +
            			 {"keydown":[null,"char"],"keypress":[null,"char"],"keyup":[null,"char"]},
         | 
| 92 | 
            +
            			'pause-break':
         | 
| 93 | 
            +
            			 {"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]},
         | 
| 94 | 
            +
            			'caps':
         | 
| 95 | 
            +
            			 {"keydown":[null,"key"],"keyup":[null,"key"]},
         | 
| 96 | 
            +
            			'escape':
         | 
| 97 | 
            +
            			 {"keydown":[null,"key"],"keypress":[null,"key"]},
         | 
| 98 | 
            +
            			'num-lock':
         | 
| 99 | 
            +
            			 {"keyup":[null,"key"],"keydown":[null,"key"],"keypress":[null,"key"]},
         | 
| 100 | 
            +
            			'scroll-lock':
         | 
| 101 | 
            +
            			 {"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]},
         | 
| 102 | 
            +
            			'print':
         | 
| 103 | 
            +
            			 {},
         | 
| 104 | 
            +
            			'function':
         | 
| 105 | 
            +
            			 {"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]},
         | 
| 106 | 
            +
            			'\r':
         | 
| 107 | 
            +
            			 {"keydown":[null,"key"],"keypress":[null,"key"],"keyup":[null,"key"]}	
         | 
| 108 | 
            +
            		}
         | 
| 109 | 
            +
            	};
         | 
| 110 | 
            +
            	
         | 
| 111 | 
            +
            	Syn.mouse.browsers = {
         | 
| 112 | 
            +
            		webkit : {"right":{"mousedown":{"button":2,"which":3},"mouseup":{"button":2,"which":3},"contextmenu":{"button":2,"which":3}},
         | 
| 113 | 
            +
            		          "left":{"mousedown":{"button":0,"which":1},"mouseup":{"button":0,"which":1},"click":{"button":0,"which":1}}},
         | 
| 114 | 
            +
            		opera: {"right":{"mousedown":{"button":2,"which":3},"mouseup":{"button":2,"which":3}},
         | 
| 115 | 
            +
            		        "left":{"mousedown":{"button":0,"which":1},"mouseup":{"button":0,"which":1},"click":{"button":0,"which":1}}},
         | 
| 116 | 
            +
            		msie: {	"right":{"mousedown":{"button":2},"mouseup":{"button":2},"contextmenu":{"button":0}},
         | 
| 117 | 
            +
            				"left":{"mousedown":{"button":1},"mouseup":{"button":1},"click":{"button":0}}},
         | 
| 118 | 
            +
            		chrome : {"right":{"mousedown":{"button":2,"which":3},"mouseup":{"button":2,"which":3},"contextmenu":{"button":2,"which":3}},
         | 
| 119 | 
            +
            				  "left":{"mousedown":{"button":0,"which":1},"mouseup":{"button":0,"which":1},"click":{"button":0,"which":1}}},
         | 
| 120 | 
            +
            		gecko: {"left":{"mousedown":{"button":0,"which":1},"mouseup":{"button":0,"which":1},"click":{"button":0,"which":1}},
         | 
| 121 | 
            +
            		        "right":{"mousedown":{"button":2,"which":3},"mouseup":{"button":2,"which":3},"contextmenu":{"button":2,"which":3}}}
         | 
| 122 | 
            +
            	}
         | 
| 123 | 
            +
            	
         | 
| 124 | 
            +
            	//set browser
         | 
| 125 | 
            +
            	Syn.key.browser = 
         | 
| 126 | 
            +
            	(function(){
         | 
| 127 | 
            +
            		if(Syn.key.browsers[window.navigator.userAgent]){
         | 
| 128 | 
            +
            			return Syn.key.browsers[window.navigator.userAgent];
         | 
| 129 | 
            +
            		}
         | 
| 130 | 
            +
            		for(var browser in Syn.browser){
         | 
| 131 | 
            +
            			if(Syn.browser[browser] && Syn.key.browsers[browser]){
         | 
| 132 | 
            +
            				return Syn.key.browsers[browser]
         | 
| 133 | 
            +
            			}
         | 
| 134 | 
            +
            		}
         | 
| 135 | 
            +
            		return Syn.key.browsers.gecko;
         | 
| 136 | 
            +
            	})();
         | 
| 137 | 
            +
            	
         | 
| 138 | 
            +
            	Syn.mouse.browser = 
         | 
| 139 | 
            +
            	(function(){
         | 
| 140 | 
            +
            		if(Syn.mouse.browsers[window.navigator.userAgent]){
         | 
| 141 | 
            +
            			return Syn.mouse.browsers[window.navigator.userAgent];
         | 
| 142 | 
            +
            		}
         | 
| 143 | 
            +
            		for(var browser in Syn.browser){
         | 
| 144 | 
            +
            			if(Syn.browser[browser] && Syn.mouse.browsers[browser]){
         | 
| 145 | 
            +
            				return Syn.mouse.browsers[browser]
         | 
| 146 | 
            +
            			}
         | 
| 147 | 
            +
            		}
         | 
| 148 | 
            +
            		return Syn.mouse.browsers.gecko;
         | 
| 149 | 
            +
            	})();
         | 
| 150 | 
            +
            })(true);
         | 
| 151 | 
            +
            (function(){
         | 
| 152 | 
            +
            	var h = Syn.helpers,
         | 
| 153 | 
            +
            		S = Syn,
         | 
| 154 | 
            +
             | 
| 155 | 
            +
            		// gets the selection of an input or textarea
         | 
| 156 | 
            +
            		getSelection = function( el ) {
         | 
| 157 | 
            +
            			// use selectionStart if we can
         | 
| 158 | 
            +
            			if ( el.selectionStart !== undefined ) {
         | 
| 159 | 
            +
            				// this is for opera, so we don't have to focus to type how we think we would
         | 
| 160 | 
            +
            				if ( document.activeElement && document.activeElement != el && el.selectionStart == el.selectionEnd && el.selectionStart == 0 ) {
         | 
| 161 | 
            +
            					return {
         | 
| 162 | 
            +
            						start: el.value.length,
         | 
| 163 | 
            +
            						end: el.value.length
         | 
| 164 | 
            +
            					};
         | 
| 165 | 
            +
            				}
         | 
| 166 | 
            +
            				return {
         | 
| 167 | 
            +
            					start: el.selectionStart,
         | 
| 168 | 
            +
            					end: el.selectionEnd
         | 
| 169 | 
            +
            				}
         | 
| 170 | 
            +
            			} else {
         | 
| 171 | 
            +
            				//check if we aren't focused
         | 
| 172 | 
            +
            				try {
         | 
| 173 | 
            +
            					//try 2 different methods that work differently (IE breaks depending on type)
         | 
| 174 | 
            +
            					if ( el.nodeName.toLowerCase() == 'input' ) {
         | 
| 175 | 
            +
            						var real = h.getWindow(el).document.selection.createRange(),
         | 
| 176 | 
            +
            							r = el.createTextRange();
         | 
| 177 | 
            +
            						r.setEndPoint("EndToStart", real);
         | 
| 178 | 
            +
             | 
| 179 | 
            +
            						var start = r.text.length
         | 
| 180 | 
            +
            						return {
         | 
| 181 | 
            +
            							start: start,
         | 
| 182 | 
            +
            							end: start + real.text.length
         | 
| 183 | 
            +
            						}
         | 
| 184 | 
            +
            					}
         | 
| 185 | 
            +
            					else {
         | 
| 186 | 
            +
            						var real = h.getWindow(el).document.selection.createRange(),
         | 
| 187 | 
            +
            							r = real.duplicate(),
         | 
| 188 | 
            +
            							r2 = real.duplicate(),
         | 
| 189 | 
            +
            							r3 = real.duplicate();
         | 
| 190 | 
            +
            						r2.collapse();
         | 
| 191 | 
            +
            						r3.collapse(false);
         | 
| 192 | 
            +
            						r2.moveStart('character', -1)
         | 
| 193 | 
            +
            						r3.moveStart('character', -1)
         | 
| 194 | 
            +
            						//select all of our element
         | 
| 195 | 
            +
            						r.moveToElementText(el)
         | 
| 196 | 
            +
            						//now move our endpoint to the end of our real range
         | 
| 197 | 
            +
            						r.setEndPoint('EndToEnd', real);
         | 
| 198 | 
            +
            						var start = r.text.length - real.text.length,
         | 
| 199 | 
            +
            							end = r.text.length;
         | 
| 200 | 
            +
            						if ( start != 0 && r2.text == "" ) {
         | 
| 201 | 
            +
            							start += 2;
         | 
| 202 | 
            +
            						}
         | 
| 203 | 
            +
            						if ( end != 0 && r3.text == "" ) {
         | 
| 204 | 
            +
            							end += 2;
         | 
| 205 | 
            +
            						}
         | 
| 206 | 
            +
            						//if we aren't at the start, but previous is empty, we are at start of newline
         | 
| 207 | 
            +
            						return {
         | 
| 208 | 
            +
            							start: start,
         | 
| 209 | 
            +
            							end: end
         | 
| 210 | 
            +
            						}
         | 
| 211 | 
            +
            					}
         | 
| 212 | 
            +
            				} catch (e) {
         | 
| 213 | 
            +
            					return {
         | 
| 214 | 
            +
            						start: el.value.length,
         | 
| 215 | 
            +
            						end: el.value.length
         | 
| 216 | 
            +
            					};
         | 
| 217 | 
            +
            				}
         | 
| 218 | 
            +
            			}
         | 
| 219 | 
            +
            		},
         | 
| 220 | 
            +
            		// gets all focusable elements
         | 
| 221 | 
            +
            		getFocusable = function( el ) {
         | 
| 222 | 
            +
            			var document = h.getWindow(el).document,
         | 
| 223 | 
            +
            				res = [];
         | 
| 224 | 
            +
             | 
| 225 | 
            +
            			var els = document.getElementsByTagName('*'),
         | 
| 226 | 
            +
            				len = els.length;
         | 
| 227 | 
            +
             | 
| 228 | 
            +
            			for ( var i = 0; i < len; i++ ) {
         | 
| 229 | 
            +
            				Syn.isFocusable(els[i]) && els[i] != document.documentElement && res.push(els[i])
         | 
| 230 | 
            +
            			}
         | 
| 231 | 
            +
            			return res;
         | 
| 232 | 
            +
             | 
| 233 | 
            +
             | 
| 234 | 
            +
            		};
         | 
| 235 | 
            +
             | 
| 236 | 
            +
            	/**
         | 
| 237 | 
            +
            	 * @add Syn static
         | 
| 238 | 
            +
            	 */
         | 
| 239 | 
            +
            	h.extend(Syn, {
         | 
| 240 | 
            +
            		/**
         | 
| 241 | 
            +
            		 * @attribute
         | 
| 242 | 
            +
            		 * A list of the keys and their keycodes codes you can type.
         | 
| 243 | 
            +
            		 * You can add type keys with
         | 
| 244 | 
            +
            		 * @codestart
         | 
| 245 | 
            +
            		 * Syn('key','delete','title');
         | 
| 246 | 
            +
            		 * 
         | 
| 247 | 
            +
            		 * //or 
         | 
| 248 | 
            +
            		 * 
         | 
| 249 | 
            +
            		 * Syn('type','One Two Three[left][left][delete]','title')
         | 
| 250 | 
            +
            		 * @codeend
         | 
| 251 | 
            +
            		 * 
         | 
| 252 | 
            +
            		 * The following are a list of keys you can type:
         | 
| 253 | 
            +
            		 * @codestart text
         | 
| 254 | 
            +
            		 * \b        - backspace
         | 
| 255 | 
            +
            		 * \t        - tab
         | 
| 256 | 
            +
            		 * \r        - enter
         | 
| 257 | 
            +
            		 * ' '       - space
         | 
| 258 | 
            +
            		 * a-Z 0-9   - normal characters
         | 
| 259 | 
            +
            		 * /!@#$*,.? - All other typeable characters
         | 
| 260 | 
            +
            		 * page-up   - scrolls up
         | 
| 261 | 
            +
            		 * page-down - scrolls down
         | 
| 262 | 
            +
            		 * end       - scrolls to bottom
         | 
| 263 | 
            +
            		 * home      - scrolls to top
         | 
| 264 | 
            +
            		 * insert    - changes how keys are entered
         | 
| 265 | 
            +
            		 * delete    - deletes the next character
         | 
| 266 | 
            +
            		 * left      - moves cursor left
         | 
| 267 | 
            +
            		 * right     - moves cursor right
         | 
| 268 | 
            +
            		 * up        - moves the cursor up
         | 
| 269 | 
            +
            		 * down      - moves the cursor down
         | 
| 270 | 
            +
            		 * f1-12     - function buttons
         | 
| 271 | 
            +
            		 * shift, ctrl, alt - special keys
         | 
| 272 | 
            +
            		 * pause-break      - the pause button
         | 
| 273 | 
            +
            		 * scroll-lock      - locks scrolling
         | 
| 274 | 
            +
            		 * caps      - makes caps
         | 
| 275 | 
            +
            		 * escape    - escape button
         | 
| 276 | 
            +
            		 * num-lock  - allows numbers on keypad
         | 
| 277 | 
            +
            		 * print     - screen capture
         | 
| 278 | 
            +
            		 * @codeend
         | 
| 279 | 
            +
            		 */
         | 
| 280 | 
            +
            		keycodes: {
         | 
| 281 | 
            +
            			//backspace
         | 
| 282 | 
            +
            			'\b': '8',
         | 
| 283 | 
            +
             | 
| 284 | 
            +
            			//tab
         | 
| 285 | 
            +
            			'\t': '9',
         | 
| 286 | 
            +
             | 
| 287 | 
            +
            			//enter
         | 
| 288 | 
            +
            			'\r': '13',
         | 
| 289 | 
            +
             | 
| 290 | 
            +
            			//special
         | 
| 291 | 
            +
            			'shift': '16',
         | 
| 292 | 
            +
            			'ctrl': '17',
         | 
| 293 | 
            +
            			'alt': '18',
         | 
| 294 | 
            +
             | 
| 295 | 
            +
            			//weird
         | 
| 296 | 
            +
            			'pause-break': '19',
         | 
| 297 | 
            +
            			'caps': '20',
         | 
| 298 | 
            +
            			'escape': '27',
         | 
| 299 | 
            +
            			'num-lock': '144',
         | 
| 300 | 
            +
            			'scroll-lock': '145',
         | 
| 301 | 
            +
            			'print': '44',
         | 
| 302 | 
            +
             | 
| 303 | 
            +
            			//navigation
         | 
| 304 | 
            +
            			'page-up': '33',
         | 
| 305 | 
            +
            			'page-down': '34',
         | 
| 306 | 
            +
            			'end': '35',
         | 
| 307 | 
            +
            			'home': '36',
         | 
| 308 | 
            +
            			'left': '37',
         | 
| 309 | 
            +
            			'up': '38',
         | 
| 310 | 
            +
            			'right': '39',
         | 
| 311 | 
            +
            			'down': '40',
         | 
| 312 | 
            +
            			'insert': '45',
         | 
| 313 | 
            +
            			'delete': '46',
         | 
| 314 | 
            +
             | 
| 315 | 
            +
            			//normal characters
         | 
| 316 | 
            +
            			' ': '32',
         | 
| 317 | 
            +
            			'0': '48',
         | 
| 318 | 
            +
            			'1': '49',
         | 
| 319 | 
            +
            			'2': '50',
         | 
| 320 | 
            +
            			'3': '51',
         | 
| 321 | 
            +
            			'4': '52',
         | 
| 322 | 
            +
            			'5': '53',
         | 
| 323 | 
            +
            			'6': '54',
         | 
| 324 | 
            +
            			'7': '55',
         | 
| 325 | 
            +
            			'8': '56',
         | 
| 326 | 
            +
            			'9': '57',
         | 
| 327 | 
            +
            			'a': '65',
         | 
| 328 | 
            +
            			'b': '66',
         | 
| 329 | 
            +
            			'c': '67',
         | 
| 330 | 
            +
            			'd': '68',
         | 
| 331 | 
            +
            			'e': '69',
         | 
| 332 | 
            +
            			'f': '70',
         | 
| 333 | 
            +
            			'g': '71',
         | 
| 334 | 
            +
            			'h': '72',
         | 
| 335 | 
            +
            			'i': '73',
         | 
| 336 | 
            +
            			'j': '74',
         | 
| 337 | 
            +
            			'k': '75',
         | 
| 338 | 
            +
            			'l': '76',
         | 
| 339 | 
            +
            			'm': '77',
         | 
| 340 | 
            +
            			'n': '78',
         | 
| 341 | 
            +
            			'o': '79',
         | 
| 342 | 
            +
            			'p': '80',
         | 
| 343 | 
            +
            			'q': '81',
         | 
| 344 | 
            +
            			'r': '82',
         | 
| 345 | 
            +
            			's': '83',
         | 
| 346 | 
            +
            			't': '84',
         | 
| 347 | 
            +
            			'u': '85',
         | 
| 348 | 
            +
            			'v': '86',
         | 
| 349 | 
            +
            			'w': '87',
         | 
| 350 | 
            +
            			'x': '88',
         | 
| 351 | 
            +
            			'y': '89',
         | 
| 352 | 
            +
            			'z': '90',
         | 
| 353 | 
            +
            			//normal-characters, numpad
         | 
| 354 | 
            +
            			'num0': '96',
         | 
| 355 | 
            +
            			'num1': '97',
         | 
| 356 | 
            +
            			'num2': '98',
         | 
| 357 | 
            +
            			'num3': '99',
         | 
| 358 | 
            +
            			'num4': '100',
         | 
| 359 | 
            +
            			'num5': '101',
         | 
| 360 | 
            +
            			'num6': '102',
         | 
| 361 | 
            +
            			'num7': '103',
         | 
| 362 | 
            +
            			'num8': '104',
         | 
| 363 | 
            +
            			'num9': '105',
         | 
| 364 | 
            +
            			'*': '106',
         | 
| 365 | 
            +
            			'+': '107',
         | 
| 366 | 
            +
            			'-': '109',
         | 
| 367 | 
            +
            			'.': '110',
         | 
| 368 | 
            +
            			//normal-characters, others
         | 
| 369 | 
            +
            			'/': '111',
         | 
| 370 | 
            +
            			';': '186',
         | 
| 371 | 
            +
            			'=': '187',
         | 
| 372 | 
            +
            			',': '188',
         | 
| 373 | 
            +
            			'-': '189',
         | 
| 374 | 
            +
            			'.': '190',
         | 
| 375 | 
            +
            			'/': '191',
         | 
| 376 | 
            +
            			'`': '192',
         | 
| 377 | 
            +
            			'[': '219',
         | 
| 378 | 
            +
            			'\\': '220',
         | 
| 379 | 
            +
            			']': '221',
         | 
| 380 | 
            +
            			"'": '222',
         | 
| 381 | 
            +
             | 
| 382 | 
            +
            			//ignore these, you shouldn't use them
         | 
| 383 | 
            +
            			'left window key': '91',
         | 
| 384 | 
            +
            			'right window key': '92',
         | 
| 385 | 
            +
            			'select key': '93',
         | 
| 386 | 
            +
             | 
| 387 | 
            +
             | 
| 388 | 
            +
            			'f1': '112',
         | 
| 389 | 
            +
            			'f2': '113',
         | 
| 390 | 
            +
            			'f3': '114',
         | 
| 391 | 
            +
            			'f4': '115',
         | 
| 392 | 
            +
            			'f5': '116',
         | 
| 393 | 
            +
            			'f6': '117',
         | 
| 394 | 
            +
            			'f7': '118',
         | 
| 395 | 
            +
            			'f8': '119',
         | 
| 396 | 
            +
            			'f9': '120',
         | 
| 397 | 
            +
            			'f10': '121',
         | 
| 398 | 
            +
            			'f11': '122',
         | 
| 399 | 
            +
            			'f12': '123'
         | 
| 400 | 
            +
            		},
         | 
| 401 | 
            +
             | 
| 402 | 
            +
            		// what we can type in
         | 
| 403 | 
            +
            		typeable: /input|textarea/i,
         | 
| 404 | 
            +
             | 
| 405 | 
            +
            		// selects text on an element
         | 
| 406 | 
            +
            		selectText: function( el, start, end ) {
         | 
| 407 | 
            +
            			if ( el.setSelectionRange ) {
         | 
| 408 | 
            +
            				if (!end ) {
         | 
| 409 | 
            +
            					el.focus();
         | 
| 410 | 
            +
            					el.setSelectionRange(start, start);
         | 
| 411 | 
            +
            				} else {
         | 
| 412 | 
            +
            					el.selectionStart = start;
         | 
| 413 | 
            +
            					el.selectionEnd = end;
         | 
| 414 | 
            +
            				}
         | 
| 415 | 
            +
            			} else if ( el.createTextRange ) {
         | 
| 416 | 
            +
            				//el.focus();
         | 
| 417 | 
            +
            				var r = el.createTextRange();
         | 
| 418 | 
            +
            				r.moveStart('character', start);
         | 
| 419 | 
            +
            				end = end || start;
         | 
| 420 | 
            +
            				r.moveEnd('character', end - el.value.length);
         | 
| 421 | 
            +
             | 
| 422 | 
            +
            				r.select();
         | 
| 423 | 
            +
            			}
         | 
| 424 | 
            +
            		},
         | 
| 425 | 
            +
            		getText: function( el ) {
         | 
| 426 | 
            +
            			//first check if the el has anything selected ..
         | 
| 427 | 
            +
            			if ( Syn.typeable.test(el.nodeName) ) {
         | 
| 428 | 
            +
            				var sel = getSelection(el);
         | 
| 429 | 
            +
            				return el.value.substring(sel.start, sel.end)
         | 
| 430 | 
            +
            			}
         | 
| 431 | 
            +
            			//otherwise get from page
         | 
| 432 | 
            +
            			var win = Syn.helpers.getWindow(el);
         | 
| 433 | 
            +
            			if ( win.getSelection ) {
         | 
| 434 | 
            +
            				return win.getSelection().toString();
         | 
| 435 | 
            +
            			}
         | 
| 436 | 
            +
            			else if ( win.document.getSelection ) {
         | 
| 437 | 
            +
            				return win.document.getSelection().toString()
         | 
| 438 | 
            +
            			}
         | 
| 439 | 
            +
            			else {
         | 
| 440 | 
            +
            				return win.document.selection.createRange().text;
         | 
| 441 | 
            +
            			}
         | 
| 442 | 
            +
            		},
         | 
| 443 | 
            +
            		getSelection: getSelection
         | 
| 444 | 
            +
            	});
         | 
| 445 | 
            +
             | 
| 446 | 
            +
            	h.extend(Syn.key, {
         | 
| 447 | 
            +
            		// retrieves a description of what events for this character should look like
         | 
| 448 | 
            +
            		data: function( key ) {
         | 
| 449 | 
            +
            			//check if it is described directly
         | 
| 450 | 
            +
            			if ( S.key.browser[key] ) {
         | 
| 451 | 
            +
            				return S.key.browser[key];
         | 
| 452 | 
            +
            			}
         | 
| 453 | 
            +
            			for ( var kind in S.key.kinds ) {
         | 
| 454 | 
            +
            				if ( h.inArray(key, S.key.kinds[kind]) > -1 ) {
         | 
| 455 | 
            +
            					return S.key.browser[kind]
         | 
| 456 | 
            +
            				}
         | 
| 457 | 
            +
            			}
         | 
| 458 | 
            +
            			return S.key.browser.character
         | 
| 459 | 
            +
            		},
         | 
| 460 | 
            +
             | 
| 461 | 
            +
            		//returns the special key if special
         | 
| 462 | 
            +
            		isSpecial: function( keyCode ) {
         | 
| 463 | 
            +
            			var specials = S.key.kinds.special;
         | 
| 464 | 
            +
            			for ( var i = 0; i < specials.length; i++ ) {
         | 
| 465 | 
            +
            				if ( Syn.keycodes[specials[i]] == keyCode ) {
         | 
| 466 | 
            +
            					return specials[i];
         | 
| 467 | 
            +
            				}
         | 
| 468 | 
            +
            			}
         | 
| 469 | 
            +
            		},
         | 
| 470 | 
            +
            		/**
         | 
| 471 | 
            +
            		 * @hide
         | 
| 472 | 
            +
            		 * gets the options for a key and event type ...
         | 
| 473 | 
            +
            		 * @param {Object} key
         | 
| 474 | 
            +
            		 * @param {Object} event
         | 
| 475 | 
            +
            		 */
         | 
| 476 | 
            +
            		options: function( key, event ) {
         | 
| 477 | 
            +
            			var keyData = Syn.key.data(key);
         | 
| 478 | 
            +
             | 
| 479 | 
            +
            			if (!keyData[event] ) {
         | 
| 480 | 
            +
            				//we shouldn't be creating this event
         | 
| 481 | 
            +
            				return null;
         | 
| 482 | 
            +
            			}
         | 
| 483 | 
            +
             | 
| 484 | 
            +
            			var charCode = keyData[event][0],
         | 
| 485 | 
            +
            				keyCode = keyData[event][1],
         | 
| 486 | 
            +
            				result = {};
         | 
| 487 | 
            +
             | 
| 488 | 
            +
            			if ( keyCode == 'key' ) {
         | 
| 489 | 
            +
            				result.keyCode = Syn.keycodes[key]
         | 
| 490 | 
            +
            			} else if ( keyCode == 'char' ) {
         | 
| 491 | 
            +
            				result.keyCode = key.charCodeAt(0)
         | 
| 492 | 
            +
            			} else {
         | 
| 493 | 
            +
            				result.keyCode = keyCode;
         | 
| 494 | 
            +
            			}
         | 
| 495 | 
            +
             | 
| 496 | 
            +
            			if ( charCode == 'char' ) {
         | 
| 497 | 
            +
            				result.charCode = key.charCodeAt(0)
         | 
| 498 | 
            +
            			} else if ( charCode !== null ) {
         | 
| 499 | 
            +
            				result.charCode = charCode;
         | 
| 500 | 
            +
            			}
         | 
| 501 | 
            +
             | 
| 502 | 
            +
             | 
| 503 | 
            +
            			return result
         | 
| 504 | 
            +
            		},
         | 
| 505 | 
            +
            		//types of event keys
         | 
| 506 | 
            +
            		kinds: {
         | 
| 507 | 
            +
            			special: ["shift", 'ctrl', 'alt', 'caps'],
         | 
| 508 | 
            +
            			specialChars: ["\b"],
         | 
| 509 | 
            +
            			navigation: ["page-up", 'page-down', 'end', 'home', 'left', 'up', 'right', 'down', 'insert', 'delete'],
         | 
| 510 | 
            +
            			'function': ['f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'f10', 'f11', 'f12']
         | 
| 511 | 
            +
            		},
         | 
| 512 | 
            +
            		//returns the default function
         | 
| 513 | 
            +
            		getDefault: function( key ) {
         | 
| 514 | 
            +
            			//check if it is described directly
         | 
| 515 | 
            +
            			if ( Syn.key.defaults[key] ) {
         | 
| 516 | 
            +
            				return Syn.key.defaults[key];
         | 
| 517 | 
            +
            			}
         | 
| 518 | 
            +
            			for ( var kind in Syn.key.kinds ) {
         | 
| 519 | 
            +
            				if ( h.inArray(key, Syn.key.kinds[kind]) > -1 && Syn.key.defaults[kind] ) {
         | 
| 520 | 
            +
            					return Syn.key.defaults[kind];
         | 
| 521 | 
            +
            				}
         | 
| 522 | 
            +
            			}
         | 
| 523 | 
            +
            			return Syn.key.defaults.character
         | 
| 524 | 
            +
            		},
         | 
| 525 | 
            +
            		// default behavior when typing
         | 
| 526 | 
            +
            		defaults: {
         | 
| 527 | 
            +
            			'character': function( options, scope, key, force, sel ) {
         | 
| 528 | 
            +
            				if (/num\d+/.test(key) ) {
         | 
| 529 | 
            +
            					key = key.match(/\d+/)[0]
         | 
| 530 | 
            +
            				}
         | 
| 531 | 
            +
             | 
| 532 | 
            +
            				if ( force || (!S.support.keyCharacters && Syn.typeable.test(this.nodeName)) ) {
         | 
| 533 | 
            +
            					var current = this.value,
         | 
| 534 | 
            +
            						before = current.substr(0, sel.start),
         | 
| 535 | 
            +
            						after = current.substr(sel.end),
         | 
| 536 | 
            +
            						character = key;
         | 
| 537 | 
            +
             | 
| 538 | 
            +
            					this.value = before + character + after;
         | 
| 539 | 
            +
            					//handle IE inserting \r\n
         | 
| 540 | 
            +
            					var charLength = character == "\n" && S.support.textareaCarriage ? 2 : character.length;
         | 
| 541 | 
            +
            					Syn.selectText(this, before.length + charLength)
         | 
| 542 | 
            +
            				}
         | 
| 543 | 
            +
            			},
         | 
| 544 | 
            +
            			'c': function( options, scope, key, force, sel ) {
         | 
| 545 | 
            +
            				if ( Syn.key.ctrlKey ) {
         | 
| 546 | 
            +
            					Syn.key.clipboard = Syn.getText(this)
         | 
| 547 | 
            +
            				} else {
         | 
| 548 | 
            +
            					Syn.key.defaults.character.apply(this, arguments);
         | 
| 549 | 
            +
            				}
         | 
| 550 | 
            +
            			},
         | 
| 551 | 
            +
            			'v': function( options, scope, key, force, sel ) {
         | 
| 552 | 
            +
            				if ( Syn.key.ctrlKey ) {
         | 
| 553 | 
            +
            					Syn.key.defaults.character.call(this, options, scope, Syn.key.clipboard, true, sel);
         | 
| 554 | 
            +
            				} else {
         | 
| 555 | 
            +
            					Syn.key.defaults.character.apply(this, arguments);
         | 
| 556 | 
            +
            				}
         | 
| 557 | 
            +
            			},
         | 
| 558 | 
            +
            			'a': function( options, scope, key, force, sel ) {
         | 
| 559 | 
            +
            				if ( Syn.key.ctrlKey ) {
         | 
| 560 | 
            +
            					Syn.selectText(this, 0, this.value.length)
         | 
| 561 | 
            +
            				} else {
         | 
| 562 | 
            +
            					Syn.key.defaults.character.apply(this, arguments);
         | 
| 563 | 
            +
            				}
         | 
| 564 | 
            +
            			},
         | 
| 565 | 
            +
            			'home': function() {
         | 
| 566 | 
            +
            				Syn.onParents(this, function( el ) {
         | 
| 567 | 
            +
            					if ( el.scrollHeight != el.clientHeight ) {
         | 
| 568 | 
            +
            						el.scrollTop = 0;
         | 
| 569 | 
            +
            						return false;
         | 
| 570 | 
            +
            					}
         | 
| 571 | 
            +
            				})
         | 
| 572 | 
            +
            			},
         | 
| 573 | 
            +
            			'end': function() {
         | 
| 574 | 
            +
            				Syn.onParents(this, function( el ) {
         | 
| 575 | 
            +
            					if ( el.scrollHeight != el.clientHeight ) {
         | 
| 576 | 
            +
            						el.scrollTop = el.scrollHeight;
         | 
| 577 | 
            +
            						return false;
         | 
| 578 | 
            +
            					}
         | 
| 579 | 
            +
            				})
         | 
| 580 | 
            +
            			},
         | 
| 581 | 
            +
            			'page-down': function() {
         | 
| 582 | 
            +
            				//find the first parent we can scroll
         | 
| 583 | 
            +
            				Syn.onParents(this, function( el ) {
         | 
| 584 | 
            +
            					if ( el.scrollHeight != el.clientHeight ) {
         | 
| 585 | 
            +
            						var ch = el.clientHeight
         | 
| 586 | 
            +
            						el.scrollTop += ch;
         | 
| 587 | 
            +
            						return false;
         | 
| 588 | 
            +
            					}
         | 
| 589 | 
            +
            				})
         | 
| 590 | 
            +
            			},
         | 
| 591 | 
            +
            			'page-up': function() {
         | 
| 592 | 
            +
            				Syn.onParents(this, function( el ) {
         | 
| 593 | 
            +
            					if ( el.scrollHeight != el.clientHeight ) {
         | 
| 594 | 
            +
            						var ch = el.clientHeight
         | 
| 595 | 
            +
            						el.scrollTop -= ch;
         | 
| 596 | 
            +
            						return false;
         | 
| 597 | 
            +
            					}
         | 
| 598 | 
            +
            				})
         | 
| 599 | 
            +
            			},
         | 
| 600 | 
            +
            			'\b': function( options, scope, key, force, sel ) {
         | 
| 601 | 
            +
            				//this assumes we are deleting from the end
         | 
| 602 | 
            +
            				if (!S.support.backspaceWorks && Syn.typeable.test(this.nodeName) ) {
         | 
| 603 | 
            +
            					var current = this.value,
         | 
| 604 | 
            +
            						before = current.substr(0, sel.start),
         | 
| 605 | 
            +
            						after = current.substr(sel.end);
         | 
| 606 | 
            +
             | 
| 607 | 
            +
            					if ( sel.start == sel.end && sel.start > 0 ) {
         | 
| 608 | 
            +
            						//remove a character
         | 
| 609 | 
            +
            						this.value = before.substring(0, before.length - 1) + after
         | 
| 610 | 
            +
            						Syn.selectText(this, sel.start - 1)
         | 
| 611 | 
            +
            					} else {
         | 
| 612 | 
            +
            						this.value = before + after;
         | 
| 613 | 
            +
            						Syn.selectText(this, sel.start)
         | 
| 614 | 
            +
            					}
         | 
| 615 | 
            +
             | 
| 616 | 
            +
            					//set back the selection
         | 
| 617 | 
            +
            				}
         | 
| 618 | 
            +
            			},
         | 
| 619 | 
            +
            			'delete': function( options, scope, key, force, sel ) {
         | 
| 620 | 
            +
            				if (!S.support.backspaceWorks && Syn.typeable.test(this.nodeName) ) {
         | 
| 621 | 
            +
            					var current = this.value,
         | 
| 622 | 
            +
            						before = current.substr(0, sel.start),
         | 
| 623 | 
            +
            						after = current.substr(sel.end);
         | 
| 624 | 
            +
            					if ( sel.start == sel.end && sel.start <= this.value.length - 1 ) {
         | 
| 625 | 
            +
            						this.value = before + after.substring(1)
         | 
| 626 | 
            +
            					} else {
         | 
| 627 | 
            +
            						this.value = before + after;
         | 
| 628 | 
            +
             | 
| 629 | 
            +
            					}
         | 
| 630 | 
            +
            					Syn.selectText(this, sel.start)
         | 
| 631 | 
            +
            				}
         | 
| 632 | 
            +
            			},
         | 
| 633 | 
            +
            			'\r': function( options, scope, key, force, sel ) {
         | 
| 634 | 
            +
             | 
| 635 | 
            +
            				var nodeName = this.nodeName.toLowerCase()
         | 
| 636 | 
            +
            				// submit a form
         | 
| 637 | 
            +
            				if (!S.support.keypressSubmits && nodeName == 'input' ) {
         | 
| 638 | 
            +
            					var form = Syn.closest(this, "form");
         | 
| 639 | 
            +
            					if ( form ) {
         | 
| 640 | 
            +
            						Syn.trigger("submit", {}, form);
         | 
| 641 | 
            +
            					}
         | 
| 642 | 
            +
             | 
| 643 | 
            +
            				}
         | 
| 644 | 
            +
            				//newline in textarea
         | 
| 645 | 
            +
            				if (!S.support.keyCharacters && nodeName == 'textarea' ) {
         | 
| 646 | 
            +
            					Syn.key.defaults.character.call(this, options, scope, "\n", undefined, sel)
         | 
| 647 | 
            +
            				}
         | 
| 648 | 
            +
            				// 'click' hyperlinks
         | 
| 649 | 
            +
            				if (!S.support.keypressOnAnchorClicks && nodeName == 'a' ) {
         | 
| 650 | 
            +
            					Syn.trigger("click", {}, this);
         | 
| 651 | 
            +
            				}
         | 
| 652 | 
            +
            			},
         | 
| 653 | 
            +
            			// 
         | 
| 654 | 
            +
            			// Gets all focusable elements.  If the element (this)
         | 
| 655 | 
            +
            			// doesn't have a tabindex, finds the next element after.
         | 
| 656 | 
            +
            			// If the element (this) has a tabindex finds the element 
         | 
| 657 | 
            +
            			// with the next higher tabindex OR the element with the same
         | 
| 658 | 
            +
            			// tabindex after it in the document.
         | 
| 659 | 
            +
            			// @return the next element
         | 
| 660 | 
            +
            			// 
         | 
| 661 | 
            +
            			'\t': function( options, scope ) {
         | 
| 662 | 
            +
            				// focusable elements
         | 
| 663 | 
            +
            				var focusEls = getFocusable(this),
         | 
| 664 | 
            +
            					// the current element's tabindex
         | 
| 665 | 
            +
            					tabIndex = Syn.tabIndex(this),
         | 
| 666 | 
            +
            					// will be set to our guess for the next element
         | 
| 667 | 
            +
            					current = null,
         | 
| 668 | 
            +
            					// the next index we care about
         | 
| 669 | 
            +
            					currentIndex = 1000000000,
         | 
| 670 | 
            +
            					// set to true once we found 'this' element
         | 
| 671 | 
            +
            					found = false,
         | 
| 672 | 
            +
            					i = 0,
         | 
| 673 | 
            +
            					el,
         | 
| 674 | 
            +
            					//the tabindex of the tabable element we are looking at
         | 
| 675 | 
            +
            					elIndex, firstNotIndexed, prev;
         | 
| 676 | 
            +
            				orders = [];
         | 
| 677 | 
            +
            				for (; i < focusEls.length; i++ ) {
         | 
| 678 | 
            +
            					orders.push([focusEls[i], i]);
         | 
| 679 | 
            +
            				}
         | 
| 680 | 
            +
            				var sort = function( order1, order2 ) {
         | 
| 681 | 
            +
            					var el1 = order1[0],
         | 
| 682 | 
            +
            						el2 = order2[0],
         | 
| 683 | 
            +
            						tab1 = Syn.tabIndex(el1) || 0,
         | 
| 684 | 
            +
            						tab2 = Syn.tabIndex(el2) || 0;
         | 
| 685 | 
            +
            					if ( tab1 == tab2 ) {
         | 
| 686 | 
            +
            						return order1[1] - order2[1]
         | 
| 687 | 
            +
            					} else {
         | 
| 688 | 
            +
            						if ( tab1 == 0 ) {
         | 
| 689 | 
            +
            							return 1;
         | 
| 690 | 
            +
            						} else if ( tab2 == 0 ) {
         | 
| 691 | 
            +
            							return -1;
         | 
| 692 | 
            +
            						} else {
         | 
| 693 | 
            +
            							return tab1 - tab2;
         | 
| 694 | 
            +
            						}
         | 
| 695 | 
            +
            					}
         | 
| 696 | 
            +
            				}
         | 
| 697 | 
            +
            				orders.sort(sort);
         | 
| 698 | 
            +
            				//now find current
         | 
| 699 | 
            +
            				for ( i = 0; i < orders.length; i++ ) {
         | 
| 700 | 
            +
            					el = orders[i][0];
         | 
| 701 | 
            +
            					if ( this == el ) {
         | 
| 702 | 
            +
            						if (!Syn.key.shiftKey ) {
         | 
| 703 | 
            +
            							current = orders[i + 1][0];
         | 
| 704 | 
            +
            							if (!current ) {
         | 
| 705 | 
            +
            								current = orders[0][0]
         | 
| 706 | 
            +
            							}
         | 
| 707 | 
            +
            						} else {
         | 
| 708 | 
            +
            							current = orders[i - 1][0];
         | 
| 709 | 
            +
            							if (!current ) {
         | 
| 710 | 
            +
            								current = orders[focusEls.length - 1][0]
         | 
| 711 | 
            +
            							}
         | 
| 712 | 
            +
            						}
         | 
| 713 | 
            +
             | 
| 714 | 
            +
            					}
         | 
| 715 | 
            +
            				}
         | 
| 716 | 
            +
             | 
| 717 | 
            +
            				//restart if we didn't find anything
         | 
| 718 | 
            +
            				if (!current ) {
         | 
| 719 | 
            +
            					current = firstNotIndexed;
         | 
| 720 | 
            +
            				}
         | 
| 721 | 
            +
            				current && current.focus();
         | 
| 722 | 
            +
            				return current;
         | 
| 723 | 
            +
            			},
         | 
| 724 | 
            +
            			'left': function( options, scope, key, force, sel ) {
         | 
| 725 | 
            +
            				if ( Syn.typeable.test(this.nodeName) ) {
         | 
| 726 | 
            +
            					if ( Syn.key.shiftKey ) {
         | 
| 727 | 
            +
            						Syn.selectText(this, sel.start == 0 ? 0 : sel.start - 1, sel.end)
         | 
| 728 | 
            +
            					} else {
         | 
| 729 | 
            +
            						Syn.selectText(this, sel.start == 0 ? 0 : sel.start - 1)
         | 
| 730 | 
            +
            					}
         | 
| 731 | 
            +
            				}
         | 
| 732 | 
            +
            			},
         | 
| 733 | 
            +
            			'right': function( options, scope, key, force, sel ) {
         | 
| 734 | 
            +
            				if ( Syn.typeable.test(this.nodeName) ) {
         | 
| 735 | 
            +
            					if ( Syn.key.shiftKey ) {
         | 
| 736 | 
            +
            						Syn.selectText(this, sel.start, sel.end + 1 > this.value.length ? this.value.length : sel.end + 1)
         | 
| 737 | 
            +
            					} else {
         | 
| 738 | 
            +
            						Syn.selectText(this, sel.end + 1 > this.value.length ? this.value.length : sel.end + 1)
         | 
| 739 | 
            +
            					}
         | 
| 740 | 
            +
            				}
         | 
| 741 | 
            +
            			},
         | 
| 742 | 
            +
            			'up': function() {
         | 
| 743 | 
            +
            				if (/select/i.test(this.nodeName) ) {
         | 
| 744 | 
            +
             | 
| 745 | 
            +
            					this.selectedIndex = this.selectedIndex ? this.selectedIndex - 1 : 0;
         | 
| 746 | 
            +
            					//set this to change on blur?
         | 
| 747 | 
            +
            				}
         | 
| 748 | 
            +
            			},
         | 
| 749 | 
            +
            			'down': function() {
         | 
| 750 | 
            +
            				if (/select/i.test(this.nodeName) ) {
         | 
| 751 | 
            +
            					Syn.changeOnBlur(this, "selectedIndex", this.selectedIndex)
         | 
| 752 | 
            +
            					this.selectedIndex = this.selectedIndex + 1;
         | 
| 753 | 
            +
            					//set this to change on blur?
         | 
| 754 | 
            +
            				}
         | 
| 755 | 
            +
            			},
         | 
| 756 | 
            +
            			'shift': function() {
         | 
| 757 | 
            +
            				return null;
         | 
| 758 | 
            +
            			}
         | 
| 759 | 
            +
            		}
         | 
| 760 | 
            +
            	});
         | 
| 761 | 
            +
             | 
| 762 | 
            +
             | 
| 763 | 
            +
            	h.extend(Syn.create, {
         | 
| 764 | 
            +
            		keydown: {
         | 
| 765 | 
            +
            			setup: function( type, options, element ) {
         | 
| 766 | 
            +
            				if ( h.inArray(options, Syn.key.kinds.special) != -1 ) {
         | 
| 767 | 
            +
            					Syn.key[options + "Key"] = element;
         | 
| 768 | 
            +
            				}
         | 
| 769 | 
            +
            			}
         | 
| 770 | 
            +
            		},
         | 
| 771 | 
            +
            		keypress: {
         | 
| 772 | 
            +
            			setup: function( type, options, element ) {
         | 
| 773 | 
            +
            				// if this browsers supports writing keys on events
         | 
| 774 | 
            +
            				// but doesn't write them if the element isn't focused
         | 
| 775 | 
            +
            				// focus on the element (ignored if already focused)
         | 
| 776 | 
            +
            				if ( S.support.keyCharacters && !S.support.keysOnNotFocused ) {
         | 
| 777 | 
            +
            					element.focus()
         | 
| 778 | 
            +
            				}
         | 
| 779 | 
            +
            			}
         | 
| 780 | 
            +
            		},
         | 
| 781 | 
            +
            		keyup: {
         | 
| 782 | 
            +
            			setup: function( type, options, element ) {
         | 
| 783 | 
            +
            				if ( h.inArray(options, Syn.key.kinds.special) != -1 ) {
         | 
| 784 | 
            +
            					Syn.key[options + "Key"] = null;
         | 
| 785 | 
            +
            				}
         | 
| 786 | 
            +
            			}
         | 
| 787 | 
            +
            		},
         | 
| 788 | 
            +
            		key: {
         | 
| 789 | 
            +
            			// return the options for a key event
         | 
| 790 | 
            +
            			options: function( type, options, element ) {
         | 
| 791 | 
            +
            				//check if options is character or has character
         | 
| 792 | 
            +
            				options = typeof options != "object" ? {
         | 
| 793 | 
            +
            					character: options
         | 
| 794 | 
            +
            				} : options;
         | 
| 795 | 
            +
             | 
| 796 | 
            +
            				//don't change the orignial
         | 
| 797 | 
            +
            				options = h.extend({}, options)
         | 
| 798 | 
            +
            				if ( options.character ) {
         | 
| 799 | 
            +
            					h.extend(options, S.key.options(options.character, type));
         | 
| 800 | 
            +
            					delete options.character;
         | 
| 801 | 
            +
            				}
         | 
| 802 | 
            +
             | 
| 803 | 
            +
            				options = h.extend({
         | 
| 804 | 
            +
            					ctrlKey: !! Syn.key.ctrlKey,
         | 
| 805 | 
            +
            					altKey: !! Syn.key.altKey,
         | 
| 806 | 
            +
            					shiftKey: !! Syn.key.shiftKey,
         | 
| 807 | 
            +
            					metaKey: !! Syn.key.metaKey
         | 
| 808 | 
            +
            				}, options)
         | 
| 809 | 
            +
             | 
| 810 | 
            +
            				return options;
         | 
| 811 | 
            +
            			},
         | 
| 812 | 
            +
            			// creates a key event
         | 
| 813 | 
            +
            			event: function( type, options, element ) { //Everyone Else
         | 
| 814 | 
            +
            				var doc = h.getWindow(element).document || document;
         | 
| 815 | 
            +
            				if ( doc.createEvent ) {
         | 
| 816 | 
            +
            					var event;
         | 
| 817 | 
            +
             | 
| 818 | 
            +
            					try {
         | 
| 819 | 
            +
             | 
| 820 | 
            +
            						event = doc.createEvent("KeyEvents");
         | 
| 821 | 
            +
            						event.initKeyEvent(type, true, true, window, options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.keyCode, options.charCode);
         | 
| 822 | 
            +
            					}
         | 
| 823 | 
            +
            					catch (e) {
         | 
| 824 | 
            +
            						event = h.createBasicStandardEvent(type, options, doc);
         | 
| 825 | 
            +
            					}
         | 
| 826 | 
            +
            					event.synthetic = true;
         | 
| 827 | 
            +
            					return event;
         | 
| 828 | 
            +
            				}
         | 
| 829 | 
            +
            				else {
         | 
| 830 | 
            +
            					var event;
         | 
| 831 | 
            +
            					try {
         | 
| 832 | 
            +
            						event = h.createEventObject.apply(this, arguments);
         | 
| 833 | 
            +
            						h.extend(event, options)
         | 
| 834 | 
            +
            					}
         | 
| 835 | 
            +
            					catch (e) {}
         | 
| 836 | 
            +
             | 
| 837 | 
            +
            					return event;
         | 
| 838 | 
            +
            				}
         | 
| 839 | 
            +
            			}
         | 
| 840 | 
            +
            		}
         | 
| 841 | 
            +
            	});
         | 
| 842 | 
            +
             | 
| 843 | 
            +
            	var convert = {
         | 
| 844 | 
            +
            		"enter": "\r",
         | 
| 845 | 
            +
            		"backspace": "\b",
         | 
| 846 | 
            +
            		"tab": "\t",
         | 
| 847 | 
            +
            		"space": " "
         | 
| 848 | 
            +
            	}
         | 
| 849 | 
            +
             | 
| 850 | 
            +
            	/**
         | 
| 851 | 
            +
            	 * @add Syn prototype
         | 
| 852 | 
            +
            	 */
         | 
| 853 | 
            +
            	h.extend(Syn.init.prototype, {
         | 
| 854 | 
            +
            		/**
         | 
| 855 | 
            +
            		 * @function key
         | 
| 856 | 
            +
            		 * Types a single key.  The key should be
         | 
| 857 | 
            +
            		 * a string that matches a 
         | 
| 858 | 
            +
            		 * [Syn.static.keycodes].
         | 
| 859 | 
            +
            		 * 
         | 
| 860 | 
            +
            		 * The following sends a carridge return
         | 
| 861 | 
            +
            		 * to the 'name' element.
         | 
| 862 | 
            +
            		 * @codestart
         | 
| 863 | 
            +
            		 * Syn.key('\r','name')
         | 
| 864 | 
            +
            		 * @codeend
         | 
| 865 | 
            +
            		 * For each character, a keydown, keypress, and keyup is triggered if
         | 
| 866 | 
            +
            		 * appropriate.
         | 
| 867 | 
            +
            		 * @param {String} options
         | 
| 868 | 
            +
            		 * @param {HTMLElement} [element]
         | 
| 869 | 
            +
            		 * @param {Function} [callback]
         | 
| 870 | 
            +
            		 * @return {HTMLElement} the element currently focused.
         | 
| 871 | 
            +
            		 */
         | 
| 872 | 
            +
            		_key: function( options, element, callback ) {
         | 
| 873 | 
            +
            			//first check if it is a special up
         | 
| 874 | 
            +
            			if (/-up$/.test(options) && h.inArray(options.replace("-up", ""), Syn.key.kinds.special) != -1 ) {
         | 
| 875 | 
            +
            				Syn.trigger('keyup', options.replace("-up", ""), element)
         | 
| 876 | 
            +
            				callback(true, element);
         | 
| 877 | 
            +
            				return;
         | 
| 878 | 
            +
            			}
         | 
| 879 | 
            +
             | 
| 880 | 
            +
             | 
| 881 | 
            +
            			var caret = Syn.typeable.test(element.nodeName) && getSelection(element),
         | 
| 882 | 
            +
            				key = convert[options] || options,
         | 
| 883 | 
            +
            				// should we run default events
         | 
| 884 | 
            +
            				runDefaults = Syn.trigger('keydown', key, element),
         | 
| 885 | 
            +
             | 
| 886 | 
            +
            				// a function that gets the default behavior for a key
         | 
| 887 | 
            +
            				getDefault = Syn.key.getDefault,
         | 
| 888 | 
            +
             | 
| 889 | 
            +
            				// how this browser handles preventing default events
         | 
| 890 | 
            +
            				prevent = Syn.key.browser.prevent,
         | 
| 891 | 
            +
             | 
| 892 | 
            +
            				// the result of the default event
         | 
| 893 | 
            +
            				defaultResult,
         | 
| 894 | 
            +
             | 
| 895 | 
            +
            				// options for keypress
         | 
| 896 | 
            +
            				keypressOptions = Syn.key.options(key, 'keypress')
         | 
| 897 | 
            +
             | 
| 898 | 
            +
             | 
| 899 | 
            +
            				if ( runDefaults ) {
         | 
| 900 | 
            +
            					//if the browser doesn't create keypresses for this key, run default
         | 
| 901 | 
            +
            					if (!keypressOptions ) {
         | 
| 902 | 
            +
            						defaultResult = getDefault(key).call(element, keypressOptions, h.getWindow(element), key, undefined, caret)
         | 
| 903 | 
            +
            					} else {
         | 
| 904 | 
            +
            						//do keypress
         | 
| 905 | 
            +
            						runDefaults = Syn.trigger('keypress', keypressOptions, element)
         | 
| 906 | 
            +
            						if ( runDefaults ) {
         | 
| 907 | 
            +
            							defaultResult = getDefault(key).call(element, keypressOptions, h.getWindow(element), key, undefined, caret)
         | 
| 908 | 
            +
            						}
         | 
| 909 | 
            +
            					}
         | 
| 910 | 
            +
            				} else {
         | 
| 911 | 
            +
            					//canceled ... possibly don't run keypress
         | 
| 912 | 
            +
            					if ( keypressOptions && h.inArray('keypress', prevent.keydown) == -1 ) {
         | 
| 913 | 
            +
            						Syn.trigger('keypress', keypressOptions, element)
         | 
| 914 | 
            +
            					}
         | 
| 915 | 
            +
            				}
         | 
| 916 | 
            +
            				if ( defaultResult && defaultResult.nodeName ) {
         | 
| 917 | 
            +
            					element = defaultResult
         | 
| 918 | 
            +
            				}
         | 
| 919 | 
            +
             | 
| 920 | 
            +
            				if ( defaultResult !== null ) {
         | 
| 921 | 
            +
            					setTimeout(function() {
         | 
| 922 | 
            +
            						Syn.trigger('keyup', Syn.key.options(key, 'keyup'), element)
         | 
| 923 | 
            +
            						callback(runDefaults, element)
         | 
| 924 | 
            +
            					}, 1)
         | 
| 925 | 
            +
            				} else {
         | 
| 926 | 
            +
            					callback(runDefaults, element)
         | 
| 927 | 
            +
            				}
         | 
| 928 | 
            +
             | 
| 929 | 
            +
             | 
| 930 | 
            +
            				//do mouseup
         | 
| 931 | 
            +
            				return element;
         | 
| 932 | 
            +
            			// is there a keypress? .. if not , run default
         | 
| 933 | 
            +
            			// yes -> did we prevent it?, if not run ...
         | 
| 934 | 
            +
            		},
         | 
| 935 | 
            +
            		/**
         | 
| 936 | 
            +
            		 * @function type
         | 
| 937 | 
            +
            		 * Types sequence of [Syn.key key actions].  Each
         | 
| 938 | 
            +
            		 * character is typed, one at a type.
         | 
| 939 | 
            +
            		 * Multi-character keys like 'left' should be
         | 
| 940 | 
            +
            		 * enclosed in square brackents.
         | 
| 941 | 
            +
            		 * 
         | 
| 942 | 
            +
            		 * The following types 'JavaScript MVC' then deletes the space.
         | 
| 943 | 
            +
            		 * @codestart
         | 
| 944 | 
            +
            		 * Syn.type('JavaScript MVC[left][left][left]\b','name')
         | 
| 945 | 
            +
            		 * @codeend
         | 
| 946 | 
            +
            		 * 
         | 
| 947 | 
            +
            		 * Type is able to handle (and move with) tabs (\t).  
         | 
| 948 | 
            +
            		 * The following simulates tabing and entering values in a form and 
         | 
| 949 | 
            +
            		 * eventually submitting the form.
         | 
| 950 | 
            +
            		 * @codestart
         | 
| 951 | 
            +
            		 * Syn.type("Justin\tMeyer\t27\tjustinbmeyer@gmail.com\r")
         | 
| 952 | 
            +
            		 * @codeend
         | 
| 953 | 
            +
            		 * @param {String} options the text to type
         | 
| 954 | 
            +
            		 * @param {HTMLElement} [element] an element or an id of an element
         | 
| 955 | 
            +
            		 * @param {Function} [callback] a function to callback
         | 
| 956 | 
            +
            		 */
         | 
| 957 | 
            +
            		_type: function( options, element, callback ) {
         | 
| 958 | 
            +
            			//break it up into parts ...
         | 
| 959 | 
            +
            			//go through each type and run
         | 
| 960 | 
            +
            			var parts = options.match(/(\[[^\]]+\])|([^\[])/g),
         | 
| 961 | 
            +
            				self = this,
         | 
| 962 | 
            +
            				runNextPart = function( runDefaults, el ) {
         | 
| 963 | 
            +
            					var part = parts.shift();
         | 
| 964 | 
            +
            					if (!part ) {
         | 
| 965 | 
            +
            						callback(runDefaults, el);
         | 
| 966 | 
            +
            						return;
         | 
| 967 | 
            +
            					}
         | 
| 968 | 
            +
            					el = el || element;
         | 
| 969 | 
            +
            					if ( part.length > 1 ) {
         | 
| 970 | 
            +
            						part = part.substr(1, part.length - 2)
         | 
| 971 | 
            +
            					}
         | 
| 972 | 
            +
            					self._key(part, el, runNextPart)
         | 
| 973 | 
            +
            				}
         | 
| 974 | 
            +
             | 
| 975 | 
            +
            				runNextPart();
         | 
| 976 | 
            +
             | 
| 977 | 
            +
            		}
         | 
| 978 | 
            +
            	});
         | 
| 979 | 
            +
             | 
| 980 | 
            +
             | 
| 981 | 
            +
            	//do support code
         | 
| 982 | 
            +
            	(function() {
         | 
| 983 | 
            +
            		if (!document.body ) {
         | 
| 984 | 
            +
            			setTimeout(arguments.callee, 1)
         | 
| 985 | 
            +
            			return;
         | 
| 986 | 
            +
            		}
         | 
| 987 | 
            +
             | 
| 988 | 
            +
            		var div = document.createElement("div"),
         | 
| 989 | 
            +
            			checkbox, submit, form, input, submitted = false,
         | 
| 990 | 
            +
            			anchor, textarea, inputter;
         | 
| 991 | 
            +
             | 
| 992 | 
            +
            		div.innerHTML = "<form id='outer'>" + 
         | 
| 993 | 
            +
            						"<input name='checkbox' type='checkbox'/>" + 
         | 
| 994 | 
            +
            						"<input name='radio' type='radio' />" + 
         | 
| 995 | 
            +
            						"<input type='submit' name='submitter'/>" + 
         | 
| 996 | 
            +
            						"<input type='input' name='inputter'/>" + 
         | 
| 997 | 
            +
            						"<input name='one'>" + 
         | 
| 998 | 
            +
            						"<input name='two'/>" + 
         | 
| 999 | 
            +
            						"<a href='#abc'></a>" + 
         | 
| 1000 | 
            +
            						"<textarea>1\n2</textarea>" +
         | 
| 1001 | 
            +
            						"</form>";
         | 
| 1002 | 
            +
             | 
| 1003 | 
            +
            		document.documentElement.appendChild(div);
         | 
| 1004 | 
            +
            		form = div.firstChild;
         | 
| 1005 | 
            +
            		checkbox = form.childNodes[0];
         | 
| 1006 | 
            +
            		submit = form.childNodes[2];
         | 
| 1007 | 
            +
            		anchor = form.getElementsByTagName("a")[0];
         | 
| 1008 | 
            +
            		textarea = form.getElementsByTagName("textarea")[0];
         | 
| 1009 | 
            +
            		inputter = form.childNodes[3];
         | 
| 1010 | 
            +
             | 
| 1011 | 
            +
            		form.onsubmit = function( ev ) {
         | 
| 1012 | 
            +
            			if ( ev.preventDefault ) ev.preventDefault();
         | 
| 1013 | 
            +
            			S.support.keypressSubmits = true;
         | 
| 1014 | 
            +
            			ev.returnValue = false;
         | 
| 1015 | 
            +
            			return false;
         | 
| 1016 | 
            +
            		};
         | 
| 1017 | 
            +
            		// Firefox 4 won't write key events if the element isn't focused
         | 
| 1018 | 
            +
            		inputter.focus();
         | 
| 1019 | 
            +
            		Syn.trigger("keypress", "\r", inputter);
         | 
| 1020 | 
            +
             | 
| 1021 | 
            +
             | 
| 1022 | 
            +
            		Syn.trigger("keypress", "a", inputter);
         | 
| 1023 | 
            +
            		S.support.keyCharacters = inputter.value == "a";
         | 
| 1024 | 
            +
             | 
| 1025 | 
            +
             | 
| 1026 | 
            +
            		inputter.value = "a";
         | 
| 1027 | 
            +
            		Syn.trigger("keypress", "\b", inputter);
         | 
| 1028 | 
            +
            		S.support.backspaceWorks = inputter.value == "";
         | 
| 1029 | 
            +
             | 
| 1030 | 
            +
             | 
| 1031 | 
            +
             | 
| 1032 | 
            +
            		inputter.onchange = function() {
         | 
| 1033 | 
            +
            			S.support.focusChanges = true;
         | 
| 1034 | 
            +
            		}
         | 
| 1035 | 
            +
            		inputter.focus();
         | 
| 1036 | 
            +
            		Syn.trigger("keypress", "a", inputter);
         | 
| 1037 | 
            +
            		form.childNodes[5].focus(); // this will throw a change event
         | 
| 1038 | 
            +
            		Syn.trigger("keypress", "b", inputter);
         | 
| 1039 | 
            +
            		S.support.keysOnNotFocused = inputter.value == "ab";
         | 
| 1040 | 
            +
             | 
| 1041 | 
            +
            		//test keypress \r on anchor submits
         | 
| 1042 | 
            +
            		S.bind(anchor, "click", function( ev ) {
         | 
| 1043 | 
            +
            			if ( ev.preventDefault ) ev.preventDefault();
         | 
| 1044 | 
            +
            			S.support.keypressOnAnchorClicks = true;
         | 
| 1045 | 
            +
            			ev.returnValue = false;
         | 
| 1046 | 
            +
            			return false;
         | 
| 1047 | 
            +
            		})
         | 
| 1048 | 
            +
            		Syn.trigger("keypress", "\r", anchor);
         | 
| 1049 | 
            +
             | 
| 1050 | 
            +
            		S.support.textareaCarriage = textarea.value.length == 4
         | 
| 1051 | 
            +
            		document.documentElement.removeChild(div);
         | 
| 1052 | 
            +
             | 
| 1053 | 
            +
            		S.support.ready++;
         | 
| 1054 | 
            +
            	})();
         | 
| 1055 | 
            +
            })(true);
         |