yepkeynav-rails 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +6 -0
  4. data/Rakefile +40 -0
  5. data/app/assets/javascripts/yepKeyNav/README.md +66 -0
  6. data/app/assets/javascripts/yepKeyNav/jquery.hotkeys.js +223 -0
  7. data/app/assets/javascripts/yepKeyNav/jquery.scrollTo-1.4.3.1.js +218 -0
  8. data/app/assets/javascripts/yepKeyNav/yepKeyNav.js +192 -0
  9. data/app/assets/javascripts/yepKeyNav.js +1 -0
  10. data/lib/tasks/yepkeynav-rails_tasks.rake +4 -0
  11. data/lib/yepkeynav-rails/engine.rb +5 -0
  12. data/lib/yepkeynav-rails/version.rb +3 -0
  13. data/lib/yepkeynav-rails.rb +4 -0
  14. data/test/dummy/README.rdoc +261 -0
  15. data/test/dummy/Rakefile +7 -0
  16. data/test/dummy/app/assets/javascripts/application.js +15 -0
  17. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  18. data/test/dummy/app/controllers/application_controller.rb +3 -0
  19. data/test/dummy/app/helpers/application_helper.rb +2 -0
  20. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  21. data/test/dummy/config/application.rb +59 -0
  22. data/test/dummy/config/boot.rb +10 -0
  23. data/test/dummy/config/database.yml +25 -0
  24. data/test/dummy/config/environment.rb +5 -0
  25. data/test/dummy/config/environments/development.rb +37 -0
  26. data/test/dummy/config/environments/production.rb +67 -0
  27. data/test/dummy/config/environments/test.rb +37 -0
  28. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  29. data/test/dummy/config/initializers/inflections.rb +15 -0
  30. data/test/dummy/config/initializers/mime_types.rb +5 -0
  31. data/test/dummy/config/initializers/secret_token.rb +7 -0
  32. data/test/dummy/config/initializers/session_store.rb +8 -0
  33. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  34. data/test/dummy/config/locales/en.yml +5 -0
  35. data/test/dummy/config/routes.rb +4 -0
  36. data/test/dummy/config.ru +4 -0
  37. data/test/dummy/public/404.html +26 -0
  38. data/test/dummy/public/422.html +26 -0
  39. data/test/dummy/public/500.html +25 -0
  40. data/test/dummy/public/favicon.ico +0 -0
  41. data/test/dummy/script/rails +6 -0
  42. data/test/integration/navigation_test.rb +10 -0
  43. data/test/test_helper.rb +15 -0
  44. data/test/yepkeynav-rails_test.rb +7 -0
  45. metadata +145 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ N2UwZGRhOTU0YThhYjAyMWRkMDRmYjYxZDUwZTlhMWQ4NDQyZDMxMA==
5
+ data.tar.gz: !binary |-
6
+ YWM1OTA0MTYxOWYzZmM3YjBiZGJkZDEyNzk5YjExMDIwYjYwOWEzZQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NjA4ZDg3YjYzMTc0ZGFkZmIzMmIyMGMxZGVjMGM2ZjZkMGYxY2ExOWRmZTkw
10
+ MTBlNmY3MzlmNzFmNDQwMjI5OWI1YjA5ZWYxOWI1ZmU1NDQyY2ZhZDgxNWZl
11
+ MzFlMDk1YjhkY2QzZjUxN2YzODgxMGZhZDZjNWUzYTI3YWYxZTA=
12
+ data.tar.gz: !binary |-
13
+ Nzg4NzYxZDM5NTI1OTI2NzUyMzc2MDZkNGEyMmM5YWEzMTUwZmRjZDUwMjMz
14
+ ZWVjM2UwMjU3MTdjMjM0ZGM5MzgxZmUwMWYwZTc5OGIyMmNhN2FjNjQ4NjNj
15
+ MWFiNTljMjJhYzRjMTMyM2E1ZGQ1MTAxMGExZTMwOTMxYjdiYzI=
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,6 @@
1
+ = YepkeynavRails
2
+
3
+ This project rocks and uses MIT-LICENSE.
4
+
5
+ == Usage
6
+
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'yepKeyNav-Rails'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+
27
+
28
+ Bundler::GemHelper.install_tasks
29
+
30
+ require 'rake/testtask'
31
+
32
+ Rake::TestTask.new(:test) do |t|
33
+ t.libs << 'lib'
34
+ t.libs << 'test'
35
+ t.pattern = 'test/**/*_test.rb'
36
+ t.verbose = false
37
+ end
38
+
39
+
40
+ task :default => :test
@@ -0,0 +1,66 @@
1
+ yepKeyNav
2
+ ==========
3
+
4
+ JQuery plugin provides a way to navigate or select items on a page using keyboad shortcuts.
5
+
6
+ # Dependencies
7
+ https://github.com/tzuryby/jquery.hotkeys/
8
+ and http://flesler.blogspot.com/2007/10/jqueryscrollto.html
9
+
10
+
11
+ # USAGE
12
+
13
+ $("selector of a list").yepNavKey()
14
+
15
+ all itens with class yep-key-nav are navigable
16
+
17
+ example to return the jquery selector for all selected itens:
18
+
19
+ $("selector of a list").yepNavKey('selected', function(ret) {
20
+ ret.each(function() {
21
+ //do something
22
+ });
23
+ });
24
+
25
+ ## Events
26
+
27
+ current.yepKeyNav - when the current item is changed
28
+ lostCurrent.yepKeyNav - when item lost the current selecion
29
+ select.yepKeyNav - when an item is selected
30
+ unselect.yepKeyNav - when an item is unselected
31
+
32
+ Example:
33
+
34
+ $("list").on('current.yepKeyNav', function(evt) {
35
+ $current = $(event.target)
36
+
37
+ #... do someting with new $current item
38
+ })
39
+
40
+
41
+ ## Default Options
42
+ classes: {
43
+ navigable: "yep-key-nav",
44
+ currentItem: "yep-key-nav-current",
45
+ selectedItem: "yep-key-nav-selected",
46
+ itemSelector: "yep-key-nav-selector", //should be a checkbox
47
+ selectAll: "yep-key-nav-select-all" //should be a checkbox, when cliecked all itens will be selected or unselected
48
+ },
49
+ scrollSelector: 'window', //selector of panel with scroll of items
50
+ shortcuts: {
51
+ next: "j",
52
+ prev: "k",
53
+ toggleSelect: "x"
54
+ }
55
+
56
+
57
+ # Default Shortcuts
58
+
59
+ j -> next element
60
+ k -> previous element
61
+ x -> select current element
62
+ space -> exec a configured function
63
+
64
+ # BUGS
65
+
66
+ - navigable itens are found on entire document, and not only on $(this) scope
@@ -0,0 +1,223 @@
1
+ /**
2
+ * http://www.openjs.com/scripts/events/keyboard_shortcuts/
3
+ * Version : 2.01.B
4
+ * By Binny V A
5
+ * License : BSD
6
+ */
7
+ shortcut = {
8
+ 'all_shortcuts':{},//All the shortcuts are stored in this array
9
+ 'add': function(shortcut_combination,callback,opt) {
10
+ //Provide a set of default options
11
+ var default_options = {
12
+ 'type':'keydown',
13
+ 'propagate':false,
14
+ 'disable_in_input':false,
15
+ 'target':document,
16
+ 'keycode':false
17
+ }
18
+ if(!opt) opt = default_options;
19
+ else {
20
+ for(var dfo in default_options) {
21
+ if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];
22
+ }
23
+ }
24
+
25
+ var ele = opt.target;
26
+ if(typeof opt.target == 'string') ele = document.getElementById(opt.target);
27
+ var ths = this;
28
+ shortcut_combination = shortcut_combination.toLowerCase();
29
+
30
+ //The function to be called at keypress
31
+ var func = function(e) {
32
+ e = e || window.event;
33
+
34
+ if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields
35
+ var element;
36
+ if(e.target) element=e.target;
37
+ else if(e.srcElement) element=e.srcElement;
38
+ if(element.nodeType==3) element=element.parentNode;
39
+
40
+ if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;
41
+ }
42
+
43
+ //Find Which key is pressed
44
+ if (e.keyCode) code = e.keyCode;
45
+ else if (e.which) code = e.which;
46
+ var character = String.fromCharCode(code).toLowerCase();
47
+
48
+ if(code == 188) character=","; //If the user presses , when the type is onkeydown
49
+ if(code == 190) character="."; //If the user presses , when the type is onkeydown
50
+
51
+ var keys = shortcut_combination.split("+");
52
+ //Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
53
+ var kp = 0;
54
+
55
+ //Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
56
+ var shift_nums = {
57
+ "`":"~",
58
+ "1":"!",
59
+ "2":"@",
60
+ "3":"#",
61
+ "4":"$",
62
+ "5":"%",
63
+ "6":"^",
64
+ "7":"&",
65
+ "8":"*",
66
+ "9":"(",
67
+ "0":")",
68
+ "-":"_",
69
+ "=":"+",
70
+ ";":":",
71
+ "'":"\"",
72
+ ",":"<",
73
+ ".":">",
74
+ "/":"?",
75
+ "\\":"|"
76
+ }
77
+ //Special Keys - and their codes
78
+ var special_keys = {
79
+ 'esc':27,
80
+ 'escape':27,
81
+ 'tab':9,
82
+ 'space':32,
83
+ 'return':13,
84
+ 'enter':13,
85
+ 'backspace':8,
86
+
87
+ 'scrolllock':145,
88
+ 'scroll_lock':145,
89
+ 'scroll':145,
90
+ 'capslock':20,
91
+ 'caps_lock':20,
92
+ 'caps':20,
93
+ 'numlock':144,
94
+ 'num_lock':144,
95
+ 'num':144,
96
+
97
+ 'pause':19,
98
+ 'break':19,
99
+
100
+ 'insert':45,
101
+ 'home':36,
102
+ 'delete':46,
103
+ 'end':35,
104
+
105
+ 'pageup':33,
106
+ 'page_up':33,
107
+ 'pu':33,
108
+
109
+ 'pagedown':34,
110
+ 'page_down':34,
111
+ 'pd':34,
112
+
113
+ 'left':37,
114
+ 'up':38,
115
+ 'right':39,
116
+ 'down':40,
117
+
118
+ 'f1':112,
119
+ 'f2':113,
120
+ 'f3':114,
121
+ 'f4':115,
122
+ 'f5':116,
123
+ 'f6':117,
124
+ 'f7':118,
125
+ 'f8':119,
126
+ 'f9':120,
127
+ 'f10':121,
128
+ 'f11':122,
129
+ 'f12':123
130
+ }
131
+
132
+ var modifiers = {
133
+ shift: { wanted:false, pressed:false},
134
+ ctrl : { wanted:false, pressed:false},
135
+ alt : { wanted:false, pressed:false},
136
+ meta : { wanted:false, pressed:false} //Meta is Mac specific
137
+ };
138
+
139
+ if(e.ctrlKey) modifiers.ctrl.pressed = true;
140
+ if(e.shiftKey) modifiers.shift.pressed = true;
141
+ if(e.altKey) modifiers.alt.pressed = true;
142
+ if(e.metaKey) modifiers.meta.pressed = true;
143
+
144
+ for(var i=0; k=keys[i],i<keys.length; i++) {
145
+ //Modifiers
146
+ if(k == 'ctrl' || k == 'control') {
147
+ kp++;
148
+ modifiers.ctrl.wanted = true;
149
+
150
+ } else if(k == 'shift') {
151
+ kp++;
152
+ modifiers.shift.wanted = true;
153
+
154
+ } else if(k == 'alt') {
155
+ kp++;
156
+ modifiers.alt.wanted = true;
157
+ } else if(k == 'meta') {
158
+ kp++;
159
+ modifiers.meta.wanted = true;
160
+ } else if(k.length > 1) { //If it is a special key
161
+ if(special_keys[k] == code) kp++;
162
+
163
+ } else if(opt['keycode']) {
164
+ if(opt['keycode'] == code) kp++;
165
+
166
+ } else { //The special keys did not match
167
+ if(character == k) kp++;
168
+ else {
169
+ if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase
170
+ character = shift_nums[character];
171
+ if(character == k) kp++;
172
+ }
173
+ }
174
+ }
175
+ }
176
+
177
+ if(kp == keys.length &&
178
+ modifiers.ctrl.pressed == modifiers.ctrl.wanted &&
179
+ modifiers.shift.pressed == modifiers.shift.wanted &&
180
+ modifiers.alt.pressed == modifiers.alt.wanted &&
181
+ modifiers.meta.pressed == modifiers.meta.wanted) {
182
+ callback(e);
183
+
184
+ if(!opt['propagate']) { //Stop the event
185
+ //e.cancelBubble is supported by IE - this will kill the bubbling process.
186
+ e.cancelBubble = true;
187
+ e.returnValue = false;
188
+
189
+ //e.stopPropagation works in Firefox.
190
+ if (e.stopPropagation) {
191
+ e.stopPropagation();
192
+ e.preventDefault();
193
+ }
194
+ return false;
195
+ }
196
+ }
197
+ }
198
+ this.all_shortcuts[shortcut_combination] = {
199
+ 'callback':func,
200
+ 'target':ele,
201
+ 'event': opt['type']
202
+ };
203
+ //Attach the function with the event
204
+ if(ele.addEventListener) ele.addEventListener(opt['type'], func, false);
205
+ else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);
206
+ else ele['on'+opt['type']] = func;
207
+ },
208
+
209
+ //Remove the shortcut - just specify the shortcut and I will remove the binding
210
+ 'remove':function(shortcut_combination) {
211
+ shortcut_combination = shortcut_combination.toLowerCase();
212
+ var binding = this.all_shortcuts[shortcut_combination];
213
+ delete(this.all_shortcuts[shortcut_combination])
214
+ if(!binding) return;
215
+ var type = binding['event'];
216
+ var ele = binding['target'];
217
+ var callback = binding['callback'];
218
+
219
+ if(ele.detachEvent) ele.detachEvent('on'+type, callback);
220
+ else if(ele.removeEventListener) ele.removeEventListener(type, callback, false);
221
+ else ele['on'+type] = false;
222
+ }
223
+ }
@@ -0,0 +1,218 @@
1
+ /*!
2
+ * jQuery.ScrollTo
3
+ * Copyright (c) 2007-2012 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
4
+ * Dual licensed under MIT and GPL.
5
+ * Date: 4/09/2012
6
+ *
7
+ * @projectDescription Easy element scrolling using jQuery.
8
+ * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
9
+ * @author Ariel Flesler
10
+ * @version 1.4.3.1
11
+ *
12
+ * @id jQuery.scrollTo
13
+ * @id jQuery.fn.scrollTo
14
+ * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
15
+ * The different options for target are:
16
+ * - A number position (will be applied to all axes).
17
+ * - A string position ('44', '100px', '+=90', etc ) will be applied to all axes
18
+ * - A jQuery/DOM element ( logically, child of the element to scroll )
19
+ * - A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
20
+ * - A hash { top:x, left:y }, x and y can be any kind of number/string like above.
21
+ * - A percentage of the container's dimension/s, for example: 50% to go to the middle.
22
+ * - The string 'max' for go-to-end.
23
+ * @param {Number, Function} duration The OVERALL length of the animation, this argument can be the settings object instead.
24
+ * @param {Object,Function} settings Optional set of settings or the onAfter callback.
25
+ * @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
26
+ * @option {Number, Function} duration The OVERALL length of the animation.
27
+ * @option {String} easing The easing method for the animation.
28
+ * @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
29
+ * @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
30
+ * @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
31
+ * @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
32
+ * @option {Function} onAfter Function to be called after the scrolling ends.
33
+ * @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
34
+ * @return {jQuery} Returns the same jQuery object, for chaining.
35
+ *
36
+ * @desc Scroll to a fixed position
37
+ * @example $('div').scrollTo( 340 );
38
+ *
39
+ * @desc Scroll relatively to the actual position
40
+ * @example $('div').scrollTo( '+=340px', { axis:'y' } );
41
+ *
42
+ * @desc Scroll using a selector (relative to the scrolled element)
43
+ * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
44
+ *
45
+ * @desc Scroll to a DOM element (same for jQuery object)
46
+ * @example var second_child = document.getElementById('container').firstChild.nextSibling;
47
+ * $('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
48
+ * alert('scrolled!!');
49
+ * }});
50
+ *
51
+ * @desc Scroll on both axes, to different values
52
+ * @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } );
53
+ */
54
+
55
+ ;(function( $ ){
56
+
57
+ var $scrollTo = $.scrollTo = function( target, duration, settings ){
58
+ $(window).scrollTo( target, duration, settings );
59
+ };
60
+
61
+ $scrollTo.defaults = {
62
+ axis:'xy',
63
+ duration: parseFloat($.fn.jquery) >= 1.3 ? 0 : 1,
64
+ limit:true
65
+ };
66
+
67
+ // Returns the element that needs to be animated to scroll the window.
68
+ // Kept for backwards compatibility (specially for localScroll & serialScroll)
69
+ $scrollTo.window = function( scope ){
70
+ return $(window)._scrollable();
71
+ };
72
+
73
+ // Hack, hack, hack :)
74
+ // Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
75
+ $.fn._scrollable = function(){
76
+ return this.map(function(){
77
+ var elem = this,
78
+ isWin = !elem.nodeName || $.inArray( elem.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1;
79
+
80
+ if( !isWin )
81
+ return elem;
82
+
83
+ var doc = (elem.contentWindow || elem).document || elem.ownerDocument || elem;
84
+
85
+ return /webkit/i.test(navigator.userAgent) || doc.compatMode == 'BackCompat' ?
86
+ doc.body :
87
+ doc.documentElement;
88
+ });
89
+ };
90
+
91
+ $.fn.scrollTo = function( target, duration, settings ){
92
+ if( typeof duration == 'object' ){
93
+ settings = duration;
94
+ duration = 0;
95
+ }
96
+ if( typeof settings == 'function' )
97
+ settings = { onAfter:settings };
98
+
99
+ if( target == 'max' )
100
+ target = 9e9;
101
+
102
+ settings = $.extend( {}, $scrollTo.defaults, settings );
103
+ // Speed is still recognized for backwards compatibility
104
+ duration = duration || settings.duration;
105
+ // Make sure the settings are given right
106
+ settings.queue = settings.queue && settings.axis.length > 1;
107
+
108
+ if( settings.queue )
109
+ // Let's keep the overall duration
110
+ duration /= 2;
111
+ settings.offset = both( settings.offset );
112
+ settings.over = both( settings.over );
113
+
114
+ return this._scrollable().each(function(){
115
+ // Null target yields nothing, just like jQuery does
116
+ if (target == null) return;
117
+
118
+ var elem = this,
119
+ $elem = $(elem),
120
+ targ = target, toff, attr = {},
121
+ win = $elem.is('html,body');
122
+
123
+ switch( typeof targ ){
124
+ // A number will pass the regex
125
+ case 'number':
126
+ case 'string':
127
+ if( /^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(targ) ){
128
+ targ = both( targ );
129
+ // We are done
130
+ break;
131
+ }
132
+ // Relative selector, no break!
133
+ targ = $(targ,this);
134
+ if (!targ.length) return;
135
+ case 'object':
136
+ // DOMElement / jQuery
137
+ if( targ.is || targ.style )
138
+ // Get the real position of the target
139
+ toff = (targ = $(targ)).offset();
140
+ }
141
+ $.each( settings.axis.split(''), function( i, axis ){
142
+ var Pos = axis == 'x' ? 'Left' : 'Top',
143
+ pos = Pos.toLowerCase(),
144
+ key = 'scroll' + Pos,
145
+ old = elem[key],
146
+ max = $scrollTo.max(elem, axis);
147
+
148
+ if( toff ){// jQuery / DOMElement
149
+ attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );
150
+
151
+ // If it's a dom element, reduce the margin
152
+ if( settings.margin ){
153
+ attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
154
+ attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
155
+ }
156
+
157
+ attr[key] += settings.offset[pos] || 0;
158
+
159
+ if( settings.over[pos] )
160
+ // Scroll to a fraction of its width/height
161
+ attr[key] += targ[axis=='x'?'width':'height']() * settings.over[pos];
162
+ }else{
163
+ var val = targ[pos];
164
+ // Handle percentage values
165
+ attr[key] = val.slice && val.slice(-1) == '%' ?
166
+ parseFloat(val) / 100 * max
167
+ : val;
168
+ }
169
+
170
+ // Number or 'number'
171
+ if( settings.limit && /^\d+$/.test(attr[key]) )
172
+ // Check the limits
173
+ attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max );
174
+
175
+ // Queueing axes
176
+ if( !i && settings.queue ){
177
+ // Don't waste time animating, if there's no need.
178
+ if( old != attr[key] )
179
+ // Intermediate animation
180
+ animate( settings.onAfterFirst );
181
+ // Don't animate this axis again in the next iteration.
182
+ delete attr[key];
183
+ }
184
+ });
185
+
186
+ animate( settings.onAfter );
187
+
188
+ function animate( callback ){
189
+ $elem.animate( attr, duration, settings.easing, callback && function(){
190
+ callback.call(this, target, settings);
191
+ });
192
+ };
193
+
194
+ }).end();
195
+ };
196
+
197
+ // Max scrolling position, works on quirks mode
198
+ // It only fails (not too badly) on IE, quirks mode.
199
+ $scrollTo.max = function( elem, axis ){
200
+ var Dim = axis == 'x' ? 'Width' : 'Height',
201
+ scroll = 'scroll'+Dim;
202
+
203
+ if( !$(elem).is('html,body') )
204
+ return elem[scroll] - $(elem)[Dim.toLowerCase()]();
205
+
206
+ var size = 'client' + Dim,
207
+ html = elem.ownerDocument.documentElement,
208
+ body = elem.ownerDocument.body;
209
+
210
+ return Math.max( html[scroll], body[scroll] )
211
+ - Math.min( html[size] , body[size] );
212
+ };
213
+
214
+ function both( val ){
215
+ return typeof val == 'object' ? val : { top:val, left:val };
216
+ };
217
+
218
+ })( jQuery );