Move Block Factory from apps to demos. Add icons to demos.

This commit is contained in:
Neil Fraser
2014-10-16 16:58:32 -07:00
parent 6748e43d30
commit 6909e38fc8
243 changed files with 213 additions and 6344 deletions

View File

@@ -0,0 +1,688 @@
/**
* Blockly Apps: Block Factory Blocks
*
* Copyright 2012 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 Blocks for Blockly's Block Factory application.
* @author fraser@google.com (Neil Fraser)
*/
'use strict';
Blockly.Blocks['factory_base'] = {
// Base of new block.
init: function() {
this.setColour(120);
this.appendDummyInput()
.appendField('name')
.appendField(new Blockly.FieldTextInput('math_foo'), 'NAME');
this.appendStatementInput('INPUTS')
.setCheck('Input')
.appendField('inputs');
var dropdown = new Blockly.FieldDropdown([
['external inputs', 'EXT'],
['inline inputs', 'INT']]);
this.appendDummyInput()
.appendField(dropdown, 'INLINE');
dropdown = new Blockly.FieldDropdown([
['no connections', 'NONE'],
['← left output', 'LEFT'],
['↕ top+bottom connections', 'BOTH'],
['↑ top connection', 'TOP'],
['↓ bottom connection', 'BOTTOM']],
function(option) {
var block = this.sourceBlock_;
var outputExists = block.getInput('OUTPUTTYPE');
var topExists = block.getInput('TOPTYPE');
var bottomExists = block.getInput('BOTTOMTYPE');
if (option == 'LEFT') {
if (!outputExists) {
block.appendValueInput('OUTPUTTYPE')
.setCheck('Type')
.appendField('output type');
block.moveInputBefore('OUTPUTTYPE', 'COLOUR');
}
} else if (outputExists) {
block.removeInput('OUTPUTTYPE');
}
if (option == 'TOP' || option == 'BOTH') {
if (!topExists) {
block.appendValueInput('TOPTYPE')
.setCheck('Type')
.appendField('top type');
block.moveInputBefore('TOPTYPE', 'COLOUR');
}
} else if (topExists) {
block.removeInput('TOPTYPE');
}
if (option == 'BOTTOM' || option == 'BOTH') {
if (!bottomExists) {
block.appendValueInput('BOTTOMTYPE')
.setCheck('Type')
.appendField('bottom type');
block.moveInputBefore('BOTTOMTYPE', 'COLOUR');
}
} else if (bottomExists) {
block.removeInput('BOTTOMTYPE');
}
});
this.appendDummyInput()
.appendField(dropdown, 'CONNECTIONS');
this.appendValueInput('COLOUR')
.setCheck('Colour')
.appendField('colour');
/*
this.appendValueInput('TOOLTIP')
.setCheck('String')
.appendField('tooltip');
this.appendValueInput('HELP')
.setCheck('String')
.appendField('help url');
*/
this.setTooltip('Build a custom block by plugging\n' +
'fields, inputs and other blocks here.');
}
};
var ALIGNMENT_OPTIONS =
[['left', 'LEFT'], ['right', 'RIGHT'], ['centre', 'CENTRE']];
Blockly.Blocks['input_value'] = {
// Value input.
init: function() {
this.setColour(210);
this.appendDummyInput()
.appendField('value input')
.appendField(new Blockly.FieldTextInput('NAME'), 'INPUTNAME');
this.appendStatementInput('FIELDS')
.setCheck('Field')
.appendField('fields')
.appendField(new Blockly.FieldDropdown(ALIGNMENT_OPTIONS), 'ALIGN');
this.appendValueInput('TYPE')
.setCheck('Type')
.setAlign(Blockly.ALIGN_RIGHT)
.appendField('type');
this.setPreviousStatement(true, 'Input');
this.setNextStatement(true, 'Input');
this.setTooltip('A value socket for horizontal connections.');
},
onchange: function() {
if (!this.workspace) {
// Block has been deleted.
return;
}
inputNameCheck(this);
}
};
Blockly.Blocks['input_statement'] = {
// Statement input.
init: function() {
this.setColour(210);
this.appendDummyInput()
.appendField('statement input')
.appendField(new Blockly.FieldTextInput('NAME'), 'INPUTNAME');
this.appendStatementInput('FIELDS')
.setCheck('Field')
.appendField('fields')
.appendField(new Blockly.FieldDropdown(ALIGNMENT_OPTIONS), 'ALIGN');
this.appendValueInput('TYPE')
.setCheck('Type')
.setAlign(Blockly.ALIGN_RIGHT)
.appendField('type');
this.setPreviousStatement(true, 'Input');
this.setNextStatement(true, 'Input');
this.setTooltip('A statement socket for enclosed vertical stacks.');
},
onchange: function() {
if (!this.workspace) {
// Block has been deleted.
return;
}
inputNameCheck(this);
}
};
Blockly.Blocks['input_dummy'] = {
// Dummy input.
init: function() {
this.setColour(210);
this.appendDummyInput()
.appendField('dummy input');
this.appendStatementInput('FIELDS')
.setCheck('Field')
.appendField('fields')
.appendField(new Blockly.FieldDropdown(ALIGNMENT_OPTIONS), 'ALIGN');
this.setPreviousStatement(true, 'Input');
this.setNextStatement(true, 'Input');
this.setTooltip('For adding fields on a separate\n' +
'row with no connections.\n' +
'Alignment options (left, right, centre)\n' +
'apply only to multi-line fields.');
}
};
Blockly.Blocks['field_static'] = {
// Text value.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendField('text')
.appendField(new Blockly.FieldTextInput(''), 'TEXT');
this.setPreviousStatement(true, 'Field');
this.setNextStatement(true, 'Field');
this.setTooltip('Static text that serves as a label.');
}
};
Blockly.Blocks['field_input'] = {
// Text input.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendField('text input')
.appendField(new Blockly.FieldTextInput('default'), 'TEXT')
.appendField(',')
.appendField(new Blockly.FieldTextInput('NAME'), 'FIELDNAME');
this.setPreviousStatement(true, 'Field');
this.setNextStatement(true, 'Field');
this.setTooltip('An input field for the user to enter text.');
},
onchange: function() {
if (!this.workspace) {
// Block has been deleted.
return;
}
fieldNameCheck(this);
}
};
Blockly.Blocks['field_angle'] = {
// Angle input.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendField('angle input')
.appendField(new Blockly.FieldAngle('90'), 'ANGLE')
.appendField(',')
.appendField(new Blockly.FieldTextInput('NAME'), 'FIELDNAME');
this.setPreviousStatement(true, 'Field');
this.setNextStatement(true, 'Field');
this.setTooltip('An input field for the user to enter an angle.');
},
onchange: function() {
if (!this.workspace) {
// Block has been deleted.
return;
}
fieldNameCheck(this);
}
};
Blockly.Blocks['field_dropdown'] = {
// Dropdown menu.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendField('dropdown')
.appendField(new Blockly.FieldTextInput('NAME'), 'FIELDNAME');
this.appendDummyInput('OPTION0')
.appendField(new Blockly.FieldTextInput('option'), 'USER0')
.appendField(',')
.appendField(new Blockly.FieldTextInput('OPTIONNAME'), 'CPU0');
this.appendDummyInput('OPTION1')
.appendField(new Blockly.FieldTextInput('option'), 'USER1')
.appendField(',')
.appendField(new Blockly.FieldTextInput('OPTIONNAME'), 'CPU1');
this.appendDummyInput('OPTION2')
.appendField(new Blockly.FieldTextInput('option'), 'USER2')
.appendField(',')
.appendField(new Blockly.FieldTextInput('OPTIONNAME'), 'CPU2');
this.setPreviousStatement(true, 'Field');
this.setNextStatement(true, 'Field');
this.setMutator(new Blockly.Mutator(['field_dropdown_option']));
this.setTooltip('Dropdown menu with a list of options.');
this.optionCount_ = 3;
},
mutationToDom: function(workspace) {
var container = document.createElement('mutation');
container.setAttribute('options', this.optionCount_);
return container;
},
domToMutation: function(container) {
for (var x = 0; x < this.optionCount_; x++) {
this.removeInput('OPTION' + x);
}
this.optionCount_ = parseInt(container.getAttribute('options'), 10);
for (var x = 0; x < this.optionCount_; x++) {
var input = this.appendDummyInput('OPTION' + x);
input.appendField(new Blockly.FieldTextInput('option'), 'USER' + x);
input.appendField(',');
input.appendField(new Blockly.FieldTextInput('OPTIONNAME'), 'CPU' + x);
}
},
decompose: function(workspace) {
var containerBlock =
Blockly.Block.obtain(workspace, 'field_dropdown_container');
containerBlock.initSvg();
var connection = containerBlock.getInput('STACK').connection;
for (var x = 0; x < this.optionCount_; x++) {
var optionBlock =
Blockly.Block.obtain(workspace, 'field_dropdown_option');
optionBlock.initSvg();
connection.connect(optionBlock.previousConnection);
connection = optionBlock.nextConnection;
}
return containerBlock;
},
compose: function(containerBlock) {
// Disconnect all input blocks and remove all inputs.
for (var x = this.optionCount_ - 1; x >= 0; x--) {
this.removeInput('OPTION' + x);
}
this.optionCount_ = 0;
// Rebuild the block's inputs.
var optionBlock = containerBlock.getInputTargetBlock('STACK');
while (optionBlock) {
this.appendDummyInput('OPTION' + this.optionCount_)
.appendField(new Blockly.FieldTextInput(
optionBlock.userData_ || 'option'), 'USER' + this.optionCount_)
.appendField(',')
.appendField(new Blockly.FieldTextInput(
optionBlock.cpuData_ || 'OPTIONNAME'), 'CPU' + this.optionCount_);
this.optionCount_++;
optionBlock = optionBlock.nextConnection &&
optionBlock.nextConnection.targetBlock();
}
},
saveConnections: function(containerBlock) {
// Store names and values for each option.
var optionBlock = containerBlock.getInputTargetBlock('STACK');
var x = 0;
while (optionBlock) {
optionBlock.userData_ = this.getFieldValue('USER' + x);
optionBlock.cpuData_ = this.getFieldValue('CPU' + x);
x++;
optionBlock = optionBlock.nextConnection &&
optionBlock.nextConnection.targetBlock();
}
},
onchange: function() {
if (!this.workspace) {
// Block has been deleted.
return;
}
if (this.optionCount_ < 1) {
this.setWarningText('Drop down menu must\nhave at least one option.');
} else {
fieldNameCheck(this);
}
}
};
Blockly.Blocks['field_dropdown_container'] = {
// Container.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendField('add options');
this.appendStatementInput('STACK');
this.setTooltip('Add, remove, or reorder options\n' +
'to reconfigure this dropdown menu.');
this.contextMenu = false;
}
};
Blockly.Blocks['field_dropdown_option'] = {
// Add option.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendField('option');
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip('Add a new option to the dropdown menu.');
this.contextMenu = false;
}
};
Blockly.Blocks['field_checkbox'] = {
// Checkbox.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendField('checkbox')
.appendField(new Blockly.FieldCheckbox('TRUE'), 'CHECKED')
.appendField(',')
.appendField(new Blockly.FieldTextInput('NAME'), 'FIELDNAME');
this.setPreviousStatement(true, 'Field');
this.setNextStatement(true, 'Field');
this.setTooltip('Checkbox field.');
},
onchange: function() {
if (!this.workspace) {
// Block has been deleted.
return;
}
fieldNameCheck(this);
}
};
Blockly.Blocks['field_colour'] = {
// Colour input.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendField('colour')
.appendField(new Blockly.FieldColour('#ff0000'), 'COLOUR')
.appendField(',')
.appendField(new Blockly.FieldTextInput('NAME'), 'FIELDNAME');
this.setPreviousStatement(true, 'Field');
this.setNextStatement(true, 'Field');
this.setTooltip('Colour input field.');
},
onchange: function() {
if (!this.workspace) {
// Block has been deleted.
return;
}
fieldNameCheck(this);
}
};
Blockly.Blocks['field_variable'] = {
// Dropdown for variables.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendField('variable')
.appendField(new Blockly.FieldTextInput('item'), 'TEXT')
.appendField(',')
.appendField(new Blockly.FieldTextInput('NAME'), 'FIELDNAME');
this.setPreviousStatement(true, 'Field');
this.setNextStatement(true, 'Field');
this.setTooltip('Dropdown menu for variable names.');
},
onchange: function() {
if (!this.workspace) {
// Block has been deleted.
return;
}
fieldNameCheck(this);
}
};
Blockly.Blocks['field_image'] = {
// Image.
init: function() {
this.setColour(160);
var src = 'http://www.gstatic.com/codesite/ph/images/star_on.gif';
this.appendDummyInput()
.appendField('image')
.appendField(new Blockly.FieldTextInput(src), 'SRC');
this.appendDummyInput()
.appendField('width')
.appendField(new Blockly.FieldTextInput('15',
Blockly.FieldTextInput.numberValidator), 'WIDTH')
.appendField('height')
.appendField(new Blockly.FieldTextInput('15',
Blockly.FieldTextInput.numberValidator), 'HEIGHT')
.appendField('alt text')
.appendField(new Blockly.FieldTextInput('*'), 'ALT');
this.setPreviousStatement(true, 'Field');
this.setNextStatement(true, 'Field');
this.setTooltip('Static image (JPEG, PNG, GIF, SVG, BMP).\n' +
'Retains aspect ratio regardless of height and width.\n' +
'Alt text is for when collapsed.');
}
};
Blockly.Blocks['type_group'] = {
// Group of types.
init: function() {
this.setColour(230);
this.appendValueInput('TYPE0')
.setCheck('Type')
.appendField('any of');
this.appendValueInput('TYPE1')
.setCheck('Type');
this.setOutput(true, 'Type');
this.setMutator(new Blockly.Mutator(['type_group_item']));
this.setTooltip('Allows more than one type to be accepted.');
this.typeCount_ = 2;
},
mutationToDom: function(workspace) {
var container = document.createElement('mutation');
container.setAttribute('types', this.typeCount_);
return container;
},
domToMutation: function(container) {
for (var x = 0; x < this.typeCount_; x++) {
this.removeInput('TYPE' + x);
}
this.typeCount_ = parseInt(container.getAttribute('types'), 10);
for (var x = 0; x < this.typeCount_; x++) {
var input = this.appendValueInput('TYPE' + x)
.setCheck('Type');
if (x == 0) {
input.appendField('any of');
}
}
},
decompose: function(workspace) {
var containerBlock =
Blockly.Block.obtain(workspace, 'type_group_container');
containerBlock.initSvg();
var connection = containerBlock.getInput('STACK').connection;
for (var x = 0; x < this.typeCount_; x++) {
var typeBlock = Blockly.Block.obtain(workspace, 'type_group_item');
typeBlock.initSvg();
connection.connect(typeBlock.previousConnection);
connection = typeBlock.nextConnection;
}
return containerBlock;
},
compose: function(containerBlock) {
// Disconnect all input blocks and remove all inputs.
for (var x = this.typeCount_ - 1; x >= 0; x--) {
this.removeInput('TYPE' + x);
}
this.typeCount_ = 0;
// Rebuild the block's inputs.
var typeBlock = containerBlock.getInputTargetBlock('STACK');
while (typeBlock) {
var input = this.appendValueInput('TYPE' + this.typeCount_)
.setCheck('Type');
if (this.typeCount_ == 0) {
input.appendField('any of');
}
// Reconnect any child blocks.
if (typeBlock.valueConnection_) {
input.connection.connect(typeBlock.valueConnection_);
}
this.typeCount_++;
typeBlock = typeBlock.nextConnection &&
typeBlock.nextConnection.targetBlock();
}
},
saveConnections: function(containerBlock) {
// Store a pointer to any connected child blocks.
var typeBlock = containerBlock.getInputTargetBlock('STACK');
var x = 0;
while (typeBlock) {
var input = this.getInput('TYPE' + x);
typeBlock.valueConnection_ = input && input.connection.targetConnection;
x++;
typeBlock = typeBlock.nextConnection &&
typeBlock.nextConnection.targetBlock();
}
}
};
Blockly.Blocks['type_group_container'] = {
// Container.
init: function() {
this.setColour(230);
this.appendDummyInput()
.appendField('add types');
this.appendStatementInput('STACK');
this.setTooltip('Add, or remove allowed type.');
this.contextMenu = false;
}
};
Blockly.Blocks['type_group_item'] = {
// Add type.
init: function() {
this.setColour(230);
this.appendDummyInput()
.appendField('type');
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip('Add a new allowed type.');
this.contextMenu = false;
}
};
Blockly.Blocks['type_null'] = {
// Null type.
valueType: 'null',
init: function() {
this.setColour(230);
this.appendDummyInput()
.appendField('any');
this.setOutput(true, 'Type');
this.setTooltip('Any type is allowed.');
}
};
Blockly.Blocks['type_boolean'] = {
// Boolean type.
valueType: 'Boolean',
init: function() {
this.setColour(230);
this.appendDummyInput()
.appendField('boolean');
this.setOutput(true, 'Type');
this.setTooltip('Booleans (true/false) are allowed.');
}
};
Blockly.Blocks['type_number'] = {
// Number type.
valueType: 'Number',
init: function() {
this.setColour(230);
this.appendDummyInput()
.appendField('number');
this.setOutput(true, 'Type');
this.setTooltip('Numbers (int/float) are allowed.');
}
};
Blockly.Blocks['type_string'] = {
// String type.
valueType: 'String',
init: function() {
this.setColour(230);
this.appendDummyInput()
.appendField('string');
this.setOutput(true, 'Type');
this.setTooltip('Strings (text) are allowed.');
}
};
Blockly.Blocks['type_list'] = {
// List type.
valueType: 'Array',
init: function() {
this.setColour(230);
this.appendDummyInput()
.appendField('list');
this.setOutput(true, 'Type');
this.setTooltip('Arrays (lists) are allowed.');
}
};
Blockly.Blocks['type_other'] = {
// Other type.
init: function() {
this.setColour(230);
this.appendDummyInput()
.appendField('other')
.appendField(new Blockly.FieldTextInput(''), 'TYPE');
this.setOutput(true, 'Type');
this.setTooltip('Custom type to allow.');
}
};
Blockly.Blocks['colour_hue'] = {
// Set the colour of the block.
init: function() {
this.appendDummyInput()
.appendField('hue:')
.appendField(new Blockly.FieldAngle('0', this.validator), 'HUE');
this.setOutput(true, 'Colour');
this.setTooltip('Paint the block with this colour.');
},
validator: function(text) {
// Update the current block's colour to match.
this.sourceBlock_.setColour(text);
}
};
/**
* Check to see if more than one field has this name.
* Highly inefficient (On^2), but n is small.
* @param {!Blockly.Block} referenceBlock Block to check.
*/
function fieldNameCheck(referenceBlock) {
var name = referenceBlock.getFieldValue('FIELDNAME').toLowerCase();
var count = 0;
var blocks = referenceBlock.workspace.getAllBlocks();
for (var x = 0, block; block = blocks[x]; x++) {
var otherName = block.getFieldValue('FIELDNAME');
if (!block.disabled && !block.getInheritedDisabled() &&
otherName && otherName.toLowerCase() == name) {
count++;
}
}
var msg = (count > 1) ?
'There are ' + count + ' field blocks\n with this name.' : null;
referenceBlock.setWarningText(msg);
}
/**
* Check to see if more than one input has this name.
* Highly inefficient (On^2), but n is small.
* @param {!Blockly.Block} referenceBlock Block to check.
*/
function inputNameCheck(referenceBlock) {
var name = referenceBlock.getFieldValue('INPUTNAME').toLowerCase();
var count = 0;
var blocks = referenceBlock.workspace.getAllBlocks();
for (var x = 0, block; block = blocks[x]; x++) {
var otherName = block.getFieldValue('INPUTNAME');
if (!block.disabled && !block.getInheritedDisabled() &&
otherName && otherName.toLowerCase() == name) {
count++;
}
}
var msg = (count > 1) ?
'There are ' + count + ' input blocks\n with this name.' : null;
referenceBlock.setWarningText(msg);
}

View File

@@ -0,0 +1,472 @@
/**
* Blockly Apps: Block Factory
*
* Copyright 2012 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 JavaScript for Blockly's Block Factory application.
* @author fraser@google.com (Neil Fraser)
*/
'use strict';
/**
* The type of the generated block.
*/
var blockType = '';
/**
* Initialize Blockly. Called on page load.
* @param {!Function} updateFunc Function to update the preview.
*/
function initPreview(updateFunc) {
updatePreview.updateFunc = updateFunc;
updatePreview();
}
/**
* When the workspace changes, update the three other displays.
*/
function onchange() {
var name = '';
var rootBlock = getRootBlock();
if (rootBlock) {
name = rootBlock.getFieldValue('NAME');
}
blockType = name.replace(/\W/g, '_').replace(/^(\d)/, '_\\1').toLowerCase();
if (!blockType) {
blockType = 'unnamed';
}
updateLanguage();
updateGenerator();
updatePreview();
}
/**
* Update the language code.
*/
function updateLanguage() {
// Generate name.
var code = [];
code.push("Blockly.Blocks['" + blockType + "'] = {");
var rootBlock = getRootBlock();
if (rootBlock) {
code.push(" init: function() {");
code.push(" this.setHelpUrl('http://www.example.com/');");
// Generate colour.
var colourBlock = rootBlock.getInputTargetBlock('COLOUR');
if (colourBlock && !colourBlock.disabled) {
var hue = parseInt(colourBlock.getFieldValue('HUE'), 10);
code.push(' this.setColour(' + hue + ');');
}
// Generate inputs.
var TYPES = {'input_value': 'appendValueInput',
'input_statement': 'appendStatementInput',
'input_dummy': 'appendDummyInput'};
var inputVarDefined = false;
var contentsBlock = rootBlock.getInputTargetBlock('INPUTS');
while (contentsBlock) {
if (!contentsBlock.disabled && !contentsBlock.getInheritedDisabled()) {
var align = contentsBlock.getFieldValue('ALIGN');
var fields = getFields(contentsBlock.getInputTargetBlock('FIELDS'));
var name = '';
// Dummy inputs don't have names. Other inputs do.
if (contentsBlock.type != 'input_dummy') {
name = escapeString(contentsBlock.getFieldValue('INPUTNAME'));
}
var check = getOptTypesFrom(contentsBlock, 'TYPE');
code.push(' this.' + TYPES[contentsBlock.type] +
'(' + name + ')');
if (check && check != 'null') {
code.push(' .setCheck(' + check + ')');
}
if (align != 'LEFT') {
code.push(' .setAlign(Blockly.ALIGN_' + align + ')');
}
for (var x = 0; x < fields.length; x++) {
code.push(' .appendField(' + fields[x] + ')');
}
// Add semicolon to last line to finish the statement.
code[code.length - 1] += ';';
}
contentsBlock = contentsBlock.nextConnection &&
contentsBlock.nextConnection.targetBlock();
}
// Generate inline/external switch.
if (rootBlock.getFieldValue('INLINE') == 'INT') {
code.push(' this.setInputsInline(true);');
}
// Generate output, or next/previous connections.
switch (rootBlock.getFieldValue('CONNECTIONS')) {
case 'LEFT':
code.push(connectionLine_('setOutput', 'OUTPUTTYPE'));
break;
case 'BOTH':
code.push(connectionLine_('setPreviousStatement', 'TOPTYPE'));
code.push(connectionLine_('setNextStatement', 'BOTTOMTYPE'));
break;
case 'TOP':
code.push(connectionLine_('setPreviousStatement', 'TOPTYPE'));
break;
case 'BOTTOM':
code.push(connectionLine_('setNextStatement', 'BOTTOMTYPE'));
break;
}
code.push(" this.setTooltip('');");
code.push(" }");
}
code.push("};");
injectCode(code, 'languagePre');
}
/**
* Create JS code required to create a top, bottom, or value connection.
* @param {string} functionName JavaScript function name.
* @param {string} typeName Name of type input.
* @return {string} Line of JavaScript code to create connection.
* @private
*/
function connectionLine_(functionName, typeName) {
var type = getOptTypesFrom(getRootBlock(), typeName);
if (type) {
type = ', ' + type;
}
return ' this.' + functionName + '(true' + type + ');';
}
/**
* Returns a field string and any config.
* @param {!Blockly.Block} block Field block.
* @return {string} Field string.
*/
function getFields(block) {
var fields = [];
while (block) {
if (!block.disabled && !block.getInheritedDisabled()) {
switch (block.type) {
case 'field_static':
// Result: 'hello'
fields.push(escapeString(block.getFieldValue('TEXT')));
break;
case 'field_input':
// Result: new Blockly.FieldTextInput('Hello'), 'GREET'
fields.push('new Blockly.FieldTextInput(' +
escapeString(block.getFieldValue('TEXT')) + '), ' +
escapeString(block.getFieldValue('FIELDNAME')));
break;
case 'field_angle':
// Result: new Blockly.FieldAngle(90), 'ANGLE'
fields.push('new Blockly.FieldAngle(' +
escapeString(block.getFieldValue('ANGLE')) + '), ' +
escapeString(block.getFieldValue('FIELDNAME')));
break;
case 'field_checkbox':
// Result: new Blockly.FieldCheckbox('TRUE'), 'CHECK'
fields.push('new Blockly.FieldCheckbox(' +
escapeString(block.getFieldValue('CHECKED')) + '), ' +
escapeString(block.getFieldValue('FIELDNAME')));
break;
case 'field_colour':
// Result: new Blockly.FieldColour('#ff0000'), 'COLOUR'
fields.push('new Blockly.FieldColour(' +
escapeString(block.getFieldValue('COLOUR')) + '), ' +
escapeString(block.getFieldValue('FIELDNAME')));
break;
case 'field_variable':
// Result:
// new Blockly.FieldVariable('item'), 'VAR'
var varname = block.getFieldValue('TEXT');
varname = varname ? escapeString(varname) : 'null';
fields.push('new Blockly.FieldVariable(' + varname + '), ' +
escapeString(block.getFieldValue('FIELDNAME')));
break;
case 'field_dropdown':
// Result:
// new Blockly.FieldDropdown([['yes', '1'], ['no', '0']]), 'TOGGLE'
var options = [];
for (var x = 0; x < block.optionCount_; x++) {
options[x] = '[' + escapeString(block.getFieldValue('USER' + x)) +
', ' + escapeString(block.getFieldValue('CPU' + x)) + ']';
}
if (options.length) {
fields.push('new Blockly.FieldDropdown([' +
options.join(', ') + ']), ' +
escapeString(block.getFieldValue('FIELDNAME')));
}
break;
case 'field_image':
// Result: new Blockly.FieldImage('http://...', 80, 60)
var src = escapeString(block.getFieldValue('SRC'));
var width = Number(block.getFieldValue('WIDTH'));
var height = Number(block.getFieldValue('HEIGHT'));
var alt = escapeString(block.getFieldValue('ALT'));
fields.push('new Blockly.FieldImage(' +
src + ', ' + width + ', ' + height + ', ' + alt + ')');
break;
}
}
block = block.nextConnection && block.nextConnection.targetBlock();
}
return fields;
}
/**
* Escape a string.
* @param {string} string String to escape.
* @return {string} Escaped string surrouned by quotes.
*/
function escapeString(string) {
if (JSON && JSON.stringify) {
return JSON.stringify(string);
}
// Hello MSIE 8.
return '"' + string.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"';
}
/**
* Fetch the type(s) defined in the given input.
* Format as a string for appending to the generated code.
* @param {!Blockly.Block} block Block with input.
* @param {string} name Name of the input.
* @return {string} String defining the types.
*/
function getOptTypesFrom(block, name) {
var types = getTypesFrom_(block, name);
if (types.length == 0) {
return '';
} else if (types.length == 1) {
return types[0];
} else if (types.indexOf('null') != -1) {
return 'null';
} else {
return '[' + types.join(', ') + ']';
}
}
/**
* Fetch the type(s) defined in the given input.
* @param {!Blockly.Block} block Block with input.
* @param {string} name Name of the input.
* @return {!Array.<string>} List of types.
* @private
*/
function getTypesFrom_(block, name) {
var typeBlock = block.getInputTargetBlock(name);
var types;
if (!typeBlock || typeBlock.disabled) {
types = [];
} else if (typeBlock.type == 'type_other') {
types = [escapeString(typeBlock.getFieldValue('TYPE'))];
} else if (typeBlock.type == 'type_group') {
types = [];
for (var n = 0; n < typeBlock.typeCount_; n++) {
types = types.concat(getTypesFrom_(typeBlock, 'TYPE' + n));
}
// Remove duplicates.
var hash = Object.create(null);
for (var n = types.length - 1; n >= 0; n--) {
if (hash[types[n]]) {
types.splice(n, 1);
}
hash[types[n]] = true;
}
} else {
types = [escapeString(typeBlock.valueType)];
}
return types;
}
/**
* Update the generator code.
*/
function updateGenerator() {
function makeVar(root, name) {
name = name.toLowerCase().replace(/\W/g, '_');
return ' var ' + root + '_' + name;
}
var language = document.getElementById('language').value;
var code = [];
code.push("Blockly." + language + "['" + blockType +
"'] = function(block) {");
var rootBlock = getRootBlock();
if (rootBlock) {
// Loop through every block, and generate getters for any fields or inputs.
var blocks = rootBlock.getDescendants();
for (var x = 0, block; block = blocks[x]; x++) {
if (block.disabled || block.getInheritedDisabled()) {
continue;
}
switch (block.type) {
case 'field_input':
var name = block.getFieldValue('FIELDNAME');
code.push(makeVar('text', name) +
" = block.getFieldValue('" + name + "');");
break;
case 'field_angle':
var name = block.getFieldValue('FIELDNAME');
code.push(makeVar('angle', name) +
" = block.getFieldValue('" + name + "');");
break;
case 'field_dropdown':
var name = block.getFieldValue('FIELDNAME');
code.push(makeVar('dropdown', name) +
" = block.getFieldValue('" + name + "');");
break;
case 'field_checkbox':
var name = block.getFieldValue('FIELDNAME');
code.push(makeVar('checkbox', name) +
" = block.getFieldValue('" + name + "') == 'TRUE';");
break;
case 'field_colour':
var name = block.getFieldValue('FIELDNAME');
code.push(makeVar('colour', name) +
" = block.getFieldValue('" + name + "');");
break;
case 'field_variable':
var name = block.getFieldValue('FIELDNAME');
code.push(makeVar('variable', name) +
" = Blockly." + language +
".variableDB_.getName(block.getFieldValue('" + name +
"'), Blockly.Variables.NAME_TYPE);");
break;
case 'input_value':
var name = block.getFieldValue('INPUTNAME');
code.push(makeVar('value', name) +
" = Blockly." + language + ".valueToCode(block, '" + name +
"', Blockly." + language + ".ORDER_ATOMIC);");
break;
case 'input_statement':
var name = block.getFieldValue('INPUTNAME');
code.push(makeVar('statements', name) +
" = Blockly." + language + ".statementToCode(block, '" +
name + "');");
break;
}
}
code.push(" // TODO: Assemble " + language + " into code variable.");
code.push(" var code = \'...\';");
if (rootBlock.getFieldValue('CONNECTIONS') == 'LEFT') {
code.push(" // TODO: Change ORDER_NONE to the correct strength.");
code.push(" return [code, Blockly." + language + ".ORDER_NONE];");
} else {
code.push(" return code;");
}
}
code.push("};");
injectCode(code, 'generatorPre');
}
var oldDir = 'ltr';
/**
* Update the preview display.
*/
function updatePreview() {
var newDir = document.getElementById('direction').value;
if (oldDir != newDir) {
document.getElementById('previewFrame').src = 'preview.html?' + newDir;
oldDir = newDir;
} else if (updatePreview.updateFunc) {
var code = document.getElementById('languagePre').textContent;
updatePreview.updateFunc(blockType, code);
}
}
/**
* Inject code into a pre tag, with syntax highlighting.
* Safe from HTML/script injection.
* @param {!Array.<string>} code Array of lines of code.
* @param {string} id ID of <pre> element to inject into.
*/
function injectCode(code, id) {
var pre = document.getElementById(id);
pre.textContent = code.join('\n');
code = pre.innerHTML;
code = prettyPrintOne(code, 'js');
pre.innerHTML = code;
}
/**
* Return the uneditable container block that everything else attaches to.
* @return {Blockly.Block}
*/
function getRootBlock() {
var blocks = Blockly.mainWorkspace.getTopBlocks(false);
for (var i = 0, block; block = blocks[i]; i++) {
if (block.type == 'factory_base') {
return block;
}
}
return null;
}
/**
* Initialize Blockly and layout. Called on page load.
*/
function init() {
if ('BlocklyStorage' in window) {
BlocklyStorage.HTTPREQUEST_ERROR =
'There was a problem with the request.\n';
BlocklyStorage.LINK_ALERT =
'Share your blocks with this link:\n\n%1';
BlocklyStorage.HASH_ERROR =
'Sorry, "%1" doesn\'t correspond with any saved Blockly file.';
BlocklyStorage.XML_ERROR = 'Could not load your saved file.\n'+
'Perhaps it was created with a different version of Blockly?';
var linkButton = document.getElementById('linkButton');
linkButton.style.display = 'inline-block';
linkButton.addEventListener('click', BlocklyStorage.link);
}
var expandList = [
document.getElementById('blockly'),
document.getElementById('previewFrame'),
document.getElementById('languagePre'),
document.getElementById('generatorPre')
];
var onresize = function(e) {
for (var i = 0, expand; expand = expandList[i]; i++) {
expand.style.width = (expand.parentNode.offsetWidth - 2) + 'px';
expand.style.height = (expand.parentNode.offsetHeight - 2) + 'px';
}
};
onresize();
window.addEventListener('resize', onresize);
var toolbox = document.getElementById('toolbox');
Blockly.inject(document.getElementById('blockly'),
{path: '../../', toolbox: toolbox});
// Create the root block.
if ('BlocklyStorage' in window && window.location.hash.length > 1) {
BlocklyStorage.retrieveXml(window.location.hash.substring(1));
} else {
var rootBlock = Blockly.Block.obtain(Blockly.mainWorkspace, 'factory_base');
rootBlock.initSvg();
rootBlock.render();
rootBlock.setMovable(false);
rootBlock.setDeletable(false);
}
Blockly.addChangeListener(onchange);
document.getElementById('direction')
.addEventListener('change', updatePreview);
document.getElementById('language')
.addEventListener('change', updateGenerator);
}
window.addEventListener('load', init);

BIN
demos/blockfactory/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -0,0 +1,185 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="target-densitydpi=device-dpi, height=660, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Blockly Demo: Block Factory</title>
<script type="text/javascript" src="/storage.js"></script>
<script type="text/javascript" src="factory.js"></script>
<script type="text/javascript" src="../../blockly_compressed.js"></script>
<script type="text/javascript" src="../../msg/messages.js"></script>
<script type="text/javascript" src="blocks.js"></script>
<style>
html, body {
height: 100%;
}
body {
background-color: #fff;
font-family: sans-serif;
margin: 0 5px;
overflow: hidden
}
h1 {
font-weight: normal;
font-size: 140%;
}
h3 {
margin-top: 5px;
margin-bottom: 0;
}
a:hover {
color: #f00;
}
table {
height: 100%;
width: 100%;
}
td {
vertical-align: top;
padding: 0;
}
#blockly {
position: fixed;
}
#previewFrame {
border-style: solid;
border-color: #ddd;
border-width: 0 1px 1px 0;
position: absolute;
}
pre {
margin-top: 0;
position: absolute;
border: #ddd 1px solid;
overflow: scroll;
}
#linkButton {
border-radius: 4px;
border: 1px solid #ddd;
background-color: #eee;
color: #000;
padding: 1px 10px;
margin: 1px 5px;
display: none;
}
#linkButton:hover {
box-shadow: 2px 2px 5px #888;
}
#linkButton>img {
opacity: 0.6;
}
#linkButton:hover>img {
opacity: 1;
}
</style>
<link rel="stylesheet" type="text/css" href="../prettify.css">
<script type="text/javascript" src="../prettify.js"></script>
</head>
<body>
<table>
<tr>
<td width="50%" height="5%">
<h1><a href="https://developers.google.com/blockly/">Blockly</a> &gt;
<a href="../index.html">Demos</a> &gt; Block Factory</h1>
</td>
<td width="50%" height="5%">
<table>
<tr>
<td style="vertical-align: bottom;">
<h3>Preview:
<select id="direction">
<option value="ltr">LTR</option>
<option value="rtl">RTL</option>
</select>
</h3>
</td>
<td style="vertical-align: middle; text-align: right;">
<button id="linkButton" title="Save and link to blocks.">
<img src="link.png" height="21" width="21">
</button>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="50%" height="95%" style="padding: 2px;">
<div id="blockly"></div>
</td>
<td width="50%" height="95%">
<table>
<tr>
<td height="30%">
<iframe id="previewFrame" src="preview.html?ltr"></iframe>
</td>
</tr>
<tr>
<td height="5%">
<h3>Language code:</h3>
</td>
</tr>
<tr>
<td height="30%">
<pre id="languagePre"></pre>
</td>
</tr>
<tr>
<td height="5%">
<h3>Generator stub:
<select id="language">
<option value="JavaScript">JavaScript</option>
<option value="Python">Python</option>
<option value="Dart">Dart</option>
</select>
</h3>
</td>
</tr>
<tr>
<td height="30%">
<pre id="generatorPre"></pre>
</td>
</tr>
</table>
</td>
</tr>
</table>
<xml id="toolbox" style="display: none">
<category name="Input">
<block type="input_value"></block>
<block type="input_statement"></block>
<block type="input_dummy"></block>
</category>
<category name="Field">
<block type="field_static"></block>
<block type="field_input"></block>
<block type="field_angle"></block>
<block type="field_dropdown"></block>
<block type="field_checkbox"></block>
<block type="field_colour"></block>
<block type="field_variable"></block>
<block type="field_image"></block>
</category>
<category name="Type">
<block type="type_group"></block>
<block type="type_null"></block>
<block type="type_boolean"></block>
<block type="type_number"></block>
<block type="type_string"></block>
<block type="type_list"></block>
<block type="type_other"></block>
</category>
<category name="Colour" id="colourCategory">
<block type="colour_hue"><field name="HUE">20</field></block>
<block type="colour_hue"><field name="HUE">65</field></block>
<block type="colour_hue"><field name="HUE">120</field></block>
<block type="colour_hue"><field name="HUE">160</field></block>
<block type="colour_hue"><field name="HUE">210</field></block>
<block type="colour_hue"><field name="HUE">230</field></block>
<block type="colour_hue"><field name="HUE">260</field></block>
<block type="colour_hue"><field name="HUE">290</field></block>
<block type="colour_hue"><field name="HUE">330</field></block>
</category>
</xml>
</body>
</html>

BIN
demos/blockfactory/link.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="google" value="notranslate">
<title>Block Factory Preview</title>
<script type="text/javascript" src="../../blockly_compressed.js"></script>
<script type="text/javascript" src="../../msg/messages.js"></script>
<script type="text/javascript" src="preview.js"></script>
<style>
html, body {
background-color: #fff;
margin: 0;
padding: 0;
overflow: hidden;
height: 100%;
}
.blocklySvg {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1,76 @@
/**
* Blockly Apps: Block Factory
*
* Copyright 2013 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 JavaScript for Blockly's Block Factory preview.
* @author fraser@google.com (Neil Fraser)
*/
'use strict';
/**
* The uneditable preview block.
* @type {Blockly.Block}
*/
var previewBlock = null;
/**
* Create the specified block in this preview pane.
* @param {string} type Name of block.
* @param {string} code JavaScript code to create a block.
*/
function updateFunc(type, code) {
if (previewBlock) {
previewBlock.dispose();
previewBlock = null;
}
eval(code);
// Create the preview block.
previewBlock = Blockly.Block.obtain(Blockly.mainWorkspace, type);
previewBlock.initSvg();
previewBlock.render();
previewBlock.setMovable(false);
previewBlock.setDeletable(false);
}
/**
* Initialize Blockly. Called on page load.
*/
function init() {
var rtl = (document.location.search == '?rtl');
Blockly.inject(document.body, {path: '../../', rtl: rtl});
if (window.parent.initPreview) {
// Let the top-level application know that Blockly is ready.
window.parent.initPreview(updateFunc);
} else {
// Attempt to diagnose the problem.
var msg = 'Error: Unable to communicate between frames.\n' +
'The preview frame will not be functional.\n\n';
if (window.parent == window) {
msg += 'Try loading index.html instead of preview.html';
} else if (window.location.protocol == 'file:') {
msg += 'This may be due to a security restriction preventing\n' +
'access when using the file:// protocol.\n' +
'http://code.google.com/p/chromium/issues/detail?id=47416';
}
alert(msg);
}
}
window.addEventListener('load', init);

BIN
demos/fixed/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
demos/generator/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
demos/iframe/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -5,15 +5,22 @@
<title>Blockly Demos</title>
<style>
body {
margin: 0 10%;
background-color: #fff;
font-family: sans-serif;
}
td {
padding: 1ex;
}
img {
border: none;
}
h1 {
font-weight: normal;
font-size: 140%;
}
dt {
margin-top: 2ex;
a:hover {
color: #f00;
}
</style>
</head>
@@ -23,30 +30,114 @@
<p>These demos are intended for developers who want to integrate Blockly with
their own applications.</p>
<dl>
<dt><a href="fixed/index.html">Fixed Blockly</a></dt>
<dd>Inject Blockly into a page as a fixed element.</dd>
<table>
<tr>
<td>
<a href="fixed/index.html">
<img src="fixed/icon.png" height=80 width=100>
</a>
</td>
<td>
<div><a href="fixed/index.html">Fixed Blockly</a></div>
<div>Inject Blockly into a page as a fixed element.</div>
</td>
</tr>
<dt><a href="iframe/index.html">Resizable Blockly</a></dt>
<dd>Inject Blockly into a page as a resizable element.</dd>
<tr>
<td>
<a href="iframe/index.html">
<img src="iframe/icon.png" height=80 width=100>
</a>
</td>
<td>
<div><a href="iframe/index.html">Resizable Blockly</a></div>
<div>Inject Blockly into a page as a resizable element.</div>
</td>
</tr>
<dt><a href="toolbox/index.html">Defining the Toolbox</a></dt>
<dd>Organize blocks into categories for the user.</dd>
<tr>
<td>
<a href="toolbox/index.html">
<img src="toolbox/icon.png" height=80 width=100>
</a>
</td>
<td>
<div><a href="toolbox/index.html">Defining the Toolbox</a></div>
<div>Organize blocks into categories for the user.</div>
</td>
</tr>
<dt><a href="rtl/index.html">RTL</a></dt>
<dd>See what Blockly looks like in right-to-left mode (for Arabic and Hebrew).</dd>
<tr>
<td>
<a href="rtl/index.html">
<img src="rtl/icon.png" height=80 width=100>
</a>
</td>
<td>
<div><a href="rtl/index.html">RTL</a></div>
<div>See what Blockly looks like in right-to-left mode (for Arabic and Hebrew).</div>
</td>
</tr>
<dt><a href="maxBlocks/index.html">Maximum Block Limit</a></dt>
<dd>Limit the total number of blocks allowed (for academic exercises).</dd>
<tr>
<td>
<a href="maxBlocks/index.html">
<img src="maxBlocks/icon.png" height=80 width=100>
</a>
</td>
<td>
<div><a href="maxBlocks/index.html">Maximum Block Limit</a></div>
<div>Limit the total number of blocks allowed (for academic exercises).</div>
</td>
</tr>
<dt><a href="generator/index.html">Generate JavaScript</a></dt>
<dd>Turn blocks into code and execute it.</dd>
<tr>
<td>
<a href="generator/index.html">
<img src="generator/icon.png" height=80 width=100>
</a>
</td>
<td>
<div><a href="generator/index.html">Generate JavaScript</a></div>
<div>Turn blocks into code and execute it.</div>
</td>
</tr>
<dt><a href="interpreter/index.html">JS Interpreter</a></dt>
<dd>Step by step execution in JavaScript.</dd>
<tr>
<td>
<a href="interpreter/index.html">
<img src="interpreter/icon.png" height=80 width=100>
</a>
</td>
<td>
<div><a href="interpreter/index.html">JS Interpreter</a></div>
<div>Step by step execution in JavaScript.</div>
</td>
</tr>
<dt><a href="storage/index.html">Cloud Storage</a></dt>
<dd>Save and load blocks with App Engine.</dd>
</dl>
<tr>
<td>
<a href="storage/index.html">
<img src="storage/icon.png" height=80 width=100>
</a>
</td>
<td>
<div><a href="storage/index.html">Cloud Storage</a></div>
<div>Save and load blocks with App Engine.</div>
</td>
</tr>
<tr>
<td>
<a href="blockfactory/index.html">
<img src="blockfactory/icon.png" height=80 width=100>
</a>
</td>
<td>
<div><a href="blockfactory/index.html">Block Factory</a></div>
<div>Build custom blocks using Blockly.</div>
</td>
</tr>
</table>
</body>
</html>

BIN
demos/interpreter/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
demos/maxBlocks/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

1
demos/prettify.css Normal file
View File

@@ -0,0 +1 @@
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}

30
demos/prettify.js Normal file
View File

@@ -0,0 +1,30 @@
!function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a=
b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a<f;++a){var h=b[a];if(/\\[bdsw]/i.test(h))c.push(h);else{var h=d(h),l;a+2<f&&"-"===b[a+1]?(l=d(b[a+2]),a+=2):l=h;e.push([h,l]);l<65||h>122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;a<e.length;++a)h=e[a],h[0]<=f[1]+1?f[1]=Math.max(f[1],h[1]):b.push(f=h);for(a=0;a<b.length;++a)h=b[a],c.push(g(h[0])),
h[1]>h[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f<c;++f){var l=a[f];l==="("?++h:"\\"===l.charAt(0)&&(l=+l.substring(1))&&(l<=h?d[l]=-1:a[f]=g(l))}for(f=1;f<d.length;++f)-1===d[f]&&(d[f]=++x);for(h=f=0;f<c;++f)l=a[f],l==="("?(++h,d[h]||(a[f]="(?:")):"\\"===l.charAt(0)&&(l=+l.substring(1))&&l<=h&&
(a[f]="\\"+d[l]);for(f=0;f<c;++f)"^"===a[f]&&"^"!==a[f+1]&&(a[f]="");if(e.ignoreCase&&m)for(f=0;f<c;++f)l=a[f],e=l.charAt(0),l.length>=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k<c;++k){var i=a[k];if(i.ignoreCase)j=!0;else if(/[a-z]/i.test(i.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){m=!0;j=!1;break}}for(var r={b:8,t:9,n:10,v:11,
f:12,r:13},n=[],k=0,c=a.length;k<c;++k){i=a[k];if(i.global||i.multiline)throw Error(""+i);n.push("(?:"+s(i)+")")}return RegExp(n.join("|"),j?"gi":"g")}function T(a,d){function g(a){var c=a.nodeType;if(c==1){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)g(c);c=a.nodeName.toLowerCase();if("br"===c||"li"===c)s[j]="\n",m[j<<1]=x++,m[j++<<1|1]=a}}else if(c==3||c==4)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[\t\n\r ]+/g," "),s[j]=c,m[j<<1]=x,x+=c.length,m[j++<<1|1]=
a)}var b=/(?:^|\s)nocode(?:\s|$)/,s=[],x=0,m=[],j=0;g(a);return{a:s.join("").replace(/\n$/,""),d:m}}function H(a,d,g,b){d&&(a={a:d,e:a},g(a),b.push.apply(b,a.g))}function U(a){for(var d=void 0,g=a.firstChild;g;g=g.nextSibling)var b=g.nodeType,d=b===1?d?a:g:b===3?V.test(g.nodeValue)?a:d:d;return d===a?void 0:d}function C(a,d){function g(a){for(var j=a.e,k=[j,"pln"],c=0,i=a.a.match(s)||[],r={},n=0,e=i.length;n<e;++n){var z=i[n],w=r[z],t=void 0,f;if(typeof w==="string")f=!1;else{var h=b[z.charAt(0)];
if(h)t=z.match(h[1]),w=h[0];else{for(f=0;f<x;++f)if(h=d[f],t=z.match(h[1])){w=h[0];break}t||(w="pln")}if((f=w.length>=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c<i;++c){var r=
g[c],n=r[3];if(n)for(var e=n.length;--e>=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com",
/^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+
s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,
q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d=
c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i<c.length;++i)b(c[i]);d===(d|0)&&c[0].setAttribute("value",d);var r=j.createElement("ol");
r.className="linenums";for(var d=Math.max(0,d-1|0)||0,i=0,n=c.length;i<n;++i)k=c[i],k.className="L"+(i+d)%10,k.firstChild||k.appendChild(j.createTextNode("\u00a0")),r.appendChild(k);a.appendChild(r)}function p(a,d){for(var g=d.length;--g>=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*</.test(d)?"default-markup":"default-code";return F[a]}function K(a){var d=a.h;try{var g=T(a.c,a.i),b=g.a;
a.a=b;a.d=g.d;a.e=0;I(d,b)(a);var s=/\bMSIE\s(\d+)/.exec(navigator.userAgent),s=s&&+s[1]<=8,d=/\n/g,x=a.a,m=x.length,g=0,j=a.d,k=j.length,b=0,c=a.g,i=c.length,r=0;c[i]=m;var n,e;for(e=n=0;e<i;)c[e]!==c[e+2]?(c[n++]=c[e++],c[n++]=c[e++]):e+=2;i=n;for(e=n=0;e<i;){for(var p=c[e],w=c[e+1],t=e+2;t+2<=i&&c[t+1]===w;)t+=2;c[n++]=p;c[n++]=w;e=t}c.length=n;var f=a.c,h;if(f)h=f.style.display,f.style.display="none";try{for(;b<k;){var l=j[b+2]||m,B=c[r+2]||m,t=Math.min(l,B),A=j[b+1],G;if(A.nodeType!==1&&(G=x.substring(g,
t))){s&&(G=G.replace(d,"\r"));A.nodeValue=G;var L=A.ownerDocument,o=L.createElement("span");o.className=c[r+1];var v=A.parentNode;v.replaceChild(o,A);o.appendChild(A);g<l&&(j[b+1]=A=L.createTextNode(x.substring(t,l)),v.insertBefore(A,o.nextSibling))}g=t;g>=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],
O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,
V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",
/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],
["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}),
["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q,
hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]);
p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1});
return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i<p.length&&c.now()<b;i++){for(var d=p[i],j=h,k=d;k=k.previousSibling;){var m=k.nodeType,o=(m===7||m===8)&&k.nodeValue;if(o?!/^\??prettify\b/.test(o):m!==3||/\S/.test(k.nodeValue))break;if(o){j={};o.replace(/\b(\w+)=([\w%+\-.:]+)/g,function(a,b,c){j[b]=c});break}}k=d.className;if((j!==h||e.test(k))&&!v.test(k)){m=!1;for(o=d.parentNode;o;o=o.parentNode)if(f.test(o.tagName)&&
o.className&&e.test(o.className)){m=!0;break}if(!m){d.className+=" prettyprinted";m=j.lang;if(!m){var m=k.match(n),y;if(!m&&(y=U(d))&&t.test(y.tagName))m=y.className.match(n);m&&(m=m[1])}if(w.test(d.tagName))o=1;else var o=d.currentStyle,u=s.defaultView,o=(o=o?o.whiteSpace:u&&u.getComputedStyle?u.getComputedStyle(d,q).getPropertyValue("white-space"):0)&&"pre"===o.substring(0,3);u=j.linenums;if(!(u=u==="true"||+u))u=(u=k.match(/\blinenums\b(?::(\d+))?/))?u[1]&&u[1].length?+u[1]:!0:!1;u&&J(d,u,o);r=
{h:m,c:d,j:u,i:o};K(r)}}}i<p.length?setTimeout(g,250):"function"===typeof a&&a()}for(var b=d||document.body,s=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],p=[],m=0;m<b.length;++m)for(var j=0,k=b[m].length;j<k;++j)p.push(b[m][j]);var b=q,c=Date;c.now||(c={now:function(){return+new Date}});var i=0,r,n=/\blang(?:uage)?-([\w.]+)(?!\S)/,e=/\bprettyprint\b/,v=/\bprettyprinted\b/,w=/pre|xmp/i,t=/^code$/i,f=/^(?:pre|code|xmp)$/i,
h={};g()}};typeof define==="function"&&define.amd&&define("google-code-prettify",[],function(){return Y})})();}()

BIN
demos/rtl/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
demos/storage/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
demos/toolbox/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB