Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
Add Selection interface
Browse files Browse the repository at this point in the history
  • Loading branch information
arv committed Jan 23, 2014
1 parent 76028bf commit e9e4304
Show file tree
Hide file tree
Showing 9 changed files with 287 additions and 8 deletions.
1 change: 1 addition & 0 deletions build.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"src/wrappers/ShadowRoot.js",
"src/ShadowRenderer.js",
"src/wrappers/elements-with-form-property.js",
"src/wrappers/Selection.js",
"src/wrappers/Document.js",
"src/wrappers/Window.js",
"src/wrappers/override-constructors.js"
Expand Down
1 change: 1 addition & 0 deletions shadowdom.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
'src/wrappers/ShadowRoot.js',
'src/ShadowRenderer.js',
'src/wrappers/elements-with-form-property.js',
'src/wrappers/Selection.js',
'src/wrappers/Document.js',
'src/wrappers/Window.js',
'src/wrappers/override-constructors.js'
Expand Down
12 changes: 10 additions & 2 deletions src/wrappers/Document.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
var GetElementsByInterface = scope.GetElementsByInterface;
var Node = scope.wrappers.Node;
var ParentNodeInterface = scope.ParentNodeInterface;
var Selection = scope.wrappers.Selection;
var SelectorsInterface = scope.SelectorsInterface;
var ShadowRoot = scope.wrappers.ShadowRoot;
var defineWrapGetter = scope.defineWrapGetter;
Expand All @@ -16,9 +17,10 @@
var matchesNames = scope.matchesNames;
var mixin = scope.mixin;
var registerWrapper = scope.registerWrapper;
var renderAllPending = scope.renderAllPending;
var rewrap = scope.rewrap;
var unwrap = scope.unwrap;
var wrap = scope.wrap;
var rewrap = scope.rewrap;
var wrapEventTargetMethods = scope.wrapEventTargetMethods;
var wrapNodeList = scope.wrapNodeList;

Expand Down Expand Up @@ -55,7 +57,7 @@
'createEventNS',
'createRange',
'createTextNode',
'getElementById',
'getElementById'
].forEach(wrapMethod);

var originalAdoptNode = document.adoptNode;
Expand All @@ -82,6 +84,7 @@
}

var originalImportNode = document.importNode;
var originalGetSelection = document.getSelection;

mixin(Document.prototype, {
adoptNode: function(node) {
Expand All @@ -103,6 +106,10 @@
}
}
return clone;
},
getSelection: function() {
renderAllPending();
return new Selection(originalGetSelection.call(unwrap(this)));
}
});

Expand Down Expand Up @@ -239,6 +246,7 @@
'createTextNode',
'elementFromPoint',
'getElementById',
'getSelection',
]);

mixin(Document.prototype, GetElementsByInterface);
Expand Down
3 changes: 3 additions & 0 deletions src/wrappers/Range.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
},
intersectsNode: function(node) {
return this.impl.intersectsNode(unwrapIfNeeded(node));
},
toString: function() {
return this.impl.toString();
}
};

Expand Down
67 changes: 67 additions & 0 deletions src/wrappers/Selection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2014 The Polymer Authors. All rights reserved.
// Use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE file.

(function(scope) {
'use strict';

var registerWrapper = scope.registerWrapper;
var unwrap = scope.unwrap;
var unwrapIfNeeded = scope.unwrapIfNeeded;
var wrap = scope.wrap;

var OriginalSelection = window.Selection;

function Selection(impl) {
this.impl = impl;
}
Selection.prototype = {
get anchorNode() {
return wrap(this.impl.anchorNode);
},
get focusNode() {
return wrap(this.impl.focusNode);
},
addRange: function(range) {
this.impl.addRange(unwrap(range));
},
collapse: function(node, index) {
this.impl.collapse(unwrapIfNeeded(node), index);
},
containsNode: function(node, allowPartial) {
return this.impl.containsNode(unwrapIfNeeded(node), allowPartial);
},
extend: function(node, offset) {
this.impl.extend(unwrapIfNeeded(node), offset);
},
getRangeAt: function(index) {
return wrap(this.impl.getRangeAt(index));
},
removeRange: function(range) {
this.impl.removeRange(unwrap(range));
},
selectAllChildren: function(node) {
this.impl.selectAllChildren(unwrapIfNeeded(node));
},
toString: function() {
return this.impl.toString();
}
};

// WebKit extensions. Not implemented.
// readonly attribute Node baseNode;
// readonly attribute long baseOffset;
// readonly attribute Node extentNode;
// readonly attribute long extentOffset;
// [RaisesException] void setBaseAndExtent([Default=Undefined] optional Node baseNode,
// [Default=Undefined] optional long baseOffset,
// [Default=Undefined] optional Node extentNode,
// [Default=Undefined] optional long extentOffset);
// [RaisesException, ImplementedAs=collapse] void setPosition([Default=Undefined] optional Node node,
// [Default=Undefined] optional long offset);

registerWrapper(window.Selection, Selection, window.getSelection());

scope.wrappers.Selection = Selection;

})(window.ShadowDOMPolyfill);
22 changes: 16 additions & 6 deletions src/wrappers/Window.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,34 @@
'use strict';

var EventTarget = scope.wrappers.EventTarget;
var Selection = scope.wrappers.Selection;
var mixin = scope.mixin;
var registerWrapper = scope.registerWrapper;
var renderAllPending = scope.renderAllPending;
var unwrap = scope.unwrap;
var unwrapIfNeeded = scope.unwrapIfNeeded;
var wrap = scope.wrap;
var renderAllPending = scope.renderAllPending;

var OriginalWindow = window.Window;
var originalGetComputedStyle = window.getComputedStyle;
var originalGetSelection = window.getSelection;

function Window(impl) {
EventTarget.call(this, impl);
}
Window.prototype = Object.create(EventTarget.prototype);

var originalGetComputedStyle = window.getComputedStyle;
OriginalWindow.prototype.getComputedStyle = function(el, pseudo) {
renderAllPending();
return originalGetComputedStyle.call(this || window, unwrapIfNeeded(el),
pseudo);
return wrap(this || window).getComputedStyle(unwrapIfNeeded(el), pseudo);
};

OriginalWindow.prototype.getSelection = function() {
return wrap(this || window).getSelection();
};

// Work around for https://bugzilla.mozilla.org/show_bug.cgi?id=943065
delete window.getComputedStyle;
delete window.getSelection;

['addEventListener', 'removeEventListener', 'dispatchEvent'].forEach(
function(name) {
Expand All @@ -43,9 +48,14 @@

mixin(Window.prototype, {
getComputedStyle: function(el, pseudo) {
renderAllPending();
return originalGetComputedStyle.call(unwrap(this), unwrapIfNeeded(el),
pseudo);
}
},
getSelection: function() {
renderAllPending();
return new Selection(originalGetSelection.call(unwrap(this)));
},
});

registerWrapper(OriginalWindow, Window);
Expand Down
19 changes: 19 additions & 0 deletions test/js/Range.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ suite('Range', function() {

var wrap = ShadowDOMPolyfill.wrap;

var div;

teardown(function() {
if (div && div.parentNode)
div.parentNode.removeChild(div);
div = undefined;
});

test('instanceof', function() {
var range = document.createRange();
assert.instanceOf(range, Range);
Expand Down Expand Up @@ -55,4 +63,15 @@ suite('Range', function() {
assert.isFalse(range.hasOwnProperty('startOffset'));
});

test('toString', function() {
var range = document.createRange();
div = document.createElement('div');
document.body.appendChild(div);
div.innerHTML = '<a>a</a><b>b</b><c>c</c>';
var a = div.firstChild;
var b = a.nextSibling;
range.selectNode(b);
assert.equal(range.toString(), 'b');
});

});
Loading

0 comments on commit e9e4304

Please sign in to comment.