{"action":"created","issue":{"url":"https://api.github.com/repos/w3c/webcomponents/issues/81","repository_url":"https://api.github.com/repos/w3c/webcomponents","labels_url":"https://api.github.com/repos/w3c/webcomponents/issues/81/labels{/name}","comments_url":"https://api.github.com/repos/w3c/webcomponents/issues/81/comments","events_url":"https://api.github.com/repos/w3c/webcomponents/issues/81/events","html_url":"https://github.com/w3c/webcomponents/issues/81","id":80454379,"number":81,"title":"node.isConnected","user":{"login":"hayatoito","id":160288,"avatar_url":"https://avatars.githubusercontent.com/u/160288?v=3","gravatar_id":"","url":"https://api.github.com/users/hayatoito","html_url":"https://github.com/hayatoito","followers_url":"https://api.github.com/users/hayatoito/followers","following_url":"https://api.github.com/users/hayatoito/following{/other_user}","gists_url":"https://api.github.com/users/hayatoito/gists{/gist_id}","starred_url":"https://api.github.com/users/hayatoito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hayatoito/subscriptions","organizations_url":"https://api.github.com/users/hayatoito/orgs","repos_url":"https://api.github.com/users/hayatoito/repos","events_url":"https://api.github.com/users/hayatoito/events{/privacy}","received_events_url":"https://api.github.com/users/hayatoito/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/w3c/webcomponents/labels/html-dom","name":"html-dom","color":"009800"},{"url":"https://api.github.com/repos/w3c/webcomponents/labels/needs%20consensus","name":"needs consensus","color":"d4c5f9"},{"url":"https://api.github.com/repos/w3c/webcomponents/labels/shadow-dom","name":"shadow-dom","color":"207de5"},{"url":"https://api.github.com/repos/w3c/webcomponents/labels/v2","name":"v2","color":"f7c6c7"}],"state":"closed","locked":false,"assignee":{"login":"annevk","id":1544111,"avatar_url":"https://avatars.githubusercontent.com/u/1544111?v=3","gravatar_id":"","url":"https://api.github.com/users/annevk","html_url":"https://github.com/annevk","followers_url":"https://api.github.com/users/annevk/followers","following_url":"https://api.github.com/users/annevk/following{/other_user}","gists_url":"https://api.github.com/users/annevk/gists{/gist_id}","starred_url":"https://api.github.com/users/annevk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/annevk/subscriptions","organizations_url":"https://api.github.com/users/annevk/orgs","repos_url":"https://api.github.com/users/annevk/repos","events_url":"https://api.github.com/users/annevk/events{/privacy}","received_events_url":"https://api.github.com/users/annevk/received_events","type":"User","site_admin":false},"milestone":null,"comments":28,"created_at":"2015-05-25T08:49:56Z","updated_at":"2016-04-07T03:33:01Z","closed_at":"2016-03-31T10:05:56Z","body":"Title: [Shadow]: Need mechanism to tell if an element in a ShadowRoot has been inserted into the Document (bugzilla: 22141)\r\n\r\nMigrated from: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141\r\n\r\n----\r\ncomment: 0\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c0\r\n*Daniel Freedman* wrote on 2013-05-22 18:23:02 +0000.\r\n\r\nBecause of necessity of encapsulation, it is very hard to tell if an arbitrary element has been inserted into the document.\r\nBlink current hides the insertion state from compareDocumentPosition,but document.contains will return the actual insertion state.\r\nThis seems fine to me, because contains would not leak the state of the surrounding elements like compareDocumentPosition would.\r\nI can also imagine cases where user code may want to gate on the insertion state, such as updating a canvas.\r\n\r\n----\r\n\r\ncomment: 1\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c1\r\n*Dominic Cooney* wrote on 2013-06-21 04:27:34 +0000.\r\n\r\nBecause the author has to have the node in question in hand, it seems like document.contains returning an accurate value for elements in Shadow DOM violates the letter of encapsulation but not the spirit.\r\n\r\nI think document.contains should return a value reflecting whether the argument is in the document (including shadow trees.)\r\n\r\n----\r\n\r\ncomment: 2\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c2\r\n*Dimitri Glazkov* wrote on 2013-06-21 15:00:58 +0000.\r\n\r\n(In reply to comment #1)\r\n> Because the author has to have the node in question in hand, it seems like\r\n> document.contains returning an accurate value for elements in Shadow DOM\r\n> violates the letter of encapsulation but not the spirit.\r\n> \r\n> I think document.contains should return a value reflecting whether the\r\n> argument is in the document (including shadow trees.)\r\n\r\nThat's a neat way to look at the problem. I am convinced.\r\n\r\n----\r\n\r\ncomment: 3\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c3\r\n*Erik Arvidsson* wrote on 2013-08-01 20:05:42 +0000.\r\n\r\nI think this is the wrong solution. `contains` has always meant that I can walk from the node's parentNode to the ancestor. This changes the semantics of contains.\r\n\r\nWhat is the scenario we are trying to solve? Figuring that out, we can then come up with a reasonable API without changing the semantics of existing methods.\r\n\r\nLet me flip the coin a bit. I've been using contains as a signal that the node is not in the main document (in a shadow tree or a disconnected tree).\r\n\r\n----\r\n\r\ncomment: 4\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c4\r\n*Jan Miksovsky* wrote on 2013-10-24 23:14:53 +0000.\r\n\r\nI ran across this issue this week, and Daniel pointed me at this bug. See the thread at https://groups.google.com/forum/#!topic/polymer-dev/mGs_zkA_7-4.\r\n\r\nErik was asking for a scenario, and this thread presents one. An overlay (popup) element wants to track and/or absorb all clicks on the document. Clicks outside the overlay should dismiss the overlay, while clicks inside the element should have no effect. The overlay author wires up a click handler on the document, capturing events so that it gets first crack at them (and stop them before they might inadvertently triggering other handlers). The overlay's click handler looks at the event target to decide whether the target is in the overlay or not. For this purpose, the developer decides to use contains(). The dev tests the overlay's click tracking behavior with light DOM content inside the overlay, and all works well.\r\n\r\nLater, someone else (me) tries to include the overlay element in the shadow of another element, and distribute content into the overlay. When the user looks at the overlay, they see content presented inside the overlay. From the user's point of view, the overlay contains the content. However, if the user clicks on the (light DOM) content, the overlay's contains() check fails, and the overlay fails to behave properly.\r\n\r\nOne could argue the overlay element should be written differently. Maybe it could track clicks outside using capturing and track clicks inside using bubbling, or find some other solution. But I think the dev made a reasonable call to use contains() for this purpose, and it seemed to work for any tests they cared to make. It was only when the overlay element was subsumed into the shadow of another element that things broke.\r\n\r\nI'll hazard that similar issues are likely to come up wherever a dev tries to use contains() within a custom element. Subsuming that element into the shadow of another element will cause problems. I believe custom elements will have a general need to know whether they (visually) contain a given element, regardless of whether the element is in their shadow or distributed to them.\r\n\r\nHow this is done, whether through modifying contains() or something new, I'll leave to people wiser than me to figure out.\r\n\r\n----\r\n\r\ncomment: 5\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c5\r\n*Hayato Ito* wrote on 2013-10-25 04:09:07 +0000.\r\n\r\nI think we can simulate the proposed *contains()* in JavaScript by using InsertionPoint.getDistributedNodes() and Node.getDestinationInsertionPoints().\r\nI am aware that this will be burden for users, but it could be possible though I've not tried.\r\n\r\nI don't think it's good idea to change the semantics of existing contains(). It should consider only a node tree and should ignore the status of the composed tree.\r\n\r\nI am not against adding something new in native Shadow DOM if we need it absolutely.\r\n\r\n----\r\n\r\ncomment: 6\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c6\r\n*Daniel Freedman* wrote on 2014-03-11 18:30:42 +0000.\r\n\r\nUnfortunately, I think this is a very bad user experience decision.\r\n\r\nYes, we would be breaking the written semantics of document.contains, but we would be keeping the developer expectation that document.contains(node) means \"this node is *in* the document\".\r\n\r\nOtherwise we've broken the developer assumptions about this method, and introduced a whole new variety of bugs.\r\n\r\nFor example, the jQuery flot charting library draws a helpful chart hover target that follows the mouse. It uses document.contains to determine if it should add page scroll offsets to the mouse x/y position to draw the the target correctly.\r\n\r\nIn the Polymer ShadowDOM polyfill, we followed the spec, and it broke this library: https://github.com/Polymer/polymer/issues/162.\r\n\r\nEmber is another library that uses document.contains to determine if an element should instantiate its controller: https://github.com/Polymer/ShadowDOM/issues/365\r\n\r\nEven if we made a new function that does what we want, like Node.prototype.isInDocumentForReals, we still have to knock on all the library authors doors to get them to use the new method, or they say \"ShadowDOM broke my stuff, it sucks\" and everybody loses.\r\n\r\nWeb developers need their tools to work, and making document.contains continue to follow developer expectations seems like winning all around.\r\n\r\nWDYT?\r\n\r\n----\r\n\r\ncomment: 7\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c7\r\n*Hayato Ito* wrote on 2014-03-12 04:55:06 +0000.\r\n\r\nTo interpret the current spec literally, I think:\r\n\r\n- document.contains should always return *false* if the argument node is in a shadow tree, as Erik said in comment #3. There is no ancestor/descendant relationship if they are in the different node trees.\r\n\r\nI understand that this might cause a very bad user experience.\r\n\r\nHow do we proceed? Let me propose some ideas.\r\n\r\nA) Change the semantics of node.contains so that it should consider the tree of trees.\r\n   That means we are extending ancestor/descendant relationships beyond one node tree. I am afraid that we have to do *monkey-patch* to `node.contains` in the Shadow DOM spec.\r\n\r\nB) Leave node.contains as is. That means if the context object and argument node are in the different node trees, it always returns *false*.\r\n\r\n As alternative, we should provide a new API, such as node.inComposedTree(). node.inComposedTree return true if and only if:\r\n   The node participates in the composed tree whose root node is document.\r\n\r\nC) Better ideas are welcome.\r\n\r\n----\r\n\r\ncomment: 8\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c8\r\n*Hayato Ito* wrote on 2014-03-12 06:02:35 +0000.\r\n\r\nFYI.\r\n\r\nIn blink, looks like the semantics of `node.contains` changed in\r\nhttps://chromiumcodereview.appspot.com/21123005\r\n\r\nHowever, we don't have any spec for that. I'm not convinced with decision.\r\n\r\nI prefer Idea B.  WDYT?\r\n\r\n----\r\n\r\ncomment: 9\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c9\r\n*Hayato Ito* wrote on 2014-03-13 05:07:45 +0000.\r\n\r\nIf we go for idea B, we need API to satisfy the original requirement.\r\n\r\nBecause node.inComposedTree() is just an tentative idea, I appreciate opinions for better API to satisfy the requirement.\r\n\r\nOther ideas:\r\n- document.containsInComposedTree(node) - I think this is preferred.\r\n\r\nAny ideas are welcome!\r\n\r\n----\r\n\r\ncomment: 10\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c10\r\n*Elliott Sprehn* wrote on 2014-03-15 02:12:08 +0000.\r\n\r\n(In reply to Hayato Ito from comment #9)\r\n> If we go for idea B, we need API to satisfy the original requirement.\r\n> \r\n> Because node.inComposedTree() is just an tentative idea, I appreciate\r\n> opinions for better API to satisfy the requirement.\r\n> \r\n> Other ideas:\r\n> - document.containsInComposedTree(node) - I think this is preferred.\r\n> \r\n> Any ideas are welcome!\r\n\r\nI think there's two separate questions here, Document.contains and Node.contains seem like totally separate questions.\r\n\r\n\"Am I in this Document\"\r\n\"Am I a child of this Node\"\r\n\r\nNow that we have ShadowRoot.host you can actually walk up to the root and get the answer you want though, so perhaps reverting this is okay. We should probably add an inDocument() method though.\r\n\r\n----\r\n\r\ncomment: 11\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c11\r\n*Hayato Ito* wrote on 2014-03-17 04:44:16 +0000.\r\n\r\nFYI,\r\nIn blink, I've reverted the change of \"node.contains\": https://codereview.chromium.org/197283016/\r\n\r\n(In reply to Elliott Sprehn from comment #10)\r\n> (In reply to Hayato Ito from comment #9)\r\n> > If we go for idea B, we need API to satisfy the original requirement.\r\n> > \r\n> > Because node.inComposedTree() is just an tentative idea, I appreciate\r\n> > opinions for better API to satisfy the requirement.\r\n> > \r\n> > Other ideas:\r\n> > - document.containsInComposedTree(node) - I think this is preferred.\r\n> > \r\n> > Any ideas are welcome!\r\n> \r\n> I think there's two separate questions here, Document.contains and\r\n> Node.contains seem like totally separate questions.\r\n> \r\n> \"Am I in this Document\"\r\n> \"Am I a child of this Node\"\r\n\r\nAgreed. IMO, we should avoid such a double meaning.\r\nWe should have a more explicit API instead of re-using 'document.contains'.\r\n\r\n> \r\n> Now that we have ShadowRoot.host you can actually walk up to the root and\r\n> get the answer you want though, so perhaps reverting this is okay. We should\r\n> probably add an inDocument() method though.\r\n\r\nYeah, we should discuss further to pursuit a good API.\r\nI'd like to hear opinions from developers to address their use cases.\r\n\r\n----\r\n\r\ncomment: 12\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c12\r\n*Hayato Ito* wrote on 2014-08-06 08:23:58 +0000.\r\n\r\nBecause we already have /deep/ combinator, http://drafts.csswg.org/css-scoping/#selectordef-deep, I think `document.deepContains(node)` might be a good name.\r\n\r\nWDYT? If it's okay, let me spec that.\r\n\r\n----\r\n\r\ncomment: 13\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c13\r\n*Hayato Ito* wrote on 2014-08-06 08:37:35 +0000.\r\n\r\nIt seems that Document doesn't have `contains`.\r\nhttp://dom.spec.whatwg.org/#interface-document\r\n\r\nWe should add `deepContains` to Node, instead of Document.\r\nhttp://dom.spec.whatwg.org/#dom-node-contains\r\n\r\n----\r\n\r\ncomment: 14\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c14\r\n*Hayato Ito* wrote on 2014-08-07 05:37:19 +0000.\r\n\r\nI've added 'Node.deepContains(Node? other)' in\r\nhttps://github.com/w3c/webcomponents/commit/14322e526d53cde0814bec041d7fab6dd77f7e88\r\n\r\nI need a feedback.\r\nCould someone verify whether this definition satisfies our requirements or not?\r\n\r\n----\r\n\r\ncomment: 15\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c15\r\n*Olli Pettay* wrote on 2014-08-07 09:56:50 +0000.\r\n\r\nI don't really like deepContains (partly because I think CSS is wrong by exposing\r\nshadow dom in that way, and also because 'deep' doesn't really say anything.)\r\n\r\nCouldn't we change contains() to take second param, which could be\r\nsome dictionary.\r\n\r\nbool contains(Node? other, optional ContainsFilter filter)\r\n\r\ndictionary ContainsFilter\r\n{\r\n  bool includeShadowDOM = false; // includeShadowDOM is a bit bad name.\r\n}\r\n\r\n----\r\n\r\ncomment: 16\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c16\r\n*Hayato Ito* wrote on 2014-08-11 03:08:26 +0000.\r\n\r\nThank you for the feedback!\r\n\r\n(In reply to Olli Pettay from comment #15)\r\n> I don't really like deepContains (partly because I think CSS is wrong by\r\n> exposing\r\n> shadow dom in that way, and also because 'deep' doesn't really say anything.)\r\n> \r\n> Couldn't we change contains() to take second param, which could be\r\n> some dictionary.\r\n> \r\n> bool contains(Node? other, optional ContainsFilter filter)\r\n> \r\n> dictionary ContainsFilter\r\n> {\r\n>   bool includeShadowDOM = false; // includeShadowDOM is a bit bad name.\r\n> }\r\n\r\nIt looks better to me than deepContains. I like it.\r\nIf no one have better idea than this, I'l change the spec.\r\nIn this case, should I make a patch for DOM spec?\r\n\r\n----\r\n\r\ncomment: 17\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c17\r\n*Anne* wrote on 2014-08-25 08:12:30 +0000.\r\n\r\nWell, includeShadow or some such could work. Or includeShadowNodes. Let's not use the term \"DOM\" in any API. Ideally, the terms we use for shadow nodes are consistent in some way.\r\n\r\n----\r\n\r\ncomment: 18\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c18\r\n*Hayato Ito* wrote on 2014-08-25 08:35:46 +0000.\r\n\r\nWell, actually, the Shadow DOM spec doesn't define any technical definition of 'Shadow DOM'. That isn't well defined term. We should avoid using the term of 'Shadow DOM' in APIs.\r\n\r\nincludeNodesInShadowTrees might be the most unambiguous, however it looks too redundant.\r\n\r\nMy preferences are:\r\n\r\n- Most preferred -\r\n\r\nA. includeShadow\r\nB. includeShadowTrees\r\nC. includeNodesInShadowTrees\r\nD. includeShadowNodes\r\n\r\n- Least preferred -\r\n\r\nI don't have a strong opinion either. I am aware this might be bike-shed discussion, but the naming of API is important.\r\n\r\n----\r\n\r\ncomment: 19\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c19\r\n*Anne* wrote on 2014-08-25 08:40:45 +0000.\r\n\r\nincludeShadow seems fine. Shortest and to the point. So I guess we'll have shadow trees and the one `<textarea>` and friends use are isolated shadow trees? (And won't be exposed here of course.)\r\n\r\n----\r\n\r\ncomment: 20\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c20\r\n*Hayato Ito* wrote on 2014-08-25 09:02:57 +0000.\r\n\r\nGood question.\r\n\r\nIMO, document.contains(nodeInShadowTreesHostedByTextAreaElementInDocument, { includeShadow: treu}) should return `true`. However, I'm not confident.\r\n\r\nI am not sure whether there is a use case for that, assuming external developers can't get an access for such a node usually.\r\n\r\nAFAIK, only use cases I've heard so far is for nodes which are in user-created shadow trees, rather than nodes in UA shadow trees for built-in elements.\r\n\r\nIf I misunderstand your question, please correct me.\r\n\r\n----\r\n\r\ncomment: 21\r\ncomment_url: https://www.w3.org/Bugs/Public/show_bug.cgi?id=22141#c21\r\n*Pedram Emrouznejad* wrote on 2015-02-15 17:33:11 +0000.\r\n\r\nFor what's it worth, I managed to solve my need for a document.contains that cuts across shadow boundaries by doing: \r\n\r\nelement.matches(':host-context(body) *')\r\n\r\n(essentially, I needed to know if a shadow-nested element was in the main document)\r\n\r\n+1 to a more versatile document.contains though. I'm not sure what other possible options a dictionary would be good for, so I think just a simple true/false as the second parameter would work well. If there is need for further config in the future, then I guess you can still keep the true/false parameter and overload it with a dictionary."},"comment":{"url":"https://api.github.com/repos/w3c/webcomponents/issues/comments/206682764","html_url":"https://github.com/w3c/webcomponents/issues/81#issuecomment-206682764","issue_url":"https://api.github.com/repos/w3c/webcomponents/issues/81","id":206682764,"user":{"login":"hayatoito","id":160288,"avatar_url":"https://avatars.githubusercontent.com/u/160288?v=3","gravatar_id":"","url":"https://api.github.com/users/hayatoito","html_url":"https://github.com/hayatoito","followers_url":"https://api.github.com/users/hayatoito/followers","following_url":"https://api.github.com/users/hayatoito/following{/other_user}","gists_url":"https://api.github.com/users/hayatoito/gists{/gist_id}","starred_url":"https://api.github.com/users/hayatoito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hayatoito/subscriptions","organizations_url":"https://api.github.com/users/hayatoito/orgs","repos_url":"https://api.github.com/users/hayatoito/repos","events_url":"https://api.github.com/users/hayatoito/events{/privacy}","received_events_url":"https://api.github.com/users/hayatoito/received_events","type":"User","site_admin":false},"created_at":"2016-04-07T03:33:00Z","updated_at":"2016-04-07T03:33:00Z","body":"Blink might want to use \"isConnected\" too, instead of \"inShadowIncludingDocument\". Let me work on that  later."}}