mirror of
https://github.com/google/blockly.git
synced 2026-01-09 10:00:09 +01:00
Merge pull request #301 from rachel-fenichel/cleanup/options
Move option parsing to its own file and decompose functions in inject.js
This commit is contained in:
279
core/inject.js
279
core/inject.js
@@ -27,6 +27,7 @@
|
||||
goog.provide('Blockly.inject');
|
||||
|
||||
goog.require('Blockly.Css');
|
||||
goog.require('Blockly.Options');
|
||||
goog.require('Blockly.WorkspaceSvg');
|
||||
goog.require('goog.dom');
|
||||
goog.require('goog.ui.Component');
|
||||
@@ -49,7 +50,7 @@ Blockly.inject = function(container, opt_options) {
|
||||
if (!goog.dom.contains(document, container)) {
|
||||
throw 'Error: container is not in current document.';
|
||||
}
|
||||
var options = Blockly.parseOptions_(opt_options || {});
|
||||
var options = new Blockly.Options(opt_options || {});
|
||||
var svg = Blockly.createDom_(container, options);
|
||||
var workspace = Blockly.createMainWorkspace_(svg, options);
|
||||
Blockly.init_(workspace);
|
||||
@@ -58,163 +59,10 @@ Blockly.inject = function(container, opt_options) {
|
||||
return workspace;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the provided toolbox tree into a consistent DOM format.
|
||||
* @param {Node|string} tree DOM tree of blocks, or text representation of same.
|
||||
* @return {Node} DOM tree of blocks, or null.
|
||||
* @private
|
||||
*/
|
||||
Blockly.parseToolboxTree_ = function(tree) {
|
||||
if (tree) {
|
||||
if (typeof tree != 'string') {
|
||||
if (typeof XSLTProcessor == 'undefined' && tree.outerHTML) {
|
||||
// In this case the tree will not have been properly built by the
|
||||
// browser. The HTML will be contained in the element, but it will
|
||||
// not have the proper DOM structure since the browser doesn't support
|
||||
// XSLTProcessor (XML -> HTML). This is the case in IE 9+.
|
||||
tree = tree.outerHTML;
|
||||
} else if (!(tree instanceof Element)) {
|
||||
tree = null;
|
||||
}
|
||||
}
|
||||
if (typeof tree == 'string') {
|
||||
tree = Blockly.Xml.textToDom(tree);
|
||||
}
|
||||
} else {
|
||||
tree = null;
|
||||
}
|
||||
return tree;
|
||||
};
|
||||
|
||||
/**
|
||||
* Configure Blockly to behave according to a set of options.
|
||||
* @param {!Object} options Dictionary of options. Specification:
|
||||
* https://developers.google.com/blockly/installation/overview#configuration
|
||||
* @return {!Object} Dictionary of normalized options.
|
||||
* @private
|
||||
*/
|
||||
Blockly.parseOptions_ = function(options) {
|
||||
var readOnly = !!options['readOnly'];
|
||||
if (readOnly) {
|
||||
var languageTree = null;
|
||||
var hasCategories = false;
|
||||
var hasTrashcan = false;
|
||||
var hasCollapse = false;
|
||||
var hasComments = false;
|
||||
var hasDisable = false;
|
||||
var hasSounds = false;
|
||||
} else {
|
||||
var languageTree = Blockly.parseToolboxTree_(options['toolbox']);
|
||||
var hasCategories = Boolean(languageTree &&
|
||||
languageTree.getElementsByTagName('category').length);
|
||||
var hasTrashcan = options['trashcan'];
|
||||
if (hasTrashcan === undefined) {
|
||||
hasTrashcan = hasCategories;
|
||||
}
|
||||
var hasCollapse = options['collapse'];
|
||||
if (hasCollapse === undefined) {
|
||||
hasCollapse = hasCategories;
|
||||
}
|
||||
var hasComments = options['comments'];
|
||||
if (hasComments === undefined) {
|
||||
hasComments = hasCategories;
|
||||
}
|
||||
var hasDisable = options['disable'];
|
||||
if (hasDisable === undefined) {
|
||||
hasDisable = hasCategories;
|
||||
}
|
||||
var hasSounds = options['sounds'];
|
||||
if (hasSounds === undefined) {
|
||||
hasSounds = true;
|
||||
}
|
||||
}
|
||||
var hasScrollbars = options['scrollbars'];
|
||||
if (hasScrollbars === undefined) {
|
||||
hasScrollbars = hasCategories;
|
||||
}
|
||||
var hasCss = options['css'];
|
||||
if (hasCss === undefined) {
|
||||
hasCss = true;
|
||||
}
|
||||
// See grid documentation at:
|
||||
// https://developers.google.com/blockly/installation/grid
|
||||
var grid = options['grid'] || {};
|
||||
var gridOptions = {};
|
||||
gridOptions.spacing = parseFloat(grid['spacing']) || 0;
|
||||
gridOptions.colour = grid['colour'] || '#888';
|
||||
gridOptions.length = parseFloat(grid['length']) || 1;
|
||||
gridOptions.snap = gridOptions.spacing > 0 && !!grid['snap'];
|
||||
var pathToMedia = 'https://blockly-demo.appspot.com/static/media/';
|
||||
if (options['media']) {
|
||||
pathToMedia = options['media'];
|
||||
} else if (options['path']) {
|
||||
// 'path' is a deprecated option which has been replaced by 'media'.
|
||||
pathToMedia = options['path'] + 'media/';
|
||||
}
|
||||
|
||||
// See zoom documentation at:
|
||||
// https://developers.google.com/blockly/installation/zoom
|
||||
var zoom = options['zoom'] || {};
|
||||
var zoomOptions = {};
|
||||
if (zoom['controls'] === undefined) {
|
||||
zoomOptions.controls = false;
|
||||
} else {
|
||||
zoomOptions.controls = !!zoom['controls'];
|
||||
}
|
||||
if (zoom['wheel'] === undefined) {
|
||||
zoomOptions.wheel = false;
|
||||
} else {
|
||||
zoomOptions.wheel = !!zoom['wheel'];
|
||||
}
|
||||
if (zoom['startScale'] === undefined) {
|
||||
zoomOptions.startScale = 1;
|
||||
} else {
|
||||
zoomOptions.startScale = parseFloat(zoom['startScale']);
|
||||
}
|
||||
if (zoom['maxScale'] === undefined) {
|
||||
zoomOptions.maxScale = 3;
|
||||
} else {
|
||||
zoomOptions.maxScale = parseFloat(zoom['maxScale']);
|
||||
}
|
||||
if (zoom['minScale'] === undefined) {
|
||||
zoomOptions.minScale = 0.3;
|
||||
} else {
|
||||
zoomOptions.minScale = parseFloat(zoom['minScale']);
|
||||
}
|
||||
if (zoom['scaleSpeed'] === undefined) {
|
||||
zoomOptions.scaleSpeed = 1.2;
|
||||
} else {
|
||||
zoomOptions.scaleSpeed = parseFloat(zoom['scaleSpeed']);
|
||||
}
|
||||
|
||||
var enableRealtime = !!options['realtime'];
|
||||
var realtimeOptions = enableRealtime ? options['realtimeOptions'] : undefined;
|
||||
|
||||
return {
|
||||
RTL: !!options['rtl'],
|
||||
collapse: hasCollapse,
|
||||
comments: hasComments,
|
||||
disable: hasDisable,
|
||||
readOnly: readOnly,
|
||||
maxBlocks: options['maxBlocks'] || Infinity,
|
||||
pathToMedia: pathToMedia,
|
||||
hasCategories: hasCategories,
|
||||
hasScrollbars: hasScrollbars,
|
||||
hasTrashcan: hasTrashcan,
|
||||
hasSounds: hasSounds,
|
||||
hasCss: hasCss,
|
||||
languageTree: languageTree,
|
||||
gridOptions: gridOptions,
|
||||
zoomOptions: zoomOptions,
|
||||
enableRealtime: enableRealtime,
|
||||
realtimeOptions: realtimeOptions
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the SVG image.
|
||||
* @param {!Element} container Containing element.
|
||||
* @param {Object} options Dictionary of options.
|
||||
* @param {!Blockly.Options} options Dictionary of options.
|
||||
* @return {!Element} Newly created SVG image.
|
||||
* @private
|
||||
*/
|
||||
@@ -328,7 +176,7 @@ Blockly.createDom_ = function(container, options) {
|
||||
/**
|
||||
* Create a main workspace and add it to the SVG.
|
||||
* @param {!Element} svg SVG element with pattern defined.
|
||||
* @param {Object} options Dictionary of options.
|
||||
* @param {!Blockly.Options} options Dictionary of options.
|
||||
* @return {!Blockly.Workspace} Newly created main workspace.
|
||||
* @private
|
||||
*/
|
||||
@@ -405,6 +253,7 @@ Blockly.createMainWorkspace_ = function(svg, options) {
|
||||
Blockly.init_ = function(mainWorkspace) {
|
||||
var options = mainWorkspace.options;
|
||||
var svg = mainWorkspace.getParentSvg();
|
||||
|
||||
// Supress the browser's context menu.
|
||||
Blockly.bindEvent_(svg, 'contextmenu', null,
|
||||
function(e) {
|
||||
@@ -412,34 +261,11 @@ Blockly.init_ = function(mainWorkspace) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
// Bind events for scrolling the workspace.
|
||||
// Most of these events should be bound to the SVG's surface.
|
||||
// However, 'mouseup' has to be on the whole document so that a block dragged
|
||||
// out of bounds and released will know that it has been released.
|
||||
// Also, 'keydown' has to be on the whole document since the browser doesn't
|
||||
// understand a concept of focus on the SVG image.
|
||||
|
||||
Blockly.bindEvent_(window, 'resize', null,
|
||||
function() {Blockly.svgResize(mainWorkspace);});
|
||||
|
||||
if (!Blockly.documentEventsBound_) {
|
||||
// Only bind the window/document events once.
|
||||
// Destroying and reinjecting Blockly should not bind again.
|
||||
Blockly.bindEvent_(document, 'keydown', null, Blockly.onKeyDown_);
|
||||
Blockly.bindEvent_(document, 'touchend', null, Blockly.longStop_);
|
||||
Blockly.bindEvent_(document, 'touchcancel', null, Blockly.longStop_);
|
||||
// Don't use bindEvent_ for document's mouseup since that would create a
|
||||
// corresponding touch handler that would squeltch the ability to interact
|
||||
// with non-Blockly elements.
|
||||
document.addEventListener('mouseup', Blockly.onMouseUp_, false);
|
||||
// Some iPad versions don't fire resize after portrait to landscape change.
|
||||
if (goog.userAgent.IPAD) {
|
||||
Blockly.bindEvent_(window, 'orientationchange', document, function() {
|
||||
Blockly.fireUiEvent(window, 'resize');
|
||||
});
|
||||
}
|
||||
Blockly.documentEventsBound_ = true;
|
||||
}
|
||||
Blockly.inject.bindDocumentEvents_();
|
||||
|
||||
if (options.languageTree) {
|
||||
if (mainWorkspace.toolbox_) {
|
||||
@@ -456,6 +282,7 @@ Blockly.init_ = function(mainWorkspace) {
|
||||
mainWorkspace.translate(mainWorkspace.scrollX, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (options.hasScrollbars) {
|
||||
mainWorkspace.scrollbar = new Blockly.ScrollbarPair(mainWorkspace);
|
||||
mainWorkspace.scrollbar.resize();
|
||||
@@ -463,35 +290,75 @@ Blockly.init_ = function(mainWorkspace) {
|
||||
|
||||
// Load the sounds.
|
||||
if (options.hasSounds) {
|
||||
mainWorkspace.loadAudio_(
|
||||
[options.pathToMedia + 'click.mp3',
|
||||
options.pathToMedia + 'click.wav',
|
||||
options.pathToMedia + 'click.ogg'], 'click');
|
||||
mainWorkspace.loadAudio_(
|
||||
[options.pathToMedia + 'disconnect.wav',
|
||||
options.pathToMedia + 'disconnect.mp3',
|
||||
options.pathToMedia + 'disconnect.ogg'], 'disconnect');
|
||||
mainWorkspace.loadAudio_(
|
||||
[options.pathToMedia + 'delete.mp3',
|
||||
options.pathToMedia + 'delete.ogg',
|
||||
options.pathToMedia + 'delete.wav'], 'delete');
|
||||
|
||||
// Bind temporary hooks that preload the sounds.
|
||||
var soundBinds = [];
|
||||
var unbindSounds = function() {
|
||||
while (soundBinds.length) {
|
||||
Blockly.unbindEvent_(soundBinds.pop());
|
||||
}
|
||||
mainWorkspace.preloadAudio_();
|
||||
};
|
||||
// Android ignores any sound not loaded as a result of a user action.
|
||||
soundBinds.push(
|
||||
Blockly.bindEvent_(document, 'mousemove', null, unbindSounds));
|
||||
soundBinds.push(
|
||||
Blockly.bindEvent_(document, 'touchstart', null, unbindSounds));
|
||||
Blockly.inject.loadSounds_(options.pathToMedia, mainWorkspace);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Bind document events, but only once. Destroying and reinjecting Blockly
|
||||
* should not bind again.
|
||||
* Bind events for scrolling the workspace.
|
||||
* Most of these events should be bound to the SVG's surface.
|
||||
* However, 'mouseup' has to be on the whole document so that a block dragged
|
||||
* out of bounds and released will know that it has been released.
|
||||
* Also, 'keydown' has to be on the whole document since the browser doesn't
|
||||
* understand a concept of focus on the SVG image.
|
||||
* @private
|
||||
*/
|
||||
Blockly.inject.bindDocumentEvents_ = function() {
|
||||
if (!Blockly.documentEventsBound_) {
|
||||
Blockly.bindEvent_(document, 'keydown', null, Blockly.onKeyDown_);
|
||||
Blockly.bindEvent_(document, 'touchend', null, Blockly.longStop_);
|
||||
Blockly.bindEvent_(document, 'touchcancel', null, Blockly.longStop_);
|
||||
// Don't use bindEvent_ for document's mouseup since that would create a
|
||||
// corresponding touch handler that would squeltch the ability to interact
|
||||
// with non-Blockly elements.
|
||||
document.addEventListener('mouseup', Blockly.onMouseUp_, false);
|
||||
// Some iPad versions don't fire resize after portrait to landscape change.
|
||||
if (goog.userAgent.IPAD) {
|
||||
Blockly.bindEvent_(window, 'orientationchange', document, function() {
|
||||
Blockly.fireUiEvent(window, 'resize');
|
||||
});
|
||||
}
|
||||
}
|
||||
Blockly.documentEventsBound_ = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Load sounds for the given workspace.
|
||||
* @param options {string} The path to the media directory.
|
||||
* @param workspace {!Blockly.Workspace} The workspace to load sounds for.
|
||||
* @private
|
||||
*/
|
||||
Blockly.inject.loadSounds_ = function(pathToMedia, workspace) {
|
||||
workspace.loadAudio_(
|
||||
[pathToMedia + 'click.mp3',
|
||||
pathToMedia + 'click.wav',
|
||||
pathToMedia + 'click.ogg'], 'click');
|
||||
workspace.loadAudio_(
|
||||
[pathToMedia + 'disconnect.wav',
|
||||
pathToMedia + 'disconnect.mp3',
|
||||
pathToMedia + 'disconnect.ogg'], 'disconnect');
|
||||
workspace.loadAudio_(
|
||||
[pathToMedia + 'delete.mp3',
|
||||
pathToMedia + 'delete.ogg',
|
||||
pathToMedia + 'delete.wav'], 'delete');
|
||||
|
||||
// Bind temporary hooks that preload the sounds.
|
||||
var soundBinds = [];
|
||||
var unbindSounds = function() {
|
||||
while (soundBinds.length) {
|
||||
Blockly.unbindEvent_(soundBinds.pop());
|
||||
}
|
||||
workspace.preloadAudio_();
|
||||
};
|
||||
// Android ignores any sound not loaded as a result of a user action.
|
||||
soundBinds.push(
|
||||
Blockly.bindEvent_(document, 'mousemove', null, unbindSounds));
|
||||
soundBinds.push(
|
||||
Blockly.bindEvent_(document, 'touchstart', null, unbindSounds));
|
||||
};
|
||||
|
||||
/**
|
||||
* Modify the block tree on the existing toolbox.
|
||||
* @param {Node|string} tree DOM tree of blocks, or text representation of same.
|
||||
|
||||
217
core/options.js
Normal file
217
core/options.js
Normal file
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2016 Google Inc.
|
||||
* https://developers.google.com/blockly/
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Object that controls settings for the workspace.
|
||||
* @author fenichel@google.com (Rachel Fenichel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.Options');
|
||||
|
||||
|
||||
/**
|
||||
* Parse the user-specified options, using reasonable defaults where behaviour
|
||||
* is unspecified.
|
||||
* @param {!Object} options Dictionary of options. Specification:
|
||||
* https://developers.google.com/blockly/installation/overview#configuration
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Options = function(options) {
|
||||
var readOnly = !!options['readOnly'];
|
||||
if (readOnly) {
|
||||
var languageTree = null;
|
||||
var hasCategories = false;
|
||||
var hasTrashcan = false;
|
||||
var hasCollapse = false;
|
||||
var hasComments = false;
|
||||
var hasDisable = false;
|
||||
var hasSounds = false;
|
||||
} else {
|
||||
var languageTree = Blockly.Options.parseToolboxTree_(options['toolbox']);
|
||||
var hasCategories = Boolean(languageTree &&
|
||||
languageTree.getElementsByTagName('category').length);
|
||||
var hasTrashcan = options['trashcan'];
|
||||
if (hasTrashcan === undefined) {
|
||||
hasTrashcan = hasCategories;
|
||||
}
|
||||
var hasCollapse = options['collapse'];
|
||||
if (hasCollapse === undefined) {
|
||||
hasCollapse = hasCategories;
|
||||
}
|
||||
var hasComments = options['comments'];
|
||||
if (hasComments === undefined) {
|
||||
hasComments = hasCategories;
|
||||
}
|
||||
var hasDisable = options['disable'];
|
||||
if (hasDisable === undefined) {
|
||||
hasDisable = hasCategories;
|
||||
}
|
||||
var hasSounds = options['sounds'];
|
||||
if (hasSounds === undefined) {
|
||||
hasSounds = true;
|
||||
}
|
||||
}
|
||||
var hasScrollbars = options['scrollbars'];
|
||||
if (hasScrollbars === undefined) {
|
||||
hasScrollbars = hasCategories;
|
||||
}
|
||||
var hasCss = options['css'];
|
||||
if (hasCss === undefined) {
|
||||
hasCss = true;
|
||||
}
|
||||
var pathToMedia = 'https://blockly-demo.appspot.com/static/media/';
|
||||
if (options['media']) {
|
||||
pathToMedia = options['media'];
|
||||
} else if (options['path']) {
|
||||
// 'path' is a deprecated option which has been replaced by 'media'.
|
||||
pathToMedia = options['path'] + 'media/';
|
||||
}
|
||||
|
||||
var enableRealtime = !!options['realtime'];
|
||||
var realtimeOptions = enableRealtime ? options['realtimeOptions'] : undefined;
|
||||
|
||||
this.RTL = !!options['rtl'];
|
||||
this.collapse = hasCollapse;
|
||||
this.comments = hasComments;
|
||||
this.disable = hasDisable;
|
||||
this.readOnly = readOnly;
|
||||
this.maxBlocks = options['maxBlocks'] || Infinity;
|
||||
this.pathToMedia = pathToMedia;
|
||||
this.hasCategories = hasCategories;
|
||||
this.hasScrollbars = hasScrollbars;
|
||||
this.hasTrashcan = hasTrashcan;
|
||||
this.hasSounds = hasSounds;
|
||||
this.hasCss = hasCss;
|
||||
this.languageTree = languageTree;
|
||||
this.gridOptions = Blockly.Options.parseGridOptions_(options);
|
||||
this.zoomOptions = Blockly.Options.parseZoomOptions_(options);
|
||||
this.enableRealtime = enableRealtime;
|
||||
this.realtimeOptions = realtimeOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Blockly.Workspace} the parent of the current workspace, or null if
|
||||
* there is no parent workspace.
|
||||
**/
|
||||
Blockly.Options.prototype.parentWorkspace = null;
|
||||
|
||||
/**
|
||||
* If set, sets the translation of the workspace to match the scrollbars.
|
||||
* No-op if unset.
|
||||
*/
|
||||
Blockly.Options.prototype.setMetrics = function(translation) { return; };
|
||||
|
||||
/**
|
||||
* Return an object with the metrics required to size the workspace, or null
|
||||
* if unset.
|
||||
* @return {Object} Contains size an position metrics, or null.
|
||||
*/
|
||||
Blockly.Options.prototype.getMetrics = function() { return null; };
|
||||
|
||||
/**
|
||||
* Parse the user-specified zoom options, using reasonable defaults where
|
||||
* behaviour is unspecified. See zoom documentation:
|
||||
* https://developers.google.com/blockly/installation/zoom
|
||||
* @param {!Object} options Dictionary of options.
|
||||
* @return {!Object} A dictionary of normalized options.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Options.parseZoomOptions_ = function(options) {
|
||||
var zoom = options['zoom'] || {};
|
||||
var zoomOptions = {};
|
||||
if (zoom['controls'] === undefined) {
|
||||
zoomOptions.controls = false;
|
||||
} else {
|
||||
zoomOptions.controls = !!zoom['controls'];
|
||||
}
|
||||
if (zoom['wheel'] === undefined) {
|
||||
zoomOptions.wheel = false;
|
||||
} else {
|
||||
zoomOptions.wheel = !!zoom['wheel'];
|
||||
}
|
||||
if (zoom['startScale'] === undefined) {
|
||||
zoomOptions.startScale = 1;
|
||||
} else {
|
||||
zoomOptions.startScale = parseFloat(zoom['startScale']);
|
||||
}
|
||||
if (zoom['maxScale'] === undefined) {
|
||||
zoomOptions.maxScale = 3;
|
||||
} else {
|
||||
zoomOptions.maxScale = parseFloat(zoom['maxScale']);
|
||||
}
|
||||
if (zoom['minScale'] === undefined) {
|
||||
zoomOptions.minScale = 0.3;
|
||||
} else {
|
||||
zoomOptions.minScale = parseFloat(zoom['minScale']);
|
||||
}
|
||||
if (zoom['scaleSpeed'] === undefined) {
|
||||
zoomOptions.scaleSpeed = 1.2;
|
||||
} else {
|
||||
zoomOptions.scaleSpeed = parseFloat(zoom['scaleSpeed']);
|
||||
}
|
||||
return zoomOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the user-specified grid options, using reasonable defaults where
|
||||
* behaviour is unspecified. See grid documentation:
|
||||
* https://developers.google.com/blockly/installation/grid
|
||||
* @param {!Object} options Dictionary of options.
|
||||
* @return {!Object} A dictionary of normalized options.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Options.parseGridOptions_ = function(options) {
|
||||
var grid = options['grid'] || {};
|
||||
var gridOptions = {};
|
||||
gridOptions.spacing = parseFloat(grid['spacing']) || 0;
|
||||
gridOptions.colour = grid['colour'] || '#888';
|
||||
gridOptions.length = parseFloat(grid['length']) || 1;
|
||||
gridOptions.snap = gridOptions.spacing > 0 && !!grid['snap'];
|
||||
return gridOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the provided toolbox tree into a consistent DOM format.
|
||||
* @param {Node|string} tree DOM tree of blocks, or text representation of same.
|
||||
* @return {Node} DOM tree of blocks, or null.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Options.parseToolboxTree_ = function(tree) {
|
||||
if (tree) {
|
||||
if (typeof tree != 'string') {
|
||||
if (typeof XSLTProcessor == 'undefined' && tree.outerHTML) {
|
||||
// In this case the tree will not have been properly built by the
|
||||
// browser. The HTML will be contained in the element, but it will
|
||||
// not have the proper DOM structure since the browser doesn't support
|
||||
// XSLTProcessor (XML -> HTML). This is the case in IE 9+.
|
||||
tree = tree.outerHTML;
|
||||
} else if (!(tree instanceof Element)) {
|
||||
tree = null;
|
||||
}
|
||||
}
|
||||
if (typeof tree == 'string') {
|
||||
tree = Blockly.Xml.textToDom(tree);
|
||||
}
|
||||
} else {
|
||||
tree = null;
|
||||
}
|
||||
return tree;
|
||||
};
|
||||
@@ -32,14 +32,14 @@ goog.require('goog.math');
|
||||
/**
|
||||
* Class for a workspace. This is a data structure that contains blocks.
|
||||
* There is no UI, and can be created headlessly.
|
||||
* @param {Object=} opt_options Dictionary of options.
|
||||
* @param {Blockly.Options} opt_options Dictionary of options.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.Workspace = function(opt_options) {
|
||||
/** @type {string} */
|
||||
this.id = Blockly.genUid();
|
||||
Blockly.Workspace.WorkspaceDB_[this.id] = this;
|
||||
/** @type {!Object} */
|
||||
/** @type {!Blockly.Options} */
|
||||
this.options = opt_options || {};
|
||||
/** @type {boolean} */
|
||||
this.RTL = !!this.options.RTL;
|
||||
|
||||
@@ -43,7 +43,7 @@ goog.require('goog.userAgent');
|
||||
/**
|
||||
* Class for a workspace. This is an onscreen area with optional trashcan,
|
||||
* scrollbars, bubbles, and dragging.
|
||||
* @param {!Object} options Dictionary of options.
|
||||
* @param {!Blockly.Options} options Dictionary of options.
|
||||
* @extends {Blockly.Workspace}
|
||||
* @constructor
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user