hobo_jquery 1.4.0.pre2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "documentation"]
2
+ path = documentation
3
+ url = git://github.com/bryanlarsen/hobo-jquery.git
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2006 Tom Locke
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1 @@
1
+ Uses jQuery to provide the javascript for the hobo_rapid plugin.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.4.0.pre2
@@ -0,0 +1,5 @@
1
+ module HoboJqueryHelper
2
+ def data_rapid(tag, options = {})
3
+ {tag => options}.to_json
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ name = File.basename( __FILE__, '.gemspec' )
2
+ version = File.read(File.expand_path('../VERSION', __FILE__)).strip
3
+ require 'date'
4
+
5
+ spec = Gem::Specification.new do |s|
6
+ s.name = "hobo_jquery"
7
+ s.summary = "JQuery support for Hobo"
8
+ s.description = "JQuery support for Hobo"
9
+ s.authors = ["Bryan Larsen"]
10
+ s.email = "bryan@larsen.st"
11
+ s.files = `git ls-files -x #{name}/* -z`.split("\0")
12
+ s.homepage = 'http://hobocentral.net'
13
+ s.version = version
14
+ s.date = Date.today.to_s
15
+
16
+ s.required_rubygems_version = ">= 1.3.6"
17
+ s.rdoc_options = ["--charset=UTF-8"]
18
+ s.require_paths = ["lib", "vendor", "taglibs"]
19
+
20
+ s.add_runtime_dependency('jquery-rails', ["~> 1.0"])
21
+ s.add_runtime_dependency('hobo', ["= #{version}"])
22
+
23
+ end
@@ -0,0 +1,6 @@
1
+ require 'hobo_jquery'
2
+ require 'rails'
3
+ module HoboJquery
4
+ class Railtie < Rails::Railtie
5
+ end
6
+ end
@@ -0,0 +1,11 @@
1
+ module HoboJquery
2
+ @@root = Pathname.new File.expand_path('../..', __FILE__)
3
+ def self.root; @@root; end
4
+
5
+ EDIT_LINK_BASE = "https://github.com/tablatom/hobo_tree_table/edit/master/hobo_jquery"
6
+
7
+ require 'hobo_jquery/railtie' if defined?(Rails)
8
+
9
+ class Engine < ::Rails::Engine
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ <!--
2
+ hobo_jquery
3
+ -->
4
+
5
+
6
+ <%# This tag must be placed at the bottom of the page. This is
7
+ typically done for you by the theme.
8
+ %>
9
+ <def tag="page-scripts">
10
+ <do param="default">
11
+ <% attributes.reverse_merge!(:data_rapid_page_data => {
12
+ 'form_auth_token' => { 'name' => request_forgery_protection_token, 'value' => form_authenticity_token},
13
+ 'hobo_parts' => part_contexts_storage_uncoded}.to_json,
14
+ :style => "display: none;") %>
15
+ <%= tag("span", deunderscore_attributes(attributes)) %>
16
+ </do>
17
+ </def>
18
+
@@ -0,0 +1,33 @@
1
+ /* a */
2
+ (function($) {
3
+ var methods = {
4
+ init: function(annotations) {
5
+ this.on('click', methods.click);
6
+ },
7
+
8
+ click: function() {
9
+ var that = $(this);
10
+ var options = that.data('rapid').a.ajax_attrs;
11
+ if(!options.message) options.message="Loading...";
12
+ var roptions = that.hjq('buildRequest', {
13
+ type: 'GET',
14
+ attrs: options
15
+ });
16
+ if(options.push_state) {
17
+ window.History.pushState(null, options.new_title || null, that.attr('href'));
18
+ };
19
+ $.ajax(that.attr('href'), roptions);
20
+ return false;
21
+ }
22
+ };
23
+ $.fn.hjq_a = function( method ) {
24
+
25
+ if ( methods[method] ) {
26
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
27
+ } else if ( typeof method === 'object' || ! method ) {
28
+ return methods.init.apply( this, arguments );
29
+ } else {
30
+ $.error( 'Method ' + method + ' does not exist on hjq_form' );
31
+ }
32
+ };
33
+ })( jQuery );
@@ -0,0 +1,44 @@
1
+ /* click_editor */
2
+ (function($) {
3
+ var methods = {
4
+ init: function(annotations) {
5
+ this.removeClass('hidden').click(methods.click);
6
+ this.next('.in-place-form').hide().on('blur', methods.blur).on('change', methods.change);
7
+ },
8
+
9
+ click: function(event) {
10
+ var that=$(this);
11
+ var annotations=that.data('rapid')['click-editor'];
12
+ that.hjq('hide', annotations.hide, function() {
13
+ that.next('.in-place-form').hjq('show', annotations.show, function() {
14
+ $(this).find('textarea,input[type=text]').focus();
15
+
16
+ });
17
+ });
18
+ },
19
+
20
+ blur: function(event) {
21
+ var formlet = $(this).closest('.in-place-form');
22
+ formlet.addClass('hidden');
23
+ formlet.prev('.in-place-edit').removeClass('hidden');
24
+ },
25
+
26
+ change: function(event) {
27
+ var formlet = $(this).closest('.in-place-form');
28
+ formlet.prev('.in-place-edit').text('saving...');
29
+ formlet.hjq_formlet('submit');
30
+ }
31
+ };
32
+
33
+ $.fn.hjq_click_editor = function( method ) {
34
+
35
+ if ( methods[method] ) {
36
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
37
+ } else if ( typeof method === 'object' || ! method ) {
38
+ return methods.init.apply( this, arguments );
39
+ } else {
40
+ $.error( 'Method ' + method + ' does not exist on hjq_click_editor' );
41
+ }
42
+ };
43
+
44
+ })( jQuery );
@@ -0,0 +1,43 @@
1
+ /* delete-button */
2
+ (function($) {
3
+ var methods = {
4
+ init: function(annotations) {
5
+ var that=this;
6
+ this.on('rapid:ajax:success.hjq_delete_button', function (ev, el) {
7
+ methods.remove.call(that, annotations, ev, el);
8
+ });
9
+ },
10
+
11
+ /* removes the element from the DOM, etc. Does not actually
12
+ * do the ajax delete call -- form.submit does that. */
13
+ remove: function(annotations, ev, el) {
14
+ if(!annotations) annotations=this.data('rapid')['delete_button'];
15
+ // select only top most elements
16
+ var selector = '[data-rapid-context="'+this.data('rapid-context')+'"]';
17
+ $(selector).not(selector+" "+selector).each(function() {
18
+ var that=$(this);
19
+ if(that.siblings().length==0) {
20
+ that.parents().each(function() {
21
+ var done=$(this).siblings(".empty-collection-message").hjq('show', annotations.show).length;
22
+ return !done;
23
+ })
24
+ }
25
+ that.hjq('hideAndRemove', annotations.hide);
26
+ });
27
+ return this;
28
+ }
29
+ };
30
+
31
+
32
+ $.fn.hjq_delete_button = function( method ) {
33
+
34
+ if ( methods[method] ) {
35
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
36
+ } else if ( typeof method === 'object' || ! method ) {
37
+ return methods.init.apply( this, arguments );
38
+ } else {
39
+ $.error( 'Method ' + method + ' does not exist on hjq_delete_button' );
40
+ }
41
+ };
42
+
43
+ })( jQuery );
@@ -0,0 +1,6 @@
1
+ /* filter_menu */
2
+ jQuery.fn.hjq_filter_menu = function(annotations) {
3
+ this.find('select').on('change', function() {
4
+ jQuery(this).parents('form').submit();
5
+ });
6
+ };
@@ -0,0 +1,64 @@
1
+ /* form */
2
+ (function($) {
3
+ var methods = {
4
+ init: function(annotations) {
5
+ $(this).on('submit', methods.submit);
6
+ },
7
+
8
+ // you should be able to call this externally:
9
+ // $(foo).hjq('submit'); It can be called on the form or any
10
+ // child of the form
11
+ submit: function () {
12
+ var form = $(this).closest("form");
13
+ if(form.length==0) return false;
14
+ var annotations = form.data('rapid').form;
15
+
16
+ var options = {type: form[0].method,
17
+ attrs: annotations.ajax_attrs,
18
+ };
19
+
20
+ if(form.attr('enctype') == 'multipart/form-data') {
21
+ if(form.ajaxSubmit) {
22
+ var roptions= form.hjq('buildRequest', $.extend(options, {preamble: '<textarea>', postamble: '</textarea>', content_type: 'text/html'}));
23
+
24
+ if(!roptions) return false;
25
+ roptions.iframe = true;
26
+ form.ajaxSubmit(roptions);
27
+ } else {
28
+ alert("malsup's jquery form plugin required to do ajax submissions of multipart forms");
29
+ }
30
+
31
+ } else {
32
+ var roptions= form.hjq('buildRequest', options);
33
+ if(!roptions) return false;
34
+
35
+ // make sure we don't serialize any nested formlets
36
+ var data = form.find(":input").
37
+ not(form.find(".formlet :input")).
38
+ serialize();
39
+
40
+ roptions.data = $.param(roptions.data) + "&" + data;
41
+
42
+ if (options.attrs.push_state) {
43
+ window.History.pushState(null, options.attrs.new_title || null, form[0].action+"?"+data);
44
+ }
45
+ $.ajax(form[0].action, roptions);
46
+ }
47
+
48
+ // prevent bubbling
49
+ return false;
50
+ }
51
+ };
52
+
53
+ $.fn.hjq_form = function( method ) {
54
+
55
+ if ( methods[method] ) {
56
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
57
+ } else if ( typeof method === 'object' || ! method ) {
58
+ return methods.init.apply( this, arguments );
59
+ } else {
60
+ $.error( 'Method ' + method + ' does not exist on hjq_form' );
61
+ }
62
+ };
63
+
64
+ })( jQuery );
@@ -0,0 +1,49 @@
1
+ /* formlet */
2
+ (function($) {
3
+ var methods = {
4
+ init: function(annotations) {
5
+ this.find('input[type=submit]').on('click', methods.submit);
6
+ },
7
+
8
+ // you should be able to call this externally:
9
+ // $(foo).hjq('submit'); It can be called on the formlet or any
10
+ // child of the formlet
11
+ submit: function(extra_callbacks, extra_options) {
12
+ var formlet = $(this).closest(".formlet");
13
+ if(formlet.length==0) return false;
14
+ var annotations = formlet.data('rapid').formlet;
15
+
16
+ // make sure we don't serialize any nested forms
17
+ var data = formlet.find(":input").
18
+ not(formlet.find("form :input")).
19
+ not(formlet.find(".formlet :input")).
20
+ serialize();
21
+
22
+ var roptions = formlet.hjq('buildRequest',
23
+ {type: annotations.form_attrs.method,
24
+ attrs: annotations.ajax_attrs,
25
+ extra_options: extra_options,
26
+ extra_callbacks: extra_callbacks
27
+ });
28
+ if(!roptions) return false;
29
+
30
+ roptions.data = $.param(roptions.data) + "&" + data;
31
+
32
+ $.ajax(annotations.form_attrs.action, roptions);
33
+
34
+ return false;
35
+ }
36
+ };
37
+
38
+ $.fn.hjq_formlet = function( method ) {
39
+
40
+ if ( methods[method] ) {
41
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
42
+ } else if ( typeof method === 'object' || ! method ) {
43
+ return methods.init.apply( this, arguments );
44
+ } else {
45
+ $.error( 'Method ' + method + ' does not exist on hjq_formlet' );
46
+ }
47
+ };
48
+
49
+ })( jQuery );
@@ -0,0 +1,15 @@
1
+ /* hot-input */
2
+ (function($) {
3
+ $.fn.hjq_hot_input = function(annotations) {
4
+ this.on(annotations.events, annotations.selector, function (event) {
5
+ var that=$(this);
6
+ var form=that.parents('form');
7
+ var roptions=that.hjq('buildRequest', {type: annotations.method, attrs: annotations.ajax_attrs});
8
+ var data = form.find(":input").not(form.find(".formlet :input")).serialize();
9
+ roptions.data = $.param(roptions.data) + "&" + data;
10
+ $.ajax(annotations.path, roptions);
11
+
12
+ return false;
13
+ });
14
+ }
15
+ })( jQuery );
@@ -0,0 +1,176 @@
1
+
2
+ if(!RegExp.escape) {
3
+ RegExp.escape = function(text) {
4
+ return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
5
+ };
6
+ }
7
+
8
+ /* input-many */
9
+ (function($) {
10
+ var methods = {
11
+ init: function (annotations) {
12
+ // disable all elements inside our template, and mark them so we can find them later.
13
+ this.find(".input-many-template :input:not([disabled])").each(function() {
14
+ this.disabled = true;
15
+ $(this).addClass("input_many_template_input");
16
+ });
17
+
18
+ // bind event handlers
19
+ this.find(".remove-item:not([disabled])").not(this.find(".input-many .add-item")).click(methods.removeOne);
20
+ this.find(".add-item:not([disabled])").not(this.find(".input-many .add-item")).click(methods.addOne);
21
+ },
22
+
23
+ addOne: function () {
24
+ var me = $(this).parent().parent();
25
+ var top = me.parent();
26
+ var template = top.children("li.input-many-template");
27
+ var clone = template.clone(true).removeClass("input-many-template");
28
+ var attrs = top.data('rapid')['input-many'];
29
+
30
+ // length-2 because ignore the template li and the empty li
31
+ var name_updater = methods.getNameUpdater.call(top, top.children().length-2, attrs['prefix']);
32
+
33
+ // enable previously marked elements
34
+ clone.find(".input_many_template_input").each(function() {
35
+ this.disabled = false;
36
+ $(this).removeClass("input_many_template_input");
37
+ });
38
+ clone.find(".remove-item:not([disabled])").not(clone.find(".input-many .add-item")).click(methods.removeOne);
39
+ clone.find(".add-item:not([disabled])").not(clone.find(".input-many .add-item")).click(methods.addOne);
40
+
41
+ // update id & name
42
+ clone.find("*").each(function() {
43
+ name_updater.call(this);
44
+ });
45
+ name_updater.call(clone.get(0));
46
+
47
+ // do the add with anim
48
+ clone.css("display", "none").insertAfter(me).hjq('show', attrs['show']);
49
+
50
+ // initialize subelements
51
+ me.next().hjq();
52
+
53
+ // visibility
54
+ if(me.hasClass("empty")) {
55
+ me.addClass("hidden");
56
+ me.find("input.empty-input").attr("disabled", true);
57
+ } else {
58
+ // now that we've added an element after us, we should only have a '-' button
59
+ me.children("div.buttons").children("button.remove-item").removeClass("hidden");
60
+ me.children("div.buttons").children("button.add-item").addClass("hidden");
61
+ }
62
+
63
+ me.hjq('createFunction', attrs.add_hook).call(me.get(0));
64
+ clone.trigger('rapid:add');
65
+ clone.trigger('rapid:change');
66
+
67
+ return false; // prevent bubbling
68
+ },
69
+
70
+ removeOne: function() {
71
+ var me = $(this).parent().parent();
72
+ var top = me.parent();
73
+ var attrs = top.data('rapid')['input-many'];
74
+
75
+ if(attrs.remove_hook) {
76
+ if(!me.hjq('createFunction', attrs.remove_hook).call(me.get(0))) {
77
+ return false;
78
+ };
79
+ }
80
+
81
+ var remove_evt=$.Event("rapid:remove");
82
+ me.trigger(remove_evt, [me]);
83
+ if(remove_evt.isPropagationStopped()) {
84
+ return false;
85
+ }
86
+
87
+ // rename everybody from me onwards
88
+ var i=methods.getIndex.call(me.get(0))
89
+ var n=me.next();
90
+ for(; n.length>0; i+=1, n=n.next()) {
91
+ var name_updater = methods.getNameUpdater.call(top, i, attrs['prefix']);
92
+ n.find("*").each(function() {
93
+ name_updater.call(this);
94
+ });
95
+ name_updater.call(n.get(0));
96
+ }
97
+
98
+ // adjust +/- buttons on the button element as appropriate
99
+ var last=top.children("li:last");
100
+ if(last.get(0)==me.get(0)) {
101
+ last = last.prev();
102
+ }
103
+
104
+ if(last.hasClass("empty")) {
105
+ last.removeClass("hidden");
106
+ last.find("input.empty-input").removeAttr("disabled");
107
+ } else {
108
+ // if we've reached the minimum, we don't want to add the '-' button
109
+ if(top.children().length-3 <= (attrs['minimum']||0)) {
110
+ last.children("div.buttons").children("button.remove-item").addClass("hidden");
111
+ } else {
112
+ last.children("div.buttons").children("button.remove-item").removeClass("hidden");
113
+ }
114
+ last.children("div.buttons").children("button.add-item").removeClass("hidden");
115
+ }
116
+
117
+ // remove with animation
118
+ me.hjq('hideAndRemove', attrs['hide']);
119
+
120
+ return false; //prevent bubbling
121
+ },
122
+
123
+ // given this==the input-many, returns a lambda that updates the name & id for an element
124
+ getNameUpdater: function(new_index, name_prefix) {
125
+ var id_prefix = name_prefix.replace(/\[/g, "_").replace(/\]/g, "");
126
+ var name_re = RegExp("^" + RegExp.escape(name_prefix)+ "\[\-?[0-9]+\]");
127
+ var name_sub = name_prefix + '[' + new_index.toString() + ']';
128
+ var id_re = RegExp("^" + RegExp.escape(id_prefix)+ "_\-?[0-9]+");
129
+ var id_sub = id_prefix + '_' + new_index.toString();
130
+ var class_re = RegExp(RegExp.escape(name_prefix)+ "\[\-?[0-9]+\]");
131
+ var class_sub = name_sub;
132
+
133
+ return function() {
134
+ if(this.name) {
135
+ this.name = this.name.replace(name_re, name_sub);
136
+ }
137
+ if (id_prefix==this.id.slice(0, id_prefix.length)) {
138
+ this.id = this.id.replace(id_re, id_sub);
139
+ } else {
140
+ // silly rails. text_area_tag and text_field_tag use different conventions for the id.
141
+ if(name_prefix==this.id.slice(0, name_prefix.length)) {
142
+ this.id = this.id.replace(name_re, name_sub);
143
+ } /* else {
144
+ hjq.util.log("hjq.input_many.update_id: id_prefix "+id_prefix+" didn't match input "+this.id);
145
+ } */
146
+ }
147
+ if (class_re.test(this.className)) {
148
+ this.className = this.className.replace(class_re, class_sub);
149
+ }
150
+ if(($(this).data('rapid') || {})['input-many']) {
151
+ var annos=$(this).data('rapid');
152
+ annos['input-many']['prefix'] = annos['input-many']['prefix'].replace(name_re, name_sub);
153
+ $(this).data('rapid', annos);
154
+ }
155
+ return this;
156
+ };
157
+ },
158
+
159
+ // given this==an input-many item, get the submit index
160
+ getIndex: function() {
161
+ return Number(this.id.match(/_([-0-9]+)$/)[1]);
162
+ }
163
+ };
164
+
165
+ $.fn.hjq_input_many = function( method ) {
166
+
167
+ if ( methods[method] ) {
168
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
169
+ } else if ( typeof method === 'object' || ! method ) {
170
+ return methods.init.apply( this, arguments );
171
+ } else {
172
+ $.error( 'Method ' + method + ' does not exist on hjq_input_many' );
173
+ }
174
+ };
175
+
176
+ })( jQuery );
@@ -0,0 +1,25 @@
1
+ /* live_editor */
2
+ (function($) {
3
+ var methods = {
4
+ init: function(annotations) {
5
+ $(this).on('change', methods.change);
6
+ },
7
+
8
+ change: function(event) {
9
+ var formlet = $(this).closest('.in-place-form');
10
+ formlet.hjq_formlet('submit');
11
+ }
12
+ };
13
+
14
+ $.fn.hjq_live_editor = function( method ) {
15
+
16
+ if ( methods[method] ) {
17
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
18
+ } else if ( typeof method === 'object' || ! method ) {
19
+ return methods.init.apply( this, arguments );
20
+ } else {
21
+ $.error( 'Method ' + method + ' does not exist on hjq_live_editor' );
22
+ }
23
+ };
24
+
25
+ })( jQuery );
@@ -0,0 +1,13 @@
1
+ /* live_search */
2
+ (function($) {
3
+ $.fn.hjq_live_search = function(annotations) {
4
+ var form=this.children("form");
5
+ // form.on("rapid:ajax:success.live_search", function() {
6
+ // $.each(form.hjq("getUpdateIds", form.data('rapid').form.ajax_attrs), function() {
7
+ // $("#"+this).trigger("rapid:open_search_results");
8
+ // });
9
+ // });
10
+
11
+ // TODO: call form.trigger('submit') on keystroke pause
12
+ }
13
+ })( jQuery );
@@ -0,0 +1,9 @@
1
+ /* search_results */
2
+ (function($) {
3
+ var first_run = true;
4
+ $.fn.hjq_search_results = function(annotations) {
5
+ // the first run is page load. Subsequent initializations will happen on ajax update.
6
+ if(first_run) first_run = false;
7
+ else $("#search-results-box").hjq_dialog_box("open");
8
+ }
9
+ })( jQuery );
@@ -0,0 +1,62 @@
1
+ /* select_many */
2
+ (function($) {
3
+ var methods = {
4
+ init: function(annotations) {
5
+ this.children('select').on('change', methods.addOne);
6
+ this.on('click', 'input.remove-item', methods.removeOne);
7
+ },
8
+
9
+ addOne: function() {
10
+ var that=$(this);
11
+ var top=that.parents(".select-many");
12
+ var annotations = top.data('rapid')['select-many'];
13
+ var selected=that.find("option:selected");
14
+ if(selected.val()) {
15
+ var clone=top.find(".item-proto .item").clone().removeClass("proto-item");
16
+ clone.find("span").text(selected.text());
17
+ clone.find("input[type=hidden]").val(selected.val()).removeClass("proto-hidden");
18
+ clone.css('display', 'none');
19
+ top.find(".items").append(clone);
20
+
21
+ var optgroup = $("<optgroup/>").
22
+ attr('alt', selected.val()).
23
+ attr('label', selected.text()).
24
+ addClass("disabled-option");
25
+ selected.replaceWith(optgroup);
26
+ selected.parent().val("");
27
+
28
+ clone.hjq('show', annotations.show, function() {
29
+ clone.trigger("rapid:add", clone);
30
+ clone.trigger("rapid:change", clone);
31
+ });
32
+ }
33
+ },
34
+
35
+
36
+ removeOne: function() {
37
+ var that=$(this);
38
+ var element = that.parent();
39
+ var top = element.parents('.select-many');
40
+ var annotations = top.data('rapid')['select-many'];
41
+ var label = element.children("span").text();
42
+ var optgroup = top.find("optgroup").filter(function() {return this.label==label;});
43
+ optgroup.replaceWith($("<option/>").text(label).val(optgroup.attr('alt')));
44
+ element.hjq('hideAndRemove', annotations.hide, function() {
45
+ element.trigger("rapid:remove", element);
46
+ element.trigger("rapid:change", element);
47
+ });
48
+ }
49
+ };
50
+
51
+ $.fn.hjq_select_many = function( method ) {
52
+
53
+ if ( methods[method] ) {
54
+ return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
55
+ } else if ( typeof method === 'object' || ! method ) {
56
+ return methods.init.apply( this, arguments );
57
+ } else {
58
+ $.error( 'Method ' + method + ' does not exist on hjq_select_many' );
59
+ }
60
+ };
61
+
62
+ })( jQuery );