jstree-rails 0.0.2
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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/INSTALLER.sh +57 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/jstree-rails.gemspec +17 -0
- data/lib/jstree-rails/rails.rb +6 -0
- data/lib/jstree-rails/version.rb +5 -0
- data/lib/jstree-rails.rb +8 -0
- data/vendor/assets/images/jstree/themes/default/d.gif +0 -0
- data/vendor/assets/images/jstree/themes/default/d.png +0 -0
- data/vendor/assets/images/jstree/themes/default/throbber.gif +0 -0
- data/vendor/assets/images/jstree/themes/default-rtl/d.gif +0 -0
- data/vendor/assets/images/jstree/themes/default-rtl/d.png +0 -0
- data/vendor/assets/images/jstree/themes/default-rtl/dots.gif +0 -0
- data/vendor/assets/images/jstree/themes/default-rtl/throbber.gif +0 -0
- data/vendor/assets/javascripts/jstree/index.js +15 -0
- data/vendor/assets/javascripts/jstree/jstree.checkbox.js +187 -0
- data/vendor/assets/javascripts/jstree/jstree.contextmenu.js +145 -0
- data/vendor/assets/javascripts/jstree/jstree.dnd.js +162 -0
- data/vendor/assets/javascripts/jstree/jstree.hotkeys.js +138 -0
- data/vendor/assets/javascripts/jstree/jstree.html.js +69 -0
- data/vendor/assets/javascripts/jstree/jstree.js +1982 -0
- data/vendor/assets/javascripts/jstree/jstree.json.js +99 -0
- data/vendor/assets/javascripts/jstree/jstree.rules.js +145 -0
- data/vendor/assets/javascripts/jstree/jstree.sort.js +38 -0
- data/vendor/assets/javascripts/jstree/jstree.state.js +39 -0
- data/vendor/assets/javascripts/jstree/jstree.themes.js +215 -0
- data/vendor/assets/javascripts/jstree/jstree.ui.js +201 -0
- data/vendor/assets/javascripts/jstree/jstree.unique.js +33 -0
- data/vendor/assets/javascripts/jstree/jstree.xml.js +185 -0
- data/vendor/assets/javascripts/jstree/vakata.js +2079 -0
- data/vendor/assets/stylesheets/jstree/themes/default/style.css +79 -0
- data/vendor/assets/stylesheets/jstree/themes/default-rtl/style.css +84 -0
- metadata +80 -0
@@ -0,0 +1,2079 @@
|
|
1
|
+
/*global XSLTProcessor: false, ActiveXObject: false, console : false */
|
2
|
+
|
3
|
+
/*
|
4
|
+
File: Helper functions
|
5
|
+
This file includes some functions that enable CSS manipulations, contextmenus, XSLT transformations and drag'n'drop.
|
6
|
+
All of those work independently of jstree.
|
7
|
+
*/
|
8
|
+
|
9
|
+
/*
|
10
|
+
Variable: $.vakata
|
11
|
+
*object* Holds all helper objects.
|
12
|
+
*/
|
13
|
+
(function ($) {
|
14
|
+
$.vakata = {};
|
15
|
+
})(jQuery);
|
16
|
+
|
17
|
+
/*
|
18
|
+
Group: Miscellaneous
|
19
|
+
Various small snippets.
|
20
|
+
*/
|
21
|
+
|
22
|
+
/*
|
23
|
+
Function: $().vakata_reverse
|
24
|
+
Makes it possible to apply the standard array reverse function to a jQuery collection.
|
25
|
+
|
26
|
+
Input:
|
27
|
+
> <div>1</div><div>2</div><div>3</div>
|
28
|
+
> $("div").vakata_reverse().each(function () { document.write(this.innerHTML); });
|
29
|
+
|
30
|
+
Output:
|
31
|
+
>321
|
32
|
+
*/
|
33
|
+
(function ($) {
|
34
|
+
$.fn.vakata_reverse = [].reverse;
|
35
|
+
})(jQuery);
|
36
|
+
|
37
|
+
(function ($) {
|
38
|
+
jQuery.expr[':'].vakata_icontains = function(a,i,m){
|
39
|
+
return (a.textContent || a.innerText || "").toLowerCase().indexOf(m[3].toLowerCase())>=0;
|
40
|
+
};
|
41
|
+
})(jQuery);
|
42
|
+
|
43
|
+
/*
|
44
|
+
Function: $.vakata.array_remove
|
45
|
+
Makes it possible to remove an item (or a group of items) form an array.
|
46
|
+
http://ejohn.org/blog/javascript-array-remove/
|
47
|
+
|
48
|
+
Input:
|
49
|
+
> $.vakata.array_remove(['a', 'b', 'c'], 1);
|
50
|
+
|
51
|
+
Output:
|
52
|
+
>['a', 'c']
|
53
|
+
*/
|
54
|
+
(function ($) {
|
55
|
+
$.vakata.array_remove = function(array, from, to) {
|
56
|
+
var rest = array.slice((to || from) + 1 || array.length);
|
57
|
+
array.length = from < 0 ? array.length + from : from;
|
58
|
+
array.push.apply(array, rest);
|
59
|
+
return array;
|
60
|
+
};
|
61
|
+
})(jQuery);
|
62
|
+
|
63
|
+
/*
|
64
|
+
Function: $.vakata.array_unique
|
65
|
+
Returns only the unique items from an array.
|
66
|
+
|
67
|
+
Input:
|
68
|
+
> $.vakata.array_unique(['c','a','a','b','c','b']);
|
69
|
+
|
70
|
+
Output:
|
71
|
+
>['a', 'b', 'c']
|
72
|
+
*/
|
73
|
+
(function ($) {
|
74
|
+
$.vakata.array_unique = function(array) {
|
75
|
+
var a = [], i, j, l;
|
76
|
+
for(i = 0, l = array.length; i < l; i++) {
|
77
|
+
for(j = 0; j <= i; j++) {
|
78
|
+
if(array[i] === array[j]) {
|
79
|
+
break;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
if(j === i) { a.push(array[i]); }
|
83
|
+
}
|
84
|
+
return a;
|
85
|
+
};
|
86
|
+
})(jQuery);
|
87
|
+
|
88
|
+
/*
|
89
|
+
Function: $.vakata.attributes
|
90
|
+
Collects all attributes from a DOM node.
|
91
|
+
*/
|
92
|
+
(function ($) {
|
93
|
+
$.vakata.attributes = function(node, with_values) {
|
94
|
+
node = $(node)[0];
|
95
|
+
var attr = with_values ? {} : [];
|
96
|
+
$.each(node.attributes, function (i, v) {
|
97
|
+
if($.inArray(v.nodeName.toLowerCase(),['style','contenteditable','hasfocus','tabindex']) !== -1) { return; }
|
98
|
+
if(v.nodeValue !== null && $.trim(v.nodeValue) !== '') {
|
99
|
+
if(with_values) { attr[v.nodeName] = v.nodeValue; }
|
100
|
+
else { attr.push(v.nodeName); }
|
101
|
+
}
|
102
|
+
});
|
103
|
+
return attr;
|
104
|
+
};
|
105
|
+
})(jQuery);
|
106
|
+
|
107
|
+
/*
|
108
|
+
Function: $.vakata.get_scrollbar_width
|
109
|
+
Gets the width of the scrollbar
|
110
|
+
*/
|
111
|
+
(function ($) {
|
112
|
+
var sb;
|
113
|
+
$.vakata.get_scrollbar_width = function () {
|
114
|
+
var e1, e2;
|
115
|
+
if(!sb) {
|
116
|
+
if(/msie/.test(navigator.userAgent.toLowerCase())) {
|
117
|
+
e1 = $('<textarea cols="10" rows="2"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body');
|
118
|
+
e2 = $('<textarea cols="10" rows="2" style="overflow: hidden;"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body');
|
119
|
+
sb = e1.width() - e2.width();
|
120
|
+
e1.add(e2).remove();
|
121
|
+
}
|
122
|
+
else {
|
123
|
+
e1 = $('<div />').css({ width: 100, height: 100, overflow: 'auto', position: 'absolute', top: -1000, left: 0 })
|
124
|
+
.prependTo('body').append('<div />').find('div').css({ width: '100%', height: 200 });
|
125
|
+
sb = 100 - e1.width();
|
126
|
+
e1.parent().remove();
|
127
|
+
}
|
128
|
+
}
|
129
|
+
return sb;
|
130
|
+
};
|
131
|
+
})(jQuery);
|
132
|
+
|
133
|
+
/*
|
134
|
+
Group: CSS
|
135
|
+
Functions needed to manipulate stylesheets (add, remove, change)
|
136
|
+
*/
|
137
|
+
(function ($) {
|
138
|
+
/*
|
139
|
+
Variable: $.vakata.css
|
140
|
+
*object* holds all CSS related functions
|
141
|
+
*/
|
142
|
+
$.vakata.css = {
|
143
|
+
/*
|
144
|
+
Function: $.vakata.css.get_css
|
145
|
+
Retrieves or deletes a specific rule.
|
146
|
+
|
147
|
+
Parameters:
|
148
|
+
rule_name - *string* the rule to search for (any CSS rule)
|
149
|
+
delete_flag - *boolean* whether you want to delete or simply retrieve a reference to the rule
|
150
|
+
sheet - the sheet to search in (do not specify this to search in all sheets)
|
151
|
+
|
152
|
+
Returns either:
|
153
|
+
a reference to the rule - if it was found and the delete flag was not set
|
154
|
+
true - if the delete flag was set and the rule was successfully removed
|
155
|
+
false - if the rule could not be found
|
156
|
+
|
157
|
+
See also:
|
158
|
+
<$.vakata.css.remove_css>
|
159
|
+
*/
|
160
|
+
get_css : function(rule_name, delete_flag, sheet) {
|
161
|
+
rule_name = rule_name.toLowerCase();
|
162
|
+
var css_rules = sheet.cssRules || sheet.rules,
|
163
|
+
j = 0;
|
164
|
+
do {
|
165
|
+
if(css_rules.length && j > css_rules.length + 5) { return false; }
|
166
|
+
if(css_rules[j].selectorText && css_rules[j].selectorText.toLowerCase() === rule_name) {
|
167
|
+
if(delete_flag === true) {
|
168
|
+
if(sheet.removeRule) { sheet.removeRule(j); }
|
169
|
+
if(sheet.deleteRule) { sheet.deleteRule(j); }
|
170
|
+
return true;
|
171
|
+
}
|
172
|
+
else { return css_rules[j]; }
|
173
|
+
}
|
174
|
+
}
|
175
|
+
while (css_rules[++j]);
|
176
|
+
return false;
|
177
|
+
},
|
178
|
+
/*
|
179
|
+
Function: $.vakata.css.add_css
|
180
|
+
Adds a rule.
|
181
|
+
|
182
|
+
Parameters:
|
183
|
+
rule_name - *string* the rule to add
|
184
|
+
sheet - a reference to the sheet to add to
|
185
|
+
|
186
|
+
Returns either:
|
187
|
+
a reference to the rule - if the rule was added
|
188
|
+
false - if the rule could not be added, or if such a rule already exists
|
189
|
+
*/
|
190
|
+
add_css : function(rule_name, sheet) {
|
191
|
+
if($.jstree.css.get_css(rule_name, false, sheet)) { return false; }
|
192
|
+
if(sheet.insertRule) { sheet.insertRule(rule_name + ' { }', 0); } else { sheet.addRule(rule_name, null, 0); }
|
193
|
+
return $.vakata.css.get_css(rule_name);
|
194
|
+
},
|
195
|
+
/*
|
196
|
+
Function: $.vakata.css.remove_css
|
197
|
+
Removes a rule, this functions is a shortcut to <$.vakata.css.get_css> with the delete flag set to true.
|
198
|
+
|
199
|
+
Parameters:
|
200
|
+
rule_name - *string* the rule to remove
|
201
|
+
sheet - the sheet to remove from (you can omit this and all sheets will be searched)
|
202
|
+
|
203
|
+
Returns either:
|
204
|
+
true - if rule was removed
|
205
|
+
false - if the rule could not be removed
|
206
|
+
|
207
|
+
See also:
|
208
|
+
<$.vakata.css.get_css>
|
209
|
+
*/
|
210
|
+
remove_css : function(rule_name, sheet) {
|
211
|
+
return $.vakata.css.get_css(rule_name, true, sheet);
|
212
|
+
},
|
213
|
+
/*
|
214
|
+
Function: $.vakata.css.add_sheet
|
215
|
+
Adds a whole stylesheet or appends to an existing stylesheet.
|
216
|
+
|
217
|
+
Parameters:
|
218
|
+
options - *object*:
|
219
|
+
options.url - location of the stylesheet - when this is supplied _options.str_ and _options.title_ should not be set and a new LINK element is always created
|
220
|
+
options.str - text content of the stylesheet - when this is supplied _options.url_ is not used. A STYLE element is used.
|
221
|
+
options.title - the ID of the added stylesheet (if you pass `foo` the ID will be `foo-stylesheet`), when the stylesheet exists the content is appended and no new stylesheet is created.
|
222
|
+
|
223
|
+
Returns:
|
224
|
+
a reference to the stylesheet
|
225
|
+
*/
|
226
|
+
add_sheet : function(opts) {
|
227
|
+
var tmp = false, is_new = true;
|
228
|
+
if(opts.str) {
|
229
|
+
if(opts.title) { tmp = $("style[id='" + opts.title + "-stylesheet']")[0]; }
|
230
|
+
if(tmp) { is_new = false; }
|
231
|
+
else {
|
232
|
+
tmp = document.createElement("style");
|
233
|
+
tmp.setAttribute('type',"text/css");
|
234
|
+
if(opts.title) { tmp.setAttribute("id", opts.title + "-stylesheet"); }
|
235
|
+
}
|
236
|
+
if(tmp.styleSheet) {
|
237
|
+
if(is_new) {
|
238
|
+
document.getElementsByTagName("head")[0].appendChild(tmp);
|
239
|
+
tmp.styleSheet.cssText = opts.str;
|
240
|
+
}
|
241
|
+
else {
|
242
|
+
tmp.styleSheet.cssText = tmp.styleSheet.cssText + " " + opts.str;
|
243
|
+
}
|
244
|
+
}
|
245
|
+
else {
|
246
|
+
tmp.appendChild(document.createTextNode(opts.str));
|
247
|
+
document.getElementsByTagName("head")[0].appendChild(tmp);
|
248
|
+
}
|
249
|
+
return tmp.sheet || tmp.styleSheet;
|
250
|
+
}
|
251
|
+
if(opts.url) {
|
252
|
+
if(document.createStyleSheet) {
|
253
|
+
try { tmp = document.createStyleSheet(opts.url); } catch (e) { }
|
254
|
+
}
|
255
|
+
else {
|
256
|
+
tmp = document.createElement('link');
|
257
|
+
tmp.rel = 'stylesheet';
|
258
|
+
tmp.type = 'text/css';
|
259
|
+
tmp.media = "all";
|
260
|
+
tmp.href = opts.url;
|
261
|
+
document.getElementsByTagName("head")[0].appendChild(tmp);
|
262
|
+
return tmp.styleSheet;
|
263
|
+
}
|
264
|
+
}
|
265
|
+
}
|
266
|
+
};
|
267
|
+
})(jQuery);
|
268
|
+
|
269
|
+
/*
|
270
|
+
Group: Drag'n'drop
|
271
|
+
Functions needed to drag'n'drop elements
|
272
|
+
*/
|
273
|
+
(function ($) {
|
274
|
+
// private variable
|
275
|
+
var vakata_dnd = {
|
276
|
+
element : false,
|
277
|
+
is_down : false,
|
278
|
+
is_drag : false,
|
279
|
+
helper : false,
|
280
|
+
helper_w: 0,
|
281
|
+
data : false,
|
282
|
+
init_x : 0,
|
283
|
+
init_y : 0,
|
284
|
+
scroll_l: 0,
|
285
|
+
scroll_t: 0,
|
286
|
+
scroll_e: false,
|
287
|
+
scroll_i: false
|
288
|
+
};
|
289
|
+
/*
|
290
|
+
Variable: $.vakata.dnd
|
291
|
+
*object* holds all DND related functions
|
292
|
+
*/
|
293
|
+
$.vakata.dnd = {
|
294
|
+
/*
|
295
|
+
Variable: $.vakata.dnd.settings
|
296
|
+
*object* holds the global settings object for DND. You can easily modify any of the settings.
|
297
|
+
>// modification example
|
298
|
+
>$.vakata.dnd.settings.threshold = 10;
|
299
|
+
*/
|
300
|
+
settings : {
|
301
|
+
/*
|
302
|
+
Variable: $.vakata.dnd.settings.scroll_speed
|
303
|
+
*integer* how fast (pixel count for each step) should a scrollable parent scroll when dragging near the edge. Default is _10_.
|
304
|
+
*/
|
305
|
+
scroll_speed : 10,
|
306
|
+
/*
|
307
|
+
Variable: $.vakata.dnd.settings.scroll_proximity
|
308
|
+
*integer* number of pixels from the edge of a scrollable parent below which the parent will start scrolling. Default is _20_.
|
309
|
+
*/
|
310
|
+
scroll_proximity : 20,
|
311
|
+
/*
|
312
|
+
Variable: $.vakata.dnd.settings.helper_left
|
313
|
+
*integer* number of pixels left of the cursor to move the drag-helper to. Default is _5_;
|
314
|
+
*/
|
315
|
+
helper_left : 5,
|
316
|
+
/*
|
317
|
+
Variable: $.vakata.dnd.settings.helper_top
|
318
|
+
*integer* number of pixels below the cursor to move the drag-helper to. Default is _10_.
|
319
|
+
*/
|
320
|
+
helper_top : 10,
|
321
|
+
/*
|
322
|
+
Variable: $.vakata.dnd.settings.threshold
|
323
|
+
*integer* amount of pixels required to move before the drag is started. Default is _5_.
|
324
|
+
*/
|
325
|
+
threshold : 5
|
326
|
+
},
|
327
|
+
/*
|
328
|
+
Function: $.vakata.dnd._trigger
|
329
|
+
Used internally to trigger all necessary events.
|
330
|
+
*/
|
331
|
+
_trigger : function (event_name, e) {
|
332
|
+
var data = $.vakata.dnd._get();
|
333
|
+
data.event = e;
|
334
|
+
$(document).triggerHandler("dnd_" + event_name + ".vakata", data);
|
335
|
+
},
|
336
|
+
/*
|
337
|
+
Function: $.vakata.dnd._get
|
338
|
+
Used internally to get all items for the drag event. Can be used by foreign code too.
|
339
|
+
*/
|
340
|
+
_get : function () {
|
341
|
+
return {
|
342
|
+
"data" : vakata_dnd.data,
|
343
|
+
"element" : vakata_dnd.element,
|
344
|
+
"helper" : vakata_dnd.helper
|
345
|
+
};
|
346
|
+
},
|
347
|
+
/*
|
348
|
+
Function: $.vakata.dnd._clean
|
349
|
+
Used internally to cleanup after a drop, so that all variables are nulled and ready for the next drag.
|
350
|
+
*/
|
351
|
+
_clean : function () {
|
352
|
+
if(vakata_dnd.helper) { vakata_dnd.helper.remove(); }
|
353
|
+
if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; }
|
354
|
+
vakata_dnd = {
|
355
|
+
element : false,
|
356
|
+
is_down : false,
|
357
|
+
is_drag : false,
|
358
|
+
helper : false,
|
359
|
+
helper_w: 0,
|
360
|
+
data : false,
|
361
|
+
init_x : 0,
|
362
|
+
init_y : 0,
|
363
|
+
scroll_l: 0,
|
364
|
+
scroll_t: 0,
|
365
|
+
scroll_e: false,
|
366
|
+
scroll_i: false
|
367
|
+
};
|
368
|
+
$(document).unbind("mousemove", $.vakata.dnd.drag);
|
369
|
+
$(document).unbind("mouseup", $.vakata.dnd.stop);
|
370
|
+
},
|
371
|
+
/*
|
372
|
+
Function: $.vakata.dnd._scroll
|
373
|
+
Used internally to scroll hovered elements.
|
374
|
+
|
375
|
+
Triggers:
|
376
|
+
<dnd_scroll>
|
377
|
+
|
378
|
+
Event: dnd_scroll
|
379
|
+
Fires when a container is scrolled due to dragging near its edge. Triggered on the document, the event is fired in the *vakata* namespace.
|
380
|
+
|
381
|
+
Parameters:
|
382
|
+
data.event - the scrolled element
|
383
|
+
data.data - the data you supplied when calling <$.vakata.dnd.start>
|
384
|
+
data.element - the origin element
|
385
|
+
data.helper - the jquery extended drag-helper node (or false if it is not used)
|
386
|
+
|
387
|
+
Example:
|
388
|
+
>$(document).bind("dnd_start.vakata", function (e, data) {
|
389
|
+
> // do something
|
390
|
+
>});
|
391
|
+
*/
|
392
|
+
_scroll : function (init_only) {
|
393
|
+
if(!vakata_dnd.scroll_e || (!vakata_dnd.scroll_l && !vakata_dnd.scroll_t)) {
|
394
|
+
if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; }
|
395
|
+
return false;
|
396
|
+
}
|
397
|
+
if(!vakata_dnd.scroll_i) {
|
398
|
+
vakata_dnd.scroll_i = setInterval($.vakata.dnd._scroll, 100);
|
399
|
+
return false;
|
400
|
+
}
|
401
|
+
if(init_only === true) { return false; }
|
402
|
+
|
403
|
+
var i = vakata_dnd.scroll_e.scrollTop(),
|
404
|
+
j = vakata_dnd.scroll_e.scrollLeft();
|
405
|
+
vakata_dnd.scroll_e.scrollTop(i + vakata_dnd.scroll_t * $.vakata.dnd.settings.scroll_speed);
|
406
|
+
vakata_dnd.scroll_e.scrollLeft(j + vakata_dnd.scroll_l * $.vakata.dnd.settings.scroll_speed);
|
407
|
+
if(i !== vakata_dnd.scroll_e.scrollTop() || j !== vakata_dnd.scroll_e.scrollLeft()) {
|
408
|
+
$.vakata.dnd._trigger("scroll", vakata_dnd.scroll_e);
|
409
|
+
}
|
410
|
+
},
|
411
|
+
/*
|
412
|
+
Function: $.vakata.dnd.start
|
413
|
+
Use this function to start a drag (usually with the mousedown event)
|
414
|
+
|
415
|
+
Parameters:
|
416
|
+
event - *event* the event which started the drag, when used with the mousedown event text selection is prevented
|
417
|
+
data - *mixed* some custom data you want to bind with that particular drag - you will receive this in all events
|
418
|
+
html - *mixed* the text for the drag-helper as a *string*, if set to _false_ no helper is shown
|
419
|
+
|
420
|
+
Returns:
|
421
|
+
false
|
422
|
+
|
423
|
+
Example:
|
424
|
+
>$("span").bind("mousedown", function (e) {
|
425
|
+
> return $.vakata.dnd.start(e, {}, "Dragging");
|
426
|
+
>});
|
427
|
+
*/
|
428
|
+
start : function (e, data, html) {
|
429
|
+
if(vakata_dnd.is_drag) { $.vakata.dnd.stop({}); }
|
430
|
+
try {
|
431
|
+
e.currentTarget.unselectable = "on";
|
432
|
+
e.currentTarget.onselectstart = function() { return false; };
|
433
|
+
if(e.currentTarget.style) { e.currentTarget.style.MozUserSelect = "none"; }
|
434
|
+
} catch(err) { }
|
435
|
+
vakata_dnd.init_x = e.pageX;
|
436
|
+
vakata_dnd.init_y = e.pageY;
|
437
|
+
vakata_dnd.data = data;
|
438
|
+
vakata_dnd.is_down = true;
|
439
|
+
vakata_dnd.element = e.currentTarget;
|
440
|
+
if(html !== false) {
|
441
|
+
vakata_dnd.helper = $("<div id='vakata-dnd'></div>").html(html).css({
|
442
|
+
"display" : "block",
|
443
|
+
"margin" : "0",
|
444
|
+
"padding" : "0",
|
445
|
+
"position" : "absolute",
|
446
|
+
"top" : "-2000px",
|
447
|
+
"lineHeight" : "16px",
|
448
|
+
"zIndex" : "10000"
|
449
|
+
});
|
450
|
+
}
|
451
|
+
$(document).bind("mousemove", $.vakata.dnd.drag);
|
452
|
+
$(document).bind("mouseup", $.vakata.dnd.stop);
|
453
|
+
return false;
|
454
|
+
},
|
455
|
+
/*
|
456
|
+
Function: $.vakata.dnd.drag
|
457
|
+
Used internally to process the mousemove event after <$.vakata.dnd.start> is called.
|
458
|
+
|
459
|
+
Parameters:
|
460
|
+
event - *event* the mousemove event
|
461
|
+
|
462
|
+
Triggers:
|
463
|
+
<dnd_start>, <dnd_move>
|
464
|
+
*/
|
465
|
+
drag : function (e) {
|
466
|
+
if(!vakata_dnd.is_down) { return; }
|
467
|
+
if(!vakata_dnd.is_drag) {
|
468
|
+
if(
|
469
|
+
Math.abs(e.pageX - vakata_dnd.init_x) > $.vakata.dnd.settings.threshold ||
|
470
|
+
Math.abs(e.pageY - vakata_dnd.init_y) > $.vakata.dnd.settings.threshold
|
471
|
+
) {
|
472
|
+
if(vakata_dnd.helper) {
|
473
|
+
vakata_dnd.helper.appendTo("body");
|
474
|
+
vakata_dnd.helper_w = vakata_dnd.helper.outerWidth();
|
475
|
+
}
|
476
|
+
vakata_dnd.is_drag = true;
|
477
|
+
/*
|
478
|
+
Event: dnd_start
|
479
|
+
Marks the start of the drag. Triggered on the document after a drag is initiated using <$.vakata.dnd.start> and the user has moved more than <$.vakata.dnd.settings.threshold> pixels, the event is fired in the *vakata* namespace.
|
480
|
+
|
481
|
+
Parameters:
|
482
|
+
data.event - the mousemove event
|
483
|
+
data.data - the data you supplied when calling <$.vakata.dnd.start>
|
484
|
+
data.element - the origin element
|
485
|
+
data.helper - the jquery extended drag-helper node (or false if it is not used)
|
486
|
+
|
487
|
+
Example:
|
488
|
+
>$(document).bind("dnd_start.vakata", function (e, data) {
|
489
|
+
> // do something
|
490
|
+
>});
|
491
|
+
*/
|
492
|
+
$.vakata.dnd._trigger("start", e);
|
493
|
+
}
|
494
|
+
else { return; }
|
495
|
+
}
|
496
|
+
|
497
|
+
var d = false, w = false,
|
498
|
+
dh = false, wh = false,
|
499
|
+
dw = false, ww = false,
|
500
|
+
dt = false, dl = false,
|
501
|
+
ht = false, hl = false;
|
502
|
+
|
503
|
+
vakata_dnd.scroll_t = 0;
|
504
|
+
vakata_dnd.scroll_l = 0;
|
505
|
+
vakata_dnd.scroll_e = false;
|
506
|
+
var p = $(e.target)
|
507
|
+
.parentsUntil("body").andSelf().vakata_reverse()
|
508
|
+
.filter(function () {
|
509
|
+
return (/^auto|scroll$/).test($(this).css("overflow")) &&
|
510
|
+
(this.scrollHeight > this.offsetHeight || this.scrollWidth > this.offsetWidth);
|
511
|
+
})
|
512
|
+
.each(function () {
|
513
|
+
var t = $(this), o = t.offset();
|
514
|
+
if(this.scrollHeight > this.offsetHeight) {
|
515
|
+
if(o.top + t.height() - e.pageY < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = 1; }
|
516
|
+
if(e.pageY - o.top < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = -1; }
|
517
|
+
}
|
518
|
+
if(this.scrollWidth > this.offsetWidth) {
|
519
|
+
if(o.left + t.width() - e.pageX < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = 1; }
|
520
|
+
if(e.pageX - o.left < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = -1; }
|
521
|
+
}
|
522
|
+
if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) {
|
523
|
+
vakata_dnd.scroll_e = $(this);
|
524
|
+
return false;
|
525
|
+
}
|
526
|
+
});
|
527
|
+
|
528
|
+
if(!vakata_dnd.scroll_e) {
|
529
|
+
d = $(document); w = $(window);
|
530
|
+
dh = d.height(); wh = w.height();
|
531
|
+
dw = d.width(); ww = w.width();
|
532
|
+
dt = d.scrollTop(); dl = d.scrollLeft();
|
533
|
+
if(dh > wh && e.pageY - dt < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = -1; }
|
534
|
+
if(dh > wh && wh - (e.pageY - dt) < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = 1; }
|
535
|
+
if(dw > ww && e.pageX - dl < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = -1; }
|
536
|
+
if(dw > ww && ww - (e.pageX - dl) < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = 1; }
|
537
|
+
if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) {
|
538
|
+
vakata_dnd.scroll_e = d;
|
539
|
+
}
|
540
|
+
}
|
541
|
+
if(vakata_dnd.scroll_e) { $.vakata.dnd._scroll(true); }
|
542
|
+
|
543
|
+
if(vakata_dnd.helper) {
|
544
|
+
ht = parseInt(e.pageY + $.vakata.dnd.settings.helper_top, 10);
|
545
|
+
hl = parseInt(e.pageX + $.vakata.dnd.settings.helper_left, 10);
|
546
|
+
if(dh && ht + 25 > dh) { ht = dh - 50; }
|
547
|
+
if(dw && hl + vakata_dnd.helper_w > dw) { hl = dw - (vakata_dnd.helper_w + 2); }
|
548
|
+
vakata_dnd.helper.css({
|
549
|
+
left : hl + "px",
|
550
|
+
top : ht + "px"
|
551
|
+
});
|
552
|
+
}
|
553
|
+
/*
|
554
|
+
Event: dnd_move
|
555
|
+
Triggered multiple times while dragging. This event is triggered on the document after the <dnd_start> event when the user moves the mouse, the event is fired in the *vakata* namespace.
|
556
|
+
|
557
|
+
Parameters:
|
558
|
+
data.event - the mousemove event
|
559
|
+
data.data - the data you supplied when calling <$.vakata.dnd.start>
|
560
|
+
data.element - the origin element
|
561
|
+
data.helper - the jquery extended drag-helper node (or false if it is not used)
|
562
|
+
|
563
|
+
Example:
|
564
|
+
>$(document).bind("dnd_move.vakata", function (e, data) {
|
565
|
+
> // do something
|
566
|
+
>});
|
567
|
+
*/
|
568
|
+
$.vakata.dnd._trigger("move", e);
|
569
|
+
},
|
570
|
+
/*
|
571
|
+
Function: $.vakata.dnd.stop
|
572
|
+
Used internally to process the mouseup event (drop) after <$.vakata.dnd.start> is called.
|
573
|
+
|
574
|
+
Parameters:
|
575
|
+
event - *event* the mouseup event
|
576
|
+
|
577
|
+
Triggers:
|
578
|
+
<dnd_stop>
|
579
|
+
*/
|
580
|
+
stop : function (e) {
|
581
|
+
/*
|
582
|
+
Event: dnd_stop
|
583
|
+
Marks the end of the drag. This event is triggered on the document after <dnd_start> (and possibly <dnd_move>) when a drop (mouseup) occurs or when the drag is programatically terminated, the event is fired in the *vakata* namespace.
|
584
|
+
|
585
|
+
Parameters:
|
586
|
+
data.event - the mouseup event (or _null_ if stopped programatically using <$.vakata.dnd.stop>())
|
587
|
+
data.data - the data you supplied when calling <$.vakata.dnd.start>
|
588
|
+
data.element - the origin element
|
589
|
+
data.helper - the jquery extended drag-helper node (or false if it is not used)
|
590
|
+
|
591
|
+
Example:
|
592
|
+
>$(document).bind("dnd_stop.vakata", function (e, data) {
|
593
|
+
> // do something
|
594
|
+
>});
|
595
|
+
*/
|
596
|
+
if(vakata_dnd.is_drag) {
|
597
|
+
$.vakata.dnd._trigger("stop", e);
|
598
|
+
}
|
599
|
+
$.vakata.dnd._clean();
|
600
|
+
}
|
601
|
+
};
|
602
|
+
})(jQuery);
|
603
|
+
|
604
|
+
/*
|
605
|
+
Group: XSLT
|
606
|
+
A function used to do XSLT transformations.
|
607
|
+
*/
|
608
|
+
(function ($) {
|
609
|
+
/*
|
610
|
+
Function: $.vakata.xslt
|
611
|
+
This functions transforms a XML string using a XSL string. The result is passed to a callback function.
|
612
|
+
|
613
|
+
Parameters:
|
614
|
+
xml - *string* the source xml string
|
615
|
+
xsl - *string* the xsl string
|
616
|
+
|
617
|
+
Returns:
|
618
|
+
the transformed result (or _false_ on failure)
|
619
|
+
|
620
|
+
Example:
|
621
|
+
>// simple
|
622
|
+
>$.vakata.xslt("<xml-string-here>", "<xsl-string-here>", function (res) { $("#some-container").append(res); });
|
623
|
+
>// with scope
|
624
|
+
>$.vakata.xslt("<xml-string-here>", "<xsl-string-here>", $.proxy(function (res) {
|
625
|
+
> this.some_process(res);
|
626
|
+
>}, some_object);
|
627
|
+
*/
|
628
|
+
$.vakata.xslt = function (xml, xsl) {
|
629
|
+
var r = false, p, q, s;
|
630
|
+
// IE9
|
631
|
+
if(r === false && window.ActiveXObject) {
|
632
|
+
try {
|
633
|
+
r = new ActiveXObject("Msxml2.XSLTemplate");
|
634
|
+
q = new ActiveXObject("Msxml2.DOMDocument");
|
635
|
+
q.loadXML(xml);
|
636
|
+
s = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
|
637
|
+
s.loadXML(xsl);
|
638
|
+
r.stylesheet = s;
|
639
|
+
p = r.createProcessor();
|
640
|
+
p.input = q;
|
641
|
+
p.transform();
|
642
|
+
r = p.output;
|
643
|
+
}
|
644
|
+
catch (e) { }
|
645
|
+
}
|
646
|
+
xml = $.parseXML(xml);
|
647
|
+
xsl = $.parseXML(xsl);
|
648
|
+
// FF, Chrome
|
649
|
+
if(r === false && typeof (XSLTProcessor) !== "undefined") {
|
650
|
+
p = new XSLTProcessor();
|
651
|
+
p.importStylesheet(xsl);
|
652
|
+
r = p.transformToFragment(xml, document);
|
653
|
+
r = $('<div />').append(r).html();
|
654
|
+
}
|
655
|
+
// OLD IE
|
656
|
+
if(r === false && typeof (xml.transformNode) !== "undefined") {
|
657
|
+
r = xml.transformNode(xsl);
|
658
|
+
}
|
659
|
+
return r;
|
660
|
+
};
|
661
|
+
})(jQuery);
|
662
|
+
|
663
|
+
/*
|
664
|
+
Group: Hotkeys
|
665
|
+
Copy of the John Resig's fork of http://github.com/tzuryby/hotkeys for consistency
|
666
|
+
*/
|
667
|
+
if(typeof jQuery.hotkeys === "undefined") {
|
668
|
+
(function ($) {
|
669
|
+
$.vakata_hotkeys = {
|
670
|
+
version: "0.8",
|
671
|
+
|
672
|
+
specialKeys: {
|
673
|
+
8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
|
674
|
+
20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
|
675
|
+
37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del",
|
676
|
+
96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
|
677
|
+
104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
|
678
|
+
112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
|
679
|
+
120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta"
|
680
|
+
},
|
681
|
+
|
682
|
+
shiftNums: {
|
683
|
+
"`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
|
684
|
+
"8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
|
685
|
+
".": ">", "/": "?", "\\": "|"
|
686
|
+
}
|
687
|
+
};
|
688
|
+
|
689
|
+
function keyHandler( handleObj ) {
|
690
|
+
// Only care when a possible input has been specified
|
691
|
+
if ( typeof handleObj.data !== "string" ) {
|
692
|
+
return;
|
693
|
+
}
|
694
|
+
|
695
|
+
var origHandler = handleObj.handler,
|
696
|
+
keys = handleObj.data.toLowerCase().split(" ");
|
697
|
+
|
698
|
+
handleObj.handler = function( event ) {
|
699
|
+
// Don't fire in text-accepting inputs that we didn't directly bind to
|
700
|
+
if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
|
701
|
+
event.target.type === "text") ) {
|
702
|
+
return;
|
703
|
+
}
|
704
|
+
|
705
|
+
// Keypress represents characters, not special keys
|
706
|
+
var special = event.type !== "keypress" && jQuery.vakata_hotkeys.specialKeys[ event.which ],
|
707
|
+
character = String.fromCharCode( event.which ).toLowerCase(),
|
708
|
+
key, modif = "", possible = {};
|
709
|
+
|
710
|
+
// check combinations (alt|ctrl|shift+anything)
|
711
|
+
if ( event.altKey && special !== "alt" ) {
|
712
|
+
modif += "alt+";
|
713
|
+
}
|
714
|
+
|
715
|
+
if ( event.ctrlKey && special !== "ctrl" ) {
|
716
|
+
modif += "ctrl+";
|
717
|
+
}
|
718
|
+
|
719
|
+
// TODO: Need to make sure this works consistently across platforms
|
720
|
+
if ( event.metaKey && !event.ctrlKey && special !== "meta" ) {
|
721
|
+
modif += "meta+";
|
722
|
+
}
|
723
|
+
|
724
|
+
if ( event.shiftKey && special !== "shift" ) {
|
725
|
+
modif += "shift+";
|
726
|
+
}
|
727
|
+
|
728
|
+
if ( special ) {
|
729
|
+
possible[ modif + special ] = true;
|
730
|
+
|
731
|
+
} else {
|
732
|
+
possible[ modif + character ] = true;
|
733
|
+
possible[ modif + jQuery.vakata_hotkeys.shiftNums[ character ] ] = true;
|
734
|
+
|
735
|
+
// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
|
736
|
+
if ( modif === "shift+" ) {
|
737
|
+
possible[ jQuery.vakata_hotkeys.shiftNums[ character ] ] = true;
|
738
|
+
}
|
739
|
+
}
|
740
|
+
|
741
|
+
for ( var i = 0, l = keys.length; i < l; i++ ) {
|
742
|
+
if ( possible[ keys[i] ] ) {
|
743
|
+
return origHandler.apply( this, arguments );
|
744
|
+
}
|
745
|
+
}
|
746
|
+
};
|
747
|
+
}
|
748
|
+
|
749
|
+
jQuery.each([ "keydown", "keyup", "keypress" ], function() {
|
750
|
+
jQuery.event.special[ this ] = { add: keyHandler };
|
751
|
+
});
|
752
|
+
})(jQuery);
|
753
|
+
}
|
754
|
+
|
755
|
+
/*
|
756
|
+
Group: Context menu
|
757
|
+
Functions needed to show a custom context menu.
|
758
|
+
*/
|
759
|
+
(function ($) {
|
760
|
+
var right_to_left = false,
|
761
|
+
vakata_context = {
|
762
|
+
element : false,
|
763
|
+
reference : false,
|
764
|
+
position_x : 0,
|
765
|
+
position_y : 0,
|
766
|
+
items : [],
|
767
|
+
html : "",
|
768
|
+
is_visible : false
|
769
|
+
};
|
770
|
+
/*
|
771
|
+
Variable: $.vakata.context
|
772
|
+
*object* holds all context menu related functions and variables.
|
773
|
+
*/
|
774
|
+
$.vakata.context = {
|
775
|
+
/*
|
776
|
+
Variable: $.vakata.context.settings
|
777
|
+
*object* holds the global settings object for context menus. You can easily modify any of the settings.
|
778
|
+
>// modification example
|
779
|
+
>$.vakata.context.settings.icons = false;
|
780
|
+
*/
|
781
|
+
settings : {
|
782
|
+
/*
|
783
|
+
Variable: $.vakata.context.settings.hide_onmouseleave
|
784
|
+
*integer* the amount of milliseconds to wait before hiding the menu after mouseleave. If set to _0_ the menu won't hide on mouseleave. Default is _0_.
|
785
|
+
*/
|
786
|
+
hide_onmouseleave : 0,
|
787
|
+
/*
|
788
|
+
Variable: $.vakata.context.settings.icons
|
789
|
+
*boolean* whether to show icons or not. Default is _true_.
|
790
|
+
*/
|
791
|
+
icons : true
|
792
|
+
},
|
793
|
+
/*
|
794
|
+
Function: $.vakata.context._trigger
|
795
|
+
Used internally to trigger all necessary events.
|
796
|
+
*/
|
797
|
+
_trigger : function (event_name) {
|
798
|
+
$(document).triggerHandler("context_" + event_name + ".vakata", {
|
799
|
+
"reference" : vakata_context.reference,
|
800
|
+
"element" : vakata_context.element,
|
801
|
+
"position" : {
|
802
|
+
"x" : vakata_context.position_x,
|
803
|
+
"y" : vakata_context.position_y
|
804
|
+
}
|
805
|
+
});
|
806
|
+
},
|
807
|
+
/*
|
808
|
+
Function: $.vakata.context._execute
|
809
|
+
Used internally to execute the action (if any) associated with an item.
|
810
|
+
|
811
|
+
Parameters:
|
812
|
+
i - the item's internal index
|
813
|
+
*/
|
814
|
+
_execute : function (i) {
|
815
|
+
i = vakata_context.items[i];
|
816
|
+
return i && !i._disabled && i.action ? i.action.call(null, {
|
817
|
+
"item" : i,
|
818
|
+
"reference" : vakata_context.reference,
|
819
|
+
"element" : vakata_context.element,
|
820
|
+
"position" : {
|
821
|
+
"x" : vakata_context.position_x,
|
822
|
+
"y" : vakata_context.position_y
|
823
|
+
}
|
824
|
+
}) : false;
|
825
|
+
},
|
826
|
+
/*
|
827
|
+
Function: $.vakata.context._parse
|
828
|
+
Used internally to parse a contextmenu description object to an HTML string.
|
829
|
+
|
830
|
+
Parameters:
|
831
|
+
o - *object* the contextmenu description object
|
832
|
+
is_callback - *boolean* used internally to indicate a recursive call
|
833
|
+
|
834
|
+
Triggers:
|
835
|
+
<context_parse>
|
836
|
+
*/
|
837
|
+
_parse : function (o, is_callback) {
|
838
|
+
if(!o) { return false; }
|
839
|
+
if(!is_callback) {
|
840
|
+
vakata_context.html = "";
|
841
|
+
vakata_context.items = [];
|
842
|
+
}
|
843
|
+
var str = "",
|
844
|
+
sep = false,
|
845
|
+
tmp;
|
846
|
+
|
847
|
+
if(is_callback) { str += "<ul>"; }
|
848
|
+
$.each(o, function (i, val) {
|
849
|
+
if(!val) { return true; }
|
850
|
+
vakata_context.items.push(val);
|
851
|
+
if(!sep && val.separator_before) {
|
852
|
+
str += "<li class='vakata-context-separator'><a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> </a></li>";
|
853
|
+
}
|
854
|
+
sep = false;
|
855
|
+
str += "<li class='" + (val._class || "") + (val._disabled ? " vakata-contextmenu-disabled " : "") + "'>";
|
856
|
+
str += "<a href='#' rel='" + (vakata_context.items.length - 1) + "'>";
|
857
|
+
if($.vakata.context.settings.icons) {
|
858
|
+
str += "<ins ";
|
859
|
+
if(val.icon) {
|
860
|
+
if(val.icon.indexOf("/") !== -1) { str += " style='background:url(\"" + val.icon + "\") center center no-repeat' "; }
|
861
|
+
else { str += " class='" + val.icon + "' "; }
|
862
|
+
}
|
863
|
+
str += "> </ins><span> </span>";
|
864
|
+
}
|
865
|
+
str += val.label + "</a>";
|
866
|
+
if(val.submenu) {
|
867
|
+
tmp = $.vakata.context._parse(val.submenu, true);
|
868
|
+
if(tmp) { str += tmp; }
|
869
|
+
}
|
870
|
+
str += "</li>";
|
871
|
+
if(val.separator_after) {
|
872
|
+
str += "<li class='vakata-context-separator'><a href='#' " + ($.vakata.context.settings.icons ? '' : 'style="margin-left:0px;"') + "> </a></li>";
|
873
|
+
sep = true;
|
874
|
+
}
|
875
|
+
});
|
876
|
+
str = str.replace(/<li class\='vakata-context-separator'\><\/li\>$/,"");
|
877
|
+
if(is_callback) { str += "</ul>"; }
|
878
|
+
/*
|
879
|
+
Event: context_parse
|
880
|
+
Triggered when the context menu is parsed but not yet shown. This event is triggered on the document in the *vakata* namespace.
|
881
|
+
|
882
|
+
Parameters:
|
883
|
+
reference - the DOM node used when <$.vakata.context.show> was called
|
884
|
+
element - the DOM node of the context menu (not yet populated and shown)
|
885
|
+
position - an object consisting of _x_ and _y_ keys, represinting the position of the menu (not yet shown)
|
886
|
+
|
887
|
+
Example:
|
888
|
+
>$(document).bind("context_parse.vakata", function (e, data) {
|
889
|
+
> // do something
|
890
|
+
>});
|
891
|
+
*/
|
892
|
+
if(!is_callback) { vakata_context.html = str; $.vakata.context._trigger("parse"); }
|
893
|
+
return str.length > 10 ? str : false;
|
894
|
+
},
|
895
|
+
/*
|
896
|
+
Function: $.vakata.context._show_submenu
|
897
|
+
Used internally to show a submenu
|
898
|
+
*/
|
899
|
+
_show_submenu : function (o) {
|
900
|
+
o = $(o);
|
901
|
+
if(!o.length || !o.children("ul").length) { return; }
|
902
|
+
var e = o.children("ul"),
|
903
|
+
x = o.offset().left + o.outerWidth(),
|
904
|
+
y = o.offset().top,
|
905
|
+
w = e.width(),
|
906
|
+
h = e.height(),
|
907
|
+
dw = $(document).width(),
|
908
|
+
dh = $(document).height();
|
909
|
+
// може да се спести е една проверка - дали няма някой от класовете вече нагоре
|
910
|
+
if(right_to_left) {
|
911
|
+
o[x - (w + 10 + o.outerWidth()) < 0 ? "addClass" : "removeClass"]("vakata-context-left");
|
912
|
+
}
|
913
|
+
else {
|
914
|
+
o[x + w + 10 > dw ? "addClass" : "removeClass"]("vakata-context-right");
|
915
|
+
}
|
916
|
+
if(y + h + 10 > dh) {
|
917
|
+
e.css("bottom","-1px");
|
918
|
+
}
|
919
|
+
e.show();
|
920
|
+
},
|
921
|
+
|
922
|
+
/*
|
923
|
+
Function: $.vakata.context.show
|
924
|
+
Shows the context menu. Please note that at least one of _reference_ or _position_ should be specified.
|
925
|
+
|
926
|
+
Parameters:
|
927
|
+
reference - *jquery* associate the menu with a DOM element (optional)
|
928
|
+
position - *object* should contain _x_ and _y_ properties, those are the coordinates to show the menu at (optional
|
929
|
+
data - *object* the contextmenu description object. It should consist of keys, each key should be a <context_menu_item>. If not specified the function will search for $(reference).data('vakata_contextmenu') and use that.
|
930
|
+
|
931
|
+
Triggers:
|
932
|
+
<context_show>
|
933
|
+
|
934
|
+
Example:
|
935
|
+
>$(document).bind("contextmenu", function (e) {
|
936
|
+
> e.preventDefault();
|
937
|
+
> $.vakata.context.show(false, { x: e.pageX, y:e.pageY }, {
|
938
|
+
> "create" : {
|
939
|
+
> // only specify what you need
|
940
|
+
> "separator_after" : true,
|
941
|
+
> "label" : "Create",
|
942
|
+
> "action" : function (data) { alert("Create"); }
|
943
|
+
> },
|
944
|
+
> "rename" : {
|
945
|
+
> "label" : "Rename",
|
946
|
+
> "icon" : "./some-icon.png",
|
947
|
+
> "action" : function (data) { alert("Rename on " + data.reference); }
|
948
|
+
> },
|
949
|
+
> "edit" : {
|
950
|
+
> "label" : "Edit",
|
951
|
+
> // Clicking this won't hide the menu, the same can be achieved with:
|
952
|
+
> // "action" : function () { return false; }
|
953
|
+
> "submenu" : {
|
954
|
+
> "copy" : { "label" : "Copy", "action" : function () { } },
|
955
|
+
> "cut" : { "label" : "Cut", "action" : function () { } },
|
956
|
+
> "paste" : { "label" : "Paste", "_disabled" : true, "action" : function () { } }
|
957
|
+
> }
|
958
|
+
> },
|
959
|
+
> "delete" : {
|
960
|
+
> "separator_before" : true,
|
961
|
+
> "label" : "Delete",
|
962
|
+
> "action" : function (data) { alert("Delete"); }
|
963
|
+
> }
|
964
|
+
> });
|
965
|
+
>});
|
966
|
+
|
967
|
+
Variable: context_menu_item
|
968
|
+
*object* Used to construct a context menu entry, this structure will always be a part of an object.
|
969
|
+
|
970
|
+
separator_before - *boolean* should there be a separator before the item. Default is _false_.
|
971
|
+
separator_after - *boolean* should there be a separator after the item. Default is _false_.
|
972
|
+
icon - *string* if supplied this string is used for an icon, if it contains _/_ it is treated as file, otherwise it is applied as a class on an INS object.
|
973
|
+
label - *string* the text for this item
|
974
|
+
submenu - *object* if supplied this object is used to build a submenu. It should consist of keys, each of which is a <context_menu_item>.
|
975
|
+
_class - *string* if supplied this class is applied to the LI node.
|
976
|
+
_disabled - *boolean* is this item disabled.
|
977
|
+
action - *functon* if supplied it will be executed when this item is clicked / activated. If not supplied or the function returns _false_ the contextmenu won't be hidden after execution. To force a context use _$.proxy_.
|
978
|
+
In the function you will receive a single argument which is an object, consisting of four keys:
|
979
|
+
_item_ (the <context_menu_item> object),
|
980
|
+
_reference_ (the DOM node used when <$.vakata.context.show> was called),
|
981
|
+
_element_ (the DOM node of the context menu),
|
982
|
+
_position_ (an object consisting of _x_ and _y_ keys, represinting the current position of the menu)
|
983
|
+
|
984
|
+
See also:
|
985
|
+
<$.vakata.context.show>
|
986
|
+
*/
|
987
|
+
show : function (reference, position, data) {
|
988
|
+
if(vakata_context.element && vakata_context.element.length) {
|
989
|
+
vakata_context.element.width('');
|
990
|
+
}
|
991
|
+
switch(!0) {
|
992
|
+
case (!position && !reference):
|
993
|
+
return false;
|
994
|
+
case (!!position && !!reference):
|
995
|
+
vakata_context.reference = reference;
|
996
|
+
vakata_context.position_x = position.x;
|
997
|
+
vakata_context.position_y = position.y;
|
998
|
+
break;
|
999
|
+
case (!position && !!reference):
|
1000
|
+
vakata_context.reference = reference;
|
1001
|
+
var o = reference.offset();
|
1002
|
+
vakata_context.position_x = o.left + reference.outerHeight();
|
1003
|
+
vakata_context.position_y = o.top;
|
1004
|
+
break;
|
1005
|
+
case (!!position && !reference):
|
1006
|
+
vakata_context.position_x = position.x;
|
1007
|
+
vakata_context.position_y = position.y;
|
1008
|
+
break;
|
1009
|
+
}
|
1010
|
+
if(!!reference && !data && $(reference).data('vakata_contextmenu')) {
|
1011
|
+
data = $(reference).data('vakata_contextmenu');
|
1012
|
+
}
|
1013
|
+
if($.vakata.context._parse(data)) {
|
1014
|
+
vakata_context.element.html(vakata_context.html);
|
1015
|
+
}
|
1016
|
+
if(vakata_context.items.length) {
|
1017
|
+
var e = vakata_context.element,
|
1018
|
+
x = vakata_context.position_x,
|
1019
|
+
y = vakata_context.position_y,
|
1020
|
+
w = e.width(),
|
1021
|
+
h = e.height(),
|
1022
|
+
dw = $(document).width(),
|
1023
|
+
dh = $(document).height();
|
1024
|
+
|
1025
|
+
if(x + w + 20 > dw) {
|
1026
|
+
x = dw - (w + 20);
|
1027
|
+
}
|
1028
|
+
if(y + h + 20 > dh) {
|
1029
|
+
y = dh - (h + 20);
|
1030
|
+
}
|
1031
|
+
|
1032
|
+
vakata_context.element
|
1033
|
+
.css({ "left" : x, "top" : y })
|
1034
|
+
.show()
|
1035
|
+
.width(vakata_context.element.outerWidth()); // for ie6
|
1036
|
+
vakata_context.is_visible = true;
|
1037
|
+
/*
|
1038
|
+
Event: context_show
|
1039
|
+
Triggered when the context menu is shown. This event is triggered on the document in the *vakata* namespace.
|
1040
|
+
|
1041
|
+
Parameters:
|
1042
|
+
reference - the DOM node used when <$.vakata.context.show> was called
|
1043
|
+
element - the DOM node of the context menu
|
1044
|
+
position - an object consisting of _x_ and _y_ keys, represinting the position of the menu
|
1045
|
+
|
1046
|
+
Example:
|
1047
|
+
>$(document).bind("context_show.vakata", function (e, data) {
|
1048
|
+
> // do something
|
1049
|
+
>});
|
1050
|
+
*/
|
1051
|
+
$.vakata.context._trigger("show");
|
1052
|
+
}
|
1053
|
+
},
|
1054
|
+
/*
|
1055
|
+
Function: $.vakata.context.hide
|
1056
|
+
Used internally to hide the contextmenu after a click, or on mouseleave, etc.
|
1057
|
+
|
1058
|
+
Triggers:
|
1059
|
+
<context_hide>
|
1060
|
+
*/
|
1061
|
+
hide : function () {
|
1062
|
+
if(vakata_context.is_visible) {
|
1063
|
+
vakata_context.element.hide().find("ul").hide();
|
1064
|
+
vakata_context.is_visible = false;
|
1065
|
+
/*
|
1066
|
+
Event: context_hide
|
1067
|
+
Triggered when the context menu is hidden. This event is triggered on the document in the *vakata* namespace.
|
1068
|
+
|
1069
|
+
Parameters:
|
1070
|
+
reference - the DOM node used when <$.vakata.context.show> was called
|
1071
|
+
element - the DOM node of the context menu
|
1072
|
+
position - an object consisting of _x_ and _y_ keys, represinting the position of the menu
|
1073
|
+
|
1074
|
+
Example:
|
1075
|
+
>$(document).bind("context_hide.vakata", function (e, data) {
|
1076
|
+
> // do something
|
1077
|
+
>});
|
1078
|
+
*/
|
1079
|
+
$.vakata.context._trigger("hide");
|
1080
|
+
}
|
1081
|
+
}
|
1082
|
+
};
|
1083
|
+
$(function () {
|
1084
|
+
right_to_left = $("body").css("direction") === "rtl";
|
1085
|
+
var to = false,
|
1086
|
+
css_string = '' +
|
1087
|
+
'.vakata-context { display:none; _width:1px; } ' +
|
1088
|
+
'.vakata-context, ' +
|
1089
|
+
'.vakata-context ul { margin:0; padding:2px; position:absolute; background:#f5f5f5; border:1px solid #979797; ' +
|
1090
|
+
' -moz-box-shadow:5px 5px 4px -4px #666666; -webkit-box-shadow:2px 2px 2px #999999; box-shadow:2px 2px 2px #999999; }' +
|
1091
|
+
'.vakata-context ul { list-style:none; left:100%; margin-top:-2.7em; margin-left:-4px; } ' +
|
1092
|
+
'.vakata-context li.vakata-context-right ul { left:auto; right:100%; margin-left:auto; margin-right:-4px; } ' +
|
1093
|
+
'.vakata-context li { list-style:none; display:inline; }' +
|
1094
|
+
'.vakata-context li a { display:block; padding:0 2em 0 2em; text-decoration:none; width:auto; color:black; white-space:nowrap; line-height:2.4em; ' +
|
1095
|
+
' -moz-text-shadow:1px 1px 0px white; -webkit-text-shadow:1px 1px 0px white; text-shadow:1px 1px 0px white; ' +
|
1096
|
+
' -moz-border-radius:1px; -webkit-border-radius:1px; border-radius:1px; }' +
|
1097
|
+
'.vakata-context li a:hover { position:relative; background-color:#e8eff7; ' +
|
1098
|
+
' -moz-box-shadow:0px 0px 2px #0a6aa1; -webkit-box-shadow:0px 0px 2px #0a6aa1; box-shadow:0px 0px 2px #0a6aa1; }' +
|
1099
|
+
'.vakata-context li.vakata-context-hover > a { position:relative; background-color:#e8eff7; ' +
|
1100
|
+
' -moz-box-shadow:0px 0px 2px #0a6aa1; -webkit-box-shadow:0px 0px 2px #0a6aa1; box-shadow:0px 0px 2px #0a6aa1; }' +
|
1101
|
+
'.vakata-context li a.vakata-context-parent { background-image:url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAIORI4JlrqN1oMSnmmZDQUAOw=="); background-position:right center; background-repeat:no-repeat; } ' +
|
1102
|
+
'.vakata-context li.vakata-context-separator a, ' +
|
1103
|
+
'.vakata-context li.vakata-context-separator a:hover { background:white; border:0; border-top:1px solid #e2e3e3; height:1px; min-height:1px; max-height:1px; padding:0; margin:0 0 0 2.4em; border-left:1px solid #e0e0e0; _overflow:hidden; ' +
|
1104
|
+
' -moz-text-shadow:0 0 0 transparent; -webkit-text-shadow:0 0 0 transparent; text-shadow:0 0 0 transparent; ' +
|
1105
|
+
' -moz-box-shadow:0 0 0 transparent; -webkit-box-shadow:0 0 0 transparent; box-shadow:0 0 0 transparent; ' +
|
1106
|
+
' -moz-border-radius:0; -webkit-border-radius:0; border-radius:0; }' +
|
1107
|
+
'.vakata-context li.vakata-contextmenu-disabled a, .vakata-context li.vakata-contextmenu-disabled a:hover { color:silver; background-color:transparent; border:0; box-shadow:0 0 0; }' +
|
1108
|
+
'' +
|
1109
|
+
'.vakata-context li a ins { text-decoration:none; display:inline-block; width:2.4em; height:2.4em; background:transparent; margin:0 0 0 -2em; } ' +
|
1110
|
+
'.vakata-context li a span { display:inline-block; width:1px; height:2.4em; background:white; margin:0 0.5em 0 0; border-left:1px solid #e2e3e3; _overflow:hidden; } ' +
|
1111
|
+
'' +
|
1112
|
+
'.vakata-context-rtl ul { left:auto; right:100%; margin-left:auto; margin-right:-4px; } ' +
|
1113
|
+
'.vakata-context-rtl li a.vakata-context-parent { background-image:url("data:image/gif;base64,R0lGODlhCwAHAIAAACgoKP///yH5BAEAAAEALAAAAAALAAcAAAINjI+AC7rWHIsPtmoxLAA7"); background-position:left center; background-repeat:no-repeat; } ' +
|
1114
|
+
'.vakata-context-rtl li.vakata-context-separator a { margin:0 2.4em 0 0; border-left:0; border-right:1px solid #e2e3e3;} ' +
|
1115
|
+
'.vakata-context-rtl li.vakata-context-left ul { right:auto; left:100%; margin-left:-4px; margin-right:auto; } ' +
|
1116
|
+
'.vakata-context-rtl li a ins { margin:0 -2em 0 0; } ' +
|
1117
|
+
'.vakata-context-rtl li a span { margin:0 0 0 0.5em; border-left-color:white; background:#e2e3e3; } ' +
|
1118
|
+
'';
|
1119
|
+
$.vakata.css.add_sheet({ str : css_string, title : "vakata-context" });
|
1120
|
+
|
1121
|
+
vakata_context.element = $("<ul class='vakata-context'></ul>");
|
1122
|
+
vakata_context.element
|
1123
|
+
.delegate("li", "mouseenter", function (e) {
|
1124
|
+
e.stopImmediatePropagation();
|
1125
|
+
|
1126
|
+
if($.contains(this, e.relatedTarget)) {
|
1127
|
+
// премахнато заради delegate mouseleave по-долу
|
1128
|
+
// $(this).find(".vakata-context-hover").removeClass("vakata-context-hover");
|
1129
|
+
return;
|
1130
|
+
}
|
1131
|
+
|
1132
|
+
if(to) { clearTimeout(to); }
|
1133
|
+
vakata_context.element.find(".vakata-context-hover").removeClass("vakata-context-hover").end();
|
1134
|
+
|
1135
|
+
$(this)
|
1136
|
+
.siblings().find("ul").hide().end().end()
|
1137
|
+
.parentsUntil(".vakata-context", "li").andSelf().addClass("vakata-context-hover");
|
1138
|
+
$.vakata.context._show_submenu(this);
|
1139
|
+
})
|
1140
|
+
// тестово - дали не натоварва?
|
1141
|
+
.delegate("li", "mouseleave", function (e) {
|
1142
|
+
if($.contains(this, e.relatedTarget)) { return; }
|
1143
|
+
$(this).find(".vakata-context-hover").andSelf().removeClass("vakata-context-hover");
|
1144
|
+
})
|
1145
|
+
.bind("mouseleave", function (e) {
|
1146
|
+
$(this).find(".vakata-context-hover").removeClass("vakata-context-hover");
|
1147
|
+
if($.vakata.context.settings.hide_onmouseleave) {
|
1148
|
+
to = setTimeout(
|
1149
|
+
(function (t) {
|
1150
|
+
return function () { $.vakata.context.hide(); };
|
1151
|
+
})(this), $.vakata.context.settings.hide_onmouseleave);
|
1152
|
+
}
|
1153
|
+
})
|
1154
|
+
.delegate("a", "click", function (e) {
|
1155
|
+
e.preventDefault();
|
1156
|
+
})
|
1157
|
+
.delegate("a", "mouseup", function (e) {
|
1158
|
+
if(!$(this).blur().parent().hasClass("vakata-context-disabled") && $.vakata.context._execute($(this).attr("rel")) !== false) {
|
1159
|
+
$.vakata.context.hide();
|
1160
|
+
}
|
1161
|
+
})
|
1162
|
+
.appendTo("body");
|
1163
|
+
|
1164
|
+
$(document)
|
1165
|
+
.bind("mousedown", function (e) {
|
1166
|
+
if(vakata_context.is_visible && !$.contains(vakata_context.element[0], e.target)) { $.vakata.context.hide(); }
|
1167
|
+
})
|
1168
|
+
.bind("context_show.vakata", function (e, data) {
|
1169
|
+
vakata_context.element.find("li:has(ul)").children("a").addClass("vakata-context-parent");
|
1170
|
+
if(right_to_left) {
|
1171
|
+
vakata_context.element.addClass("vakata-context-rtl").css("direction", "rtl");
|
1172
|
+
}
|
1173
|
+
// also apply a RTL class?
|
1174
|
+
vakata_context.element.find("ul").hide().end();
|
1175
|
+
});
|
1176
|
+
|
1177
|
+
if(typeof $.hotkeys !== "undefined" || typeof $.vakata_hotkeys !== "undefined") {
|
1178
|
+
$(document)
|
1179
|
+
.bind("keydown", "up", function (e) {
|
1180
|
+
if(vakata_context.is_visible) {
|
1181
|
+
var o = vakata_context.element.find("ul:visible").andSelf().last().children(".vakata-context-hover").removeClass("vakata-context-hover").prevAll("li:not(.vakata-context-separator)").first();
|
1182
|
+
if(!o.length) { o = vakata_context.element.find("ul:visible").andSelf().last().children("li:not(.vakata-context-separator)").last(); }
|
1183
|
+
o.addClass("vakata-context-hover");
|
1184
|
+
e.stopImmediatePropagation();
|
1185
|
+
e.preventDefault();
|
1186
|
+
}
|
1187
|
+
})
|
1188
|
+
.bind("keydown", "down", function (e) {
|
1189
|
+
if(vakata_context.is_visible) {
|
1190
|
+
var o = vakata_context.element.find("ul:visible").andSelf().last().children(".vakata-context-hover").removeClass("vakata-context-hover").nextAll("li:not(.vakata-context-separator)").first();
|
1191
|
+
if(!o.length) { o = vakata_context.element.find("ul:visible").andSelf().last().children("li:not(.vakata-context-separator)").first(); }
|
1192
|
+
o.addClass("vakata-context-hover");
|
1193
|
+
e.stopImmediatePropagation();
|
1194
|
+
e.preventDefault();
|
1195
|
+
}
|
1196
|
+
})
|
1197
|
+
.bind("keydown", "right", function (e) {
|
1198
|
+
if(vakata_context.is_visible) {
|
1199
|
+
vakata_context.element.find(".vakata-context-hover").last().children("ul").show().children("li:not(.vakata-context-separator)").removeClass("vakata-context-hover").first().addClass("vakata-context-hover");
|
1200
|
+
e.stopImmediatePropagation();
|
1201
|
+
e.preventDefault();
|
1202
|
+
}
|
1203
|
+
})
|
1204
|
+
.bind("keydown", "left", function (e) {
|
1205
|
+
if(vakata_context.is_visible) {
|
1206
|
+
vakata_context.element.find(".vakata-context-hover").last().parents("li:eq(0)").find("ul").hide().find(".vakata-context-hover").removeClass("vakata-context-hover");
|
1207
|
+
e.stopImmediatePropagation();
|
1208
|
+
e.preventDefault();
|
1209
|
+
}
|
1210
|
+
})
|
1211
|
+
.bind("keydown", "esc", function (e) {
|
1212
|
+
$.vakata.context.hide();
|
1213
|
+
e.preventDefault();
|
1214
|
+
})
|
1215
|
+
.bind("keydown", "space", function (e) {
|
1216
|
+
vakata_context.element.find(".vakata-context-hover").last().children("a").click();
|
1217
|
+
e.preventDefault();
|
1218
|
+
});
|
1219
|
+
}
|
1220
|
+
});
|
1221
|
+
})(jQuery);
|
1222
|
+
|
1223
|
+
/*
|
1224
|
+
Group: JSON
|
1225
|
+
Functions needed to encode/decode JSON. Based on the jQuery JSON Plugin.
|
1226
|
+
*/
|
1227
|
+
(function ($) {
|
1228
|
+
// private function for quoting strings
|
1229
|
+
var _quote = function (str) {
|
1230
|
+
var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g,
|
1231
|
+
meta = { '\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"' :'\\"','\\':'\\\\' };
|
1232
|
+
if(str.match(escapeable)) {
|
1233
|
+
return '"' + str.replace(escapeable, function (a) {
|
1234
|
+
var c = meta[a];
|
1235
|
+
if(typeof c === 'string') { return c; }
|
1236
|
+
c = a.charCodeAt();
|
1237
|
+
return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
|
1238
|
+
}) + '"';
|
1239
|
+
}
|
1240
|
+
return '"' + str + '"';
|
1241
|
+
};
|
1242
|
+
/*
|
1243
|
+
Variable: $.vakata.json
|
1244
|
+
*object* holds all JSON related functions.
|
1245
|
+
*/
|
1246
|
+
$.vakata.json = {
|
1247
|
+
/*
|
1248
|
+
Function: $.vakata.json.encode
|
1249
|
+
A function for encoding data in a JSON notated string.
|
1250
|
+
|
1251
|
+
Parameters:
|
1252
|
+
o - *mixed* the data to be encoded
|
1253
|
+
|
1254
|
+
Returns:
|
1255
|
+
string - the encoded data
|
1256
|
+
*/
|
1257
|
+
encode : function (o) {
|
1258
|
+
if (o === null) { return "null"; }
|
1259
|
+
|
1260
|
+
var tmp = [], i;
|
1261
|
+
switch(typeof(o)) {
|
1262
|
+
case "undefined":
|
1263
|
+
return undefined;
|
1264
|
+
case "number":
|
1265
|
+
case "boolean":
|
1266
|
+
return o + "";
|
1267
|
+
case "string":
|
1268
|
+
return _quote(o);
|
1269
|
+
case "object":
|
1270
|
+
if($.isFunction(o.toJSON)) {
|
1271
|
+
return $.vakata.json.encode(o.toJSON());
|
1272
|
+
}
|
1273
|
+
if(o.constructor === Date) {
|
1274
|
+
return '"' +
|
1275
|
+
o.getUTCFullYear() + '-' +
|
1276
|
+
String("0" + (o.getUTCMonth() + 1)).slice(-2) + '-' +
|
1277
|
+
String("0" + o.getUTCDate()).slice(-2) + 'T' +
|
1278
|
+
String("0" + o.getUTCHours()).slice(-2) + ':' +
|
1279
|
+
String("0" + o.getUTCMinutes()).slice(-2) + ':' +
|
1280
|
+
String("0" + o.getUTCSeconds()).slice(-2) + '.' +
|
1281
|
+
String("00" + o.getUTCMilliseconds()).slice(-3) + 'Z"';
|
1282
|
+
}
|
1283
|
+
if(o.constructor === Array) {
|
1284
|
+
for(i = 0; i < o.length; i++) {
|
1285
|
+
tmp.push( $.vakata.json.encode(o[i]) || "null" );
|
1286
|
+
}
|
1287
|
+
return "[" + tmp.join(",") + "]";
|
1288
|
+
}
|
1289
|
+
|
1290
|
+
$.each(o, function (i, v) {
|
1291
|
+
if($.isFunction(v)) { return true; }
|
1292
|
+
i = typeof i === "number" ? '"' + i + '"' : _quote(i);
|
1293
|
+
v = $.vakata.json.encode(v);
|
1294
|
+
tmp.push(i + ":" + v);
|
1295
|
+
});
|
1296
|
+
return "{" + tmp.join(", ") + "}";
|
1297
|
+
}
|
1298
|
+
},
|
1299
|
+
/*
|
1300
|
+
Function: $.vakata.json.decode
|
1301
|
+
Exists for consistency and is a simple wrapper for jQuery.parseJSON.
|
1302
|
+
|
1303
|
+
Parameters:
|
1304
|
+
json - the string to be decoded
|
1305
|
+
|
1306
|
+
Returns:
|
1307
|
+
Same as jQuery.parseJSON
|
1308
|
+
*/
|
1309
|
+
decode : function (json) {
|
1310
|
+
return $.parseJSON(json);
|
1311
|
+
}
|
1312
|
+
};
|
1313
|
+
})(jQuery);
|
1314
|
+
|
1315
|
+
/*
|
1316
|
+
Group: Cookie
|
1317
|
+
A copy of the jQuery cookie plugin.
|
1318
|
+
*/
|
1319
|
+
(function ($) {
|
1320
|
+
/*
|
1321
|
+
Function: $.vakata.cookie
|
1322
|
+
A function for getting and setting cookies.
|
1323
|
+
|
1324
|
+
Parameters:
|
1325
|
+
Same as the original plugin
|
1326
|
+
|
1327
|
+
Returns:
|
1328
|
+
string - the encoded data
|
1329
|
+
*/
|
1330
|
+
$.vakata.cookie = function (key, value, options) {
|
1331
|
+
var days, t, result, decode;
|
1332
|
+
if (arguments.length > 1 && String(value) !== "[object Object]") {
|
1333
|
+
options = $.extend({}, options);
|
1334
|
+
if(value === null || value === undefined) { options.expires = -1; }
|
1335
|
+
if(typeof options.expires === 'number') { days = options.expires; t = options.expires = new Date(); t.setDate(t.getDate() + days); }
|
1336
|
+
value = String(value);
|
1337
|
+
return (document.cookie = [
|
1338
|
+
encodeURIComponent(key), '=',
|
1339
|
+
options.raw ? value : encodeURIComponent(value),
|
1340
|
+
options.expires ? '; expires=' + options.expires.toUTCString() : '',
|
1341
|
+
options.path ? '; path=' + options.path : '',
|
1342
|
+
options.domain ? '; domain=' + options.domain : '',
|
1343
|
+
options.secure ? '; secure' : ''
|
1344
|
+
].join(''));
|
1345
|
+
}
|
1346
|
+
options = value || {};
|
1347
|
+
decode = options.raw ? function (s) { return s; } : decodeURIComponent;
|
1348
|
+
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
|
1349
|
+
};
|
1350
|
+
})(jQuery);
|
1351
|
+
|
1352
|
+
/*
|
1353
|
+
Group: LocalStorage
|
1354
|
+
Functions for dealing with localStorage with fallback to userData or cookies. A slight modification of jstorage.
|
1355
|
+
*/
|
1356
|
+
|
1357
|
+
(function ($) {
|
1358
|
+
var _storage = {},
|
1359
|
+
_storage_service = {jStorage:"{}"},
|
1360
|
+
_storage_elm = null,
|
1361
|
+
_storage_size = 0,
|
1362
|
+
json_encode = $.vakata.json.encode,
|
1363
|
+
json_decode = $.vakata.json.decode,
|
1364
|
+
_backend = false,
|
1365
|
+
_ttl_timeout = false;
|
1366
|
+
|
1367
|
+
function _init() {
|
1368
|
+
var localStorageReallyWorks = false;
|
1369
|
+
if("localStorage" in window){
|
1370
|
+
try {
|
1371
|
+
window.localStorage.setItem('_tmptest', 'tmpval');
|
1372
|
+
localStorageReallyWorks = true;
|
1373
|
+
window.localStorage.removeItem('_tmptest');
|
1374
|
+
} catch(BogusQuotaExceededErrorOnIos5) {
|
1375
|
+
// Thanks be to iOS5 Private Browsing mode which throws
|
1376
|
+
// QUOTA_EXCEEDED_ERRROR DOM Exception 22.
|
1377
|
+
}
|
1378
|
+
}
|
1379
|
+
|
1380
|
+
if(localStorageReallyWorks){
|
1381
|
+
try {
|
1382
|
+
if(window.localStorage) {
|
1383
|
+
_storage_service = window.localStorage;
|
1384
|
+
_backend = "localStorage";
|
1385
|
+
}
|
1386
|
+
} catch(E3) {/* Firefox fails when touching localStorage and cookies are disabled */}
|
1387
|
+
}
|
1388
|
+
else if("globalStorage" in window) {
|
1389
|
+
try {
|
1390
|
+
if(window.globalStorage) {
|
1391
|
+
_storage_service = window.globalStorage[window.location.hostname];
|
1392
|
+
_backend = "globalStorage";
|
1393
|
+
}
|
1394
|
+
} catch(E4) {/* Firefox fails when touching localStorage and cookies are disabled */}
|
1395
|
+
}
|
1396
|
+
else {
|
1397
|
+
_storage_elm = document.createElement('link');
|
1398
|
+
if(_storage_elm.addBehavior) {
|
1399
|
+
_storage_elm.style.behavior = 'url(#default#userData)';
|
1400
|
+
document.getElementsByTagName('head')[0].appendChild(_storage_elm);
|
1401
|
+
try {
|
1402
|
+
_storage_elm.load("jStorage");
|
1403
|
+
var data = "{}";
|
1404
|
+
data = _storage_elm.getAttribute("jStorage");
|
1405
|
+
_storage_service.jStorage = data;
|
1406
|
+
_backend = "userDataBehavior";
|
1407
|
+
} catch(E5) {}
|
1408
|
+
}
|
1409
|
+
if(
|
1410
|
+
!_backend && (
|
1411
|
+
!!$.vakata.cookie('__vjstorage') ||
|
1412
|
+
($.vakata.cookie('__vjstorage', '{}', { 'expires' : 365 }) && $.vakata.cookie('__vjstorage') === '{}')
|
1413
|
+
)
|
1414
|
+
) {
|
1415
|
+
_storage_elm = null;
|
1416
|
+
_storage_service.jStorage = $.vakata.cookie('__vjstorage');
|
1417
|
+
_backend = "cookie";
|
1418
|
+
}
|
1419
|
+
|
1420
|
+
if(!_backend) {
|
1421
|
+
_storage_elm = null;
|
1422
|
+
return;
|
1423
|
+
}
|
1424
|
+
}
|
1425
|
+
_load_storage();
|
1426
|
+
_handleTTL();
|
1427
|
+
}
|
1428
|
+
|
1429
|
+
function _load_storage() {
|
1430
|
+
if(_storage_service.jStorage) {
|
1431
|
+
try {
|
1432
|
+
_storage = json_decode(String(_storage_service.jStorage));
|
1433
|
+
} catch(E6) { _storage_service.jStorage = "{}"; }
|
1434
|
+
} else {
|
1435
|
+
_storage_service.jStorage = "{}";
|
1436
|
+
}
|
1437
|
+
_storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0;
|
1438
|
+
}
|
1439
|
+
|
1440
|
+
function _save() {
|
1441
|
+
try {
|
1442
|
+
_storage_service.jStorage = json_encode(_storage);
|
1443
|
+
if(_backend === 'userDataBehavior') {
|
1444
|
+
_storage_elm.setAttribute("jStorage", _storage_service.jStorage);
|
1445
|
+
_storage_elm.save("jStorage");
|
1446
|
+
}
|
1447
|
+
if(_backend === 'cookie') {
|
1448
|
+
$.vakata.cookie('__vjstorage', _storage_service.jStorage, { 'expires' : 365 });
|
1449
|
+
}
|
1450
|
+
_storage_size = _storage_service.jStorage?String(_storage_service.jStorage).length:0;
|
1451
|
+
} catch(E7) { /* probably cache is full, nothing is saved this way*/ }
|
1452
|
+
}
|
1453
|
+
|
1454
|
+
function _checkKey(key) {
|
1455
|
+
if(!key || (typeof key !== "string" && typeof key !== "number")){
|
1456
|
+
throw new TypeError('Key name must be string or numeric');
|
1457
|
+
}
|
1458
|
+
if(key === "__jstorage_meta") {
|
1459
|
+
throw new TypeError('Reserved key name');
|
1460
|
+
}
|
1461
|
+
return true;
|
1462
|
+
}
|
1463
|
+
|
1464
|
+
function _handleTTL() {
|
1465
|
+
var curtime = +new Date(),
|
1466
|
+
i,
|
1467
|
+
TTL,
|
1468
|
+
nextExpire = Infinity,
|
1469
|
+
changed = false;
|
1470
|
+
|
1471
|
+
if(_ttl_timeout !== false) {
|
1472
|
+
clearTimeout(_ttl_timeout);
|
1473
|
+
}
|
1474
|
+
if(!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL !== "object"){
|
1475
|
+
return;
|
1476
|
+
}
|
1477
|
+
TTL = _storage.__jstorage_meta.TTL;
|
1478
|
+
for(i in TTL) {
|
1479
|
+
if(TTL.hasOwnProperty(i)) {
|
1480
|
+
if(TTL[i] <= curtime) {
|
1481
|
+
delete TTL[i];
|
1482
|
+
delete _storage[i];
|
1483
|
+
changed = true;
|
1484
|
+
}
|
1485
|
+
else if(TTL[i] < nextExpire) {
|
1486
|
+
nextExpire = TTL[i];
|
1487
|
+
}
|
1488
|
+
}
|
1489
|
+
}
|
1490
|
+
|
1491
|
+
// set next check
|
1492
|
+
if(nextExpire !== Infinity) {
|
1493
|
+
_ttl_timeout = setTimeout(_handleTTL, nextExpire - curtime);
|
1494
|
+
}
|
1495
|
+
// save changes
|
1496
|
+
if(changed) {
|
1497
|
+
_save();
|
1498
|
+
}
|
1499
|
+
}
|
1500
|
+
|
1501
|
+
/*
|
1502
|
+
Variable: $.vakata.storage
|
1503
|
+
*object* holds all storage related functions and properties.
|
1504
|
+
*/
|
1505
|
+
$.vakata.storage = {
|
1506
|
+
/*
|
1507
|
+
Variable: $.vakata.storage.version
|
1508
|
+
*string* the version of jstorage used
|
1509
|
+
*/
|
1510
|
+
version: "0.1.6.1",
|
1511
|
+
/*
|
1512
|
+
Function: $.vakata.storage.set
|
1513
|
+
Set a key to a value
|
1514
|
+
|
1515
|
+
Parameters:
|
1516
|
+
key - the key
|
1517
|
+
value - the value
|
1518
|
+
|
1519
|
+
Returns:
|
1520
|
+
_value_
|
1521
|
+
*/
|
1522
|
+
set : function (key, value) {
|
1523
|
+
_checkKey(key);
|
1524
|
+
_storage[key] = value;
|
1525
|
+
_save();
|
1526
|
+
return value;
|
1527
|
+
},
|
1528
|
+
/*
|
1529
|
+
Function: $.vakata.storage.get
|
1530
|
+
Get a value by key.
|
1531
|
+
|
1532
|
+
Parameters:
|
1533
|
+
key - the key
|
1534
|
+
def - the value to return if _key_ is not found
|
1535
|
+
|
1536
|
+
Returns:
|
1537
|
+
The found value, _def_ if key not found or _null_ if _def_ is not supplied.
|
1538
|
+
*/
|
1539
|
+
get : function (key, def) {
|
1540
|
+
_checkKey(key);
|
1541
|
+
if(key in _storage){
|
1542
|
+
return _storage[key];
|
1543
|
+
}
|
1544
|
+
return typeof(def) === 'undefined' ? null : def;
|
1545
|
+
},
|
1546
|
+
/*
|
1547
|
+
Function: $.vakata.storage.del
|
1548
|
+
Remove a key.
|
1549
|
+
|
1550
|
+
Parameters:
|
1551
|
+
key - the key
|
1552
|
+
|
1553
|
+
Returns:
|
1554
|
+
*boolean*
|
1555
|
+
*/
|
1556
|
+
del : function (key) {
|
1557
|
+
_checkKey(key);
|
1558
|
+
if(key in _storage) {
|
1559
|
+
delete _storage[key];
|
1560
|
+
|
1561
|
+
if(_storage.__jstorage_meta && typeof _storage.__jstorage_meta.TTL === "object" && key in _storage.__jstorage_meta.TTL) {
|
1562
|
+
delete _storage.__jstorage_meta.TTL[key];
|
1563
|
+
}
|
1564
|
+
_save();
|
1565
|
+
return true;
|
1566
|
+
}
|
1567
|
+
return false;
|
1568
|
+
},
|
1569
|
+
|
1570
|
+
setTTL: function(key, ttl){
|
1571
|
+
var curtime = +new Date();
|
1572
|
+
|
1573
|
+
_checkKey(key);
|
1574
|
+
ttl = Number(ttl) || 0;
|
1575
|
+
if(key in _storage){
|
1576
|
+
if(!_storage.__jstorage_meta){
|
1577
|
+
_storage.__jstorage_meta = {};
|
1578
|
+
}
|
1579
|
+
if(!_storage.__jstorage_meta.TTL) {
|
1580
|
+
_storage.__jstorage_meta.TTL = {};
|
1581
|
+
}
|
1582
|
+
if(ttl > 0) {
|
1583
|
+
_storage.__jstorage_meta.TTL[key] = curtime + ttl;
|
1584
|
+
}
|
1585
|
+
else {
|
1586
|
+
delete _storage.__jstorage_meta.TTL[key];
|
1587
|
+
}
|
1588
|
+
_save();
|
1589
|
+
_handleTTL();
|
1590
|
+
return true;
|
1591
|
+
}
|
1592
|
+
return false;
|
1593
|
+
},
|
1594
|
+
|
1595
|
+
/*
|
1596
|
+
Function: $.vakata.storage.flush
|
1597
|
+
Empty the storage.
|
1598
|
+
|
1599
|
+
Returns:
|
1600
|
+
_true_
|
1601
|
+
*/
|
1602
|
+
flush : function(){
|
1603
|
+
_storage = {};
|
1604
|
+
_save();
|
1605
|
+
// try{ window.localStorage.clear(); } catch(E8) { }
|
1606
|
+
return true;
|
1607
|
+
},
|
1608
|
+
/*
|
1609
|
+
Function: $.vakata.storage.storageObj
|
1610
|
+
Get a read only copy of the whole storage.
|
1611
|
+
|
1612
|
+
Returns:
|
1613
|
+
*object*
|
1614
|
+
*/
|
1615
|
+
storageObj : function(){
|
1616
|
+
function F() {}
|
1617
|
+
F.prototype = _storage;
|
1618
|
+
return new F();
|
1619
|
+
},
|
1620
|
+
/*
|
1621
|
+
Function: $.vakata.storage.index
|
1622
|
+
Get an array of all the set keys in the storage.
|
1623
|
+
|
1624
|
+
Returns:
|
1625
|
+
*array*
|
1626
|
+
*/
|
1627
|
+
index : function(){
|
1628
|
+
var index = [], i;
|
1629
|
+
$.each(_storage, function (i, v) { if(i !== "__jstorage_meta") { index.push(i); } });
|
1630
|
+
return index;
|
1631
|
+
},
|
1632
|
+
/*
|
1633
|
+
Function: $.vakata.storage.storageSize
|
1634
|
+
Get the size of all items in the storage in bytes.
|
1635
|
+
|
1636
|
+
Returns:
|
1637
|
+
*number*
|
1638
|
+
*/
|
1639
|
+
storageSize : function(){
|
1640
|
+
return _storage_size;
|
1641
|
+
},
|
1642
|
+
/*
|
1643
|
+
Function: $.vakata.storage.currentBackend
|
1644
|
+
Get the current backend used.
|
1645
|
+
|
1646
|
+
Returns:
|
1647
|
+
*string*
|
1648
|
+
*/
|
1649
|
+
currentBackend : function(){
|
1650
|
+
return _backend;
|
1651
|
+
},
|
1652
|
+
/*
|
1653
|
+
Function: $.vakata.storage.storageAvailable
|
1654
|
+
See if storage functionality is available.
|
1655
|
+
|
1656
|
+
Returns:
|
1657
|
+
*boolean*
|
1658
|
+
*/
|
1659
|
+
storageAvailable : function(){
|
1660
|
+
return !!_backend;
|
1661
|
+
}
|
1662
|
+
};
|
1663
|
+
_init();
|
1664
|
+
})(jQuery);
|
1665
|
+
|
1666
|
+
/*
|
1667
|
+
Group: PrettyDate
|
1668
|
+
Modifies time elements to a more human readable value. Taken from: https://github.com/zachleat/Humane-Dates/blob/master/src/humane.js
|
1669
|
+
*/
|
1670
|
+
(function ($) {
|
1671
|
+
/*
|
1672
|
+
Variable: $.vakata.pretty_date
|
1673
|
+
*object* holds all pretty-date related functions and properties.
|
1674
|
+
*/
|
1675
|
+
$.vakata.pretty_date = {
|
1676
|
+
/*
|
1677
|
+
Variable: $.vakata.pretty_date.lang
|
1678
|
+
*object* the localization to use.
|
1679
|
+
*/
|
1680
|
+
lang : {
|
1681
|
+
ago: 'Ago',
|
1682
|
+
from: 'From Now',
|
1683
|
+
now: 'Just Now',
|
1684
|
+
minute: 'Minute',
|
1685
|
+
minutes: 'Minutes',
|
1686
|
+
hour: 'Hour',
|
1687
|
+
hours: 'Hours',
|
1688
|
+
day: 'Day',
|
1689
|
+
days: 'Days',
|
1690
|
+
week: 'Week',
|
1691
|
+
weeks: 'Weeks',
|
1692
|
+
month: 'Month',
|
1693
|
+
months: 'Months',
|
1694
|
+
year: 'Year',
|
1695
|
+
years: 'Years'
|
1696
|
+
},
|
1697
|
+
/*
|
1698
|
+
Function: $.vakata.pretty_date.parse
|
1699
|
+
Parses the difference between to dates to a human readable string.
|
1700
|
+
|
1701
|
+
Parameters:
|
1702
|
+
date - the date to calculate from (а string in this YYYY-MM-DDTHH:MM:SSZ format - UTC)
|
1703
|
+
comareTo - the date to compare to (as date), if left empty the current date is used
|
1704
|
+
|
1705
|
+
Returns:
|
1706
|
+
*mixed* - the formatted string on success or _null_ on error
|
1707
|
+
*/
|
1708
|
+
parse : function (date, compareTo) {
|
1709
|
+
// remove the timezone (always use gmdate on server side)
|
1710
|
+
date = new Date(date.replace(/-/g,"/").replace(/[TZ]/g," ").replace(/\+\d\d\:\d\d$/,''));
|
1711
|
+
compareTo = compareTo || new Date();
|
1712
|
+
var lang = $.vakata.pretty_date.lang,
|
1713
|
+
formats = [
|
1714
|
+
[60, lang.now],
|
1715
|
+
[3600, lang.minute, lang.minutes, 60], // 60 minutes, 1 minute
|
1716
|
+
[86400, lang.hour, lang.hours, 3600], // 24 hours, 1 hour
|
1717
|
+
[604800, lang.day, lang.days, 86400], // 7 days, 1 day
|
1718
|
+
[2628000, lang.week, lang.weeks, 604800], // ~1 month, 1 week
|
1719
|
+
[31536000, lang.month, lang.months, 2628000], // 1 year, ~1 month
|
1720
|
+
[Infinity, lang.year, lang.years, 31536000] // Infinity, 1 year
|
1721
|
+
],
|
1722
|
+
seconds = (compareTo - date + compareTo.getTimezoneOffset() * 60000) / 1000,
|
1723
|
+
normalize = function (val, single) {
|
1724
|
+
var margin = 0.1;
|
1725
|
+
if(val >= single && val <= single * (1+margin)) {
|
1726
|
+
return single;
|
1727
|
+
}
|
1728
|
+
return val;
|
1729
|
+
},
|
1730
|
+
token;
|
1731
|
+
|
1732
|
+
if(seconds < 0) {
|
1733
|
+
seconds = Math.abs(seconds);
|
1734
|
+
token = ' ' + lang.from;
|
1735
|
+
}
|
1736
|
+
else {
|
1737
|
+
token = ' ' + lang.ago;
|
1738
|
+
}
|
1739
|
+
|
1740
|
+
for(var i = 0, format = formats[0]; formats[i]; format = formats[++i]) {
|
1741
|
+
if(seconds < format[0]) {
|
1742
|
+
if(i === 0) {
|
1743
|
+
return format[1];
|
1744
|
+
}
|
1745
|
+
var val = Math.ceil(normalize(seconds, format[3]) / (format[3]));
|
1746
|
+
return val +
|
1747
|
+
' ' +
|
1748
|
+
(val !== 1 ? format[2] : format[1]) +
|
1749
|
+
(i > 0 ? token : '');
|
1750
|
+
}
|
1751
|
+
}
|
1752
|
+
},
|
1753
|
+
/*
|
1754
|
+
Function: $.vakata.pretty_date.init
|
1755
|
+
Parses all time elements in the document and keeps reparsing them every few seconds.
|
1756
|
+
|
1757
|
+
Parameters:
|
1758
|
+
i - the interval for reparsing (in milliseconds). Default is 60000.
|
1759
|
+
format - the format to use, example: _Published %{s}._. Default is _%{s}_.
|
1760
|
+
*/
|
1761
|
+
init : function (i, format) {
|
1762
|
+
$("time, [datetime]").vakata_pretty_date(format);
|
1763
|
+
setInterval(function(){ $("time, [datetime]").vakata_pretty_date(format); }, i || 60000);
|
1764
|
+
}
|
1765
|
+
};
|
1766
|
+
/*
|
1767
|
+
Function: $().vakata_pretty_date
|
1768
|
+
Sets the HTML of every element to the parsed difference of its _datetime_ attribute and the compare parameter.
|
1769
|
+
|
1770
|
+
Parameters:
|
1771
|
+
format - makes it possible to modify the parsed string, example: _Published %{s}._. Default is _%{s}_.
|
1772
|
+
compare - the date to compare to. Default is the current date.
|
1773
|
+
*/
|
1774
|
+
$.fn.vakata_pretty_date = function (format, compare) {
|
1775
|
+
if(!format) { format = '%{s}'; }
|
1776
|
+
return this.each(function() {
|
1777
|
+
var $t = jQuery(this),
|
1778
|
+
date = $.vakata.pretty_date.parse($t.attr('datetime'), compare);
|
1779
|
+
if(date) {
|
1780
|
+
date = format.replace('%{s}', date);
|
1781
|
+
if($t.html() !== date) {
|
1782
|
+
$t.html(date);
|
1783
|
+
}
|
1784
|
+
}
|
1785
|
+
});
|
1786
|
+
};
|
1787
|
+
})(jQuery);
|
1788
|
+
|
1789
|
+
/*
|
1790
|
+
Group: Selection
|
1791
|
+
Selection related functions
|
1792
|
+
*/
|
1793
|
+
(function ($) {
|
1794
|
+
/*
|
1795
|
+
Variable: $.vakata.selection
|
1796
|
+
*object* holds all selection related functions and properties.
|
1797
|
+
*/
|
1798
|
+
$.vakata.selection = {
|
1799
|
+
/*
|
1800
|
+
Function: $.vakata.selection.get
|
1801
|
+
Gets the current selection.
|
1802
|
+
|
1803
|
+
Parameters:
|
1804
|
+
as_text - a boolean - if set to _true_ selection is returned as text, otherwise as HTML
|
1805
|
+
|
1806
|
+
Returns:
|
1807
|
+
*string* - the current selection
|
1808
|
+
*/
|
1809
|
+
get : function (as_text) {
|
1810
|
+
if(window.getSelection) {
|
1811
|
+
if(as_text) {
|
1812
|
+
return window.getSelection().toString();
|
1813
|
+
}
|
1814
|
+
var userSelection = window.getSelection(),
|
1815
|
+
range = userSelection.getRangeAt && userSelection.rangeCount ? userSelection.getRangeAt(0) : document.createRange(),
|
1816
|
+
div = document.createElement('div');
|
1817
|
+
if(!userSelection.getRangeAt) {
|
1818
|
+
range.setStart(userSelection.anchorNode, userSelection.anchorOffset);
|
1819
|
+
range.setEnd(userSelection.focusNode, userSelection.focusOffset);
|
1820
|
+
}
|
1821
|
+
div.appendChild(range.cloneContents());
|
1822
|
+
return div.innerHTML;
|
1823
|
+
}
|
1824
|
+
if(document.selection) {
|
1825
|
+
return document.selection.createRange()[ as_text ? 'text' : 'htmlText' ];
|
1826
|
+
}
|
1827
|
+
return '';
|
1828
|
+
},
|
1829
|
+
/*
|
1830
|
+
Function: $.vakata.selection.elm_get
|
1831
|
+
Gets the selection inside an input element or textarea.
|
1832
|
+
|
1833
|
+
Parameters:
|
1834
|
+
e - the actual DOM element or the ID of the element
|
1835
|
+
|
1836
|
+
Returns:
|
1837
|
+
*object* - the current selection (start, end, length, text)
|
1838
|
+
*/
|
1839
|
+
elm_get : function (e) {
|
1840
|
+
e = typeof e === 'string' ? document.getElementById(e) : e;
|
1841
|
+
if(e.jquery) { e = e.get(0); }
|
1842
|
+
if('selectionStart' in e) { // Mozilla and DOM 3.0
|
1843
|
+
return {
|
1844
|
+
'start' : e.selectionStart,
|
1845
|
+
'end' : e.selectionEnd,
|
1846
|
+
'length' : (e.selectionEnd - e.selectionStart),
|
1847
|
+
'text' : e.value.substr(e.selectionStart, (e.selectionEnd - e.selectionStart))
|
1848
|
+
};
|
1849
|
+
}
|
1850
|
+
else if(document.selection) { // IE
|
1851
|
+
e.focus();
|
1852
|
+
var tr0 = document.selection.createRange(),
|
1853
|
+
tr1 = false,
|
1854
|
+
tr2 = false,
|
1855
|
+
len, text_whole, the_start, the_end;
|
1856
|
+
if(tr0 && tr0.parentElement() === e) {
|
1857
|
+
len = e.value.length;
|
1858
|
+
text_whole = e.value.replace(/\r\n/g, "\n");
|
1859
|
+
|
1860
|
+
tr1 = e.createTextRange();
|
1861
|
+
tr1.moveToBookmark(tr0.getBookmark());
|
1862
|
+
tr2 = e.createTextRange();
|
1863
|
+
tr2.collapse(false);
|
1864
|
+
|
1865
|
+
if(tr1.compareEndPoints("StartToEnd", tr2) > -1) {
|
1866
|
+
the_start = the_end = len;
|
1867
|
+
}
|
1868
|
+
else {
|
1869
|
+
the_start = -tr1.moveStart("character", -len);
|
1870
|
+
the_start += text_whole.slice(0, the_start).split("\n").length - 1;
|
1871
|
+
if (tr1.compareEndPoints("EndToEnd", tr2) > -1) {
|
1872
|
+
the_end = len;
|
1873
|
+
} else {
|
1874
|
+
the_end = -tr1.moveEnd("character", -len);
|
1875
|
+
the_end += text_whole.slice(0, the_end).split("\n").length - 1;
|
1876
|
+
}
|
1877
|
+
}
|
1878
|
+
text_whole = e.value.slice(the_start, the_end);
|
1879
|
+
return {
|
1880
|
+
'start' : the_start,
|
1881
|
+
'end' : the_end,
|
1882
|
+
'length' : text_whole.length,
|
1883
|
+
'text' : text_whole
|
1884
|
+
};
|
1885
|
+
}
|
1886
|
+
}
|
1887
|
+
else { // not supported
|
1888
|
+
return {
|
1889
|
+
'start' : e.value.length,
|
1890
|
+
'end' : e.value.length,
|
1891
|
+
'length' : 0,
|
1892
|
+
'text' : ''
|
1893
|
+
};
|
1894
|
+
}
|
1895
|
+
},
|
1896
|
+
/*
|
1897
|
+
Function: $.vakata.selection.elm_set
|
1898
|
+
Sets the selection inside an input element or textarea.
|
1899
|
+
|
1900
|
+
Parameters:
|
1901
|
+
e - the actual DOM element or the ID of the element
|
1902
|
+
beg - the char to start the selection
|
1903
|
+
end - the char to end the selection
|
1904
|
+
|
1905
|
+
Returns:
|
1906
|
+
*object* - the current selection (start, end, length, text)
|
1907
|
+
*/
|
1908
|
+
elm_set : function (e, beg, end) {
|
1909
|
+
e = typeof e === 'string' ? document.getElementById(e) : e;
|
1910
|
+
if(e.jquery) { e = e.get(0); }
|
1911
|
+
if('selectionStart' in e) { // Mozilla and DOM 3.0
|
1912
|
+
e.focus();
|
1913
|
+
e.selectionStart = beg;
|
1914
|
+
e.selectionEnd = end;
|
1915
|
+
}
|
1916
|
+
else if(document.selection) { // IE
|
1917
|
+
e.focus();
|
1918
|
+
var tr = e.createTextRange(),
|
1919
|
+
tx = e.value.replace(/\r\n/g, "\n");
|
1920
|
+
|
1921
|
+
beg -= tx.slice(0, beg).split("\n").length - 1;
|
1922
|
+
end -= tx.slice(0, end).split("\n").length - 1;
|
1923
|
+
|
1924
|
+
tr.collapse(true);
|
1925
|
+
tr.moveEnd('character', end);
|
1926
|
+
tr.moveStart('character', beg);
|
1927
|
+
tr.select();
|
1928
|
+
}
|
1929
|
+
return $.vakata.selection.elm_get(e);
|
1930
|
+
},
|
1931
|
+
/*
|
1932
|
+
Function: $.vakata.selection.elm_replace
|
1933
|
+
Replace the selection inside an input element or textarea.
|
1934
|
+
|
1935
|
+
Parameters:
|
1936
|
+
e - the actual DOM element or the ID of the element
|
1937
|
+
replace - the string to replace the selection with
|
1938
|
+
|
1939
|
+
Returns:
|
1940
|
+
*object* - the current selection (start, end, length, text)
|
1941
|
+
*/
|
1942
|
+
elm_replace : function (e, replace) {
|
1943
|
+
e = typeof e === 'string' ? document.getElementById(e) : e;
|
1944
|
+
if(e.jquery) { e = e.get(0); }
|
1945
|
+
var sel = $.vakata.selection.elm_get(e),
|
1946
|
+
beg = sel.start,
|
1947
|
+
end = beg + replace.length;
|
1948
|
+
e.value = e.value.substr(0, beg) + replace + e.value.substr(sel.end, e.value.length);
|
1949
|
+
$.vakata.selection.elm_set(e, beg, end);
|
1950
|
+
return {
|
1951
|
+
'start' : beg,
|
1952
|
+
'end' : end,
|
1953
|
+
'length' : replace.length,
|
1954
|
+
'text' : replace
|
1955
|
+
};
|
1956
|
+
},
|
1957
|
+
/*
|
1958
|
+
Function: $.vakata.selection.elm_get_caret
|
1959
|
+
Returns the caret position in the element.
|
1960
|
+
|
1961
|
+
Parameters:
|
1962
|
+
e - the actual DOM element or the ID of the element
|
1963
|
+
|
1964
|
+
Returns:
|
1965
|
+
*number* - the current caret position
|
1966
|
+
*/
|
1967
|
+
elm_get_caret : function (e) {
|
1968
|
+
return $.vakata.selection.elm_get(e).end;
|
1969
|
+
},
|
1970
|
+
/*
|
1971
|
+
Function: $.vakata.selection.elm_set_caret
|
1972
|
+
Sets the caret position in the element.
|
1973
|
+
|
1974
|
+
Parameters:
|
1975
|
+
e - the actual DOM element or the ID of the element
|
1976
|
+
pos - the position to move the caret to
|
1977
|
+
|
1978
|
+
Returns:
|
1979
|
+
*object* - the current selection
|
1980
|
+
*/
|
1981
|
+
elm_set_caret : function (e, pos) {
|
1982
|
+
return $.vakata.selection.elm_set(e, pos, pos);
|
1983
|
+
},
|
1984
|
+
/*
|
1985
|
+
Function: $.vakata.selection.elm_get_caret_position
|
1986
|
+
Returns the caret position in pixels relative to the element.
|
1987
|
+
|
1988
|
+
Parameters:
|
1989
|
+
e - the actual DOM element or the ID of the element
|
1990
|
+
|
1991
|
+
Returns:
|
1992
|
+
*object* - the current position (with _left_ and _top_ values)
|
1993
|
+
*/
|
1994
|
+
elm_get_caret_position : function (e) {
|
1995
|
+
e = typeof e === 'string' ? document.getElementById(e) : e;
|
1996
|
+
if(e.jquery) { e = e.get(0); }
|
1997
|
+
var p = $.vakata.selection.elm_get_caret(e),
|
1998
|
+
s = e.value.substring(0, p).replace(/&/g,'&').replace(/</ig,'<').replace(/>/ig,'>').replace(/\r/g, '').replace(/\t/g,' ').replace(/\n/ig, '<br />'),
|
1999
|
+
b = $.vakata.get_scrollbar_width(),
|
2000
|
+
w = $(e).width(),
|
2001
|
+
h = $(e).height();
|
2002
|
+
if(e.scrollHeight > h) { w -= b; }
|
2003
|
+
if(e.scrollWidth > w) { h -= b; }
|
2004
|
+
e = $(e);
|
2005
|
+
e = $('<div />').html(s).css({
|
2006
|
+
'background': 'red',
|
2007
|
+
'width' : w + 'px',
|
2008
|
+
'height' : 'auto',
|
2009
|
+
'position' : 'absolute',
|
2010
|
+
'left' : '0px',
|
2011
|
+
'top' : '-10000px',
|
2012
|
+
|
2013
|
+
'fontSize' : e.css('fontSize'),
|
2014
|
+
'fontFamily' : e.css('fontFamily'),
|
2015
|
+
'fontWeight' : e.css('fontWeight'),
|
2016
|
+
'fontVariant' : e.css('fontVariant'),
|
2017
|
+
'fontStyle' : e.css('fontStyle'),
|
2018
|
+
'textTransform' : e.css('textTransform'),
|
2019
|
+
'lineHeight' : e.css('lineHeight'),
|
2020
|
+
'whiteSpace' : 'pre-wrap'
|
2021
|
+
});
|
2022
|
+
e.append('<span class="caret"> </span>').appendTo('body');
|
2023
|
+
s = e.find('span.caret');
|
2024
|
+
p = s.offset();
|
2025
|
+
p.top = p.top + 10000 + s.height();
|
2026
|
+
e.remove();
|
2027
|
+
return p;
|
2028
|
+
}
|
2029
|
+
};
|
2030
|
+
})(jQuery);
|
2031
|
+
|
2032
|
+
|
2033
|
+
|
2034
|
+
(function ($) {
|
2035
|
+
/*
|
2036
|
+
Function: $.vakata_highlight
|
2037
|
+
Hightlight words in the matched elements
|
2038
|
+
|
2039
|
+
Parameters:
|
2040
|
+
settings - if a string is passed, it is used to search and highlight, if an array of strings is passed, each string is highlighted, you can also pass an object, containing a _words_ string or array, a _color_ string or array, a _css_class_ string.
|
2041
|
+
*/
|
2042
|
+
$.fn.vakata_highlight = function (settings) {
|
2043
|
+
var _return = this;
|
2044
|
+
if(typeof settings === 'string') {
|
2045
|
+
settings = [ settings ];
|
2046
|
+
}
|
2047
|
+
if($.isArray(settings)) {
|
2048
|
+
settings = { 'words' : settings };
|
2049
|
+
}
|
2050
|
+
settings = $.extend(true, {}, { 'css_class' : 'vakata-highlight', 'words' : [], 'color' : '#99ccff' }, settings);
|
2051
|
+
if(settings.words.length) {
|
2052
|
+
this.each(function () {
|
2053
|
+
var t = $(this);
|
2054
|
+
$.each(settings.words, function (i,v) {
|
2055
|
+
var color = false;
|
2056
|
+
if(typeof settings.color === 'string') {
|
2057
|
+
color = settings.color;
|
2058
|
+
}
|
2059
|
+
if($.isArray(settings.color) && typeof settings.color[i] === 'string') {
|
2060
|
+
color = settings.color[i];
|
2061
|
+
}
|
2062
|
+
t
|
2063
|
+
.find(':vakata_icontains("' + v.replace(/\"/ig,'') + '")')
|
2064
|
+
.filter('strong, span, li, p, h1, h2, h3, h4, h5, h6, div, u, em, i, dt, dd')
|
2065
|
+
.contents()
|
2066
|
+
.filter(function() { return this.nodeType === 3; })
|
2067
|
+
.each(function () {
|
2068
|
+
if(this.nodeValue.toLowerCase().indexOf(v.toLowerCase()) >= 0) {
|
2069
|
+
this.nodeValue = this.nodeValue.replace(new RegExp('(' + v.replace(/([\-.*+?\^${}()|\[\]\/\\])/g,"\\$1") + ')', 'ig'), '|{{{$1}}}|');
|
2070
|
+
var o = $(this).parent();
|
2071
|
+
o.html(o.html().replace(/\|\{\{\{/g,'<span class="' + settings.css_class + ' ' + settings.css_class + '-' + i + '" ' + ( typeof color === 'string' ? ' style="background:' + color + ';" ' : '' ) + '>').replace(/\}\}\}\|/g,'</span>'));
|
2072
|
+
}
|
2073
|
+
});
|
2074
|
+
});
|
2075
|
+
});
|
2076
|
+
}
|
2077
|
+
return _return;
|
2078
|
+
};
|
2079
|
+
})(jQuery);
|