jquerypp-rails 1.0.1.1.rc3 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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)
|