diff --git a/core/zoom_controls.js b/core/zoom_controls.js index 8d8b085d4..48eddb2ba 100644 --- a/core/zoom_controls.js +++ b/core/zoom_controls.js @@ -93,106 +93,16 @@ Blockly.ZoomControls.prototype.top_ = 0; * @return {!Element} The zoom controls SVG group. */ Blockly.ZoomControls.prototype.createDom = function() { - var workspace = this.workspace_; - /* Here's the markup that will be generated: - - - - - - - - - - - - - - - */ - this.svgGroup_ = Blockly.utils.createSvgElement('g', - {'class': 'blocklyZoom'}, null); - var clip; + this.svgGroup_ = + Blockly.utils.createSvgElement('g', {'class': 'blocklyZoom'}, null); + + // Each filter/pattern needs a unique ID for the case of multiple Blockly + // instances on a page. Browser behaviour becomes undefined otherwise. + // https://neil.fraser.name/news/2015/11/01/ var rnd = String(Math.random()).substring(2); - - clip = Blockly.utils.createSvgElement('clipPath', - {'id': 'blocklyZoomoutClipPath' + rnd}, - this.svgGroup_); - Blockly.utils.createSvgElement('rect', - {'width': 32, 'height': 32, 'y': 77}, - clip); - var zoomoutSvg = Blockly.utils.createSvgElement('image', - { - 'width': Blockly.SPRITE.width, - 'height': Blockly.SPRITE.height, 'x': -64, - 'y': -15, - 'clip-path': 'url(#blocklyZoomoutClipPath' + rnd + ')' - }, - this.svgGroup_); - zoomoutSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', - workspace.options.pathToMedia + Blockly.SPRITE.url); - - clip = Blockly.utils.createSvgElement('clipPath', - {'id': 'blocklyZoominClipPath' + rnd}, - this.svgGroup_); - Blockly.utils.createSvgElement('rect', - {'width': 32, 'height': 32, 'y': 43}, - clip); - var zoominSvg = Blockly.utils.createSvgElement('image', - { - 'width': Blockly.SPRITE.width, - 'height': Blockly.SPRITE.height, - 'x': -32, - 'y': -49, - 'clip-path': 'url(#blocklyZoominClipPath' + rnd + ')' - }, - this.svgGroup_); - zoominSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', - workspace.options.pathToMedia + Blockly.SPRITE.url); - - clip = Blockly.utils.createSvgElement('clipPath', - {'id': 'blocklyZoomresetClipPath' + rnd}, - this.svgGroup_); - Blockly.utils.createSvgElement('rect', - {'width': 32, 'height': 32}, - clip); - var zoomresetSvg = Blockly.utils.createSvgElement('image', - { - 'width': Blockly.SPRITE.width, - 'height': Blockly.SPRITE.height, 'y': -92, - 'clip-path': 'url(#blocklyZoomresetClipPath' + rnd + ')' - }, - this.svgGroup_); - zoomresetSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', - workspace.options.pathToMedia + Blockly.SPRITE.url); - - // Attach event listeners. - Blockly.bindEventWithChecks_(zoomresetSvg, 'mousedown', null, function(e) { - workspace.markFocused(); - workspace.setScale(workspace.options.zoomOptions.startScale); - workspace.scrollCenter(); - Blockly.Touch.clearTouchIdentifier(); // Don't block future drags. - e.stopPropagation(); // Don't start a workspace scroll. - e.preventDefault(); // Stop double-clicking from selecting text. - }); - Blockly.bindEventWithChecks_(zoominSvg, 'mousedown', null, function(e) { - workspace.markFocused(); - workspace.zoomCenter(1); - Blockly.Touch.clearTouchIdentifier(); // Don't block future drags. - e.stopPropagation(); // Don't start a workspace scroll. - e.preventDefault(); // Stop double-clicking from selecting text. - }); - Blockly.bindEventWithChecks_(zoomoutSvg, 'mousedown', null, function(e) { - workspace.markFocused(); - workspace.zoomCenter(-1); - Blockly.Touch.clearTouchIdentifier(); // Don't block future drags. - e.stopPropagation(); // Don't start a workspace scroll. - e.preventDefault(); // Stop double-clicking from selecting text. - }); - + this.createZoomOutSvg_(rnd); + this.createZoomInSvg_(rnd); + this.createZoomResetSvg_(rnd); return this.svgGroup_; }; @@ -251,3 +161,150 @@ Blockly.ZoomControls.prototype.position = function() { this.svgGroup_.setAttribute('transform', 'translate(' + this.left_ + ',' + this.top_ + ')'); }; + +/** + * Create the zoom in icon and its event handler. + * @param {string} rnd The random string to use as a suffix in the clip path's + * ID. These IDs must be unique in case there are multiple Blockly + * instances on the same page. + * @private + */ +Blockly.ZoomControls.prototype.createZoomOutSvg_ = function(rnd) { + /* This markup will be generated and added to the "blocklyZoom" group: + + + + + */ + var ws = this.workspace_; + var clip = Blockly.utils.createSvgElement('clipPath', + { + 'id': 'blocklyZoomoutClipPath' + rnd + }, + this.svgGroup_); + Blockly.utils.createSvgElement('rect', + { + 'width': 32, + 'height': 32, + 'y': 77 + }, + clip); + var zoomoutSvg = Blockly.utils.createSvgElement('image', + { + 'width': Blockly.SPRITE.width, + 'height': Blockly.SPRITE.height, 'x': -64, + 'y': -15, + 'clip-path': 'url(#blocklyZoomoutClipPath' + rnd + ')' + }, + this.svgGroup_); + zoomoutSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', + ws.options.pathToMedia + Blockly.SPRITE.url); + + // Attach listener. + Blockly.bindEventWithChecks_(zoomoutSvg, 'mousedown', null, function(e) { + ws.markFocused(); + ws.zoomCenter(-1); + Blockly.Touch.clearTouchIdentifier(); // Don't block future drags. + e.stopPropagation(); // Don't start a workspace scroll. + e.preventDefault(); // Stop double-clicking from selecting text. + }); +}; + +/** + * Create the zoom out icon and its event handler. + * @param {string} rnd The random string to use as a suffix in the clip path's + * ID. These IDs must be unique in case there are multiple Blockly + * instances on the same page. + * @private + */ +Blockly.ZoomControls.prototype.createZoomInSvg_ = function(rnd) { + /* This markup will be generated and added to the "blocklyZoom" group: + + + + + */ + var ws = this.workspace_; + var clip = Blockly.utils.createSvgElement('clipPath', + { + 'id': 'blocklyZoominClipPath' + rnd + }, + this.svgGroup_); + Blockly.utils.createSvgElement('rect', + { + 'width': 32, + 'height': 32, + 'y': 43 + }, + clip); + var zoominSvg = Blockly.utils.createSvgElement('image', + { + 'width': Blockly.SPRITE.width, + 'height': Blockly.SPRITE.height, + 'x': -32, + 'y': -49, + 'clip-path': 'url(#blocklyZoominClipPath' + rnd + ')' + }, + this.svgGroup_); + zoominSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', + ws.options.pathToMedia + Blockly.SPRITE.url); + + // Attach listener. + Blockly.bindEventWithChecks_(zoominSvg, 'mousedown', null, function(e) { + ws.markFocused(); + ws.zoomCenter(1); + Blockly.Touch.clearTouchIdentifier(); // Don't block future drags. + e.stopPropagation(); // Don't start a workspace scroll. + e.preventDefault(); // Stop double-clicking from selecting text. + }); +}; + +/** + * Create the zoom reset icon and its event handler. + * @param {string} rnd The random string to use as a suffix in the clip path's + * ID. These IDs must be unique in case there are multiple Blockly + * instances on the same page. + * @private + */ +Blockly.ZoomControls.prototype.createZoomResetSvg_ = function(rnd) { + /* This markup will be generated and added to the "blocklyZoom" group: + + + + + */ + var ws = this.workspace_; + var clip = Blockly.utils.createSvgElement('clipPath', + { + 'id': 'blocklyZoomresetClipPath' + rnd + }, + this.svgGroup_); + Blockly.utils.createSvgElement('rect', + { + 'width': 32, + 'height': 32 + }, + clip); + var zoomresetSvg = Blockly.utils.createSvgElement('image', + { + 'width': Blockly.SPRITE.width, + 'height': Blockly.SPRITE.height, 'y': -92, + 'clip-path': 'url(#blocklyZoomresetClipPath' + rnd + ')' + }, + this.svgGroup_); + zoomresetSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', + ws.options.pathToMedia + Blockly.SPRITE.url); + + // Attach event listeners. + Blockly.bindEventWithChecks_(zoomresetSvg, 'mousedown', null, function(e) { + ws.markFocused(); + ws.setScale(ws.options.zoomOptions.startScale); + ws.scrollCenter(); + Blockly.Touch.clearTouchIdentifier(); // Don't block future drags. + e.stopPropagation(); // Don't start a workspace scroll. + e.preventDefault(); // Stop double-clicking from selecting text. + }); +};