Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Wesley Luyten committed Mar 6, 2014
0 parents commit 638c59a
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
node_modules
3 changes: 3 additions & 0 deletions README.md
@@ -0,0 +1,3 @@
# Selection Shiv

window.getSelection shiv for IE8 or lower
33 changes: 33 additions & 0 deletions gulpfile.js
@@ -0,0 +1,33 @@

var gulp = require('gulp');
var coffee = require('gulp-coffee');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');
var wrap = require('gulp-wrap');
var rename = require('gulp-rename');

var paths = {
scripts: 'src/*.coffee'
};

var wrapTemplate =
'(function(window, document) {' +
'<%= contents %>' +
'})(window, document);';

gulp.task('scripts', function() {
gulp.src(paths.scripts)
.pipe(coffee({ bare: true }))
.pipe(concat('selection-shiv.js'))
.pipe(wrap(wrapTemplate))
.pipe(gulp.dest(''))
.pipe(rename('selection-shiv.min.js'))
.pipe(uglify())
.pipe(gulp.dest(''));
});

gulp.task('watch', function() {
gulp.watch(paths.scripts, ['scripts']);
});

gulp.task('default', ['scripts']);
50 changes: 50 additions & 0 deletions index.html
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<title>Selection shiv</title>
</head>
<body>

<div id="text" contenteditable="true">
Select <b>Bold</b>
<p>Para <b>Strong</b></p>
<p>Para <b>Strong</b></p>
</div>
<br/>
<div id="output"></div>

<script src="selection-shiv.js"></script>
<script src="http://code.jquery.com/jquery.min.js"></script>
<script>
$(function() {
$(document).on('mouseup', function() {
var selection = window.getSelection();
if (selection.rangeCount > 0) {
var range = selection.getRangeAt(0),
ancestor = range.commonAncestorContainer,
output = [
'<br/>rangeCount: ',
selection.rangeCount,
'<br/>anchorOffset',
selection.anchorOffset,

'<br/>commonAncestorContainer: ',
ancestor.tagType == 3 ? 'TEXT' : ancestor.tagName,

'<br/>startContainer: ',
range.startContainer.data,
'<br/>startOffset: ',
range.startOffset,

'<br/>endContainer: ',
range.endContainer.data,
'<br/>endOffset: ',
range.endOffset
];
$('#output').html(output.join(' '));
}
});
});
</script>
</body>
</html>
87 changes: 87 additions & 0 deletions selection-shiv.js
@@ -0,0 +1,87 @@
(function(window, document) {if (window.getSelection || !document.selection) {
return;
}

window.getSelection = function() {
return new Selection;
};

document.createRange = function() {
return new Range;
};

var Range;

Range = (function() {
function Range(selection) {
var flag, parent, result, temp;
this.selection = selection;
this.range = this.selection.createRange();
parent = this.range.parentElement();
this.commonAncestorContainer = parent;
temp = this.range.duplicate();
temp.moveToElementText(parent);
flag = this.range.text.length > 0 ? 0 : 1;
temp.setEndPoint('EndToStart', this.range);
result = this.findNodeByPos(parent, temp.text.length, flag);
this.startContainer = result.el;
this.startOffset = result.offset;
temp.setEndPoint('EndToEnd', this.range);
result = this.findNodeByPos(parent, temp.text.length, 1);
this.endContainer = result.el;
this.endOffset = result.offset;
}

Range.prototype.findNodeByPos = function(parent, pos, end) {
var fn, obj;
if (end == null) {
end = 0;
}
obj = {
length: 0,
el: 0,
offset: 0
};
(fn = function(parent, pos, end, obj) {
var node, _i, _len, _ref, _results;
_ref = parent.childNodes;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
if (node.nodeType === 3) {
if (obj.length + node.nodeValue.length + end > pos) {
obj.el = node;
obj.offset = pos - obj.length;
break;
}
_results.push(obj.length += node.nodeValue.length);
} else {
_results.push(fn(node, pos, end, obj));
}
}
return _results;
})(parent, pos, end, obj);
return obj;
};

return Range;

})();

var Selection;

Selection = (function() {
function Selection() {
this.rangeCount = 1;
this.selection = document.selection;
this.range = new Range(this.selection);
}

Selection.prototype.getRangeAt = function() {
return this.range;
};

return Selection;

})();
})(window, document);
1 change: 1 addition & 0 deletions selection-shiv.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions src/main.coffee
@@ -0,0 +1,9 @@


if window.getSelection || !document.selection then return

window.getSelection = ->
new Selection

document.createRange = ->
new Range
37 changes: 37 additions & 0 deletions src/range.coffee
@@ -0,0 +1,37 @@

class Range
constructor: (@selection) ->
@range = @selection.createRange()

parent = @range.parentElement()
@commonAncestorContainer = parent

temp = @range.duplicate()
temp.moveToElementText(parent)

# if range text length > 0 try to stay in start
# element when the cursor is right on a boundary
flag = if @range.text.length > 0 then 0 else 1
temp.setEndPoint('EndToStart', @range)
result = @findNodeByPos(parent, temp.text.length, flag)
@startContainer = result.el
@startOffset = result.offset

temp.setEndPoint('EndToEnd', @range)
result = @findNodeByPos(parent, temp.text.length, 1)
@endContainer = result.el
@endOffset = result.offset

findNodeByPos: (parent, pos, end=0) ->
obj = { length: 0, el: 0, offset: 0 }
do fn = (parent, pos, end, obj) ->
for node in parent.childNodes
if node.nodeType == 3
if obj.length + node.nodeValue.length + end > pos
obj.el = node
obj.offset = pos - obj.length
break
obj.length += node.nodeValue.length
else
fn(node, pos, end, obj)
return obj
10 changes: 10 additions & 0 deletions src/selection.coffee
@@ -0,0 +1,10 @@

class Selection
constructor: ->
@rangeCount = 1
@selection = document.selection
@range = new Range(@selection)

getRangeAt: ->
@range

0 comments on commit 638c59a

Please sign in to comment.