diff --git a/src/item/HitResult.js b/src/item/HitResult.js
index c9069e39..c2fadde5 100644
--- a/src/item/HitResult.js
+++ b/src/item/HitResult.js
@@ -108,7 +108,8 @@ var HitResult = Base.extend(/** @lends HitResult# */{
// Use _merged property to not repeatetly merge using new Base in
// recursion.
return options && options._merged ? options : new Base({
- // Type of item, for instanceof check: PathItem, TexItem, etc
+ // Type of item, for instanceof check: 'group', 'layer', 'path',
+ // 'compound-path', 'shape','raster', 'placed-symbol', ...
type: null,
// Tolerance
tolerance: paper.project.options.hitTolerance || 2,
diff --git a/src/item/Item.js b/src/item/Item.js
index 118b3b8d..f43a991b 100644
--- a/src/item/Item.js
+++ b/src/item/Item.js
@@ -292,8 +292,8 @@ var Item = Base.extend(Callback, /** @lends Item# */{
/**
* The type of the item as a string.
*
- * @type String('group', 'layer', 'path', 'compound-path', 'raster',
- * 'placed-symbol', 'point-text')
+ * @type String('group', 'layer', 'path', 'compound-path', 'shape',
+ * 'raster', 'placed-symbol', 'point-text')
* @bean
*/
getType: function() {
@@ -1532,7 +1532,8 @@ var Item = Base.extend(Callback, /** @lends Item# */{
* in points. Can also be controlled through
* {@link Project#options}{@code .hitTolerance}.
* options.type: Only hit test again a certain item
- * type: {@link PathItem}, {@link Raster}, {@link TextItem}, etc.
+ * type: {String('group', 'layer', 'path', 'compound-path', 'shape',
+ * 'raster', 'placed-symbol', 'point-text')}, etc.
* options.fill: {@code Boolean} – hit test the fill of items.
* options.stroke: {@code Boolean} – hit test the curves of path
* items, taking into account stroke width.
@@ -1574,9 +1575,13 @@ var Item = Base.extend(Callback, /** @lends Item# */{
// Transform point to local coordinates but use untransformed point
// for bounds check above.
point = this._matrix._inverseTransform(point);
-
- var that = this,
+ // Filter for type, guides and selected items if that's required.
+ var checkSelf = !(options.guides && !this._guide
+ || options.selected && !this._selected
+ || options.type && this._type !== options.type),
+ that = this,
res;
+
function checkBounds(type, part) {
var pt = bounds['get' + part]();
// TODO: We need to transform the point back to the coordinate
@@ -1586,9 +1591,8 @@ var Item = Base.extend(Callback, /** @lends Item# */{
{ name: Base.hyphenate(part), point: pt });
}
- if ((options.center || options.bounds) &&
- // Ignore top level layers:
- !(this instanceof Layer && !this._parent)) {
+ // Ignore top level layers by checking for _parent:
+ if (checkSelf && (options.center || options.bounds) && this._parent) {
// Don't get the transformed bounds, check against transformed
// points instead
var bounds = this._getBounds('getBounds');
@@ -1605,30 +1609,29 @@ var Item = Base.extend(Callback, /** @lends Item# */{
}
}
- // TODO: Support option.type even for things like CompoundPath where
- // children are matched but the parent is returned.
-
- // Filter for guides or selected items if that's required
- if ((res || (res = this._children || !(options.guides && !this._guide
- || options.selected && !this._selected)
- ? this._hitTest(point, options) : null))
- && res.point) {
- // Transform the point back to the outer coordinate system.
- res.point = that._matrix.transform(res.point);
+ var children = !res && this._children;
+ if (children) {
+ var opts = this._getChildHitTestOptions(options);
+ // Loop backwards, so items that get drawn last are tested first
+ for (var i = children.length - 1; i >= 0 && !res; i--)
+ res = children[i].hitTest(point, opts);
}
+ if (!res && checkSelf)
+ res = this._hitTest(point, options);
+ // Transform the point back to the outer coordinate system.
+ if (res && res.point)
+ res.point = that._matrix.transform(res.point);
return res;
},
+ _getChildHitTestOptions: function(options) {
+ return options;
+ },
+
_hitTest: function(point, options) {
- var children = this._children;
- if (children) {
- // Loop backwards, so items that get drawn last are tested first
- for (var i = children.length - 1, res; i >= 0; i--)
- if (res = children[i].hitTest(point, options))
- return res;
- } else if (options.fill && this.hasFill() && this._contains(point)) {
+ // The default implementation honly handles 'fill' through #_contains()
+ if (options.fill && this.hasFill() && this._contains(point))
return new HitResult('fill', this);
- }
},
// DOCS: Item#matches
diff --git a/src/item/PlacedSymbol.js b/src/item/PlacedSymbol.js
index bc66aea2..24ec45d6 100644
--- a/src/item/PlacedSymbol.js
+++ b/src/item/PlacedSymbol.js
@@ -121,12 +121,12 @@ var PlacedSymbol = Item.extend(/** @lends PlacedSymbol# */{
},
_hitTest: function(point, options, matrix) {
- var result = this._symbol._definition._hitTest(point, options, matrix);
+ var res = this._symbol._definition._hitTest(point, options, matrix);
// TODO: When the symbol's definition is a path, should hitResult
// contain information like HitResult#curve?
- if (result)
- result.item = this;
- return result;
+ if (res)
+ res.item = this;
+ return res;
},
_draw: function(ctx, param) {
diff --git a/src/path/CompoundPath.js b/src/path/CompoundPath.js
index 5dca4722..3b648f0d 100644
--- a/src/path/CompoundPath.js
+++ b/src/path/CompoundPath.js
@@ -244,24 +244,13 @@ var CompoundPath = PathItem.extend(/** @lends CompoundPath# */{
return winding;
},
- _hitTest : function _hitTest(point, options) {
- // Do not test children for fill, since a compound path forms one shape.
- // options.compoundChildren allows to specifically do so, see below.
- var res = _hitTest.base.call(this, point,
- new Base(options, { fill: false }));
- if (!res) {
- // If asked to query all children seperately, perform the same loop
- // as Item#hitTest() now on the compound children.
- if (options.compoundChildren) {
- var children = this._children;
- for (var i = children.length - 1; i >= 0 && !res; i--)
- res = children[i]._hitTest(point, options);
- } else if (options.fill && this.hasFill()
- && this._contains(point)) {
- res = new HitResult('fill', this);
- }
- }
- return res;
+ _getChildHitTestOptions: function(options) {
+ // If we're not specifically asked to returns paths through
+ // options.type == 'path' do not test children for fill, since a
+ // compound path forms one shape.
+ return options.type === 'path'
+ ? options
+ : new Base(options, { fill: false });
},
_draw: function(ctx, param) {
diff --git a/src/project/Project.js b/src/project/Project.js
index e5e6f979..c9011c99 100644
--- a/src/project/Project.js
+++ b/src/project/Project.js
@@ -263,7 +263,8 @@ var Project = PaperScopeItem.extend(/** @lends Project# */{
* in points, can also be controlled through
* {@link Project#options}{@code .hitTolerance}.
* options.type: Only hit test again a certain item
- * type: {@link PathItem}, {@link Raster}, {@link TextItem}, etc.
+ * type: {String('group', 'layer', 'path', 'compound-path', 'shape',
+ * 'raster', 'placed-symbol', 'point-text')}, etc.
* options.fill: {@code Boolean} – hit test the fill of items.
* options.stroke: {@code Boolean} – hit test the curves of path
* items, taking into account stroke width.