right-rails 0.6.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/CHANGELOG +8 -0
  2. data/README.rdoc +71 -0
  3. data/Rakefile +144 -14
  4. data/generators/right_rails/right_rails_generator.rb +18 -21
  5. data/init.rb +11 -32
  6. data/lib/generators/right_rails/right_rails_generator.rb +27 -0
  7. data/lib/generators/right_rails/templates/iframed.html.erb +10 -0
  8. data/lib/right-rails.rb +1 -1
  9. data/lib/right_rails/config.rb +278 -0
  10. data/lib/right_rails/controller_extensions.rb +10 -5
  11. data/lib/right_rails/helpers/basic.rb +10 -66
  12. data/lib/right_rails/helpers/forms.rb +141 -139
  13. data/lib/right_rails/helpers/misc.rb +45 -67
  14. data/lib/right_rails/helpers/rails.rb +40 -105
  15. data/lib/right_rails/helpers.rb +364 -1
  16. data/lib/right_rails/java_script_generator.rb +34 -24
  17. data/lib/right_rails.rb +6 -1
  18. data/{images → public/images}/colorpicker.png +0 -0
  19. data/{images → public/images}/resizable.png +0 -0
  20. data/public/javascripts/right/autocompleter-src.js +612 -0
  21. data/public/javascripts/right/autocompleter.js +18 -0
  22. data/public/javascripts/right/calendar-src.js +1448 -0
  23. data/public/javascripts/right/calendar.js +36 -0
  24. data/public/javascripts/right/colorpicker-src.js +967 -0
  25. data/public/javascripts/right/colorpicker.js +26 -0
  26. data/{javascripts/right-dnd-src.js → public/javascripts/right/dnd-src.js} +86 -52
  27. data/public/javascripts/right/dnd.js +20 -0
  28. data/{javascripts/right-effects-src.js → public/javascripts/right/effects-src.js} +90 -45
  29. data/public/javascripts/right/effects.js +17 -0
  30. data/{javascripts/right-ui-i18n-de.js → public/javascripts/right/i18n/de.js} +7 -7
  31. data/{javascripts/right-ui-i18n-en-us.js → public/javascripts/right/i18n/en-us.js} +1 -1
  32. data/{javascripts/right-ui-i18n-es.js → public/javascripts/right/i18n/es.js} +7 -7
  33. data/{javascripts/right-ui-i18n-fr.js → public/javascripts/right/i18n/fr.js} +7 -7
  34. data/{javascripts/right-ui-i18n-hu.js → public/javascripts/right/i18n/hu.js} +7 -7
  35. data/{javascripts/right-ui-i18n-jp.js → public/javascripts/right/i18n/jp.js} +7 -7
  36. data/{javascripts/right-ui-i18n-nl.js → public/javascripts/right/i18n/nl.js} +7 -7
  37. data/{javascripts/right-ui-i18n-pt-br.js → public/javascripts/right/i18n/pt-br.js} +7 -7
  38. data/{javascripts/right-ui-i18n-ru.js → public/javascripts/right/i18n/ru.js} +7 -7
  39. data/{javascripts/right-ui-i18n-ua.js → public/javascripts/right/i18n/ua.js} +17 -12
  40. data/public/javascripts/right/in-edit-src.js +352 -0
  41. data/public/javascripts/right/in-edit.js +13 -0
  42. data/public/javascripts/right/json-src.js +160 -0
  43. data/public/javascripts/right/json.js +10 -0
  44. data/public/javascripts/right/lightbox-src.js +881 -0
  45. data/public/javascripts/right/lightbox.js +24 -0
  46. data/{javascripts/right-rails-src.js → public/javascripts/right/rails-src.js} +195 -171
  47. data/public/javascripts/right/rails.js +14 -0
  48. data/public/javascripts/right/rater-src.js +366 -0
  49. data/public/javascripts/right/rater.js +13 -0
  50. data/public/javascripts/right/resizable-src.js +420 -0
  51. data/public/javascripts/right/resizable.js +15 -0
  52. data/public/javascripts/right/selectable-src.js +687 -0
  53. data/public/javascripts/right/selectable.js +22 -0
  54. data/public/javascripts/right/slider-src.js +377 -0
  55. data/public/javascripts/right/slider.js +14 -0
  56. data/public/javascripts/right/sortable-src.js +392 -0
  57. data/public/javascripts/right/sortable.js +16 -0
  58. data/public/javascripts/right/tabs-src.js +1123 -0
  59. data/public/javascripts/right/tabs.js +29 -0
  60. data/public/javascripts/right/tooltip-src.js +307 -0
  61. data/public/javascripts/right/tooltip.js +12 -0
  62. data/public/javascripts/right/uploader-src.js +283 -0
  63. data/public/javascripts/right/uploader.js +13 -0
  64. data/{javascripts → public/javascripts}/right-olds-src.js +134 -186
  65. data/public/javascripts/right-olds.js +18 -0
  66. data/public/javascripts/right-safe-src.js +161 -0
  67. data/public/javascripts/right-safe.js +8 -0
  68. data/{javascripts → public/javascripts}/right-src.js +2558 -1750
  69. data/public/javascripts/right.js +92 -0
  70. data/spec/lib/right_rails/config_spec.rb +133 -0
  71. data/spec/lib/right_rails/controller_extensions_spec.rb +1 -1
  72. data/spec/lib/right_rails/helpers/basic_spec.rb +77 -66
  73. data/spec/lib/right_rails/helpers/forms_spec.rb +231 -33
  74. data/spec/lib/right_rails/helpers/misc_spec.rb +94 -26
  75. data/spec/lib/right_rails/helpers/rails_spec.rb +42 -7
  76. data/spec/lib/right_rails/helpers_spec.rb +125 -0
  77. data/spec/lib/right_rails/java_script_generator_spec.rb +30 -0
  78. data/spec/rcov.opts +3 -0
  79. data/spec/spec_helper.rb +12 -7
  80. metadata +70 -61
  81. data/README.textile +0 -69
  82. data/javascripts/right-autocompleter-src.js +0 -318
  83. data/javascripts/right-autocompleter.js +0 -9
  84. data/javascripts/right-behavior-src.js +0 -261
  85. data/javascripts/right-behavior.js +0 -8
  86. data/javascripts/right-calendar-src.js +0 -946
  87. data/javascripts/right-calendar.js +0 -9
  88. data/javascripts/right-colorpicker-src.js +0 -635
  89. data/javascripts/right-colorpicker.js +0 -9
  90. data/javascripts/right-dnd.js +0 -9
  91. data/javascripts/right-effects.js +0 -6
  92. data/javascripts/right-events-src.js +0 -321
  93. data/javascripts/right-events.js +0 -6
  94. data/javascripts/right-in-edit-src.js +0 -194
  95. data/javascripts/right-in-edit.js +0 -6
  96. data/javascripts/right-json-src.js +0 -141
  97. data/javascripts/right-json.js +0 -6
  98. data/javascripts/right-lightbox-src.js +0 -651
  99. data/javascripts/right-lightbox.js +0 -9
  100. data/javascripts/right-olds.js +0 -9
  101. data/javascripts/right-rails.js +0 -9
  102. data/javascripts/right-rater-src.js +0 -253
  103. data/javascripts/right-rater.js +0 -9
  104. data/javascripts/right-resizable-src.js +0 -336
  105. data/javascripts/right-resizable.js +0 -9
  106. data/javascripts/right-selectable-src.js +0 -565
  107. data/javascripts/right-selectable.js +0 -7
  108. data/javascripts/right-slider-src.js +0 -288
  109. data/javascripts/right-slider.js +0 -7
  110. data/javascripts/right-sortable-src.js +0 -225
  111. data/javascripts/right-sortable.js +0 -9
  112. data/javascripts/right-tabs-src.js +0 -937
  113. data/javascripts/right-tabs.js +0 -6
  114. data/javascripts/right-tooltips-src.js +0 -195
  115. data/javascripts/right-tooltips.js +0 -9
  116. data/javascripts/right-uploader-src.js +0 -167
  117. data/javascripts/right-uploader.js +0 -9
  118. data/javascripts/right.js +0 -7
@@ -0,0 +1,1123 @@
1
+ /**
2
+ * Tabs widget for RightJS (http://rightjs.org/ui/tabs)
3
+ *
4
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
5
+ */
6
+ var Tabs = RightJS.Tabs = (function(document, parseInt, RightJS) {
7
+ /**
8
+ * This module defines the basic widgets constructor
9
+ * it creates an abstract proxy with the common functionality
10
+ * which then we reuse and override in the actual widgets
11
+ *
12
+ * Copyright (C) 2010 Nikolay Nemshilov
13
+ */
14
+
15
+ /**
16
+ * The tabs init-script
17
+ *
18
+ * Copyright (C) 2010 Nikolay Nemshilov
19
+ */
20
+ var R = RightJS,
21
+ $ = RightJS.$,
22
+ $$ = RightJS.$$,
23
+ $w = RightJS.$w,
24
+ $E = RightJS.$E,
25
+ Fx = RightJS.Fx,
26
+ Object = RightJS.Object,
27
+ Browser = RightJS.Browser,
28
+ isArray = RightJS.isArray,
29
+ isNumber = RightJS.isNumber,
30
+ Wrapper = RightJS.Wrapper,
31
+ Element = RightJS.Element,
32
+ Cookie = RightJS.Cookie;
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+ /**
41
+ * The widget units constructor
42
+ *
43
+ * @param String tag-name or Object methods
44
+ * @param Object methods
45
+ * @return Widget wrapper
46
+ */
47
+ function Widget(tag_name, methods) {
48
+ if (!methods) {
49
+ methods = tag_name;
50
+ tag_name = 'DIV';
51
+ }
52
+
53
+ /**
54
+ * An Abstract Widget Unit
55
+ *
56
+ * Copyright (C) 2010 Nikolay Nemshilov
57
+ */
58
+ var AbstractWidget = new RightJS.Wrapper(RightJS.Element.Wrappers[tag_name] || RightJS.Element, {
59
+ /**
60
+ * The common constructor
61
+ *
62
+ * @param Object options
63
+ * @param String optional tag name
64
+ * @return void
65
+ */
66
+ initialize: function(key, options) {
67
+ this.key = key;
68
+ var args = [{'class': 'rui-' + key}];
69
+
70
+ // those two have different constructors
71
+ if (!(this instanceof RightJS.Input || this instanceof RightJS.Form)) {
72
+ args.unshift(tag_name);
73
+ }
74
+ this.$super.apply(this, args);
75
+
76
+ if (RightJS.isString(options)) {
77
+ options = RightJS.$(options);
78
+ }
79
+
80
+ // if the options is another element then
81
+ // try to dynamically rewrap it with our widget
82
+ if (options instanceof RightJS.Element) {
83
+ this._ = options._;
84
+ if ('$listeners' in options) {
85
+ options.$listeners = options.$listeners;
86
+ }
87
+ options = {};
88
+ }
89
+ this.setOptions(options, this);
90
+ return this;
91
+ },
92
+
93
+ // protected
94
+
95
+ /**
96
+ * Catches the options
97
+ *
98
+ * @param Object user-options
99
+ * @param Element element with contextual options
100
+ * @return void
101
+ */
102
+ setOptions: function(options, element) {
103
+ element = element || this;
104
+ RightJS.Options.setOptions.call(this,
105
+ RightJS.Object.merge(options, eval("("+(
106
+ element.get('data-'+ this.key) || '{}'
107
+ )+")"))
108
+ );
109
+ return this;
110
+ }
111
+ });
112
+
113
+ /**
114
+ * Creating the actual widget class
115
+ *
116
+ */
117
+ var Klass = new RightJS.Wrapper(AbstractWidget, methods);
118
+
119
+ // creating the widget related shortcuts
120
+ RightJS.Observer.createShortcuts(Klass.prototype, Klass.EVENTS || []);
121
+
122
+ return Klass;
123
+ }
124
+
125
+
126
+ /**
127
+ * A shared module to create textual spinners
128
+ *
129
+ * Copyright (C) 2010 Nikolay Nemshilov
130
+ */
131
+ var Spinner = new RightJS.Wrapper(RightJS.Element, {
132
+ /**
133
+ * Constructor
134
+ *
135
+ * @param Number optional spinner size (4 by default)
136
+ * @return void
137
+ */
138
+ initialize: function(size) {
139
+ this.$super('div', {'class': 'rui-spinner'});
140
+ this.dots = [];
141
+
142
+ for (var i=0; i < (size || 4); i++) {
143
+ this.dots.push(new RightJS.Element('div'));
144
+ }
145
+
146
+ this.dots[0].addClass('glowing');
147
+ this.insert(this.dots);
148
+ RightJS(this.shift).bind(this).periodical(300);
149
+ },
150
+
151
+ /**
152
+ * Shifts the spinner elements
153
+ *
154
+ * @return void
155
+ */
156
+ shift: function() {
157
+ if (this.visible()) {
158
+ var dot = this.dots.pop();
159
+ this.dots.unshift(dot);
160
+ this.insert(dot, 'top');
161
+ }
162
+ }
163
+ });
164
+
165
+ /**
166
+ * The basic tabs handling engine
167
+ *
168
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
169
+ */
170
+ var Tabs = new Widget('UL', {
171
+ extend: {
172
+ version: '2.0.0',
173
+
174
+ EVENTS: $w('select hide load disable enable add remove move'),
175
+
176
+ Options: {
177
+ idPrefix: '', // the tab-body elements id prefix
178
+ tabsElement: null, // the tabs list element reference, in case it's situated somewhere else
179
+
180
+ resizeFx: 'both', // 'slide', 'fade', 'both' or null for no fx
181
+ resizeDuration: 400, // the tab panels resize fx duration
182
+
183
+ scrollTabs: false, // use the tabs list scrolling
184
+ scrollDuration: 400, // the tabs scrolling fx duration
185
+
186
+ selected: null, // the index of the currently opened tab, by default will check url, cookies or set 0
187
+ disabled: null, // list of disabled tab indexes
188
+
189
+ closable: false, // set true if you want a close icon on your tabs
190
+
191
+ loop: false, // put a delay in ms to make it autostart the slideshow loop
192
+ loopPause: true, // make the loop get paused when user hovers the tabs with mouse
193
+
194
+ url: false, // a common remote tabs url template, should have the %{id} placeholder
195
+ cache: false, // marker if the remote tabs should be cached
196
+
197
+ Xhr: null, // the xhr addtional options
198
+ Cookie: null // set the cookie options if you'd like to keep the last selected tab index in cookies
199
+ },
200
+
201
+ // scans and automatically intializes the tabs
202
+ rescan: function(scope) {
203
+ $(scope || document).find('.rui-tabs,*[data-tabs]').each(function(element) {
204
+ element = element instanceof Tabs ? element : new Tabs(element);
205
+ });
206
+ }
207
+ },
208
+
209
+ /**
210
+ * The basic constructor
211
+ *
212
+ * @param element or id
213
+ * @param Object options
214
+ */
215
+ initialize: function(element, options) {
216
+ this
217
+ .$super('tabs', element)
218
+ .setOptions(options)
219
+ .addClass('rui-tabs');
220
+
221
+ this.isHarmonica = this._.tagName === 'DL';
222
+ this.isCarousel = this.hasClass('rui-tabs-carousel');
223
+ this.isSimple = !this.isHarmonica && !this.isCarousel;
224
+
225
+ this
226
+ .findTabs()
227
+ .initScrolls()
228
+ .findCurrent()
229
+ .setStyle('visibility:visible');
230
+
231
+ if (this.options.disabled) {
232
+ this.disable(this.options.disabled);
233
+ }
234
+
235
+ if (this.options.loop) {
236
+ this.startLoop();
237
+ }
238
+ },
239
+
240
+ /**
241
+ * Shows the given tab
242
+ *
243
+ * @param integer tab index or a Tabs.Tab instance
244
+ * @return Tabs this
245
+ */
246
+ select: function(tab) {
247
+ return this.callTab(tab, 'select');
248
+ },
249
+
250
+ /**
251
+ * Disables the given tab
252
+ *
253
+ * @param integer tab index or a Tabs.Tab instance or a list of them
254
+ * @return Tabs this
255
+ */
256
+ disable: function(tab) {
257
+ return this.callTab(tab, 'disable');
258
+ },
259
+
260
+ /**
261
+ * Enables the given tab
262
+ *
263
+ * @param integer tab index or a Tabs.Tab instance or a list of them
264
+ * @return Tabs this
265
+ */
266
+ enable: function(tab) {
267
+ return this.callTab(tab, 'enable');
268
+ },
269
+
270
+ /**
271
+ * Returns the reference to the currently opened tab
272
+ *
273
+ * @return Tab tab or undefined
274
+ */
275
+ current: function() {
276
+ return this.tabs.first('current');
277
+ },
278
+
279
+ /**
280
+ * Returns the list of enabled tabs
281
+ *
282
+ * @return Array of enabled tabs
283
+ */
284
+ enabled: function() {
285
+ return this.tabs.filter('enabled');
286
+ },
287
+
288
+ // protected
289
+
290
+ // calls the tab (or tabs) method
291
+ callTab: function(tabs, method) {
292
+ R(isArray(tabs) ? tabs : [tabs]).each(function(tab) {
293
+ if (isNumber(tab)) { tab = this.tabs[tab]; }
294
+ if (tab && tab instanceof Tab) {
295
+ tab[method]();
296
+ }
297
+ }, this);
298
+
299
+ return this;
300
+ },
301
+
302
+ // finds and interconnects the tabs
303
+ findTabs: function() {
304
+ this.tabsList = this.isHarmonica ? this :
305
+ $(this.options.tabsElement) || this.first('.rui-tabs-list') ||
306
+ (this.first('UL') || $E('UL').insertTo(this)).addClass('rui-tabs-list');
307
+
308
+ this.tabs = R([]);
309
+
310
+ this.tabsList.children(this.isHarmonica ? 'dt' : null).map(function(node) {
311
+ this.tabs.push(new Tab(node, this));
312
+ }, this);
313
+
314
+ // removing the whitespaces so the didn't screw with the margins
315
+ for (var i=0, list = this.tabsList.get('childNodes'); i < list.length; i++) {
316
+ if (list[i].nodeType == 3) { this.tabsList._.removeChild(list[i]); }
317
+ }
318
+
319
+ return this;
320
+ }
321
+ });
322
+
323
+ /**
324
+ * A single tab handling object
325
+ *
326
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
327
+ */
328
+ var Tab = Tabs.Tab = new Wrapper(Element, {
329
+ extend: {
330
+ autoId: 0
331
+ },
332
+
333
+ /**
334
+ * Constructor
335
+ *
336
+ * @param Element the tab's element
337
+ * @param Tabs the main element
338
+ * @return void
339
+ */
340
+ initialize: function(element, main) {
341
+ this.$super(element._);
342
+ this.addClass('rui-tabs-tab');
343
+
344
+ this.main = main;
345
+ this.link = this.first('a');
346
+ this.id = this.link.get('href').split('#')[1] || Tab.autoId++;
347
+ this.panel = new Panel(this.findPanel(), this);
348
+
349
+ if (this.current()) {
350
+ this.select();
351
+ }
352
+
353
+ // adding the 'close' icon onto the tab if needed
354
+ if (main.options.closable) {
355
+ this.link.insert($E('div', {
356
+ 'class': 'rui-tabs-tab-close-icon', 'html': '&times;'
357
+ }).onClick(R(this.remove).bind(this)));
358
+ }
359
+
360
+ this.onClick(this._clicked);
361
+ },
362
+
363
+ select: function() {
364
+ if (this.enabled()) {
365
+ var prev_tab = this.main.current();
366
+ if (prev_tab) {
367
+ prev_tab.removeClass('rui-tabs-current').fire('hide');
368
+ }
369
+
370
+ this.addClass('rui-tabs-current');
371
+ this.main.scrollToTab(this);
372
+ this.panel.show();
373
+ }
374
+
375
+ return this.fire('select');
376
+ },
377
+
378
+ disable: function() {
379
+ return this.addClass('rui-tabs-disabled').fire('disable');
380
+ },
381
+
382
+ enable: function() {
383
+ return this.removeClass('rui-tabs-disabled').fire('enable');
384
+ },
385
+
386
+ disabled: function() {
387
+ return !this.enabled();
388
+ },
389
+
390
+ enabled: function() {
391
+ return !this.hasClass('rui-tabs-disabled');
392
+ },
393
+
394
+ current: function() {
395
+ return this.hasClass('rui-tabs-current');
396
+ },
397
+
398
+ remove: function(event) {
399
+ if (event) { event.stop(); }
400
+
401
+ // switching to the next available sibling
402
+ if (this.current()) {
403
+ var enabled = this.main.enabled();
404
+ var sibling = enabled[enabled.indexOf(this) + 1] || enabled[enabled.indexOf(this)-1];
405
+
406
+ if (sibling) {
407
+ sibling.select();
408
+ }
409
+ }
410
+
411
+ // removing the tab out of the list
412
+ this.main.tabs.splice(this.main.tabs.indexOf(this), 1);
413
+ this.panel.remove();
414
+
415
+ return this.$super().fire('remove');
416
+ },
417
+
418
+ // protected
419
+
420
+ // handles the clicks on the tabs
421
+ _clicked: function(event) {
422
+ event.stop();
423
+ return this.select();
424
+ },
425
+
426
+ // searches for a panel for the tab
427
+ findPanel: function() {
428
+ var main = this.main, panel_id = main.options.idPrefix + this.id, panel;
429
+
430
+ if (main.isHarmonica) {
431
+ var next = this.next();
432
+ panel = (next && next._.tagName === 'DD') ? next : $E('DD').insertTo(this, 'after');
433
+ } else {
434
+ panel = $(panel_id) || $E(main._.tagName === 'UL' ? 'LI' : 'DIV').insertTo(main);
435
+ }
436
+
437
+ return panel.set('id', panel_id);
438
+ },
439
+
440
+ // returns the tab width, used for the scrolling calculations
441
+ width: function() {
442
+ var next = this.next();
443
+
444
+ if (next) {
445
+ return next.position().x - this.position().x;
446
+ } else {
447
+ return this.size().x + 1;
448
+ }
449
+ }
450
+
451
+ });
452
+
453
+ /**
454
+ * The tab panels behavior logic
455
+ *
456
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
457
+ */
458
+ var Panel = Tabs.Panel = new Wrapper(Element, {
459
+
460
+ /**
461
+ * Basic constructor
462
+ *
463
+ * @param Element panel-element
464
+ * @param Tab the tab object
465
+ * @return void
466
+ */
467
+ initialize: function(element, tab) {
468
+ this.$super(element._);
469
+ this.addClass('rui-tabs-panel');
470
+
471
+ this.tab = tab;
472
+ this.id = this.get('id');
473
+ },
474
+
475
+ // shows the panel
476
+ show: function() {
477
+ return this.resizing(function() {
478
+ this.tab.main.find('.rui-tabs-panel').each(function(panel) {
479
+ panel[panel === this ? 'addClass' : 'removeClass']('rui-tabs-current');
480
+ }, this);
481
+ });
482
+ },
483
+
484
+ // updates the panel content
485
+ update: function(content) {
486
+ // don't use resize if it's some other hidden tab was loaded asynch
487
+ if (this.tab.current()) {
488
+ this.resizing(function() {
489
+ Element.prototype.update.call(this, content||'');
490
+ });
491
+ } else {
492
+ this.$super(content||'');
493
+ }
494
+
495
+ return this;
496
+ },
497
+
498
+ // locks the panel with a spinner locker
499
+ lock: function() {
500
+ this.insert(this.locker(), 'top');
501
+ },
502
+
503
+ // protected
504
+
505
+ resizing: function(callback) {
506
+ var controller = this.tab.main;
507
+
508
+ if (controller.__working) { return this.resizing.bind(this, callback).delay(100); }
509
+
510
+ var options = controller.options;
511
+ var prev_panel = controller.first('.rui-tabs-panel.rui-tabs-current');
512
+ var this_panel = this;
513
+ var swapping = prev_panel !== this_panel;
514
+ var loading = this.first('div.rui-tabs-panel-locker');
515
+
516
+ // sometimes it looses the parent on remote tabs
517
+ if (this_panel.parent().hasClass('rui-tabs-resizer')) {
518
+ this_panel.insertTo(prev_panel.parent());
519
+ }
520
+
521
+ if (options.resizeFx && RightJS.Fx && prev_panel && (swapping || loading)) {
522
+ controller.__working = true;
523
+ var unlock = function() { controller.__working = false; };
524
+
525
+ // calculating the visual effects durations
526
+ var fx_name = (options.resizeFx === 'both' && loading) ? 'slide' : options.resizeFx;
527
+ var duration = options.resizeDuration; duration = Fx.Durations[duration] || duration;
528
+ var resize_duration = fx_name === 'fade' ? 0 : fx_name === 'slide' ? duration : duration / 2;
529
+ var fade_duration = duration - resize_duration;
530
+
531
+ if (fx_name !== 'slide') {
532
+ this_panel.setStyle({opacity: 0});
533
+ }
534
+
535
+ // saving the previous sizes
536
+ var prev_panel_height = (controller.isHarmonica && swapping) ? 0 : prev_panel.size().y;
537
+
538
+ // applying the changes
539
+ callback.call(this);
540
+
541
+ // getting the new size
542
+ var new_panel_height = this_panel.size().y;
543
+ var fx_wrapper = null;
544
+ var hide_wrapper = null;
545
+ var prev_back = null;
546
+
547
+ if (fx_name !== 'fade' && prev_panel_height !== new_panel_height) {
548
+ // preserving the whole element size so it didn't jump when we are tossing the tabs around
549
+ controller._.style.height = controller.size().y + 'px';
550
+
551
+ // wrapping the element with an overflowed element to visualize the resize
552
+ fx_wrapper = $E('div', {
553
+ 'class': 'rui-tabs-resizer',
554
+ 'style': 'height: '+ prev_panel_height + 'px'
555
+ });
556
+
557
+ // in case of harmonica nicely hidding the previous panel
558
+ if (controller.isHarmonica && swapping) {
559
+ prev_panel.addClass('rui-tabs-current');
560
+ hide_wrapper = $E('div', {'class': 'rui-tabs-resizer'});
561
+ hide_wrapper._.style.height = prev_panel.size().y + 'px';
562
+ prev_back = function() {
563
+ hide_wrapper.replace(prev_panel.removeClass('rui-tabs-current'));
564
+ };
565
+ prev_panel.wrap(hide_wrapper);
566
+
567
+ fx_wrapper._.style.height = '0px';
568
+ }
569
+
570
+ this_panel.wrap(fx_wrapper);
571
+
572
+ // getting back the auto-size so we could resize it
573
+ controller._.style.height = 'auto';
574
+
575
+ } else {
576
+ // removing the resize duration out of the equasion
577
+ rezise_duration = 0;
578
+ duration = fade_duration;
579
+ }
580
+
581
+ var counter = 0;
582
+ var set_back = function() {
583
+ if (fx_wrapper) {
584
+ if (fx_name == 'both' && !counter) {
585
+ return counter ++;
586
+ }
587
+
588
+ fx_wrapper.replace(this_panel);
589
+ }
590
+
591
+ unlock();
592
+ };
593
+
594
+ if (hide_wrapper) {
595
+ hide_wrapper.morph({height: '0px'},
596
+ {duration: resize_duration, onFinish: prev_back});
597
+ }
598
+
599
+ if (fx_wrapper) {
600
+ fx_wrapper.morph({height: new_panel_height + 'px'},
601
+ {duration: resize_duration, onFinish: set_back});
602
+ }
603
+
604
+ if (fx_name !== 'slide') {
605
+ this_panel.morph.bind(this_panel, {opacity: 1},
606
+ {duration: fade_duration, onFinish: set_back}
607
+ ).delay(resize_duration);
608
+ }
609
+
610
+ if (!fx_wrapper && fx_name === 'slide') {
611
+ set_back();
612
+ }
613
+
614
+ } else {
615
+ callback.call(this);
616
+ }
617
+
618
+ return this;
619
+ },
620
+
621
+ // builds the locker element
622
+ locker: function() {
623
+ return this._locker || (this._locker =
624
+ $E('div', {'class': 'rui-tabs-panel-locker'}).insert(new Spinner(5))
625
+ );
626
+ }
627
+ });
628
+
629
+ /**
630
+ * Contains the tabs scrolling functionality
631
+ *
632
+ * NOTE: different types of tabs have different scrolling behavior
633
+ * simple tabs just scroll the tabs line without actually picking
634
+ * any tab. But the carousel tabs scrolls to the next/previous
635
+ * tabs on the list.
636
+ *
637
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
638
+ */
639
+ Tabs.include({
640
+ /**
641
+ * Shows the next tab
642
+ *
643
+ * @return Tabs this
644
+ */
645
+ next: function() {
646
+ return this.pickTab(+1);
647
+ },
648
+
649
+ /**
650
+ * Shows the preveious tab
651
+ *
652
+ * @return Tabs this
653
+ */
654
+ prev: function() {
655
+ return this.pickTab(-1);
656
+ },
657
+
658
+ /**
659
+ * Scrolls the tabs to the left
660
+ *
661
+ * @return Tabs this
662
+ */
663
+ scrollLeft: function() {
664
+ if (!this.prevButton.hasClass('rui-tabs-scroller-disabled')) {
665
+ this[this.isCarousel ? 'prev' : 'justScroll'](+0.6);
666
+ }
667
+ return this;
668
+ },
669
+
670
+ /**
671
+ * Scrolls the tabs to the right
672
+ *
673
+ * @return Tabs this
674
+ */
675
+ scrollRight: function() {
676
+ if (!this.nextButton.hasClass('rui-tabs-scroller-disabled')) {
677
+ this[this.isCarousel ? 'next' : 'justScroll'](-0.6);
678
+ }
679
+ return this;
680
+ },
681
+
682
+ // protected
683
+
684
+ // overloading the init script to add the scrollbar support
685
+ initScrolls: function() {
686
+ if ((this.scrollable = (this.options.scrollTabs || this.isCarousel))) {
687
+ this.buildScroller();
688
+ }
689
+
690
+ return this;
691
+ },
692
+
693
+ // builds the tabs scroller block
694
+ buildScroller: function() {
695
+ if (!(
696
+ (this.prevButton = this.first('.rui-tabs-scroller-prev')) &&
697
+ (this.nextButton = this.first('.rui-tabs-scroller-next'))
698
+ )) {
699
+ this.prevButton = $E('div', {'class': 'rui-tabs-scroller-prev', 'html': '&laquo;'});
700
+ this.nextButton = $E('div', {'class': 'rui-tabs-scroller-next', 'html': '&raquo;'});
701
+
702
+ // using a dummy element to insert the scroller in place of the tabs list
703
+ $E('div').insertTo(this.tabsList, 'before')
704
+ .replace(
705
+ $E('div', {'class': 'rui-tabs-scroller'}).insert([
706
+ this.prevButton, this.nextButton, this.scroller = $E('div', {
707
+ 'class': 'rui-tabs-scroller-body'
708
+ }).insert(this.tabsList)
709
+ ])
710
+ ).remove();
711
+ }
712
+
713
+ this.prevButton.onClick(R(this.scrollLeft).bind(this));
714
+ this.nextButton.onClick(R(this.scrollRight).bind(this));
715
+ },
716
+
717
+ // picks the next/prev non-disabled available tab
718
+ pickTab: function(pos) {
719
+ var current = this.current();
720
+ if (current && current.enabled()) {
721
+ var enabled_tabs = this.enabled();
722
+ var tab = enabled_tabs[enabled_tabs.indexOf(current) + pos];
723
+ if (tab) { tab.select(); }
724
+ }
725
+ },
726
+
727
+ // scrolls the tabs line to make the tab visible
728
+ scrollToTab: function(tab) {
729
+ if (this.scroller) {
730
+ // calculating the previous tabs widths
731
+ var tabs_width = 0;
732
+ for (var i=0; i < this.tabs.length; i++) {
733
+ tabs_width += this.tabs[i].width();
734
+ if (this.tabs[i] === tab) { break; }
735
+ }
736
+
737
+ // calculating the scroll (the carousel tabs should be centralized)
738
+ var available_width = this.scroller.size().x;
739
+ var scroll = (this.isCarousel ? (available_width/2 + tab.width()/2) : available_width) - tabs_width;
740
+
741
+ // check if the tab doesn't need to be scrolled
742
+ if (!this.isCarousel) {
743
+ var current_scroll = parseInt(this.tabsList.getStyle('left') || 0, 10);
744
+
745
+ if (scroll >= current_scroll && scroll < (current_scroll + available_width - tab.width())) {
746
+ scroll = current_scroll;
747
+ } else if (current_scroll > -tabs_width && current_scroll <= (tab.width() - tabs_width)) {
748
+ scroll = tab.width() - tabs_width;
749
+ }
750
+ }
751
+
752
+ this.scrollTo(scroll);
753
+ }
754
+ },
755
+
756
+ // just scrolls the scrollable area onto the given number of scrollable area widths
757
+ justScroll: function(size) {
758
+ if (!this.scroller) { return this; }
759
+ var current_scroll = parseInt(this.tabsList.getStyle('left') || 0, 10);
760
+ var available_width = this.scroller.size().x;
761
+
762
+ this.scrollTo(current_scroll + available_width * size);
763
+ },
764
+
765
+ // scrolls the tabs list to the position
766
+ scrollTo: function(scroll) {
767
+ // checking the constraints
768
+ var available_width = this.scroller.size().x;
769
+ var overall_width = this.tabs.map('width').sum();
770
+
771
+ if (scroll < (available_width - overall_width)) {
772
+ scroll = available_width - overall_width;
773
+ }
774
+ if (scroll > 0) { scroll = 0; }
775
+
776
+ // applying the scroll
777
+ this.tabsList.morph({left: scroll+'px'}, {duration: this.options.scrollDuration});
778
+
779
+ this.checkScrollButtons(overall_width, available_width, scroll);
780
+ },
781
+
782
+ // checks the scroll buttons
783
+ checkScrollButtons: function(overall_width, available_width, scroll) {
784
+ var has_prev = false, has_next = false;
785
+
786
+ if (this.isCarousel) {
787
+ var enabled = this.enabled();
788
+ var current = enabled.first('current');
789
+
790
+ if (current) {
791
+ var index = enabled.indexOf(current);
792
+
793
+ has_prev = index > 0;
794
+ has_next = index < enabled.length - 1;
795
+ }
796
+ } else {
797
+ has_prev = scroll !== 0;
798
+ has_next = scroll > (available_width - overall_width);
799
+ }
800
+
801
+ this.prevButton[has_prev ? 'removeClass' : 'addClass']('rui-tabs-scroller-disabled');
802
+ this.nextButton[has_next ? 'removeClass' : 'addClass']('rui-tabs-scroller-disabled');
803
+ }
804
+
805
+ });
806
+
807
+ /**
808
+ * This module handles the current tab state saving/restoring processes
809
+ *
810
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
811
+ */
812
+ function get_cookie_indexes() {
813
+ return R(RightJS.Cookie ? (Cookie.get('right-tabs-indexes') || '').split(',') : []);
814
+ }
815
+
816
+ function save_tab_in_cookies(options, tabs, event) {
817
+ if (RightJS.Cookie) {
818
+ var indexes = get_cookie_indexes();
819
+ indexes = indexes.without.apply(indexes, tabs.map('id'));
820
+ indexes.push(event.target.id);
821
+ Cookie.set('right-tabs-indexes', indexes.uniq().join(','), options);
822
+ }
823
+ }
824
+
825
+ Tabs.include({
826
+
827
+ // protected
828
+
829
+ // searches and activates the current tab
830
+ findCurrent: function() {
831
+ var current;
832
+ if (this.options.selected !== null) {
833
+ current = this.options.selected;
834
+ } else {
835
+ var enabled = this.enabled();
836
+ current = enabled[this.urlIndex()] || enabled[this.cookieIndex()] || enabled.first('current') || enabled[0];
837
+ }
838
+
839
+ if (current) {
840
+ current.select();
841
+ }
842
+
843
+ // initializing the cookies storage if set
844
+ if (this.options.Cookie) {
845
+ this.onSelect(R(save_tab_in_cookies).curry(this.options.Cookie, this.tabs));
846
+ }
847
+
848
+ return this;
849
+ },
850
+
851
+ // tries to find the current tab index in the url hash
852
+ urlIndex: function() {
853
+ var index = -1, id = document.location.href.split('#')[1];
854
+
855
+ if (id) {
856
+ for (var i=0; i < this.tabs.length; i++) {
857
+ if (this.tabs[i].id == id) {
858
+ index = i;
859
+ break;
860
+ }
861
+ }
862
+ }
863
+
864
+ return index;
865
+ },
866
+
867
+ // tries to find the current tab index in the cookies storage
868
+ cookieIndex: function() {
869
+ var index = -1;
870
+
871
+ if (this.options.Cookie) {
872
+ var indexes = get_cookie_indexes();
873
+ for (var i=0; i < this.tabs.length; i++) {
874
+ if (indexes.include(this.tabs[i].id)) {
875
+ index = i;
876
+ break;
877
+ }
878
+ }
879
+ }
880
+
881
+ return index;
882
+ }
883
+
884
+ });
885
+
886
+ /**
887
+ * This module handles the tabs cration and removing processes
888
+ *
889
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
890
+ */
891
+ Tabs.include({
892
+ /**
893
+ * Creates a new tab
894
+ *
895
+ * USAGE:
896
+ * With the #add method you have to specify the tab title
897
+ * optional content (possibly empty or null) and some options
898
+ * The options might have the following keys
899
+ *
900
+ * * id - the tab/panel id (will use the idPrefix option for the panels)
901
+ * * url - a remote tab content address
902
+ * * position - an integer position of the tab in the stack
903
+ *
904
+ * @param String title
905
+ * @param mixed content
906
+ * @param Object options
907
+ * @return Tabs this
908
+ */
909
+ add: function(title, content, options) {
910
+ options = options || {};
911
+
912
+ // creating the new tab element
913
+ var element = $E(this.isHarmonica ? 'dt' : 'li').insert(
914
+ $E('a', {html: title, href: options.url || '#'+(options.id||'')}
915
+ )).insertTo(this.tabsList);
916
+
917
+ // creating the actual tab instance
918
+ var tab = new Tab(element, this);
919
+ tab.panel.update(content||'');
920
+ this.tabs.push(tab);
921
+ tab.fire('add');
922
+
923
+ // moving the tab in place if asked
924
+ if ('position' in options) {
925
+ this.move(tab, options.position);
926
+ }
927
+
928
+ return this;
929
+ },
930
+
931
+ /**
932
+ * Moves the given tab to the given position
933
+ *
934
+ * NOTE if the position is not within the tabs range then it will do nothing
935
+ *
936
+ * @param mixed tab index or a tab instance
937
+ * @param Integer position
938
+ * @return Tabs this
939
+ */
940
+ move: function(tab, position) {
941
+ tab = this.tabs[tab] || tab;
942
+
943
+ if (this.tabs[position] && this.tabs[position] !== tab) {
944
+ // moving the tab element
945
+ this.tabs[position].insert(tab, (position === this.tabs.length-1) ? 'after' : 'before');
946
+
947
+ // inserting the panel after the tab if it's a harmonica
948
+ if (this.isHarmonica) {
949
+ tab.insert(tab.panel, 'after');
950
+ }
951
+
952
+ // moving the tab in the registry
953
+ this.tabs.splice(this.tabs.indexOf(tab), 1);
954
+ this.tabs.splice(position, 0, tab);
955
+
956
+ tab.fire('move', {index: position});
957
+ }
958
+
959
+ return this;
960
+ },
961
+
962
+ /**
963
+ * Removes the given tab
964
+ *
965
+ * @param integer tab index or a Tabs.Tab instance or a list of them
966
+ * @return Tabs this
967
+ */
968
+ remove: function(tab) {
969
+ return this.callTab(tab, 'remove');
970
+ }
971
+
972
+ });
973
+
974
+ /**
975
+ * This module contains the remote tabs loading logic
976
+ *
977
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
978
+ */
979
+ var old_select = Tab.prototype.select;
980
+
981
+ Tab.include({
982
+
983
+ // wrapping the original mehtod, to catch the remote requests
984
+ select: function() {
985
+ if (this.dogPiling(arguments)) { return this; }
986
+
987
+ var result = old_select.apply(this, arguments);
988
+ var url = R(this.link.get('href'));
989
+ var options = this.main.options;
990
+
991
+ // building the url
992
+ if (url.includes('#')) {
993
+ url = options.url ? options.url.replace('%{id}', url.split('#')[1]) : null;
994
+ }
995
+
996
+ // if there is an actual url and no ongoing request or a cache, starting the request
997
+ if (url && !this.request && !(options.cache || this.cache)) {
998
+ this.panel.lock();
999
+
1000
+ try { // basically that's for the development tests, so the IE browsers didn't get screwed on the test page
1001
+
1002
+ this.request = new RightJS.Xhr(url, Object.merge({method: 'get'}, options.Xhr))
1003
+ .onComplete(R(function(response) {
1004
+ if (this.main.__working) {
1005
+ return arguments.callee.bind(this, response).delay(100);
1006
+ }
1007
+
1008
+ this.panel.update(response.text);
1009
+
1010
+ this.request = null; // removing the request marker so it could be rerun
1011
+ if (options.cache) {
1012
+ this.cache = true;
1013
+ }
1014
+
1015
+ this.fire('load');
1016
+ }).bind(this)
1017
+ ).send();
1018
+
1019
+ } catch(e) { if (!Browser.OLD) { throw(e); } }
1020
+ }
1021
+
1022
+ return result;
1023
+ },
1024
+
1025
+ // protected
1026
+
1027
+ dogPiling: function(args) {
1028
+ if (this.main.__working) {
1029
+ if (this.main.__timeout) {
1030
+ this.main.__timeout.cancel();
1031
+ }
1032
+
1033
+ this.main.__timeout = R(function(args) {
1034
+ this.select.apply(this, args);
1035
+ }).bind(this, args).delay(100);
1036
+
1037
+ return true;
1038
+ }
1039
+
1040
+ return (this.main.__timeout = null);
1041
+ }
1042
+
1043
+ });
1044
+
1045
+ /**
1046
+ * This module handles the slide-show loop feature for the Tabs
1047
+ *
1048
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
1049
+ */
1050
+ Tabs.include({
1051
+
1052
+ /**
1053
+ * Starts the slideshow loop
1054
+ *
1055
+ * @param Number optional delay in ms
1056
+ * @return Tabs this
1057
+ */
1058
+ startLoop: function(delay) {
1059
+ if (!delay && !this.options.loop) { return this; }
1060
+
1061
+ // attaching the loop pause feature
1062
+ if (this.options.loopPause) {
1063
+ this._stopLoop = this._stopLoop || R(this.stopLoop).bind(this, true);
1064
+ this._startLoop = this._startLoop || R(this.startLoop).bind(this, delay);
1065
+
1066
+ this.forgetHovers().on({
1067
+ mouseover: this._stopLoop,
1068
+ mouseout: this._startLoop
1069
+ });
1070
+ }
1071
+
1072
+ if (this.timer) { this.timer.stop(); }
1073
+
1074
+ this.timer = R(function() {
1075
+ var enabled = this.enabled();
1076
+ var current = this.current();
1077
+ var next = enabled[enabled.indexOf(current)+1];
1078
+
1079
+ this.select(next || enabled.first());
1080
+
1081
+ }).bind(this).periodical(this.options.loop || delay);
1082
+
1083
+ return this;
1084
+ },
1085
+
1086
+ /**
1087
+ * Stops the slideshow loop
1088
+ *
1089
+ * @return Tabs this
1090
+ */
1091
+ stopLoop: function(event, pause) {
1092
+ if (this.timer) {
1093
+ this.timer.stop();
1094
+ this.timer = null;
1095
+ }
1096
+ if (!pause && this._startLoop) {
1097
+ this.forgetHovers();
1098
+ }
1099
+ },
1100
+
1101
+ // private
1102
+ forgetHovers: function() {
1103
+ return this
1104
+ .stopObserving('mouseover', this._stopLoop)
1105
+ .stopObserving('mouseout', this._startLoop);
1106
+ }
1107
+
1108
+
1109
+ });
1110
+
1111
+ /**
1112
+ * The document level hooks for the tabs-egnine
1113
+ *
1114
+ * Copyright (C) 2009-2010 Nikolay Nemshilov
1115
+ */
1116
+ $(document).onReady(function() {
1117
+ Tabs.rescan();
1118
+ });
1119
+
1120
+ document.write("<style type=\"text/css\">div.rui-spinner,div.rui-spinner div{margin:0;padding:0;border:none;background:none;list-style:none;font-weight:normal;float:none;display:inline-block; *display:inline; *zoom:1;border-radius:.12em;-moz-border-radius:.12em;-webkit-border-radius:.12em}div.rui-spinner{text-align:center;white-space:nowrap;background:#EEE;border:1px solid #DDD;height:1.2em;padding:0 .2em}div.rui-spinner div{width:.4em;height:70%;background:#BBB;margin-left:1px}div.rui-spinner div:first-child{margin-left:0}div.rui-spinner div.glowing{background:#777}.rui-tabs,.rui-tabs-list,.rui-tabs-tab,.rui-tabs-panel,.rui-tabs-scroll-left,.rui-tabs-scroll-right,.rui-tabs-scroll-body,.rui-tabs-panel-locker,.rui-tabs-resizer{margin:0;padding:0;background:none;border:none;list-style:none;display:block;width:auto;height:auto}.rui-tabs{display:block;visibility:hidden;border-bottom:1px solid #CCC}.rui-tabs-resizer{overflow:hidden}.rui-tabs-list{display:block;position:relative;padding:0 .5em;border-bottom:1px solid #CCC;white-space:nowrap}.rui-tabs-list .rui-tabs-tab,.rui-tabs-tab *,.rui-tabs-tab *:hover{display:inline-block; *display:inline; *zoom:1;cursor:pointer;text-decoration:none;vertical-align:center}.rui-tabs-list .rui-tabs-tab{vertical-align:bottom;margin-right:.1em}.rui-tabs-tab a{outline:none;position:relative;border:1px solid #CCC;background:#DDD;color:#444;padding:.3em 1em;border-radius:.3em;-moz-border-radius:.3em;-webkit-border-radius:.3em;border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomleft:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0}.rui-tabs-tab a:hover{border-color:#CCC;background:#EEE}.rui-tabs-list .rui-tabs-current a,.rui-tabs-list .rui-tabs-current a:hover{font-weight:bold;color:#000;background:#FFF;border-bottom:1px solid #FFF;border-top-width:2px;padding-top:.34em;padding-bottom:.34em;top:1px}.rui-tabs-tab a img{border:none;opacity:.6;filter:alpha(opacity=60)}.rui-tabs-tab a:hover img,.rui-tabs-list .rui-tabs-current a img{opacity:1;filter:alpha(opacity=100)}.rui-tabs-disabled a,.rui-tabs-disabled a:hover{background:#EEE;border-color:#DDD;color:#AAA;cursor:default}.rui-tabs-disabled a img,.rui-tabs-disabled a:hover img{opacity:.5;filter:alpha(opacity=50)}.rui-tabs-tab-close-icon{display:inline-block; *display:inline; *zoom:1;margin-right:-0.5em;margin-left:0.5em;cursor:pointer;opacity:0.5;filter:alpha(opacity=50)}.rui-tabs-tab-close-icon:hover{opacity:1;filter:alpha(opacity=100);color:#B00;text-shadow:#888 .15em .15em .2em}.rui-tabs-panel{display:none;position:relative;min-height:4em;padding:.5em 0}.rui-tabs-current{display:block}.rui-tabs-scroller{position:relative;padding:0 1.4em}.rui-tabs-scroller-prev,.rui-tabs-scroller-next{width:1.1em;text-align:center;background:#EEE;color:#666;cursor:pointer;border:1px solid #CCC;border-radius:.2em;-moz-border-radius:.2em;-webkit-border-radius:.2em;position:absolute;bottom:0px;left:0px;padding:0.3em 0;user-select:none;-moz-user-select:none;-webkit-user-select:none}.rui-tabs-scroller-prev:hover,.rui-tabs-scroller-next:hover{color:#000;background:#DDD;border-color:#AAA}.rui-tabs-scroller-prev:active,.rui-tabs-scroller-next:active{background:#eee;border-color:#ccc}.rui-tabs-scroller-next{left:auto;right:0px}.rui-tabs-scroller-disabled,.rui-tabs-scroller-disabled:hover{cursor:default;background:#DDD;border-color:#DDD;color:#AAA}.rui-tabs-scroller-body{overflow:hidden;width:100%;position:relative}.rui-tabs-scroller .rui-tabs-list{padding-left:0;padding-right:0;width:9999em;z-index:10}.rui-tabs-panel-locker{position:absolute;top:0px;left:0px;opacity:0.5;filter:alpha(opacity=50);background:#CCC;width:100%;height:100%;text-align:center}.rui-tabs-panel-locker .rui-spinner{position:absolute;left:44%;top:44%;background:none;border:none;height:2em}.rui-tabs-panel-locker .rui-spinner div{background:#666;width:.65em;margin-left:.15em}.rui-tabs-panel-locker .rui-spinner div.glowing{background:#000}.rui-tabs-carousel .rui-tabs-list{border:none}.rui-tabs-carousel .rui-tabs-tab a,.rui-tabs-carousel .rui-tabs-scroller .rui-tabs-scroller-prev,.rui-tabs-carousel .rui-tabs-scroller .rui-tabs-scroller-next{height:6em;line-height:6em;padding:0;border-bottom:1px solid #ccc;border-radius:.25em;-moz-border-radius:.25em;-webkit-border-radius:.25em}.rui-tabs-carousel .rui-tabs-tab{margin-right:3px}.rui-tabs-carousel .rui-tabs-tab a img{border:1px solid #CCC;vertical-align:middle;margin:.4em;padding:0;border-radius:0;-moz-border-radius:0;-webkit-border-radius:0}.rui-tabs-carousel .rui-tabs-list .rui-tabs-current a{border-width:1px;border-color:#AAA;padding:0;top:auto}.rui-tabs-carousel .rui-tabs-list .rui-tabs-current a img{border-color:#bbb}.rui-tabs-carousel .rui-tabs-panel{text-align:center}dl.rui-tabs{border:none}dt.rui-tabs-tab,dt.rui-tabs-tab a,dt.rui-tabs-tab a:hover{display:block;float:none}dt.rui-tabs-tab a,dt.rui-tabs-tab a:hover{padding:.2em 1em;border:1px solid #ccc;border-radius:.25em;-moz-border-radius:.3em;-webkit-border-radius:.3em}dl.rui-tabs dt.rui-tabs-current a{background:#EEE;border-bottom-left-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomleft:0;-moz-border-radius-bottomright:0;-webkit-border-bottom-left-radius:0;-webkit-border-bottom-right-radius:0}dl.rui-tabs dd.rui-tabs-current+dt.rui-tabs-tab a{border-top-left-radius:0;border-top-right-radius:0;-moz-border-radius-topleft:0;-moz-border-radius-topright:0;-webkit-border-top-left-radius:0;-webkit-border-top-right-radius:0}</style>");
1121
+
1122
+ return Tabs;
1123
+ })(document, parseInt, RightJS);