jstree-rails 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|