1
|
/**
|
2
|
* Expected dom structure:
|
3
|
* <div class="form-item form-type-checkbox form-item-search-areas-area-0-4f854b84-2d93-4b0d-a40d-9e05be7cbae1">
|
4
|
<input
|
5
|
id="edit-search-areas-area-0-4f854b84-2d93-4b0d-a40d-9e05be7cbae1"
|
6
|
name="search[areas][area][0][4f854b84-2d93-4b0d-a40d-9e05be7cbae1]"
|
7
|
value="4f854b84-2d93-4b0d-a40d-9e05be7cbae1"
|
8
|
class="form-checkbox" type="checkbox">
|
9
|
<label class="option" for="edit-search-areas-area-0-4f854b84-2d93-4b0d-a40d-9e05be7cbae1">
|
10
|
<span class="parents">Pacific (6) > Northwestern Pacific (62) > </span>Marianas (MRN)
|
11
|
</label>
|
12
|
</div>
|
13
|
*/
|
14
|
|
15
|
// see also https://github.com/geetarista/jquery-plugin-template/blob/master/jquery.plugin-template.js
|
16
|
|
17
|
// the semi-colon before function invocation is a safety net against concatenated
|
18
|
// scripts and/or other plugins which may not be closed properly.
|
19
|
;(function($, document, window, undefined) {
|
20
|
|
21
|
|
22
|
// Name the plugin so it's only in one place
|
23
|
var pluginName = 'search_area_filter';
|
24
|
|
25
|
// Default options for the plugin as a simple object
|
26
|
var defaults = {
|
27
|
};
|
28
|
|
29
|
function Plugin(element, filter_text_selector, options) {
|
30
|
|
31
|
this.element = element;
|
32
|
this.text_field = $(filter_text_selector);
|
33
|
this.form_items;
|
34
|
this.checked_items_container;
|
35
|
|
36
|
// firebug console stub (avoids errors if firebug is not active)
|
37
|
if (typeof console === "undefined") {
|
38
|
console = {
|
39
|
log: function () {
|
40
|
}
|
41
|
};
|
42
|
}
|
43
|
|
44
|
// Merge the options given by the user with the defaults
|
45
|
this.options = $.extend({}, defaults, options);
|
46
|
|
47
|
// Attach data to the elment
|
48
|
this.$el = $(element);
|
49
|
this.$el.data(name, this);
|
50
|
|
51
|
this._defaults = defaults;
|
52
|
|
53
|
var meta = this.$el.data(name + '-opts');
|
54
|
this.opts = $.extend(this._defaults, options, meta);
|
55
|
|
56
|
// Initialization code to get the ball rolling
|
57
|
// If your plugin is simple, this may not be necessary and
|
58
|
// you could place your implementation here
|
59
|
this.init();
|
60
|
}
|
61
|
|
62
|
Plugin.prototype = {
|
63
|
// Public functions accessible to users
|
64
|
// Prototype methods are shared across all elements
|
65
|
// You have access to this.options and this.element
|
66
|
// If your plugin is complex, you can split functionality into more
|
67
|
// methods like this one
|
68
|
|
69
|
init: function () {
|
70
|
// Plugin initializer - prepare your plugin
|
71
|
|
72
|
var timer;
|
73
|
|
74
|
// init
|
75
|
var form_item_container = this.$el;
|
76
|
|
77
|
form_items = form_item_container.find('.form-checkboxes').find('.form-item');
|
78
|
// --- add container for labels of checked items
|
79
|
checked_items_container = $('<div class="checked-items clearfix"></div>');
|
80
|
this.text_field.before(checked_items_container);
|
81
|
|
82
|
form_items.find('input:checked').each(function(){
|
83
|
handle_item_checked($(this));
|
84
|
});
|
85
|
|
86
|
|
87
|
this.text_field.keyup(function () {
|
88
|
clearTimeout(timer);
|
89
|
timer = setTimeout(filter_elements($(this).val()), 1000);
|
90
|
});
|
91
|
|
92
|
form_items.children('input').change(function (e) {
|
93
|
handle_item_checked($(this));
|
94
|
});
|
95
|
}
|
96
|
};
|
97
|
|
98
|
$.fn[pluginName] = function(options) {
|
99
|
// Iterate through each DOM element and return it
|
100
|
return this.each(function() {
|
101
|
// prevent multiple instantiations
|
102
|
if (!$.data(this, 'plugin_' + pluginName)) {
|
103
|
$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
|
104
|
}
|
105
|
});
|
106
|
};
|
107
|
|
108
|
|
109
|
var handle_item_checked = function(item){
|
110
|
|
111
|
var label = item.siblings('label');
|
112
|
|
113
|
console.log('input of ' + label.text() + ' changed to ' + (item.is(':checked') ? '1':'0'));
|
114
|
|
115
|
if (item.is(':checked')) {
|
116
|
checked_items_container.append('<div class="selected-item-label" data-cdm-checked="' + item.val() + '">' + label.text() + '</div>');
|
117
|
} else {
|
118
|
// i was trying to use an attribute selector 'div[data-cdm-checked="' + target.val() + '"' here,
|
119
|
// but it did not work at all,
|
120
|
// so looping over the children seems to be the better approach
|
121
|
checked_items_container.children().each(function(index, element){
|
122
|
var el = $(element);
|
123
|
if(el.attr('data-cdm-checked') == item.val()){
|
124
|
console.log(' removing');
|
125
|
el.remove();
|
126
|
}
|
127
|
});
|
128
|
}
|
129
|
};
|
130
|
|
131
|
var filter_elements = function(entered_text){
|
132
|
|
133
|
console.log('entered text: ' + entered_text);
|
134
|
|
135
|
// --- remove all highlighting and
|
136
|
// --- hide all form items except checked items which always must be visible
|
137
|
form_items.each(function(){
|
138
|
var form_item_container = $(this);
|
139
|
if(form_item_container.children(':checked').length == 0){
|
140
|
form_item_container.hide();
|
141
|
}
|
142
|
var matching_label = form_item_container.find('.child-label');
|
143
|
matching_label.html(matching_label.text());
|
144
|
});
|
145
|
|
146
|
|
147
|
if(entered_text.length > 0){
|
148
|
|
149
|
var rexgexp = new RegExp(entered_text , 'i');
|
150
|
|
151
|
var matching_items = form_items.filter(function(){
|
152
|
return $(this).text().match(rexgexp);
|
153
|
});
|
154
|
|
155
|
// --- highlite the matching text
|
156
|
matching_items.each(function(){
|
157
|
var matching_label = $(this).find('.child-label');
|
158
|
var matching_snippet = matching_label.text().match(rexgexp);
|
159
|
if(matching_snippet && matching_snippet.length > 0){
|
160
|
// NOTE this will only highlite the first match in the string
|
161
|
matching_label.html(matching_label.text().replace(matching_snippet[0], '<span class="highlite">' + matching_snippet[0] + '</span>'));
|
162
|
}
|
163
|
var matching_label_abbrev = $(this).find('.child-label-abbreviated');
|
164
|
matching_snippet = matching_label_abbrev.text().match(rexgexp);
|
165
|
if(matching_snippet && matching_snippet.length > 0){
|
166
|
// NOTE this will only highlite the first match in the string
|
167
|
matching_label_abbrev.html(matching_label_abbrev.text().replace(matching_snippet[0], '<span class="highlite">' + matching_snippet[0] + '</span>'));
|
168
|
}
|
169
|
});
|
170
|
matching_items.show();
|
171
|
|
172
|
// --- also show the options of parent areas
|
173
|
var parent_uuids = [];
|
174
|
matching_items.find('span.parent').each(function(){
|
175
|
var parent_uuid = $(this).attr('data-cdm-parent');
|
176
|
if(parent_uuids.indexOf(parent_uuid) == -1){
|
177
|
parent_uuids.push(parent_uuid);
|
178
|
}
|
179
|
});
|
180
|
|
181
|
parent_uuids.forEach(function(uuid, index, array) {
|
182
|
// form-item-search-areas-area-0-bda3f9fb-30cf-43fd-8d17-5e4d69545ed5"
|
183
|
// TODO make the class attribute prefix configurable!
|
184
|
$('.form-item-search-areas-area-0-' + uuid).show();
|
185
|
});
|
186
|
} else {
|
187
|
form_items.show();
|
188
|
}
|
189
|
|
190
|
};
|
191
|
|
192
|
|
193
|
})(jQuery, document, window);
|
194
|
|