{"action":"created","comment":{"url":"https://api.github.com/repos/openlayers/ol3/pulls/comments/25132175","id":25132175,"diff_hunk":"@@ -0,0 +1,217 @@\n+goog.provide('ol.source.TileArcGISRest');\n+\n+goog.require('goog.array');\n+goog.require('goog.asserts');\n+goog.require('goog.math');\n+goog.require('goog.object');\n+goog.require('goog.string');\n+goog.require('goog.uri.utils');\n+goog.require('ol');\n+goog.require('ol.TileCoord');\n+goog.require('ol.TileUrlFunction');\n+goog.require('ol.extent');\n+goog.require('ol.proj');\n+goog.require('ol.source.TileImage');\n+goog.require('ol.tilecoord');\n+\n+\n+\n+/**\n+ * @classdesc\n+ * Layer source for tile data from ArcGIS Rest services. Map and Image\n+ * Services are supported.\n+ *\n+ * @constructor\n+ * @extends {ol.source.TileImage}\n+ * @param {olx.source.TileArcGISRestOptions=} opt_options Tile ArcGIS Rest\n+ *     options.\n+ * @api stable\n+ */\n+ol.source.TileArcGISRest = function(opt_options) {\n+\n+  var options = goog.isDef(opt_options) ? opt_options : {};\n+\n+  var params = goog.isDef(options.params) ? options.params : {};\n+\n+  goog.base(this, {\n+    attributions: options.attributions,\n+    logo: options.logo,\n+    projection: options.projection,\n+    tileGrid: options.tileGrid,\n+    tileLoadFunction: options.tileLoadFunction,\n+    tileUrlFunction: goog.bind(this.tileUrlFunction_, this)\n+  });\n+\n+  var urls = options.urls;\n+  if (!goog.isDef(urls) && goog.isDef(options.url)) {\n+    urls = ol.TileUrlFunction.expandUrl(options.url);\n+  }\n+\n+  /**\n+   * @private\n+   * @type {!Array.<string>}\n+   */\n+  this.urls_ = goog.isDefAndNotNull(urls) ? urls : [];\n+\n+  /**\n+   * @private\n+   * @type {Object}\n+   */\n+  this.params_ = params;\n+\n+  /**\n+   * @private\n+   * @type {ol.Extent}\n+   */\n+  this.tmpExtent_ = ol.extent.createEmpty();\n+\n+};\n+goog.inherits(ol.source.TileArcGISRest, ol.source.TileImage);\n+\n+\n+/**\n+ * Get the user-provided params, i.e. those passed to the constructor through\n+ * the \"params\" option, and possibly updated using the updateParams method.\n+ * @return {Object} Params.\n+ * @api\n+ */\n+ol.source.TileArcGISRest.prototype.getParams = function() {\n+  return this.params_;\n+};\n+\n+\n+/**\n+ * @param {ol.TileCoord} tileCoord Tile coordinate.\n+ * @param {number} tileSize Tile size.\n+ * @param {ol.Extent} tileExtent Tile extent.\n+ * @param {number} pixelRatio Pixel ratio.\n+ * @param {ol.proj.Projection} projection Projection.\n+ * @param {Object} params Params.\n+ * @return {string|undefined} Request URL.\n+ * @private\n+ */\n+ol.source.TileArcGISRest.prototype.getRequestUrl_ =\n+    function(tileCoord, tileSize, tileExtent,\n+        pixelRatio, projection, params) {\n+\n+  var urls = this.urls_;\n+  if (goog.array.isEmpty(urls)) {\n+    return undefined;\n+  }\n+\n+  // ArcGIS Server only wants the numeric portion of the projection ID.\n+  var projWords = projection.getCode().split(':');\n+  var srid = projWords[projWords.length - 1];\n+\n+  params.SIZE = tileSize + ',' + tileSize;\n+  params.BBOX = tileExtent.join(',');\n+  params.BBOXSR = srid;\n+  params.IMAGESR = srid;\n+\n+  var url;\n+  if (urls.length == 1) {\n+    url = urls[0];\n+  } else {\n+    var index = goog.math.modulo(ol.tilecoord.hash(tileCoord), urls.length);\n+    url = urls[index];\n+  }\n+\n+  if (!goog.string.endsWith(url, '/')) {\n+    url = url + '/';\n+  }\n+\n+  // If a MapServer, use export. If an ImageServer, use exportImage.\n+  if (goog.string.endsWith(url, 'MapServer/')) {\n+    url = url + 'export';\n+  }\n+  else if (goog.string.endsWith(url, 'ImageServer/')) {\n+    url = url + 'exportImage';\n+  }\n+  else {\n+    goog.asserts.fail('Unknown Rest Service', url);\n+  }\n+\n+  return goog.uri.utils.appendParamsFromMap(url, params);\n+};\n+\n+\n+/**\n+ * Return the URLs used for this ArcGIS source.\n+ * @return {!Array.<string>} URLs.\n+ * @api stable\n+ */\n+ol.source.TileArcGISRest.prototype.getUrls = function() {\n+  return this.urls_;\n+};\n+\n+\n+/**\n+ * @param {string|undefined} url URL.\n+ * @api stable\n+ */\n+ol.source.TileArcGISRest.prototype.setUrl = function(url) {\n+  var urls = goog.isDef(url) ? ol.TileUrlFunction.expandUrl(url) : null;\n+  this.setUrls(urls);\n+};\n+\n+\n+/**\n+ * @param {Array.<string>|undefined} urls URLs.\n+ * @api stable\n+ */\n+ol.source.TileArcGISRest.prototype.setUrls = function(urls) {\n+  this.urls_ = goog.isDefAndNotNull(urls) ? urls : [];\n+  this.changed();\n+};\n+\n+\n+/**\n+ * @param {ol.TileCoord} tileCoord Tile coordinate.\n+ * @param {number} pixelRatio Pixel ratio.\n+ * @param {ol.proj.Projection} projection Projection.\n+ * @return {string|undefined} Tile URL.\n+ * @private\n+ */\n+ol.source.TileArcGISRest.prototype.tileUrlFunction_ =\n+    function(tileCoord, pixelRatio, projection) {\n+\n+  var tileGrid = this.getTileGrid();\n+  if (goog.isNull(tileGrid)) {\n+    tileGrid = this.getTileGridForProjection(projection);\n+  }\n+\n+  if (tileGrid.getResolutions().length <= tileCoord[0]) {\n+    return undefined;\n+  }\n+\n+  var tileExtent = tileGrid.getTileCoordExtent(\n+      tileCoord, this.tmpExtent_);\n+  var tileSize = tileGrid.getTileSize(tileCoord[0]);\n+\n+  if (pixelRatio != 1) {\n+    tileSize = (tileSize * pixelRatio + 0.5) | 0;\n+  }\n+\n+  // Apply default params and override with user specified values.\n+  var baseParams = {\n+    'F': 'image',\n+    'FORMAT': 'PNG32',\n+    'TRANSPARENT': true\n+  };\n+  goog.object.extend(baseParams, this.params_);\n+\n+  return this.getRequestUrl_(tileCoord, tileSize, tileExtent,\n+      pixelRatio, projection, baseParams);\n+};\n+\n+\n+/**\n+ * Update the user-provided params.\n+ * @param {Object} params Params.\n+ * @api stable\n+ */\n+ol.source.TileArcGISRest.prototype.updateParams = function(params) {\n+  goog.object.extend(this.params_, params);\n+  goog.object.extend(this.params_, params);","path":"src/ol/source/tilearcgissource.js","position":215,"original_position":215,"commit_id":"5966f70a7d5230f5edf7783271a5e0dac101fe7f","original_commit_id":"5966f70a7d5230f5edf7783271a5e0dac101fe7f","user":{"login":"ahocevar","id":211514,"avatar_url":"https://avatars.githubusercontent.com/u/211514?v=3","gravatar_id":"","url":"https://api.github.com/users/ahocevar","html_url":"https://github.com/ahocevar","followers_url":"https://api.github.com/users/ahocevar/followers","following_url":"https://api.github.com/users/ahocevar/following{/other_user}","gists_url":"https://api.github.com/users/ahocevar/gists{/gist_id}","starred_url":"https://api.github.com/users/ahocevar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ahocevar/subscriptions","organizations_url":"https://api.github.com/users/ahocevar/orgs","repos_url":"https://api.github.com/users/ahocevar/repos","events_url":"https://api.github.com/users/ahocevar/events{/privacy}","received_events_url":"https://api.github.com/users/ahocevar/received_events","type":"User","site_admin":false},"body":"Duplicate line. Remove one.","created_at":"2015-02-22T13:47:04Z","updated_at":"2015-02-22T13:47:04Z","html_url":"https://github.com/openlayers/ol3/pull/3263#discussion_r25132175","pull_request_url":"https://api.github.com/repos/openlayers/ol3/pulls/3263","_links":{"self":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/comments/25132175"},"html":{"href":"https://github.com/openlayers/ol3/pull/3263#discussion_r25132175"},"pull_request":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/3263"}}},"pull_request":{"url":"https://api.github.com/repos/openlayers/ol3/pulls/3263","id":29761573,"html_url":"https://github.com/openlayers/ol3/pull/3263","diff_url":"https://github.com/openlayers/ol3/pull/3263.diff","patch_url":"https://github.com/openlayers/ol3/pull/3263.patch","issue_url":"https://api.github.com/repos/openlayers/ol3/issues/3263","number":3263,"state":"open","locked":false,"title":"Support ArcGIS Rest Services","user":{"login":"cwgrant","id":10567775,"avatar_url":"https://avatars.githubusercontent.com/u/10567775?v=3","gravatar_id":"","url":"https://api.github.com/users/cwgrant","html_url":"https://github.com/cwgrant","followers_url":"https://api.github.com/users/cwgrant/followers","following_url":"https://api.github.com/users/cwgrant/following{/other_user}","gists_url":"https://api.github.com/users/cwgrant/gists{/gist_id}","starred_url":"https://api.github.com/users/cwgrant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cwgrant/subscriptions","organizations_url":"https://api.github.com/users/cwgrant/orgs","repos_url":"https://api.github.com/users/cwgrant/repos","events_url":"https://api.github.com/users/cwgrant/events{/privacy}","received_events_url":"https://api.github.com/users/cwgrant/received_events","type":"User","site_admin":false},"body":"This adds native support for ArcGIS Rest Layers to ol3.  Both MapServer and ImageServer services are supported - the ArcGIS Rest API is documented at http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Export_Map/02r3000000v7000000/.  \r\n\r\nImplementation wise, this is supported by adding a data source, TileArcGISRest, which is similar to the exiting WMS source.  ArcGIS support is loosely based on the ArcGIS93Rest layer available in OpenLayers 2.13.1.  Creating a tile layer using a TileArcGISRest is easy:\r\n\r\n```javascript\r\nvar layer = new ol.layer.Tile({\r\n  source: new ol.source.TileArcGISRest({\r\n    url: \"http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StateCityHighway_USA/MapServer\",\r\n  }),\r\n  opacity: .5  \r\n});\r\n```\r\nThis feature is discussed in #654. ","created_at":"2015-02-21T22:42:17Z","updated_at":"2015-02-22T13:47:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2b504fe4c2936d7a09cb656a5ffeb187740ab559","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/openlayers/ol3/pulls/3263/commits","review_comments_url":"https://api.github.com/repos/openlayers/ol3/pulls/3263/comments","review_comment_url":"https://api.github.com/repos/openlayers/ol3/pulls/comments/{number}","comments_url":"https://api.github.com/repos/openlayers/ol3/issues/3263/comments","statuses_url":"https://api.github.com/repos/openlayers/ol3/statuses/5966f70a7d5230f5edf7783271a5e0dac101fe7f","head":{"label":"cwgrant:master","ref":"master","sha":"5966f70a7d5230f5edf7783271a5e0dac101fe7f","user":{"login":"cwgrant","id":10567775,"avatar_url":"https://avatars.githubusercontent.com/u/10567775?v=3","gravatar_id":"","url":"https://api.github.com/users/cwgrant","html_url":"https://github.com/cwgrant","followers_url":"https://api.github.com/users/cwgrant/followers","following_url":"https://api.github.com/users/cwgrant/following{/other_user}","gists_url":"https://api.github.com/users/cwgrant/gists{/gist_id}","starred_url":"https://api.github.com/users/cwgrant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cwgrant/subscriptions","organizations_url":"https://api.github.com/users/cwgrant/orgs","repos_url":"https://api.github.com/users/cwgrant/repos","events_url":"https://api.github.com/users/cwgrant/events{/privacy}","received_events_url":"https://api.github.com/users/cwgrant/received_events","type":"User","site_admin":false},"repo":{"id":29793606,"name":"ol3","full_name":"cwgrant/ol3","owner":{"login":"cwgrant","id":10567775,"avatar_url":"https://avatars.githubusercontent.com/u/10567775?v=3","gravatar_id":"","url":"https://api.github.com/users/cwgrant","html_url":"https://github.com/cwgrant","followers_url":"https://api.github.com/users/cwgrant/followers","following_url":"https://api.github.com/users/cwgrant/following{/other_user}","gists_url":"https://api.github.com/users/cwgrant/gists{/gist_id}","starred_url":"https://api.github.com/users/cwgrant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cwgrant/subscriptions","organizations_url":"https://api.github.com/users/cwgrant/orgs","repos_url":"https://api.github.com/users/cwgrant/repos","events_url":"https://api.github.com/users/cwgrant/events{/privacy}","received_events_url":"https://api.github.com/users/cwgrant/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/cwgrant/ol3","description":"OpenLayers 3","fork":true,"url":"https://api.github.com/repos/cwgrant/ol3","forks_url":"https://api.github.com/repos/cwgrant/ol3/forks","keys_url":"https://api.github.com/repos/cwgrant/ol3/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cwgrant/ol3/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cwgrant/ol3/teams","hooks_url":"https://api.github.com/repos/cwgrant/ol3/hooks","issue_events_url":"https://api.github.com/repos/cwgrant/ol3/issues/events{/number}","events_url":"https://api.github.com/repos/cwgrant/ol3/events","assignees_url":"https://api.github.com/repos/cwgrant/ol3/assignees{/user}","branches_url":"https://api.github.com/repos/cwgrant/ol3/branches{/branch}","tags_url":"https://api.github.com/repos/cwgrant/ol3/tags","blobs_url":"https://api.github.com/repos/cwgrant/ol3/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cwgrant/ol3/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cwgrant/ol3/git/refs{/sha}","trees_url":"https://api.github.com/repos/cwgrant/ol3/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cwgrant/ol3/statuses/{sha}","languages_url":"https://api.github.com/repos/cwgrant/ol3/languages","stargazers_url":"https://api.github.com/repos/cwgrant/ol3/stargazers","contributors_url":"https://api.github.com/repos/cwgrant/ol3/contributors","subscribers_url":"https://api.github.com/repos/cwgrant/ol3/subscribers","subscription_url":"https://api.github.com/repos/cwgrant/ol3/subscription","commits_url":"https://api.github.com/repos/cwgrant/ol3/commits{/sha}","git_commits_url":"https://api.github.com/repos/cwgrant/ol3/git/commits{/sha}","comments_url":"https://api.github.com/repos/cwgrant/ol3/comments{/number}","issue_comment_url":"https://api.github.com/repos/cwgrant/ol3/issues/comments{/number}","contents_url":"https://api.github.com/repos/cwgrant/ol3/contents/{+path}","compare_url":"https://api.github.com/repos/cwgrant/ol3/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cwgrant/ol3/merges","archive_url":"https://api.github.com/repos/cwgrant/ol3/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cwgrant/ol3/downloads","issues_url":"https://api.github.com/repos/cwgrant/ol3/issues{/number}","pulls_url":"https://api.github.com/repos/cwgrant/ol3/pulls{/number}","milestones_url":"https://api.github.com/repos/cwgrant/ol3/milestones{/number}","notifications_url":"https://api.github.com/repos/cwgrant/ol3/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cwgrant/ol3/labels{/name}","releases_url":"https://api.github.com/repos/cwgrant/ol3/releases{/id}","created_at":"2015-01-24T22:13:58Z","updated_at":"2015-02-21T22:28:24Z","pushed_at":"2015-02-21T22:28:23Z","git_url":"git://github.com/cwgrant/ol3.git","ssh_url":"git@github.com:cwgrant/ol3.git","clone_url":"https://github.com/cwgrant/ol3.git","svn_url":"https://github.com/cwgrant/ol3","homepage":"http://openlayers.org","size":26686,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"openlayers:master","ref":"master","sha":"3fbc6fa361a442317b2d421c9970c4ef558900ef","user":{"login":"openlayers","id":240579,"avatar_url":"https://avatars.githubusercontent.com/u/240579?v=3","gravatar_id":"","url":"https://api.github.com/users/openlayers","html_url":"https://github.com/openlayers","followers_url":"https://api.github.com/users/openlayers/followers","following_url":"https://api.github.com/users/openlayers/following{/other_user}","gists_url":"https://api.github.com/users/openlayers/gists{/gist_id}","starred_url":"https://api.github.com/users/openlayers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openlayers/subscriptions","organizations_url":"https://api.github.com/users/openlayers/orgs","repos_url":"https://api.github.com/users/openlayers/repos","events_url":"https://api.github.com/users/openlayers/events{/privacy}","received_events_url":"https://api.github.com/users/openlayers/received_events","type":"Organization","site_admin":false},"repo":{"id":4723248,"name":"ol3","full_name":"openlayers/ol3","owner":{"login":"openlayers","id":240579,"avatar_url":"https://avatars.githubusercontent.com/u/240579?v=3","gravatar_id":"","url":"https://api.github.com/users/openlayers","html_url":"https://github.com/openlayers","followers_url":"https://api.github.com/users/openlayers/followers","following_url":"https://api.github.com/users/openlayers/following{/other_user}","gists_url":"https://api.github.com/users/openlayers/gists{/gist_id}","starred_url":"https://api.github.com/users/openlayers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openlayers/subscriptions","organizations_url":"https://api.github.com/users/openlayers/orgs","repos_url":"https://api.github.com/users/openlayers/repos","events_url":"https://api.github.com/users/openlayers/events{/privacy}","received_events_url":"https://api.github.com/users/openlayers/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/openlayers/ol3","description":"OpenLayers 3","fork":false,"url":"https://api.github.com/repos/openlayers/ol3","forks_url":"https://api.github.com/repos/openlayers/ol3/forks","keys_url":"https://api.github.com/repos/openlayers/ol3/keys{/key_id}","collaborators_url":"https://api.github.com/repos/openlayers/ol3/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/openlayers/ol3/teams","hooks_url":"https://api.github.com/repos/openlayers/ol3/hooks","issue_events_url":"https://api.github.com/repos/openlayers/ol3/issues/events{/number}","events_url":"https://api.github.com/repos/openlayers/ol3/events","assignees_url":"https://api.github.com/repos/openlayers/ol3/assignees{/user}","branches_url":"https://api.github.com/repos/openlayers/ol3/branches{/branch}","tags_url":"https://api.github.com/repos/openlayers/ol3/tags","blobs_url":"https://api.github.com/repos/openlayers/ol3/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/openlayers/ol3/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/openlayers/ol3/git/refs{/sha}","trees_url":"https://api.github.com/repos/openlayers/ol3/git/trees{/sha}","statuses_url":"https://api.github.com/repos/openlayers/ol3/statuses/{sha}","languages_url":"https://api.github.com/repos/openlayers/ol3/languages","stargazers_url":"https://api.github.com/repos/openlayers/ol3/stargazers","contributors_url":"https://api.github.com/repos/openlayers/ol3/contributors","subscribers_url":"https://api.github.com/repos/openlayers/ol3/subscribers","subscription_url":"https://api.github.com/repos/openlayers/ol3/subscription","commits_url":"https://api.github.com/repos/openlayers/ol3/commits{/sha}","git_commits_url":"https://api.github.com/repos/openlayers/ol3/git/commits{/sha}","comments_url":"https://api.github.com/repos/openlayers/ol3/comments{/number}","issue_comment_url":"https://api.github.com/repos/openlayers/ol3/issues/comments{/number}","contents_url":"https://api.github.com/repos/openlayers/ol3/contents/{+path}","compare_url":"https://api.github.com/repos/openlayers/ol3/compare/{base}...{head}","merges_url":"https://api.github.com/repos/openlayers/ol3/merges","archive_url":"https://api.github.com/repos/openlayers/ol3/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/openlayers/ol3/downloads","issues_url":"https://api.github.com/repos/openlayers/ol3/issues{/number}","pulls_url":"https://api.github.com/repos/openlayers/ol3/pulls{/number}","milestones_url":"https://api.github.com/repos/openlayers/ol3/milestones{/number}","notifications_url":"https://api.github.com/repos/openlayers/ol3/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/openlayers/ol3/labels{/name}","releases_url":"https://api.github.com/repos/openlayers/ol3/releases{/id}","created_at":"2012-06-20T06:53:59Z","updated_at":"2015-02-20T15:06:57Z","pushed_at":"2015-02-20T15:01:37Z","git_url":"git://github.com/openlayers/ol3.git","ssh_url":"git@github.com:openlayers/ol3.git","clone_url":"https://github.com/openlayers/ol3.git","svn_url":"https://github.com/openlayers/ol3","homepage":"http://openlayers.org","size":67251,"stargazers_count":969,"watchers_count":969,"language":"XML","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":577,"mirror_url":null,"open_issues_count":275,"forks":577,"open_issues":275,"watchers":969,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/3263"},"html":{"href":"https://github.com/openlayers/ol3/pull/3263"},"issue":{"href":"https://api.github.com/repos/openlayers/ol3/issues/3263"},"comments":{"href":"https://api.github.com/repos/openlayers/ol3/issues/3263/comments"},"review_comments":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/3263/comments"},"review_comment":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/openlayers/ol3/pulls/3263/commits"},"statuses":{"href":"https://api.github.com/repos/openlayers/ol3/statuses/5966f70a7d5230f5edf7783271a5e0dac101fe7f"}}}}