Automatic commit Sat Feb 22 03:00:01 PST 2014

This commit is contained in:
ellen.spertus
2014-02-22 03:00:01 -08:00
parent 739cc2227b
commit 58f264f4ce
7 changed files with 376 additions and 191 deletions

View File

@@ -797,10 +797,10 @@ Blockly.ConnectionDB.init=function(a){var b=[];b[Blockly.INPUT_VALUE]=new Blockl
Blockly.ContextMenu={};Blockly.ContextMenu.X_PADDING=20;Blockly.ContextMenu.Y_HEIGHT=20;Blockly.ContextMenu.visible=!1;
Blockly.ContextMenu.createDom=function(){var a=Blockly.createSvgElement("g",{"class":"blocklyHidden"},null);Blockly.ContextMenu.svgGroup=a;Blockly.ContextMenu.svgShadow=Blockly.createSvgElement("rect",{"class":"blocklyContextMenuShadow",x:2,y:-2,rx:4,ry:4},a);Blockly.ContextMenu.svgBackground=Blockly.createSvgElement("rect",{"class":"blocklyContextMenuBackground",y:-4,rx:4,ry:4},a);Blockly.ContextMenu.svgOptions=Blockly.createSvgElement("g",{"class":"blocklyContextMenuOptions"},a);return a};
Blockly.ContextMenu.show=function(a,b){if(b.length){goog.dom.removeChildren(Blockly.ContextMenu.svgOptions);Blockly.ContextMenu.svgGroup.style.display="block";for(var c=0,d=[Blockly.ContextMenu.svgBackground,Blockly.ContextMenu.svgShadow],e=0,f;f=b[e];e++){var g=Blockly.ContextMenu.optionToDom(f.text),h=g.firstChild,k=g.lastChild;Blockly.ContextMenu.svgOptions.appendChild(g);g.setAttribute("transform","translate(0, "+e*Blockly.ContextMenu.Y_HEIGHT+")");d.push(h);Blockly.bindEvent_(g,"mousedown",null,
Blockly.noEvent);f.enabled?(Blockly.bindEvent_(g,"mouseup",null,f.callback),Blockly.bindEvent_(g,"mouseup",null,Blockly.ContextMenu.hide)):g.setAttribute("class","blocklyMenuDivDisabled");c=Math.max(c,k.getComputedTextLength())}c+=2*Blockly.ContextMenu.X_PADDING;for(e=0;e<d.length;e++)d[e].setAttribute("width",c);if(Blockly.RTL)for(e=0;g=Blockly.ContextMenu.svgOptions.childNodes[e];e++)k=g.lastChild,k.setAttribute("text-anchor","end"),k.setAttribute("x",c-Blockly.ContextMenu.X_PADDING);Blockly.ContextMenu.svgBackground.setAttribute("height",
b.length*Blockly.ContextMenu.Y_HEIGHT+8);Blockly.ContextMenu.svgShadow.setAttribute("height",b.length*Blockly.ContextMenu.Y_HEIGHT+10);c=a.x;d=a.y;e=Blockly.ContextMenu.svgGroup.getBBox();f=Blockly.svgSize();d+e.height>f.height&&(d-=e.height-10);Blockly.RTL?0>=c-e.width?c++:c-=e.width:c+e.width>f.width?c-=e.width:c++;Blockly.ContextMenu.svgGroup.setAttribute("transform","translate("+c+", "+d+")");Blockly.ContextMenu.visible=!0}else Blockly.ContextMenu.hide()};
Blockly.ContextMenu.optionToDom=function(a){var b=Blockly.createSvgElement("g",{"class":"blocklyMenuDiv"},null);Blockly.createSvgElement("rect",{height:Blockly.ContextMenu.Y_HEIGHT},b);var c=Blockly.createSvgElement("text",{"class":"blocklyMenuText",x:Blockly.ContextMenu.X_PADDING,y:15},b);a=document.createTextNode(a);c.appendChild(a);return b};Blockly.ContextMenu.hide=function(){Blockly.ContextMenu.visible&&(Blockly.ContextMenu.svgGroup.style.display="none",Blockly.ContextMenu.visible=!1)};
Blockly.ContextMenu.callbackFactory=function(a,b){return function(){var c=Blockly.Xml.domToBlock(a.workspace,b),d=a.getRelativeToSurfaceXY();d.x=Blockly.RTL?d.x-Blockly.SNAP_RADIUS:d.x+Blockly.SNAP_RADIUS;d.y+=2*Blockly.SNAP_RADIUS;c.moveBy(d.x,d.y);c.select()}};
Blockly.noEvent);f.enabled?(f=function(a){return function(){Blockly.doCommand(a)}}(f.callback),Blockly.bindEvent_(g,"mouseup",null,f),Blockly.bindEvent_(g,"mouseup",null,Blockly.ContextMenu.hide)):g.setAttribute("class","blocklyMenuDivDisabled");c=Math.max(c,k.getComputedTextLength())}c+=2*Blockly.ContextMenu.X_PADDING;for(e=0;e<d.length;e++)d[e].setAttribute("width",c);if(Blockly.RTL)for(e=0;g=Blockly.ContextMenu.svgOptions.childNodes[e];e++)k=g.lastChild,k.setAttribute("text-anchor","end"),k.setAttribute("x",
c-Blockly.ContextMenu.X_PADDING);Blockly.ContextMenu.svgBackground.setAttribute("height",b.length*Blockly.ContextMenu.Y_HEIGHT+8);Blockly.ContextMenu.svgShadow.setAttribute("height",b.length*Blockly.ContextMenu.Y_HEIGHT+10);c=a.x;d=a.y;e=Blockly.ContextMenu.svgGroup.getBBox();g=Blockly.svgSize();d+e.height>g.height&&(d-=e.height-10);Blockly.RTL?0>=c-e.width?c++:c-=e.width:c+e.width>g.width?c-=e.width:c++;Blockly.ContextMenu.svgGroup.setAttribute("transform","translate("+c+", "+d+")");Blockly.ContextMenu.visible=
!0}else Blockly.ContextMenu.hide()};Blockly.ContextMenu.optionToDom=function(a){var b=Blockly.createSvgElement("g",{"class":"blocklyMenuDiv"},null);Blockly.createSvgElement("rect",{height:Blockly.ContextMenu.Y_HEIGHT},b);var c=Blockly.createSvgElement("text",{"class":"blocklyMenuText",x:Blockly.ContextMenu.X_PADDING,y:15},b);a=document.createTextNode(a);c.appendChild(a);return b};
Blockly.ContextMenu.hide=function(){Blockly.ContextMenu.visible&&(Blockly.ContextMenu.svgGroup.style.display="none",Blockly.ContextMenu.visible=!1)};Blockly.ContextMenu.callbackFactory=function(a,b){return function(){var c=Blockly.Xml.domToBlock(a.workspace,b),d=a.getRelativeToSurfaceXY();d.x=Blockly.RTL?d.x-Blockly.SNAP_RADIUS:d.x+Blockly.SNAP_RADIUS;d.y+=2*Blockly.SNAP_RADIUS;c.moveBy(d.x,d.y);c.select()}};
// Copyright 2012 Google Inc. Apache License 2.0
Blockly.Field=function(a){this.sourceBlock_=null;this.fieldGroup_=Blockly.createSvgElement("g",{},null);this.borderRect_=Blockly.createSvgElement("rect",{rx:4,ry:4,x:-Blockly.BlockSvg.SEP_SPACE_X/2,y:-12,height:16},this.fieldGroup_);this.textElement_=Blockly.createSvgElement("text",{"class":"blocklyText"},this.fieldGroup_);this.size_={height:25,width:0};this.setText(a);this.visible_=!0};Blockly.Field.prototype.clone=function(){goog.asserts.fail("There should never be an instance of Field, only its derived classes.")};
Blockly.Field.NBSP="\u00a0";Blockly.Field.prototype.EDITABLE=!0;Blockly.Field.prototype.init=function(a){if(this.sourceBlock_)throw"Field has already been initialized once.";this.sourceBlock_=a;this.updateEditable();a.getSvgRoot().appendChild(this.fieldGroup_);this.mouseUpWrapper_=Blockly.bindEvent_(this.fieldGroup_,"mouseup",this,this.onMouseUp_);this.setText(null)};
@@ -851,8 +851,8 @@ Blockly.Warning.prototype.textToDom_=function(a){var b=Blockly.createSvgElement(
Blockly.Warning.prototype.setVisible=function(a){if(a!=this.isVisible())if(a){a=this.textToDom_(this.text_);this.bubble_=new Blockly.Bubble(this.block_.workspace,a,this.block_.svg_.svgGroup_,this.iconX_,this.iconY_,null,null);if(Blockly.RTL)for(var b=a.getBBox().width,c=0,d;d=a.childNodes[c];c++)d.setAttribute("text-anchor","end"),d.setAttribute("x",b+Blockly.Bubble.BORDER_WIDTH);this.updateColour();a=this.bubble_.getBubbleSize();this.bubble_.setBubbleSize(a.width,a.height)}else this.bubble_.dispose(),
this.foreignObject_=this.body_=this.bubble_=null};Blockly.Warning.prototype.bodyFocus_=function(a){this.bubble_.promote_()};Blockly.Warning.prototype.setText=function(a){this.text_=a;this.isVisible()&&(this.setVisible(!1),this.setVisible(!0))};Blockly.Warning.prototype.dispose=function(){this.block_.warning=null;Blockly.Icon.prototype.dispose.call(this)};
// Copyright 2011 Google Inc. Apache License 2.0
Blockly.uidCounter_=0;Blockly.getUidCounter=function(){return Blockly.uidCounter_};Blockly.setUidCounter=function(a){Blockly.uidCounter_=a};Blockly.Block=function(){goog.asserts.assert(0==arguments.length,"Please use Blockly.Block.obtain.")};Blockly.Block.obtain=function(a,b){if(Blockly.Realtime.isEnabled())return Blockly.Realtime.obtainBlock(a,b);var c=new Blockly.Block;c.initialize(a,b);return c};
Blockly.Block.prototype.initialize=function(a,b){this.id=++Blockly.uidCounter_;a.addTopBlock(this);this.fill(a,b);goog.isFunction(this.onchange)&&Blockly.bindEvent_(a.getCanvas(),"blocklyWorkspaceChange",this,this.onchange)};
Blockly.uidCounter_=0;Blockly.getUidCounter=function(){return Blockly.uidCounter_};Blockly.setUidCounter=function(a){Blockly.uidCounter_=a};Blockly.genUid=function(){var a=(++Blockly.uidCounter_).toString();return Blockly.Realtime.isEnabled()?Blockly.Realtime.genUid(a):a};Blockly.Block=function(){goog.asserts.assert(0==arguments.length,"Please use Blockly.Block.obtain.")};
Blockly.Block.obtain=function(a,b){if(Blockly.Realtime.isEnabled())return Blockly.Realtime.obtainBlock(a,b);var c=new Blockly.Block;c.initialize(a,b);return c};Blockly.Block.prototype.initialize=function(a,b){this.id=Blockly.genUid();a.addTopBlock(this);this.fill(a,b);goog.isFunction(this.onchange)&&Blockly.bindEvent_(a.getCanvas(),"blocklyWorkspaceChange",this,this.onchange)};
Blockly.Block.prototype.fill=function(a,b){this.previousConnection=this.nextConnection=this.outputConnection=null;this.inputList=[];this.disabled=this.rendered=this.inputsInline=!1;this.tooltip="";this.contextMenu=!0;this.parentBlock_=null;this.childBlocks_=[];this.editable_=this.movable_=this.deletable_=!0;this.collapsed_=!1;this.workspace=a;this.isInFlyout=a.isFlyout;if(b){this.type=b;var c=Blockly.Blocks[b];goog.asserts.assertObject(c,'Error: "%s" is an unknown language block.',b);goog.mixin(this,
c)}goog.isFunction(this.init)&&this.init()};Blockly.Block.getById=function(a,b){return Blockly.Realtime.isEnabled()?Blockly.Realtime.getBlockById(a):b.getBlockById(a)};Blockly.Block.prototype.svg_=null;Blockly.Block.prototype.mutator=null;Blockly.Block.prototype.comment=null;Blockly.Block.prototype.warning=null;Blockly.Block.prototype.getIcons=function(){var a=[];this.mutator&&a.push(this.mutator);this.comment&&a.push(this.comment);this.warning&&a.push(this.warning);return a};
Blockly.Block.prototype.initSvg=function(){this.svg_=new Blockly.BlockSvg(this);this.svg_.init();Blockly.readOnly||Blockly.bindEvent_(this.svg_.getRootElement(),"mousedown",this,this.onMouseDown_);this.workspace.getCanvas().appendChild(this.svg_.getRootElement())};Blockly.Block.prototype.getSvgRoot=function(){return this.svg_&&this.svg_.getRootElement()};Blockly.Block.dragMode_=0;Blockly.Block.onMouseUpWrapper_=null;Blockly.Block.onMouseMoveWrapper_=null;
@@ -867,8 +867,8 @@ Blockly.Block.prototype.moveBy=function(a,b){var c=this.getRelativeToSurfaceXY()
Blockly.Block.prototype.getHeightWidth=function(){try{var a=this.getSvgRoot().getBBox(),b=a.height}catch(c){return{height:0,width:0}}Blockly.BROKEN_CONTROL_POINTS&&(b-=10,this.nextConnection&&(b+=4));return{height:b-1,width:a.width}};
Blockly.Block.prototype.onMouseDown_=function(a){if(!this.isInFlyout){Blockly.svgResize();Blockly.terminateDrag_();this.select();Blockly.hideChaff();if(Blockly.isRightButton(a))Blockly.ContextMenu&&this.showContextMenu_(Blockly.mouseToSvg(a));else if(this.isMovable()){Blockly.removeAllRanges();Blockly.setCursorHand_(!0);var b=this.getRelativeToSurfaceXY();this.startDragX=b.x;this.startDragY=b.y;this.startDragMouseX=a.clientX;this.startDragMouseY=a.clientY;Blockly.Block.dragMode_=1;Blockly.Block.onMouseUpWrapper_=
Blockly.bindEvent_(document,"mouseup",this,this.onMouseUp_);Blockly.Block.onMouseMoveWrapper_=Blockly.bindEvent_(document,"mousemove",this,this.onMouseMove_);this.draggedBubbles_=[];for(var b=this.getDescendants(),c=0,d;d=b[c];c++){d=d.getIcons();for(var e=0;e<d.length;e++){var f=d[e].getIconLocation();f.bubble=d[e];this.draggedBubbles_.push(f)}}}else return;a.stopPropagation()}};
Blockly.Block.prototype.onMouseUp_=function(a){Blockly.terminateDrag_();Blockly.selected&&Blockly.highlightedConnection_?(Blockly.localConnection_.connect(Blockly.highlightedConnection_),this.svg_&&(Blockly.localConnection_.isSuperior()?Blockly.highlightedConnection_:Blockly.localConnection_).sourceBlock_.svg_.connectionUiEffect(),this.workspace.trashcan&&this.workspace.trashcan.isOpen&&this.workspace.trashcan.close()):this.workspace.trashcan&&this.workspace.trashcan.isOpen&&(a=this.workspace.trashcan,
goog.Timer.callOnce(a.close,100,a),Blockly.selected.dispose(!1,!0),Blockly.fireUiEvent(window,"resize"));Blockly.highlightedConnection_&&(Blockly.highlightedConnection_.unhighlight(),Blockly.highlightedConnection_=null)};Blockly.Block.prototype.showHelp_=function(){var a=goog.isFunction(this.helpUrl)?this.helpUrl():this.helpUrl;a&&window.open(a)};
Blockly.Block.prototype.onMouseUp_=function(a){var b=this;Blockly.doCommand(function(){Blockly.terminateDrag_();if(Blockly.selected&&Blockly.highlightedConnection_)Blockly.localConnection_.connect(Blockly.highlightedConnection_),b.svg_&&(Blockly.localConnection_.isSuperior()?Blockly.highlightedConnection_:Blockly.localConnection_).sourceBlock_.svg_.connectionUiEffect(),b.workspace.trashcan&&b.workspace.trashcan.isOpen&&b.workspace.trashcan.close();else if(b.workspace.trashcan&&b.workspace.trashcan.isOpen){var a=
b.workspace.trashcan;goog.Timer.callOnce(a.close,100,a);Blockly.selected.dispose(!1,!0);Blockly.fireUiEvent(window,"resize")}Blockly.highlightedConnection_&&(Blockly.highlightedConnection_.unhighlight(),Blockly.highlightedConnection_=null)})};Blockly.Block.prototype.showHelp_=function(){var a=goog.isFunction(this.helpUrl)?this.helpUrl():this.helpUrl;a&&window.open(a)};
Blockly.Block.prototype.duplicate_=function(){var a=Blockly.Xml.blockToDom_(this);Blockly.Xml.deleteNext(a);var a=Blockly.Xml.domToBlock(this.workspace,a),b=this.getRelativeToSurfaceXY();b.x=Blockly.RTL?b.x-Blockly.SNAP_RADIUS:b.x+Blockly.SNAP_RADIUS;b.y+=2*Blockly.SNAP_RADIUS;a.moveBy(b.x,b.y);return a};
Blockly.Block.prototype.showContextMenu_=function(a){if(!Blockly.readOnly&&this.contextMenu){var b=this,c=[];if(this.isDeletable()&&!b.isInFlyout){var d={text:Blockly.Msg.DUPLICATE_BLOCK,enabled:!0,callback:function(){b.duplicate_()}};this.getDescendants().length>this.workspace.remainingCapacity()&&(d.enabled=!1);c.push(d);this.isEditable()&&!this.collapsed_&&(d={enabled:!0},this.comment?(d.text=Blockly.Msg.REMOVE_COMMENT,d.callback=function(){b.setCommentText(null)}):(d.text=Blockly.Msg.ADD_COMMENT,
d.callback=function(){b.setCommentText("")}),c.push(d));if(!this.collapsed_)for(d=0;d<this.inputList.length;d++)if(this.inputList[d].type==Blockly.INPUT_VALUE){d={enabled:!0};d.text=this.inputsInline?Blockly.Msg.EXTERNAL_INPUTS:Blockly.Msg.INLINE_INPUTS;d.callback=function(){b.setInputsInline(!b.inputsInline)};c.push(d);break}Blockly.collapse&&(this.collapsed_?(d={enabled:!0},d.text=Blockly.Msg.EXPAND_BLOCK,d.callback=function(){b.setCollapsed(!1)}):(d={enabled:!0},d.text=Blockly.Msg.COLLAPSE_BLOCK,
@@ -876,9 +876,9 @@ d.callback=function(){b.setCollapsed(!0)}),c.push(d));d={text:this.disabled?Bloc
c.push(d)}d={enabled:!(goog.isFunction(this.helpUrl)?!this.helpUrl():!this.helpUrl)};d.text=Blockly.Msg.HELP;d.callback=function(){b.showHelp_()};c.push(d);this.customContextMenu&&!b.isInFlyout&&this.customContextMenu(c);Blockly.ContextMenu.show(a,c)}};
Blockly.Block.prototype.getConnections_=function(a){var b=[];if(a||this.rendered)if(this.outputConnection&&b.push(this.outputConnection),this.nextConnection&&b.push(this.nextConnection),this.previousConnection&&b.push(this.previousConnection),a||!this.collapsed_){a=0;for(var c;c=this.inputList[a];a++)c.connection&&b.push(c.connection)}return b};
Blockly.Block.prototype.moveConnections_=function(a,b){if(this.rendered){for(var c=this.getConnections_(!1),d=0;d<c.length;d++)c[d].moveBy(a,b);c=this.getIcons();for(d=0;d<c.length;d++)c[d].computeIconLocation();for(d=0;d<this.childBlocks_.length;d++)this.childBlocks_[d].moveConnections_(a,b)}};Blockly.Block.prototype.setDragging_=function(a){a?this.svg_.addDragging():this.svg_.removeDragging();for(var b=0;b<this.childBlocks_.length;b++)this.childBlocks_[b].setDragging_(a)};
Blockly.Block.prototype.onMouseMove_=function(a){if(!("mousemove"==a.type&&1>=a.clientX&&0==a.clientY&&0==a.button)){Blockly.removeAllRanges();var b=a.clientX-this.startDragMouseX,c=a.clientY-this.startDragMouseY;1==Blockly.Block.dragMode_&&Math.sqrt(Math.pow(b,2)+Math.pow(c,2))>Blockly.DRAG_RADIUS&&(Blockly.Block.dragMode_=2,this.setParent(null),this.setDragging_(!0));if(2==Blockly.Block.dragMode_){var d=this.startDragX+b,e=this.startDragY+c;this.svg_.getRootElement().setAttribute("transform","translate("+
d+", "+e+")");for(d=0;d<this.draggedBubbles_.length;d++)e=this.draggedBubbles_[d],e.bubble.setIconLocation(e.x+b,e.y+c);for(var e=this.getConnections_(!1),f=null,g=null,h=Blockly.SNAP_RADIUS,d=0;d<e.length;d++){var k=e[d],l=k.closest(h,b,c);l.connection&&(f=l.connection,g=k,h=l.radius)}Blockly.highlightedConnection_&&Blockly.highlightedConnection_!=f&&(Blockly.highlightedConnection_.unhighlight(),Blockly.highlightedConnection_=null,Blockly.localConnection_=null);f&&f!=Blockly.highlightedConnection_&&
(f.highlight(),Blockly.highlightedConnection_=f,Blockly.localConnection_=g);if(this.workspace.trashcan&&this.isDeletable())this.workspace.trashcan.onMouseMove(a)}}a.stopPropagation()};
Blockly.Block.prototype.onMouseMove_=function(a){var b=this;Blockly.doCommand(function(){if(!("mousemove"==a.type&&1>=a.clientX&&0==a.clientY&&0==a.button)){Blockly.removeAllRanges();var c=a.clientX-b.startDragMouseX,d=a.clientY-b.startDragMouseY;1==Blockly.Block.dragMode_&&Math.sqrt(Math.pow(c,2)+Math.pow(d,2))>Blockly.DRAG_RADIUS&&(Blockly.Block.dragMode_=2,b.setParent(null),b.setDragging_(!0));if(2==Blockly.Block.dragMode_){var e=b.startDragX+c,f=b.startDragY+d;b.svg_.getRootElement().setAttribute("transform",
"translate("+e+", "+f+")");for(e=0;e<b.draggedBubbles_.length;e++)f=b.draggedBubbles_[e],f.bubble.setIconLocation(f.x+c,f.y+d);for(var f=b.getConnections_(!1),g=null,h=null,k=Blockly.SNAP_RADIUS,e=0;e<f.length;e++){var l=f[e],q=l.closest(k,c,d);q.connection&&(g=q.connection,h=l,k=q.radius)}Blockly.highlightedConnection_&&Blockly.highlightedConnection_!=g&&(Blockly.highlightedConnection_.unhighlight(),Blockly.highlightedConnection_=null,Blockly.localConnection_=null);g&&g!=Blockly.highlightedConnection_&&
(g.highlight(),Blockly.highlightedConnection_=g,Blockly.localConnection_=h);if(b.workspace.trashcan&&b.isDeletable())b.workspace.trashcan.onMouseMove(a)}}a.stopPropagation()})};
Blockly.Block.prototype.bumpNeighbours_=function(){if(0==Blockly.Block.dragMode_){var a=this.getRootBlock();if(!a.isInFlyout)for(var b=this.getConnections_(!1),c=0;c<b.length;c++){var d=b[c];d.targetConnection&&d.isSuperior()&&d.targetBlock().bumpNeighbours_();for(var e=d.neighbours_(Blockly.SNAP_RADIUS),f=0;f<e.length;f++){var g=e[f];d.targetConnection&&g.targetConnection||g.sourceBlock_.getRootBlock()!=a&&(d.isSuperior()?g.bumpAwayFrom_(d):d.bumpAwayFrom_(g))}}}};
Blockly.Block.prototype.getParent=function(){return this.parentBlock_};Blockly.Block.prototype.getSurroundParent=function(){for(var a=this;;){do{var b=a,a=a.getParent();if(!a)return null}while(a.nextConnection&&a.nextConnection.targetBlock()==b);return a}};Blockly.Block.prototype.getRootBlock=function(){var a,b=this;do a=b,b=a.parentBlock_;while(b);return a};Blockly.Block.prototype.getChildren=function(){return this.childBlocks_};
Blockly.Block.prototype.setParent=function(a){if(this.parentBlock_){for(var b=this.parentBlock_.childBlocks_,c,d=0;c=b[d];d++)if(c==this){b.splice(d,1);break}b=this.getRelativeToSurfaceXY();this.workspace.getCanvas().appendChild(this.svg_.getRootElement());this.svg_.getRootElement().setAttribute("transform","translate("+b.x+", "+b.y+")");this.parentBlock_=null;this.previousConnection&&this.previousConnection.targetConnection&&this.previousConnection.disconnect();this.outputConnection&&this.outputConnection.targetConnection&&
@@ -1042,26 +1042,27 @@ rtclient.RealtimeLoader.prototype.handleErrors=function(a){a.type==gapi.drive.re
rtclient.RealtimeLoader.prototype.load=function(){var a=rtclient.params.fileIds;a&&(a=a.split(","));var b=this.authorizer.userId,b=rtclient.params.state;if(a)for(var c in a)gapi.drive.realtime.load(a[c],this.onFileLoaded,this.initializeModel,this.handleErrors);else{if(b&&(c=rtclient.parseState(b),"open"==c.action)){a=c.ids;b=c.userId;this.redirectTo(a,b);return}this.autoCreate&&this.createNewFileAndRedirect()}};
rtclient.RealtimeLoader.prototype.createNewFileAndRedirect=function(){var a=this;rtclient.createRealtimeFile(this.defaultTitle,this.newFileMimeType,function(b){b.id?(a.afterCreate&&a.afterCreate(b.id),a.redirectTo([b.id],a.authorizer.userId)):(console.error("Error creating file."),console.error(b))})};
// Copyright 2014 Google Inc. Apache License 2.0
Blockly.Realtime={};Blockly.Realtime.enabled_=!1;Blockly.Realtime.model_=null;Blockly.Realtime.initUi_=null;Blockly.Realtime.blocksMap_=null;Blockly.Realtime.withinSync=!1;Blockly.Realtime.realtimeLoader_=null;Blockly.Realtime.chatBoxElementId_=null;Blockly.Realtime.chatBoxInitialText_=null;Blockly.Realtime.isEnabled=function(){return Blockly.Realtime.enabled_};
Blockly.Realtime.initializeModel_=function(a){Blockly.Realtime.model_=a;var b=a.createMap();a.getRoot().set("blocks",b);b=a.createList();a.getRoot().set("topBlocks",b);Blockly.Realtime.chatBoxElementId_&&a.getRoot().set(Blockly.Realtime.chatBoxElementId_,a.createString(Blockly.Realtime.chatBoxInitialText_))};Blockly.Realtime.removeBlock=function(a){Blockly.Realtime.blocksMap_["delete"](a.id.toString())};Blockly.Realtime.addTopBlock=function(a){-1==Blockly.Realtime.topBlocks_.indexOf(a)&&Blockly.Realtime.topBlocks_.push(a)};
Blockly.Realtime.removeTopBlock=function(a){Blockly.Realtime.topBlocks_.removeValue(a)};Blockly.Realtime.obtainBlock=function(a,b){return Blockly.Realtime.model_.create(Blockly.Block,a,b)};Blockly.Realtime.getBlockById=function(a){return Blockly.Realtime.blocksMap_.get(a)};
Blockly.Realtime.onObjectChange_=function(a){var b=a.events;a=a.events.length;for(var c=0;c<a;c++){var d=b[c];if(!d.isLocal&&"value_changed"==d.type)if("xmlDom"==d.property){var e=d.target;Blockly.Realtime.doWithinSync_(function(){Blockly.Realtime.placeBlockOnWorkspace_(e,!1);Blockly.Realtime.moveBlock_(e)})}else if("relativeX"==d.property||"relativeY"==d.property){var f=d.target;Blockly.Realtime.doWithinSync_(function(){f.svg_||Blockly.Realtime.placeBlockOnWorkspace_(f,!1);Blockly.Realtime.moveBlock_(f)})}}};
Blockly.Realtime.onBlocksMapChange_=function(a){console.log("Blocks Map event:");console.log(" id: "+a.property);if(!a.isLocal){var b=a.newValue;b?Blockly.Realtime.placeBlockOnWorkspace_(b,!a.oldValue):(b=a.oldValue,Blockly.Realtime.deleteBlock(b))}};Blockly.Realtime.doWithinSync_=function(a){if(Blockly.Realtime.withinSync)a();else try{Blockly.Realtime.withinSync=!0,a()}finally{Blockly.Realtime.withinSync=!1}};
Blockly.Realtime={};Blockly.Realtime.enabled_=!1;Blockly.Realtime.document_=null;Blockly.Realtime.model_=null;Blockly.Realtime.sessionId_=null;Blockly.Realtime.initUi_=null;Blockly.Realtime.blocksMap_=null;Blockly.Realtime.withinSync=!1;Blockly.Realtime.realtimeLoader_=null;Blockly.Realtime.chatBoxElementId_=null;Blockly.Realtime.chatBoxInitialText_=null;Blockly.Realtime.withinUndo_=!1;Blockly.Realtime.isEnabled=function(){return Blockly.Realtime.enabled_};Blockly.Realtime.undoElementId_=null;
Blockly.Realtime.redoElementId_=null;Blockly.Realtime.initializeModel_=function(a){Blockly.Realtime.model_=a;var b=a.createMap();a.getRoot().set("blocks",b);b=a.createList();a.getRoot().set("topBlocks",b);Blockly.Realtime.chatBoxElementId_&&a.getRoot().set(Blockly.Realtime.chatBoxElementId_,a.createString(Blockly.Realtime.chatBoxInitialText_))};Blockly.Realtime.removeBlock=function(a){Blockly.Realtime.blocksMap_["delete"](a.id.toString())};
Blockly.Realtime.addTopBlock=function(a){-1==Blockly.Realtime.topBlocks_.indexOf(a)&&Blockly.Realtime.topBlocks_.push(a)};Blockly.Realtime.removeTopBlock=function(a){Blockly.Realtime.topBlocks_.removeValue(a)};Blockly.Realtime.obtainBlock=function(a,b){return Blockly.Realtime.model_.create(Blockly.Block,a,b)};Blockly.Realtime.getBlockById=function(a){return Blockly.Realtime.blocksMap_.get(a)};
Blockly.Realtime.logEvent_=function(a){console.log("Object event:");console.log(" id: "+a.target.id);console.log(" type: "+a.type);if(a=a.events)for(var b=a.length,c=0;c<b;c++){var d=a[c];console.log(" child event:");console.log(" id: "+d.target.id);console.log(" type: "+d.type)}};
Blockly.Realtime.onObjectChange_=function(a){Blockly.Realtime.logEvent_(a);var b=a.events;a=a.events.length;for(var c=0;c<a;c++){var d=b[c];if(!d.isLocal||Blockly.Realtime.withinUndo_){var e=d.target;"value_changed"==d.type&&("xmlDom"==d.property?Blockly.Realtime.doWithinSync_(function(){Blockly.Realtime.placeBlockOnWorkspace_(e,!1);Blockly.Realtime.moveBlock_(e)}):"relativeX"!=d.property&&"relativeY"!=d.property||Blockly.Realtime.doWithinSync_(function(){e.svg_||Blockly.Realtime.placeBlockOnWorkspace_(e,
!1);Blockly.Realtime.moveBlock_(e)}))}}};Blockly.Realtime.onBlocksMapChange_=function(a){Blockly.Realtime.logEvent_(a);if(!a.isLocal||Blockly.Realtime.withinUndo_){var b=a.newValue;b?Blockly.Realtime.placeBlockOnWorkspace_(b,!a.oldValue):(b=a.oldValue,Blockly.Realtime.deleteBlock(b))}};Blockly.Realtime.doWithinSync_=function(a){if(Blockly.Realtime.withinSync)a();else try{Blockly.Realtime.withinSync=!0,a()}finally{Blockly.Realtime.withinSync=!1}};
Blockly.Realtime.placeBlockOnWorkspace_=function(a,b){Blockly.Realtime.doWithinSync_(function(){var c=Blockly.Xml.textToDom(a.xmlDom).firstChild;if(c=Blockly.Xml.domToBlock(Blockly.mainWorkspace,c,!0))b&&c.workspace.addTopBlock(c),(b||goog.array.contains(Blockly.Realtime.topBlocks_,c))&&Blockly.Realtime.moveBlock_(c)})};
Blockly.Realtime.moveBlock_=function(a){if(!isNaN(a.relativeX)&&!isNaN(a.relativeY)){var b=Blockly.svgSize().width,c=a.getRelativeToSurfaceXY(),d=a.relativeX-c.x;a.moveBy(Blockly.RTL?b-d:d,a.relativeY-c.y)}};Blockly.Realtime.deleteBlock=function(a){Blockly.Realtime.doWithinSync_(function(){a.dispose(!0,!0,!0)})};
Blockly.Realtime.loadBlocks_=function(){for(var a=Blockly.Realtime.blocksMap_.values(),b=0;b<a.length;b++){var c=parseInt(a[b].id,10);c>Blockly.getUidCounter()&&Blockly.setUidCounter(c+1)}a=Blockly.Realtime.topBlocks_;for(b=0;b<a.length;b++)c=a.get(b),Blockly.Realtime.placeBlockOnWorkspace_(c,!0)};
Blockly.Realtime.moveBlock_=function(a){if(!isNaN(a.relativeX)&&!isNaN(a.relativeY)){var b=Blockly.svgSize().width,c=a.getRelativeToSurfaceXY(),d=a.relativeX-c.x;a.moveBy(Blockly.RTL?b-d:d,a.relativeY-c.y)}};Blockly.Realtime.deleteBlock=function(a){Blockly.Realtime.doWithinSync_(function(){a.dispose(!0,!0,!0)})};Blockly.Realtime.loadBlocks_=function(){for(var a=Blockly.Realtime.topBlocks_,b=0;b<a.length;b++){var c=a.get(b);Blockly.Realtime.placeBlockOnWorkspace_(c,!0)}};
Blockly.Realtime.blockChanged=function(a){if(a.workspace==Blockly.mainWorkspace){a=a.getRootBlock();var b=a.getRelativeToSurfaceXY(),c=!1,d=Blockly.Xml.blockToDom_(a);d.setAttribute("id",a.id);var e=goog.dom.createDom("xml");e.appendChild(d);d=Blockly.Xml.domToText(e);d!=a.xmlDom&&(c=!0,a.xmlDom=d);if(a.relativeX!=b.x||a.relativeY!=b.y)a.relativeX=b.x,a.relativeY=b.y,c=!0;c&&Blockly.Realtime.blocksMap_.set(a.id.toString(),a)}};
Blockly.Realtime.onFileLoaded_=function(a){Blockly.Realtime.model_=a.getModel();Blockly.Realtime.blocksMap_=Blockly.Realtime.model_.getRoot().get("blocks");Blockly.Realtime.topBlocks_=Blockly.Realtime.model_.getRoot().get("topBlocks");Blockly.Realtime.model_.getRoot().addEventListener(gapi.drive.realtime.EventType.OBJECT_CHANGED,Blockly.Realtime.onObjectChange_);Blockly.Realtime.blocksMap_.addEventListener(gapi.drive.realtime.EventType.VALUE_CHANGED,Blockly.Realtime.onBlocksMapChange_);Blockly.Realtime.initUi_();
Blockly.Realtime.loadBlocks_()};Blockly.Realtime.registerTypes_=function(){var a=gapi.drive.realtime.custom;a.registerType(Blockly.Block,"Block");Blockly.Block.prototype.id=a.collaborativeField("id");Blockly.Block.prototype.type=a.collaborativeField("type");Blockly.Block.prototype.xmlDom=a.collaborativeField("xmlDom");Blockly.Block.prototype.relativeX=a.collaborativeField("relativeX");Blockly.Block.prototype.relativeY=a.collaborativeField("relativeY");a.setInitializer(Blockly.Block,Blockly.Block.prototype.initialize)};
Blockly.Realtime.REAUTH_INTERVAL_IN_MILLISECONDS_=18E5;Blockly.Realtime.afterAuth_=function(){window.setTimeout(function(){Blockly.Realtime.realtimeLoader_.authorizer.authorize(Blockly.Realtime.afterAuth_)},Blockly.Realtime.REAUTH_INTERVAL_IN_MILLISECONDS_)};
Blockly.Realtime.onFileLoaded_=function(a){Blockly.Realtime.document_=a;Blockly.Realtime.sessionId_=Blockly.Realtime.getSessionId_(a);Blockly.Realtime.model_=a.getModel();Blockly.Realtime.blocksMap_=Blockly.Realtime.model_.getRoot().get("blocks");Blockly.Realtime.topBlocks_=Blockly.Realtime.model_.getRoot().get("topBlocks");Blockly.Realtime.model_.getRoot().addEventListener(gapi.drive.realtime.EventType.OBJECT_CHANGED,Blockly.Realtime.onObjectChange_);Blockly.Realtime.blocksMap_.addEventListener(gapi.drive.realtime.EventType.VALUE_CHANGED,
Blockly.Realtime.onBlocksMapChange_);Blockly.Realtime.initUi_();Blockly.Realtime.loadBlocks_()};Blockly.Realtime.getSessionId_=function(a){a=a.getCollaborators();for(var b=0;b<a.length;b++){var c=a[b];if(c.isMe)return c.sessionId}};
Blockly.Realtime.registerTypes_=function(){var a=gapi.drive.realtime.custom;a.registerType(Blockly.Block,"Block");Blockly.Block.prototype.id=a.collaborativeField("id");Blockly.Block.prototype.xmlDom=a.collaborativeField("xmlDom");Blockly.Block.prototype.relativeX=a.collaborativeField("relativeX");Blockly.Block.prototype.relativeY=a.collaborativeField("relativeY");a.setInitializer(Blockly.Block,Blockly.Block.prototype.initialize)};Blockly.Realtime.REAUTH_INTERVAL_IN_MILLISECONDS_=18E5;
Blockly.Realtime.afterAuth_=function(){window.setTimeout(function(){Blockly.Realtime.realtimeLoader_.authorizer.authorize(Blockly.Realtime.afterAuth_)},Blockly.Realtime.REAUTH_INTERVAL_IN_MILLISECONDS_)};
Blockly.Realtime.afterCreate_=function(a){var b=gapi.client.drive.permissions.insert({fileId:a,resource:{type:"anyone",role:"writer",value:"default",withLink:!0}});b.execute(function(c){c.error&&Blockly.Realtime.getUserDomain(a,function(c){b=gapi.client.drive.permissions.insert({fileId:a,resource:{type:"domain",role:"writer",value:c,withLink:!0}});b.execute(function(a){})})})};
Blockly.Realtime.getUserDomain=function(a,b){gapi.client.drive.permissions.list({fileId:a}).execute(function(a){for(var d=0;d<a.items.length;d++){var e=a.items[d];if("owner"==e.role){b(e.domain);break}}})};
Blockly.Realtime.realtimeOptions_={clientId:"INSERT YOUR CLIENT ID HERE",authButtonElementId:"authorizeButton",authDivElementId:"authButtonDiv",initializeModel:Blockly.Realtime.initializeModel_,autoCreate:!0,defaultTitle:"New Realtime Blockly File",newFileMimeType:null,onFileLoaded:Blockly.Realtime.onFileLoaded_,registerTypes:Blockly.Realtime.registerTypes_,afterAuth:Blockly.Realtime.afterAuth_,afterCreate:Blockly.Realtime.afterCreate_};
Blockly.Realtime.parseOptions_=function(a){if(a=rtclient.getOption(a,"chatbox"))Blockly.Realtime.chatBoxElementId_=rtclient.getOption(a,"elementId"),Blockly.Realtime.chatBoxInitialText_=rtclient.getOption(a,"initText",Blockly.Msg.CHAT)};
Blockly.Realtime.startRealtime=function(a,b,c){Blockly.Realtime.parseOptions_(c);Blockly.Realtime.enabled_=!0;Blockly.Realtime.addAuthUi_(b);Blockly.Realtime.initUi_=function(){a();if(Blockly.Realtime.chatBoxElementId_){var b=Blockly.Realtime.model_.getRoot().get(Blockly.Realtime.chatBoxElementId_),c=document.getElementById(Blockly.Realtime.chatBoxElementId_);gapi.drive.realtime.databinding.bindString(b,c);c.disabled=!1}};Blockly.Realtime.realtimeLoader_=new rtclient.RealtimeLoader(Blockly.Realtime.realtimeOptions_);
Blockly.Realtime.rtclientOptions_={clientId:null,authButtonElementId:"authorizeButton",authDivElementId:"authButtonDiv",initializeModel:Blockly.Realtime.initializeModel_,autoCreate:!0,defaultTitle:"New Realtime Blockly File",newFileMimeType:null,onFileLoaded:Blockly.Realtime.onFileLoaded_,registerTypes:Blockly.Realtime.registerTypes_,afterAuth:Blockly.Realtime.afterAuth_,afterCreate:Blockly.Realtime.afterCreate_};
Blockly.Realtime.parseOptions_=function(a){var b=rtclient.getOption(a,"chatbox");b&&(Blockly.Realtime.chatBoxElementId_=rtclient.getOption(b,"elementId"),Blockly.Realtime.chatBoxInitialText_=rtclient.getOption(b,"initText",Blockly.Msg.CHAT));Blockly.Realtime.rtclientOptions_.clientId=rtclient.getOption(a,"clientId")};
Blockly.Realtime.startRealtime=function(a,b,c){Blockly.Realtime.parseOptions_(c);Blockly.Realtime.enabled_=!0;Blockly.Realtime.addAuthUi_(b);Blockly.Realtime.initUi_=function(){a();if(Blockly.Realtime.chatBoxElementId_){var b=Blockly.Realtime.model_.getRoot().get(Blockly.Realtime.chatBoxElementId_),c=document.getElementById(Blockly.Realtime.chatBoxElementId_);gapi.drive.realtime.databinding.bindString(b,c);c.disabled=!1}};Blockly.Realtime.realtimeLoader_=new rtclient.RealtimeLoader(Blockly.Realtime.rtclientOptions_);
Blockly.Realtime.realtimeLoader_.start()};
Blockly.Realtime.addAuthUi_=function(a){var b=goog.style.getBounds(a),c=goog.dom.createDom("div");c.id="authButtonDiv";var d=goog.dom.createDom("p",null,Blockly.Msg.AUTH);c.appendChild(d);d=goog.dom.createDom("button",null,"Authorize");d.id=Blockly.Realtime.realtimeOptions_.authButtonElementId;c.appendChild(d);a.appendChild(c);c.style.display="none";c.style.position="relative";c.style.textAlign="center";c.style.border="1px solid";c.style.backgroundColor="#f6f9ff";c.style.borderRadius="15px";c.style.boxShadow=
"10px 10px 5px #888";c.style.width=b.width/3+"px";a=goog.style.getBounds(c);c.style.left=(b.width-a.width)/3+"px";c.style.top=(b.height-a.height)/4+"px";return c};
Blockly.Realtime.addAuthUi_=function(a){var b=goog.style.getBounds(a),c=goog.dom.createDom("div");c.id="authButtonDiv";var d=goog.dom.createDom("p",null,Blockly.Msg.AUTH);c.appendChild(d);d=goog.dom.createDom("button",null,"Authorize");d.id=Blockly.Realtime.rtclientOptions_.authButtonElementId;c.appendChild(d);a.appendChild(c);c.style.display="none";c.style.position="relative";c.style.textAlign="center";c.style.border="1px solid";c.style.backgroundColor="#f6f9ff";c.style.borderRadius="15px";c.style.boxShadow=
"10px 10px 5px #888";c.style.width=b.width/3+"px";a=goog.style.getBounds(c);c.style.left=(b.width-a.width)/3+"px";c.style.top=(b.height-a.height)/4+"px";return c};Blockly.Realtime.doCommand=function(a){a()};Blockly.Realtime.genUid=function(a){var b=Blockly.Realtime.sessionId_+"-"+a;return Blockly.Realtime.blocksMap_.has(b)?Blockly.Realtime.genUid("-"+a):b};
// Copyright 2013 Google Inc. Apache License 2.0
Blockly.Css={};Blockly.Css.inject=function(){var a=Blockly.Css.CONTENT.join("\n"),b=Blockly.pathToBlockly.replace(/[\\\/]$/,""),a=a.replace(/<<<PATH>>>/g,b);goog.cssom.addCssText(a)};
Blockly.Css.CONTENT=[".blocklySvg {"," background-color: #fff;"," border: 1px solid #ddd;","}",".blocklyWidgetDiv {"," position: absolute;"," display: none;"," z-index: 999;","}",".blocklyDraggable {"," /* Hotspot coordinates are baked into the CUR file, but they are still"," required in the CSS due to a Chrome bug."," http://code.google.com/p/chromium/issues/detail?id=1446 */"," cursor: url(<<<PATH>>>/media/handopen.cur) 8 5, auto;","}",".blocklyResizeSE {"," fill: #aaa;"," cursor: se-resize;",
@@ -1125,4 +1126,5 @@ Blockly.setCursorHand_=function(a){if(!Blockly.readOnly){var b="";a&&(b="url("+B
Blockly.getMainWorkspaceMetrics_=function(){var a=Blockly.svgSize();a.width-=Blockly.Toolbox.width;var b=a.width-Blockly.Scrollbar.scrollbarThickness,c=a.height-Blockly.Scrollbar.scrollbarThickness;try{var d=Blockly.mainWorkspace.getCanvas().getBBox()}catch(e){return null}if(Blockly.mainWorkspace.scrollbar)var f=Math.min(d.x-b/2,d.x+d.width-b),b=Math.max(d.x+d.width+b/2,d.x+b),g=Math.min(d.y-c/2,d.y+d.height-c),c=Math.max(d.y+d.height+c/2,d.y+c);else f=d.x,b=f+d.width,g=d.y,c=g+d.height;return{viewHeight:a.height,
viewWidth:a.width,contentHeight:c-g,contentWidth:b-f,viewTop:-Blockly.mainWorkspace.scrollY,viewLeft:-Blockly.mainWorkspace.scrollX,contentTop:g,contentLeft:f,absoluteTop:0,absoluteLeft:Blockly.RTL?0:Blockly.Toolbox.width}};
Blockly.setMainWorkspaceMetrics_=function(a){if(!Blockly.mainWorkspace.scrollbar)throw"Attempt to set main workspace scroll without scrollbars.";var b=Blockly.getMainWorkspaceMetrics_();goog.isNumber(a.x)&&(Blockly.mainWorkspace.scrollX=-b.contentWidth*a.x-b.contentLeft);goog.isNumber(a.y)&&(Blockly.mainWorkspace.scrollY=-b.contentHeight*a.y-b.contentTop);a="translate("+(Blockly.mainWorkspace.scrollX+b.absoluteLeft)+","+(Blockly.mainWorkspace.scrollY+b.absoluteTop)+")";Blockly.mainWorkspace.getCanvas().setAttribute("transform",
a);Blockly.mainWorkspace.getBubbleCanvas().setAttribute("transform",a)};Blockly.addChangeListener=function(a){return Blockly.bindEvent_(Blockly.mainWorkspace.getCanvas(),"blocklyWorkspaceChange",null,a)};Blockly.removeChangeListener=function(a){Blockly.unbindEvent_(a)};Blockly.getMainWorkspace=function(){return Blockly.mainWorkspace};window.Blockly=Blockly;Blockly.getMainWorkspace=Blockly.getMainWorkspace;Blockly.addChangeListener=Blockly.addChangeListener;Blockly.removeChangeListener=Blockly.removeChangeListener;
a);Blockly.mainWorkspace.getBubbleCanvas().setAttribute("transform",a)};Blockly.doCommand=function(a){Blockly.Realtime.isEnabled?Blockly.Realtime.doCommand(a):a()};Blockly.addChangeListener=function(a){return Blockly.bindEvent_(Blockly.mainWorkspace.getCanvas(),"blocklyWorkspaceChange",null,a)};Blockly.removeChangeListener=function(a){Blockly.unbindEvent_(a)};Blockly.getMainWorkspace=function(){return Blockly.mainWorkspace};window.Blockly=Blockly;Blockly.getMainWorkspace=Blockly.getMainWorkspace;
Blockly.addChangeListener=Blockly.addChangeListener;Blockly.removeChangeListener=Blockly.removeChangeListener;

View File

@@ -24,9 +24,9 @@ if (!window.goog) {
// Build map of all dependencies (used and unused).
var dir = window.BLOCKLY_DIR.match(/[^\/]+$/)[0];
goog.addDependency("../../../" + dir + "/core/block.js", ['Blockly.Block'], ['Blockly.BlockSvg', 'Blockly.Blocks', 'Blockly.Comment', 'Blockly.Connection', 'Blockly.ContextMenu', 'Blockly.Input', 'Blockly.Msg', 'Blockly.Mutator', 'Blockly.Warning', 'Blockly.Workspace', 'Blockly.Xml', 'goog.asserts', 'goog.string', 'goog.Timer', 'goog.array']);
goog.addDependency("../../../" + dir + "/core/block.js", ['Blockly.Block'], ['Blockly.BlockSvg', 'Blockly.Blocks', 'Blockly.Comment', 'Blockly.Connection', 'Blockly.ContextMenu', 'Blockly.Input', 'Blockly.Msg', 'Blockly.Mutator', 'Blockly.Warning', 'Blockly.Workspace', 'Blockly.Xml', 'goog.Timer', 'goog.array', 'goog.asserts', 'goog.string']);
goog.addDependency("../../../" + dir + "/core/block_svg.js", ['Blockly.BlockSvg'], ['goog.userAgent']);
goog.addDependency("../../../" + dir + "/core/blockly.js", ['Blockly'], ['Blockly.Block', 'Blockly.Connection', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.Generator', 'Blockly.Msg', 'Blockly.Procedures', 'Blockly.Realtime', 'Blockly.Toolbox', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.inject', 'Blockly.utils', 'goog.dom', 'goog.color', 'goog.events', 'goog.string', 'goog.ui.ColorPicker', 'goog.ui.tree.TreeControl', 'goog.userAgent']);
goog.addDependency("../../../" + dir + "/core/blockly.js", ['Blockly'], ['Blockly.Block', 'Blockly.Connection', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.Generator', 'Blockly.Msg', 'Blockly.Procedures', 'Blockly.Realtime', 'Blockly.Toolbox', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.inject', 'Blockly.utils', 'goog.color', 'goog.dom', 'goog.events', 'goog.string', 'goog.ui.ColorPicker', 'goog.ui.tree.TreeControl', 'goog.userAgent']);
goog.addDependency("../../../" + dir + "/core/blocks.js", ['Blockly.Blocks'], ['goog.asserts']);
goog.addDependency("../../../" + dir + "/core/bubble.js", ['Blockly.Bubble'], ['Blockly.Workspace']);
goog.addDependency("../../../" + dir + "/core/comment.js", ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Icon']);

View File

@@ -37,10 +37,10 @@ goog.require('Blockly.Mutator');
goog.require('Blockly.Warning');
goog.require('Blockly.Workspace');
goog.require('Blockly.Xml');
goog.require('goog.asserts');
goog.require('goog.string');
goog.require('goog.Timer');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.string');
/**
@@ -51,11 +51,11 @@ Blockly.uidCounter_ = 0;
/**
* Get the Blockly.uidCounter_
* @returns {number}
* @return {number}
*/
Blockly.getUidCounter = function() {
return Blockly.uidCounter_;
}
};
/**
* Set the Blockly.uidCounter_
@@ -63,7 +63,21 @@ Blockly.getUidCounter = function() {
*/
Blockly.setUidCounter = function(val) {
Blockly.uidCounter_ = val;
}
};
/**
* Generate a unique id. This will be locally or globally unique, depending on
* whether we are in single user or realtime collaborative mode.
* @return {string}
*/
Blockly.genUid = function() {
var uid = (++Blockly.uidCounter_).toString();
if (Blockly.Realtime.isEnabled()) {
return Blockly.Realtime.genUid(uid);
} else {
return uid;
}
};
/**
* Class for one block.
@@ -100,7 +114,7 @@ Blockly.Block.obtain = function(workspace, prototypeName) {
* type-specific functions for this block.
*/
Blockly.Block.prototype.initialize = function(workspace, prototypeName) {
this.id = ++Blockly.uidCounter_;
this.id = Blockly.genUid();
workspace.addTopBlock(this);
this.fill(workspace, prototypeName);
// Bind an onchange function, if it exists.
@@ -552,38 +566,41 @@ Blockly.Block.prototype.onMouseDown_ = function(e) {
* @private
*/
Blockly.Block.prototype.onMouseUp_ = function(e) {
Blockly.terminateDrag_();
if (Blockly.selected && Blockly.highlightedConnection_) {
// Connect two blocks together.
Blockly.localConnection_.connect(Blockly.highlightedConnection_);
if (this.svg_) {
// Trigger a connection animation.
// Determine which connection is inferior (lower in the source stack).
var inferiorConnection;
if (Blockly.localConnection_.isSuperior()) {
inferiorConnection = Blockly.highlightedConnection_;
} else {
inferiorConnection = Blockly.localConnection_;
var this_ = this;
Blockly.doCommand(function() {
Blockly.terminateDrag_();
if (Blockly.selected && Blockly.highlightedConnection_) {
// Connect two blocks together.
Blockly.localConnection_.connect(Blockly.highlightedConnection_);
if (this_.svg_) {
// Trigger a connection animation.
// Determine which connection is inferior (lower in the source stack).
var inferiorConnection;
if (Blockly.localConnection_.isSuperior()) {
inferiorConnection = Blockly.highlightedConnection_;
} else {
inferiorConnection = Blockly.localConnection_;
}
inferiorConnection.sourceBlock_.svg_.connectionUiEffect();
}
inferiorConnection.sourceBlock_.svg_.connectionUiEffect();
if (this_.workspace.trashcan && this_.workspace.trashcan.isOpen) {
// Don't throw an object in the trash can if it just got connected.
this_.workspace.trashcan.close();
}
} else if (this_.workspace.trashcan && this_.workspace.trashcan.isOpen) {
var trashcan = this_.workspace.trashcan;
goog.Timer.callOnce(trashcan.close, 100, trashcan);
Blockly.selected.dispose(false, true);
// Dropping a block on the trash can will usually cause the workspace to
// resize to contain the newly positioned block. Force a second resize
// now that the block has been deleted.
Blockly.fireUiEvent(window, 'resize');
}
if (this.workspace.trashcan && this.workspace.trashcan.isOpen) {
// Don't throw an object in the trash can if it just got connected.
this.workspace.trashcan.close();
if (Blockly.highlightedConnection_) {
Blockly.highlightedConnection_.unhighlight();
Blockly.highlightedConnection_ = null;
}
} else if (this.workspace.trashcan && this.workspace.trashcan.isOpen) {
var trashcan = this.workspace.trashcan;
goog.Timer.callOnce(trashcan.close, 100, trashcan);
Blockly.selected.dispose(false, true);
// Dropping a block on the trash can will usually cause the workspace to
// resize to contain the newly positioned block. Force a second resize now
// that the block has been deleted.
Blockly.fireUiEvent(window, 'resize');
}
if (Blockly.highlightedConnection_) {
Blockly.highlightedConnection_.unhighlight();
Blockly.highlightedConnection_ = null;
}
});
};
/**
@@ -828,80 +845,83 @@ Blockly.Block.prototype.setDragging_ = function(adding) {
* @private
*/
Blockly.Block.prototype.onMouseMove_ = function(e) {
if (e.type == 'mousemove' && e.clientX <= 1 && e.clientY == 0 &&
e.button == 0) {
/* HACK:
Safari Mobile 6.0 and Chrome for Android 18.0 fire rogue mousemove events
on certain touch actions. Ignore events with these signatures.
This may result in a one-pixel blind spot in other browsers,
but this shouldn't be noticable. */
e.stopPropagation();
return;
}
Blockly.removeAllRanges();
var dx = e.clientX - this.startDragMouseX;
var dy = e.clientY - this.startDragMouseY;
if (Blockly.Block.dragMode_ == 1) {
// Still dragging within the sticky DRAG_RADIUS.
var dr = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
if (dr > Blockly.DRAG_RADIUS) {
// Switch to unrestricted dragging.
Blockly.Block.dragMode_ = 2;
// Push this block to the very top of the stack.
this.setParent(null);
this.setDragging_(true);
var this_ = this;
Blockly.doCommand(function() {
if (e.type == 'mousemove' && e.clientX <= 1 && e.clientY == 0 &&
e.button == 0) {
/* HACK:
Safari Mobile 6.0 and Chrome for Android 18.0 fire rogue mousemove events
on certain touch actions. Ignore events with these signatures.
This may result in a one-pixel blind spot in other browsers,
but this shouldn't be noticable. */
e.stopPropagation();
return;
}
}
if (Blockly.Block.dragMode_ == 2) {
// Unrestricted dragging.
var x = this.startDragX + dx;
var y = this.startDragY + dy;
this.svg_.getRootElement().setAttribute('transform',
'translate(' + x + ', ' + y + ')');
// Drag all the nested bubbles.
for (var i = 0; i < this.draggedBubbles_.length; i++) {
var commentData = this.draggedBubbles_[i];
commentData.bubble.setIconLocation(commentData.x + dx,
commentData.y + dy);
}
// Check to see if any of this block's connections are within range of
// another block's connection.
var myConnections = this.getConnections_(false);
var closestConnection = null;
var localConnection = null;
var radiusConnection = Blockly.SNAP_RADIUS;
for (var i = 0; i < myConnections.length; i++) {
var myConnection = myConnections[i];
var neighbour = myConnection.closest(radiusConnection, dx, dy);
if (neighbour.connection) {
closestConnection = neighbour.connection;
localConnection = myConnection;
radiusConnection = neighbour.radius;
Blockly.removeAllRanges();
var dx = e.clientX - this_.startDragMouseX;
var dy = e.clientY - this_.startDragMouseY;
if (Blockly.Block.dragMode_ == 1) {
// Still dragging within the sticky DRAG_RADIUS.
var dr = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
if (dr > Blockly.DRAG_RADIUS) {
// Switch to unrestricted dragging.
Blockly.Block.dragMode_ = 2;
// Push this block to the very top of the stack.
this_.setParent(null);
this_.setDragging_(true);
}
}
if (Blockly.Block.dragMode_ == 2) {
// Unrestricted dragging.
var x = this_.startDragX + dx;
var y = this_.startDragY + dy;
this_.svg_.getRootElement().setAttribute('transform',
'translate(' + x + ', ' + y + ')');
// Drag all the nested bubbles.
for (var i = 0; i < this_.draggedBubbles_.length; i++) {
var commentData = this_.draggedBubbles_[i];
commentData.bubble.setIconLocation(commentData.x + dx,
commentData.y + dy);
}
// Remove connection highlighting if needed.
if (Blockly.highlightedConnection_ &&
Blockly.highlightedConnection_ != closestConnection) {
Blockly.highlightedConnection_.unhighlight();
Blockly.highlightedConnection_ = null;
Blockly.localConnection_ = null;
// Check to see if any of this block's connections are within range of
// another block's connection.
var myConnections = this_.getConnections_(false);
var closestConnection = null;
var localConnection = null;
var radiusConnection = Blockly.SNAP_RADIUS;
for (var i = 0; i < myConnections.length; i++) {
var myConnection = myConnections[i];
var neighbour = myConnection.closest(radiusConnection, dx, dy);
if (neighbour.connection) {
closestConnection = neighbour.connection;
localConnection = myConnection;
radiusConnection = neighbour.radius;
}
}
// Remove connection highlighting if needed.
if (Blockly.highlightedConnection_ &&
Blockly.highlightedConnection_ != closestConnection) {
Blockly.highlightedConnection_.unhighlight();
Blockly.highlightedConnection_ = null;
Blockly.localConnection_ = null;
}
// Add connection highlighting if needed.
if (closestConnection &&
closestConnection != Blockly.highlightedConnection_) {
closestConnection.highlight();
Blockly.highlightedConnection_ = closestConnection;
Blockly.localConnection_ = localConnection;
}
// Flip the trash can lid if needed.
if (this_.workspace.trashcan && this_.isDeletable()) {
this_.workspace.trashcan.onMouseMove(e);
}
}
// Add connection highlighting if needed.
if (closestConnection &&
closestConnection != Blockly.highlightedConnection_) {
closestConnection.highlight();
Blockly.highlightedConnection_ = closestConnection;
Blockly.localConnection_ = localConnection;
}
// Flip the trash can lid if needed.
if (this.workspace.trashcan && this.isDeletable()) {
this.workspace.trashcan.onMouseMove(e);
}
}
// This event has been handled. No need to bubble up to the document.
e.stopPropagation();
// This event has been handled. No need to bubble up to the document.
e.stopPropagation();
});
};
/**
@@ -1423,7 +1443,7 @@ Blockly.Block.prototype.setCollapsed = function(collapsed) {
var text = this.toString(Blockly.COLLAPSE_CHARS);
this.appendDummyInput(COLLAPSED_INPUT_NAME).appendField(text);
} else {
this.removeInput(COLLAPSED_INPUT_NAME)
this.removeInput(COLLAPSED_INPUT_NAME);
}
if (!renderList.length) {
@@ -1465,7 +1485,7 @@ Blockly.Block.prototype.toString = function(opt_maxLength) {
text = goog.string.truncate(text, opt_maxLength);
}
return text;
}
};
/**
* Shortcut for appending a value input row.
@@ -1678,9 +1698,9 @@ Blockly.Block.prototype.moveNumberedInputBefore = function(
// Validate arguments.
goog.asserts.assert(inputIndex != refIndex, 'Can\'t move input to itself.');
goog.asserts.assert(inputIndex < this.inputList.length,
'Input index ' + inputIndex + ' out of bounds.')
'Input index ' + inputIndex + ' out of bounds.');
goog.asserts.assert(refIndex <= this.inputList.length,
'Reference input ' + refIndex + ' out of bounds.')
'Reference input ' + refIndex + ' out of bounds.');
// Remove input.
var input = this.inputList[inputIndex];
this.inputList.splice(inputIndex, 1);

View File

@@ -48,8 +48,8 @@ goog.require('Blockly.inject');
goog.require('Blockly.utils');
// Closure dependencies.
goog.require('goog.dom');
goog.require('goog.color');
goog.require('goog.dom');
goog.require('goog.events');
goog.require('goog.string');
goog.require('goog.ui.ColorPicker');
@@ -669,6 +669,22 @@ Blockly.setMainWorkspaceMetrics_ = function(xyRatio) {
translation);
};
/**
* Execute a command. Generally, a command is the result of a user action
* e.g., a click, drag or context menu selection. Calling the cmdThunk function
* through doCommand() allows us to capture information that can be used for
* capabilities like undo (which is supported by the realtime collaboration
* feature).
* @param {function()} cmdThunk A function representing the command execution.
*/
Blockly.doCommand = function(cmdThunk) {
if (Blockly.Realtime.isEnabled) {
Blockly.Realtime.doCommand(cmdThunk);
} else {
cmdThunk();
}
};
/**
* When something in Blockly's workspace changes, call a function.
* @param {!Function} func Function to call.

View File

@@ -109,7 +109,11 @@ Blockly.ContextMenu.show = function(xy, options) {
resizeList.push(rectElement);
Blockly.bindEvent_(gElement, 'mousedown', null, Blockly.noEvent);
if (option.enabled) {
Blockly.bindEvent_(gElement, 'mouseup', null, option.callback);
var evtHandlerCapturer = function(callback) {
return function() { Blockly.doCommand(callback); };
};
var evtHandler = evtHandlerCapturer(option.callback);
Blockly.bindEvent_(gElement, 'mouseup', null, evtHandler);
Blockly.bindEvent_(gElement, 'mouseup', null, Blockly.ContextMenu.hide);
} else {
gElement.setAttribute('class', 'blocklyMenuDivDisabled');

View File

@@ -21,10 +21,6 @@
/**
* This file contains functions used by any Blockly app that wants to provide
* realtime collaboration functionality.
*
* Note that it depends on the existence of particularly named UI elements.
*
* TODO: Inject the UI element names
*/
/**
@@ -34,7 +30,7 @@
* Console. Instructions on how to do that can be found in the Blockly wiki page
* at https://code.google.com/p/blockly/wiki/RealtimeCollaboration
* Once you do that you can set the clientId in
* Blockly.Realtime.realtimeOptions_
* Blockly.Realtime.rtclientOptions_
* @author markf@google.com (Mark Friedman)
*/
'use strict';
@@ -52,6 +48,13 @@ goog.require('rtclient');
*/
Blockly.Realtime.enabled_ = false;
/**
* The Realtime document being collaborated on.
* @type {gapi.drive.realtime.Document}
* @private
*/
Blockly.Realtime.document_ = null;
/**
* The Realtime model of this doc.
* @type {gapi.drive.realtime.Model}
@@ -59,6 +62,13 @@ Blockly.Realtime.enabled_ = false;
*/
Blockly.Realtime.model_ = null;
/**
* The unique id associated with this editing session.
* @type {string}
* @private
*/
Blockly.Realtime.sessionId_ = null;
/**
* The function used to initialize the UI after realtime is initialized.
* @type {function()}
@@ -100,6 +110,13 @@ Blockly.Realtime.chatBoxElementId_ = null;
*/
Blockly.Realtime.chatBoxInitialText_ = null;
/**
* Indicator of whether we are in the context of an undo or redo operation.
* @type {boolean}
* @private
*/
Blockly.Realtime.withinUndo_ = false;
/**
* Returns whether realtime collaboration is enabled.
* @return {boolean}
@@ -108,6 +125,20 @@ Blockly.Realtime.isEnabled = function() {
return Blockly.Realtime.enabled_;
};
/**
* The id of the button to use for undo.
* @type {string}
* @private
*/
Blockly.Realtime.undoElementId_ = null;
/**
* The id of the button to use for redo.
* @type {string}
* @private
*/
Blockly.Realtime.redoElementId_ = null;
/**
* This function is called the first time that the Realtime model is created
* for a file. This function should be used to initialize any values of the
@@ -175,37 +206,58 @@ Blockly.Realtime.getBlockById = function(id) {
return Blockly.Realtime.blocksMap_.get(id);
};
/**
* Log the event for debugging purposses.
* @param {gapi.drive.realtime.BaseModelEvent} evt The event that occurred.
* @private
*/
Blockly.Realtime.logEvent_ = function (evt) {
console.log("Object event:");
console.log(" id: " + evt.target.id);
console.log(" type: " + evt.type);
var events = evt.events;
if (events) {
var eventCount = events.length;
for (var i = 0; i < eventCount; i++) {
var event = events[i];
console.log(" child event:");
console.log(" id: " + event.target.id);
console.log(" type: " + event.type);
}
}
};
/**
* Event handler to call when a block is changed.
* @param {gapi.drive.realtime.ObjectChangedEvent} evt The event that occurred.
* @private
*/
Blockly.Realtime.onObjectChange_ = function(evt) {
Blockly.Realtime.logEvent_(evt);
var events = evt.events;
var eventCount = evt.events.length;
for (var i = 0; i < eventCount; i++) {
var event = events[i];
if (!event.isLocal) {
if (!event.isLocal || Blockly.Realtime.withinUndo_) {
var block = event.target;
if (event.type == 'value_changed') {
if (event.property == 'xmlDom') {
var block = event.target;
Blockly.Realtime.doWithinSync_(function() {
Blockly.Realtime.placeBlockOnWorkspace_(block, false);
Blockly.Realtime.moveBlock_(block);
});
} else if (event.property == 'relativeX' ||
event.property == 'relativeY') {
var block2 = event.target;
event.property == 'relativeY') {
Blockly.Realtime.doWithinSync_(function() {
if (!block2.svg_) {
// If this is a move of a newly disconnected (i.e newly top level)
// block it will not have any svg (because it has been disposed of
// by it's parent), so we need to handle that here.
Blockly.Realtime.placeBlockOnWorkspace_(block2, false);
if (!block.svg_) {
// If this is a move of a newly disconnected (i.e newly top
// level) block it will not have any svg (because it has been
// disposed of by it's parent), so we need to handle that here.
Blockly.Realtime.placeBlockOnWorkspace_(block, false);
}
Blockly.Realtime.moveBlock_(block2);
Blockly.Realtime.moveBlock_(block);
});
}
}
}
}
}
@@ -217,9 +269,10 @@ Blockly.Realtime.onObjectChange_ = function(evt) {
* @private
*/
Blockly.Realtime.onBlocksMapChange_ = function(evt) {
console.log('Blocks Map event:');
console.log(' id: ' + evt.property);
if (!evt.isLocal) {
Blockly.Realtime.logEvent_(evt);
// console.log('Blocks Map event:');
// console.log(' id: ' + evt.property);
if (!evt.isLocal || Blockly.Realtime.withinUndo_) {
var block = evt.newValue;
if (block) {
Blockly.Realtime.placeBlockOnWorkspace_(block, !(evt.oldValue));
@@ -259,6 +312,9 @@ Blockly.Realtime.doWithinSync_ = function(thunk) {
*/
Blockly.Realtime.placeBlockOnWorkspace_ = function(block, addToTop) {
Blockly.Realtime.doWithinSync_(function() {
// if (!Blockly.Realtime.blocksMap_.has(block.id)) {
// Blockly.Realtime.blocksMap_.set(block.id, block);
// }
var blockDom = Blockly.Xml.textToDom(block.xmlDom).firstChild;
var newBlock =
Blockly.Xml.domToBlock(Blockly.mainWorkspace, blockDom, true);
@@ -309,16 +365,6 @@ Blockly.Realtime.deleteBlock = function(block) {
* @private
*/
Blockly.Realtime.loadBlocks_ = function() {
var blocks = Blockly.Realtime.blocksMap_.values();
for (var i = 0; i < blocks.length; i++) {
var block = blocks[i];
// Since we now have blocks with already existing ids, we have to make sure
// that new blocks don't get any of the existing ids.
var blockIdNum = parseInt(block.id, 10);
if (blockIdNum > Blockly.getUidCounter()) {
Blockly.setUidCounter(blockIdNum + 1);
}
}
var topBlocks = Blockly.Realtime.topBlocks_;
for (var j = 0; j < topBlocks.length; j++) {
var topBlock = topBlocks.get(j);
@@ -366,6 +412,8 @@ Blockly.Realtime.blockChanged = function(block) {
* @private
*/
Blockly.Realtime.onFileLoaded_ = function(doc) {
Blockly.Realtime.document_ = doc;
Blockly.Realtime.sessionId_ = Blockly.Realtime.getSessionId_(doc);
Blockly.Realtime.model_ = doc.getModel();
Blockly.Realtime.blocksMap_ =
Blockly.Realtime.model_.getRoot().get('blocks');
@@ -385,26 +433,57 @@ Blockly.Realtime.onFileLoaded_ = function(doc) {
// Add logic for undo button.
// TODO: Uncomment this when undo/redo are fixed.
/*
var undoButton = document.getElementById('undoButton');
var redoButton = document.getElementById('redoButton');
//
// var undoButton = document.getElementById(Blockly.Realtime.undoElementId_);
// var redoButton = document.getElementById(Blockly.Realtime.redoElementId_);
//
// if (undoButton) {
// undoButton.onclick = function (e) {
// try {
// Blockly.Realtime.withinUndo_ = true;
// Blockly.Realtime.model_.undo();
// } finally {
// Blockly.Realtime.withinUndo_ = false;
// }
// };
// }
// if (redoButton) {
// redoButton.onclick = function (e) {
// try {
// Blockly.Realtime.withinUndo_ = true;
// Blockly.Realtime.model_.redo();
// } finally {
// Blockly.Realtime.withinUndo_ = false;
// }
// };
// }
//
// // Add event handler for UndoRedoStateChanged events.
// var onUndoRedoStateChanged = function(e) {
// undoButton.disabled = !e.canUndo;
// redoButton.disabled = !e.canRedo;
// };
// Blockly.Realtime.model_.addEventListener(
// gapi.drive.realtime.EventType.UNDO_REDO_STATE_CHANGED,
// onUndoRedoStateChanged);
undoButton.onclick = function(e) {
Blockly.Realtime.model_.undo();
};
redoButton.onclick = function(e) {
Blockly.Realtime.model_.redo();
};
};
// Add event handler for UndoRedoStateChanged events.
var onUndoRedoStateChanged = function(e) {
undoButton.disabled = !e.canUndo;
redoButton.disabled = !e.canRedo;
};
Blockly.Realtime.model_.addEventListener(
gapi.drive.realtime.EventType.UNDO_REDO_STATE_CHANGED,
onUndoRedoStateChanged);
/**
* Get the sessionId associated with this editing session. Note that it is
* unique to the current browser window/tab.
* @param {gapi.drive.realtime.Document} doc
* @return {*}
* @private
*/
Blockly.Realtime.getSessionId_ = function(doc) {
var collaborators = doc.getCollaborators();
for (var i = 0; i < collaborators.length; i++) {
var collaborator = collaborators[i];
if (collaborator.isMe) {
return collaborator.sessionId;
}
}
};
/**
@@ -417,7 +496,6 @@ Blockly.Realtime.registerTypes_ = function() {
custom.registerType(Blockly.Block, 'Block');
Blockly.Block.prototype.id = custom.collaborativeField('id');
Blockly.Block.prototype.type = custom.collaborativeField('type');
Blockly.Block.prototype.xmlDom = custom.collaborativeField('xmlDom');
Blockly.Block.prototype.relativeX = custom.collaborativeField('relativeX');
Blockly.Block.prototype.relativeY = custom.collaborativeField('relativeY');
@@ -516,11 +594,12 @@ Blockly.Realtime.getUserDomain = function(fileId, callback) {
* Options for the Realtime loader.
* @private
*/
Blockly.Realtime.realtimeOptions_ = {
Blockly.Realtime.rtclientOptions_ = {
/**
* Client ID from the console.
* This will be set from the options passed into Blockly.Realtime.start()
*/
clientId: 'INSERT YOUR CLIENT ID HERE',
clientId: null,
/**
* The ID of the button to click to authorize. Must be a DOM element ID.
@@ -588,6 +667,13 @@ Blockly.Realtime.parseOptions_ = function(options) {
Blockly.Realtime.chatBoxInitialText_ =
rtclient.getOption(chatBoxOptions, 'initText', Blockly.Msg.CHAT);
}
Blockly.Realtime.rtclientOptions_.clientId =
rtclient.getOption(options, 'clientId');
// TODO: Uncomment this when undo/redo are fixed.
// Blockly.Realtime.undoElementId_ =
// rtclient.getOption(options, 'undoElementId', 'undoButton');
// Blockly.Realtime.redoElementId_ =
// rtclient.getOption(options, 'redoElementId', 'redoButton');
};
/**
@@ -615,7 +701,7 @@ Blockly.Realtime.startRealtime = function(uiInitialize, uiContainer, options) {
}
};
Blockly.Realtime.realtimeLoader_ =
new rtclient.RealtimeLoader(Blockly.Realtime.realtimeOptions_);
new rtclient.RealtimeLoader(Blockly.Realtime.rtclientOptions_);
Blockly.Realtime.realtimeLoader_.start();
};
@@ -632,7 +718,7 @@ Blockly.Realtime.addAuthUi_ = function(uiContainer) {
var authText = goog.dom.createDom('p', null, Blockly.Msg.AUTH);
authButtonDiv.appendChild(authText);
var authButton = goog.dom.createDom('button', null, 'Authorize');
authButton.id = Blockly.Realtime.realtimeOptions_.authButtonElementId;
authButton.id = Blockly.Realtime.rtclientOptions_.authButtonElementId;
authButtonDiv.appendChild(authButton);
uiContainer.appendChild(authButtonDiv);
@@ -653,3 +739,57 @@ Blockly.Realtime.addAuthUi_ = function(uiContainer) {
(blocklyDivBounds.height - authButtonDivBounds.height) / 4 + 'px';
return authButtonDiv;
};
/**
* Execute a command. Generally, a command is the result of a user action
* e.g., a click, drag or context menu selection.
* @param {function()} cmdThunk A function representing the command execution.
*/
Blockly.Realtime.doCommand = function(cmdThunk) {
// TODO(): We'd like to use the realtime API compound operations as in the
// commented out code below. However, it appears that the realtime API is
// re-ordering events when they're within compound operations in a way which
// breaks us. We might need to implement our own compound operations as a
// workaround. Doing so might give us some other advantages since we could
// then allow compound operations that span synchronous blocks of code (e.g.,
// span multiple Blockly events). It would also allow us to deal with the
// fact that the current realtime API puts some operations into the undo stack
// that we would prefer weren't there; namely local changes that occur as a
// result of remote realtime events.
// try {
// Blockly.Realtime.model_.beginCompoundOperation();
// cmdThunk();
// } finally {
// Blockly.Realtime.model_.endCompoundOperation();
// }
cmdThunk();
};
/**
* Generate an id that is unique among the all the sessions that ever
* collaborated on this document.
* @param {string} extra A string id which is unique within this particular
* session.
* @return {string}
*/
Blockly.Realtime.genUid = function(extra) {
/* The idea here is that we use the extra string to ensure uniqueness within
this session and the current sessionId to ensure uniqueness across
all the current sessions. There's still the (remote) chance that the
current sessionId is the same as some old (non-current) one, so we still
need to check that our uid hasn't been previously used.
Note that you could potentially use a random number to generate the id but
there remains the small chance of regenerating the same number that's been
used before and I'm paranoid. It's not enough to just check that the
random uid hasn't been previously used because other concurrent sessions
might generate the same uid at the same time. Like I said, I'm paranoid.
*/
var potentialUid = Blockly.Realtime.sessionId_ + '-' + extra;
if (!Blockly.Realtime.blocksMap_.has(potentialUid)) {
return potentialUid;
} else {
return (Blockly.Realtime.genUid('-' + extra));
}
};

View File

@@ -57,7 +57,9 @@ function start() {
var toolbox = document.getElementById('toolbox');
Blockly.inject(document.getElementById('blocklyDiv'),
{rtl: rtl, path: '../', toolbox: toolbox, realtime: false,
realtimeOptions: {chatbox: {elementId: 'chatbox'}}});
realtimeOptions:
{clientId: 'YOUR CLIENT ID GOES HERE',
chatbox: {elementId: 'chatbox'}}});
if (Blockly.Realtime.isEnabled()) {
enableRealtimeSpecificUi();
}
@@ -339,6 +341,7 @@ h1 {
<br>
<!-- Undo and redo buttons. -->
<!-- TODO: Uncomment this when undo/redo are fixed. -->
<!--
<button id="undoButton" disabled>Undo</button>
<button id="redoButton" disabled>Redo</button>