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