mirror of
https://github.com/google/blockly.git
synced 2026-03-11 07:40:10 +01:00
Automatic commit Sat Feb 22 03:00:01 PST 2014
This commit is contained in:
@@ -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;
|
||||
@@ -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']);
|
||||
|
||||
236
core/block.js
236
core/block.js
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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');
|
||||
|
||||
242
core/realtime.js
242
core/realtime.js
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user