hobix 0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. data/COPYING +18 -0
  2. data/README +18 -0
  3. data/Rakefile +96 -0
  4. data/bin/hobix +94 -0
  5. data/contrib/blosxom-to-hobix.rb +253 -0
  6. data/contrib/txp-to-hobix.rb +56 -0
  7. data/contrib/webrick-all-mine.rb +20 -0
  8. data/doc/CHANGELOG +285 -0
  9. data/doc/rdoc/classes/Hobix/API.html +382 -0
  10. data/doc/rdoc/classes/Hobix/Article.html +111 -0
  11. data/doc/rdoc/classes/Hobix/BaseContent.html +692 -0
  12. data/doc/rdoc/classes/Hobix/BaseEntry.html +218 -0
  13. data/doc/rdoc/classes/Hobix/BaseFacet.html +205 -0
  14. data/doc/rdoc/classes/Hobix/BaseOutput.html +122 -0
  15. data/doc/rdoc/classes/Hobix/BasePlugin.html +201 -0
  16. data/doc/rdoc/classes/Hobix/BaseProperties/ClassMethods.html +243 -0
  17. data/doc/rdoc/classes/Hobix/BaseProperties.html +218 -0
  18. data/doc/rdoc/classes/Hobix/BasePublish.html +157 -0
  19. data/doc/rdoc/classes/Hobix/BaseStorage.html +417 -0
  20. data/doc/rdoc/classes/Hobix/BixWik/Entry.html +196 -0
  21. data/doc/rdoc/classes/Hobix/BixWik/IndexEntry.html +170 -0
  22. data/doc/rdoc/classes/Hobix/BixWik/WikiRedCloth.html +111 -0
  23. data/doc/rdoc/classes/Hobix/BixWik.html +418 -0
  24. data/doc/rdoc/classes/Hobix/BixWikPlugin.html +158 -0
  25. data/doc/rdoc/classes/Hobix/CommandLine.html +1970 -0
  26. data/doc/rdoc/classes/Hobix/Comment.html +113 -0
  27. data/doc/rdoc/classes/Hobix/Config.html +212 -0
  28. data/doc/rdoc/classes/Hobix/DataMarsh.html +667 -0
  29. data/doc/rdoc/classes/Hobix/Entry.html +178 -0
  30. data/doc/rdoc/classes/Hobix/EntryEnum.html +162 -0
  31. data/doc/rdoc/classes/Hobix/Enumerable.html +170 -0
  32. data/doc/rdoc/classes/Hobix/Facets/WikiEdit.html +180 -0
  33. data/doc/rdoc/classes/Hobix/Facets.html +111 -0
  34. data/doc/rdoc/classes/Hobix/LinkList.html +182 -0
  35. data/doc/rdoc/classes/Hobix/Out/Quick.html +412 -0
  36. data/doc/rdoc/classes/Hobix/Out.html +119 -0
  37. data/doc/rdoc/classes/Hobix/Page.html +381 -0
  38. data/doc/rdoc/classes/Hobix/Trackback.html +113 -0
  39. data/doc/rdoc/classes/Hobix/UriStr.html +198 -0
  40. data/doc/rdoc/classes/Hobix/WebApp/QueryString.html +207 -0
  41. data/doc/rdoc/classes/Hobix/WebApp/QueryValidationFailure.html +111 -0
  42. data/doc/rdoc/classes/Hobix/WebApp.html +1383 -0
  43. data/doc/rdoc/classes/Hobix/Weblog/AuthorNotFound.html +111 -0
  44. data/doc/rdoc/classes/Hobix/Weblog.html +2082 -0
  45. data/doc/rdoc/classes/Hobix.html +399 -0
  46. data/doc/rdoc/classes/Kernel.html +139 -0
  47. data/doc/rdoc/classes/Regexp.html +154 -0
  48. data/doc/rdoc/classes/YAML/Omap.html +144 -0
  49. data/doc/rdoc/classes/YAML.html +111 -0
  50. data/doc/rdoc/created.rid +1 -0
  51. data/doc/rdoc/files/COPYING.html +129 -0
  52. data/doc/rdoc/files/README.html +131 -0
  53. data/doc/rdoc/files/doc/CHANGELOG.html +101 -0
  54. data/doc/rdoc/files/lib/hobix/api_rb.html +119 -0
  55. data/doc/rdoc/files/lib/hobix/article_rb.html +126 -0
  56. data/doc/rdoc/files/lib/hobix/base_rb.html +128 -0
  57. data/doc/rdoc/files/lib/hobix/bixwik_rb.html +126 -0
  58. data/doc/rdoc/files/lib/hobix/commandline_rb.html +140 -0
  59. data/doc/rdoc/files/lib/hobix/comments_rb.html +126 -0
  60. data/doc/rdoc/files/lib/hobix/config_rb.html +125 -0
  61. data/doc/rdoc/files/lib/hobix/datamarsh_rb.html +108 -0
  62. data/doc/rdoc/files/lib/hobix/entry_rb.html +118 -0
  63. data/doc/rdoc/files/lib/hobix/linklist_rb.html +127 -0
  64. data/doc/rdoc/files/lib/hobix/publisher_rb.html +126 -0
  65. data/doc/rdoc/files/lib/hobix/trackbacks_rb.html +128 -0
  66. data/doc/rdoc/files/lib/hobix/webapp_rb.html +127 -0
  67. data/doc/rdoc/files/lib/hobix/weblog_rb.html +135 -0
  68. data/doc/rdoc/files/lib/hobix_rb.html +127 -0
  69. data/doc/rdoc/fr_class_index.html +67 -0
  70. data/doc/rdoc/fr_file_index.html +44 -0
  71. data/doc/rdoc/fr_method_index.html +307 -0
  72. data/doc/rdoc/index.html +24 -0
  73. data/doc/rdoc/rdoc-style.css +208 -0
  74. data/git_hobix_update.php +13 -0
  75. data/lib/hobix/api.rb +91 -0
  76. data/lib/hobix/article.rb +22 -0
  77. data/lib/hobix/base.rb +480 -0
  78. data/lib/hobix/bixwik.rb +200 -0
  79. data/lib/hobix/commandline.rb +677 -0
  80. data/lib/hobix/comments.rb +98 -0
  81. data/lib/hobix/config.rb +39 -0
  82. data/lib/hobix/datamarsh.rb +110 -0
  83. data/lib/hobix/entry.rb +84 -0
  84. data/lib/hobix/facets/comments.rb +99 -0
  85. data/lib/hobix/facets/publisher.rb +314 -0
  86. data/lib/hobix/facets/trackbacks.rb +80 -0
  87. data/lib/hobix/linklist.rb +81 -0
  88. data/lib/hobix/out/atom.rb +101 -0
  89. data/lib/hobix/out/erb.rb +64 -0
  90. data/lib/hobix/out/okaynews.rb +55 -0
  91. data/lib/hobix/out/quick.rb +314 -0
  92. data/lib/hobix/out/rdf.rb +97 -0
  93. data/lib/hobix/out/redrum.rb +26 -0
  94. data/lib/hobix/out/rss.rb +128 -0
  95. data/lib/hobix/plugin/akismet.rb +196 -0
  96. data/lib/hobix/plugin/bloglines.rb +73 -0
  97. data/lib/hobix/plugin/calendar.rb +212 -0
  98. data/lib/hobix/plugin/flickr.rb +110 -0
  99. data/lib/hobix/plugin/recent_comments.rb +84 -0
  100. data/lib/hobix/plugin/sections.rb +91 -0
  101. data/lib/hobix/plugin/tags.rb +60 -0
  102. data/lib/hobix/publish/ping.rb +53 -0
  103. data/lib/hobix/publish/replicate.rb +283 -0
  104. data/lib/hobix/publisher.rb +18 -0
  105. data/lib/hobix/search/dictionary.rb +141 -0
  106. data/lib/hobix/search/porter_stemmer.rb +203 -0
  107. data/lib/hobix/search/simple.rb +209 -0
  108. data/lib/hobix/search/vector.rb +100 -0
  109. data/lib/hobix/storage/filesys.rb +408 -0
  110. data/lib/hobix/trackbacks.rb +93 -0
  111. data/lib/hobix/util/objedit.rb +193 -0
  112. data/lib/hobix/util/patcher.rb +155 -0
  113. data/lib/hobix/webapp/cli.rb +195 -0
  114. data/lib/hobix/webapp/htmlform.rb +107 -0
  115. data/lib/hobix/webapp/message.rb +177 -0
  116. data/lib/hobix/webapp/urigen.rb +141 -0
  117. data/lib/hobix/webapp/webrick-servlet.rb +90 -0
  118. data/lib/hobix/webapp.rb +723 -0
  119. data/lib/hobix/weblog.rb +893 -0
  120. data/lib/hobix.rb +230 -0
  121. data/share/default-blog/hobix.yaml +16 -0
  122. data/share/default-blog/htdocs/site.css +174 -0
  123. data/share/default-blog/skel/entry.html.quick +0 -0
  124. data/share/default-blog/skel/index.atom.atom +0 -0
  125. data/share/default-blog/skel/index.html.quick-summary +0 -0
  126. data/share/default-blog/skel/index.xml.rss +0 -0
  127. data/share/default-blog/skel/index.yaml.okaynews +0 -0
  128. data/share/default-blog/skel/monthly.html.quick-archive +0 -0
  129. data/share/default-blog/skel/section.html.quick-archive +0 -0
  130. data/share/default-blog/skel/yearly.html.quick-archive +0 -0
  131. data/share/default-blog-modes.yaml +7 -0
  132. data/share/default-blog.apache-cgi.patch +8 -0
  133. data/share/default-blog.apache-ssi.patch +38 -0
  134. data/share/default-blog.apache2-ssi.patch +3 -0
  135. data/share/default-blog.cgi.patch +8 -0
  136. data/share/default-blog.comments.patch +5 -0
  137. data/share/default-blog.prototype.patch +766 -0
  138. data/share/default-blog.publisher.patch +5 -0
  139. data/share/default-blog.wiki.patch +29 -0
  140. data/share/publisher/css/control.css +90 -0
  141. data/share/publisher/css/form.css +238 -0
  142. data/share/publisher/css/form.import.css +72 -0
  143. data/share/publisher/css/main-menu.css +134 -0
  144. data/share/publisher/i/hobix-emblazen-1.png +0 -0
  145. data/share/publisher/i/hobix-emblazen-2.png +0 -0
  146. data/share/publisher/i/hobix-emblazen-3.png +0 -0
  147. data/share/publisher/i/hobix-emblazen-4.png +0 -0
  148. data/share/publisher/i/hobix-emblazen-5.png +0 -0
  149. data/share/publisher/i/hobix-emblazen-6.png +0 -0
  150. data/share/publisher/i/hobix-emblazen-7.png +0 -0
  151. data/share/publisher/index.erb +66 -0
  152. data/share/publisher/js/controls.js +261 -0
  153. data/share/publisher/js/dragdrop.js +476 -0
  154. data/share/publisher/js/effects.js +570 -0
  155. data/share/publisher/js/prototype.js +1011 -0
  156. metadata +230 -0
@@ -0,0 +1,476 @@
1
+ // Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
2
+ //
3
+ // Element.Class part Copyright (c) 2005 by Rick Olson
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
+ Element.Class = {
25
+ // Element.toggleClass(element, className) toggles the class being on/off
26
+ // Element.toggleClass(element, className1, className2) toggles between both classes,
27
+ // defaulting to className1 if neither exist
28
+ toggle: function(element, className) {
29
+ if(Element.Class.has(element, className)) {
30
+ Element.Class.remove(element, className);
31
+ if(arguments.length == 3) Element.Class.add(element, arguments[2]);
32
+ } else {
33
+ Element.Class.add(element, className);
34
+ if(arguments.length == 3) Element.Class.remove(element, arguments[2]);
35
+ }
36
+ },
37
+
38
+ // gets space-delimited classnames of an element as an array
39
+ get: function(element) {
40
+ element = $(element);
41
+ return element.className.split(' ');
42
+ },
43
+
44
+ // functions adapted from original functions by Gavin Kistner
45
+ remove: function(element) {
46
+ element = $(element);
47
+ var regEx;
48
+ for(var i = 1; i < arguments.length; i++) {
49
+ regEx = new RegExp("^" + arguments[i] + "\\b\\s*|\\s*\\b" + arguments[i] + "\\b", 'g');
50
+ element.className = element.className.replace(regEx, '')
51
+ }
52
+ },
53
+
54
+ add: function(element) {
55
+ element = $(element);
56
+ for(var i = 1; i < arguments.length; i++) {
57
+ Element.Class.remove(element, arguments[i]);
58
+ element.className += (element.className.length > 0 ? ' ' : '') + arguments[i];
59
+ }
60
+ },
61
+
62
+ // returns true if all given classes exist in said element
63
+ has: function(element) {
64
+ element = $(element);
65
+ if(!element || !element.className) return false;
66
+ var regEx;
67
+ for(var i = 1; i < arguments.length; i++) {
68
+ regEx = new RegExp("\\b" + arguments[i] + "\\b");
69
+ if(!regEx.test(element.className)) return false;
70
+ }
71
+ return true;
72
+ },
73
+
74
+ // expects arrays of strings and/or strings as optional paramters
75
+ // Element.Class.has_any(element, ['classA','classB','classC'], 'classD')
76
+ has_any: function(element) {
77
+ element = $(element);
78
+ if(!element || !element.className) return false;
79
+ var regEx;
80
+ for(var i = 1; i < arguments.length; i++) {
81
+ if((typeof arguments[i] == 'object') &&
82
+ (arguments[i].constructor == Array)) {
83
+ for(var j = 0; j < arguments[i].length; j++) {
84
+ regEx = new RegExp("\\b" + arguments[i][j] + "\\b");
85
+ if(regEx.test(element.className)) return true;
86
+ }
87
+ } else {
88
+ regEx = new RegExp("\\b" + arguments[i] + "\\b");
89
+ if(regEx.test(element.className)) return true;
90
+ }
91
+ }
92
+ return false;
93
+ },
94
+
95
+ childrenWith: function(element, className) {
96
+ var children = $(element).getElementsByTagName('*');
97
+ var elements = new Array();
98
+
99
+ for (var i = 0; i < children.length; i++) {
100
+ if (Element.Class.has(children[i], className)) {
101
+ elements.push(children[i]);
102
+ break;
103
+ }
104
+ }
105
+
106
+ return elements;
107
+ }
108
+ }
109
+
110
+ /*--------------------------------------------------------------------------*/
111
+
112
+ var Droppables = {
113
+ drops: false,
114
+
115
+ add: function(element) {
116
+ var element = $(element);
117
+ var options = {
118
+ greedy: true,
119
+ hoverclass: null
120
+ }.extend(arguments[1] || {});
121
+
122
+ // cache containers
123
+ if(options.containment) {
124
+ options._containers = new Array();
125
+ var containment = options.containment;
126
+ if((typeof containment == 'object') &&
127
+ (containment.constructor == Array)) {
128
+ for(var i=0; i<containment.length; i++)
129
+ options._containers.push($(containment[i]));
130
+ } else {
131
+ options._containers.push($(containment));
132
+ }
133
+ options._containers_length =
134
+ options._containers.length-1;
135
+ }
136
+
137
+ if(element.style.position=='') //fix IE
138
+ element.style.position = 'relative';
139
+
140
+ // activate the droppable
141
+ element.droppable = options;
142
+
143
+ if(!this.drops) this.drops = [];
144
+ this.drops.push(element);
145
+ },
146
+
147
+ is_contained: function(element, drop) {
148
+ var containers = drop.droppable._containers;
149
+ var parentNode = element.parentNode;
150
+ var i = drop.droppable._containers_length;
151
+ do { if(parentNode==containers[i]) return true; } while (i--);
152
+ return false;
153
+ },
154
+
155
+ is_affected: function(pX, pY, element, drop) {
156
+ return (
157
+ (drop!=element) &&
158
+ ((!drop.droppable._containers) ||
159
+ this.is_contained(element, drop)) &&
160
+ ((!drop.droppable.accept) ||
161
+ (Element.Class.has_any(element, drop.droppable.accept))) &&
162
+ Position.within(drop, pX, pY) );
163
+ },
164
+
165
+ deactivate: function(drop) {
166
+ Element.Class.remove(drop, drop.droppable.hoverclass);
167
+ this.last_active = null;
168
+ },
169
+
170
+ activate: function(drop) {
171
+ if(this.last_active) this.deactivate(this.last_active);
172
+ if(drop.droppable.hoverclass) {
173
+ Element.Class.add(drop, drop.droppable.hoverclass);
174
+ this.last_active = drop;
175
+ }
176
+ },
177
+
178
+ show: function(event, element) {
179
+ if(!this.drops) return;
180
+ var pX = Event.pointerX(event);
181
+ var pY = Event.pointerY(event);
182
+ Position.prepare();
183
+
184
+ var i = this.drops.length-1; do {
185
+ var drop = this.drops[i];
186
+ if(this.is_affected(pX, pY, element, drop)) {
187
+ if(drop.droppable.onHover)
188
+ drop.droppable.onHover(
189
+ element, drop, Position.overlap(drop.droppable.overlap, drop));
190
+ if(drop.droppable.greedy) {
191
+ this.activate(drop);
192
+ return;
193
+ }
194
+ }
195
+ } while (i--);
196
+ },
197
+
198
+ fire: function(event, element) {
199
+ if(!this.drops) return;
200
+ var pX = Event.pointerX(event);
201
+ var pY = Event.pointerY(event);
202
+ Position.prepare();
203
+
204
+ var i = this.drops.length-1; do {
205
+ var drop = this.drops[i];
206
+ if(this.is_affected(pX, pY, element, drop))
207
+ if(drop.droppable.onDrop)
208
+ drop.droppable.onDrop(element);
209
+ } while (i--);
210
+ },
211
+
212
+ reset: function() {
213
+ if(this.last_active)
214
+ this.deactivate(this.last_active);
215
+ }
216
+ }
217
+
218
+ Draggables = {
219
+ observers: new Array(),
220
+ addObserver: function(observer) {
221
+ this.observers.push(observer);
222
+ },
223
+ notify: function(eventName, draggable) { // 'onStart', 'onEnd'
224
+ for(var i = 0; i < this.observers.length; i++)
225
+ this.observers[i][eventName](draggable);
226
+ }
227
+ }
228
+
229
+ /*--------------------------------------------------------------------------*/
230
+
231
+ Draggable = Class.create();
232
+ Draggable.prototype = {
233
+ initialize: function(element) {
234
+ var options = {
235
+ handle: false,
236
+ starteffect: function(element) {
237
+ new Effect.Opacity(element, {duration:0.2, from:1.0, to:0.7});
238
+ },
239
+ reverteffect: function(element, top_offset, left_offset) {
240
+ new Effect.MoveBy(element, -top_offset, -left_offset, {duration:0.4});
241
+ },
242
+ endeffect: function(element) {
243
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:1.0});
244
+ },
245
+ zindex: 1000,
246
+ revert: false
247
+ }.extend(arguments[1] || {});
248
+
249
+ this.element = $(element);
250
+ this.element.drag = this;
251
+ this.handle = options.handle ? $(options.handle) : this.element;
252
+
253
+ // fix IE
254
+ if(!this.element.style.position)
255
+ this.element.style.position = 'relative';
256
+
257
+ this.offsetX = 0;
258
+ this.offsetY = 0;
259
+ this.originalLeft = this.currentLeft();
260
+ this.originalTop = this.currentTop();
261
+ this.originalX = this.element.offsetLeft;
262
+ this.originalY = this.element.offsetTop;
263
+ this.originalZ = parseInt(this.element.style.zIndex || "0");
264
+
265
+ this.options = options;
266
+
267
+ this.active = false;
268
+ this.dragging = false;
269
+
270
+ Event.observe(this.handle, "mousedown", this.startDrag.bindAsEventListener(this));
271
+ Event.observe(document, "mouseup", this.endDrag.bindAsEventListener(this));
272
+ Event.observe(document, "mousemove", this.update.bindAsEventListener(this));
273
+ },
274
+ currentLeft: function() {
275
+ return parseInt(this.element.style.left || '0');
276
+ },
277
+ currentTop: function() {
278
+ return parseInt(this.element.style.top || '0')
279
+ },
280
+ startDrag: function(event) {
281
+ if(Event.isLeftClick(event)) {
282
+ this.active = true;
283
+
284
+ var style = this.element.style;
285
+ this.originalY = this.element.offsetTop - this.currentTop() - this.originalTop;
286
+ this.originalX = this.element.offsetLeft - this.currentLeft() - this.originalLeft;
287
+ this.offsetY = event.clientY - this.originalY - this.originalTop;
288
+ this.offsetX = event.clientX - this.originalX - this.originalLeft;
289
+
290
+ Event.stop(event);
291
+ }
292
+ },
293
+ endDrag: function(event) {
294
+ if(this.active && this.dragging) {
295
+ this.active = false;
296
+ this.dragging = false;
297
+
298
+ Droppables.fire(event, this.element);
299
+ Draggables.notify('onEnd', this);
300
+
301
+ var revert = this.options.revert;
302
+ if(revert && typeof revert == 'function') revert = revert(this.element);
303
+
304
+ if(revert && this.options.reverteffect) {
305
+ this.options.reverteffect(this.element,
306
+ this.currentTop()-this.originalTop,
307
+ this.currentLeft()-this.originalLeft);
308
+ } else {
309
+ this.originalLeft = this.currentLeft();
310
+ this.originalTop = this.currentTop();
311
+ }
312
+ this.element.style.zIndex = this.originalZ;
313
+
314
+ if(this.options.endeffect)
315
+ this.options.endeffect(this.element);
316
+
317
+ Droppables.reset();
318
+ Event.stop(event);
319
+ }
320
+ this.active = false;
321
+ this.dragging = false;
322
+ },
323
+ draw: function(event) {
324
+ var style = this.element.style;
325
+ this.originalX = this.element.offsetLeft - this.currentLeft() - this.originalLeft;
326
+ this.originalY = this.element.offsetTop - this.currentTop() - this.originalTop;
327
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
328
+ style.left = ((event.clientX - this.originalX) - this.offsetX) + "px";
329
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
330
+ style.top = ((event.clientY - this.originalY) - this.offsetY) + "px";
331
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
332
+ },
333
+ update: function(event) {
334
+ if(this.active) {
335
+ if(!this.dragging) {
336
+ var style = this.element.style;
337
+ this.dragging = true;
338
+ if(style.position=="") style.position = "relative";
339
+ style.zIndex = this.options.zindex;
340
+ Draggables.notify('onStart', this);
341
+ if(this.options.starteffect) this.options.starteffect(this.element);
342
+ }
343
+
344
+ Droppables.show(event, this.element);
345
+ this.draw(event);
346
+ if(this.options.change) this.options.change(this);
347
+
348
+ // fix AppleWebKit rendering
349
+ if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
350
+
351
+ Event.stop(event);
352
+ }
353
+ }
354
+ }
355
+
356
+ /*--------------------------------------------------------------------------*/
357
+
358
+ SortableObserver = Class.create();
359
+ SortableObserver.prototype = {
360
+ initialize: function(element, observer) {
361
+ this.element = $(element);
362
+ this.observer = observer;
363
+ this.lastValue = Sortable.serialize(this.element);
364
+ },
365
+ onStart: function() {
366
+ this.lastValue = Sortable.serialize(this.element);
367
+ },
368
+ onEnd: function() {
369
+ if(this.lastValue != Sortable.serialize(this.element))
370
+ this.observer(this.element)
371
+ }
372
+ }
373
+
374
+ Sortable = {
375
+ create: function(element) {
376
+ var element = $(element);
377
+ var options = {
378
+ tag: 'li', // assumes li children, override with tag: 'tagname'
379
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
380
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
381
+ containment: element, // also takes array of elements (or id's); or false
382
+ handle: false, // or a CSS class
383
+ only: false,
384
+ hoverclass: null,
385
+ onChange: function() {},
386
+ onUpdate: function() {}
387
+ }.extend(arguments[1] || {});
388
+ element.sortable = options;
389
+
390
+ // build options for the draggables
391
+ var options_for_draggable = {
392
+ revert: true,
393
+ constraint: options.constraint,
394
+ handle: handle };
395
+ if(options.starteffect)
396
+ options_for_draggable.starteffect = options.starteffect;
397
+ if(options.reverteffect)
398
+ options_for_draggable.reverteffect = options.reverteffect;
399
+ if(options.endeffect)
400
+ options_for_draggable.endeffect = options.endeffect;
401
+ if(options.zindex)
402
+ options_for_draggable.zindex = options.zindex;
403
+
404
+ // build options for the droppables
405
+ var options_for_droppable = {
406
+ overlap: options.overlap,
407
+ containment: options.containment,
408
+ hoverclass: options.hoverclass,
409
+ onHover: function(element, dropon, overlap) {
410
+ if(overlap>0.5) {
411
+ if(dropon.previousSibling != element) {
412
+ var oldParentNode = element.parentNode;
413
+ element.style.visibility = "hidden"; // fix gecko rendering
414
+ dropon.parentNode.insertBefore(element, dropon);
415
+ if(dropon.parentNode!=oldParentNode && oldParentNode.sortable)
416
+ oldParentNode.sortable.onChange(element);
417
+ if(dropon.parentNode.sortable)
418
+ dropon.parentNode.sortable.onChange(element);
419
+ }
420
+ } else {
421
+ var nextElement = dropon.nextSibling || null;
422
+ if(nextElement != element) {
423
+ var oldParentNode = element.parentNode;
424
+ element.style.visibility = "hidden"; // fix gecko rendering
425
+ dropon.parentNode.insertBefore(element, nextElement);
426
+ if(dropon.parentNode!=oldParentNode && oldParentNode.sortable)
427
+ oldParentNode.sortable.onChange(element);
428
+ if(dropon.parentNode.sortable)
429
+ dropon.parentNode.sortable.onChange(element);
430
+ }
431
+ }
432
+ }
433
+ }
434
+
435
+ // fix for gecko engine
436
+ Element.cleanWhitespace(element);
437
+
438
+ // for onupdate
439
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
440
+
441
+ // make it so
442
+ var elements = element.childNodes;
443
+ for (var i = 0; i < elements.length; i++)
444
+ if(elements[i].tagName && elements[i].tagName==options.tag.toUpperCase() &&
445
+ (!options.only || (Element.Class.has(elements[i], options.only)))) {
446
+
447
+ // handles are per-draggable
448
+ var handle = options.handle ?
449
+ Element.Class.childrenWith(elements[i], options.handle)[0] : elements[i];
450
+
451
+ new Draggable(elements[i], options_for_draggable.extend({ handle: handle }));
452
+ Droppables.add(elements[i], options_for_droppable);
453
+ }
454
+
455
+ },
456
+ serialize: function(element) {
457
+ var element = $(element);
458
+ var options = {
459
+ tag: element.sortable.tag,
460
+ only: element.sortable.only,
461
+ name: element.id
462
+ }.extend(arguments[1] || {});
463
+
464
+ var items = $(element).childNodes;
465
+ var queryComponents = new Array();
466
+
467
+ for(var i=0; i<items.length; i++)
468
+ if(items[i].tagName && items[i].tagName==options.tag.toUpperCase() &&
469
+ (!options.only || (Element.Class.has(items[i], options.only))))
470
+ queryComponents.push(
471
+ encodeURIComponent(options.name) + "[]=" +
472
+ encodeURIComponent(items[i].id.split("_")[1]));
473
+
474
+ return queryComponents.join("&");
475
+ }
476
+ }