{"action":"created","comment":{"url":"https://api.github.com/repos/google/blockly/pulls/comments/62137423","id":62137423,"diff_hunk":"@@ -0,0 +1,188 @@\n+/**\n+ * AccessibleBlockly\n+ *\n+ * Copyright 2016 Google Inc.\n+ * https://developers.google.com/blockly/\n+ *\n+ * Licensed under the Apache License, Version 2.0 (the 'License');\n+ * you may not use this file except in compliance with the License.\n+ * You may obtain a copy of the License at\n+ *\n+ *   http://www.apache.org/licenses/LICENSE-2.0\n+ *\n+ * Unless required by applicable law or agreed to in writing, software\n+ * distributed under the License is distributed on an 'AS IS' BASIS,\n+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+ * See the License for the specific language governing permissions and\n+ * limitations under the License.\n+ */\n+\n+/**\n+ * @fileoverview Angular2 Component that details how blocks are\n+ * rendered in the toolbox in AccessibleBlockly. Also handles any interactions\n+ * with the blocks.\n+ * @author madeeha@google.com (Madeeha Ghori)\n+ */\n+blocklyApp.ToolboxTreeView = ng.core\n+  .Component({\n+    selector: 'toolbox-tree-view',\n+    template: `\n+      <li #parentList aria-selected=false role=\"treeitem\" [attr.aria-level]=\"level\" id=\"{{createCategoryDependantId(index, parentList)}}\">\n+        <label #blockSummaryLabel id=\"blockly-{{block.id}}\" style=\"color:red\">{{block.toString()}}</label>\n+        {{setLabelledBy(parentList, concatStringWithSpaces(\"blockly-block-summary\", blockSummaryLabel.id))}}\n+        <ol role=\"group\" *ngIf=\"displayBlockMenu || block.inputList.length > 0\"  [attr.aria-level]=\"level+1\">\n+          {{addClass(parentList, \"blocklyHasChildren\")}}\n+          <li #listItem id=\"{{treeService.createId(listItem)}}\" *ngIf=\"displayBlockMenu\" role=\"treeitem\" aria-selected=false [attr.aria-level]=\"level+1\">\n+            {{setLabelledBy(listItem, concatStringWithSpaces(\"blockly-block-menu\", blockSummaryLabel.id))}}\n+            <label #label id=\"{{treeService.createId(label)}}\">block action list </label>\n+            <ol role=\"group\" *ngIf=\"displayBlockMenu\"  [attr.aria-level]=\"level+2\">\n+              <li #workspaceCopy id=\"{{treeService.createId(workspaceCopy)}}\" role=\"treeitem\" aria-selected=false [attr.aria-level]=\"level+2\">\n+                <button #workspaceCopyButton id=\"{{treeService.createId(workspaceCopyButton)}}\" (click)=\"copyToWorkspace(block)\">copy to workspace</button>\n+                {{setLabelledBy(workspaceCopy, concatStringWithSpaces(workspaceCopyButton.id, \"blockly-button\"))}}\n+              </li>\n+              <li #blockCopy id=\"{{treeService.createId(blockCopy)}}\" role=\"treeitem\" aria-selected=false [attr.aria-level]=\"level+2\">\n+                <button #blockCopyButton id=\"{{treeService.createId(blockCopyButton)}}\" (click)=\"sharedClipboardService.copy(block)\">copy to clipboard</button>\n+                {{setLabelledBy(blockCopy, concatStringWithSpaces(blockCopyButton.id, \"blockly-button\"))}}\n+              </li>\n+              <li #sendToSelected id=\"{{treeService.createId(sendToSelected)}}\" role=\"treeitem\" aria-selected=false [attr.aria-level]=\"level+2\">\n+                <button #sendToSelectedButton id=\"{{treeService.createId(sendToSelectedButton)}}\" (click)=\"copyToMarked(block)\" disabled=\"{{markedBlockCompatibilityHTMLText(block)}}\" [attr.aria-disabled]=\"markedBlockCompatibilityHTMLText(block)\">copy to marked spot</button>\n+                {{setLabelledBy(sendToSelected, concatStringWithSpaces(sendToSelectedButton.id, \"blockly-button\", markedBlockCompatibilityHTMLText(block)))}}\n+              </li>\n+            </ol>\n+            {{addClass(listItem, \"blocklyHasChildren\")}}\n+          </li>\n+          <div *ngFor=\"#inputBlock of block.inputList; #i=index\">\n+            <field-view [attr.aria-level]=\"level+1\" *ngFor=\"#field of getInfo(inputBlock); #j=index\" [field]=\"field\" [level]=\"level+1\"></field-view>\n+            <toolbox-tree-view *ngIf=\"inputBlock.connection && inputBlock.connection.targetBlock()\" [block]=\"inputBlock.connection.targetBlock()\" [displayBlockMenu]=\"false\" [level]=\"level+1\"></toolbox-tree-view>\n+            <li aria-selected=false #listItem1 role=\"treeitem\" [attr.aria-level]=\"level+1\" id=\"{{treeService.createId(listItem1)}}\" *ngIf=\"inputBlock.connection && !inputBlock.connection.targetBlock()\">\n+              <label #label id=\"{{treeService.createId(label)}}\">{{getInputTypeLabel(inputBlock.connection)}} {{valueOrStatement(inputBlock)}} needed:</label>\n+              {{setLabelledBy(listItem1, concatStringWithSpaces(\"blockly-argument-text\", label.id))}}\n+            </li>\n+          </div>\n+        </ol>\n+      </li>\n+      <toolbox-tree-view *ngIf= \"block.nextConnection && block.nextConnection.targetBlock()\" [level]=\"level\" [block]=\"block.nextConnection.targetBlock()\" [displayBlockMenu]=\"false\"></toolbox-tree-view>\n+    `,\n+    directives: [ng.core.forwardRef(\n+        function() { return blocklyApp.ToolboxTreeView; }),\n+        blocklyApp.FieldView],\n+    inputs: ['block', 'displayBlockMenu', 'level', 'index', 'tree'],\n+  })\n+  .Class({\n+    constructor: [blocklyApp.ClipboardService, blocklyApp.TreeService,\n+                  function(_clipboardService, _treeService) {\n+      this.infoBlocks = {};\n+      this.nextBlock = {};\n+      this.sharedClipboardService = _clipboardService;\n+      this.treeService = _treeService;\n+    }],\n+    setLabelledBy: function(item, id) {\n+      if (!item.getAttribute('aria-labelledby')) {\n+        item.setAttribute('aria-labelledby', id);\n+      }\n+    },\n+    concatStringWithSpaces: function() {\n+      var string = arguments[0];\n+      for (i = 1; i < arguments.length; i++) {\n+        var arg = arguments[i];\n+        // arg can be undefined and if so, should be ignored.\n+        if (arg) {\n+          string = string + ' ' + arguments[i];\n+        }\n+      }\n+      return string;\n+    },\n+    createCategoryDependantId: function(index, parentList) {\n+      // if this is the first block in a category-less toolbox,\n+      // the id should be blockly-toolbox-tree-node0\n+      if (index !== undefined && index === 0) {\n+        if (this.tree.getAttribute('aria-activedescendant') ==\n+          'blockly-toolbox-tree-node0') {\n+          this.addClass(parentList, 'blocklyActiveDescendant');\n+          parentList.setAttribute('aria-selected', 'true');\n+          this.treeService.setActiveDesc(parentList, this.tree.id);\n+        }\n+        return 'blockly-toolbox-tree-node0';\n+      } else {\n+        return this.treeService.createId(parentList);\n+      }\n+    },\n+    addClass: function(node, classText) {\n+      // ensure that node doesn't have class already in it\n+      var classList = node.className;\n+      classList = classList.split(' ');\n+      var canAdd = true;\n+      for (var i = 0; i < classList.length; i++) {\n+        if (classList[i] == classText) {\n+          canAdd = false;\n+        }\n+      }\n+      // add class if it doesn't\n+      if (canAdd) {\n+        if (classList.length) {\n+          node.className += classText;\n+        } else {\n+          node.className += ' ' + classText;\n+        }\n+      }\n+    },\n+    getInfo: function(block) {\n+      // list all inputs\n+      if (this.infoBlocks[block.id]) {\n+        this.infoBlocks[block.id].length = 0;\n+      } else {\n+        this.infoBlocks[block.id] = [];\n+      }\n+\n+      var blockInfoList = this.infoBlocks[block.id];\n+\n+      for (var j = 0, field; field = block.fieldRow[j]; j++) {","path":"accessible/toolbox_treeview.component.js","position":139,"original_position":139,"commit_id":"f62f55233385888659690fa32de4854ef92e732e","original_commit_id":"f62f55233385888659690fa32de4854ef92e732e","user":{"login":"NeilFraser","id":250480,"avatar_url":"https://avatars.githubusercontent.com/u/250480?v=3","gravatar_id":"","url":"https://api.github.com/users/NeilFraser","html_url":"https://github.com/NeilFraser","followers_url":"https://api.github.com/users/NeilFraser/followers","following_url":"https://api.github.com/users/NeilFraser/following{/other_user}","gists_url":"https://api.github.com/users/NeilFraser/gists{/gist_id}","starred_url":"https://api.github.com/users/NeilFraser/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NeilFraser/subscriptions","organizations_url":"https://api.github.com/users/NeilFraser/orgs","repos_url":"https://api.github.com/users/NeilFraser/repos","events_url":"https://api.github.com/users/NeilFraser/events{/privacy}","received_events_url":"https://api.github.com/users/NeilFraser/received_events","type":"User","site_admin":false},"body":"j?  Why not i?","created_at":"2016-05-05T00:41:04Z","updated_at":"2016-05-05T00:41:04Z","html_url":"https://github.com/google/blockly/pull/354#discussion_r62137423","pull_request_url":"https://api.github.com/repos/google/blockly/pulls/354","_links":{"self":{"href":"https://api.github.com/repos/google/blockly/pulls/comments/62137423"},"html":{"href":"https://github.com/google/blockly/pull/354#discussion_r62137423"},"pull_request":{"href":"https://api.github.com/repos/google/blockly/pulls/354"}}},"pull_request":{"url":"https://api.github.com/repos/google/blockly/pulls/354","id":68438554,"html_url":"https://github.com/google/blockly/pull/354","diff_url":"https://github.com/google/blockly/pull/354.diff","patch_url":"https://github.com/google/blockly/pull/354.patch","issue_url":"https://api.github.com/repos/google/blockly/issues/354","number":354,"state":"open","locked":false,"title":"AccessibleBlockly","user":{"login":"madCode","id":2229305,"avatar_url":"https://avatars.githubusercontent.com/u/2229305?v=3","gravatar_id":"","url":"https://api.github.com/users/madCode","html_url":"https://github.com/madCode","followers_url":"https://api.github.com/users/madCode/followers","following_url":"https://api.github.com/users/madCode/following{/other_user}","gists_url":"https://api.github.com/users/madCode/gists{/gist_id}","starred_url":"https://api.github.com/users/madCode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/madCode/subscriptions","organizations_url":"https://api.github.com/users/madCode/orgs","repos_url":"https://api.github.com/users/madCode/repos","events_url":"https://api.github.com/users/madCode/events{/privacy}","received_events_url":"https://api.github.com/users/madCode/received_events","type":"User","site_admin":false},"body":"AccessibleBlockly is an alternative web UI for developers that is supports keyboard navigation. If the user is blind, AccessibleBlockly is best experienced in conjunction with NVDA or Jaws on Firefox on Windows.","created_at":"2016-04-29T21:45:54Z","updated_at":"2016-05-05T00:41:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"87566a19a41a301b00c3f8b980b4209df2dd229e","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/google/blockly/pulls/354/commits","review_comments_url":"https://api.github.com/repos/google/blockly/pulls/354/comments","review_comment_url":"https://api.github.com/repos/google/blockly/pulls/comments{/number}","comments_url":"https://api.github.com/repos/google/blockly/issues/354/comments","statuses_url":"https://api.github.com/repos/google/blockly/statuses/f62f55233385888659690fa32de4854ef92e732e","head":{"label":"madCode:rebase-blind","ref":"rebase-blind","sha":"f62f55233385888659690fa32de4854ef92e732e","user":{"login":"madCode","id":2229305,"avatar_url":"https://avatars.githubusercontent.com/u/2229305?v=3","gravatar_id":"","url":"https://api.github.com/users/madCode","html_url":"https://github.com/madCode","followers_url":"https://api.github.com/users/madCode/followers","following_url":"https://api.github.com/users/madCode/following{/other_user}","gists_url":"https://api.github.com/users/madCode/gists{/gist_id}","starred_url":"https://api.github.com/users/madCode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/madCode/subscriptions","organizations_url":"https://api.github.com/users/madCode/orgs","repos_url":"https://api.github.com/users/madCode/repos","events_url":"https://api.github.com/users/madCode/events{/privacy}","received_events_url":"https://api.github.com/users/madCode/received_events","type":"User","site_admin":false},"repo":{"id":53075895,"name":"blockly","full_name":"madCode/blockly","owner":{"login":"madCode","id":2229305,"avatar_url":"https://avatars.githubusercontent.com/u/2229305?v=3","gravatar_id":"","url":"https://api.github.com/users/madCode","html_url":"https://github.com/madCode","followers_url":"https://api.github.com/users/madCode/followers","following_url":"https://api.github.com/users/madCode/following{/other_user}","gists_url":"https://api.github.com/users/madCode/gists{/gist_id}","starred_url":"https://api.github.com/users/madCode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/madCode/subscriptions","organizations_url":"https://api.github.com/users/madCode/orgs","repos_url":"https://api.github.com/users/madCode/repos","events_url":"https://api.github.com/users/madCode/events{/privacy}","received_events_url":"https://api.github.com/users/madCode/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/madCode/blockly","description":"The web-based visual programming editor.","fork":true,"url":"https://api.github.com/repos/madCode/blockly","forks_url":"https://api.github.com/repos/madCode/blockly/forks","keys_url":"https://api.github.com/repos/madCode/blockly/keys{/key_id}","collaborators_url":"https://api.github.com/repos/madCode/blockly/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/madCode/blockly/teams","hooks_url":"https://api.github.com/repos/madCode/blockly/hooks","issue_events_url":"https://api.github.com/repos/madCode/blockly/issues/events{/number}","events_url":"https://api.github.com/repos/madCode/blockly/events","assignees_url":"https://api.github.com/repos/madCode/blockly/assignees{/user}","branches_url":"https://api.github.com/repos/madCode/blockly/branches{/branch}","tags_url":"https://api.github.com/repos/madCode/blockly/tags","blobs_url":"https://api.github.com/repos/madCode/blockly/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/madCode/blockly/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/madCode/blockly/git/refs{/sha}","trees_url":"https://api.github.com/repos/madCode/blockly/git/trees{/sha}","statuses_url":"https://api.github.com/repos/madCode/blockly/statuses/{sha}","languages_url":"https://api.github.com/repos/madCode/blockly/languages","stargazers_url":"https://api.github.com/repos/madCode/blockly/stargazers","contributors_url":"https://api.github.com/repos/madCode/blockly/contributors","subscribers_url":"https://api.github.com/repos/madCode/blockly/subscribers","subscription_url":"https://api.github.com/repos/madCode/blockly/subscription","commits_url":"https://api.github.com/repos/madCode/blockly/commits{/sha}","git_commits_url":"https://api.github.com/repos/madCode/blockly/git/commits{/sha}","comments_url":"https://api.github.com/repos/madCode/blockly/comments{/number}","issue_comment_url":"https://api.github.com/repos/madCode/blockly/issues/comments{/number}","contents_url":"https://api.github.com/repos/madCode/blockly/contents/{+path}","compare_url":"https://api.github.com/repos/madCode/blockly/compare/{base}...{head}","merges_url":"https://api.github.com/repos/madCode/blockly/merges","archive_url":"https://api.github.com/repos/madCode/blockly/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/madCode/blockly/downloads","issues_url":"https://api.github.com/repos/madCode/blockly/issues{/number}","pulls_url":"https://api.github.com/repos/madCode/blockly/pulls{/number}","milestones_url":"https://api.github.com/repos/madCode/blockly/milestones{/number}","notifications_url":"https://api.github.com/repos/madCode/blockly/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/madCode/blockly/labels{/name}","releases_url":"https://api.github.com/repos/madCode/blockly/releases{/id}","deployments_url":"https://api.github.com/repos/madCode/blockly/deployments","created_at":"2016-03-03T19:09:31Z","updated_at":"2016-03-19T05:32:02Z","pushed_at":"2016-05-05T00:07:13Z","git_url":"git://github.com/madCode/blockly.git","ssh_url":"git@github.com:madCode/blockly.git","clone_url":"https://github.com/madCode/blockly.git","svn_url":"https://github.com/madCode/blockly","homepage":"https://developers.google.com/blockly/","size":73259,"stargazers_count":1,"watchers_count":1,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"google:develop","ref":"develop","sha":"6c0bf9f9662615cded68f1ae587042f20934694a","user":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"repo":{"id":13872231,"name":"blockly","full_name":"google/blockly","owner":{"login":"google","id":1342004,"avatar_url":"https://avatars.githubusercontent.com/u/1342004?v=3","gravatar_id":"","url":"https://api.github.com/users/google","html_url":"https://github.com/google","followers_url":"https://api.github.com/users/google/followers","following_url":"https://api.github.com/users/google/following{/other_user}","gists_url":"https://api.github.com/users/google/gists{/gist_id}","starred_url":"https://api.github.com/users/google/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/google/subscriptions","organizations_url":"https://api.github.com/users/google/orgs","repos_url":"https://api.github.com/users/google/repos","events_url":"https://api.github.com/users/google/events{/privacy}","received_events_url":"https://api.github.com/users/google/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/google/blockly","description":"The web-based visual programming editor.","fork":false,"url":"https://api.github.com/repos/google/blockly","forks_url":"https://api.github.com/repos/google/blockly/forks","keys_url":"https://api.github.com/repos/google/blockly/keys{/key_id}","collaborators_url":"https://api.github.com/repos/google/blockly/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/google/blockly/teams","hooks_url":"https://api.github.com/repos/google/blockly/hooks","issue_events_url":"https://api.github.com/repos/google/blockly/issues/events{/number}","events_url":"https://api.github.com/repos/google/blockly/events","assignees_url":"https://api.github.com/repos/google/blockly/assignees{/user}","branches_url":"https://api.github.com/repos/google/blockly/branches{/branch}","tags_url":"https://api.github.com/repos/google/blockly/tags","blobs_url":"https://api.github.com/repos/google/blockly/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/google/blockly/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/google/blockly/git/refs{/sha}","trees_url":"https://api.github.com/repos/google/blockly/git/trees{/sha}","statuses_url":"https://api.github.com/repos/google/blockly/statuses/{sha}","languages_url":"https://api.github.com/repos/google/blockly/languages","stargazers_url":"https://api.github.com/repos/google/blockly/stargazers","contributors_url":"https://api.github.com/repos/google/blockly/contributors","subscribers_url":"https://api.github.com/repos/google/blockly/subscribers","subscription_url":"https://api.github.com/repos/google/blockly/subscription","commits_url":"https://api.github.com/repos/google/blockly/commits{/sha}","git_commits_url":"https://api.github.com/repos/google/blockly/git/commits{/sha}","comments_url":"https://api.github.com/repos/google/blockly/comments{/number}","issue_comment_url":"https://api.github.com/repos/google/blockly/issues/comments{/number}","contents_url":"https://api.github.com/repos/google/blockly/contents/{+path}","compare_url":"https://api.github.com/repos/google/blockly/compare/{base}...{head}","merges_url":"https://api.github.com/repos/google/blockly/merges","archive_url":"https://api.github.com/repos/google/blockly/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/google/blockly/downloads","issues_url":"https://api.github.com/repos/google/blockly/issues{/number}","pulls_url":"https://api.github.com/repos/google/blockly/pulls{/number}","milestones_url":"https://api.github.com/repos/google/blockly/milestones{/number}","notifications_url":"https://api.github.com/repos/google/blockly/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/google/blockly/labels{/name}","releases_url":"https://api.github.com/repos/google/blockly/releases{/id}","deployments_url":"https://api.github.com/repos/google/blockly/deployments","created_at":"2013-10-25T21:13:33Z","updated_at":"2016-05-04T23:37:21Z","pushed_at":"2016-05-05T00:25:17Z","git_url":"git://github.com/google/blockly.git","ssh_url":"git@github.com:google/blockly.git","clone_url":"https://github.com/google/blockly.git","svn_url":"https://github.com/google/blockly","homepage":"https://developers.google.com/blockly/","size":102129,"stargazers_count":2247,"watchers_count":2247,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":734,"mirror_url":null,"open_issues_count":88,"forks":734,"open_issues":88,"watchers":2247,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/google/blockly/pulls/354"},"html":{"href":"https://github.com/google/blockly/pull/354"},"issue":{"href":"https://api.github.com/repos/google/blockly/issues/354"},"comments":{"href":"https://api.github.com/repos/google/blockly/issues/354/comments"},"review_comments":{"href":"https://api.github.com/repos/google/blockly/pulls/354/comments"},"review_comment":{"href":"https://api.github.com/repos/google/blockly/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/google/blockly/pulls/354/commits"},"statuses":{"href":"https://api.github.com/repos/google/blockly/statuses/f62f55233385888659690fa32de4854ef92e732e"}}}}