jquerypp-rails 1.0.1.1.rc3 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +28 -31
- data/lib/jquerypp/rails/version.rb +1 -1
- metadata +2 -25
- data/vendor/assets/javascripts/lib/jquery.animate.js +0 -326
- data/vendor/assets/javascripts/lib/jquery.compare.js +0 -75
- data/vendor/assets/javascripts/lib/jquery.cookie.js +0 -118
- data/vendor/assets/javascripts/lib/jquery.dimensions.js +0 -191
- data/vendor/assets/javascripts/lib/jquery.event.default.js +0 -115
- data/vendor/assets/javascripts/lib/jquery.event.destroyed.js +0 -23
- data/vendor/assets/javascripts/lib/jquery.event.drag.js +0 -727
- data/vendor/assets/javascripts/lib/jquery.event.drop.js +0 -457
- data/vendor/assets/javascripts/lib/jquery.event.fastfix.js +0 -95
- data/vendor/assets/javascripts/lib/jquery.event.hover.js +0 -266
- data/vendor/assets/javascripts/lib/jquery.event.key.js +0 -156
- data/vendor/assets/javascripts/lib/jquery.event.livehack.js +0 -174
- data/vendor/assets/javascripts/lib/jquery.event.pause.js +0 -92
- data/vendor/assets/javascripts/lib/jquery.event.resize.js +0 -47
- data/vendor/assets/javascripts/lib/jquery.event.swipe.js +0 -133
- data/vendor/assets/javascripts/lib/jquery.fills.js +0 -249
- data/vendor/assets/javascripts/lib/jquery.form_params.js +0 -167
- data/vendor/assets/javascripts/lib/jquery.lang.json.js +0 -196
- data/vendor/assets/javascripts/lib/jquery.lang.vector.js +0 -214
- data/vendor/assets/javascripts/lib/jquery.range.js +0 -861
- data/vendor/assets/javascripts/lib/jquery.selection.js +0 -232
- data/vendor/assets/javascripts/lib/jquery.styles.js +0 -103
- data/vendor/assets/javascripts/lib/jquery.within.js +0 -94
@@ -1,861 +0,0 @@
|
|
1
|
-
// Dependencies:
|
2
|
-
//
|
3
|
-
// - jquery.range.js
|
4
|
-
// - jquery.compare.js
|
5
|
-
|
6
|
-
(function($){
|
7
|
-
|
8
|
-
$.fn.range =
|
9
|
-
/**
|
10
|
-
* @function jQuery.fn.range
|
11
|
-
* @parent jQuery.Range
|
12
|
-
*
|
13
|
-
* `$.fn.range` returns a new [jQuery.Range] instance for the first selected element.
|
14
|
-
*
|
15
|
-
* $('#content').range() //-> range
|
16
|
-
*
|
17
|
-
* @return {$.Range} A $.Range instance for the selected element
|
18
|
-
*/
|
19
|
-
function(){
|
20
|
-
return $.Range(this[0])
|
21
|
-
}
|
22
|
-
|
23
|
-
var convertType = function(type){
|
24
|
-
return type.replace(/([a-z])([a-z]+)/gi, function(all,first, next){
|
25
|
-
return first+next.toLowerCase()
|
26
|
-
}).replace(/_/g,"");
|
27
|
-
},
|
28
|
-
// reverses things like START_TO_END into END_TO_START
|
29
|
-
reverse = function(type){
|
30
|
-
return type.replace(/^([a-z]+)_TO_([a-z]+)/i, function(all, first, last){
|
31
|
-
return last+"_TO_"+first;
|
32
|
-
});
|
33
|
-
},
|
34
|
-
getWindow = function( element ) {
|
35
|
-
return element ? element.ownerDocument.defaultView || element.ownerDocument.parentWindow : window
|
36
|
-
},
|
37
|
-
bisect = function(el, start, end){
|
38
|
-
//split the start and end ... figure out who is touching ...
|
39
|
-
if(end-start == 1){
|
40
|
-
return
|
41
|
-
}
|
42
|
-
},
|
43
|
-
support = {};
|
44
|
-
/**
|
45
|
-
* @Class jQuery.Range
|
46
|
-
* @parent jQuery.Range
|
47
|
-
*
|
48
|
-
* Depending on the object passed, the selected text will be different.
|
49
|
-
*
|
50
|
-
* @param {TextRange|HTMLElement|Point} [range] An object specifiying a
|
51
|
-
* range. Depending on the object, the selected text will be different. $.Range supports the
|
52
|
-
* following types
|
53
|
-
*
|
54
|
-
* - __undefined or null__ - returns a range with nothing selected
|
55
|
-
* - __HTMLElement__ - returns a range with the node's text selected
|
56
|
-
* - __Point__ - returns a range at the point on the screen. The point can be specified like:
|
57
|
-
*
|
58
|
-
* //client coordinates
|
59
|
-
* {clientX: 200, clientY: 300}
|
60
|
-
*
|
61
|
-
* //page coordinates
|
62
|
-
* {pageX: 200, pageY: 300}
|
63
|
-
* {top: 200, left: 300}
|
64
|
-
*
|
65
|
-
* - __TextRange__ a raw text range object.
|
66
|
-
*/
|
67
|
-
$.Range = function(range){
|
68
|
-
// If it's called w/o new, call it with new!
|
69
|
-
if(this.constructor !== $.Range){
|
70
|
-
return new $.Range(range);
|
71
|
-
}
|
72
|
-
// If we are passed a jQuery-wrapped element, get the raw element
|
73
|
-
if(range && range.jquery){
|
74
|
-
range = range[0];
|
75
|
-
}
|
76
|
-
// If we have an element, or nothing
|
77
|
-
if(!range || range.nodeType){
|
78
|
-
// create a range
|
79
|
-
this.win = getWindow(range)
|
80
|
-
if(this.win.document.createRange){
|
81
|
-
this.range = this.win.document.createRange()
|
82
|
-
}else{
|
83
|
-
this.range = this.win.document.body.createTextRange()
|
84
|
-
}
|
85
|
-
// if we have an element, make the range select it
|
86
|
-
if(range){
|
87
|
-
this.select(range)
|
88
|
-
}
|
89
|
-
}
|
90
|
-
// if we are given a point
|
91
|
-
else if (range.clientX != null || range.pageX != null || range.left != null) {
|
92
|
-
this.moveToPoint(range);
|
93
|
-
}
|
94
|
-
// if we are given a touch event
|
95
|
-
else if (range.originalEvent && range.originalEvent.touches && range.originalEvent.touches.length) {
|
96
|
-
this.moveToPoint(range.originalEvent.touches[0])
|
97
|
-
|
98
|
-
}
|
99
|
-
// if we are a normal event
|
100
|
-
else if (range.originalEvent && range.originalEvent.changedTouches && range.originalEvent.changedTouches.length) {
|
101
|
-
this.moveToPoint(range.originalEvent.changedTouches[0])
|
102
|
-
}
|
103
|
-
// given a TextRange or something else?
|
104
|
-
else {
|
105
|
-
this.range = range;
|
106
|
-
}
|
107
|
-
};
|
108
|
-
/**
|
109
|
-
* @static
|
110
|
-
*/
|
111
|
-
$.Range.
|
112
|
-
/**
|
113
|
-
* `$.Range.current([element])` returns the currently selected range
|
114
|
-
* (using [window.getSelection](https://developer.mozilla.org/en/nsISelection)).
|
115
|
-
*
|
116
|
-
* var range = $.Range.current()
|
117
|
-
* range.start().offset // -> selection start offset
|
118
|
-
* range.end().offset // -> selection end offset
|
119
|
-
*
|
120
|
-
* @param {HTMLElement} [el] an optional element used to get selection for a given window.
|
121
|
-
* @return {jQuery.Range} The range instance.
|
122
|
-
*/
|
123
|
-
current = function(el){
|
124
|
-
var win = getWindow(el),
|
125
|
-
selection;
|
126
|
-
if(win.getSelection){
|
127
|
-
// If we can get the selection
|
128
|
-
selection = win.getSelection()
|
129
|
-
return new $.Range( selection.rangeCount ? selection.getRangeAt(0) : win.document.createRange())
|
130
|
-
} else {
|
131
|
-
// Otherwise use document.selection
|
132
|
-
return new $.Range( win.document.selection.createRange() );
|
133
|
-
}
|
134
|
-
};
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
$.extend($.Range.prototype,
|
140
|
-
/** @prototype **/
|
141
|
-
{
|
142
|
-
/**
|
143
|
-
* `range.moveToPoint(point)` moves the range end and start position to a specific point.
|
144
|
-
* A point can be specified like:
|
145
|
-
*
|
146
|
-
* //client coordinates
|
147
|
-
* {clientX: 200, clientY: 300}
|
148
|
-
*
|
149
|
-
* //page coordinates
|
150
|
-
* {pageX: 200, pageY: 300}
|
151
|
-
* {top: 200, left: 300}
|
152
|
-
*
|
153
|
-
* @param point The point to move the range to
|
154
|
-
* @return {$.Range}
|
155
|
-
*/
|
156
|
-
moveToPoint : function(point){
|
157
|
-
var clientX = point.clientX, clientY = point.clientY
|
158
|
-
if(!clientX){
|
159
|
-
var off = scrollOffset();
|
160
|
-
clientX = (point.pageX || point.left || 0 ) - off.left;
|
161
|
-
clientY = (point.pageY || point.top || 0 ) - off.top;
|
162
|
-
}
|
163
|
-
if(support.moveToPoint){
|
164
|
-
this.range = $.Range().range
|
165
|
-
this.range.moveToPoint(clientX, clientY);
|
166
|
-
return this;
|
167
|
-
}
|
168
|
-
|
169
|
-
|
170
|
-
// it's some text node in this range ...
|
171
|
-
var parent = document.elementFromPoint(clientX, clientY);
|
172
|
-
|
173
|
-
//typically it will be 'on' text
|
174
|
-
for(var n=0; n < parent.childNodes.length; n++){
|
175
|
-
var node = parent.childNodes[n];
|
176
|
-
if(node.nodeType === 3 || node.nodeType === 4){
|
177
|
-
var range = $.Range(node),
|
178
|
-
length = range.toString().length;
|
179
|
-
|
180
|
-
|
181
|
-
// now lets start moving the end until the boundingRect is within our range
|
182
|
-
for(var i = 1; i < length+1; i++){
|
183
|
-
var rect = range.end(i).rect();
|
184
|
-
if(rect.left <= clientX && rect.left+rect.width >= clientX &&
|
185
|
-
rect.top <= clientY && rect.top+rect.height >= clientY ){
|
186
|
-
range.start(i-1);
|
187
|
-
this.range = range.range;
|
188
|
-
return this;
|
189
|
-
}
|
190
|
-
}
|
191
|
-
}
|
192
|
-
}
|
193
|
-
|
194
|
-
// if not 'on' text, recursively go through and find out when we shift to next
|
195
|
-
// 'line'
|
196
|
-
var previous;
|
197
|
-
iterate(parent.childNodes, function(textNode){
|
198
|
-
var range = $.Range(textNode);
|
199
|
-
if(range.rect().top > point.clientY){
|
200
|
-
return false;
|
201
|
-
}else{
|
202
|
-
previous = range;
|
203
|
-
}
|
204
|
-
});
|
205
|
-
|
206
|
-
if(previous){
|
207
|
-
previous.start(previous.toString().length);
|
208
|
-
this.range = previous.range;
|
209
|
-
}else{
|
210
|
-
this.range = $.Range(parent).range
|
211
|
-
}
|
212
|
-
},
|
213
|
-
|
214
|
-
window : function(){
|
215
|
-
return this.win || window;
|
216
|
-
},
|
217
|
-
/**
|
218
|
-
* `range.overlaps([elRange])` returns `true` if any portion of these two ranges overlap.
|
219
|
-
*
|
220
|
-
* var foo = document.getElementById('foo');
|
221
|
-
*
|
222
|
-
* $.Range(foo.childNodes[0]).overlaps(foo.childNodes[1]) //-> false
|
223
|
-
*
|
224
|
-
* @param {jQuery.Range} elRange The range to compare
|
225
|
-
* @return {Boolean} true if part of the ranges overlap, false if otherwise.
|
226
|
-
*/
|
227
|
-
overlaps : function(elRange){
|
228
|
-
if(elRange.nodeType){
|
229
|
-
elRange = $.Range(elRange).select(elRange);
|
230
|
-
}
|
231
|
-
//if the start is within the element ...
|
232
|
-
var startToStart = this.compare("START_TO_START", elRange),
|
233
|
-
endToEnd = this.compare("END_TO_END", elRange)
|
234
|
-
|
235
|
-
// if we wrap elRange
|
236
|
-
if(startToStart <=0 && endToEnd >=0){
|
237
|
-
return true;
|
238
|
-
}
|
239
|
-
// if our start is inside of it
|
240
|
-
if( startToStart >= 0 &&
|
241
|
-
this.compare("START_TO_END", elRange) <= 0 ) {
|
242
|
-
return true;
|
243
|
-
}
|
244
|
-
// if our end is inside of elRange
|
245
|
-
if(this.compare("END_TO_START", elRange) >= 0 &&
|
246
|
-
endToEnd <= 0 ) {
|
247
|
-
return true;
|
248
|
-
}
|
249
|
-
return false;
|
250
|
-
},
|
251
|
-
/**
|
252
|
-
* `range.collapse([toStart])` collapses a range to one of its boundary points.
|
253
|
-
* See [range.collapse](https://developer.mozilla.org/en/DOM/range.collapse).
|
254
|
-
*
|
255
|
-
* $('#foo').range().collapse()
|
256
|
-
*
|
257
|
-
* @param {Boolean} [toStart] true if to the start of the range, false if to the
|
258
|
-
* end. Defaults to false.
|
259
|
-
* @return {jQuery.Range} returns the range for chaining.
|
260
|
-
*/
|
261
|
-
collapse : function(toStart){
|
262
|
-
this.range.collapse(toStart === undefined ? true : toStart);
|
263
|
-
return this;
|
264
|
-
},
|
265
|
-
/**
|
266
|
-
* `range.toString()` returns the text of the range.
|
267
|
-
*
|
268
|
-
* currentText = $.Range.current().toString()
|
269
|
-
*
|
270
|
-
* @return {String} The text content of this range
|
271
|
-
*/
|
272
|
-
toString : function(){
|
273
|
-
return typeof this.range.text == "string" ? this.range.text : this.range.toString();
|
274
|
-
},
|
275
|
-
/**
|
276
|
-
* `range.start([start])` gets or sets the start of the range.
|
277
|
-
*
|
278
|
-
* If a value is not provided, start returns the range's starting container and offset like:
|
279
|
-
*
|
280
|
-
* $('#foo').range().start()
|
281
|
-
* //-> {container: fooElement, offset: 0 }
|
282
|
-
*
|
283
|
-
* If a set value is provided, it can set the range. The start of the range is set differently
|
284
|
-
* depending on the type of set value:
|
285
|
-
*
|
286
|
-
* - __Object__ - an object with the new starting container and offset like
|
287
|
-
*
|
288
|
-
* $.Range().start({container: $('#foo')[0], offset: 20})
|
289
|
-
*
|
290
|
-
* - __Number__ - the new offset value. The container is kept the same.
|
291
|
-
*
|
292
|
-
* - __String__ - adjusts the offset by converting the string offset to a number and adding it to the current
|
293
|
-
* offset. For example, the following moves the offset forward four characters:
|
294
|
-
*
|
295
|
-
* $('#foo').range().start("+4")
|
296
|
-
*
|
297
|
-
* Note that `start` can return a text node. To get the containing element use this:
|
298
|
-
*
|
299
|
-
* var startNode = range.start().container;
|
300
|
-
* if( startNode.nodeType === Node.TEXT_NODE ||
|
301
|
-
* startNode.nodeType === Node.CDATA_SECTION_NODE ) {
|
302
|
-
* startNode = startNode.parentNode;
|
303
|
-
* }
|
304
|
-
* $(startNode).addClass('highlight');
|
305
|
-
*
|
306
|
-
* @param {Object|String|Number} [set] a set value if setting the start of the range or nothing if reading it.
|
307
|
-
* @return {jQuery.Range|Object} if setting the start, the range is returned for chaining, otherwise, the
|
308
|
-
* start offset and container are returned.
|
309
|
-
*/
|
310
|
-
start : function(set){
|
311
|
-
// return start
|
312
|
-
if(set === undefined){
|
313
|
-
if(this.range.startContainer){
|
314
|
-
return {
|
315
|
-
container : this.range.startContainer,
|
316
|
-
offset : this.range.startOffset
|
317
|
-
}
|
318
|
-
}else{
|
319
|
-
// Get the start parent element
|
320
|
-
var start = this.clone().collapse().parent();
|
321
|
-
// used to get the start element offset
|
322
|
-
var startRange = $.Range(start).select(start).collapse();
|
323
|
-
startRange.move("END_TO_START", this);
|
324
|
-
return {
|
325
|
-
container : start,
|
326
|
-
offset : startRange.toString().length
|
327
|
-
}
|
328
|
-
}
|
329
|
-
} else {
|
330
|
-
if (this.range.setStart) {
|
331
|
-
// supports setStart
|
332
|
-
if(typeof set == 'number'){
|
333
|
-
this.range.setStart(this.range.startContainer, set)
|
334
|
-
} else if(typeof set == 'string') {
|
335
|
-
var res = callMove(this.range.startContainer, this.range.startOffset, parseInt(set,10))
|
336
|
-
this.range.setStart(res.node, res.offset );
|
337
|
-
} else {
|
338
|
-
this.range.setStart(set.container, set.offset)
|
339
|
-
}
|
340
|
-
} else {
|
341
|
-
if(typeof set == "string"){
|
342
|
-
this.range.moveStart('character', parseInt(set,10))
|
343
|
-
} else {
|
344
|
-
// get the current end container
|
345
|
-
var container = this.start().container,
|
346
|
-
offset
|
347
|
-
if(typeof set == "number") {
|
348
|
-
offset = set
|
349
|
-
} else {
|
350
|
-
container = set.container
|
351
|
-
offset = set.offset
|
352
|
-
}
|
353
|
-
var newPoint = $.Range(container).collapse();
|
354
|
-
//move it over offset characters
|
355
|
-
newPoint.range.move(offset);
|
356
|
-
this.move("START_TO_START",newPoint);
|
357
|
-
}
|
358
|
-
}
|
359
|
-
return this;
|
360
|
-
}
|
361
|
-
|
362
|
-
|
363
|
-
},
|
364
|
-
/**
|
365
|
-
* `range.end([end])` gets or sets the end of the range.
|
366
|
-
* It takes similar options as [jQuery.Range::start start]:
|
367
|
-
*
|
368
|
-
* - __Object__ - an object with the new end container and offset like
|
369
|
-
*
|
370
|
-
* $.Range().end({container: $('#foo')[0], offset: 20})
|
371
|
-
*
|
372
|
-
* - __Number__ - the new offset value. The container is kept the same.
|
373
|
-
*
|
374
|
-
* - __String__ - adjusts the offset by converting the string offset to a number and adding it to the current
|
375
|
-
* offset. For example, the following moves the offset forward four characters:
|
376
|
-
*
|
377
|
-
* $('#foo').range().end("+4")
|
378
|
-
*
|
379
|
-
* Note that `end` can return a text node. To get the containing element use this:
|
380
|
-
*
|
381
|
-
* var startNode = range.end().container;
|
382
|
-
* if( startNode.nodeType === Node.TEXT_NODE ||
|
383
|
-
* startNode.nodeType === Node.CDATA_SECTION_NODE ) {
|
384
|
-
* startNode = startNode.parentNode;
|
385
|
-
* }
|
386
|
-
* $(startNode).addClass('highlight');
|
387
|
-
*
|
388
|
-
* @param {Object|String|Number} [set] a set value if setting the end of the range or nothing if reading it.
|
389
|
-
*/
|
390
|
-
end : function(set){
|
391
|
-
// read end
|
392
|
-
if (set === undefined) {
|
393
|
-
if (this.range.startContainer) {
|
394
|
-
return {
|
395
|
-
container: this.range.endContainer,
|
396
|
-
offset: this.range.endOffset
|
397
|
-
}
|
398
|
-
}
|
399
|
-
else {
|
400
|
-
var
|
401
|
-
// Get the end parent element
|
402
|
-
end = this.clone().collapse(false).parent(),
|
403
|
-
// used to get the end elements offset
|
404
|
-
endRange = $.Range(end).select(end).collapse();
|
405
|
-
endRange.move("END_TO_END", this);
|
406
|
-
return {
|
407
|
-
container: end,
|
408
|
-
offset: endRange.toString().length
|
409
|
-
}
|
410
|
-
}
|
411
|
-
} else {
|
412
|
-
if (this.range.setEnd) {
|
413
|
-
if(typeof set == 'number'){
|
414
|
-
this.range.setEnd(this.range.endContainer, set)
|
415
|
-
} else if(typeof set == 'string') {
|
416
|
-
var res = callMove(this.range.endContainer, this.range.endOffset, parseInt(set,10))
|
417
|
-
this.range.setEnd(res.node, res.offset );
|
418
|
-
} else {
|
419
|
-
this.range.setEnd(set.container, set.offset)
|
420
|
-
}
|
421
|
-
} else {
|
422
|
-
if(typeof set == "string"){
|
423
|
-
this.range.moveEnd('character', parseInt(set,10));
|
424
|
-
} else {
|
425
|
-
// get the current end container
|
426
|
-
var container = this.end().container,
|
427
|
-
offset
|
428
|
-
if(typeof set == "number") {
|
429
|
-
offset = set
|
430
|
-
} else {
|
431
|
-
container = set.container
|
432
|
-
offset = set.offset
|
433
|
-
}
|
434
|
-
var newPoint = $.Range(container).collapse();
|
435
|
-
//move it over offset characters
|
436
|
-
newPoint.range.move(offset);
|
437
|
-
this.move("END_TO_START",newPoint);
|
438
|
-
}
|
439
|
-
}
|
440
|
-
return this;
|
441
|
-
}
|
442
|
-
},
|
443
|
-
/**
|
444
|
-
* `range.parent()` returns the most common ancestor element of
|
445
|
-
* the endpoints in the range. This will return a text element if the range is
|
446
|
-
* within a text element. In this case, to get the containing element use this:
|
447
|
-
*
|
448
|
-
* var parent = range.parent();
|
449
|
-
* if( parent.nodeType === Node.TEXT_NODE ||
|
450
|
-
* parent.nodeType === Node.CDATA_SECTION_NODE ) {
|
451
|
-
* parent = startNode.parentNode;
|
452
|
-
* }
|
453
|
-
* $(parent).addClass('highlight');
|
454
|
-
*
|
455
|
-
* @return {HTMLNode} the TextNode or HTMLElement
|
456
|
-
* that fully contains the range
|
457
|
-
*/
|
458
|
-
parent : function(){
|
459
|
-
if(this.range.commonAncestorContainer){
|
460
|
-
return this.range.commonAncestorContainer;
|
461
|
-
} else {
|
462
|
-
|
463
|
-
var parentElement = this.range.parentElement(),
|
464
|
-
range = this.range;
|
465
|
-
|
466
|
-
// IE's parentElement will always give an element, we want text ranges
|
467
|
-
iterate(parentElement.childNodes, function(txtNode){
|
468
|
-
if($.Range(txtNode).range.inRange( range ) ){
|
469
|
-
// swap out the parentElement
|
470
|
-
parentElement = txtNode;
|
471
|
-
return false;
|
472
|
-
}
|
473
|
-
});
|
474
|
-
|
475
|
-
return parentElement;
|
476
|
-
}
|
477
|
-
},
|
478
|
-
/**
|
479
|
-
* `range.rect([from])` returns the bounding rectangle of this range.
|
480
|
-
*
|
481
|
-
* @param {String} [from] - where the coordinates should be
|
482
|
-
* positioned from. By default, coordinates are given from the client viewport.
|
483
|
-
* But if 'page' is given, they are provided relative to the page.
|
484
|
-
*
|
485
|
-
* @return {TextRectangle} - The client rects.
|
486
|
-
*/
|
487
|
-
rect : function(from){
|
488
|
-
var rect = this.range.getBoundingClientRect();
|
489
|
-
// for some reason in webkit this gets a better value
|
490
|
-
if(!rect.height && !rect.width){
|
491
|
-
rect = this.range.getClientRects()[0]
|
492
|
-
}
|
493
|
-
if(from === 'page'){
|
494
|
-
// Add the scroll offset
|
495
|
-
var off = scrollOffset();
|
496
|
-
rect = $.extend({}, rect);
|
497
|
-
rect.top += off.top;
|
498
|
-
rect.left += off.left;
|
499
|
-
}
|
500
|
-
return rect;
|
501
|
-
},
|
502
|
-
/**
|
503
|
-
* `range.rects(from)` returns the client rects.
|
504
|
-
*
|
505
|
-
* @param {String} [from] how the rects coordinates should be given (viewport or page). Provide 'page' for
|
506
|
-
* rect coordinates from the page.
|
507
|
-
* @return {Array} The client rects
|
508
|
-
*/
|
509
|
-
rects : function(from){
|
510
|
-
// order rects by size
|
511
|
-
var rects = $.map($.makeArray( this.range.getClientRects() ).sort(function(rect1, rect2){
|
512
|
-
return rect2.width*rect2.height - rect1.width*rect1.height;
|
513
|
-
}), function(rect){
|
514
|
-
return $.extend({}, rect)
|
515
|
-
}),
|
516
|
-
i=0,j,
|
517
|
-
len = rects.length;
|
518
|
-
|
519
|
-
// safari returns overlapping client rects
|
520
|
-
//
|
521
|
-
// - big rects can contain 2 smaller rects
|
522
|
-
// - some rects can contain 0 - width rects
|
523
|
-
// - we don't want these 0 width rects
|
524
|
-
while(i < rects.length){
|
525
|
-
var cur = rects[i],
|
526
|
-
found = false;
|
527
|
-
|
528
|
-
j = i+1;
|
529
|
-
while( j < rects.length ){
|
530
|
-
if( withinRect( cur, rects[j] ) ) {
|
531
|
-
if(!rects[j].width){
|
532
|
-
rects.splice(j,1)
|
533
|
-
} else {
|
534
|
-
found = rects[j];
|
535
|
-
break;
|
536
|
-
}
|
537
|
-
} else {
|
538
|
-
j++;
|
539
|
-
}
|
540
|
-
}
|
541
|
-
|
542
|
-
|
543
|
-
if(found){
|
544
|
-
rects.splice(i,1)
|
545
|
-
}else{
|
546
|
-
i++;
|
547
|
-
}
|
548
|
-
|
549
|
-
}
|
550
|
-
// safari will be return overlapping ranges ...
|
551
|
-
if(from == 'page'){
|
552
|
-
var off = scrollOffset();
|
553
|
-
return $.each(rects, function(ith, item){
|
554
|
-
item.top += off.top;
|
555
|
-
item.left += off.left;
|
556
|
-
})
|
557
|
-
}
|
558
|
-
|
559
|
-
|
560
|
-
return rects;
|
561
|
-
}
|
562
|
-
|
563
|
-
});
|
564
|
-
(function(){
|
565
|
-
//method branching ....
|
566
|
-
var fn = $.Range.prototype,
|
567
|
-
range = $.Range().range;
|
568
|
-
|
569
|
-
/**
|
570
|
-
* @function compare
|
571
|
-
*
|
572
|
-
* `range.compare(type, compareRange)` compares one range to another range.
|
573
|
-
*
|
574
|
-
* ## Example
|
575
|
-
*
|
576
|
-
* // compare the highlight element's start position
|
577
|
-
* // to the start of the current range
|
578
|
-
* $('#highlight')
|
579
|
-
* .range()
|
580
|
-
* .compare('START_TO_START', $.Range.current())
|
581
|
-
*
|
582
|
-
*
|
583
|
-
*
|
584
|
-
* @param {String} type Specifies the boundary of the
|
585
|
-
* range and the <code>compareRange</code> to compare.
|
586
|
-
*
|
587
|
-
* - `"START_TO_START"` - the start of the range and the start of compareRange
|
588
|
-
* - `"START_TO_END"` - the start of the range and the end of compareRange
|
589
|
-
* - `"END_TO_END"` - the end of the range and the end of compareRange
|
590
|
-
* - `"END_TO_START"` - the end of the range and the start of compareRange
|
591
|
-
*
|
592
|
-
* @param {$.Range} compareRange The other range
|
593
|
-
* to compare against.
|
594
|
-
* @return {Number} a number indicating if the range
|
595
|
-
* boundary is before,
|
596
|
-
* after, or equal to <code>compareRange</code>'s
|
597
|
-
* boundary where:
|
598
|
-
*
|
599
|
-
* - -1 - the range boundary comes before the compareRange boundary
|
600
|
-
* - 0 - the boundaries are equal
|
601
|
-
* - 1 - the range boundary comes after the compareRange boundary
|
602
|
-
*/
|
603
|
-
fn.compare = range.compareBoundaryPoints ?
|
604
|
-
function(type, range){
|
605
|
-
return this.range.compareBoundaryPoints(this.window().Range[reverse( type )], range.range)
|
606
|
-
}:
|
607
|
-
function(type, range){
|
608
|
-
return this.range.compareEndPoints(convertType(type), range.range)
|
609
|
-
}
|
610
|
-
|
611
|
-
/**
|
612
|
-
* @function move
|
613
|
-
*
|
614
|
-
* `range.move([referenceRange])` moves the endpoints of a range relative to another range.
|
615
|
-
*
|
616
|
-
* // Move the current selection's end to the
|
617
|
-
* // end of the #highlight element
|
618
|
-
* $.Range.current().move('END_TO_END',
|
619
|
-
* $('#highlight').range() )
|
620
|
-
*
|
621
|
-
*
|
622
|
-
* @param {String} type a string indicating the ranges boundary point
|
623
|
-
* to move to which referenceRange boundary point where:
|
624
|
-
*
|
625
|
-
* - `"START_TO_START"` - the start of the range moves to the start of referenceRange
|
626
|
-
* - `"START\_TO\_END"` - the start of the range move to the end of referenceRange
|
627
|
-
* - `"END_TO_END"` - the end of the range moves to the end of referenceRange
|
628
|
-
* - `"END_TO_START"` - the end of the range moves to the start of referenceRange
|
629
|
-
*
|
630
|
-
* @param {jQuery.Range} referenceRange
|
631
|
-
* @return {jQuery.Range} the original range for chaining
|
632
|
-
*/
|
633
|
-
fn.move = range.setStart ?
|
634
|
-
function(type, range){
|
635
|
-
|
636
|
-
var rangesRange = range.range;
|
637
|
-
switch(type){
|
638
|
-
case "START_TO_END" :
|
639
|
-
this.range.setStart(rangesRange.endContainer, rangesRange.endOffset)
|
640
|
-
break;
|
641
|
-
case "START_TO_START" :
|
642
|
-
this.range.setStart(rangesRange.startContainer, rangesRange.startOffset)
|
643
|
-
break;
|
644
|
-
case "END_TO_END" :
|
645
|
-
this.range.setEnd(rangesRange.endContainer, rangesRange.endOffset)
|
646
|
-
break;
|
647
|
-
case "END_TO_START" :
|
648
|
-
this.range.setEnd(rangesRange.startContainer, rangesRange.startOffset)
|
649
|
-
break;
|
650
|
-
}
|
651
|
-
|
652
|
-
return this;
|
653
|
-
}:
|
654
|
-
function(type, range){
|
655
|
-
this.range.setEndPoint(convertType(type), range.range)
|
656
|
-
return this;
|
657
|
-
};
|
658
|
-
var cloneFunc = range.cloneRange ? "cloneRange" : "duplicate",
|
659
|
-
selectFunc = range.selectNodeContents ? "selectNodeContents" : "moveToElementText";
|
660
|
-
|
661
|
-
fn.
|
662
|
-
/**
|
663
|
-
* `range.clone()` clones the range and returns a new $.Range
|
664
|
-
* object:
|
665
|
-
*
|
666
|
-
* var range = new $.Range(document.getElementById('text'));
|
667
|
-
* var newRange = range.clone();
|
668
|
-
* range.start('+2');
|
669
|
-
* range.select();
|
670
|
-
*
|
671
|
-
* @return {jQuery.Range} returns the range as a $.Range.
|
672
|
-
*/
|
673
|
-
clone = function(){
|
674
|
-
return $.Range( this.range[cloneFunc]() );
|
675
|
-
};
|
676
|
-
|
677
|
-
fn.
|
678
|
-
/**
|
679
|
-
* @function
|
680
|
-
*
|
681
|
-
* `range.select([el])` selects an element with this range. If nothing
|
682
|
-
* is provided, makes the current range appear as if the user has selected it.
|
683
|
-
*
|
684
|
-
* This works with text nodes. For example with:
|
685
|
-
*
|
686
|
-
* <div id="text">This is a text</div>
|
687
|
-
*
|
688
|
-
* $.Range can select `is a` like this:
|
689
|
-
*
|
690
|
-
* var range = new $.Range(document.getElementById('text'));
|
691
|
-
* range.start('+5');
|
692
|
-
* range.end('-5');
|
693
|
-
* range.select();
|
694
|
-
*
|
695
|
-
* @param {HTMLElement} [el] The element in which this range should be selected
|
696
|
-
* @return {jQuery.Range} the range for chaining.
|
697
|
-
*/
|
698
|
-
select = range.selectNodeContents ? function(el){
|
699
|
-
if(!el){
|
700
|
-
var selection = this.window().getSelection();
|
701
|
-
selection.removeAllRanges();
|
702
|
-
selection.addRange(this.range);
|
703
|
-
}else {
|
704
|
-
this.range.selectNodeContents(el);
|
705
|
-
}
|
706
|
-
return this;
|
707
|
-
} : function(el){
|
708
|
-
if(!el){
|
709
|
-
this.range.select()
|
710
|
-
} else if(el.nodeType === 3){
|
711
|
-
//select this node in the element ...
|
712
|
-
var parent = el.parentNode,
|
713
|
-
start = 0,
|
714
|
-
end;
|
715
|
-
iterate(parent.childNodes, function(txtNode){
|
716
|
-
if(txtNode === el){
|
717
|
-
end = start + txtNode.nodeValue.length;
|
718
|
-
return false;
|
719
|
-
} else {
|
720
|
-
start = start + txtNode.nodeValue.length
|
721
|
-
}
|
722
|
-
})
|
723
|
-
this.range.moveToElementText(parent);
|
724
|
-
|
725
|
-
this.range.moveEnd('character', end - this.range.text.length)
|
726
|
-
this.range.moveStart('character', start);
|
727
|
-
} else {
|
728
|
-
this.range.moveToElementText(el);
|
729
|
-
}
|
730
|
-
return this;
|
731
|
-
};
|
732
|
-
|
733
|
-
})();
|
734
|
-
|
735
|
-
|
736
|
-
// helpers -----------------
|
737
|
-
|
738
|
-
// iterates through a list of elements, calls cb on every text node
|
739
|
-
// if cb returns false, exits the iteration
|
740
|
-
var iterate = function(elems, cb){
|
741
|
-
var elem, start;
|
742
|
-
for (var i = 0; elems[i]; i++) {
|
743
|
-
elem = elems[i];
|
744
|
-
// Get the text from text nodes and CDATA nodes
|
745
|
-
if (elem.nodeType === 3 || elem.nodeType === 4) {
|
746
|
-
if (cb(elem) === false) {
|
747
|
-
return false;
|
748
|
-
}
|
749
|
-
// Traverse everything else, except comment nodes
|
750
|
-
}
|
751
|
-
else
|
752
|
-
if (elem.nodeType !== 8) {
|
753
|
-
if (iterate(elem.childNodes, cb) === false) {
|
754
|
-
return false;
|
755
|
-
}
|
756
|
-
}
|
757
|
-
}
|
758
|
-
|
759
|
-
},
|
760
|
-
isText = function(node){
|
761
|
-
return node.nodeType === 3 || node.nodeType === 4
|
762
|
-
},
|
763
|
-
iteratorMaker = function(toChildren, toNext){
|
764
|
-
return function( node, mustMoveRight ) {
|
765
|
-
// first try down
|
766
|
-
if(node[toChildren] && !mustMoveRight){
|
767
|
-
return isText(node[toChildren]) ?
|
768
|
-
node[toChildren] :
|
769
|
-
arguments.callee(node[toChildren])
|
770
|
-
} else if(node[toNext]) {
|
771
|
-
return isText(node[toNext]) ?
|
772
|
-
node[toNext] :
|
773
|
-
arguments.callee(node[toNext])
|
774
|
-
} else if(node.parentNode){
|
775
|
-
return arguments.callee(node.parentNode, true)
|
776
|
-
}
|
777
|
-
}
|
778
|
-
},
|
779
|
-
getNextTextNode = iteratorMaker("firstChild","nextSibling"),
|
780
|
-
getPrevTextNode = iteratorMaker("lastChild","previousSibling"),
|
781
|
-
callMove = function(container, offset, howMany){
|
782
|
-
if(isText(container)){
|
783
|
-
return move(container, offset+howMany)
|
784
|
-
} else {
|
785
|
-
return container.childNodes[offset] ?
|
786
|
-
move(container.childNodes[offset] , howMany) :
|
787
|
-
move(container.lastChild, howMany , true)
|
788
|
-
return
|
789
|
-
}
|
790
|
-
},
|
791
|
-
move = function(from, howMany){
|
792
|
-
var mover = howMany < 0 ?
|
793
|
-
getPrevTextNode : getNextTextNode;
|
794
|
-
|
795
|
-
howMany = Math.abs(howMany);
|
796
|
-
|
797
|
-
if(!isText(from)){
|
798
|
-
from = mover(from)
|
799
|
-
}
|
800
|
-
while(from && howMany >= from.nodeValue.length){
|
801
|
-
hasMany = howMany- from.nodeValue.length;
|
802
|
-
from = mover(from)
|
803
|
-
}
|
804
|
-
return {
|
805
|
-
node: from,
|
806
|
-
offset: mover === getNextTextNode ?
|
807
|
-
howMany :
|
808
|
-
from.nodeValue.length - howMany
|
809
|
-
}
|
810
|
-
},
|
811
|
-
supportWhitespace,
|
812
|
-
isWhitespace = function(el){
|
813
|
-
if(supportWhitespace == null){
|
814
|
-
supportWhitespace = 'isElementContentWhitespace' in el;
|
815
|
-
}
|
816
|
-
return (supportWhitespace? el.isElementContentWhitespace :
|
817
|
-
(el.nodeType === 3 && '' == el.data.trim()));
|
818
|
-
|
819
|
-
},
|
820
|
-
// if a point is within a rectangle
|
821
|
-
within = function(rect, point){
|
822
|
-
|
823
|
-
return rect.left <= point.clientX && rect.left + rect.width >= point.clientX &&
|
824
|
-
rect.top <= point.clientY &&
|
825
|
-
rect.top + rect.height >= point.clientY
|
826
|
-
},
|
827
|
-
// if a rectangle is within another rectangle
|
828
|
-
withinRect = function(outer, inner){
|
829
|
-
return within(outer, {
|
830
|
-
clientX: inner.left,
|
831
|
-
clientY: inner.top
|
832
|
-
}) && //top left
|
833
|
-
within(outer, {
|
834
|
-
clientX: inner.left + inner.width,
|
835
|
-
clientY: inner.top
|
836
|
-
}) && //top right
|
837
|
-
within(outer, {
|
838
|
-
clientX: inner.left,
|
839
|
-
clientY: inner.top + inner.height
|
840
|
-
}) && //bottom left
|
841
|
-
within(outer, {
|
842
|
-
clientX: inner.left + inner.width,
|
843
|
-
clientY: inner.top + inner.height
|
844
|
-
}) //bottom right
|
845
|
-
},
|
846
|
-
// gets the scroll offset from a window
|
847
|
-
scrollOffset = function( win){
|
848
|
-
var win = win ||window;
|
849
|
-
doc = win.document.documentElement, body = win.document.body;
|
850
|
-
|
851
|
-
return {
|
852
|
-
left: (doc && doc.scrollLeft || body && body.scrollLeft || 0) + (doc.clientLeft || 0),
|
853
|
-
top: (doc && doc.scrollTop || body && body.scrollTop || 0) + (doc.clientTop || 0)
|
854
|
-
};
|
855
|
-
};
|
856
|
-
|
857
|
-
|
858
|
-
support.moveToPoint = !!$.Range().range.moveToPoint
|
859
|
-
|
860
|
-
|
861
|
-
})(jQuery)
|