bivouac 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/README +9 -0
  2. data/bin/bivouac +15 -19
  3. data/doc/rdoc/classes/BivouacHelpers.html +117 -0
  4. data/doc/rdoc/classes/BivouacHelpers/BaseView.html +140 -0
  5. data/doc/rdoc/classes/BivouacHelpers/FormView.html +398 -0
  6. data/doc/rdoc/classes/BivouacHelpers/HtmlView.html +274 -0
  7. data/doc/rdoc/classes/BivouacHelpers/JavaScriptView.html +573 -0
  8. data/doc/rdoc/classes/BivouacHelpers/ScriptAculoUsView.html +258 -0
  9. data/doc/rdoc/classes/BivouacHelpers/TooltipView.html +158 -0
  10. data/doc/rdoc/classes/JavaScriptGenerator.html +564 -0
  11. data/doc/rdoc/created.rid +1 -1
  12. data/doc/rdoc/files/AUTHORS.html +14 -0
  13. data/doc/rdoc/files/COPYING.html +14 -0
  14. data/doc/rdoc/files/README.html +40 -1
  15. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/base_rb.html +109 -0
  16. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/form_rb.html +109 -0
  17. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/html_rb.html +109 -0
  18. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/javascript_rb.html +113 -0
  19. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/scriptaculous_rb.html +113 -0
  20. data/doc/rdoc/files/lib/bivouac/helpers/view/goh/tooltip_rb.html +109 -0
  21. data/examples/bivouac_sample/app/bivouac_sample.rb +61 -0
  22. data/examples/bivouac_sample/app/controllers/autocomplete.rb +24 -0
  23. data/examples/bivouac_sample/app/controllers/drag_and_drop.rb +11 -0
  24. data/examples/bivouac_sample/app/controllers/index.rb +7 -0
  25. data/examples/bivouac_sample/app/controllers/observe.rb +14 -0
  26. data/examples/bivouac_sample/app/controllers/periodically_call.rb +12 -0
  27. data/examples/bivouac_sample/app/controllers/remote_form.rb +10 -0
  28. data/examples/bivouac_sample/app/controllers/remote_link.rb +11 -0
  29. data/examples/bivouac_sample/app/controllers/submit_remote.rb +17 -0
  30. data/examples/bivouac_sample/app/controllers/toggle.rb +10 -0
  31. data/examples/bivouac_sample/app/controllers/toggle_sortable.rb +11 -0
  32. data/examples/bivouac_sample/app/helpers/_helpers.rb +25 -0
  33. data/examples/bivouac_sample/app/helpers/source.rb +25 -0
  34. data/examples/bivouac_sample/app/views/_autocomplete_result.rb +9 -0
  35. data/examples/bivouac_sample/app/views/_drag_and_drop_result.rb +5 -0
  36. data/examples/bivouac_sample/app/views/_observe_result.rb +17 -0
  37. data/examples/bivouac_sample/app/views/_periodically_call_result.rb +5 -0
  38. data/examples/bivouac_sample/app/views/_remote_link_result.rb +5 -0
  39. data/examples/bivouac_sample/app/views/_sortable_result.rb +5 -0
  40. data/examples/bivouac_sample/app/views/_submit_remote_result.rb +5 -0
  41. data/examples/bivouac_sample/app/views/autocomplete.rb +28 -0
  42. data/examples/bivouac_sample/app/views/drag_and_drop.rb +35 -0
  43. data/examples/bivouac_sample/app/views/index.rb +19 -0
  44. data/examples/bivouac_sample/app/views/observe.rb +19 -0
  45. data/examples/bivouac_sample/app/views/periodically_call.rb +17 -0
  46. data/examples/bivouac_sample/app/views/remote_form.rb +19 -0
  47. data/examples/bivouac_sample/app/views/remote_link.rb +20 -0
  48. data/examples/bivouac_sample/app/views/submit_remote.rb +21 -0
  49. data/examples/bivouac_sample/app/views/toggle.rb +44 -0
  50. data/examples/bivouac_sample/app/views/toggle_sortable.rb +52 -0
  51. data/examples/bivouac_sample/config/environment.rb +37 -0
  52. data/examples/bivouac_sample/config/postamble.rb +62 -0
  53. data/examples/bivouac_sample/log/BivouacSample.log +77 -0
  54. data/examples/bivouac_sample/public/images/camping.png +0 -0
  55. data/examples/bivouac_sample/public/index.html +242 -0
  56. data/examples/bivouac_sample/public/javascripts/builder.js +131 -0
  57. data/examples/bivouac_sample/public/javascripts/controls.js +835 -0
  58. data/examples/bivouac_sample/public/javascripts/dragdrop.js +944 -0
  59. data/examples/bivouac_sample/public/javascripts/effects.js +1090 -0
  60. data/examples/bivouac_sample/public/javascripts/prototype.js +2515 -0
  61. data/examples/bivouac_sample/public/javascripts/scriptaculous.js +51 -0
  62. data/examples/bivouac_sample/public/javascripts/slider.js +278 -0
  63. data/examples/bivouac_sample/public/javascripts/tooltip.js +208 -0
  64. data/examples/bivouac_sample/public/javascripts/unittest.js +564 -0
  65. data/examples/bivouac_sample/public/stylesheets/autocomplete.css +22 -0
  66. data/examples/bivouac_sample/public/stylesheets/coderay.css +104 -0
  67. data/examples/bivouac_sample/script/generate +3 -0
  68. data/examples/bivouac_sample/script/server +5 -0
  69. data/lib/bivouac/helpers/view/goh/base.rb +16 -0
  70. data/lib/bivouac/helpers/view/goh/form.rb +170 -0
  71. data/lib/bivouac/helpers/view/goh/html.rb +138 -0
  72. data/lib/bivouac/helpers/view/goh/javascript.rb +532 -0
  73. data/lib/bivouac/helpers/view/goh/scriptaculous.rb +133 -0
  74. data/lib/bivouac/helpers/view/goh/tooltip.rb +33 -0
  75. data/lib/bivouac/template.rb +3 -3
  76. data/lib/bivouac/template/application/helpers_erb.rb +11 -0
  77. data/lib/bivouac/template/application/helpers_goh.rb +25 -0
  78. data/lib/bivouac/template/application/postamble.rb +62 -0
  79. data/lib/bivouac/template/application_erb.rb +4 -0
  80. data/lib/bivouac/template/application_goh.rb +4 -0
  81. data/lib/bivouac/template/environment.rb +19 -5
  82. data/lib/bivouac/template/server.rb +1 -1
  83. data/lib/bivouac/template/static/autocomplete.css +22 -0
  84. data/lib/bivouac/template/static/builder.js +131 -0
  85. data/lib/bivouac/template/static/controls.js +835 -0
  86. data/lib/bivouac/template/static/dragdrop.js +944 -0
  87. data/lib/bivouac/template/static/effects.js +1090 -0
  88. data/lib/bivouac/template/static/prototype.js +2515 -0
  89. data/lib/bivouac/template/static/scriptaculous.js +51 -0
  90. data/lib/bivouac/template/static/slider.js +278 -0
  91. data/lib/bivouac/template/static/tooltip.js +208 -0
  92. data/lib/bivouac/template/static/unittest.js +564 -0
  93. metadata +124 -7
  94. data/lib/bivouac/template/application/postamble_cgi.rb +0 -8
  95. data/lib/bivouac/template/application/postamble_fastcgi.rb +0 -8
  96. data/lib/bivouac/template/application/postamble_mongrel.rb +0 -19
  97. data/lib/bivouac/template/application/postamble_none.rb +0 -1
  98. data/lib/bivouac/template/application/postamble_webrick.rb +0 -19
@@ -0,0 +1,51 @@
1
+ // script.aculo.us scriptaculous.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
2
+
3
+ // Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ //
5
+ // Permission is hereby granted, free of charge, to any person obtaining
6
+ // a copy of this software and associated documentation files (the
7
+ // "Software"), to deal in the Software without restriction, including
8
+ // without limitation the rights to use, copy, modify, merge, publish,
9
+ // distribute, sublicense, and/or sell copies of the Software, and to
10
+ // permit persons to whom the Software is furnished to do so, subject to
11
+ // the following conditions:
12
+ //
13
+ // The above copyright notice and this permission notice shall be
14
+ // included in all copies or substantial portions of the Software.
15
+ //
16
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ //
24
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
25
+
26
+ var Scriptaculous = {
27
+ Version: '1.7.0',
28
+ require: function(libraryName) {
29
+ // inserting via DOM fails in Safari 2.0, so brute force approach
30
+ document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
31
+ },
32
+ load: function() {
33
+ if((typeof Prototype=='undefined') ||
34
+ (typeof Element == 'undefined') ||
35
+ (typeof Element.Methods=='undefined') ||
36
+ parseFloat(Prototype.Version.split(".")[0] + "." +
37
+ Prototype.Version.split(".")[1]) < 1.5)
38
+ throw("script.aculo.us requires the Prototype JavaScript framework >= 1.5.0");
39
+
40
+ $A(document.getElementsByTagName("script")).findAll( function(s) {
41
+ return (s.src && s.src.match(/scriptaculous\.js(\?.*)?$/))
42
+ }).each( function(s) {
43
+ var path = s.src.replace(/scriptaculous\.js(\?.*)?$/,'');
44
+ var includes = s.src.match(/\?.*load=([a-z,]*)/);
45
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider').split(',').each(
46
+ function(include) { Scriptaculous.require(path+include+'.js') });
47
+ });
48
+ }
49
+ }
50
+
51
+ Scriptaculous.load();
@@ -0,0 +1,278 @@
1
+ // script.aculo.us slider.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
2
+
3
+ // Copyright (c) 2005, 2006 Marty Haught, Thomas Fuchs
4
+ //
5
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
6
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
7
+
8
+ if(!Control) var Control = {};
9
+ Control.Slider = Class.create();
10
+
11
+ // options:
12
+ // axis: 'vertical', or 'horizontal' (default)
13
+ //
14
+ // callbacks:
15
+ // onChange(value)
16
+ // onSlide(value)
17
+ Control.Slider.prototype = {
18
+ initialize: function(handle, track, options) {
19
+ var slider = this;
20
+
21
+ if(handle instanceof Array) {
22
+ this.handles = handle.collect( function(e) { return $(e) });
23
+ } else {
24
+ this.handles = [$(handle)];
25
+ }
26
+
27
+ this.track = $(track);
28
+ this.options = options || {};
29
+
30
+ this.axis = this.options.axis || 'horizontal';
31
+ this.increment = this.options.increment || 1;
32
+ this.step = parseInt(this.options.step || '1');
33
+ this.range = this.options.range || $R(0,1);
34
+
35
+ this.value = 0; // assure backwards compat
36
+ this.values = this.handles.map( function() { return 0 });
37
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
38
+ this.options.startSpan = $(this.options.startSpan || null);
39
+ this.options.endSpan = $(this.options.endSpan || null);
40
+
41
+ this.restricted = this.options.restricted || false;
42
+
43
+ this.maximum = this.options.maximum || this.range.end;
44
+ this.minimum = this.options.minimum || this.range.start;
45
+
46
+ // Will be used to align the handle onto the track, if necessary
47
+ this.alignX = parseInt(this.options.alignX || '0');
48
+ this.alignY = parseInt(this.options.alignY || '0');
49
+
50
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
51
+
52
+ this.handleLength = this.isVertical() ?
53
+ (this.handles[0].offsetHeight != 0 ?
54
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
55
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
56
+ this.handles[0].style.width.replace(/px$/,""));
57
+
58
+ this.active = false;
59
+ this.dragging = false;
60
+ this.disabled = false;
61
+
62
+ if(this.options.disabled) this.setDisabled();
63
+
64
+ // Allowed values array
65
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
66
+ if(this.allowedValues) {
67
+ this.minimum = this.allowedValues.min();
68
+ this.maximum = this.allowedValues.max();
69
+ }
70
+
71
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
72
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
73
+ this.eventMouseMove = this.update.bindAsEventListener(this);
74
+
75
+ // Initialize handles in reverse (make sure first handle is active)
76
+ this.handles.each( function(h,i) {
77
+ i = slider.handles.length-1-i;
78
+ slider.setValue(parseFloat(
79
+ (slider.options.sliderValue instanceof Array ?
80
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
81
+ slider.range.start), i);
82
+ Element.makePositioned(h); // fix IE
83
+ Event.observe(h, "mousedown", slider.eventMouseDown);
84
+ });
85
+
86
+ Event.observe(this.track, "mousedown", this.eventMouseDown);
87
+ Event.observe(document, "mouseup", this.eventMouseUp);
88
+ Event.observe(document, "mousemove", this.eventMouseMove);
89
+
90
+ this.initialized = true;
91
+ },
92
+ dispose: function() {
93
+ var slider = this;
94
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
95
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
96
+ Event.stopObserving(document, "mousemove", this.eventMouseMove);
97
+ this.handles.each( function(h) {
98
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
99
+ });
100
+ },
101
+ setDisabled: function(){
102
+ this.disabled = true;
103
+ },
104
+ setEnabled: function(){
105
+ this.disabled = false;
106
+ },
107
+ getNearestValue: function(value){
108
+ if(this.allowedValues){
109
+ if(value >= this.allowedValues.max()) return(this.allowedValues.max());
110
+ if(value <= this.allowedValues.min()) return(this.allowedValues.min());
111
+
112
+ var offset = Math.abs(this.allowedValues[0] - value);
113
+ var newValue = this.allowedValues[0];
114
+ this.allowedValues.each( function(v) {
115
+ var currentOffset = Math.abs(v - value);
116
+ if(currentOffset <= offset){
117
+ newValue = v;
118
+ offset = currentOffset;
119
+ }
120
+ });
121
+ return newValue;
122
+ }
123
+ if(value > this.range.end) return this.range.end;
124
+ if(value < this.range.start) return this.range.start;
125
+ return value;
126
+ },
127
+ setValue: function(sliderValue, handleIdx){
128
+ if(!this.active) {
129
+ this.activeHandleIdx = handleIdx || 0;
130
+ this.activeHandle = this.handles[this.activeHandleIdx];
131
+ this.updateStyles();
132
+ }
133
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
134
+ if(this.initialized && this.restricted) {
135
+ if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
136
+ sliderValue = this.values[handleIdx-1];
137
+ if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
138
+ sliderValue = this.values[handleIdx+1];
139
+ }
140
+ sliderValue = this.getNearestValue(sliderValue);
141
+ this.values[handleIdx] = sliderValue;
142
+ this.value = this.values[0]; // assure backwards compat
143
+
144
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
145
+ this.translateToPx(sliderValue);
146
+
147
+ this.drawSpans();
148
+ if(!this.dragging || !this.event) this.updateFinished();
149
+ },
150
+ setValueBy: function(delta, handleIdx) {
151
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
152
+ handleIdx || this.activeHandleIdx || 0);
153
+ },
154
+ translateToPx: function(value) {
155
+ return Math.round(
156
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
157
+ (value - this.range.start)) + "px";
158
+ },
159
+ translateToValue: function(offset) {
160
+ return ((offset/(this.trackLength-this.handleLength) *
161
+ (this.range.end-this.range.start)) + this.range.start);
162
+ },
163
+ getRange: function(range) {
164
+ var v = this.values.sortBy(Prototype.K);
165
+ range = range || 0;
166
+ return $R(v[range],v[range+1]);
167
+ },
168
+ minimumOffset: function(){
169
+ return(this.isVertical() ? this.alignY : this.alignX);
170
+ },
171
+ maximumOffset: function(){
172
+ return(this.isVertical() ?
173
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
174
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
175
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
176
+ this.track.style.width.replace(/px$/,"")) - this.alignY);
177
+ },
178
+ isVertical: function(){
179
+ return (this.axis == 'vertical');
180
+ },
181
+ drawSpans: function() {
182
+ var slider = this;
183
+ if(this.spans)
184
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
185
+ if(this.options.startSpan)
186
+ this.setSpan(this.options.startSpan,
187
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
188
+ if(this.options.endSpan)
189
+ this.setSpan(this.options.endSpan,
190
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
191
+ },
192
+ setSpan: function(span, range) {
193
+ if(this.isVertical()) {
194
+ span.style.top = this.translateToPx(range.start);
195
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
196
+ } else {
197
+ span.style.left = this.translateToPx(range.start);
198
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
199
+ }
200
+ },
201
+ updateStyles: function() {
202
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
203
+ Element.addClassName(this.activeHandle, 'selected');
204
+ },
205
+ startDrag: function(event) {
206
+ if(Event.isLeftClick(event)) {
207
+ if(!this.disabled){
208
+ this.active = true;
209
+
210
+ var handle = Event.element(event);
211
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
212
+ var track = handle;
213
+ if(track==this.track) {
214
+ var offsets = Position.cumulativeOffset(this.track);
215
+ this.event = event;
216
+ this.setValue(this.translateToValue(
217
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
218
+ ));
219
+ var offsets = Position.cumulativeOffset(this.activeHandle);
220
+ this.offsetX = (pointer[0] - offsets[0]);
221
+ this.offsetY = (pointer[1] - offsets[1]);
222
+ } else {
223
+ // find the handle (prevents issues with Safari)
224
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
225
+ handle = handle.parentNode;
226
+
227
+ if(this.handles.indexOf(handle)!=-1) {
228
+ this.activeHandle = handle;
229
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
230
+ this.updateStyles();
231
+
232
+ var offsets = Position.cumulativeOffset(this.activeHandle);
233
+ this.offsetX = (pointer[0] - offsets[0]);
234
+ this.offsetY = (pointer[1] - offsets[1]);
235
+ }
236
+ }
237
+ }
238
+ Event.stop(event);
239
+ }
240
+ },
241
+ update: function(event) {
242
+ if(this.active) {
243
+ if(!this.dragging) this.dragging = true;
244
+ this.draw(event);
245
+ // fix AppleWebKit rendering
246
+ if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
247
+ Event.stop(event);
248
+ }
249
+ },
250
+ draw: function(event) {
251
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
252
+ var offsets = Position.cumulativeOffset(this.track);
253
+ pointer[0] -= this.offsetX + offsets[0];
254
+ pointer[1] -= this.offsetY + offsets[1];
255
+ this.event = event;
256
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
257
+ if(this.initialized && this.options.onSlide)
258
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
259
+ },
260
+ endDrag: function(event) {
261
+ if(this.active && this.dragging) {
262
+ this.finishDrag(event, true);
263
+ Event.stop(event);
264
+ }
265
+ this.active = false;
266
+ this.dragging = false;
267
+ },
268
+ finishDrag: function(event, success) {
269
+ this.active = false;
270
+ this.dragging = false;
271
+ this.updateFinished();
272
+ },
273
+ updateFinished: function() {
274
+ if(this.initialized && this.options.onChange)
275
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
276
+ this.event = null;
277
+ }
278
+ }
@@ -0,0 +1,208 @@
1
+ /*
2
+ * Copyright (c) 2006 Jonathan Weiss <jw@innerewut.de>
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+
18
+ /* tooltip-0.2.js - Small tooltip library on top of Prototype
19
+ * by Jonathan Weiss <jw@innerewut.de> distributed under the BSD license.
20
+ *
21
+ * This tooltip library works in two modes. If it gets a valid DOM element
22
+ * or DOM id as an argument it uses this element as the tooltip. This
23
+ * element will be placed (and shown) near the mouse pointer when a trigger-
24
+ * element is moused-over.
25
+ * If it gets only a text as an argument instead of a DOM id or DOM element
26
+ * it will create a div with the classname 'tooltip' that holds the given text.
27
+ * This newly created div will be used as the tooltip. This is usefull if you
28
+ * want to use tooltip.js to create popups out of title attributes.
29
+ *
30
+ *
31
+ * Usage:
32
+ * <script src="/javascripts/prototype.js" type="text/javascript"></script>
33
+ * <script src="/javascripts/tooltip.js" type="text/javascript"></script>
34
+ * <script type="text/javascript">
35
+ * // with valid DOM id
36
+ * var my_tooltip = new Tooltip('id_of_trigger_element', 'id_of_tooltip_to_show_element')
37
+ *
38
+ * // with text
39
+ * var my_other_tooltip = new Tooltip('id_of_trigger_element', 'a nice description')
40
+ *
41
+ * // create popups for each element with a title attribute
42
+ * Event.observe(window,"load",function() {
43
+ * $$("*").findAll(function(node){
44
+ * return node.getAttribute('title');
45
+ * }).each(function(node){
46
+ * new Tooltip(node,node.title);
47
+ * node.removeAttribute("title");
48
+ * });
49
+ * });
50
+ *
51
+ * </script>
52
+ *
53
+ * Now whenever you trigger a mouseOver on the `trigger` element, the tooltip element will
54
+ * be shown. On o mouseOut the tooltip disappears.
55
+ *
56
+ * Example:
57
+ *
58
+ * <script src="/javascripts/prototype.js" type="text/javascript"></script>
59
+ * <script src="/javascripts/scriptaculous.js" type="text/javascript"></script>
60
+ * <script src="/javascripts/tooltip.js" type="text/javascript"></script>
61
+ *
62
+ * <div id='tooltip' style="display:none; margin: 5px; background-color: red;">
63
+ * Detail infos on product 1....<br />
64
+ * </div>
65
+ *
66
+ * <div id='product_1'>
67
+ * This is product 1
68
+ * </div>
69
+ *
70
+ * <script type="text/javascript">
71
+ * var my_tooltip = new Tooltip('product_1', 'tooltip')
72
+ * </script>
73
+ *
74
+ * You can use my_tooltip.destroy() to remove the event observers and thereby the tooltip.
75
+ */
76
+
77
+ var Tooltip = Class.create();
78
+ Tooltip.prototype = {
79
+ initialize: function(element, tool_tip) {
80
+ var options = Object.extend({
81
+ default_css: false,
82
+ margin: "0px",
83
+ padding: "5px",
84
+ backgroundColor: "#d6d6fc",
85
+ min_distance_x: 5,
86
+ min_distance_y: 5,
87
+ delta_x: 0,
88
+ delta_y: 0,
89
+ zindex: 1000
90
+ }, arguments[2] || {});
91
+
92
+ this.element = $(element);
93
+
94
+ this.options = options;
95
+
96
+ // use the supplied tooltip element or create our own div
97
+ if($(tool_tip)) {
98
+ this.tool_tip = $(tool_tip);
99
+ } else {
100
+ this.tool_tip = $(document.createElement("div"));
101
+ document.body.appendChild(this.tool_tip);
102
+ this.tool_tip.addClassName("tooltip");
103
+ this.tool_tip.appendChild(document.createTextNode(tool_tip));
104
+ }
105
+
106
+ // hide the tool-tip by default
107
+ this.tool_tip.hide();
108
+
109
+ this.eventMouseOver = this.showTooltip.bindAsEventListener(this);
110
+ this.eventMouseOut = this.hideTooltip.bindAsEventListener(this);
111
+ this.eventMouseMove = this.moveTooltip.bindAsEventListener(this);
112
+
113
+ this.registerEvents();
114
+ },
115
+
116
+ destroy: function() {
117
+ Event.stopObserving(this.element, "mouseover", this.eventMouseOver);
118
+ Event.stopObserving(this.element, "mouseout", this.eventMouseOut);
119
+ Event.stopObserving(this.element, "mousemove", this.eventMouseMove);
120
+ },
121
+
122
+ registerEvents: function() {
123
+ Event.observe(this.element, "mouseover", this.eventMouseOver);
124
+ Event.observe(this.element, "mouseout", this.eventMouseOut);
125
+ Event.observe(this.element, "mousemove", this.eventMouseMove);
126
+ },
127
+
128
+ moveTooltip: function(event){
129
+ Event.stop(event);
130
+ // get Mouse position
131
+ var mouse_x = Event.pointerX(event);
132
+ var mouse_y = Event.pointerY(event);
133
+
134
+ // decide if wee need to switch sides for the tooltip
135
+ var dimensions = Element.getDimensions( this.tool_tip );
136
+ var element_width = dimensions.width;
137
+ var element_height = dimensions.height;
138
+
139
+ if ( (element_width + mouse_x) >= ( this.getWindowWidth() - this.options.min_distance_x) ){ // too big for X
140
+ mouse_x = mouse_x - element_width;
141
+ // apply min_distance to make sure that the mouse is not on the tool-tip
142
+ mouse_x = mouse_x - this.options.min_distance_x;
143
+ } else {
144
+ mouse_x = mouse_x + this.options.min_distance_x;
145
+ }
146
+
147
+ if ( (element_height + mouse_y) >= ( this.getWindowHeight() - this.options.min_distance_y) ){ // too big for Y
148
+ mouse_y = mouse_y - element_height;
149
+ // apply min_distance to make sure that the mouse is not on the tool-tip
150
+ mouse_y = mouse_y - this.options.min_distance_y;
151
+ } else {
152
+ mouse_y = mouse_y + this.options.min_distance_y;
153
+ }
154
+
155
+ // now set the right styles
156
+ this.setStyles(mouse_x, mouse_y);
157
+ },
158
+
159
+
160
+ showTooltip: function(event) {
161
+ Event.stop(event);
162
+ this.moveTooltip(event);
163
+ new Element.show(this.tool_tip);
164
+ },
165
+
166
+ setStyles: function(x, y){
167
+ // set the right styles to position the tool tip
168
+ Element.setStyle(this.tool_tip, { position:'absolute',
169
+ top:y + this.options.delta_y + "px",
170
+ left:x + this.options.delta_x + "px",
171
+ zindex:this.options.zindex
172
+ });
173
+
174
+ // apply default theme if wanted
175
+ if (this.options.default_css){
176
+ Element.setStyle(this.tool_tip, { margin:this.options.margin,
177
+ padding:this.options.padding,
178
+ backgroundColor:this.options.backgroundColor,
179
+ zindex:this.options.zindex
180
+ });
181
+ }
182
+ },
183
+
184
+ hideTooltip: function(event){
185
+ new Element.hide(this.tool_tip);
186
+ },
187
+
188
+ getWindowHeight: function(){
189
+ var innerHeight;
190
+ if (navigator.appVersion.indexOf('MSIE')>0) {
191
+ innerHeight = document.body.clientHeight;
192
+ } else {
193
+ innerHeight = window.innerHeight;
194
+ }
195
+ return innerHeight;
196
+ },
197
+
198
+ getWindowWidth: function(){
199
+ var innerWidth;
200
+ if (navigator.appVersion.indexOf('MSIE')>0) {
201
+ innerWidth = document.body.clientWidth;
202
+ } else {
203
+ innerWidth = window.innerWidth;
204
+ }
205
+ return innerWidth;
206
+ }
207
+
208
+ }