1
|
// see also https://github.com/geetarista/jquery-plugin-template/blob/master/jquery.plugin-template.js
|
2
|
|
3
|
/**
|
4
|
* Expected DOM structure:
|
5
|
*
|
6
|
* <div id="cdm_taxontree_parent">
|
7
|
* <div class="cdm_taxontree_scroller_xy">
|
8
|
* <ul class="taxon-nodes">
|
9
|
* <li class="leaf filter_included">
|
10
|
* <a href="/d7/test/cdm_dataportal/taxon/996dc2b4-e73d-4d40-99f9-fac18b503d1c"></a>
|
11
|
* </li>
|
12
|
* ...
|
13
|
* </ul>
|
14
|
* </div>
|
15
|
* </div>
|
16
|
*/
|
17
|
;(function($, document, window, undefined) {
|
18
|
|
19
|
$.fn.cdm_taxontree = function(options) {
|
20
|
|
21
|
var opts = $.extend({}, $.fn.cdm_taxontree.defaults, options);
|
22
|
|
23
|
var vertical_scroller_selector = 'cdm_taxontree_scroller_xy';
|
24
|
|
25
|
var cdm_taxontree_parent = $(this);
|
26
|
var cdm_taxontree_list = cdm_taxontree_parent.find('ul.taxon-nodes');
|
27
|
|
28
|
/* ----------- magicbox ---------- */
|
29
|
if (opts.magicbox) {
|
30
|
cdm_taxontree_parent.cdm_taxontree_magicbox();
|
31
|
vertical_sroller_selector = 'cdm_taxontree_scroller_x';
|
32
|
}
|
33
|
|
34
|
/* ----------- tree browser ---------- */
|
35
|
cdm_taxontree_list.delegate("li:not(.invisible)", "click", function(event) {
|
36
|
handle_taxon_node_click(event);
|
37
|
}
|
38
|
);
|
39
|
// Stop event propagation for links (unclear why this is nessecary,
|
40
|
// was this needed for the filter buttons?)
|
41
|
cdm_taxontree_list.delegate("li a", "click", function(event) {
|
42
|
event.stopPropagation();
|
43
|
}
|
44
|
);
|
45
|
|
46
|
/* ----------- widget ------------------- */
|
47
|
if (opts.widget) {
|
48
|
var widget = cdm_taxontree_parent.find('.cdm_taxontree_widget');
|
49
|
var optionList = widget.find('select');
|
50
|
|
51
|
// Keep all options unselected.
|
52
|
optionList.change(function() {
|
53
|
cdm_taxontree_list.children("[@selected]").remove();
|
54
|
cdm_taxontree_list.children().removeAttr('selected');
|
55
|
});
|
56
|
optionList.children("[@selected]").click(function() {
|
57
|
cdm_taxontree_list.remove();
|
58
|
});
|
59
|
// Select all options onsubmit.
|
60
|
optionList.parents('form').submit(function() {
|
61
|
optionList.children().attr('selected', 'selected');
|
62
|
});
|
63
|
|
64
|
bind_select_click(optionList, cdm_taxontree_list, opts.multiselect);
|
65
|
};
|
66
|
|
67
|
// finally scroll to the focused element
|
68
|
scrollToFocused();
|
69
|
|
70
|
/**
|
71
|
* handler function for clicks on the li elelements which
|
72
|
* represent CDM TaxonNodes. The click will load the
|
73
|
* nodes children via an AHAH call to the CdmdataPortal
|
74
|
* and expands the clicked node.
|
75
|
*
|
76
|
* @param event
|
77
|
* The javascript event object of the click event
|
78
|
*/
|
79
|
function handle_taxon_node_click(event){
|
80
|
|
81
|
event.stopPropagation();
|
82
|
var li = $(event.target);
|
83
|
if (li.hasClass('collapsed')) {
|
84
|
var bindChildren = (li.find('ul').length == 0);
|
85
|
if (bindChildren) {
|
86
|
var url = li.attr('data-cdm-ahah-url');
|
87
|
if (url != undefined) {
|
88
|
li.removeAttr('data-cdm-ahah-url');
|
89
|
var parent_li = li;
|
90
|
li.set_background_image('loading_subtree.gif');
|
91
|
|
92
|
// Load DOM subtree via AHAH and append it.
|
93
|
$.get(url, function(html) {
|
94
|
parent_li.set_background_image('minus.png');
|
95
|
if (opts.magicbox) {
|
96
|
// Preserve scroll positions.
|
97
|
var tmp_scroller_y_left = parent_li.parents('div.cdm_taxontree_container').children().scrollTop();
|
98
|
|
99
|
parent_li.append(html);
|
100
|
|
101
|
// Resize parent container.
|
102
|
cdm_taxontree_container_resize(tree_container);
|
103
|
|
104
|
// Restore scroll positions.
|
105
|
tree_container.children().scrollTop(tmp_scroller_y_left);
|
106
|
} else {
|
107
|
parent_li.append(html);
|
108
|
}
|
109
|
});
|
110
|
}
|
111
|
} else {
|
112
|
li.set_background_image('minus.png');
|
113
|
}
|
114
|
li.removeClass('collapsed').addClass('expanded').children(
|
115
|
'ul').css('display', 'block');
|
116
|
} else if (li.hasClass('expanded')) {
|
117
|
li.removeClass('expanded').addClass('collapsed').children(
|
118
|
'ul').css('display', 'none');
|
119
|
li.set_background_image('plus.png');
|
120
|
}
|
121
|
};
|
122
|
|
123
|
/**
|
124
|
*
|
125
|
*/
|
126
|
function bind_select_click(optionList, treelist, isMultiselect) {
|
127
|
treelist.find('li .widget_select').click(
|
128
|
function(event) {
|
129
|
event.stopPropagation();
|
130
|
var li_widget_select = $(event.target);
|
131
|
var value = li_widget_select.attr('alt');
|
132
|
if (optionList.children('[value=' + value + ']').length > 0) {
|
133
|
// Remove from select.
|
134
|
optionList.children('[value=' + value + ']').remove();
|
135
|
} else {
|
136
|
// Add to select.
|
137
|
if (!isMultiselect) {
|
138
|
// Remove all from select
|
139
|
optionList.children().remove();
|
140
|
}
|
141
|
optionList.append('<option value="' + value + '">'
|
142
|
+ li_widget_select.attr('title') + '</option>');
|
143
|
|
144
|
// Fix bug in IE.
|
145
|
if (jQuery.browser['msie']) {
|
146
|
if (jQuery.browser['version'].charAt(0) <= '6') {
|
147
|
return;
|
148
|
}
|
149
|
}
|
150
|
// optionList.children().removeAttr('selected'); // Yields a bug
|
151
|
// in IE6, @see
|
152
|
// http://gimp4you.eu.org/sandbox/js/test/removeAttr.html
|
153
|
optionList.children("[@selected]").attr('selected', '');
|
154
|
}
|
155
|
});
|
156
|
} // END bind_select_click()
|
157
|
|
158
|
/**
|
159
|
*
|
160
|
*/
|
161
|
function scrollToFocused() {
|
162
|
var focusedElement = cdm_taxontree_parent.find('.focused');
|
163
|
if(focusedElement.length > 0){
|
164
|
var lineHeight = focusedElement.css('line-height');
|
165
|
lineHeight = lineHeight.replace('px', '');
|
166
|
lineHeight = lineHeight.length == 0 ? 18 : lineHeight;
|
167
|
cdm_taxontree_parent.find('div.' + vertical_scroller_selector).scrollTop(focusedElement.position().top - (4 * lineHeight));
|
168
|
}
|
169
|
|
170
|
}
|
171
|
|
172
|
}; // END cdm_taxontree()
|
173
|
|
174
|
})(jQuery, document, window);
|
175
|
|
176
|
/**
|
177
|
* helper function to set the background image as jQuery extension
|
178
|
*/
|
179
|
jQuery.fn.set_background_image = function(imageFile) {
|
180
|
var bg_image_tmp = jQuery(this).css('background-image');
|
181
|
var bg_image_new = bg_image_tmp.replace(/^(.*)(\/.*)(\))$/, '$1/' + imageFile + '$3');
|
182
|
if (jQuery.browser.mozilla) {
|
183
|
// Special bug handling for mozilla: strip of last closing bracket.
|
184
|
bg_image_new = bg_image_new.substr(0, bg_image_new.length - 1);
|
185
|
}
|
186
|
jQuery(this).css('background-image', bg_image_new);
|
187
|
};
|
188
|
|
189
|
jQuery.fn.cdm_taxontree.defaults = { // Set up default options.
|
190
|
widget : false, // True = enable widget mode.
|
191
|
magicbox : false, // True = enable quirky magicbox.
|
192
|
element_name : 'widgetval',
|
193
|
multiselect : false // True = enable selection of multiple.
|
194
|
};
|
195
|
|
196
|
|
197
|
// ====================================================================================== //
|
198
|
|
199
|
/**
|
200
|
* jQuery function which implements the Magicbox behavior for the taxontree.
|
201
|
* A Magicbox the container of the taxon tree will extend on mouse over
|
202
|
* events in order to show the entrys without truncation through cropping.
|
203
|
*/
|
204
|
jQuery.fn.cdm_taxontree_magicbox = function() {
|
205
|
// Exclude IE6 and lower versions.
|
206
|
if (!(jQuery.browser['msie'] && jQuery.browser['version'].charAt(0) < '7')) {
|
207
|
|
208
|
var container = $(this).parent().parent('div.cdm_taxontree_container');
|
209
|
if (container[0] != undefined) {
|
210
|
container.hover(
|
211
|
function(event) {
|
212
|
handle_mouseOver(event);
|
213
|
},
|
214
|
function(event) {
|
215
|
handle_mouseOut(event);
|
216
|
}
|
217
|
);
|
218
|
}
|
219
|
} // END exclude IE6
|
220
|
|
221
|
/**
|
222
|
* expands the box on mouse over events the
|
223
|
*/
|
224
|
function handle_mouseOver(event){
|
225
|
var taxontree_container = $(event.target);
|
226
|
var scroller_x = taxontree_container.parent();
|
227
|
var scroller_y = taxontree_container.children('.cdm_taxontree_scroller_y');
|
228
|
var container = scroller_x.parent();
|
229
|
|
230
|
var h = parseFloat(scroller_x.height());
|
231
|
var scroll_top = scroller_x.scrollTop();
|
232
|
var border_color = scroller_x.css('border-top-color');
|
233
|
|
234
|
// Store scroll_left of scroller_x so that it can be restored on mouseOut.
|
235
|
scroller_x.append('<div class="_scrollLeft" style="display: none;" title="'
|
236
|
+ scroller_x.scrollLeft() + '"></div>');
|
237
|
|
238
|
var newWidth = cdm_taxontree_container_resize(taxontree_container);
|
239
|
|
240
|
var shift_left = '0';
|
241
|
if (scroller_x.hasClass('expand-left')) {
|
242
|
shift_left = container.outerWidth({margin : true}) - newWidth;
|
243
|
}
|
244
|
|
245
|
scroller_y.css('overflow-y', 'auto')
|
246
|
.css('border-color', border_color)
|
247
|
.scrollTop(scroll_top);
|
248
|
scroller_x.css('overflow-y', 'visible')
|
249
|
.css('overflow-x', 'visible')
|
250
|
.css('margin-left', shift_left)
|
251
|
.css('border-color', 'transparent')
|
252
|
.height(h);
|
253
|
};
|
254
|
|
255
|
/**
|
256
|
* Restores the original appearance on mouse out events
|
257
|
*/
|
258
|
function handle_mouseOut(event){
|
259
|
|
260
|
var taxontree_container = $(event.target);
|
261
|
var scroller_x = taxontree_container.parent('.cdm_taxontree_scroller_x');
|
262
|
var scroller_y = taxontree_container.children('.cdm_taxontree_scroller_y');
|
263
|
var border_color = scroller_y.css('border-top-color');
|
264
|
|
265
|
var scroll_top = scroller_y.scrollTop();
|
266
|
scroller_y.css('overflow-y', 'visible')
|
267
|
.css('border-color', 'transparent');
|
268
|
scroller_x.css('overflow-y', 'auto').css('margin-left', '0').css(
|
269
|
'border-color', border_color).width('auto').scrollTop(scroll_top);
|
270
|
|
271
|
// Restore scroll_left of scroller_x.
|
272
|
var scrollLeft = scroller_x.children('._scrollLeft').attr('title');
|
273
|
scroller_x.scrollLeft(scrollLeft);
|
274
|
scroller_x.children('._scrollLeft').remove();
|
275
|
};
|
276
|
|
277
|
/**
|
278
|
* Resizes the taxontree_container and returns the new outerWidth
|
279
|
*/
|
280
|
function taxontree_container_resize(taxontree_container) {
|
281
|
var current_w = taxontree_container.parent().width();
|
282
|
|
283
|
// Determine max horizontal extent of any children.
|
284
|
var tree_list = taxontree_container.find('.cdm_taxontree_scroller_y > ul');
|
285
|
var w = tree_list.css('position', 'absolute').outerWidth({
|
286
|
margin : true
|
287
|
});
|
288
|
tree_list.css('position', 'static');
|
289
|
|
290
|
// Other Browsers than Firefox.
|
291
|
if (jQuery.browser['msie']) {
|
292
|
if (jQuery.browser['version'].charAt(0) == '7') {
|
293
|
w = w + 17;
|
294
|
}
|
295
|
if (jQuery.browser['version'].charAt(0) <= '6') {
|
296
|
return;
|
297
|
}
|
298
|
}
|
299
|
|
300
|
if (current_w < w) {
|
301
|
taxontree_container.parent().width(w);
|
302
|
taxontree_container.children().width(w);
|
303
|
}
|
304
|
return taxontree_container.children().outerWidth();
|
305
|
};
|
306
|
|
307
|
/**
|
308
|
* Debug function, currently unused
|
309
|
*/
|
310
|
function cdm_taxontree_container_debug_size(taxontree_container, msg) {
|
311
|
var out = msg + '<br /> scoll_x: ' + taxontree_container.parent().width()
|
312
|
+ '<br /> container: ' + taxontree_container.width() + '<br /> scoll_y: '
|
313
|
+ taxontree_container.children().width() + '<br /> ul: '
|
314
|
+ taxontree_container.find('.cdm_taxontree_scroller_y > ul').width() + '<br />';
|
315
|
jQuery('#DEBUG_JS').append(out);
|
316
|
};
|
317
|
};
|
318
|
|
319
|
//====================================================================================== //
|