pm2-gui-fr
Version:
Une interface web et terminal élégante pour Unitech / PM2.
8 lines • 16.9 kB
JavaScript
/**
* fanavi 0.0.1
* https://github.com/Tjatse/fanavi
*
* Apache, License 2.0
* Copyright (C) 2015 Tjatse
*/
function d3menu(d3){return function(selector){var _defOptions={outerRadius:100,innerRadius:30,spacing:4,margin:40,bounce:0.1,startAngle:-90,endAngle:270,padAngle:2,menuItemStrokeWidth:2,backgroundColor:"#50b44c",buttonStrokeWidth:4,buttonForegroundColor:"#fff",buttonAutoShape:true,shadow:{x:2,y:2,blur:3,opacity:0.5,color:"#054502"},iconSize:32,speed:500,hideTooltip:false};function menu(_selector){if(!(this instanceof menu)){return new menu(_selector)}this.options=_mixin({selector:_selector||"body",_id:Math.random()},_defOptions);this._listeners={};this._updateVars()}menu.prototype.load=function(items){if(this._loaded||!items||items.length==0){return this}this._loaded=true;this.options._items=[].concat(items);Object.freeze(this.options);this._visualize()._drawMenuButton();return this};menu.prototype.option=function(key,value){if(typeof value=="undefined"){if(typeof key=="object"){this.options=_mixin({},_defOptions,this.options,key);return this._updateVars()}return this.options[key]}else{if(value==null){delete this.options[key]}else{this.options[key]=value}}this.options=_mixin({},_defOptions,this.options);return this._updateVars()};menu.prototype._updateVars=function(){this.options.width=this.options.height=_getSize(this.options);(typeof this.options.backgroundColor=="string")&&(this.options.backgroundColor=d3.rgb(this.options.backgroundColor));(typeof this.options.buttonForegroundColor=="string")&&(this.options.buttonForegroundColor=d3.rgb(this.options.buttonForegroundColor));return this};menu.prototype._visualize=function(){var options=this.options;var attrs={width:options.width,height:options.height};options.className&&(attrs["class"]=options.className);options.id&&(attrs.id=options.id);this.svg=d3.select(options.selector).append("svg").attr(attrs).style("opacity",0.95);this.defs=this.svg.append("defs");var stopColors=[{offset:"0%",color:options.backgroundColor.brighter(0.5)},{offset:"70%",color:options.backgroundColor},{offset:"100%",color:options.backgroundColor.brighter(0.1)}];this.defs.append("radialGradient").attr({id:"gradBg"+options._id,gradientUnits:"userSpaceOnUse",cx:"0",cy:"0",r:options.innerRadius-options.buttonStrokeWidth,spreadMethod:"pad"}).selectAll("stop").data(stopColors).enter().append("stop").attr({offset:function(d){return d.offset},"stop-color":function(d){return d.color},"stop-opacity":function(d){return d.opacity||1}});var filter=this.defs.append("filter").attr({id:"dropshadow"+options._id,x:"-50%",y:"-50%",width:"200%",height:"200%"});filter.append("feGaussianBlur").attr({"in":"SourceAlpha",stdDeviation:options.shadow.blur,result:"blur"});filter.append("feOffset").attr({"in":"blur",dx:options.shadow.x,dy:options.shadow.y,result:"offsetBlur"});filter.append("feFlood").attr({"flood-opacity":options.shadow.opacity,"flood-color":options.shadow.color,result:"offsetColor"});filter.append("feComposite").attr({"in":"offsetColor",in2:"offsetBlur",operator:"in",result:"offsetBlur"});var feMerge=filter.append("feMerge");feMerge.append("feMergeNode").attr("in","offsetBlur");feMerge.append("feMergeNode").attr("in","SourceGraphic");return this};menu.prototype._drawMenuButton=function(){var that=this,options=this.options;var gMenu=this.svg.append("g").attr({transform:"translate("+(options.width/2-options.innerRadius)+", "+(options.height/2-options.innerRadius)+")","class":"menuButton",id:"gMenu"+options._id});var startAngle=0,endAngle=2*Math.PI,rectFactor=false;if(options.buttonAutoShape){var settings=this._getMenuSettings();if(!settings.circular&&(rectFactor=!!~[90,180].indexOf(Math.abs(settings.diffAngle)))){startAngle=settings.startArc.startAngle;endAngle=_degToRad(options.endAngle)}}var arc=d3.svg.arc().innerRadius(0).outerRadius(options.innerRadius).startAngle(startAngle).endAngle(endAngle);gMenu.append("path").style({fill:"url(#gradBg"+options._id+")",stroke:options.backgroundColor,"stroke-width":options.buttonStrokeWidth+"px",cursor:"pointer"}).attr({filter:"url(#dropshadow"+options._id+")",d:arc,transform:"translate("+options.innerRadius+", "+options.innerRadius+")","class":"menuButtonBg"});var menuSize=options.innerRadius/Math.sin(Math.PI/4)*0.75*(rectFactor?0.6:1),offset=(options.innerRadius-menuSize/2),ord=d3.scale.ordinal(),pad=0.2;ord.domain(d3.range(3)).rangeBands([0,menuSize],pad,0);var rectSize=ord.rangeBand(),padSize=pad*rectSize,offsetSize=rectSize*(1+pad)/2,rects=d3.range(9).map(function(n,i){var col=i%3,row=Math.floor(i/3);return{x:offset+ord(col),y:offset+ord(row),r:row,c:col}});var attrs={"class":"menuRects"};if(rectFactor){var deg=(options.startAngle+settings.diffAngle/2)%360,angleX=_degToRad(deg),angleY=angleX,factX=1,factY=1,radius=options.innerRadius*0.35,tx=0,ty=0;if(deg%180==0){factY=-1}if(deg%90!=0){angleX=options.startAngle%180==0?options.endAngle:options.startAngle;angleY=options.startAngle%180==0?options.startAngle:options.endAngle;if(angleX%180==0){factX=-1}if(angleY%180==0){factY=-1}angleX=_degToRad(angleX);angleY=_degToRad(angleY)}tx=factX*Math.sin(angleX)*radius;ty=factY*Math.cos(angleY)*radius;attrs.transform="translate("+tx+", "+ty+")"}var gRects=gMenu.append("g").attr(attrs);gRects.selectAll(".menuRect").data(rects).enter().append("rect").style({cursor:"pointer",fill:options.buttonForegroundColor,opacity:0.001}).attr({"class":"menuRect",width:rectSize,height:rectSize,transform:"translate("+(options.innerRadius-rectSize/2)+","+(options.innerRadius-rectSize/2)+")"}).transition().delay(function(d,i){return i*20}).style("opacity",1).attr("transform",function(d){return"translate("+d.x+","+d.y+")"});gMenu.on("mouseenter",mouseenter).on("mouseleave",mouseleave).on("mouseup",mouseup);function mouseenter(){if(gMenu.attr("enter")){return}gMenu.attr("enter","Y");if(gMenu.attr("press")){return}gMenu.selectAll(".menuRect").interrupt().style("opacity",1).transition().delay(function(d,i){return i*20}).attr("transform",function(d){return"translate("+(d.x+(d.c-1))+","+(d.y+(d.r-1))+") scale(1.1)"})}function mouseleave(){gMenu.attr("enter",null);if(gMenu.attr("press")){return}gMenu.selectAll(".menuRect").interrupt().transition().delay(function(d,i){return(8-i)*20}).attr("transform",function(d){return"translate("+d.x+","+d.y+")"})}function mouseup(){if(!gMenu.attr("enter")||gMenu.attr("animate")=="Y"){return}gMenu.attr("animate","Y");setTimeout(function(){gMenu.attr("animate",null)},options.speed+5);if(gMenu.attr("press")){return that.dismiss()}gMenu.attr("press","Y");gMenu.selectAll(".menuRect").interrupt().transition().duration(options.speed).attr("transform",function(d,i){var x,y;if((d.c!=1&&d.r!=1)||(d.c==1&&d.r==1)){x=rects[4].x;y=rects[4].y}else{if(d.r==1){var factor=(d.c-1);x=d.x-factor*(offsetSize-padSize*2);y=d.y+factor*(offsetSize+padSize*2)}else{var factor=d.r-1;x=d.x-factor*(offsetSize+padSize*2);y=d.y-factor*(offsetSize-padSize*2)}}return"translate("+x+","+y+") rotate(45 "+(rectSize/2)+","+(rectSize/2)+") scale("+(1+pad)+")"});that.show()}this.gMenu=gMenu;return this};menu.prototype._getMenuSettings=function(){if(this._menuSettings){return this._menuSettings}var options=this.options,items=options._items,len=items.length,isImage=!options.fontFamily,diffAngle=options.endAngle-options.startAngle,circular=Math.abs(diffAngle)==360,clockFactor=diffAngle<0?-1:1,startAngle=_degToRad(options.startAngle),stepAngle=clockFactor*_degToRad(Math.abs(diffAngle)+(circular?0:options.padAngle*2))/len,actualStepAngle=stepAngle-clockFactor*(_degToRad(options.padAngle)+_degToRad(options.menuItemStrokeWidth)),actualInnerRadius=options.innerRadius+options.spacing+options.buttonStrokeWidth/2,actualOuterRadius=options.outerRadius-options.menuItemStrokeWidth/2;var arcs={path:{arc:d3.svg.arc(),center:[options.width/2,options.height/2]}};arcs[isImage?"image":"text"]={arc:d3.svg.arc().innerRadius(actualInnerRadius).outerRadius(actualOuterRadius),center:[(options.width-options.iconSize)/2,(options.height-options.iconSize)/2]};return this._menuSettings={isImage:isImage,angles:items.map(function(n,i){var start=startAngle+stepAngle*i;return _mixin({startAngle:start,endAngle:start+actualStepAngle,outerRadius:actualOuterRadius},n)}),circular:circular,diffAngle:diffAngle,arcs:arcs,startArc:{startAngle:startAngle,endAngle:startAngle,innerRadius:actualInnerRadius,outerRadius:actualInnerRadius}}};menu.prototype.show=function(){var options=this.options,triggered=-1;var color=function(d,i,factor){return options.backgroundColor[i%2==0?"darker":"brighter"](factor||0.2)};var settings=this._getMenuSettings();var menuItems=this.svg.selectAll(".menuItem").data(settings.angles);menuItems.enter().append("g").on("mouseenter",mouseenter).on("mouseleave",mouseleave).on("mouseup",mouseup).attr("class","menuItem").style("cursor","pointer");menuItems.append("path").attr({transform:"translate("+settings.arcs.path.center+")",filter:"url(#dropshadow"+options._id+")"}).style({fill:color,stroke:function(d,i){return color(d,i).darker(0.1)},"stroke-width":options.menuItemStrokeWidth+"px"}).transition().duration(options.speed).attrTween("d",function(d,i){var interpolate=d3.interpolate(settings.startArc,d);this._current=interpolate(0);return function(t){return settings.arcs.path.arc(interpolate(t))}}).each("end",function(d,i){var g=this.parentNode;g.setAttribute("active","Y");!options.hideTooltip&&addTooltip.call(g,d,i);if(triggered==i){mouseenter.call(g,d,i)}});var iconStyles={"opacity":0.001},iconAttrs={width:options.iconSize,height:options.iconSize},iconNodeName="image";if(!settings.isImage){iconNodeName="text";_mixin(iconStyles,{opacity:1,fill:options.iconColor||options.backgroundColor.brighter(1),"font-family":options.fontFamily,"font-size":options.iconSize+"px"});iconAttrs["dominant-baseline"]="central"}menuItems.append(iconNodeName).style(iconStyles).attr(iconAttrs).each(function(d,i){var ele=d3.select(this),extAttr="";if(settings.isImage){ele.attr("xlink:href",d.icon);extAttr=" scale(0.01)"}else{ele.text(d.icon).style("fill",options.buttonForegroundColor);this._center=[(options.width-this.getBBox().width)/2,options.height/2]}ele.attr("transform","translate("+(this._center||settings.arcs[iconNodeName].center)+")"+extAttr)}).transition().duration(options.speed).delay(1).tween("ta",function(d,i){var interpolate=d3.interpolate(settings.startArc,d);this._current=interpolate(1);return function(t){var center=settings.arcs[iconNodeName].arc.centroid(interpolate(t)),ocenter=this._center||settings.arcs[iconNodeName].center,styles={opacity:t},extAttr="";if(settings.isImage){extAttr=" scale("+t+")"}else{styles["font-size"]=t*options.iconSize+"px"}d3.select(this).style(styles).attr("transform","translate("+(ocenter[0]+center[0]*t)+", "+(ocenter[1]+center[1]*t)+")"+extAttr)}});function mouseenter(d,i){triggered=i;_hover.call(this,true,function(ele){return(!ele.attr("active")||ele.attr("enter")=="Y")})}function mouseleave(){triggered=-1;_hover.call(this,false,function(ele){return(!ele.attr("active")||!ele.attr("enter"))})}var that=this;function mouseup(d,i){var ele=d3.select(this);if(!ele.attr("active")||ele.attr("press")=="Y"){return}ele.attr("press","Y");var entered=ele.attr("enter")=="Y";if(entered){menuItems.filter(function(_d,_i){return i!=_i}).transition().duration(options.speed).style("opacity",0.2)}ele.select("path").transition().duration(Math.ceil(options.speed/3)).ease("bounce").style("fill",function(){return color(d,i,0.5)}).each("end",function(){if(entered){mouseleave.call(this.parentNode,d,i,true)}menuItems.attr("active",null);that.trigger("click",i,d);that.gMenu.attr("animate","Y");setTimeout(function(){that.dismiss(true)},options.speed)})}function _hover(enter,abortPred,np){var ele=d3.select(this);if(!np&&abortPred(ele)){return}var children=this.childNodes,len=children.length;if(len==0){return}ele.attr("enter",enter?"Y":null);for(var k in children){var child=children[k];if(child._current){var nodeName=child.nodeName,center=settings.arcs[nodeName].arc.centroid(child._current),relCenter=child._center||settings.arcs[nodeName].center,isIconEle=nodeName==iconNodeName,actualCenter=[(relCenter[0]+(isIconEle?center[0]:0)),(relCenter[1]+(isIconEle?center[1]:0))];if(enter){actualCenter[0]+=center[0]*options.bounce;actualCenter[1]+=center[1]*options.bounce}d3.select(child).transition().duration(options.speed).ease("bounce").attr("transform","translate("+actualCenter+")")}else{if(child.nodeName=="g"){d3.select(child).transition().duration(options.speed/2).style("opacity",enter?0.8:0.001)}}}}var getTipCenter=function(d,i,f){if(typeof f=="undefined"){f=1}var center=settings.arcs[iconNodeName].arc.centroid(d);return[f*settings.arcs.path.center[0]+center[0]*(1+options.bounce),f*settings.arcs.path.center[1]+center[1]*(1+options.bounce)]},getTipPos=function(d,i,index){var angle=Math.atan2.apply(null,getTipCenter(d,i,0).reverse());return settings.arcs.path.center[index]+Math[index==0?"cos":"sin"](angle)*options.outerRadius*(0.8+options.bounce)},tooltipColor=options.tooltipColor||function(d,i){return color(d,i).darker(1)},tooltipBg=function(x,y,w,h,r){return"M"+(x+r)+","+y+"h"+(w-r)+"a"+r+","+r+" 0 0 1 "+r+","+r+"v"+(h-2*r)+"a"+r+","+r+" 0 0 1 "+-r+","+r+"h"+(r-w)+"a"+r+","+r+" 0 0 1 "+-r+","+-r+"v"+(2*r-h)+"a"+r+","+r+" 0 0 1 "+r+","+-r+"z"};function addTooltip(d,i){var tg=d3.select(this).append("g").attr("opacity",0.001);tg.append("circle").attr({x:0,y:0,r:2,transform:function(d,i){return"translate("+getTipCenter(d,i)+")"}}).style({fill:tooltipColor});tg.append("line").attr({x1:function(d,i){return getTipCenter(d,i)[0]},y1:function(d,i){return getTipCenter(d,i)[1]},x2:function(d,i){return getTipPos(d,i,0)},y2:function(d,i){return getTipPos(d,i,1)}}).style({stroke:tooltipColor,"stroke-width":"1px"});var txtBg=tg.append("path");var txtEle=tg.append("text").attr({x:function(d,i){return getTipPos(d,i,0)},y:function(d,i){return getTipPos(d,i,1)}}).style({"text-anchor":"middle",fill:tooltipColor}).text(function(d){return d.title});var rect=txtEle.node().getBBox();txtBg.attr({"d":tooltipBg(rect.x-10,rect.y-5,rect.width+10,rect.height+10,10),filter:"url(#dropshadow"+options._id+")"}).style({fill:"#f0f0f0",stroke:tooltipColor,"stroke-width":"1px"})}};menu.prototype.dismiss=function(inactive){var options=this.options;var settings=this._getMenuSettings();var menuItems=this.svg.selectAll(".menuItem");!inactive&&menuItems.attr("active",null);menuItems.selectAll("path").data([]).exit().transition().duration(options.speed).attrTween("d",function(d,i){var interpolate=d3.interpolate(d,settings.startArc);return function(t){return settings.arcs.path.arc(interpolate(t))}}).each("end",function(){d3.select(this.parentNode).remove()});var iconNodeName="image";if(!settings.isImage){iconNodeName="text"}menuItems.selectAll(iconNodeName).data([]).exit().transition().duration(options.speed).delay(1).tween("ta",function(d,i){var interpolate=d3.interpolate(d,settings.startArc);return function(t1){var t=1-t1;var center=settings.arcs[iconNodeName].arc.centroid(interpolate(t1)),ocenter=this._center||settings.arcs[iconNodeName].center,styles={opacity:t},extAttr="";if(settings.isImage){extAttr=" scale("+t+")"}else{styles["font-size"]=t*options.iconSize+"px"}d3.select(this).style(styles).attr("transform","translate("+(ocenter[0]+center[0]*t)+", "+(ocenter[1]+center[1]*t)+")"+extAttr)}});this.gMenu.selectAll(".menuRect").transition().duration(options.speed).attr("transform",function(d){return"translate("+d.x+","+d.y+")"});setTimeout(function(that){that.gMenu.attr({"press":null,"animate":null})},options.speed+5,this)};menu.prototype.trigger=function(n){var e=this._listeners[n];if(!e){return}var args=Array.prototype.slice.call(arguments,1);for(var i=0;i<e.length;i++){e[i].apply(this,args)}};menu.prototype.on=function(n,e){if(!n||!e){return this}(this._listeners[n]=this._listeners[n]||[]).push(e);return this};menu.prototype.off=function(n,e){if(!n||!e){n&&(delete this._listeners[n]);return this}var ls=this._listeners[n];if(!ls){return this}var es=String(e);for(var i=ls.length;i>=0;i--){if(es===String(ls[i])){ls.splice(i,1)}}return this};function _getSize(options){return(options.outerRadius+options.margin)*2}function _mixin(){if(arguments.length==0){return{}}var options=arguments[0];for(var i=1;i<arguments.length;i++){var args=arguments[i];for(var key in args){if(args.hasOwnProperty(key)){var arg=args[key];if(typeof arg=="object"&&!Array.isArray(arg)&&!/color$/i.test(key)){options[key]=_mixin(options[key]||{},arg)}else{options[key]=arg}}}}return options}function _degToRad(deg){return deg/180*Math.PI}function _radToDeg(rad){return rad*180/Math.PI}return menu(selector)}}(function(root,factory){if(typeof define==="function"&&define.amd){define(["d3"],factory)}else{if(typeof module==="object"&&module.exports){module.exports=function(d3){return d3.menu=factory(d3)}}else{root.d3.menu=factory(root.d3)}}})(this,d3menu);