jquery-treeview-rails 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,11 @@
1
+ Add jquery-treeview (http://bassistance.de/jquery-plugins/jquery-plugin-treeview/) to your rails app.
2
+
3
+ Requires Rails 3.1.
4
+
5
+ To install:
6
+
7
+ 1. Add to your Gemfile, in the :assets group:
8
+ gem "jquery-treeview-rails", :git => 'git@github.com:kclair/jquery-treeview-rails.git'
9
+
10
+ 2. Add to your application.js file:
11
+ //= require jquery_treeview
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../lib/jquery_treeview/rails/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "jquery-treeview-rails"
5
+ s.version = JqueryTreeview::Rails::VERSION
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Kristina Clair"]
8
+ s.email = ["kclair@pickledradish.com"]
9
+ s.homepage = "https://github.com/kclair/jquery-treeview-rails"
10
+ s.summary = "Use the jQuery Treeview plugin with Rails 3.1"
11
+ s.description = "This gem provides the jQuery plugin jquery-treeview for your Rails 3.1 application."
12
+
13
+ s.required_rubygems_version = ">= 1.3.6"
14
+
15
+ s.add_dependency "railties", "~> 3.0"
16
+ s.add_development_dependency "bundler", "~> 1.0.0"
17
+ s.add_development_dependency "rails", "~> 3.1"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.executables = `git ls-files`.split("\n").select{|f| f =~ /^bin/}
21
+ s.require_path = 'lib'
22
+ end
@@ -0,0 +1 @@
1
+ require 'jquery_treeview/rails'
@@ -0,0 +1,6 @@
1
+ module JqueryTreeview
2
+ module Rails
3
+ require 'jquery_treeview/rails/version.rb'
4
+ require 'jquery_treeview/rails/engine.rb'
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ # Configure Rails 3.1
2
+ module JqueryTreeview
3
+ module Rails
4
+ class Engine < ::Rails::Engine
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module JqueryTreeview
2
+ module Rails
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,110 @@
1
+ /*
2
+ * Async Treeview 0.1 - Lazy-loading extension for Treeview
3
+ *
4
+ * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
5
+ *
6
+ * Copyright (c) 2007 Jörn Zaefferer
7
+ *
8
+ * Dual licensed under the MIT and GPL licenses:
9
+ * http://www.opensource.org/licenses/mit-license.php
10
+ * http://www.gnu.org/licenses/gpl.html
11
+ *
12
+ * Revision: $Id$
13
+ *
14
+ */
15
+
16
+ ;(function($) {
17
+
18
+ function load(settings, root, child, container) {
19
+ function createNode(parent) {
20
+ var current = $("<li/>").attr("id", this.id || "").html("<span>" + this.text + "</span>").appendTo(parent);
21
+ if (this.classes) {
22
+ current.children("span").addClass(this.classes);
23
+ }
24
+ if (this.expanded) {
25
+ current.addClass("open");
26
+ }
27
+ if (this.hasChildren || this.children && this.children.length) {
28
+ var branch = $("<ul/>").appendTo(current);
29
+ if (this.hasChildren) {
30
+ current.addClass("hasChildren");
31
+ createNode.call({
32
+ classes: "placeholder",
33
+ text: "&nbsp;",
34
+ children:[]
35
+ }, branch);
36
+ }
37
+ if (this.children && this.children.length) {
38
+ $.each(this.children, createNode, [branch])
39
+ }
40
+ }
41
+ }
42
+ $.ajax($.extend(true, {
43
+ url: settings.url,
44
+ dataType: "json",
45
+ data: {
46
+ root: root
47
+ },
48
+ success: function(response) {
49
+ child.empty();
50
+ $.each(response, createNode, [child]);
51
+ $(container).treeview({add: child});
52
+ }
53
+ }, settings.ajax));
54
+ /*
55
+ $.getJSON(settings.url, {root: root}, function(response) {
56
+ function createNode(parent) {
57
+ var current = $("<li/>").attr("id", this.id || "").html("<span>" + this.text + "</span>").appendTo(parent);
58
+ if (this.classes) {
59
+ current.children("span").addClass(this.classes);
60
+ }
61
+ if (this.expanded) {
62
+ current.addClass("open");
63
+ }
64
+ if (this.hasChildren || this.children && this.children.length) {
65
+ var branch = $("<ul/>").appendTo(current);
66
+ if (this.hasChildren) {
67
+ current.addClass("hasChildren");
68
+ createNode.call({
69
+ classes: "placeholder",
70
+ text: "&nbsp;",
71
+ children:[]
72
+ }, branch);
73
+ }
74
+ if (this.children && this.children.length) {
75
+ $.each(this.children, createNode, [branch])
76
+ }
77
+ }
78
+ }
79
+ child.empty();
80
+ $.each(response, createNode, [child]);
81
+ $(container).treeview({add: child});
82
+ });
83
+ */
84
+ }
85
+
86
+ var proxied = $.fn.treeview;
87
+ $.fn.treeview = function(settings) {
88
+ if (!settings.url) {
89
+ return proxied.apply(this, arguments);
90
+ }
91
+ var container = this;
92
+ if (!container.children().size())
93
+ load(settings, "source", this, container);
94
+ var userToggle = settings.toggle;
95
+ return proxied.call(this, $.extend({}, settings, {
96
+ collapsed: true,
97
+ toggle: function() {
98
+ var $this = $(this);
99
+ if ($this.hasClass("hasChildren")) {
100
+ var childList = $this.removeClass("hasChildren").find("ul");
101
+ load(settings, this.id, childList, container);
102
+ }
103
+ if (userToggle) {
104
+ userToggle.apply(this, arguments);
105
+ }
106
+ }
107
+ }));
108
+ };
109
+
110
+ })(jQuery);
@@ -0,0 +1,37 @@
1
+ (function($) {
2
+ var CLASSES = $.treeview.classes;
3
+ var proxied = $.fn.treeview;
4
+ $.fn.treeview = function(settings) {
5
+ settings = $.extend({}, settings);
6
+ if (settings.add) {
7
+ return this.trigger("add", [settings.add]);
8
+ }
9
+ if (settings.remove) {
10
+ return this.trigger("remove", [settings.remove]);
11
+ }
12
+ return proxied.apply(this, arguments).bind("add", function(event, branches) {
13
+ $(branches).prev()
14
+ .removeClass(CLASSES.last)
15
+ .removeClass(CLASSES.lastCollapsable)
16
+ .removeClass(CLASSES.lastExpandable)
17
+ .find(">.hitarea")
18
+ .removeClass(CLASSES.lastCollapsableHitarea)
19
+ .removeClass(CLASSES.lastExpandableHitarea);
20
+ $(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, $(this).data("toggler"));
21
+ }).bind("remove", function(event, branches) {
22
+ var prev = $(branches).prev();
23
+ var parent = $(branches).parent();
24
+ $(branches).remove();
25
+ prev.filter(":last-child").addClass(CLASSES.last)
26
+ .filter("." + CLASSES.expandable).replaceClass(CLASSES.last, CLASSES.lastExpandable).end()
27
+ .find(">.hitarea").replaceClass(CLASSES.expandableHitarea, CLASSES.lastExpandableHitarea).end()
28
+ .filter("." + CLASSES.collapsable).replaceClass(CLASSES.last, CLASSES.lastCollapsable).end()
29
+ .find(">.hitarea").replaceClass(CLASSES.collapsableHitarea, CLASSES.lastCollapsableHitarea);
30
+ if (parent.is(":not(:has(>))") && parent[0] != this) {
31
+ parent.parent().removeClass(CLASSES.collapsable).removeClass(CLASSES.expandable)
32
+ parent.siblings(".hitarea").andSelf().remove();
33
+ }
34
+ });
35
+ };
36
+
37
+ })(jQuery);
@@ -0,0 +1,378 @@
1
+ /*
2
+ * jQuery UI Sortable
3
+ *
4
+ * Copyright (c) 2008 Paul Bakaus
5
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
6
+ * and GPL (GPL-LICENSE.txt) licenses.
7
+ *
8
+ * http://docs.jquery.com/UI/Sortables
9
+ *
10
+ * Depends:
11
+ * ui.base.js
12
+ *
13
+ * Revision: $Id: ui.sortable.js 5262 2008-04-17 13:13:51Z paul.bakaus $
14
+ */
15
+ ;(function($) {
16
+
17
+ if (window.Node && Node.prototype && !Node.prototype.contains) {
18
+ Node.prototype.contains = function (arg) {
19
+ return !!(this.compareDocumentPosition(arg) & 16);
20
+ };
21
+ }
22
+
23
+
24
+ $.widget("ui.sortableTree", $.extend($.ui.mouse, {
25
+ init: function() {
26
+
27
+ //Initialize needed constants
28
+ var self = this, o = this.options;
29
+ this.containerCache = {};
30
+ this.element.addClass("ui-sortableTree");
31
+
32
+ //Get the items
33
+ this.refresh();
34
+
35
+ //Let's determine the parent's offset
36
+ if(!(/(relative|absolute|fixed)/).test(this.element.css('position'))) this.element.css('position', 'relative');
37
+ this.offset = this.element.offset();
38
+
39
+ //Initialize mouse events for interaction
40
+ this.mouseInit();
41
+
42
+ //Prepare cursorAt
43
+ if(o.cursorAt && o.cursorAt.constructor == Array)
44
+ o.cursorAt = { left: o.cursorAt[0], top: o.cursorAt[1] };
45
+
46
+ },
47
+ plugins: {},
48
+ ui: function(inst) {
49
+ return {
50
+ helper: (inst || this)["helper"],
51
+ position: (inst || this)["position"].current,
52
+ absolutePosition: (inst || this)["position"].absolute,
53
+ instance: this,
54
+ options: this.options,
55
+ element: this.element,
56
+ item: (inst || this)["currentItem"],
57
+ sender: inst ? inst.element : null
58
+ };
59
+ },
60
+ propagate: function(n,e,inst) {
61
+ $.ui.plugin.call(this, n, [e, this.ui(inst)]);
62
+ this.element.triggerHandler(n == "sort" ? n : "sort"+n, [e, this.ui(inst)], this.options[n]);
63
+ },
64
+ serialize: function(o) {
65
+
66
+ var items = $(this.options.items, this.element).not('.ui-sortableTree-helper'); //Only the items of the sortable itself
67
+ var str = []; o = o || {};
68
+
69
+ items.each(function() {
70
+ var res = ($(this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
71
+ if(res) str.push((o.key || res[1])+'[]='+(o.key ? res[1] : res[2]));
72
+ });
73
+
74
+ return str.join('&');
75
+
76
+ },
77
+ toArray: function(attr) {
78
+ var items = $(this.options.items, this.element).not('.ui-sortableTree-helper'); //Only the items of the sortable itself
79
+ var ret = [];
80
+
81
+ items.each(function() { ret.push($(this).attr(attr || 'id')); });
82
+ return ret;
83
+ },
84
+ enable: function() {
85
+ this.element.removeClass("ui-sortableTree-disabled");
86
+ this.options.disabled = false;
87
+ },
88
+ disable: function() {
89
+ this.element.addClass("ui-sortableTree-disabled");
90
+ this.options.disabled = true;
91
+ },
92
+ /* Be careful with the following core functions */
93
+ intersectsWith: function(item) {
94
+
95
+ var x1 = this.position.absolute.left - 10, x2 = x1 + 10,
96
+ y1 = this.position.absolute.top - 10, y2 = y1 + 10;
97
+ var l = item.left, r = l + item.width,
98
+ t = item.top, b = t + item.height;
99
+
100
+ return ( l < x1 + (this.helperProportions.width / 2) // Right Half
101
+ && x2 - (this.helperProportions.width / 2) < r // Left Half
102
+ && t < y1 + (this.helperProportions.height / 2) // Bottom Half
103
+ && y2 - (this.helperProportions.height / 2) < b ); // Top Half
104
+
105
+ },
106
+ intersectsWithEdge: function(item) {
107
+ var y1 = this.position.absolute.top - 10, y2 = y1 + 10;
108
+ var t = item.top, b = t + item.height;
109
+
110
+ if(!this.intersectsWith(item.item.parents(".ui-sortableTree").data("sortableTree").containerCache)) return false;
111
+
112
+ if (!( t < y1 + (this.helperProportions.height / 2) // Bottom Half
113
+ && y2 - (this.helperProportions.height / 2) < b )) return false; // Top Half
114
+
115
+ if(y2 > t && y1 < t) return 1; //Crosses top edge
116
+ if(y1 < b && y2 > b) return 2; //Crosses bottom edge
117
+
118
+ return false;
119
+
120
+ },
121
+ refresh: function() {
122
+ this.refreshItems();
123
+ this.refreshPositions();
124
+ },
125
+ refreshItems: function() {
126
+
127
+ this.items = [];
128
+ this.containers = [this];
129
+ var items = this.items;
130
+ var queries = [$(this.options.items, this.element)];
131
+
132
+ if(this.options.connectWith) {
133
+ for (var i = this.options.connectWith.length - 1; i >= 0; i--){
134
+ var cur = $(this.options.connectWith[i]);
135
+ for (var j = cur.length - 1; j >= 0; j--){
136
+ var inst = $.data(cur[j], 'sortableTree');
137
+ if(inst && !inst.options.disabled) {
138
+ queries.push($(inst.options.items, inst.element));
139
+ this.containers.push(inst);
140
+ }
141
+ };
142
+ };
143
+ }
144
+
145
+ for (var i = queries.length - 1; i >= 0; i--){
146
+ queries[i].each(function() {
147
+ $.data(this, 'sortableTree-item', true); // Data for target checking (mouse manager)
148
+ items.push({
149
+ item: $(this),
150
+ width: 0, height: 0,
151
+ left: 0, top: 0
152
+ });
153
+ });
154
+ };
155
+
156
+ },
157
+ refreshPositions: function(fast) {
158
+ for (var i = this.items.length - 1; i >= 0; i--){
159
+ if(!fast) this.items[i].height = this.items[i].item.outerHeight();
160
+ this.items[i].top = this.items[i].item.offset().top;
161
+ };
162
+ for (var i = this.containers.length - 1; i >= 0; i--){
163
+ var p =this.containers[i].element.offset();
164
+ this.containers[i].containerCache.left = p.left;
165
+ this.containers[i].containerCache.top = p.top;
166
+ this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
167
+ this.containers[i].containerCache.height= this.containers[i].element.outerHeight();
168
+ };
169
+ },
170
+ destroy: function() {
171
+
172
+ this.element
173
+ .removeClass("ui-sortableTree ui-sortableTree-disabled")
174
+ .removeData("sortableTree")
175
+ .unbind(".sortableTree");
176
+ this.mouseDestroy();
177
+
178
+ for ( var i = this.items.length - 1; i >= 0; i-- )
179
+ this.items[i].item.removeData("sortableTree-item");
180
+
181
+ },
182
+ contactContainers: function(e) {
183
+ for (var i = this.containers.length - 1; i >= 0; i--){
184
+
185
+ if(this.intersectsWith(this.containers[i].containerCache)) {
186
+ if(!this.containers[i].containerCache.over) {
187
+
188
+ if(this.currentContainer != this.containers[i]) {
189
+
190
+ //When entering a new container, we will find the item with the least distance and append our item near it
191
+ var dist = 10000; var itemWithLeastDistance = null; var base = this.position.absolute.top;
192
+ for (var j = this.items.length - 1; j >= 0; j--) {
193
+ if(!this.containers[i].element[0].contains(this.items[j].item[0])) continue;
194
+ var cur = this.items[j].top;
195
+ if(Math.abs(cur - base) < dist) {
196
+ dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
197
+ }
198
+ }
199
+
200
+ itemWithLeastDistance ? this.rearrange(e, itemWithLeastDistance) : this.rearrange(e, null, this.containers[i].element);
201
+ this.propagate("change", e); //Call plugins and callbacks
202
+ this.containers[i].propagate("change", e, this); //Call plugins and callbacks
203
+ this.currentContainer = this.containers[i];
204
+
205
+ }
206
+
207
+ this.containers[i].propagate("over", e, this);
208
+ this.containers[i].containerCache.over = 1;
209
+ }
210
+ } else {
211
+ if(this.containers[i].containerCache.over) {
212
+ this.containers[i].propagate("out", e, this);
213
+ this.containers[i].containerCache.over = 0;
214
+ }
215
+ }
216
+
217
+ };
218
+ },
219
+ mouseStart: function(e,el) {
220
+
221
+ if(this.options.disabled || this.options.type == 'static') return false;
222
+
223
+ //Find out if the clicked node (or one of its parents) is a actual item in this.items
224
+ var currentItem = null, nodes = $(e.target).parents().each(function() {
225
+ if($.data(this, 'sortableTree-item')) {
226
+ currentItem = $(this);
227
+ return false;
228
+ }
229
+ });
230
+ if($.data(e.target, 'sortableTree-item')) currentItem = $(e.target);
231
+
232
+ if(!currentItem) return false;
233
+ if(this.options.handle) {
234
+ var validHandle = false;
235
+ $(this.options.handle, currentItem).each(function() { if(this == e.target) validHandle = true; });
236
+ if(!validHandle) return false;
237
+ }
238
+
239
+ this.currentItem = currentItem;
240
+
241
+ var o = this.options;
242
+ this.currentContainer = this;
243
+ this.refresh();
244
+
245
+ //Create and append the visible helper
246
+ this.helper = typeof o.helper == 'function' ? $(o.helper.apply(this.element[0], [e, this.currentItem])) : this.currentItem.clone();
247
+ if(!this.helper.parents('body').length) this.helper.appendTo("body"); //Add the helper to the DOM if that didn't happen already
248
+ this.helper.css({ position: 'absolute', clear: 'both' }).addClass('ui-sortableTree-helper'); //Position it absolutely and add a helper class
249
+
250
+ //Prepare variables for position generation
251
+ $.extend(this, {
252
+ offsetParent: this.helper.offsetParent(),
253
+ offsets: { absolute: this.currentItem.offset() }
254
+ });
255
+
256
+ //Save the first time position
257
+ $.extend(this, {
258
+ position: {
259
+ current: { left: e.pageX, top: e.pageY },
260
+ absolute: { left: e.pageX, top: e.pageY },
261
+ dom: this.currentItem.prev()[0]
262
+ },
263
+ clickOffset: { left: -5, top: -5 }
264
+ });
265
+
266
+ this.propagate("start", e); //Call plugins and callbacks
267
+ this.helperProportions = { width: this.helper.outerWidth(), height: this.helper.outerHeight() }; //Save and store the helper proportions
268
+
269
+ for (var i = this.containers.length - 1; i >= 0; i--) {
270
+ this.containers[i].propagate("activate", e, this);
271
+ } //Post 'activate' events to possible containers
272
+
273
+ //Prepare possible droppables
274
+ if($.ui.ddmanager) $.ui.ddmanager.current = this;
275
+ if ($.ui.ddmanager && !o.dropBehaviour) $.ui.ddmanager.prepareOffsets(this, e);
276
+
277
+ this.dragging = true;
278
+ return true;
279
+
280
+ },
281
+ mouseStop: function(e) {
282
+
283
+ if(this.newPositionAt) this.options.sortIndication.remove.call(this.currentItem, this.newPositionAt); //remove sort indicator
284
+ this.propagate("stop", e); //Call plugins and trigger callbacks
285
+
286
+ //If we are using droppables, inform the manager about the drop
287
+ var dropped = ($.ui.ddmanager && !this.options.dropBehaviour) ? $.ui.ddmanager.drop(this, e) : false;
288
+ if(!dropped && this.newPositionAt) this.newPositionAt[this.direction == 'down' ? 'before' : 'after'](this.currentItem); //Append to element to its new position
289
+
290
+ if(this.position.dom != this.currentItem.prev()[0]) this.propagate("update", e); //Trigger update callback if the DOM position has changed
291
+ if(!this.element[0].contains(this.currentItem[0])) { //Node was moved out of the current element
292
+ this.propagate("remove", e);
293
+ for (var i = this.containers.length - 1; i >= 0; i--){
294
+ if(this.containers[i].element[0].contains(this.currentItem[0])) {
295
+ this.containers[i].propagate("update", e, this);
296
+ this.containers[i].propagate("receive", e, this);
297
+ }
298
+ };
299
+ };
300
+
301
+ //Post events to containers
302
+ for (var i = this.containers.length - 1; i >= 0; i--){
303
+ this.containers[i].propagate("deactivate", e, this);
304
+ if(this.containers[i].containerCache.over) {
305
+ this.containers[i].propagate("out", e, this);
306
+ this.containers[i].containerCache.over = 0;
307
+ }
308
+ }
309
+
310
+ this.dragging = false;
311
+ if(this.cancelHelperRemoval) return false;
312
+ this.helper.remove();
313
+
314
+ return false;
315
+
316
+ },
317
+ mouseDrag: function(e) {
318
+
319
+ //Compute the helpers position
320
+ this.position.current = { top: e.pageY + 5, left: e.pageX + 5 };
321
+ this.position.absolute = { left: e.pageX + 5, top: e.pageY + 5 };
322
+
323
+ //Interconnect with droppables
324
+ if($.ui.ddmanager) $.ui.ddmanager.drag(this, e);
325
+ var intersectsWithDroppable = false;
326
+ $.each($.ui.ddmanager.droppables, function() {
327
+ if(this.isover) intersectsWithDroppable = true;
328
+ });
329
+
330
+ //Rearrange
331
+ if(intersectsWithDroppable) {
332
+ if(this.newPositionAt) this.options.sortIndication.remove.call(this.currentItem, this.newPositionAt);
333
+ } else {
334
+ for (var i = this.items.length - 1; i >= 0; i--) {
335
+
336
+ if(this.currentItem[0].contains(this.items[i].item[0])) continue;
337
+
338
+ var intersection = this.intersectsWithEdge(this.items[i]);
339
+ if(!intersection) continue;
340
+
341
+ this.direction = intersection == 1 ? "down" : "up";
342
+ this.rearrange(e, this.items[i]);
343
+ this.propagate("change", e); //Call plugins and callbacks
344
+ break;
345
+ }
346
+ }
347
+
348
+ //Post events to containers
349
+ this.contactContainers(e);
350
+
351
+ this.propagate("sort", e); //Call plugins and callbacks
352
+ this.helper.css({ left: this.position.current.left+'px', top: this.position.current.top+'px' }); // Stick the helper to the cursor
353
+ return false;
354
+
355
+ },
356
+ rearrange: function(e, i, a) {
357
+ if(i) {
358
+ if(this.newPositionAt) this.options.sortIndication.remove.call(this.currentItem, this.newPositionAt);
359
+ this.newPositionAt = i.item;
360
+ this.options.sortIndication[this.direction].call(this.currentItem, this.newPositionAt);
361
+ } else {
362
+ //Append
363
+ }
364
+ }
365
+ }));
366
+
367
+ $.extend($.ui.sortableTree, {
368
+ defaults: {
369
+ items: '> *',
370
+ zIndex: 1000,
371
+ distance: 1
372
+ },
373
+ getter: "serialize toArray"
374
+ });
375
+
376
+
377
+
378
+ })(jQuery);
@@ -0,0 +1,256 @@
1
+ /*
2
+ * Treeview 1.5pre - jQuery plugin to hide and show branches of a tree
3
+ *
4
+ * http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
5
+ * http://docs.jquery.com/Plugins/Treeview
6
+ *
7
+ * Copyright (c) 2007 Jörn Zaefferer
8
+ *
9
+ * Dual licensed under the MIT and GPL licenses:
10
+ * http://www.opensource.org/licenses/mit-license.php
11
+ * http://www.gnu.org/licenses/gpl.html
12
+ *
13
+ * Revision: $Id: jquery.treeview.js 5759 2008-07-01 07:50:28Z joern.zaefferer $
14
+ *
15
+ */
16
+
17
+ ;(function($) {
18
+
19
+ // TODO rewrite as a widget, removing all the extra plugins
20
+ $.extend($.fn, {
21
+ swapClass: function(c1, c2) {
22
+ var c1Elements = this.filter('.' + c1);
23
+ this.filter('.' + c2).removeClass(c2).addClass(c1);
24
+ c1Elements.removeClass(c1).addClass(c2);
25
+ return this;
26
+ },
27
+ replaceClass: function(c1, c2) {
28
+ return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
29
+ },
30
+ hoverClass: function(className) {
31
+ className = className || "hover";
32
+ return this.hover(function() {
33
+ $(this).addClass(className);
34
+ }, function() {
35
+ $(this).removeClass(className);
36
+ });
37
+ },
38
+ heightToggle: function(animated, callback) {
39
+ animated ?
40
+ this.animate({ height: "toggle" }, animated, callback) :
41
+ this.each(function(){
42
+ jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
43
+ if(callback)
44
+ callback.apply(this, arguments);
45
+ });
46
+ },
47
+ heightHide: function(animated, callback) {
48
+ if (animated) {
49
+ this.animate({ height: "hide" }, animated, callback);
50
+ } else {
51
+ this.hide();
52
+ if (callback)
53
+ this.each(callback);
54
+ }
55
+ },
56
+ prepareBranches: function(settings) {
57
+ if (!settings.prerendered) {
58
+ // mark last tree items
59
+ this.filter(":last-child:not(ul)").addClass(CLASSES.last);
60
+ // collapse whole tree, or only those marked as closed, anyway except those marked as open
61
+ this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
62
+ }
63
+ // return all items with sublists
64
+ return this.filter(":has(>ul)");
65
+ },
66
+ applyClasses: function(settings, toggler) {
67
+ // TODO use event delegation
68
+ this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) {
69
+ // don't handle click events on children, eg. checkboxes
70
+ if ( this == event.target )
71
+ toggler.apply($(this).next());
72
+ }).add( $("a", this) ).hoverClass();
73
+
74
+ if (!settings.prerendered) {
75
+ // handle closed ones first
76
+ this.filter(":has(>ul:hidden)")
77
+ .addClass(CLASSES.expandable)
78
+ .replaceClass(CLASSES.last, CLASSES.lastExpandable);
79
+
80
+ // handle open ones
81
+ this.not(":has(>ul:hidden)")
82
+ .addClass(CLASSES.collapsable)
83
+ .replaceClass(CLASSES.last, CLASSES.lastCollapsable);
84
+
85
+ // create hitarea if not present
86
+ var hitarea = this.find("div." + CLASSES.hitarea);
87
+ if (!hitarea.length)
88
+ hitarea = this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea);
89
+ hitarea.removeClass().addClass(CLASSES.hitarea).each(function() {
90
+ var classes = "";
91
+ $.each($(this).parent().attr("class").split(" "), function() {
92
+ classes += this + "-hitarea ";
93
+ });
94
+ $(this).addClass( classes );
95
+ })
96
+ }
97
+
98
+ // apply event to hitarea
99
+ this.find("div." + CLASSES.hitarea).click( toggler );
100
+ },
101
+ treeview: function(settings) {
102
+
103
+ settings = $.extend({
104
+ cookieId: "treeview"
105
+ }, settings);
106
+
107
+ if ( settings.toggle ) {
108
+ var callback = settings.toggle;
109
+ settings.toggle = function() {
110
+ return callback.apply($(this).parent()[0], arguments);
111
+ };
112
+ }
113
+
114
+ // factory for treecontroller
115
+ function treeController(tree, control) {
116
+ // factory for click handlers
117
+ function handler(filter) {
118
+ return function() {
119
+ // reuse toggle event handler, applying the elements to toggle
120
+ // start searching for all hitareas
121
+ toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
122
+ // for plain toggle, no filter is provided, otherwise we need to check the parent element
123
+ return filter ? $(this).parent("." + filter).length : true;
124
+ }) );
125
+ return false;
126
+ };
127
+ }
128
+ // click on first element to collapse tree
129
+ $("a:eq(0)", control).click( handler(CLASSES.collapsable) );
130
+ // click on second to expand tree
131
+ $("a:eq(1)", control).click( handler(CLASSES.expandable) );
132
+ // click on third to toggle tree
133
+ $("a:eq(2)", control).click( handler() );
134
+ }
135
+
136
+ // handle toggle event
137
+ function toggler() {
138
+ $(this)
139
+ .parent()
140
+ // swap classes for hitarea
141
+ .find(">.hitarea")
142
+ .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
143
+ .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
144
+ .end()
145
+ // swap classes for parent li
146
+ .swapClass( CLASSES.collapsable, CLASSES.expandable )
147
+ .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
148
+ // find child lists
149
+ .find( ">ul" )
150
+ // toggle them
151
+ .heightToggle( settings.animated, settings.toggle );
152
+ if ( settings.unique ) {
153
+ $(this).parent()
154
+ .siblings()
155
+ // swap classes for hitarea
156
+ .find(">.hitarea")
157
+ .replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
158
+ .replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
159
+ .end()
160
+ .replaceClass( CLASSES.collapsable, CLASSES.expandable )
161
+ .replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
162
+ .find( ">ul" )
163
+ .heightHide( settings.animated, settings.toggle );
164
+ }
165
+ }
166
+ this.data("toggler", toggler);
167
+
168
+ function serialize() {
169
+ function binary(arg) {
170
+ return arg ? 1 : 0;
171
+ }
172
+ var data = [];
173
+ branches.each(function(i, e) {
174
+ data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
175
+ });
176
+ $.cookie(settings.cookieId, data.join(""), settings.cookieOptions );
177
+ }
178
+
179
+ function deserialize() {
180
+ var stored = $.cookie(settings.cookieId);
181
+ if ( stored ) {
182
+ var data = stored.split("");
183
+ branches.each(function(i, e) {
184
+ $(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
185
+ });
186
+ }
187
+ }
188
+
189
+ // add treeview class to activate styles
190
+ this.addClass("treeview");
191
+
192
+ // prepare branches and find all tree items with child lists
193
+ var branches = this.find("li").prepareBranches(settings);
194
+
195
+ switch(settings.persist) {
196
+ case "cookie":
197
+ var toggleCallback = settings.toggle;
198
+ settings.toggle = function() {
199
+ serialize();
200
+ if (toggleCallback) {
201
+ toggleCallback.apply(this, arguments);
202
+ }
203
+ };
204
+ deserialize();
205
+ break;
206
+ case "location":
207
+ var current = this.find("a").filter(function() {
208
+ return this.href.toLowerCase() == location.href.toLowerCase();
209
+ });
210
+ if ( current.length ) {
211
+ // TODO update the open/closed classes
212
+ var items = current.addClass("selected").parents("ul, li").add( current.next() ).show();
213
+ if (settings.prerendered) {
214
+ // if prerendered is on, replicate the basic class swapping
215
+ items.filter("li")
216
+ .swapClass( CLASSES.collapsable, CLASSES.expandable )
217
+ .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
218
+ .find(">.hitarea")
219
+ .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
220
+ .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea );
221
+ }
222
+ }
223
+ break;
224
+ }
225
+
226
+ branches.applyClasses(settings, toggler);
227
+
228
+ // if control option is set, create the treecontroller and show it
229
+ if ( settings.control ) {
230
+ treeController(this, settings.control);
231
+ $(settings.control).show();
232
+ }
233
+
234
+ return this;
235
+ }
236
+ });
237
+
238
+ // classes used by the plugin
239
+ // need to be styled via external stylesheet, see first example
240
+ $.treeview = {};
241
+ var CLASSES = ($.treeview.classes = {
242
+ open: "open",
243
+ closed: "closed",
244
+ expandable: "expandable",
245
+ expandableHitarea: "expandable-hitarea",
246
+ lastExpandableHitarea: "lastExpandable-hitarea",
247
+ collapsable: "collapsable",
248
+ collapsableHitarea: "collapsable-hitarea",
249
+ lastCollapsableHitarea: "lastCollapsable-hitarea",
250
+ lastCollapsable: "lastCollapsable",
251
+ lastExpandable: "lastExpandable",
252
+ last: "last",
253
+ hitarea: "hitarea"
254
+ });
255
+
256
+ })(jQuery);
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Cookie plugin
3
+ *
4
+ * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
5
+ * Dual licensed under the MIT and GPL licenses:
6
+ * http://www.opensource.org/licenses/mit-license.php
7
+ * http://www.gnu.org/licenses/gpl.html
8
+ *
9
+ */
10
+
11
+ /**
12
+ * Create a cookie with the given name and value and other optional parameters.
13
+ *
14
+ * @example $.cookie('the_cookie', 'the_value');
15
+ * @desc Set the value of a cookie.
16
+ * @example $.cookie('the_cookie', 'the_value', {expires: 7, path: '/', domain: 'jquery.com', secure: true});
17
+ * @desc Create a cookie with all available options.
18
+ * @example $.cookie('the_cookie', 'the_value');
19
+ * @desc Create a session cookie.
20
+ * @example $.cookie('the_cookie', null);
21
+ * @desc Delete a cookie by passing null as value.
22
+ *
23
+ * @param String name The name of the cookie.
24
+ * @param String value The value of the cookie.
25
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
26
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
27
+ * If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
28
+ * If set to null or omitted, the cookie will be a session cookie and will not be retained
29
+ * when the the browser exits.
30
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
31
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
32
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
33
+ * require a secure protocol (like HTTPS).
34
+ * @type undefined
35
+ *
36
+ * @name $.cookie
37
+ * @cat Plugins/Cookie
38
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
39
+ */
40
+
41
+ /**
42
+ * Get the value of a cookie with the given name.
43
+ *
44
+ * @example $.cookie('the_cookie');
45
+ * @desc Get the value of a cookie.
46
+ *
47
+ * @param String name The name of the cookie.
48
+ * @return The value of the cookie.
49
+ * @type String
50
+ *
51
+ * @name $.cookie
52
+ * @cat Plugins/Cookie
53
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
54
+ */
55
+ jQuery.cookie = function(name, value, options) {
56
+ if (typeof value != 'undefined') { // name and value given, set cookie
57
+ options = options || {};
58
+ if (value === null) {
59
+ value = '';
60
+ options.expires = -1;
61
+ }
62
+ var expires = '';
63
+ if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
64
+ var date;
65
+ if (typeof options.expires == 'number') {
66
+ date = new Date();
67
+ date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
68
+ } else {
69
+ date = options.expires;
70
+ }
71
+ expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
72
+ }
73
+ var path = options.path ? '; path=' + options.path : '';
74
+ var domain = options.domain ? '; domain=' + options.domain : '';
75
+ var secure = options.secure ? '; secure' : '';
76
+ document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
77
+ } else { // only name given, get cookie
78
+ var cookieValue = null;
79
+ if (document.cookie && document.cookie != '') {
80
+ var cookies = document.cookie.split(';');
81
+ for (var i = 0; i < cookies.length; i++) {
82
+ var cookie = jQuery.trim(cookies[i]);
83
+ // Does this cookie string begin with the name we want?
84
+ if (cookie.substring(0, name.length + 1) == (name + '=')) {
85
+ cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
86
+ break;
87
+ }
88
+ }
89
+ }
90
+ return cookieValue;
91
+ }
92
+ };
@@ -0,0 +1,74 @@
1
+ .treeview, .treeview ul {
2
+ padding: 0;
3
+ margin: 0;
4
+ list-style: none;
5
+ }
6
+
7
+ .treeview ul {
8
+ background-color: white;
9
+ margin-top: 4px;
10
+ }
11
+
12
+ .treeview .hitarea {
13
+ background: url(assets/treeview-default.gif) -64px -25px no-repeat;
14
+ height: 16px;
15
+ width: 16px;
16
+ margin-left: -16px;
17
+ float: left;
18
+ cursor: pointer;
19
+ }
20
+ /* fix for IE6 */
21
+ * html .hitarea {
22
+ display: inline;
23
+ float:none;
24
+ }
25
+
26
+ .treeview li {
27
+ margin: 0;
28
+ padding: 3px 0pt 3px 16px;
29
+ }
30
+
31
+ .treeview a.selected {
32
+ background-color: #eee;
33
+ }
34
+
35
+ #treecontrol { margin: 1em 0; display: none; }
36
+
37
+ .treeview .hover { color: red; cursor: pointer; }
38
+
39
+ .treeview li { background: url(assets/treeview-default-line.gif) 0 0 no-repeat; }
40
+ .treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; }
41
+
42
+ .treeview .expandable-hitarea { background-position: -80px -3px; }
43
+
44
+ .treeview li.last { background-position: 0 -1766px }
45
+ .treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(assets/treeview-default.gif); }
46
+ .treeview li.lastCollapsable { background-position: 0 -111px }
47
+ .treeview li.lastExpandable { background-position: -32px -67px }
48
+
49
+ .treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea { background-position: 0; }
50
+
51
+ .treeview-red li { background-image: url(assets/treeview-red-line.gif); }
52
+ .treeview-red .hitarea, .treeview-red li.lastCollapsable, .treeview-red li.lastExpandable { background-image: url(images/treeview-red.gif); }
53
+
54
+ .treeview-black li { background-image: url(assets/treeview-black-line.gif); }
55
+ .treeview-black .hitarea, .treeview-black li.lastCollapsable, .treeview-black li.lastExpandable { background-image: url(images/treeview-black.gif); }
56
+
57
+ .treeview-gray li { background-image: url(assets/treeview-gray-line.gif); }
58
+ .treeview-gray .hitarea, .treeview-gray li.lastCollapsable, .treeview-gray li.lastExpandable { background-image: url(images/treeview-gray.gif); }
59
+
60
+ .treeview-famfamfam li { background-image: url(assets/treeview-famfamfam-line.gif); }
61
+ .treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable { background-image: url(images/treeview-famfamfam.gif); }
62
+
63
+ .treeview .placeholder {
64
+ background: url(assets/ajax-loader.gif) 0 0 no-repeat;
65
+ height: 16px;
66
+ width: 16px;
67
+ display: block;
68
+ }
69
+
70
+ .filetree li { padding: 3px 0 2px 16px; }
71
+ .filetree span.folder, .filetree span.file { padding: 1px 0 1px 16px; display: block; }
72
+ .filetree span.folder { background: url(assets/folder.gif) 0 0 no-repeat; }
73
+ .filetree li.expandable span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; }
74
+ .filetree span.file { background: url(images/file.gif) 0 0 no-repeat; }
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jquery-treeview-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kristina Clair
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: railties
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: bundler
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 1.0.0
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.0.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: rails
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '3.1'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.1'
62
+ description: This gem provides the jQuery plugin jquery-treeview for your Rails 3.1
63
+ application.
64
+ email:
65
+ - kclair@pickledradish.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - README
71
+ - Rakefile
72
+ - jquery-treeview-rails.gemspec
73
+ - lib/jquery-treeview-rails.rb
74
+ - lib/jquery_treeview/rails.rb
75
+ - lib/jquery_treeview/rails/engine.rb
76
+ - lib/jquery_treeview/rails/version.rb
77
+ - vendor/assets/images/ajax-loader.gif
78
+ - vendor/assets/images/file.gif
79
+ - vendor/assets/images/folder-closed.gif
80
+ - vendor/assets/images/folder.gif
81
+ - vendor/assets/images/minus.gif
82
+ - vendor/assets/images/plus.gif
83
+ - vendor/assets/images/treeview-black-line.gif
84
+ - vendor/assets/images/treeview-black.gif
85
+ - vendor/assets/images/treeview-default-line.gif
86
+ - vendor/assets/images/treeview-default.gif
87
+ - vendor/assets/images/treeview-famfamfam-line.gif
88
+ - vendor/assets/images/treeview-famfamfam.gif
89
+ - vendor/assets/images/treeview-gray-line.gif
90
+ - vendor/assets/images/treeview-gray.gif
91
+ - vendor/assets/images/treeview-red-line.gif
92
+ - vendor/assets/images/treeview-red.gif
93
+ - vendor/assets/javascripts/jquery.treeview.async.js
94
+ - vendor/assets/javascripts/jquery.treeview.edit.js
95
+ - vendor/assets/javascripts/jquery.treeview.sortable.js
96
+ - vendor/assets/javascripts/jquery_treeview.js
97
+ - vendor/assets/javascripts/lib/jquery.cookie.js
98
+ - vendor/assets/stylesheets/jquery.treeview.css
99
+ homepage: https://github.com/kclair/jquery-treeview-rails
100
+ licenses: []
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: 1.3.6
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 1.8.24
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: Use the jQuery Treeview plugin with Rails 3.1
123
+ test_files: []