text: var RemixGraph=function(){var instance=null;return{getInstance:function(){return null==instance&&(instance=new _InternalRemixGraph),instance}}}(),_InternalRemixGraph=function(){var self=this;self.programID=0,self.recommendedByPageID=0,self.remixGraphLayerId=null,self.network=null,self.nodes=null,self.edges=null,self.unavailableNodes=null,self.relationDescendantMap=null,self.relationAncestorMap=null,self.backwardEdgeMap=null,self.backwardReverseEdgeMap=null,self.closeButtonSelector=null,self.programDetailsUrlTemplate=null,self.clickStatisticUrl=null,self.remixGraphTranslations=null,self.init=function(programID,recommendedByPageID,modalLayerId,remixGraphLayerId,closeButtonClassName,programDetailsUrlTemplate,clickStatisticUrl,remixGraphTranslations){self.reset(),self.programID=programID,self.recommendedByPageID=recommendedByPageID,self.remixGraphLayerId=remixGraphLayerId,self.closeButtonSelector=$("."+closeButtonClassName),self.remixGraphTranslations=remixGraphTranslations,self.clickStatisticUrl=clickStatisticUrl,self.programDetailsUrlTemplate=programDetailsUrlTemplate,$('<div id="context-menu" class="context-menu-trigger" style="display:none;"></div>').appendTo("#"+modalLayerId)},self.getNodes=function(){return self.nodes},self.getEdges=function(){return self.edges},self.reset=function(){self.network=null,self.nodes=new vis.DataSet,self.edges=new vis.DataSet,self.unavailableNodes=[]},self.destroy=function(){self.reset(),null!==self.network&&(self.network.destroy(),self.network=null)},self.render=function(loadingAnimation,networkDescription){loadingAnimation.show(),$("body").css("overflow","hidden"),self.network=networkDescription.network,self.nodes=networkDescription.nodes,self.edges=networkDescription.edges,self.unavailableNodes=networkDescription.unavailableNodes,self.relationDescendantMap=networkDescription.relationDescendantMap,self.relationAncestorMap=networkDescription.relationAncestorMap,self.backwardEdgeMap=networkDescription.backwardEdgeMap,self.backwardReverseEdgeMap=networkDescription.backwardReverseEdgeMap,self.nodes.update([{id:CATROBAT_NODE_PREFIX+"_"+self.programID,color:{border:"#FFFF00"}}]),self.network.on("click",self.onClick),self.network.on("afterDrawing",function(){loadingAnimation.hide(),setTimeout(function(){loadingAnimation.hide()},1e3)}),self.network.fit({animation:!1})},self.onClick=function(params){var overlayDiv=$("<div></div>").attr("id","overlay").addClass("overlay");overlayDiv.appendTo("body"),setTimeout("$('#overlay').remove();",300);var selectedNodes=params.nodes;if(self.edges.forEach(function(edgeData){self.nodes.update([{id:edgeData.from,borderWidth:NETWORK_OPTIONS.nodes.borderWidth,color:NETWORK_OPTIONS.nodes.color}]),self.nodes.update([{id:edgeData.to,borderWidth:NETWORK_OPTIONS.nodes.borderWidth,color:NETWORK_OPTIONS.nodes.color}]),self.edges.update([{id:edgeData.id,color:NETWORK_OPTIONS.edges.color}])}),0!=selectedNodes.length){var selectedNodeId=selectedNodes[0],idParts=selectedNodeId.split("_"),nodeId=parseInt(idParts[1]);if($.inArray(nodeId,self.unavailableNodes)!=-1)return void swal({title:self.remixGraphTranslations.programNotAvailableErrorTitle,text:self.remixGraphTranslations.programNotAvailableErrorDescription,type:"error",showCancelButton:!1,confirmButtonText:self.remixGraphTranslations.ok,closeOnConfirm:!0},function(){self.network.selectNodes([]),$("#overlay").remove()});var domPosition=params.pointer.DOM,menuWidth=220,offsetX=-menuWidth/2,selectedNodeData=self.nodes.get(selectedNodeId);self.network.getConnectedEdges(selectedNodeId);$.contextMenu("destroy");var contextMenuItems={title:{name:"<b>"+selectedNodeData.name+"</b>",isHtmlName:!0,className:"context-menu-item-title context-menu-not-selectable"},subtitle:{name:self.remixGraphTranslations.by+" "+selectedNodeData.username,isHtmlName:!0,className:"context-menu-item-subtitle context-menu-not-selectable"}};self.edges.length>0&&(contextMenuItems.sep1="---------"),nodeId!=self.programID&&(contextMenuItems.open={name:self.remixGraphTranslations.open,icon:"fa-external-link",callback:function(){self.performClickStatisticRequest(nodeId,idParts[0]!=CATROBAT_NODE_PREFIX),self.closeButtonSelector.click();var newUrlPrefix=idParts[0]==CATROBAT_NODE_PREFIX?self.programDetailsUrlTemplate.replace("0",""):SCRATCH_PROJECT_BASE_URL,queryString=idParts[0]==CATROBAT_NODE_PREFIX?"?rec_by_page_id="+self.recommendedByPageID+"&rec_by_program_id="+self.programID:"";window.location=newUrlPrefix+nodeId+queryString}}),self.edges.length>0&&(contextMenuItems.edges={name:self.remixGraphTranslations.showPaths,icon:"fa-retweet",callback:function(){self.highlightPathEdgesOfSelectedNode(nodeId)}}),$.contextMenu({selector:".context-menu-trigger",trigger:"left",className:"data-title",events:{show:function(opt){},hide:function(opt){self.network.selectNodes([])}},callback:function(key,options){var m="clicked: "+key;window.console&&console.log(m)||alert(m)},position:function(opt,x,y){var windowWidth=$(window).width();$(window).height();if(windowWidth>767){var menuWidth=260,minMarginLeft=10,minMarginRight=10,menuOffsetX=Math.max(Math.min(offsetX+domPosition.x,windowWidth-menuWidth-minMarginRight),minMarginLeft);opt.$menu.css({top:domPosition.y,left:menuOffsetX,width:menuWidth})}else{var width=Math.max(windowWidth-40,320),height=opt.$menu.css("height").replace("px","");opt.$menu.css({top:"50%",left:"50%",width:width,maxWidth:width,marginTop:-height/2,marginLeft:-width/2})}},items:contextMenuItems}),$("#context-menu").click()}},self.highlightPathEdgesOfSelectedNode=function(nodeId){self.edges.forEach(function(edgeData){var isFromIdConnectingAncestorOrDescendant=!1,isToIdConnectingAncestorOrDescendant=!1,fromId=parseInt(edgeData.from.split("_")[1]),toId=parseInt(edgeData.to.split("_")[1]);edgeData.from.startsWith(CATROBAT_NODE_PREFIX)&&edgeData.to.startsWith(CATROBAT_NODE_PREFIX)?(isFromIdConnectingAncestorOrDescendant=$.inArray(fromId,self.relationAncestorMap[nodeId])!=-1||$.inArray(fromId,self.relationDescendantMap[nodeId])!=-1,isToIdConnectingAncestorOrDescendant=$.inArray(toId,self.relationAncestorMap[nodeId])!=-1||$.inArray(toId,self.relationDescendantMap[nodeId])!=-1):edgeData.from.startsWith(SCRATCH_NODE_PREFIX)&&edgeData.to.startsWith(CATROBAT_NODE_PREFIX)&&(isFromIdConnectingAncestorOrDescendant=!0,isToIdConnectingAncestorOrDescendant=$.inArray(toId,self.relationAncestorMap[nodeId])!=-1||$.inArray(toId,self.relationDescendantMap[nodeId])!=-1),isFromIdConnectingAncestorOrDescendant&&isToIdConnectingAncestorOrDescendant?(self.highlightNode(edgeData.from),self.highlightNode(edgeData.to),self.highlightEdge(edgeData.id)):self.unhighlightEdge(edgeData.id)})},self.highlightNode=function(nodeId){self.nodes.update([{id:nodeId,borderWidth:9,color:{border:"#FFFF00"}}])},self.highlightEdge=function(edgeId){self.edges.update([{id:edgeId,color:{color:"#FFFF00",opacity:1}}])},self.unhighlightEdge=function(edgeId){self.edges.update([{id:edgeId,color:{opacity:.05}}])},self.performClickStatisticRequest=function(recommendedProgramID,isScratchProgram){var type="rec_remix_graph",params={type:type,recFromID:self.programID,recID:recommendedProgramID,isScratchProgram:isScratchProgram?1:0};$.ajaxSetup({async:!1}),$.post(self.clickStatisticUrl,params,function(data){"error"==data&&console.log("No click statistic is created!")}).fail(function(data){console.log(data)})}};