diff --git a/amd/build/learningmap.min.js b/amd/build/learningmap.min.js index ec0aa2e..1315620 100644 --- a/amd/build/learningmap.min.js +++ b/amd/build/learningmap.min.js @@ -1,3 +1,3 @@ -define("mod_learningmap/learningmap",["exports","core/notification","core/templates","mod_learningmap/placestore","mod_learningmap/svg","./shapes"],(function(_exports,_notification,_templates,_placestore,_svg,_shapes){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_templates=_interopRequireDefault(_templates),_placestore=_interopRequireDefault(_placestore),_svg=_interopRequireDefault(_svg),_shapes=_interopRequireDefault(_shapes);const targetPoints_firstPoint=1,targetPoints_secondPoint=2,targetPoints_bezierPoint=3,pathTypes_line=1,pathTypes_quadraticbezier=2;_exports.init=()=>{_templates.default.prefetchTemplates(["mod_learningmap/cssskeleton"]);var offset,dragel,pathsToUpdateFirstPoint,pathsToUpdateSecondPoint,circleRadius=10,selectedElement=null,firstPlace=null,secondPlace=null,lastTarget=null,elementForActivitySelector=null,touchstart=!1,touchend=!1,touchmove=0;let mapdiv=document.getElementById("learningmap-editor-map"),code=document.getElementById("id_svgcode"),activitySetting=document.getElementById("learningmap-activity-setting"),activitySelector=document.getElementById("learningmap-activity-selector"),activityStarting=document.getElementById("learningmap-activity-starting"),activityTarget=document.getElementById("learningmap-activity-target"),activityHiddenWarning=document.getElementById("learningmap-activity-hidden-warning"),treeView=document.querySelector(".fp-viewbar .fp-vb-tree");treeView&&treeView.setAttribute("style","display: none;");let iconView=document.querySelector(".fp-viewbar .fp-vb-icons");iconView&&setTimeout((()=>{iconView.dispatchEvent(new Event("click"))}),1e3),activitySelector&&(activitySelector.addEventListener("change",(function(){if(_placestore.default.setActivityId(elementForActivitySelector,activitySelector.value),activitySelector.value){let text=document.getElementById("text"+elementForActivitySelector);text&&(text.textContent=activitySelector.querySelector('option[value="'+activitySelector.value+'"]').textContent);let title=document.getElementById("title"+elementForActivitySelector);title&&(title.textContent=activitySelector.querySelector('option[value="'+activitySelector.value+'"]').textContent),document.getElementById(elementForActivitySelector).classList.remove("learningmap-emptyplace")}else document.getElementById(elementForActivitySelector).classList.add("learningmap-emptyplace");updateActivities(),updateCode()})),activityStarting.addEventListener("change",(function(){activityStarting.checked?_placestore.default.addStartingPlace(elementForActivitySelector):_placestore.default.removeStartingPlace(elementForActivitySelector),updateCode()})),activityTarget.addEventListener("change",(function(){activityTarget.checked?(_placestore.default.addTargetPlace(elementForActivitySelector),document.getElementById(elementForActivitySelector).classList.add("learningmap-targetplace")):(_placestore.default.removeTargetPlace(elementForActivitySelector),document.getElementById(elementForActivitySelector).classList.remove("learningmap-targetplace")),updateCode()})));let placestoreInput=document.getElementsByName("placestore")[0];placestoreInput&&_placestore.default.loadJSON(placestoreInput.value),updateColorPickers(),updateActivities(),initMenu("advanced-settings",[{name:"hidepaths",get:_placestore.default.getHidePaths,set:_placestore.default.setHidePaths},{name:"showall",get:_placestore.default.getShowall,set:_placestore.default.setShowall},{name:"slicemode",get:_placestore.default.getSliceMode,set:_placestore.default.setSliceMode},{name:"showwaygone",get:_placestore.default.getShowWayGone,set:_placestore.default.setShowWayGone}]),initMenu("place-settings",[{name:"usecheckmark",get:_placestore.default.getUseCheckmark,set:_placestore.default.setUseCheckmark},{name:"hover",get:_placestore.default.getHover,set:_placestore.default.setHover},{name:"pulse",get:_placestore.default.getPulse,set:_placestore.default.setPulse},{name:"hidestroke",get:_placestore.default.getHideStroke,set:_placestore.default.setHideStroke},{name:"showtext",get:_placestore.default.getShowText,set:_placestore.default.setShowText,callback:function(){let options=Array.from(activitySelector.getElementsByTagName("option")),places=_placestore.default.getPlaces();for(const place of places)if(null===document.getElementById("text"+place.id)){let content="";for(const option of options)if(option.value==place.linkedActivity){content=option.textContent;break}let placeNode=mapsvg.findOne("#"+place.id);text("text"+place.id,content,placeNode.cx(),placeNode.cy()).addTo(placeNode.parent())}}},{name:"placesize",get:_placestore.default.getPlaceSize,set:_placestore.default.setPlaceSize,callback:function(){circleRadius=_placestore.default.getPlaceSize();let places=_placestore.default.getPlaces();for(const place of places){let placeel=getSVGShape(place.id);if(placeel){let cx=placeel.cx(),cy=placeel.cy();"text"!=placeel.type?placeel.width(2*circleRadius).height(2*circleRadius):placeel.font({size:circleRadius}),placeel.center(cx,cy)}}}},{name:"placecolor",get:_placestore.default.getPlaceColor,set:_placestore.default.setPlaceColor},{name:"visitedcolor",get:_placestore.default.getVisitedColor,set:_placestore.default.setVisitedColor},{name:"strokecolor",get:_placestore.default.getStrokeColor,set:_placestore.default.setStrokeColor}]),code&&mapdiv&&(mapdiv.innerHTML=code.value),refreshBackgroundImage(),function(){let background=document.getElementById("learningmap-background-image");background&&background.addEventListener("load",(function(){background.removeAttribute("height");let height=parseInt(background.getBBox().height),width=background.getBBox().width;_placestore.default.setBackgroundDimensions(width,height),svgel.setAttribute("viewBox","0 0 "+_placestore.default.width+" "+_placestore.default.height),background.setAttribute("width",width),background.setAttribute("height",height),updateCode()}))}(),updateCode();let svgel=document.getElementById("learningmap-svgmap-"+_placestore.default.getMapid());!function(el){dragel=el,el&&(el.addEventListener("mousedown",startDrag),el.addEventListener("mousemove",drag),el.addEventListener("mouseup",endDrag),el.addEventListener("mouseleave",endDrag),el.addEventListener("touchstart",(function(evt){evt.cancelable&&evt.preventDefault();evt.target.classList.contains("learningmap-draggable")||"text"==evt.target.nodeName||"path"==evt.target.nodeName?(touchstart?(dblclickHandler(evt),touchstart=!1):(touchstart=!0,touchmove=0,touchend=!1,setTimeout((evt=>{touchmove<3&&!touchend&&(evt.touches&&(evt=evt.touches[0]),showContextMenu(evt))}),2e3,evt),setTimeout((()=>{touchstart=!1}),300)),startDrag(evt)):touchstart?(dblclickHandler(evt),touchstart=!1):(touchstart=!0,touchend=!1,touchmove=0,setTimeout((()=>{touchstart=!1}),300))})),el.addEventListener("touchmove",drag),el.addEventListener("touchend",endTouch),el.addEventListener("touchleave",endTouch),el.addEventListener("touchcancel",endTouch));function startDrag(evt){if(evt.cancelable&&evt.preventDefault(),pathsToUpdateFirstPoint=[],pathsToUpdateSecondPoint=[],evt.target.classList.contains("learningmap-draggable")){let svgel=getSVGShape(selectedElement=evt.target);(offset=getMousePosition(evt)).x-=svgel.cx(),offset.y-=svgel.cy(),pathsToUpdateFirstPoint=_placestore.default.getPathsWithFid(evt.target.id),pathsToUpdateSecondPoint=_placestore.default.getPathsWithSid(evt.target.id)}else if("text"==evt.target.nodeName){let svgel=getSVGShape(selectedElement=evt.target),place=svgel.parent().findOne(".learningmap-place");(offset=getMousePosition(evt)).x-=svgel.attr("dx")+place.cx(),offset.y-=svgel.attr("dy")+place.cy()}else if("path"==evt.target.nodeName){selectedElement=evt.target,offset=getMousePosition(evt);let pathPoint=transformCoordinates(evt.layerX,evt.layerY);offset.x+=pathPoint.x,offset.y+=pathPoint.y}}function drag(evt){if(evt.cancelable&&evt.preventDefault(),touchmove++,selectedElement){var coord=getMousePosition(evt);let cx=coord.x-offset.x,cy=coord.y-offset.y;if(selectedElement.classList.contains("learningmap-place")){let placeel=mapsvg.findOne("#"+selectedElement.id);placeel.center(cx,cy);let textNode=mapsvg.findOne("#text"+selectedElement.id);null!==textNode&&textNode.amove(cx,cy),pathsToUpdateFirstPoint.forEach((function(path){let pathElement=getSVGShape(path);null!==pathElement&&("path"==pathElement.type?pathElement.attr({d:updatePathDeclaration(pathElement.attr("d"),cx,cy,targetPoints_firstPoint)}):pathElement.attr({x1:cx,y1:cy}))})),pathsToUpdateSecondPoint.forEach((function(path){let pathElement=getSVGShape(path);null!==pathElement&&("path"==pathElement.type?pathElement.attr({d:updatePathDeclaration(pathElement.attr("d"),cx,cy,targetPoints_secondPoint)}):pathElement.attr({x2:cx,y2:cy}))})),_placestore.default.setBbox(selectedElement.id,placeel.parent().bbox())}else if("text"==selectedElement.nodeName){let textel=getSVGShape(selectedElement),place=textel.parent().findOne(".learningmap-place"),dx=cx-place.cx(),dy=cy-place.cy();textel.attr({dx:dx,dy:dy}),_placestore.default.setBbox(place.node.id,textel.parent().bbox())}else"path"==selectedElement.nodeName&&selectedElement.setAttribute("d",updatePathDeclaration(selectedElement.getAttribute("d"),coord.x,coord.y,targetPoints_bezierPoint))}}function endDrag(evt){evt.cancelable&&evt.preventDefault(),selectedElement=null,unselectAll(),updateCode()}function endTouch(evt){selectedElement=null,touchend=!0,touchmove<3&&touchstart?clickHandler(evt):endDrag(evt),evt.cancelable&&evt.preventDefault()}function updatePathDeclaration(oldDefinition,targetX,targetY){let targetP=arguments.length>3&&void 0!==arguments[3]?arguments[3]:targetPoints_firstPoint,parts=oldDefinition.split(" "),fromX=0,fromY=0,toX=0,toY=0,bezierX=0,bezierY=0,pathType=pathTypes_line;for(let i=0;i2&&void 0!==arguments[2]?arguments[2]:null,text=arguments.length>3&&void 0!==arguments[3]?arguments[3]:null;return mapsvg.link("").id(id).add(child).add(title).add(text)}(_shapes.default.emoji(mapsvg,cx,cy,circleRadius,"learningmap-place learningmap-draggable learningmap-emptyplace",placeId),linkId,(id="title"+placeId,mapsvg.element("title").id(id)),text("text"+placeId,"",cx,cy));var id;svglink.addTo(placesgroup),_placestore.default.addPlace(placeId,linkId,null,svglink.bbox())}(event):event.target.classList.contains("learningmap-place")?lastTarget==event.target.id?(lastTarget=null,clickHandler(event)):function(event){let place=getSVGShape(event.target.id);id=event.target.id,_placestore.default.getTouchingPaths(id).forEach((function(e){removePath(e.id)})),_placestore.default.removePlace(event.target.id),place.parent().remove(),updateCode();var id}(event):event.target.classList.contains("learningmap-path")&&removePath(event.target.id),updateCode()}function text(id,content,x,y){return mapsvg.text().attr({dx:1.5*circleRadius,dy:1.5*circleRadius}).plain(content).move(x,y).id(id)}function clickHandler(event){if(event.preventDefault(),hideContextMenu(),hideOtherMenus(),event.target.classList.contains("learningmap-place")&&null===selectedElement)if(null===firstPlace)firstPlace=event.target.id,document.getElementById(firstPlace).classList.add("learningmap-selected");else{secondPlace=event.target.id;let fid=parseInt(firstPlace.replace("p","")),sid=parseInt(secondPlace.replace("p",""));if(sid==fid)return;if(sid0){let background=document.getElementById("learningmap-background-image"),backgroundurl=previewimage[0].getAttribute("src").split("?")[0];previewimage[0].getAttribute("src").split("?")[1].includes("&oid=")&&(backgroundurl+="?oid="+previewimage[0].getAttribute("src").split("&oid=")[1]),background.setAttribute("xlink:href",backgroundurl)}}function updateCSS(){_templates.default.renderForPromise("mod_learningmap/cssskeleton",_placestore.default.getPlacestore()).then((_ref=>{let{html:html,js:js}=_ref;return _templates.default.replaceNode("#learningmap-svgstyle",html,js),updateCode(),!0})).catch((ex=>(0,_notification.exception)(ex)));let placestoretemp=_placestore.default.getPlacestore();placestoretemp.mapid="preview",placestoretemp.cssid="learningmap-preview-svgstyle",placestoretemp.editmode=!1,_templates.default.renderForPromise("mod_learningmap/cssskeleton",placestoretemp).then((_ref2=>{let{html:html,js:js}=_ref2;return _templates.default.replaceNode("#learningmap-preview-svgstyle",html,js),!0})).catch((ex=>(0,_notification.exception)(ex)))}function updateActivities(){let activities=_placestore.default.getAllActivities(),options=Array.from(activitySelector.getElementsByTagName("option"));activityHiddenWarning.setAttribute("hidden",""),options.forEach((function(n){activities.includes(n.value)?(n.classList.add("learningmap-used-activity"),n.selected&&1==n.getAttribute("data-activity-hidden")&&activityHiddenWarning.removeAttribute("hidden")):n.classList.remove("learningmap-used-activity")}))}function initMenu(name,features){let icon=document.getElementById("learningmap-"+name+"-icon");if(icon){icon.addEventListener("click",(function(){!function(name){let menu=document.getElementById("learningmap-"+name+"-menu");if(menu)return null!==menu.getAttribute("hidden");return!1}(name)?hideMenu(name):function(name){let menu=document.getElementById("learningmap-"+name+"-menu");menu&&(menu.removeAttribute("hidden"),updateColorPickers(),hideOtherMenus(name),hideContextMenu())}(name)}));let close=document.getElementById("learningmap-"+name+"-close");close&&close.addEventListener("click",(function(){hideMenu(name)}))}features.forEach((function(feature){!function(type,name,getCall,setCall){let callback=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null,menuItem=document.getElementById("learningmap-"+type+"-"+name);if(menuItem)if("checkbox"===menuItem.attributes.type.nodeValue)menuItem.checked=getCall.call(_placestore.default),menuItem.addEventListener("input",(function(){setCall.call(_placestore.default,menuItem.checked),null!==callback&&callback(),updateCSS()}));else menuItem.value=getCall.call(_placestore.default),menuItem.addEventListener("input",(function(){setCall.call(_placestore.default,menuItem.value),null!==callback&&callback(),updateCSS()}))}(name,feature.name,feature.get,feature.set,feature.callback,feature.second)}))}function hideMenu(name){let menu=document.getElementById("learningmap-"+name+"-menu");menu&&menu.setAttribute("hidden","")}function hideOtherMenus(){let name=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",otherMenus=document.querySelectorAll(".learningmap-menu");otherMenus.forEach((function(menu){menu.id!="learningmap-"+name+"-menu"&&menu.setAttribute("hidden","")}))}function updateColorPickers(){document.querySelectorAll('[id^="learningmap-place-settings-jscolor-"]').forEach((function(colorpicker){colorpicker.jscolor&&colorpicker.jscolor.fromString(_placestore.default[colorpicker.id.split("jscolor-")[1]])}))}}})); +define("mod_learningmap/learningmap",["exports","core/notification","core/templates","mod_learningmap/placestore","mod_learningmap/svg","./shapes"],(function(_exports,_notification,_templates,_placestore,_svg,_shapes){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_templates=_interopRequireDefault(_templates),_placestore=_interopRequireDefault(_placestore),_svg=_interopRequireDefault(_svg),_shapes=_interopRequireDefault(_shapes);const targetPoints_firstPoint=1,targetPoints_secondPoint=2,targetPoints_bezierPoint=3,pathTypes_line=1,pathTypes_quadraticbezier=2;_exports.init=()=>{_templates.default.prefetchTemplates(["mod_learningmap/cssskeleton"]);var offset,dragel,pathsToUpdateFirstPoint,pathsToUpdateSecondPoint,circleRadius=10,selectedElement=null,firstPlace=null,secondPlace=null,lastTarget=null,elementForActivitySelector=null,touchstart=!1,touchend=!1,touchmove=0;let mapdiv=document.getElementById("learningmap-editor-map"),code=document.getElementById("id_svgcode"),activitySetting=document.getElementById("learningmap-activity-setting"),activitySelector=document.getElementById("learningmap-activity-selector"),activityStarting=document.getElementById("learningmap-activity-starting"),activityTarget=document.getElementById("learningmap-activity-target"),activityHiddenWarning=document.getElementById("learningmap-activity-hidden-warning"),treeView=document.querySelector(".fp-viewbar .fp-vb-tree");treeView&&treeView.setAttribute("style","display: none;");let iconView=document.querySelector(".fp-viewbar .fp-vb-icons");iconView&&setTimeout((()=>{iconView.dispatchEvent(new Event("click"))}),1e3),activitySelector&&(activitySelector.addEventListener("change",(function(){if(_placestore.default.setActivityId(elementForActivitySelector,activitySelector.value),activitySelector.value){let text=document.getElementById("text"+elementForActivitySelector);text&&(text.textContent=activitySelector.querySelector('option[value="'+activitySelector.value+'"]').textContent);let title=document.getElementById("title"+elementForActivitySelector);title&&(title.textContent=activitySelector.querySelector('option[value="'+activitySelector.value+'"]').textContent),document.getElementById(elementForActivitySelector).classList.remove("learningmap-emptyplace")}else document.getElementById(elementForActivitySelector).classList.add("learningmap-emptyplace");updateActivities(),updateCode()})),activityStarting.addEventListener("change",(function(){activityStarting.checked?_placestore.default.addStartingPlace(elementForActivitySelector):_placestore.default.removeStartingPlace(elementForActivitySelector),updateCode()})),activityTarget.addEventListener("change",(function(){activityTarget.checked?(_placestore.default.addTargetPlace(elementForActivitySelector),document.getElementById(elementForActivitySelector).classList.add("learningmap-targetplace")):(_placestore.default.removeTargetPlace(elementForActivitySelector),document.getElementById(elementForActivitySelector).classList.remove("learningmap-targetplace")),updateCode()})));let placestoreInput=document.getElementsByName("placestore")[0];placestoreInput&&_placestore.default.loadJSON(placestoreInput.value),updateColorPickers(),updateActivities(),initMenu("advanced-settings",[{name:"hidepaths",get:_placestore.default.getHidePaths,set:_placestore.default.setHidePaths},{name:"showall",get:_placestore.default.getShowall,set:_placestore.default.setShowall},{name:"slicemode",get:_placestore.default.getSliceMode,set:_placestore.default.setSliceMode},{name:"showwaygone",get:_placestore.default.getShowWayGone,set:_placestore.default.setShowWayGone}]),initMenu("place-settings",[{name:"usecheckmark",get:_placestore.default.getUseCheckmark,set:_placestore.default.setUseCheckmark},{name:"hover",get:_placestore.default.getHover,set:_placestore.default.setHover},{name:"pulse",get:_placestore.default.getPulse,set:_placestore.default.setPulse},{name:"hidestroke",get:_placestore.default.getHideStroke,set:_placestore.default.setHideStroke},{name:"showtext",get:_placestore.default.getShowText,set:_placestore.default.setShowText,callback:function(){let options=Array.from(activitySelector.getElementsByTagName("option")),places=_placestore.default.getPlaces(),textgroup=mapsvg.findOne(".learningmap-text-group");for(const place of places)if(null===document.getElementById("text"+place.id)){let content="";for(const option of options)if(option.value==place.linkedActivity){content=option.textContent;break}let placeNode=mapsvg.findOne("#"+place.id);text("text"+place.id,content,placeNode.cx(),placeNode.cy()).addTo(textgroup)}else{mapsvg.findOne("#text"+place.id).addTo(textgroup)}}},{name:"placesize",get:_placestore.default.getPlaceSize,set:_placestore.default.setPlaceSize,callback:function(){circleRadius=_placestore.default.getPlaceSize();let places=_placestore.default.getPlaces();for(const place of places){let placeel=getSVGShape(place.id);if(placeel){let cx=placeel.cx(),cy=placeel.cy();"text"!=placeel.type?placeel.width(2*circleRadius).height(2*circleRadius):placeel.font({size:circleRadius}),placeel.center(cx,cy)}}}},{name:"placecolor",get:_placestore.default.getPlaceColor,set:_placestore.default.setPlaceColor},{name:"visitedcolor",get:_placestore.default.getVisitedColor,set:_placestore.default.setVisitedColor},{name:"strokecolor",get:_placestore.default.getStrokeColor,set:_placestore.default.setStrokeColor},{name:"textcolor",get:_placestore.default.getTextColor,set:_placestore.default.setTextColor}]),code&&mapdiv&&(mapdiv.innerHTML=code.value),refreshBackgroundImage(),function(){let background=document.getElementById("learningmap-background-image");background&&background.addEventListener("load",(function(){background.removeAttribute("height");let height=parseInt(background.getBBox().height),width=background.getBBox().width;_placestore.default.setBackgroundDimensions(width,height),svgel.setAttribute("viewBox","0 0 "+_placestore.default.width+" "+_placestore.default.height),background.setAttribute("width",width),background.setAttribute("height",height),updateCode()}))}(),updateCode();let svgel=document.getElementById("learningmap-svgmap-"+_placestore.default.getMapid());!function(el){dragel=el,el&&(el.addEventListener("mousedown",startDrag),el.addEventListener("mousemove",drag),el.addEventListener("mouseup",endDrag),el.addEventListener("mouseleave",endDrag),el.addEventListener("touchstart",(function(evt){evt.cancelable&&evt.preventDefault();evt.target.classList.contains("learningmap-draggable")||"text"==evt.target.nodeName||"path"==evt.target.nodeName?(touchstart?(dblclickHandler(evt),touchstart=!1):(touchstart=!0,touchmove=0,touchend=!1,setTimeout((evt=>{touchmove<3&&!touchend&&(evt.touches&&(evt=evt.touches[0]),showContextMenu(evt))}),2e3,evt),setTimeout((()=>{touchstart=!1}),300)),startDrag(evt)):touchstart?(dblclickHandler(evt),touchstart=!1):(touchstart=!0,touchend=!1,touchmove=0,setTimeout((()=>{touchstart=!1}),300))})),el.addEventListener("touchmove",drag),el.addEventListener("touchend",endTouch),el.addEventListener("touchleave",endTouch),el.addEventListener("touchcancel",endTouch));function startDrag(evt){if(evt.cancelable&&evt.preventDefault(),pathsToUpdateFirstPoint=[],pathsToUpdateSecondPoint=[],evt.target.classList.contains("learningmap-draggable")){let svgel=getSVGShape(selectedElement=evt.target);(offset=getMousePosition(evt)).x-=svgel.cx(),offset.y-=svgel.cy(),pathsToUpdateFirstPoint=_placestore.default.getPathsWithFid(evt.target.id),pathsToUpdateSecondPoint=_placestore.default.getPathsWithSid(evt.target.id)}else if("text"==evt.target.nodeName){let svgel=getSVGShape(selectedElement=evt.target),place=findPlaceForText(selectedElement.id);(offset=getMousePosition(evt)).x-=svgel.attr("dx")+place.cx(),offset.y-=svgel.attr("dy")+place.cy()}else if("path"==evt.target.nodeName){selectedElement=evt.target,offset=getMousePosition(evt);let pathPoint=transformCoordinates(evt.layerX,evt.layerY);offset.x+=pathPoint.x,offset.y+=pathPoint.y}}function drag(evt){if(evt.cancelable&&evt.preventDefault(),touchmove++,selectedElement){var coord=getMousePosition(evt);let cx=coord.x-offset.x,cy=coord.y-offset.y;if(selectedElement.classList.contains("learningmap-place")){mapsvg.findOne("#"+selectedElement.id).center(cx,cy);let textNode=mapsvg.findOne("#text"+selectedElement.id);null!==textNode&&textNode.amove(cx,cy),pathsToUpdateFirstPoint.forEach((function(path){let pathElement=getSVGShape(path);null!==pathElement&&("path"==pathElement.type?pathElement.attr({d:updatePathDeclaration(pathElement.attr("d"),cx,cy,targetPoints_firstPoint)}):pathElement.attr({x1:cx,y1:cy}))})),pathsToUpdateSecondPoint.forEach((function(path){let pathElement=getSVGShape(path);null!==pathElement&&("path"==pathElement.type?pathElement.attr({d:updatePathDeclaration(pathElement.attr("d"),cx,cy,targetPoints_secondPoint)}):pathElement.attr({x2:cx,y2:cy}))}))}else if("text"==selectedElement.nodeName){let textel=getSVGShape(selectedElement),place=findPlaceForText(selectedElement.id),dx=cx-place.cx(),dy=cy-place.cy();textel.attr({dx:dx,dy:dy})}else"path"==selectedElement.nodeName&&selectedElement.setAttribute("d",updatePathDeclaration(selectedElement.getAttribute("d"),coord.x,coord.y,targetPoints_bezierPoint))}}function endDrag(evt){evt.cancelable&&evt.preventDefault(),selectedElement=null,unselectAll(),updateCode()}function endTouch(evt){selectedElement=null,touchend=!0,touchmove<3&&touchstart?clickHandler(evt):endDrag(evt),evt.cancelable&&evt.preventDefault()}function updatePathDeclaration(oldDefinition,targetX,targetY){let targetP=arguments.length>3&&void 0!==arguments[3]?arguments[3]:targetPoints_firstPoint,parts=oldDefinition.split(" "),fromX=0,fromY=0,toX=0,toY=0,bezierX=0,bezierY=0,pathType=pathTypes_line;for(let i=0;i2&&void 0!==arguments[2]?arguments[2]:null;return mapsvg.link("").id(id).add(child).add(title)}(_shapes.default.circle(mapsvg,cx,cy,circleRadius,"learningmap-place learningmap-draggable learningmap-emptyplace",placeId),linkId,(id="title"+placeId,mapsvg.element("title").id(id)));var id;svglink.addTo(placesgroup),text("text"+placeId,"",cx,cy).addTo(textgroup),_placestore.default.addPlace(placeId,linkId,null,svglink.bbox())}(event):event.target.classList.contains("learningmap-place")?lastTarget==event.target.id?(lastTarget=null,clickHandler(event)):function(event){let place=getSVGShape(event.target.id);id=event.target.id,_placestore.default.getTouchingPaths(id).forEach((function(e){removePath(e.id)})),_placestore.default.removePlace(event.target.id),place.parent().remove();var id;let textNode=document.getElementById("text"+event.target.id);textNode&&textNode.remove();updateCode()}(event):event.target.classList.contains("learningmap-path")&&removePath(event.target.id),updateCode()}function text(id,content,x,y){return mapsvg.text().attr({dx:1.5*circleRadius,dy:1.5*circleRadius}).plain(content).move(x,y).id(id)}function clickHandler(event){if(event.preventDefault(),hideContextMenu(),hideOtherMenus(),event.target.classList.contains("learningmap-place")&&null===selectedElement)if(null===firstPlace)firstPlace=event.target.id,document.getElementById(firstPlace).classList.add("learningmap-selected");else{secondPlace=event.target.id;let fid=parseInt(firstPlace.replace("p","")),sid=parseInt(secondPlace.replace("p",""));if(sid==fid)return;if(sid0){let background=document.getElementById("learningmap-background-image"),backgroundurl=previewimage[0].getAttribute("src").split("?")[0];previewimage[0].getAttribute("src").split("?")[1].includes("&oid=")&&(backgroundurl+="?oid="+previewimage[0].getAttribute("src").split("&oid=")[1]),background.setAttribute("xlink:href",backgroundurl)}}function updateCSS(){_templates.default.renderForPromise("mod_learningmap/cssskeleton",_placestore.default.getPlacestore()).then((_ref=>{let{html:html,js:js}=_ref;return _templates.default.replaceNode("#learningmap-svgstyle",html,js),updateCode(),!0})).catch((ex=>(0,_notification.exception)(ex)));let placestoretemp=_placestore.default.getPlacestore();placestoretemp.mapid="preview",placestoretemp.cssid="learningmap-preview-svgstyle",placestoretemp.editmode=!1,_templates.default.renderForPromise("mod_learningmap/cssskeleton",placestoretemp).then((_ref2=>{let{html:html,js:js}=_ref2;return _templates.default.replaceNode("#learningmap-preview-svgstyle",html,js),!0})).catch((ex=>(0,_notification.exception)(ex)))}function updateActivities(){let activities=_placestore.default.getAllActivities(),options=Array.from(activitySelector.getElementsByTagName("option"));activityHiddenWarning.setAttribute("hidden",""),options.forEach((function(n){activities.includes(n.value)?(n.classList.add("learningmap-used-activity"),n.selected&&1==n.getAttribute("data-activity-hidden")&&activityHiddenWarning.removeAttribute("hidden")):n.classList.remove("learningmap-used-activity")}))}function initMenu(name,features){let icon=document.getElementById("learningmap-"+name+"-icon");if(icon){icon.addEventListener("click",(function(){!function(name){let menu=document.getElementById("learningmap-"+name+"-menu");if(menu)return null!==menu.getAttribute("hidden");return!1}(name)?hideMenu(name):function(name){let menu=document.getElementById("learningmap-"+name+"-menu");menu&&(menu.removeAttribute("hidden"),updateColorPickers(),hideOtherMenus(name),hideContextMenu())}(name)}));let close=document.getElementById("learningmap-"+name+"-close");close&&close.addEventListener("click",(function(){hideMenu(name)}))}features.forEach((function(feature){!function(type,name,getCall,setCall){let callback=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null,menuItem=document.getElementById("learningmap-"+type+"-"+name);if(menuItem)if("checkbox"===menuItem.attributes.type.nodeValue)menuItem.checked=getCall.call(_placestore.default),menuItem.addEventListener("input",(function(){setCall.call(_placestore.default,menuItem.checked),null!==callback&&callback(),updateCSS()}));else menuItem.value=getCall.call(_placestore.default),menuItem.addEventListener("input",(function(){setCall.call(_placestore.default,menuItem.value),null!==callback&&callback(),updateCSS()}))}(name,feature.name,feature.get,feature.set,feature.callback,feature.second)}))}function hideMenu(name){let menu=document.getElementById("learningmap-"+name+"-menu");menu&&menu.setAttribute("hidden","")}function hideOtherMenus(){let name=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",otherMenus=document.querySelectorAll(".learningmap-menu");otherMenus.forEach((function(menu){menu.id!="learningmap-"+name+"-menu"&&menu.setAttribute("hidden","")}))}function updateColorPickers(){document.querySelectorAll('[id^="learningmap-place-settings-jscolor-"]').forEach((function(colorpicker){colorpicker.jscolor&&colorpicker.jscolor.fromString(_placestore.default[colorpicker.id.split("jscolor-")[1]])}))}function findPlaceForText(textId){let placename=textId.replace("text","");return mapsvg.findOne("#"+placename)}}})); //# sourceMappingURL=learningmap.min.js.map \ No newline at end of file diff --git a/amd/build/learningmap.min.js.map b/amd/build/learningmap.min.js.map index bcc5fb6..a909871 100644 --- a/amd/build/learningmap.min.js.map +++ b/amd/build/learningmap.min.js.map @@ -1 +1 @@ -{"version":3,"file":"learningmap.min.js","sources":["../src/learningmap.js"],"sourcesContent":["import {exception as displayException} from 'core/notification';\nimport Templates from 'core/templates';\nimport placestore from 'mod_learningmap/placestore';\nimport svgjs from 'mod_learningmap/svg';\nimport shapes from './shapes';\n\n// Constants for updatePathDeclaration.\nconst targetPoints = {\n firstPoint: 1,\n secondPoint: 2,\n bezierPoint: 3,\n};\n\nconst pathTypes = {\n line: 1,\n quadraticbezier: 2,\n};\n\nexport const init = () => {\n // Load the needed template on startup for better execution speed.\n Templates.prefetchTemplates(['mod_learningmap/cssskeleton']);\n\n // Size for the new circles. This will be overriden by placesize from the placestore.\n var circleRadius = 10;\n\n // Variable for storing the mouse offset\n var offset;\n\n // Variable for draggable element\n var dragel;\n\n // Variables for storing the paths that need update of the first or\n // the second coordinates.\n var pathsToUpdateFirstPoint, pathsToUpdateSecondPoint;\n\n // Variables for handling the currently selected elements\n var selectedElement = null,\n firstPlace = null,\n secondPlace = null,\n lastTarget = null;\n\n // Variable for storing the selected element for the activity selector\n var elementForActivitySelector = null;\n\n // Variables for simulating double click on touch devices, set when the\n // corresponding events are handled\n var touchstart = false;\n var touchend = false;\n // Counter for touchmove events\n var touchmove = 0;\n\n // DOM nodes for the editor\n let mapdiv = document.getElementById('learningmap-editor-map');\n let code = document.getElementById('id_svgcode');\n\n // DOM nodes for the activity selector\n let activitySetting = document.getElementById('learningmap-activity-setting');\n let activitySelector = document.getElementById('learningmap-activity-selector');\n let activityStarting = document.getElementById('learningmap-activity-starting');\n let activityTarget = document.getElementById('learningmap-activity-target');\n let activityHiddenWarning = document.getElementById('learningmap-activity-hidden-warning');\n\n // Hide tree view as there is no preview file we can attach to\n let treeView = document.querySelector('.fp-viewbar .fp-vb-tree');\n if (treeView) {\n treeView.setAttribute('style', 'display: none;');\n }\n\n // Trigger click event on icon view to ensure that tree view is not active.\n let iconView = document.querySelector('.fp-viewbar .fp-vb-icons');\n if (iconView) {\n // Handle possible delay in form loading.\n setTimeout(() => {\n iconView.dispatchEvent(new Event('click'));\n }, 1000);\n }\n\n // Attach listeners to the activity selector\n if (activitySelector) {\n // Show places that are not linked to an activity\n activitySelector.addEventListener('change', function() {\n placestore.setActivityId(elementForActivitySelector, activitySelector.value);\n if (activitySelector.value) {\n let text = document.getElementById('text' + elementForActivitySelector);\n if (text) {\n text.textContent = activitySelector.querySelector('option[value=\"' + activitySelector.value + '\"]').textContent;\n }\n let title = document.getElementById('title' + elementForActivitySelector);\n if (title) {\n title.textContent =\n activitySelector.querySelector('option[value=\"' + activitySelector.value + '\"]').textContent;\n }\n document.getElementById(elementForActivitySelector).classList.remove('learningmap-emptyplace');\n } else {\n document.getElementById(elementForActivitySelector).classList.add('learningmap-emptyplace');\n }\n updateActivities();\n updateCode();\n });\n // Add / remove a place to the starting places array\n activityStarting.addEventListener('change', function() {\n if (activityStarting.checked) {\n placestore.addStartingPlace(elementForActivitySelector);\n } else {\n placestore.removeStartingPlace(elementForActivitySelector);\n }\n updateCode();\n });\n // Add / remove a place to the target places array\n activityTarget.addEventListener('change', function() {\n if (activityTarget.checked) {\n placestore.addTargetPlace(elementForActivitySelector);\n document.getElementById(elementForActivitySelector).classList.add('learningmap-targetplace');\n } else {\n placestore.removeTargetPlace(elementForActivitySelector);\n document.getElementById(elementForActivitySelector).classList.remove('learningmap-targetplace');\n }\n updateCode();\n });\n }\n\n // Load placestore values from the hidden input field\n let placestoreInput = document.getElementsByName('placestore')[0];\n if (placestoreInput) {\n placestore.loadJSON(placestoreInput.value);\n }\n\n updateColorPickers();\n\n // Mark all activities in the placestore as \"used\".\n updateActivities();\n\n // Inititalize the menus.\n initMenu('advanced-settings', [\n {name: 'hidepaths', get: placestore.getHidePaths, set: placestore.setHidePaths},\n {name: 'showall', get: placestore.getShowall, set: placestore.setShowall},\n {name: 'slicemode', get: placestore.getSliceMode, set: placestore.setSliceMode},\n {name: 'showwaygone', get: placestore.getShowWayGone, set: placestore.setShowWayGone},\n ]);\n\n initMenu('place-settings', [\n {name: 'usecheckmark', get: placestore.getUseCheckmark, set: placestore.setUseCheckmark},\n {name: 'hover', get: placestore.getHover, set: placestore.setHover},\n {name: 'pulse', get: placestore.getPulse, set: placestore.setPulse},\n {name: 'hidestroke', get: placestore.getHideStroke, set: placestore.setHideStroke},\n {name: 'showtext', get: placestore.getShowText, set: placestore.setShowText, callback: fixPlaceLabels},\n {name: 'placesize', get: placestore.getPlaceSize, set: placestore.setPlaceSize, callback: updatePlaceSize},\n {name: 'placecolor', get: placestore.getPlaceColor, set: placestore.setPlaceColor},\n {name: 'visitedcolor', get: placestore.getVisitedColor, set: placestore.setVisitedColor},\n {name: 'strokecolor', get: placestore.getStrokeColor, set: placestore.setStrokeColor},\n ]);\n\n // Get SVG code from the (hidden) textarea field\n if (code && mapdiv) {\n mapdiv.innerHTML = code.value;\n }\n // Reload background image to get the correct width and height values\n refreshBackgroundImage();\n registerBackgroundListener();\n updateCode();\n\n // Enable dragging of places\n let svgel = document.getElementById('learningmap-svgmap-' + placestore.getMapid());\n makeDraggable(svgel);\n var mapsvg = svgjs().SVG('#learningmap-svgmap-' + placestore.getMapid());\n\n // Refresh stylesheet values from placestore\n updateCSS();\n\n // Add listeners for clicking and context menu\n if (mapdiv) {\n mapdiv.addEventListener('dblclick', dblclickHandler);\n mapdiv.addEventListener('click', clickHandler);\n\n mapdiv.addEventListener('contextmenu', function(e) {\n e.preventDefault();\n showContextMenu(e);\n }, false);\n }\n /**\n * Shows the context menu at the current mouse position\n * @param {*} e\n */\n function showContextMenu(e) {\n unselectAll();\n hideOtherMenus();\n // Check for the existence of the target (could have vanished since the event started).\n if (activitySetting && document.getElementById(e.target.id) !== null) {\n if (e.touches) {\n e = e.touches[0];\n }\n if (e.target.classList.contains('learningmap-place')) {\n let element = getSVGShape(e.target.id);\n e.target.classList.add('learningmap-selected-activity-selector');\n let activityId = placestore.getActivityId(e.target.id);\n let scalingFactor = mapdiv.clientWidth / 800;\n activitySetting.style.setProperty('--pos-x', element.cx() * scalingFactor + 'px');\n activitySetting.style.setProperty('--pos-y', element.cy() * scalingFactor + 'px');\n activitySetting.style.setProperty('--map-width', mapdiv.clientWidth + 'px');\n activitySetting.style.setProperty('--map-height', mapdiv.clientHeight + 'px');\n activitySetting.style.display = 'block';\n document.getElementById('learningmap-activity-selector').value = activityId;\n document.getElementById('learningmap-activity-starting').checked = placestore.isStartingPlace(e.target.id);\n document.getElementById('learningmap-activity-target').checked = placestore.isTargetPlace(e.target.id);\n elementForActivitySelector = e.target.id;\n updateActivities();\n } else {\n hideContextMenu();\n hideOtherMenus();\n }\n }\n }\n\n /**\n * Hides the context menu\n */\n function hideContextMenu() {\n let e = document.getElementById(elementForActivitySelector);\n if (e) {\n e.classList.remove('learningmap-selected-activity-selector');\n }\n activitySetting.style.display = 'none';\n }\n\n let backgroundfileNode = document.getElementById('id_backgroundfile_fieldset');\n if (backgroundfileNode) {\n let observer = new MutationObserver(refreshBackgroundImage);\n observer.observe(backgroundfileNode, {attributes: true, childList: true, subtree: true});\n }\n\n /**\n * Helper function for getting the right coordinates from the mouse\n * @param {*} evt\n * @returns {object}\n */\n function getMousePosition(evt) {\n if (evt.touches) {\n evt = evt.touches[0];\n }\n return transformCoordinates(evt.clientX, evt.clientY);\n }\n\n /**\n * Transforms client coordinates to SVG coordinates\n * @param {number} x x coordinate to transform\n * @param {number} y y coordinate to transform\n * @returns {object} Object containing transformed x and y coordinate\n */\n function transformCoordinates(x, y) {\n var CTM = dragel.getScreenCTM();\n return {\n x: (x - CTM.e) / CTM.a,\n y: (y - CTM.f) / CTM.d\n };\n }\n\n /**\n * Returns the SVG shape with the given id or representing the\n * given object.\n * @param {*} element\n * @returns\n */\n function getSVGShape(element) {\n if (typeof element === 'object') {\n return mapsvg.findOne('#' + element.id);\n } else {\n return mapsvg.findOne('#' + element);\n }\n }\n\n /**\n * Enables dragging on an DOM node\n * @param {*} el\n */\n function makeDraggable(el) {\n dragel = el;\n if (el) {\n el.addEventListener('mousedown', startDrag);\n el.addEventListener('mousemove', drag);\n el.addEventListener('mouseup', endDrag);\n el.addEventListener('mouseleave', endDrag);\n el.addEventListener('touchstart', startTouch);\n el.addEventListener('touchmove', drag);\n el.addEventListener('touchend', endTouch);\n el.addEventListener('touchleave', endTouch);\n el.addEventListener('touchcancel', endTouch);\n }\n\n /**\n * Function called whenn dragging starts.\n * @param {*} evt\n */\n function startDrag(evt) {\n if (evt.cancelable) {\n evt.preventDefault();\n }\n pathsToUpdateFirstPoint = [];\n pathsToUpdateSecondPoint = [];\n if (evt.target.classList.contains('learningmap-draggable')) {\n selectedElement = evt.target;\n let svgel = getSVGShape(selectedElement);\n offset = getMousePosition(evt);\n offset.x -= svgel.cx();\n offset.y -= svgel.cy();\n // Get paths that need to be updated.\n pathsToUpdateFirstPoint = placestore.getPathsWithFid(evt.target.id);\n pathsToUpdateSecondPoint = placestore.getPathsWithSid(evt.target.id);\n } else if (evt.target.nodeName == 'text') {\n selectedElement = evt.target;\n let svgel = getSVGShape(selectedElement);\n let place = svgel.parent().findOne('.learningmap-place');\n offset = getMousePosition(evt);\n offset.x -= svgel.attr('dx') + place.cx();\n offset.y -= svgel.attr('dy') + place.cy();\n } else if (evt.target.nodeName == 'path') {\n selectedElement = evt.target;\n offset = getMousePosition(evt);\n let pathPoint = transformCoordinates(evt.layerX, evt.layerY);\n offset.x += pathPoint.x;\n offset.y += pathPoint.y;\n }\n }\n\n /**\n * Function called during dragging. Continuously updates places center coordinates and the\n * coordinates of the touching paths.\n * @param {*} evt\n */\n function drag(evt) {\n if (evt.cancelable) {\n evt.preventDefault();\n }\n // Count touchmove events\n touchmove++;\n if (selectedElement) {\n var coord = getMousePosition(evt);\n let cx = coord.x - offset.x;\n let cy = coord.y - offset.y;\n if (selectedElement.classList.contains('learningmap-place')) {\n let placeel = mapsvg.findOne('#' + selectedElement.id);\n placeel.center(cx, cy);\n let textNode = mapsvg.findOne('#text' + selectedElement.id);\n if (textNode !== null) {\n textNode.amove(cx, cy);\n }\n pathsToUpdateFirstPoint.forEach(function(path) {\n let pathElement = getSVGShape(path);\n if (pathElement !== null) {\n if (pathElement.type == 'path') {\n pathElement.attr(\n {'d': updatePathDeclaration(pathElement.attr('d'), cx, cy, targetPoints.firstPoint)}\n );\n } else {\n pathElement.attr({'x1': cx, 'y1': cy});\n }\n }\n });\n\n pathsToUpdateSecondPoint.forEach(function(path) {\n let pathElement = getSVGShape(path);\n if (pathElement !== null) {\n if (pathElement.type == 'path') {\n pathElement.attr(\n {'d': updatePathDeclaration(pathElement.attr('d'), cx, cy, targetPoints.secondPoint)}\n );\n } else {\n pathElement.attr({'x2': cx, 'y2': cy});\n }\n }\n });\n placestore.setBbox(selectedElement.id, placeel.parent().bbox());\n } else if (selectedElement.nodeName == 'text') {\n let textel = getSVGShape(selectedElement);\n let place = textel.parent().findOne('.learningmap-place');\n // Calculate the delta from the current mouse position to the corresponding place.\n // coord: current mouse position\n // offset: delta from the mouse position to the coordinates of the text node\n let dx = cx - place.cx();\n let dy = cy - place.cy();\n // We cannot use the dx() and dy() functions of the text node, because they are not\n // setting the attributes dx and dy.\n textel.attr({dx: dx, dy: dy});\n placestore.setBbox(place.node.id, textel.parent().bbox());\n } else if (selectedElement.nodeName == 'path') {\n selectedElement.setAttribute(\n 'd',\n updatePathDeclaration(selectedElement.getAttribute('d'), coord.x, coord.y, targetPoints.bezierPoint)\n );\n }\n }\n }\n\n /**\n * Function called when dragging ends.\n * @param {*} evt\n */\n function endDrag(evt) {\n if (evt.cancelable) {\n evt.preventDefault();\n }\n selectedElement = null;\n unselectAll();\n updateCode();\n }\n\n /**\n * Function called when touchstart event occurs.\n * @param {*} evt\n */\n function startTouch(evt) {\n if (evt.cancelable) {\n evt.preventDefault();\n }\n if (\n evt.target.classList.contains('learningmap-draggable') ||\n evt.target.nodeName == 'text' ||\n evt.target.nodeName == 'path'\n ) {\n if (!touchstart) {\n touchstart = true;\n touchmove = 0;\n touchend = false;\n setTimeout(\n (evt) => {\n if (touchmove < 3 && !touchend) {\n if (evt.touches) {\n evt = evt.touches[0];\n }\n showContextMenu(evt);\n }\n },\n 2000,\n evt\n );\n setTimeout(\n () => {\n touchstart = false;\n },\n 300);\n } else {\n dblclickHandler(evt);\n touchstart = false;\n }\n startDrag(evt);\n } else {\n if (!touchstart) {\n touchstart = true;\n touchend = false;\n touchmove = 0;\n setTimeout(\n () => {\n touchstart = false;\n },\n 300);\n } else {\n dblclickHandler(evt);\n touchstart = false;\n }\n }\n }\n\n /**\n * Function called when touchend, touchleave or touchcancel event occurs.\n * @param {*} evt\n */\n function endTouch(evt) {\n selectedElement = null;\n touchend = true;\n // If there was only a small move (<3 move events), this also counts as a click.\n if (touchmove < 3 && touchstart) {\n clickHandler(evt);\n } else {\n endDrag(evt);\n }\n if (evt.cancelable) {\n evt.preventDefault();\n }\n }\n\n /**\n * Updates the path declaration of lines and quadratic bezier curves setting one of the points.\n * @param {string} oldDefinition SVG path definition string\n * @param {number} targetX x coordinate of the point to set\n * @param {number} targetY y coordinate of the point to set\n * @param {number} targetP Which point to change (you can use the targetPoints constants here)\n * @returns {string} Updated SVG path definition\n */\n function updatePathDeclaration(oldDefinition, targetX, targetY, targetP = targetPoints.firstPoint) {\n let parts = oldDefinition.split(' ');\n let fromX = 0;\n let fromY = 0;\n let toX = 0;\n let toY = 0;\n let bezierX = 0;\n let bezierY = 0;\n let pathType = pathTypes.line;\n\n // The d attribute of an SVG path in a learning map can have two different formats (in this version):\n // \"M x1 y1 L x2 y2\" Line from x1, y1 to x2, y2\n // \"M x1 y2 Q x3 y3 x2 y2\" Quadratic bezier curve inside the triangle defined by x1, y1, x2, y2 and x3, y3.\n for (let i = 0; i < parts.length; i++) {\n // Every path contains the first point in that way.\n if (parts[i] == 'M') {\n fromX = parseInt(parts[i + 1]);\n fromY = parseInt(parts[i + 2]);\n i += 2;\n }\n // This path is a direct line, so there are only two points in total.\n if (parts[i] == 'L') {\n toX = parseInt(parts[i + 1]);\n toY = parseInt(parts[i + 2]);\n i += 2;\n }\n // This path is a bezier curve, there are three points in total.\n if (parts[i] == 'Q') {\n bezierX = parseInt(parts[i + 1]);\n bezierY = parseInt(parts[i + 2]);\n toX = parseInt(parts[i + 3]);\n toY = parseInt(parts[i + 4]);\n i += 4;\n pathType = pathTypes.quadraticbezier;\n }\n }\n\n switch (targetP) {\n case targetPoints.firstPoint:\n fromX = targetX;\n fromY = targetY;\n break;\n case targetPoints.secondPoint:\n toX = targetX;\n toY = targetY;\n break;\n case targetPoints.bezierPoint:\n // Calculate the third triangle point for the bezier curve.\n bezierX = targetX * 2 - (fromX + toX) * 0.5;\n bezierY = targetY * 2 - (fromY + toY) * 0.5;\n pathType = pathTypes.quadraticbezier;\n break;\n }\n\n if (pathType == pathTypes.quadraticbezier) {\n return 'M ' + fromX + ' ' + fromY + ' Q ' + bezierX + ' ' + bezierY + ', ' + toX + ' ' + toY;\n } else {\n return 'M ' + fromX + ' ' + fromY + ' L ' + toX + ' ' + toY;\n }\n }\n }\n\n /**\n * Updates the form fields for the SVG code and the placestore from the editor.\n */\n function updateCode() {\n if (code && mapdiv) {\n code.innerHTML = mapdiv.innerHTML;\n }\n if (placestoreInput) {\n document.getElementsByName('placestore')[0].value = JSON.stringify(placestore.getPlacestore());\n }\n }\n\n /**\n * Handles double clicks on the map\n * @param {*} event\n */\n function dblclickHandler(event) {\n hideContextMenu();\n hideOtherMenus();\n unselectAll();\n if (event.target.classList.contains('learningmap-mapcontainer') ||\n event.target.classList.contains('learningmap-background-image')) {\n addPlace(event);\n } else if (event.target.classList.contains('learningmap-place')) {\n if (lastTarget == event.target.id) {\n lastTarget = null;\n clickHandler(event);\n } else {\n removePlace(event);\n }\n } else if (event.target.classList.contains('learningmap-path')) {\n removePath(event.target.id);\n }\n updateCode();\n }\n\n /**\n * Returns an empty title tag with the given id.\n * @param {*} id id for the title\n * @returns {any}\n */\n function title(id) {\n return mapsvg.element('title').id(id);\n }\n\n /**\n * Returns an text tag with the given id.\n * @param {*} id id for the text\n * @param {*} content content of the tag\n * @param {*} x x coordinate of the text\n * @param {*} y y coordinate of the text\n * @returns {any}\n */\n function text(id, content, x, y) {\n return mapsvg.text().attr({dx: circleRadius * 1.5, dy: circleRadius * 1.5}).plain(content).move(x, y).id(id);\n }\n\n /**\n * Returns a path between two points.\n * @param {*} x1 x coordinate of the first point\n * @param {*} y1 y coordinate of the first point\n * @param {*} x2 x coordinate of the second point\n * @param {*} y2 y coordinate of the second point\n * @param {*} classes CSS classes to set\n * @param {*} id id of the path\n * @returns {any}\n */\n function path(x1, y1, x2, y2, classes, id) {\n return mapsvg.path('M ' + x1 + ' ' + y1 + ' L ' + x2 + ' ' + y2).attr({'class': classes}).id(id);\n }\n\n /**\n * Returns a link around a given child element. This function also adds a title element next\n * to the child for accessibility.\n * @param {*} child child item to set the link on\n * @param {*} id id of the link\n * @param {*} title title of the link\n * @param {*} text text to describe the link\n * @returns {any}\n */\n function link(child, id, title = null, text = null) {\n return mapsvg.link('').id(id).add(child).add(title).add(text);\n }\n\n /**\n * Adds a place on the SVG map. This function also prepares the code for linking activities\n * and adding titles (for accessibility).\n * @param {*} event event causing the command\n */\n function addPlace(event) {\n let placesgroup = mapsvg.findOne('#placesGroup');\n let placeId = 'p' + placestore.getId();\n let linkId = 'a' + placestore.getId();\n var CTM = event.target.getScreenCTM();\n if (event.touches) {\n event = event.touches[0];\n }\n let cx = (event.clientX - CTM.e) / CTM.a;\n let cy = (event.clientY - CTM.f) / CTM.d;\n let svglink = link(\n shapes.emoji(mapsvg, cx, cy, circleRadius, 'learningmap-place learningmap-draggable learningmap-emptyplace', placeId),\n linkId,\n title('title' + placeId),\n text('text' + placeId, '', cx, cy)\n );\n svglink.addTo(placesgroup);\n placestore.addPlace(placeId, linkId, null, svglink.bbox());\n }\n\n /**\n * Handles single clicks on the background image.\n * @param {*} event click event\n * @returns {void}\n */\n function clickHandler(event) {\n event.preventDefault();\n hideContextMenu();\n hideOtherMenus();\n if (event.target.classList.contains('learningmap-place') && selectedElement === null) {\n if (firstPlace === null) {\n firstPlace = event.target.id;\n document.getElementById(firstPlace).classList.add('learningmap-selected');\n } else {\n secondPlace = event.target.id;\n let fid = parseInt(firstPlace.replace('p', ''));\n let sid = parseInt(secondPlace.replace('p', ''));\n if (sid == fid) {\n return;\n }\n if (sid < fid) {\n let z = sid;\n sid = fid;\n fid = z;\n }\n addPath(fid, sid);\n let first = document.getElementById(firstPlace);\n if (first) {\n first.classList.remove('learningmap-selected');\n }\n firstPlace = null;\n lastTarget = secondPlace;\n secondPlace = null;\n }\n } else {\n unselectAll();\n firstPlace = null;\n }\n }\n /**\n * Removes the classes 'learningmap-selected' and 'learningmap-selectet-activity-selector'\n * from all nodes\n */\n function unselectAll() {\n Array.from(document.getElementsByClassName('learningmap-selected')).forEach(function(e) {\n e.classList.remove('learningmap-selected');\n });\n Array.from(document.getElementsByClassName('learningmap-selected-activity-selector')).forEach(function(e) {\n e.classList.remove('learningmap-selected-activity-selector');\n });\n }\n\n /**\n * Adds a path between two places.\n * @param {number} fid id of the first place (meant to be the smaller one)\n * @param {number} sid id of the second place (meant to be the bigger one)\n */\n function addPath(fid, sid) {\n let pid = 'p' + fid + '_' + sid;\n if (document.getElementById(pid) === null) {\n let pathsgroup = mapsvg.findOne('#pathsGroup');\n let first = mapsvg.findOne('#p' + fid);\n let second = mapsvg.findOne('#p' + sid);\n if (pathsgroup && first && second) {\n let svgpath = path(\n first.cx(),\n first.cy(),\n second.cx(),\n second.cy(),\n 'learningmap-path',\n pid\n );\n svgpath.addTo(pathsgroup);\n placestore.addPath(pid, 'p' + fid, 'p' + sid);\n }\n }\n }\n\n /**\n * Removes a place from the SVG and the placestore. This function also removes all\n * touching paths and entries in statringplaces / targetplaces linking to the removed\n * place.\n * @param {any} event event causing the remove order\n */\n function removePlace(event) {\n let place = getSVGShape(event.target.id);\n removePathsTouchingPlace(event.target.id);\n placestore.removePlace(event.target.id);\n place.parent().remove();\n\n updateCode();\n }\n\n /**\n * Removes all paths touching a certain place\n * @param {number} id id of the place\n */\n function removePathsTouchingPlace(id) {\n placestore.getTouchingPaths(id).forEach(\n function(e) {\n removePath(e.id);\n }\n );\n }\n\n /**\n * Removes a path from the SVG and from the placestore\n * @param {number} id id of the path\n */\n function removePath(id) {\n let path = getSVGShape(id);\n if (path !== null) {\n path.remove();\n placestore.removePath(id);\n }\n }\n\n /**\n * Sets the background image of the SVG to the current image in filemanager.\n */\n function refreshBackgroundImage() {\n let previewimage = document.getElementsByClassName('realpreview');\n if (previewimage.length > 0) {\n let background = document.getElementById('learningmap-background-image');\n let backgroundurl = previewimage[0].getAttribute('src').split('?')[0];\n // If the uploaded file reuses the filename of a previously uploaded image, they differ\n // only in the oid. So one has to append the oid to the url.\n if (previewimage[0].getAttribute('src').split('?')[1].includes('&oid=')) {\n backgroundurl += '?oid=' + previewimage[0].getAttribute('src').split('&oid=')[1];\n }\n background.setAttribute('xlink:href', backgroundurl);\n }\n }\n\n /**\n * Adds an eventListener to the background image for watching file changes and updating\n * height and width of the image.\n */\n function registerBackgroundListener() {\n let background = document.getElementById('learningmap-background-image');\n if (background) {\n background.addEventListener('load', function() {\n background.removeAttribute('height');\n let height = parseInt(background.getBBox().height);\n let width = background.getBBox().width;\n placestore.setBackgroundDimensions(width, height);\n svgel.setAttribute('viewBox', '0 0 ' + placestore.width + ' ' + placestore.height);\n background.setAttribute('width', width);\n background.setAttribute('height', height);\n updateCode();\n });\n }\n }\n\n /**\n * Updates CSS code inside the SVG (called, when one of the colors is changed).\n * Calls updateCode() when completed.\n */\n function updateCSS() {\n Templates.renderForPromise('mod_learningmap/cssskeleton', placestore.getPlacestore())\n .then(({html, js}) => {\n Templates.replaceNode('#learningmap-svgstyle', html, js);\n updateCode();\n return true;\n })\n .catch(ex => displayException(ex));\n let placestoretemp = placestore.getPlacestore();\n placestoretemp.mapid = 'preview';\n placestoretemp.cssid = 'learningmap-preview-svgstyle';\n placestoretemp.editmode = false;\n Templates.renderForPromise('mod_learningmap/cssskeleton', placestoretemp)\n .then(({html, js}) => {\n Templates.replaceNode('#learningmap-preview-svgstyle', html, js);\n return true;\n })\n .catch(ex => displayException(ex));\n }\n\n /**\n * Updates the activity selector to highlight the activities already used\n * and to show the alert for hidden activities.\n */\n function updateActivities() {\n let activities = placestore.getAllActivities();\n let options = Array.from(activitySelector.getElementsByTagName('option'));\n activityHiddenWarning.setAttribute('hidden', '');\n options.forEach(function(n) {\n if (activities.includes(n.value)) {\n n.classList.add('learningmap-used-activity');\n if (n.selected) {\n if (n.getAttribute('data-activity-hidden') == true) {\n activityHiddenWarning.removeAttribute('hidden');\n }\n }\n } else {\n n.classList.remove('learningmap-used-activity');\n }\n });\n }\n\n /**\n * Adds missing text nodes\n */\n function fixPlaceLabels() {\n let options = Array.from(activitySelector.getElementsByTagName('option'));\n let places = placestore.getPlaces();\n for (const place of places) {\n if (document.getElementById('text' + place.id) === null) {\n let content = '';\n for (const option of options) {\n if (option.value == place.linkedActivity) {\n content = option.textContent;\n break;\n }\n }\n let placeNode = mapsvg.findOne('#' + place.id);\n let textNode = text('text' + place.id, content, placeNode.cx(), placeNode.cy());\n textNode.addTo(placeNode.parent());\n }\n }\n }\n\n /**\n * Updates the size of the places.\n */\n function updatePlaceSize() {\n circleRadius = placestore.getPlaceSize();\n let places = placestore.getPlaces();\n for (const place of places) {\n let placeel = getSVGShape(place.id);\n if (placeel) {\n let cx = placeel.cx();\n let cy = placeel.cy();\n if (placeel.type != 'text') {\n placeel.width(circleRadius * 2).height(circleRadius * 2);\n } else {\n placeel.font({size: circleRadius});\n }\n placeel.center(cx, cy);\n }\n }\n }\n\n /**\n * Initializes a menu with the given features.\n * @param {*} name Name of the menu\n * @param {*} features Array with features to add to the menu\n */\n function initMenu(name, features) {\n let icon = document.getElementById('learningmap-' + name + '-icon');\n if (icon) {\n icon.addEventListener('click', function() {\n if (menuIsHidden(name)) {\n showMenu(name);\n } else {\n hideMenu(name);\n }\n });\n let close = document.getElementById('learningmap-' + name + '-close');\n if (close) {\n close.addEventListener('click', function() {\n hideMenu(name);\n });\n }\n }\n features.forEach(function(feature) {\n menuItemLogic(name, feature.name, feature.get, feature.set, feature.callback, feature.second);\n });\n }\n\n /**\n * Returns whether the menu is hidden or not.\n * @param {*} name Name of the menu\n * @returns {boolean}\n */\n function menuIsHidden(name) {\n let menu = document.getElementById('learningmap-' + name + '-menu');\n if (menu) {\n return menu.getAttribute('hidden') !== null;\n }\n return false;\n }\n\n /**\n * Hides the menu with the given name.\n * @param {*} name Name of the menu\n */\n function hideMenu(name) {\n let menu = document.getElementById('learningmap-' + name + '-menu');\n if (menu) {\n menu.setAttribute('hidden', '');\n }\n }\n\n /**\n * Hides all menus except the one with the given name.\n * @param {*} name Name of the menu not to hide\n */\n function hideOtherMenus(name = '') {\n let otherMenus = document.querySelectorAll('.learningmap-menu');\n otherMenus.forEach(function(menu) {\n if (menu.id != 'learningmap-' + name + '-menu') {\n menu.setAttribute('hidden', '');\n }\n });\n }\n\n /**\n * Shows the menu with the given name.\n * @param {*} name Name of the menu\n */\n function showMenu(name) {\n let menu = document.getElementById('learningmap-' + name + '-menu');\n if (menu) {\n menu.removeAttribute('hidden');\n updateColorPickers();\n hideOtherMenus(name);\n hideContextMenu();\n }\n }\n\n /**\n * Adds the event listener to menu items\n * @param {*} type Type of the item (describes the menu where it is located, e.g. advanced-settings, place-settings, ...)\n * @param {*} name Name of the item\n * @param {*} getCall Method of placestore to call to read value\n * @param {*} setCall Method of placestore to call to save value\n * @param {*} callback Additional callback after value is saved\n */\n function menuItemLogic(type, name, getCall, setCall, callback = null) {\n let menuItem = document.getElementById('learningmap-' + type + '-' + name);\n if (menuItem) {\n switch (menuItem.attributes.type.nodeValue) {\n case 'checkbox':\n menuItem.checked = getCall.call(placestore);\n menuItem.addEventListener('input', function() {\n setCall.call(placestore, menuItem.checked);\n if (callback !== null) {\n callback();\n }\n updateCSS();\n });\n break;\n default:\n menuItem.value = getCall.call(placestore);\n menuItem.addEventListener('input', function() {\n setCall.call(placestore, menuItem.value);\n if (callback !== null) {\n callback();\n }\n updateCSS();\n });\n }\n\n }\n }\n\n /**\n * Updates the color pickers to the current values from the placestore.\n */\n function updateColorPickers() {\n let colorPickers = document.querySelectorAll('[id^=\"learningmap-place-settings-jscolor-\"]');\n colorPickers.forEach(function(colorpicker) {\n if (colorpicker.jscolor) {\n colorpicker.jscolor.fromString(placestore[colorpicker.id.split('jscolor-')[1]]);\n }\n });\n }\n};\n"],"names":["targetPoints","pathTypes","prefetchTemplates","offset","dragel","pathsToUpdateFirstPoint","pathsToUpdateSecondPoint","circleRadius","selectedElement","firstPlace","secondPlace","lastTarget","elementForActivitySelector","touchstart","touchend","touchmove","mapdiv","document","getElementById","code","activitySetting","activitySelector","activityStarting","activityTarget","activityHiddenWarning","treeView","querySelector","setAttribute","iconView","setTimeout","dispatchEvent","Event","addEventListener","setActivityId","value","text","textContent","title","classList","remove","add","updateActivities","updateCode","checked","addStartingPlace","removeStartingPlace","addTargetPlace","removeTargetPlace","placestoreInput","getElementsByName","loadJSON","updateColorPickers","initMenu","name","get","placestore","getHidePaths","set","setHidePaths","getShowall","setShowall","getSliceMode","setSliceMode","getShowWayGone","setShowWayGone","getUseCheckmark","setUseCheckmark","getHover","setHover","getPulse","setPulse","getHideStroke","setHideStroke","getShowText","setShowText","callback","options","Array","from","getElementsByTagName","places","getPlaces","place","id","content","option","linkedActivity","placeNode","mapsvg","findOne","cx","cy","addTo","parent","getPlaceSize","setPlaceSize","placeel","getSVGShape","type","width","height","font","size","center","getPlaceColor","setPlaceColor","getVisitedColor","setVisitedColor","getStrokeColor","setStrokeColor","innerHTML","refreshBackgroundImage","background","removeAttribute","parseInt","getBBox","setBackgroundDimensions","svgel","registerBackgroundListener","getMapid","el","startDrag","drag","endDrag","evt","cancelable","preventDefault","target","contains","nodeName","dblclickHandler","touches","showContextMenu","endTouch","getMousePosition","x","y","getPathsWithFid","getPathsWithSid","attr","pathPoint","transformCoordinates","layerX","layerY","coord","textNode","amove","forEach","path","pathElement","updatePathDeclaration","setBbox","bbox","textel","dx","dy","node","getAttribute","unselectAll","clickHandler","oldDefinition","targetX","targetY","targetP","parts","split","fromX","fromY","toX","toY","bezierX","bezierY","pathType","i","length","makeDraggable","SVG","e","hideOtherMenus","element","activityId","getActivityId","scalingFactor","clientWidth","style","setProperty","clientHeight","display","isStartingPlace","isTargetPlace","hideContextMenu","updateCSS","backgroundfileNode","MutationObserver","observe","attributes","childList","subtree","clientX","clientY","CTM","getScreenCTM","a","f","d","JSON","stringify","getPlacestore","event","placesgroup","placeId","getId","linkId","svglink","child","link","shapes","emoji","addPlace","getTouchingPaths","removePath","removePlace","plain","move","fid","replace","sid","z","pid","pathsgroup","first","second","x1","y1","x2","y2","classes","addPath","getElementsByClassName","previewimage","backgroundurl","includes","renderForPromise","then","_ref","html","js","replaceNode","catch","ex","placestoretemp","mapid","cssid","editmode","_ref2","activities","getAllActivities","n","selected","features","icon","menu","menuIsHidden","hideMenu","showMenu","close","feature","getCall","setCall","menuItem","nodeValue","call","menuItemLogic","otherMenus","querySelectorAll","colorpicker","jscolor","fromString"],"mappings":"uiBAOMA,wBACU,EADVA,yBAEW,EAFXA,yBAGW,EAGXC,eACI,EADJA,0BAEe,gBAGD,wBAENC,kBAAkB,CAAC,oCAMzBC,OAGAC,OAIAC,wBAAyBC,yBAVzBC,aAAe,GAafC,gBAAkB,KAClBC,WAAa,KACbC,YAAc,KACdC,WAAa,KAGbC,2BAA6B,KAI7BC,YAAa,EACbC,UAAW,EAEXC,UAAY,MAGZC,OAASC,SAASC,eAAe,0BACjCC,KAAOF,SAASC,eAAe,cAG/BE,gBAAkBH,SAASC,eAAe,gCAC1CG,iBAAmBJ,SAASC,eAAe,iCAC3CI,iBAAmBL,SAASC,eAAe,iCAC3CK,eAAiBN,SAASC,eAAe,+BACzCM,sBAAwBP,SAASC,eAAe,uCAGhDO,SAAWR,SAASS,cAAc,2BAClCD,UACAA,SAASE,aAAa,QAAS,sBAI/BC,SAAWX,SAASS,cAAc,4BAClCE,UAEAC,YAAW,KACPD,SAASE,cAAc,IAAIC,MAAM,YAClC,KAIHV,mBAEAA,iBAAiBW,iBAAiB,UAAU,kCAC7BC,cAAcrB,2BAA4BS,iBAAiBa,OAClEb,iBAAiBa,MAAO,KACpBC,KAAOlB,SAASC,eAAe,OAASN,4BACxCuB,OACAA,KAAKC,YAAcf,iBAAiBK,cAAc,iBAAmBL,iBAAiBa,MAAQ,MAAME,iBAEpGC,MAAQpB,SAASC,eAAe,QAAUN,4BAC1CyB,QACAA,MAAMD,YACFf,iBAAiBK,cAAc,iBAAmBL,iBAAiBa,MAAQ,MAAME,aAEzFnB,SAASC,eAAeN,4BAA4B0B,UAAUC,OAAO,+BAErEtB,SAASC,eAAeN,4BAA4B0B,UAAUE,IAAI,0BAEtEC,mBACAC,gBAGJpB,iBAAiBU,iBAAiB,UAAU,WACpCV,iBAAiBqB,4BACNC,iBAAiBhC,gDAEjBiC,oBAAoBjC,4BAEnC8B,gBAGJnB,eAAeS,iBAAiB,UAAU,WAClCT,eAAeoB,6BACJG,eAAelC,4BAC1BK,SAASC,eAAeN,4BAA4B0B,UAAUE,IAAI,iDAEvDO,kBAAkBnC,4BAC7BK,SAASC,eAAeN,4BAA4B0B,UAAUC,OAAO,4BAEzEG,qBAKJM,gBAAkB/B,SAASgC,kBAAkB,cAAc,GAC3DD,qCACWE,SAASF,gBAAgBd,OAGxCiB,qBAGAV,mBAGAW,SAAS,oBAAqB,CAC1B,CAACC,KAAM,YAAaC,IAAKC,oBAAWC,aAAcC,IAAKF,oBAAWG,cAClE,CAACL,KAAM,UAAWC,IAAKC,oBAAWI,WAAYF,IAAKF,oBAAWK,YAC9D,CAACP,KAAM,YAAaC,IAAKC,oBAAWM,aAAcJ,IAAKF,oBAAWO,cAClE,CAACT,KAAM,cAAeC,IAAKC,oBAAWQ,eAAgBN,IAAKF,oBAAWS,kBAG1EZ,SAAS,iBAAkB,CACvB,CAACC,KAAM,eAAgBC,IAAKC,oBAAWU,gBAAiBR,IAAKF,oBAAWW,iBACxE,CAACb,KAAM,QAASC,IAAKC,oBAAWY,SAAUV,IAAKF,oBAAWa,UAC1D,CAACf,KAAM,QAASC,IAAKC,oBAAWc,SAAUZ,IAAKF,oBAAWe,UAC1D,CAACjB,KAAM,aAAcC,IAAKC,oBAAWgB,cAAed,IAAKF,oBAAWiB,eACpE,CAACnB,KAAM,WAAYC,IAAKC,oBAAWkB,YAAahB,IAAKF,oBAAWmB,YAAaC,wBA6sBzEC,QAAUC,MAAMC,KAAKzD,iBAAiB0D,qBAAqB,WAC3DC,OAASzB,oBAAW0B,gBACnB,MAAMC,SAASF,UACmC,OAA/C/D,SAASC,eAAe,OAASgE,MAAMC,IAAc,KACjDC,QAAU,OACT,MAAMC,UAAUT,WACbS,OAAOnD,OAASgD,MAAMI,eAAgB,CACtCF,QAAUC,OAAOjD,sBAIrBmD,UAAYC,OAAOC,QAAQ,IAAMP,MAAMC,IAC5BhD,KAAK,OAAS+C,MAAMC,GAAIC,QAASG,UAAUG,KAAMH,UAAUI,MACjEC,MAAML,UAAUM,aAztBjC,CAACxC,KAAM,YAAaC,IAAKC,oBAAWuC,aAAcrC,IAAKF,oBAAWwC,aAAcpB,oBAkuBhFpE,aAAegD,oBAAWuC,mBACtBd,OAASzB,oBAAW0B,gBACnB,MAAMC,SAASF,OAAQ,KACpBgB,QAAUC,YAAYf,MAAMC,OAC5Ba,QAAS,KACLN,GAAKM,QAAQN,KACbC,GAAKK,QAAQL,KACG,QAAhBK,QAAQE,KACRF,QAAQG,MAAqB,EAAf5F,cAAkB6F,OAAsB,EAAf7F,cAEvCyF,QAAQK,KAAK,CAACC,KAAM/F,eAExByF,QAAQO,OAAOb,GAAIC,QA7uB3B,CAACtC,KAAM,aAAcC,IAAKC,oBAAWiD,cAAe/C,IAAKF,oBAAWkD,eACpE,CAACpD,KAAM,eAAgBC,IAAKC,oBAAWmD,gBAAiBjD,IAAKF,oBAAWoD,iBACxE,CAACtD,KAAM,cAAeC,IAAKC,oBAAWqD,eAAgBnD,IAAKF,oBAAWsD,kBAItE1F,MAAQH,SACRA,OAAO8F,UAAY3F,KAAKe,OAG5B6E,wCAgoBQC,WAAa/F,SAASC,eAAe,gCACrC8F,YACAA,WAAWhF,iBAAiB,QAAQ,WAChCgF,WAAWC,gBAAgB,cACvBb,OAASc,SAASF,WAAWG,UAAUf,QACvCD,MAAQa,WAAWG,UAAUhB,0BACtBiB,wBAAwBjB,MAAOC,QAC1CiB,MAAM1F,aAAa,UAAW,OAAS4B,oBAAW4C,MAAQ,IAAM5C,oBAAW6C,QAC3EY,WAAWrF,aAAa,QAASwE,OACjCa,WAAWrF,aAAa,SAAUyE,QAClC1D,gBAzoBZ4E,GACA5E,iBAGI2E,MAAQpG,SAASC,eAAe,sBAAwBqC,oBAAWgE,sBAgHhDC,IACnBpH,OAASoH,GACLA,KACAA,GAAGxF,iBAAiB,YAAayF,WACjCD,GAAGxF,iBAAiB,YAAa0F,MACjCF,GAAGxF,iBAAiB,UAAW2F,SAC/BH,GAAGxF,iBAAiB,aAAc2F,SAClCH,GAAGxF,iBAAiB,uBAgIJ4F,KACZA,IAAIC,YACJD,IAAIE,iBAGJF,IAAIG,OAAOzF,UAAU0F,SAAS,0BACP,QAAvBJ,IAAIG,OAAOE,UACY,QAAvBL,IAAIG,OAAOE,UAENpH,YAsBDqH,gBAAgBN,KAChB/G,YAAa,IAtBbA,YAAa,EACbE,UAAY,EACZD,UAAW,EACXe,YACK+F,MACO7G,UAAY,IAAMD,WACd8G,IAAIO,UACJP,IAAMA,IAAIO,QAAQ,IAEtBC,gBAAgBR,QAGxB,IACAA,KAEJ/F,YACI,KACIhB,YAAa,IAErB,MAKJ4G,UAAUG,MAEL/G,YAUDqH,gBAAgBN,KAChB/G,YAAa,IAVbA,YAAa,EACbC,UAAW,EACXC,UAAY,EACZc,YACI,KACIhB,YAAa,IAErB,SA3KR2G,GAAGxF,iBAAiB,YAAa0F,MACjCF,GAAGxF,iBAAiB,WAAYqG,UAChCb,GAAGxF,iBAAiB,aAAcqG,UAClCb,GAAGxF,iBAAiB,cAAeqG,oBAO9BZ,UAAUG,QACXA,IAAIC,YACJD,IAAIE,iBAERzH,wBAA0B,GAC1BC,yBAA2B,GACvBsH,IAAIG,OAAOzF,UAAU0F,SAAS,yBAA0B,KAEpDX,MAAQpB,YADZzF,gBAAkBoH,IAAIG,SAEtB5H,OAASmI,iBAAiBV,MACnBW,GAAKlB,MAAM3B,KAClBvF,OAAOqI,GAAKnB,MAAM1B,KAElBtF,wBAA0BkD,oBAAWkF,gBAAgBb,IAAIG,OAAO5C,IAChE7E,yBAA2BiD,oBAAWmF,gBAAgBd,IAAIG,OAAO5C,SAC9D,GAA2B,QAAvByC,IAAIG,OAAOE,SAAoB,KAElCZ,MAAQpB,YADZzF,gBAAkBoH,IAAIG,QAElB7C,MAAQmC,MAAMxB,SAASJ,QAAQ,uBACnCtF,OAASmI,iBAAiBV,MACnBW,GAAKlB,MAAMsB,KAAK,MAAQzD,MAAMQ,KACrCvF,OAAOqI,GAAKnB,MAAMsB,KAAK,MAAQzD,MAAMS,UAClC,GAA2B,QAAvBiC,IAAIG,OAAOE,SAAoB,CACtCzH,gBAAkBoH,IAAIG,OACtB5H,OAASmI,iBAAiBV,SACtBgB,UAAYC,qBAAqBjB,IAAIkB,OAAQlB,IAAImB,QACrD5I,OAAOoI,GAAKK,UAAUL,EACtBpI,OAAOqI,GAAKI,UAAUJ,YASrBd,KAAKE,QACNA,IAAIC,YACJD,IAAIE,iBAGR/G,YACIP,gBAAiB,KACbwI,MAAQV,iBAAiBV,SACzBlC,GAAKsD,MAAMT,EAAIpI,OAAOoI,EACtB5C,GAAKqD,MAAMR,EAAIrI,OAAOqI,KACtBhI,gBAAgB8B,UAAU0F,SAAS,qBAAsB,KACrDhC,QAAUR,OAAOC,QAAQ,IAAMjF,gBAAgB2E,IACnDa,QAAQO,OAAOb,GAAIC,QACfsD,SAAWzD,OAAOC,QAAQ,QAAUjF,gBAAgB2E,IACvC,OAAb8D,UACAA,SAASC,MAAMxD,GAAIC,IAEvBtF,wBAAwB8I,SAAQ,SAASC,UACjCC,YAAcpD,YAAYmD,MACV,OAAhBC,cACwB,QAApBA,YAAYnD,KACZmD,YAAYV,KACR,GAAMW,sBAAsBD,YAAYV,KAAK,KAAMjD,GAAIC,GAAI3F,2BAG/DqJ,YAAYV,KAAK,IAAOjD,MAAUC,SAK9CrF,yBAAyB6I,SAAQ,SAASC,UAClCC,YAAcpD,YAAYmD,MACV,OAAhBC,cACwB,QAApBA,YAAYnD,KACZmD,YAAYV,KACR,GAAMW,sBAAsBD,YAAYV,KAAK,KAAMjD,GAAIC,GAAI3F,4BAG/DqJ,YAAYV,KAAK,IAAOjD,MAAUC,6BAInC4D,QAAQ/I,gBAAgB2E,GAAIa,QAAQH,SAAS2D,aACrD,GAAgC,QAA5BhJ,gBAAgByH,SAAoB,KACvCwB,OAASxD,YAAYzF,iBACrB0E,MAAQuE,OAAO5D,SAASJ,QAAQ,sBAIhCiE,GAAKhE,GAAKR,MAAMQ,KAChBiE,GAAKhE,GAAKT,MAAMS,KAGpB8D,OAAOd,KAAK,CAACe,GAAIA,GAAIC,GAAIA,yBACdJ,QAAQrE,MAAM0E,KAAKzE,GAAIsE,OAAO5D,SAAS2D,YACf,QAA5BhJ,gBAAgByH,UACvBzH,gBAAgBmB,aACZ,IACA2H,sBAAsB9I,gBAAgBqJ,aAAa,KAAMb,MAAMT,EAAGS,MAAMR,EAAGxI,qCAUlF2H,QAAQC,KACTA,IAAIC,YACJD,IAAIE,iBAERtH,gBAAkB,KAClBsJ,cACApH,sBA+DK2F,SAAST,KACdpH,gBAAkB,KAClBM,UAAW,EAEPC,UAAY,GAAKF,WACjBkJ,aAAanC,KAEbD,QAAQC,KAERA,IAAIC,YACJD,IAAIE,0BAYHwB,sBAAsBU,cAAeC,QAASC,aAASC,+DAAUnK,wBAClEoK,MAAQJ,cAAcK,MAAM,KAC5BC,MAAQ,EACRC,MAAQ,EACRC,IAAM,EACNC,IAAM,EACNC,QAAU,EACVC,QAAU,EACVC,SAAW3K,mBAKV,IAAI4K,EAAI,EAAGA,EAAIT,MAAMU,OAAQD,IAEd,KAAZT,MAAMS,KACNP,MAAQpD,SAASkD,MAAMS,EAAI,IAC3BN,MAAQrD,SAASkD,MAAMS,EAAI,IAC3BA,GAAK,GAGO,KAAZT,MAAMS,KACNL,IAAMtD,SAASkD,MAAMS,EAAI,IACzBJ,IAAMvD,SAASkD,MAAMS,EAAI,IACzBA,GAAK,GAGO,KAAZT,MAAMS,KACNH,QAAUxD,SAASkD,MAAMS,EAAI,IAC7BF,QAAUzD,SAASkD,MAAMS,EAAI,IAC7BL,IAAMtD,SAASkD,MAAMS,EAAI,IACzBJ,IAAMvD,SAASkD,MAAMS,EAAI,IACzBA,GAAK,EACLD,SAAW3K,kCAIXkK,cACCnK,wBACDsK,MAAQL,QACRM,MAAQL,mBAEPlK,yBACDwK,IAAMP,QACNQ,IAAMP,mBAELlK,yBAED0K,QAAoB,EAAVT,QAA8B,IAAfK,MAAQE,KACjCG,QAAoB,EAAVT,QAA8B,IAAfK,MAAQE,KACjCG,SAAW3K,iCAIf2K,UAAY3K,0BACL,KAAOqK,MAAQ,IAAMC,MAAQ,MAAQG,QAAU,IAAMC,QAAU,KAAOH,IAAM,IAAMC,IAElF,KAAOH,MAAQ,IAAMC,MAAQ,MAAQC,IAAM,IAAMC,KA7XpEM,CAAc1D,WACV7B,QAAS,kBAAQwF,IAAI,uBAAyBzH,oBAAWgE,qBAmBpDa,gBAAgB6C,MACrBnB,cACAoB,iBAEI9J,iBAA4D,OAAzCH,SAASC,eAAe+J,EAAElD,OAAO5C,OAChD8F,EAAE9C,UACF8C,EAAIA,EAAE9C,QAAQ,IAEd8C,EAAElD,OAAOzF,UAAU0F,SAAS,qBAAsB,KAC9CmD,QAAUlF,YAAYgF,EAAElD,OAAO5C,IACnC8F,EAAElD,OAAOzF,UAAUE,IAAI,8CACnB4I,WAAa7H,oBAAW8H,cAAcJ,EAAElD,OAAO5C,IAC/CmG,cAAgBtK,OAAOuK,YAAc,IACzCnK,gBAAgBoK,MAAMC,YAAY,UAAWN,QAAQzF,KAAO4F,cAAgB,MAC5ElK,gBAAgBoK,MAAMC,YAAY,UAAWN,QAAQxF,KAAO2F,cAAgB,MAC5ElK,gBAAgBoK,MAAMC,YAAY,cAAezK,OAAOuK,YAAc,MACtEnK,gBAAgBoK,MAAMC,YAAY,eAAgBzK,OAAO0K,aAAe,MACxEtK,gBAAgBoK,MAAMG,QAAU,QAChC1K,SAASC,eAAe,iCAAiCgB,MAAQkJ,WACjEnK,SAASC,eAAe,iCAAiCyB,QAAUY,oBAAWqI,gBAAgBX,EAAElD,OAAO5C,IACvGlE,SAASC,eAAe,+BAA+ByB,QAAUY,oBAAWsI,cAAcZ,EAAElD,OAAO5C,IACnGvE,2BAA6BqK,EAAElD,OAAO5C,GACtC1C,wBAEAqJ,kBACAZ,0BAQHY,sBACDb,EAAIhK,SAASC,eAAeN,4BAC5BqK,GACAA,EAAE3I,UAAUC,OAAO,0CAEvBnB,gBAAgBoK,MAAMG,QAAU,OAtDpCI,YAGI/K,SACAA,OAAOgB,iBAAiB,WAAYkG,iBACpClH,OAAOgB,iBAAiB,QAAS+H,cAEjC/I,OAAOgB,iBAAiB,eAAe,SAASiJ,GAC5CA,EAAEnD,iBACFM,gBAAgB6C,MACjB,QA+CHe,mBAAqB/K,SAASC,eAAe,iCAC7C8K,mBAAoB,CACL,IAAIC,iBAAiBlF,wBAC3BmF,QAAQF,mBAAoB,CAACG,YAAY,EAAMC,WAAW,EAAMC,SAAS,aAQ7E/D,iBAAiBV,YAClBA,IAAIO,UACJP,IAAMA,IAAIO,QAAQ,IAEfU,qBAAqBjB,IAAI0E,QAAS1E,IAAI2E,kBASxC1D,qBAAqBN,EAAGC,OACzBgE,IAAMpM,OAAOqM,qBACV,CACHlE,GAAIA,EAAIiE,IAAIvB,GAAKuB,IAAIE,EACrBlE,GAAIA,EAAIgE,IAAIG,GAAKH,IAAII,YAUpB3G,YAAYkF,eACM,iBAAZA,QACA3F,OAAOC,QAAQ,IAAM0F,QAAQhG,IAE7BK,OAAOC,QAAQ,IAAM0F,kBA8R3BzI,aACDvB,MAAQH,SACRG,KAAK2F,UAAY9F,OAAO8F,WAExB9D,kBACA/B,SAASgC,kBAAkB,cAAc,GAAGf,MAAQ2K,KAAKC,UAAUvJ,oBAAWwJ,2BAQ7E7E,gBAAgB8E,OACrBlB,kBACAZ,iBACApB,cACIkD,MAAMjF,OAAOzF,UAAU0F,SAAS,6BAChCgF,MAAMjF,OAAOzF,UAAU0F,SAAS,yCAoEtBgF,WACVC,YAAczH,OAAOC,QAAQ,gBAC7ByH,QAAU,IAAM3J,oBAAW4J,QAC3BC,OAAS,IAAM7J,oBAAW4J,YAC1BX,IAAMQ,MAAMjF,OAAO0E,eACnBO,MAAM7E,UACN6E,MAAQA,MAAM7E,QAAQ,QAEtBzC,IAAMsH,MAAMV,QAAUE,IAAIvB,GAAKuB,IAAIE,EACnC/G,IAAMqH,MAAMT,QAAUC,IAAIG,GAAKH,IAAII,EACnCS,iBAnBMC,MAAOnI,QAAI9C,6DAAQ,KAAMF,4DAAO,YACnCqD,OAAO+H,KAAK,IAAIpI,GAAGA,IAAI3C,IAAI8K,OAAO9K,IAAIH,OAAOG,IAAIL,MAkB1CoL,CACVC,gBAAOC,MAAMjI,OAAQE,GAAIC,GAAIpF,aAAc,iEAAkE2M,SAC7GE,QA5DOjI,GA6DD,QAAU+H,QA5Db1H,OAAO2F,QAAQ,SAAShG,GAAGA,KA6D9BhD,KAAK,OAAS+K,QAAS,GAAIxH,GAAIC,SA9DxBR,GAgEXkI,QAAQzH,MAAMqH,iCACHS,SAASR,QAASE,OAAQ,KAAMC,QAAQ7D,QApF/CkE,CAASV,OACFA,MAAMjF,OAAOzF,UAAU0F,SAAS,qBACnCrH,YAAcqM,MAAMjF,OAAO5C,IAC3BxE,WAAa,KACboJ,aAAaiD,iBAuKJA,WACb9H,MAAQe,YAAY+G,MAAMjF,OAAO5C,IAYPA,GAXL6H,MAAMjF,OAAO5C,uBAY3BwI,iBAAiBxI,IAAIgE,SAC5B,SAAS8B,GACL2C,WAAW3C,EAAE9F,2BAbV0I,YAAYb,MAAMjF,OAAO5C,IACpCD,MAAMW,SAAStD,SAEfG,iBAO8ByC,GAlLtB0I,CAAYb,OAETA,MAAMjF,OAAOzF,UAAU0F,SAAS,qBACvC4F,WAAWZ,MAAMjF,OAAO5C,IAE5BzC,sBAoBMP,KAAKgD,GAAIC,QAASmD,EAAGC,UACpBhD,OAAOrD,OAAOwG,KAAK,CAACe,GAAmB,IAAfnJ,aAAoBoJ,GAAmB,IAAfpJ,eAAqBuN,MAAM1I,SAAS2I,KAAKxF,EAAGC,GAAGrD,GAAGA,aA4DpG4E,aAAaiD,UAClBA,MAAMlF,iBACNgE,kBACAZ,iBACI8B,MAAMjF,OAAOzF,UAAU0F,SAAS,sBAA4C,OAApBxH,mBACrC,OAAfC,WACAA,WAAauM,MAAMjF,OAAO5C,GAC1BlE,SAASC,eAAeT,YAAY6B,UAAUE,IAAI,4BAC/C,CACH9B,YAAcsM,MAAMjF,OAAO5C,OACvB6I,IAAM9G,SAASzG,WAAWwN,QAAQ,IAAK,KACvCC,IAAMhH,SAASxG,YAAYuN,QAAQ,IAAK,QACxCC,KAAOF,cAGPE,IAAMF,IAAK,KACPG,EAAID,IACRA,IAAMF,IACNA,IAAMG,YAkCLH,IAAKE,SACdE,IAAM,IAAMJ,IAAM,IAAME,OACS,OAAjCjN,SAASC,eAAekN,KAAe,KACnCC,WAAa7I,OAAOC,QAAQ,eAC5B6I,MAAQ9I,OAAOC,QAAQ,KAAOuI,KAC9BO,OAAS/I,OAAOC,QAAQ,KAAOyI,QAC/BG,YAAcC,OAASC,OAAQ,EAzG5BC,GA2GCF,MAAM5I,KA3GH+I,GA4GHH,MAAM3I,KA5GC+I,GA6GPH,OAAO7I,KA7GIiJ,GA8GXJ,OAAO5I,KA9GQiJ,QA+Gf,mBA/GwBzJ,GAgHxBiJ,IA/GL5I,OAAO4D,KAAK,KAAOoF,GAAK,IAAMC,GAAK,MAAQC,GAAK,IAAMC,IAAIhG,KAAK,OAAUiG,UAAUzJ,GAAGA,KAiH7ES,MAAMyI,gCACHQ,QAAQT,IAAK,IAAMJ,IAAK,IAAME,UAnHtCM,GAAIC,GAAIC,GAAIC,GAAIC,QAASzJ,GAmE5B0J,CAAQb,IAAKE,SACTI,MAAQrN,SAASC,eAAeT,YAChC6N,OACAA,MAAMhM,UAAUC,OAAO,wBAE3B9B,WAAa,KACbE,WAAaD,YACbA,YAAc,UAGlBoJ,cACArJ,WAAa,cAOZqJ,cACLjF,MAAMC,KAAK7D,SAAS6N,uBAAuB,yBAAyB3F,SAAQ,SAAS8B,GACjFA,EAAE3I,UAAUC,OAAO,2BAEvBsC,MAAMC,KAAK7D,SAAS6N,uBAAuB,2CAA2C3F,SAAQ,SAAS8B,GACnGA,EAAE3I,UAAUC,OAAO,sDA6DlBqL,WAAWzI,QACZiE,KAAOnD,YAAYd,IACV,OAATiE,OACAA,KAAK7G,6BACMqL,WAAWzI,cAOrB4B,6BACDgI,aAAe9N,SAAS6N,uBAAuB,kBAC/CC,aAAajE,OAAS,EAAG,KACrB9D,WAAa/F,SAASC,eAAe,gCACrC8N,cAAgBD,aAAa,GAAGlF,aAAa,OAAOQ,MAAM,KAAK,GAG/D0E,aAAa,GAAGlF,aAAa,OAAOQ,MAAM,KAAK,GAAG4E,SAAS,WAC3DD,eAAiB,QAAUD,aAAa,GAAGlF,aAAa,OAAOQ,MAAM,SAAS,IAElFrD,WAAWrF,aAAa,aAAcqN,yBA4BrCjD,+BACKmD,iBAAiB,8BAA+B3L,oBAAWwJ,iBAChEoC,MAAKC,WAACC,KAACA,KAADC,GAAOA,mCACAC,YAAY,wBAAyBF,KAAMC,IACrD5M,cACO,KAEV8M,OAAMC,KAAM,2BAAiBA,UAC9BC,eAAiBnM,oBAAWwJ,gBAChC2C,eAAeC,MAAQ,UACvBD,eAAeE,MAAQ,+BACvBF,eAAeG,UAAW,qBAChBX,iBAAiB,8BAA+BQ,gBACrDP,MAAKW,YAACT,KAACA,KAADC,GAAOA,oCACAC,YAAY,gCAAiCF,KAAMC,KACtD,KAEVE,OAAMC,KAAM,2BAAiBA,eAO7BhN,uBACDsN,WAAaxM,oBAAWyM,mBACxBpL,QAAUC,MAAMC,KAAKzD,iBAAiB0D,qBAAqB,WAC/DvD,sBAAsBG,aAAa,SAAU,IAC7CiD,QAAQuE,SAAQ,SAAS8G,GACjBF,WAAWd,SAASgB,EAAE/N,QACtB+N,EAAE3N,UAAUE,IAAI,6BACZyN,EAAEC,UAC4C,GAA1CD,EAAEpG,aAAa,yBACfrI,sBAAsByF,gBAAgB,WAI9CgJ,EAAE3N,UAAUC,OAAO,yCAqDtBa,SAASC,KAAM8M,cAChBC,KAAOnP,SAASC,eAAe,eAAiBmC,KAAO,YACvD+M,KAAM,CACNA,KAAKpO,iBAAiB,SAAS,qBAwBjBqB,UACdgN,KAAOpP,SAASC,eAAe,eAAiBmC,KAAO,YACvDgN,YACuC,OAAhCA,KAAKxG,aAAa,iBAEtB,EA5BKyG,CAAajN,MAGbkN,SAASlN,eAwDPA,UACVgN,KAAOpP,SAASC,eAAe,eAAiBmC,KAAO,SACvDgN,OACAA,KAAKpJ,gBAAgB,UACrB9D,qBACA+H,eAAe7H,MACfyI,mBAhEQ0E,CAASnN,aAKboN,MAAQxP,SAASC,eAAe,eAAiBmC,KAAO,UACxDoN,OACAA,MAAMzO,iBAAiB,SAAS,WAC5BuO,SAASlN,SAIrB8M,SAAShH,SAAQ,SAASuH,mBAgEPxK,KAAM7C,KAAMsN,QAASC,aAASjM,gEAAW,KACxDkM,SAAW5P,SAASC,eAAe,eAAiBgF,KAAO,IAAM7C,SACjEwN,YAES,aADDA,SAAS1E,WAAWjG,KAAK4K,UAEzBD,SAASlO,QAAUgO,QAAQI,KAAKxN,qBAChCsN,SAAS7O,iBAAiB,SAAS,WAC/B4O,QAAQG,KAAKxN,oBAAYsN,SAASlO,SACjB,OAAbgC,UACAA,WAEJoH,oBAIJ8E,SAAS3O,MAAQyO,QAAQI,KAAKxN,qBAC9BsN,SAAS7O,iBAAiB,SAAS,WAC/B4O,QAAQG,KAAKxN,oBAAYsN,SAAS3O,OACjB,OAAbyC,UACAA,WAEJoH,eApFZiF,CAAc3N,KAAMqN,QAAQrN,KAAMqN,QAAQpN,IAAKoN,QAAQjN,IAAKiN,QAAQ/L,SAAU+L,QAAQnC,oBAqBrFgC,SAASlN,UACVgN,KAAOpP,SAASC,eAAe,eAAiBmC,KAAO,SACvDgN,MACAA,KAAK1O,aAAa,SAAU,aAQ3BuJ,qBAAe7H,4DAAO,GACvB4N,WAAahQ,SAASiQ,iBAAiB,qBAC3CD,WAAW9H,SAAQ,SAASkH,MACpBA,KAAKlL,IAAM,eAAiB9B,KAAO,SACnCgN,KAAK1O,aAAa,SAAU,gBA0D/BwB,qBACclC,SAASiQ,iBAAiB,+CAChC/H,SAAQ,SAASgI,aACtBA,YAAYC,SACZD,YAAYC,QAAQC,WAAW9N,oBAAW4N,YAAYhM,GAAGkF,MAAM,YAAY"} \ No newline at end of file +{"version":3,"file":"learningmap.min.js","sources":["../src/learningmap.js"],"sourcesContent":["import {exception as displayException} from 'core/notification';\nimport Templates from 'core/templates';\nimport placestore from 'mod_learningmap/placestore';\nimport svgjs from 'mod_learningmap/svg';\nimport shapes from './shapes';\n\n// Constants for updatePathDeclaration.\nconst targetPoints = {\n firstPoint: 1,\n secondPoint: 2,\n bezierPoint: 3,\n};\n\nconst pathTypes = {\n line: 1,\n quadraticbezier: 2,\n};\n\nexport const init = () => {\n // Load the needed template on startup for better execution speed.\n Templates.prefetchTemplates(['mod_learningmap/cssskeleton']);\n\n // Size for the new circles. This will be overriden by placesize from the placestore.\n var circleRadius = 10;\n\n // Variable for storing the mouse offset\n var offset;\n\n // Variable for draggable element\n var dragel;\n\n // Variables for storing the paths that need update of the first or\n // the second coordinates.\n var pathsToUpdateFirstPoint, pathsToUpdateSecondPoint;\n\n // Variables for handling the currently selected elements\n var selectedElement = null,\n firstPlace = null,\n secondPlace = null,\n lastTarget = null;\n\n // Variable for storing the selected element for the activity selector\n var elementForActivitySelector = null;\n\n // Variables for simulating double click on touch devices, set when the\n // corresponding events are handled\n var touchstart = false;\n var touchend = false;\n // Counter for touchmove events\n var touchmove = 0;\n\n // DOM nodes for the editor\n let mapdiv = document.getElementById('learningmap-editor-map');\n let code = document.getElementById('id_svgcode');\n\n // DOM nodes for the activity selector\n let activitySetting = document.getElementById('learningmap-activity-setting');\n let activitySelector = document.getElementById('learningmap-activity-selector');\n let activityStarting = document.getElementById('learningmap-activity-starting');\n let activityTarget = document.getElementById('learningmap-activity-target');\n let activityHiddenWarning = document.getElementById('learningmap-activity-hidden-warning');\n\n // Hide tree view as there is no preview file we can attach to\n let treeView = document.querySelector('.fp-viewbar .fp-vb-tree');\n if (treeView) {\n treeView.setAttribute('style', 'display: none;');\n }\n\n // Trigger click event on icon view to ensure that tree view is not active.\n let iconView = document.querySelector('.fp-viewbar .fp-vb-icons');\n if (iconView) {\n // Handle possible delay in form loading.\n setTimeout(() => {\n iconView.dispatchEvent(new Event('click'));\n }, 1000);\n }\n\n // Attach listeners to the activity selector\n if (activitySelector) {\n // Show places that are not linked to an activity\n activitySelector.addEventListener('change', function() {\n placestore.setActivityId(elementForActivitySelector, activitySelector.value);\n if (activitySelector.value) {\n let text = document.getElementById('text' + elementForActivitySelector);\n if (text) {\n text.textContent = activitySelector.querySelector('option[value=\"' + activitySelector.value + '\"]').textContent;\n }\n let title = document.getElementById('title' + elementForActivitySelector);\n if (title) {\n title.textContent =\n activitySelector.querySelector('option[value=\"' + activitySelector.value + '\"]').textContent;\n }\n document.getElementById(elementForActivitySelector).classList.remove('learningmap-emptyplace');\n } else {\n document.getElementById(elementForActivitySelector).classList.add('learningmap-emptyplace');\n }\n updateActivities();\n updateCode();\n });\n // Add / remove a place to the starting places array\n activityStarting.addEventListener('change', function() {\n if (activityStarting.checked) {\n placestore.addStartingPlace(elementForActivitySelector);\n } else {\n placestore.removeStartingPlace(elementForActivitySelector);\n }\n updateCode();\n });\n // Add / remove a place to the target places array\n activityTarget.addEventListener('change', function() {\n if (activityTarget.checked) {\n placestore.addTargetPlace(elementForActivitySelector);\n document.getElementById(elementForActivitySelector).classList.add('learningmap-targetplace');\n } else {\n placestore.removeTargetPlace(elementForActivitySelector);\n document.getElementById(elementForActivitySelector).classList.remove('learningmap-targetplace');\n }\n updateCode();\n });\n }\n\n // Load placestore values from the hidden input field\n let placestoreInput = document.getElementsByName('placestore')[0];\n if (placestoreInput) {\n placestore.loadJSON(placestoreInput.value);\n }\n\n updateColorPickers();\n\n // Mark all activities in the placestore as \"used\".\n updateActivities();\n\n // Inititalize the menus.\n initMenu('advanced-settings', [\n {name: 'hidepaths', get: placestore.getHidePaths, set: placestore.setHidePaths},\n {name: 'showall', get: placestore.getShowall, set: placestore.setShowall},\n {name: 'slicemode', get: placestore.getSliceMode, set: placestore.setSliceMode},\n {name: 'showwaygone', get: placestore.getShowWayGone, set: placestore.setShowWayGone},\n ]);\n\n initMenu('place-settings', [\n {name: 'usecheckmark', get: placestore.getUseCheckmark, set: placestore.setUseCheckmark},\n {name: 'hover', get: placestore.getHover, set: placestore.setHover},\n {name: 'pulse', get: placestore.getPulse, set: placestore.setPulse},\n {name: 'hidestroke', get: placestore.getHideStroke, set: placestore.setHideStroke},\n {name: 'showtext', get: placestore.getShowText, set: placestore.setShowText, callback: fixPlaceLabels},\n {name: 'placesize', get: placestore.getPlaceSize, set: placestore.setPlaceSize, callback: updatePlaceSize},\n {name: 'placecolor', get: placestore.getPlaceColor, set: placestore.setPlaceColor},\n {name: 'visitedcolor', get: placestore.getVisitedColor, set: placestore.setVisitedColor},\n {name: 'strokecolor', get: placestore.getStrokeColor, set: placestore.setStrokeColor},\n {name: 'textcolor', get: placestore.getTextColor, set: placestore.setTextColor},\n ]);\n\n // Get SVG code from the (hidden) textarea field\n if (code && mapdiv) {\n mapdiv.innerHTML = code.value;\n }\n // Reload background image to get the correct width and height values\n refreshBackgroundImage();\n registerBackgroundListener();\n updateCode();\n\n // Enable dragging of places\n let svgel = document.getElementById('learningmap-svgmap-' + placestore.getMapid());\n makeDraggable(svgel);\n var mapsvg = svgjs().SVG('#learningmap-svgmap-' + placestore.getMapid());\n\n // Refresh stylesheet values from placestore\n updateCSS();\n\n // Add listeners for clicking and context menu\n if (mapdiv) {\n mapdiv.addEventListener('dblclick', dblclickHandler);\n mapdiv.addEventListener('click', clickHandler);\n\n mapdiv.addEventListener('contextmenu', function(e) {\n e.preventDefault();\n showContextMenu(e);\n }, false);\n }\n /**\n * Shows the context menu at the current mouse position\n * @param {*} e\n */\n function showContextMenu(e) {\n unselectAll();\n hideOtherMenus();\n // Check for the existence of the target (could have vanished since the event started).\n if (activitySetting && document.getElementById(e.target.id) !== null) {\n if (e.touches) {\n e = e.touches[0];\n }\n if (e.target.classList.contains('learningmap-place')) {\n let element = getSVGShape(e.target.id);\n e.target.classList.add('learningmap-selected-activity-selector');\n let activityId = placestore.getActivityId(e.target.id);\n let scalingFactor = mapdiv.clientWidth / 800;\n activitySetting.style.setProperty('--pos-x', element.cx() * scalingFactor + 'px');\n activitySetting.style.setProperty('--pos-y', element.cy() * scalingFactor + 'px');\n activitySetting.style.setProperty('--map-width', mapdiv.clientWidth + 'px');\n activitySetting.style.setProperty('--map-height', mapdiv.clientHeight + 'px');\n activitySetting.style.display = 'block';\n document.getElementById('learningmap-activity-selector').value = activityId;\n document.getElementById('learningmap-activity-starting').checked = placestore.isStartingPlace(e.target.id);\n document.getElementById('learningmap-activity-target').checked = placestore.isTargetPlace(e.target.id);\n elementForActivitySelector = e.target.id;\n updateActivities();\n } else {\n hideContextMenu();\n hideOtherMenus();\n }\n }\n }\n\n /**\n * Hides the context menu\n */\n function hideContextMenu() {\n let e = document.getElementById(elementForActivitySelector);\n if (e) {\n e.classList.remove('learningmap-selected-activity-selector');\n }\n activitySetting.style.display = 'none';\n }\n\n let backgroundfileNode = document.getElementById('id_backgroundfile_fieldset');\n if (backgroundfileNode) {\n let observer = new MutationObserver(refreshBackgroundImage);\n observer.observe(backgroundfileNode, {attributes: true, childList: true, subtree: true});\n }\n\n /**\n * Helper function for getting the right coordinates from the mouse\n * @param {*} evt\n * @returns {object}\n */\n function getMousePosition(evt) {\n if (evt.touches) {\n evt = evt.touches[0];\n }\n return transformCoordinates(evt.clientX, evt.clientY);\n }\n\n /**\n * Transforms client coordinates to SVG coordinates\n * @param {number} x x coordinate to transform\n * @param {number} y y coordinate to transform\n * @returns {object} Object containing transformed x and y coordinate\n */\n function transformCoordinates(x, y) {\n var CTM = dragel.getScreenCTM();\n return {\n x: (x - CTM.e) / CTM.a,\n y: (y - CTM.f) / CTM.d\n };\n }\n\n /**\n * Returns the SVG shape with the given id or representing the\n * given object.\n * @param {*} element\n * @returns\n */\n function getSVGShape(element) {\n if (typeof element === 'object') {\n return mapsvg.findOne('#' + element.id);\n } else {\n return mapsvg.findOne('#' + element);\n }\n }\n\n /**\n * Enables dragging on an DOM node\n * @param {*} el\n */\n function makeDraggable(el) {\n dragel = el;\n if (el) {\n el.addEventListener('mousedown', startDrag);\n el.addEventListener('mousemove', drag);\n el.addEventListener('mouseup', endDrag);\n el.addEventListener('mouseleave', endDrag);\n el.addEventListener('touchstart', startTouch);\n el.addEventListener('touchmove', drag);\n el.addEventListener('touchend', endTouch);\n el.addEventListener('touchleave', endTouch);\n el.addEventListener('touchcancel', endTouch);\n }\n\n /**\n * Function called whenn dragging starts.\n * @param {*} evt\n */\n function startDrag(evt) {\n if (evt.cancelable) {\n evt.preventDefault();\n }\n pathsToUpdateFirstPoint = [];\n pathsToUpdateSecondPoint = [];\n if (evt.target.classList.contains('learningmap-draggable')) {\n selectedElement = evt.target;\n let svgel = getSVGShape(selectedElement);\n offset = getMousePosition(evt);\n offset.x -= svgel.cx();\n offset.y -= svgel.cy();\n // Get paths that need to be updated.\n pathsToUpdateFirstPoint = placestore.getPathsWithFid(evt.target.id);\n pathsToUpdateSecondPoint = placestore.getPathsWithSid(evt.target.id);\n } else if (evt.target.nodeName == 'text') {\n selectedElement = evt.target;\n let svgel = getSVGShape(selectedElement);\n let place = findPlaceForText(selectedElement.id);\n offset = getMousePosition(evt);\n offset.x -= svgel.attr('dx') + place.cx();\n offset.y -= svgel.attr('dy') + place.cy();\n } else if (evt.target.nodeName == 'path') {\n selectedElement = evt.target;\n offset = getMousePosition(evt);\n let pathPoint = transformCoordinates(evt.layerX, evt.layerY);\n offset.x += pathPoint.x;\n offset.y += pathPoint.y;\n }\n }\n\n /**\n * Function called during dragging. Continuously updates places center coordinates and the\n * coordinates of the touching paths.\n * @param {*} evt\n */\n function drag(evt) {\n if (evt.cancelable) {\n evt.preventDefault();\n }\n // Count touchmove events\n touchmove++;\n if (selectedElement) {\n var coord = getMousePosition(evt);\n let cx = coord.x - offset.x;\n let cy = coord.y - offset.y;\n if (selectedElement.classList.contains('learningmap-place')) {\n let placeel = mapsvg.findOne('#' + selectedElement.id);\n placeel.center(cx, cy);\n let textNode = mapsvg.findOne('#text' + selectedElement.id);\n if (textNode !== null) {\n textNode.amove(cx, cy);\n }\n pathsToUpdateFirstPoint.forEach(function(path) {\n let pathElement = getSVGShape(path);\n if (pathElement !== null) {\n if (pathElement.type == 'path') {\n pathElement.attr(\n {'d': updatePathDeclaration(pathElement.attr('d'), cx, cy, targetPoints.firstPoint)}\n );\n } else {\n pathElement.attr({'x1': cx, 'y1': cy});\n }\n }\n });\n\n pathsToUpdateSecondPoint.forEach(function(path) {\n let pathElement = getSVGShape(path);\n if (pathElement !== null) {\n if (pathElement.type == 'path') {\n pathElement.attr(\n {'d': updatePathDeclaration(pathElement.attr('d'), cx, cy, targetPoints.secondPoint)}\n );\n } else {\n pathElement.attr({'x2': cx, 'y2': cy});\n }\n }\n });\n } else if (selectedElement.nodeName == 'text') {\n let textel = getSVGShape(selectedElement);\n let place = findPlaceForText(selectedElement.id);\n // Calculate the delta from the current mouse position to the corresponding place.\n // coord: current mouse position\n // offset: delta from the mouse position to the coordinates of the text node\n let dx = cx - place.cx();\n let dy = cy - place.cy();\n // We cannot use the dx() and dy() functions of the text node, because they are not\n // setting the attributes dx and dy.\n textel.attr({dx: dx, dy: dy});\n } else if (selectedElement.nodeName == 'path') {\n selectedElement.setAttribute(\n 'd',\n updatePathDeclaration(selectedElement.getAttribute('d'), coord.x, coord.y, targetPoints.bezierPoint)\n );\n }\n }\n }\n\n /**\n * Function called when dragging ends.\n * @param {*} evt\n */\n function endDrag(evt) {\n if (evt.cancelable) {\n evt.preventDefault();\n }\n selectedElement = null;\n unselectAll();\n updateCode();\n }\n\n /**\n * Function called when touchstart event occurs.\n * @param {*} evt\n */\n function startTouch(evt) {\n if (evt.cancelable) {\n evt.preventDefault();\n }\n if (\n evt.target.classList.contains('learningmap-draggable') ||\n evt.target.nodeName == 'text' ||\n evt.target.nodeName == 'path'\n ) {\n if (!touchstart) {\n touchstart = true;\n touchmove = 0;\n touchend = false;\n setTimeout(\n (evt) => {\n if (touchmove < 3 && !touchend) {\n if (evt.touches) {\n evt = evt.touches[0];\n }\n showContextMenu(evt);\n }\n },\n 2000,\n evt\n );\n setTimeout(\n () => {\n touchstart = false;\n },\n 300);\n } else {\n dblclickHandler(evt);\n touchstart = false;\n }\n startDrag(evt);\n } else {\n if (!touchstart) {\n touchstart = true;\n touchend = false;\n touchmove = 0;\n setTimeout(\n () => {\n touchstart = false;\n },\n 300);\n } else {\n dblclickHandler(evt);\n touchstart = false;\n }\n }\n }\n\n /**\n * Function called when touchend, touchleave or touchcancel event occurs.\n * @param {*} evt\n */\n function endTouch(evt) {\n selectedElement = null;\n touchend = true;\n // If there was only a small move (<3 move events), this also counts as a click.\n if (touchmove < 3 && touchstart) {\n clickHandler(evt);\n } else {\n endDrag(evt);\n }\n if (evt.cancelable) {\n evt.preventDefault();\n }\n }\n\n /**\n * Updates the path declaration of lines and quadratic bezier curves setting one of the points.\n * @param {string} oldDefinition SVG path definition string\n * @param {number} targetX x coordinate of the point to set\n * @param {number} targetY y coordinate of the point to set\n * @param {number} targetP Which point to change (you can use the targetPoints constants here)\n * @returns {string} Updated SVG path definition\n */\n function updatePathDeclaration(oldDefinition, targetX, targetY, targetP = targetPoints.firstPoint) {\n let parts = oldDefinition.split(' ');\n let fromX = 0;\n let fromY = 0;\n let toX = 0;\n let toY = 0;\n let bezierX = 0;\n let bezierY = 0;\n let pathType = pathTypes.line;\n\n // The d attribute of an SVG path in a learning map can have two different formats (in this version):\n // \"M x1 y1 L x2 y2\" Line from x1, y1 to x2, y2\n // \"M x1 y2 Q x3 y3 x2 y2\" Quadratic bezier curve inside the triangle defined by x1, y1, x2, y2 and x3, y3.\n for (let i = 0; i < parts.length; i++) {\n // Every path contains the first point in that way.\n if (parts[i] == 'M') {\n fromX = parseInt(parts[i + 1]);\n fromY = parseInt(parts[i + 2]);\n i += 2;\n }\n // This path is a direct line, so there are only two points in total.\n if (parts[i] == 'L') {\n toX = parseInt(parts[i + 1]);\n toY = parseInt(parts[i + 2]);\n i += 2;\n }\n // This path is a bezier curve, there are three points in total.\n if (parts[i] == 'Q') {\n bezierX = parseInt(parts[i + 1]);\n bezierY = parseInt(parts[i + 2]);\n toX = parseInt(parts[i + 3]);\n toY = parseInt(parts[i + 4]);\n i += 4;\n pathType = pathTypes.quadraticbezier;\n }\n }\n\n switch (targetP) {\n case targetPoints.firstPoint:\n fromX = targetX;\n fromY = targetY;\n break;\n case targetPoints.secondPoint:\n toX = targetX;\n toY = targetY;\n break;\n case targetPoints.bezierPoint:\n // Calculate the third triangle point for the bezier curve.\n bezierX = targetX * 2 - (fromX + toX) * 0.5;\n bezierY = targetY * 2 - (fromY + toY) * 0.5;\n pathType = pathTypes.quadraticbezier;\n break;\n }\n\n if (pathType == pathTypes.quadraticbezier) {\n return 'M ' + fromX + ' ' + fromY + ' Q ' + bezierX + ' ' + bezierY + ', ' + toX + ' ' + toY;\n } else {\n return 'M ' + fromX + ' ' + fromY + ' L ' + toX + ' ' + toY;\n }\n }\n }\n\n /**\n * Updates the form fields for the SVG code and the placestore from the editor.\n */\n function updateCode() {\n if (code && mapdiv) {\n code.innerHTML = mapdiv.innerHTML;\n }\n if (placestoreInput) {\n document.getElementsByName('placestore')[0].value = JSON.stringify(placestore.getPlacestore());\n }\n }\n\n /**\n * Handles double clicks on the map\n * @param {*} event\n */\n function dblclickHandler(event) {\n hideContextMenu();\n hideOtherMenus();\n unselectAll();\n if (event.target.classList.contains('learningmap-mapcontainer') ||\n event.target.classList.contains('learningmap-background-image')) {\n addPlace(event);\n } else if (event.target.classList.contains('learningmap-place')) {\n if (lastTarget == event.target.id) {\n lastTarget = null;\n clickHandler(event);\n } else {\n removePlace(event);\n }\n } else if (event.target.classList.contains('learningmap-path')) {\n removePath(event.target.id);\n }\n updateCode();\n }\n\n /**\n * Returns an empty title tag with the given id.\n * @param {*} id id for the title\n * @returns {any}\n */\n function title(id) {\n return mapsvg.element('title').id(id);\n }\n\n /**\n * Returns an text tag with the given id.\n * @param {*} id id for the text\n * @param {*} content content of the tag\n * @param {*} x x coordinate of the text\n * @param {*} y y coordinate of the text\n * @returns {any}\n */\n function text(id, content, x, y) {\n return mapsvg.text().attr({dx: circleRadius * 1.5, dy: circleRadius * 1.5}).plain(content).move(x, y).id(id);\n }\n\n /**\n * Returns a path between two points.\n * @param {*} x1 x coordinate of the first point\n * @param {*} y1 y coordinate of the first point\n * @param {*} x2 x coordinate of the second point\n * @param {*} y2 y coordinate of the second point\n * @param {*} classes CSS classes to set\n * @param {*} id id of the path\n * @returns {any}\n */\n function path(x1, y1, x2, y2, classes, id) {\n return mapsvg.path('M ' + x1 + ' ' + y1 + ' L ' + x2 + ' ' + y2).attr({'class': classes}).id(id);\n }\n\n /**\n * Returns a link around a given child element. This function also adds a title element next\n * to the child for accessibility.\n * @param {*} child child item to set the link on\n * @param {*} id id of the link\n * @param {*} title title of the link\n * @returns {any}\n */\n function link(child, id, title = null) {\n return mapsvg.link('').id(id).add(child).add(title);\n }\n\n /**\n * Adds a place on the SVG map. This function also prepares the code for linking activities\n * and adding titles (for accessibility).\n * @param {*} event event causing the command\n */\n function addPlace(event) {\n let placesgroup = mapsvg.findOne('.learningmap-places-group');\n let textgroup = mapsvg.findOne('.learningmap-text-group');\n let placeId = 'p' + placestore.getId();\n let linkId = 'a' + placestore.getId();\n var CTM = event.target.getScreenCTM();\n if (event.touches) {\n event = event.touches[0];\n }\n let cx = (event.clientX - CTM.e) / CTM.a;\n let cy = (event.clientY - CTM.f) / CTM.d;\n let svglink = link(\n shapes.circle(mapsvg, cx, cy, circleRadius, 'learningmap-place learningmap-draggable learningmap-emptyplace', placeId),\n linkId,\n title('title' + placeId)\n );\n svglink.addTo(placesgroup);\n let textNode = text('text' + placeId, '', cx, cy);\n textNode.addTo(textgroup);\n placestore.addPlace(placeId, linkId, null, svglink.bbox());\n }\n\n /**\n * Handles single clicks on the background image.\n * @param {*} event click event\n * @returns {void}\n */\n function clickHandler(event) {\n event.preventDefault();\n hideContextMenu();\n hideOtherMenus();\n if (event.target.classList.contains('learningmap-place') && selectedElement === null) {\n if (firstPlace === null) {\n firstPlace = event.target.id;\n document.getElementById(firstPlace).classList.add('learningmap-selected');\n } else {\n secondPlace = event.target.id;\n let fid = parseInt(firstPlace.replace('p', ''));\n let sid = parseInt(secondPlace.replace('p', ''));\n if (sid == fid) {\n return;\n }\n if (sid < fid) {\n let z = sid;\n sid = fid;\n fid = z;\n }\n addPath(fid, sid);\n let first = document.getElementById(firstPlace);\n if (first) {\n first.classList.remove('learningmap-selected');\n }\n firstPlace = null;\n lastTarget = secondPlace;\n secondPlace = null;\n }\n } else {\n unselectAll();\n firstPlace = null;\n }\n }\n /**\n * Removes the classes 'learningmap-selected' and 'learningmap-selectet-activity-selector'\n * from all nodes\n */\n function unselectAll() {\n Array.from(document.getElementsByClassName('learningmap-selected')).forEach(function(e) {\n e.classList.remove('learningmap-selected');\n });\n Array.from(document.getElementsByClassName('learningmap-selected-activity-selector')).forEach(function(e) {\n e.classList.remove('learningmap-selected-activity-selector');\n });\n }\n\n /**\n * Adds a path between two places.\n * @param {number} fid id of the first place (meant to be the smaller one)\n * @param {number} sid id of the second place (meant to be the bigger one)\n */\n function addPath(fid, sid) {\n let pid = 'p' + fid + '_' + sid;\n if (document.getElementById(pid) === null) {\n let pathsgroup = mapsvg.findOne('.learningmap-pathsgroup');\n let first = mapsvg.findOne('#p' + fid);\n let second = mapsvg.findOne('#p' + sid);\n if (pathsgroup && first && second) {\n let svgpath = path(\n first.cx(),\n first.cy(),\n second.cx(),\n second.cy(),\n 'learningmap-path',\n pid\n );\n svgpath.addTo(pathsgroup);\n placestore.addPath(pid, 'p' + fid, 'p' + sid);\n }\n }\n }\n\n /**\n * Removes a place from the SVG and the placestore. This function also removes all\n * touching paths and entries in statringplaces / targetplaces linking to the removed\n * place.\n * @param {any} event event causing the remove order\n */\n function removePlace(event) {\n let place = getSVGShape(event.target.id);\n removePathsTouchingPlace(event.target.id);\n placestore.removePlace(event.target.id);\n place.parent().remove();\n let textNode = document.getElementById('text' + event.target.id);\n if (textNode) {\n textNode.remove();\n }\n\n updateCode();\n }\n\n /**\n * Removes all paths touching a certain place\n * @param {number} id id of the place\n */\n function removePathsTouchingPlace(id) {\n placestore.getTouchingPaths(id).forEach(\n function(e) {\n removePath(e.id);\n }\n );\n }\n\n /**\n * Removes a path from the SVG and from the placestore\n * @param {number} id id of the path\n */\n function removePath(id) {\n let path = getSVGShape(id);\n if (path !== null) {\n path.remove();\n placestore.removePath(id);\n }\n }\n\n /**\n * Sets the background image of the SVG to the current image in filemanager.\n */\n function refreshBackgroundImage() {\n let previewimage = document.getElementsByClassName('realpreview');\n if (previewimage.length > 0) {\n let background = document.getElementById('learningmap-background-image');\n let backgroundurl = previewimage[0].getAttribute('src').split('?')[0];\n // If the uploaded file reuses the filename of a previously uploaded image, they differ\n // only in the oid. So one has to append the oid to the url.\n if (previewimage[0].getAttribute('src').split('?')[1].includes('&oid=')) {\n backgroundurl += '?oid=' + previewimage[0].getAttribute('src').split('&oid=')[1];\n }\n background.setAttribute('xlink:href', backgroundurl);\n }\n }\n\n /**\n * Adds an eventListener to the background image for watching file changes and updating\n * height and width of the image.\n */\n function registerBackgroundListener() {\n let background = document.getElementById('learningmap-background-image');\n if (background) {\n background.addEventListener('load', function() {\n background.removeAttribute('height');\n let height = parseInt(background.getBBox().height);\n let width = background.getBBox().width;\n placestore.setBackgroundDimensions(width, height);\n svgel.setAttribute('viewBox', '0 0 ' + placestore.width + ' ' + placestore.height);\n background.setAttribute('width', width);\n background.setAttribute('height', height);\n updateCode();\n });\n }\n }\n\n /**\n * Updates CSS code inside the SVG (called, when one of the colors is changed).\n * Calls updateCode() when completed.\n */\n function updateCSS() {\n Templates.renderForPromise('mod_learningmap/cssskeleton', placestore.getPlacestore())\n .then(({html, js}) => {\n Templates.replaceNode('#learningmap-svgstyle', html, js);\n updateCode();\n return true;\n })\n .catch(ex => displayException(ex));\n let placestoretemp = placestore.getPlacestore();\n placestoretemp.mapid = 'preview';\n placestoretemp.cssid = 'learningmap-preview-svgstyle';\n placestoretemp.editmode = false;\n Templates.renderForPromise('mod_learningmap/cssskeleton', placestoretemp)\n .then(({html, js}) => {\n Templates.replaceNode('#learningmap-preview-svgstyle', html, js);\n return true;\n })\n .catch(ex => displayException(ex));\n }\n\n /**\n * Updates the activity selector to highlight the activities already used\n * and to show the alert for hidden activities.\n */\n function updateActivities() {\n let activities = placestore.getAllActivities();\n let options = Array.from(activitySelector.getElementsByTagName('option'));\n activityHiddenWarning.setAttribute('hidden', '');\n options.forEach(function(n) {\n if (activities.includes(n.value)) {\n n.classList.add('learningmap-used-activity');\n if (n.selected) {\n if (n.getAttribute('data-activity-hidden') == true) {\n activityHiddenWarning.removeAttribute('hidden');\n }\n }\n } else {\n n.classList.remove('learningmap-used-activity');\n }\n });\n }\n\n /**\n * Adds missing text nodes\n */\n function fixPlaceLabels() {\n let options = Array.from(activitySelector.getElementsByTagName('option'));\n let places = placestore.getPlaces();\n let textgroup = mapsvg.findOne('.learningmap-text-group');\n for (const place of places) {\n if (document.getElementById('text' + place.id) === null) {\n let content = '';\n for (const option of options) {\n if (option.value == place.linkedActivity) {\n content = option.textContent;\n break;\n }\n }\n let placeNode = mapsvg.findOne('#' + place.id);\n let textNode = text('text' + place.id, content, placeNode.cx(), placeNode.cy());\n textNode.addTo(textgroup);\n } else {\n let textNode = mapsvg.findOne('#text' + place.id);\n textNode.addTo(textgroup);\n }\n }\n }\n\n /**\n * Updates the size of the places.\n */\n function updatePlaceSize() {\n circleRadius = placestore.getPlaceSize();\n let places = placestore.getPlaces();\n for (const place of places) {\n let placeel = getSVGShape(place.id);\n if (placeel) {\n let cx = placeel.cx();\n let cy = placeel.cy();\n if (placeel.type != 'text') {\n placeel.width(circleRadius * 2).height(circleRadius * 2);\n } else {\n placeel.font({size: circleRadius});\n }\n placeel.center(cx, cy);\n }\n }\n }\n\n /**\n * Initializes a menu with the given features.\n * @param {*} name Name of the menu\n * @param {*} features Array with features to add to the menu\n */\n function initMenu(name, features) {\n let icon = document.getElementById('learningmap-' + name + '-icon');\n if (icon) {\n icon.addEventListener('click', function() {\n if (menuIsHidden(name)) {\n showMenu(name);\n } else {\n hideMenu(name);\n }\n });\n let close = document.getElementById('learningmap-' + name + '-close');\n if (close) {\n close.addEventListener('click', function() {\n hideMenu(name);\n });\n }\n }\n features.forEach(function(feature) {\n menuItemLogic(name, feature.name, feature.get, feature.set, feature.callback, feature.second);\n });\n }\n\n /**\n * Returns whether the menu is hidden or not.\n * @param {*} name Name of the menu\n * @returns {boolean}\n */\n function menuIsHidden(name) {\n let menu = document.getElementById('learningmap-' + name + '-menu');\n if (menu) {\n return menu.getAttribute('hidden') !== null;\n }\n return false;\n }\n\n /**\n * Hides the menu with the given name.\n * @param {*} name Name of the menu\n */\n function hideMenu(name) {\n let menu = document.getElementById('learningmap-' + name + '-menu');\n if (menu) {\n menu.setAttribute('hidden', '');\n }\n }\n\n /**\n * Hides all menus except the one with the given name.\n * @param {*} name Name of the menu not to hide\n */\n function hideOtherMenus(name = '') {\n let otherMenus = document.querySelectorAll('.learningmap-menu');\n otherMenus.forEach(function(menu) {\n if (menu.id != 'learningmap-' + name + '-menu') {\n menu.setAttribute('hidden', '');\n }\n });\n }\n\n /**\n * Shows the menu with the given name.\n * @param {*} name Name of the menu\n */\n function showMenu(name) {\n let menu = document.getElementById('learningmap-' + name + '-menu');\n if (menu) {\n menu.removeAttribute('hidden');\n updateColorPickers();\n hideOtherMenus(name);\n hideContextMenu();\n }\n }\n\n /**\n * Adds the event listener to menu items\n * @param {*} type Type of the item (describes the menu where it is located, e.g. advanced-settings, place-settings, ...)\n * @param {*} name Name of the item\n * @param {*} getCall Method of placestore to call to read value\n * @param {*} setCall Method of placestore to call to save value\n * @param {*} callback Additional callback after value is saved\n */\n function menuItemLogic(type, name, getCall, setCall, callback = null) {\n let menuItem = document.getElementById('learningmap-' + type + '-' + name);\n if (menuItem) {\n switch (menuItem.attributes.type.nodeValue) {\n case 'checkbox':\n menuItem.checked = getCall.call(placestore);\n menuItem.addEventListener('input', function() {\n setCall.call(placestore, menuItem.checked);\n if (callback !== null) {\n callback();\n }\n updateCSS();\n });\n break;\n default:\n menuItem.value = getCall.call(placestore);\n menuItem.addEventListener('input', function() {\n setCall.call(placestore, menuItem.value);\n if (callback !== null) {\n callback();\n }\n updateCSS();\n });\n }\n\n }\n }\n\n /**\n * Updates the color pickers to the current values from the placestore.\n */\n function updateColorPickers() {\n let colorPickers = document.querySelectorAll('[id^=\"learningmap-place-settings-jscolor-\"]');\n colorPickers.forEach(function(colorpicker) {\n if (colorpicker.jscolor) {\n colorpicker.jscolor.fromString(placestore[colorpicker.id.split('jscolor-')[1]]);\n }\n });\n }\n\n /**\n * Returns the place that belongs to the given text id.\n * @param {*} textId\n * @returns\n */\n function findPlaceForText(textId) {\n let placename = textId.replace('text', '');\n return mapsvg.findOne('#' + placename);\n }\n};\n"],"names":["targetPoints","pathTypes","prefetchTemplates","offset","dragel","pathsToUpdateFirstPoint","pathsToUpdateSecondPoint","circleRadius","selectedElement","firstPlace","secondPlace","lastTarget","elementForActivitySelector","touchstart","touchend","touchmove","mapdiv","document","getElementById","code","activitySetting","activitySelector","activityStarting","activityTarget","activityHiddenWarning","treeView","querySelector","setAttribute","iconView","setTimeout","dispatchEvent","Event","addEventListener","setActivityId","value","text","textContent","title","classList","remove","add","updateActivities","updateCode","checked","addStartingPlace","removeStartingPlace","addTargetPlace","removeTargetPlace","placestoreInput","getElementsByName","loadJSON","updateColorPickers","initMenu","name","get","placestore","getHidePaths","set","setHidePaths","getShowall","setShowall","getSliceMode","setSliceMode","getShowWayGone","setShowWayGone","getUseCheckmark","setUseCheckmark","getHover","setHover","getPulse","setPulse","getHideStroke","setHideStroke","getShowText","setShowText","callback","options","Array","from","getElementsByTagName","places","getPlaces","textgroup","mapsvg","findOne","place","id","content","option","linkedActivity","placeNode","cx","cy","addTo","getPlaceSize","setPlaceSize","placeel","getSVGShape","type","width","height","font","size","center","getPlaceColor","setPlaceColor","getVisitedColor","setVisitedColor","getStrokeColor","setStrokeColor","getTextColor","setTextColor","innerHTML","refreshBackgroundImage","background","removeAttribute","parseInt","getBBox","setBackgroundDimensions","svgel","registerBackgroundListener","getMapid","el","startDrag","drag","endDrag","evt","cancelable","preventDefault","target","contains","nodeName","dblclickHandler","touches","showContextMenu","endTouch","getMousePosition","x","y","getPathsWithFid","getPathsWithSid","findPlaceForText","attr","pathPoint","transformCoordinates","layerX","layerY","coord","textNode","amove","forEach","path","pathElement","updatePathDeclaration","textel","dx","dy","getAttribute","unselectAll","clickHandler","oldDefinition","targetX","targetY","targetP","parts","split","fromX","fromY","toX","toY","bezierX","bezierY","pathType","i","length","makeDraggable","SVG","e","hideOtherMenus","element","activityId","getActivityId","scalingFactor","clientWidth","style","setProperty","clientHeight","display","isStartingPlace","isTargetPlace","hideContextMenu","updateCSS","backgroundfileNode","MutationObserver","observe","attributes","childList","subtree","clientX","clientY","CTM","getScreenCTM","a","f","d","JSON","stringify","getPlacestore","event","placesgroup","placeId","getId","linkId","svglink","child","link","shapes","circle","addPlace","bbox","getTouchingPaths","removePath","removePlace","parent","plain","move","fid","replace","sid","z","pid","pathsgroup","first","second","x1","y1","x2","y2","classes","addPath","getElementsByClassName","previewimage","backgroundurl","includes","renderForPromise","then","_ref","html","js","replaceNode","catch","ex","placestoretemp","mapid","cssid","editmode","_ref2","activities","getAllActivities","n","selected","features","icon","menu","menuIsHidden","hideMenu","showMenu","close","feature","getCall","setCall","menuItem","nodeValue","call","menuItemLogic","otherMenus","querySelectorAll","colorpicker","jscolor","fromString","textId","placename"],"mappings":"uiBAOMA,wBACU,EADVA,yBAEW,EAFXA,yBAGW,EAGXC,eACI,EADJA,0BAEe,gBAGD,wBAENC,kBAAkB,CAAC,oCAMzBC,OAGAC,OAIAC,wBAAyBC,yBAVzBC,aAAe,GAafC,gBAAkB,KAClBC,WAAa,KACbC,YAAc,KACdC,WAAa,KAGbC,2BAA6B,KAI7BC,YAAa,EACbC,UAAW,EAEXC,UAAY,MAGZC,OAASC,SAASC,eAAe,0BACjCC,KAAOF,SAASC,eAAe,cAG/BE,gBAAkBH,SAASC,eAAe,gCAC1CG,iBAAmBJ,SAASC,eAAe,iCAC3CI,iBAAmBL,SAASC,eAAe,iCAC3CK,eAAiBN,SAASC,eAAe,+BACzCM,sBAAwBP,SAASC,eAAe,uCAGhDO,SAAWR,SAASS,cAAc,2BAClCD,UACAA,SAASE,aAAa,QAAS,sBAI/BC,SAAWX,SAASS,cAAc,4BAClCE,UAEAC,YAAW,KACPD,SAASE,cAAc,IAAIC,MAAM,YAClC,KAIHV,mBAEAA,iBAAiBW,iBAAiB,UAAU,kCAC7BC,cAAcrB,2BAA4BS,iBAAiBa,OAClEb,iBAAiBa,MAAO,KACpBC,KAAOlB,SAASC,eAAe,OAASN,4BACxCuB,OACAA,KAAKC,YAAcf,iBAAiBK,cAAc,iBAAmBL,iBAAiBa,MAAQ,MAAME,iBAEpGC,MAAQpB,SAASC,eAAe,QAAUN,4BAC1CyB,QACAA,MAAMD,YACFf,iBAAiBK,cAAc,iBAAmBL,iBAAiBa,MAAQ,MAAME,aAEzFnB,SAASC,eAAeN,4BAA4B0B,UAAUC,OAAO,+BAErEtB,SAASC,eAAeN,4BAA4B0B,UAAUE,IAAI,0BAEtEC,mBACAC,gBAGJpB,iBAAiBU,iBAAiB,UAAU,WACpCV,iBAAiBqB,4BACNC,iBAAiBhC,gDAEjBiC,oBAAoBjC,4BAEnC8B,gBAGJnB,eAAeS,iBAAiB,UAAU,WAClCT,eAAeoB,6BACJG,eAAelC,4BAC1BK,SAASC,eAAeN,4BAA4B0B,UAAUE,IAAI,iDAEvDO,kBAAkBnC,4BAC7BK,SAASC,eAAeN,4BAA4B0B,UAAUC,OAAO,4BAEzEG,qBAKJM,gBAAkB/B,SAASgC,kBAAkB,cAAc,GAC3DD,qCACWE,SAASF,gBAAgBd,OAGxCiB,qBAGAV,mBAGAW,SAAS,oBAAqB,CAC1B,CAACC,KAAM,YAAaC,IAAKC,oBAAWC,aAAcC,IAAKF,oBAAWG,cAClE,CAACL,KAAM,UAAWC,IAAKC,oBAAWI,WAAYF,IAAKF,oBAAWK,YAC9D,CAACP,KAAM,YAAaC,IAAKC,oBAAWM,aAAcJ,IAAKF,oBAAWO,cAClE,CAACT,KAAM,cAAeC,IAAKC,oBAAWQ,eAAgBN,IAAKF,oBAAWS,kBAG1EZ,SAAS,iBAAkB,CACvB,CAACC,KAAM,eAAgBC,IAAKC,oBAAWU,gBAAiBR,IAAKF,oBAAWW,iBACxE,CAACb,KAAM,QAASC,IAAKC,oBAAWY,SAAUV,IAAKF,oBAAWa,UAC1D,CAACf,KAAM,QAASC,IAAKC,oBAAWc,SAAUZ,IAAKF,oBAAWe,UAC1D,CAACjB,KAAM,aAAcC,IAAKC,oBAAWgB,cAAed,IAAKF,oBAAWiB,eACpE,CAACnB,KAAM,WAAYC,IAAKC,oBAAWkB,YAAahB,IAAKF,oBAAWmB,YAAaC,wBAitBzEC,QAAUC,MAAMC,KAAKzD,iBAAiB0D,qBAAqB,WAC3DC,OAASzB,oBAAW0B,YACpBC,UAAYC,OAAOC,QAAQ,+BAC1B,MAAMC,SAASL,UACmC,OAA/C/D,SAASC,eAAe,OAASmE,MAAMC,IAAc,KACjDC,QAAU,OACT,MAAMC,UAAUZ,WACbY,OAAOtD,OAASmD,MAAMI,eAAgB,CACtCF,QAAUC,OAAOpD,sBAIrBsD,UAAYP,OAAOC,QAAQ,IAAMC,MAAMC,IAC5BnD,KAAK,OAASkD,MAAMC,GAAIC,QAASG,UAAUC,KAAMD,UAAUE,MACjEC,MAAMX,eACZ,CACYC,OAAOC,QAAQ,QAAUC,MAAMC,IACrCO,MAAMX,cAjuBvB,CAAC7B,KAAM,YAAaC,IAAKC,oBAAWuC,aAAcrC,IAAKF,oBAAWwC,aAAcpB,oBA0uBhFpE,aAAegD,oBAAWuC,mBACtBd,OAASzB,oBAAW0B,gBACnB,MAAMI,SAASL,OAAQ,KACpBgB,QAAUC,YAAYZ,MAAMC,OAC5BU,QAAS,KACLL,GAAKK,QAAQL,KACbC,GAAKI,QAAQJ,KACG,QAAhBI,QAAQE,KACRF,QAAQG,MAAqB,EAAf5F,cAAkB6F,OAAsB,EAAf7F,cAEvCyF,QAAQK,KAAK,CAACC,KAAM/F,eAExByF,QAAQO,OAAOZ,GAAIC,QArvB3B,CAACvC,KAAM,aAAcC,IAAKC,oBAAWiD,cAAe/C,IAAKF,oBAAWkD,eACpE,CAACpD,KAAM,eAAgBC,IAAKC,oBAAWmD,gBAAiBjD,IAAKF,oBAAWoD,iBACxE,CAACtD,KAAM,cAAeC,IAAKC,oBAAWqD,eAAgBnD,IAAKF,oBAAWsD,gBACtE,CAACxD,KAAM,YAAaC,IAAKC,oBAAWuD,aAAcrD,IAAKF,oBAAWwD,gBAIlE5F,MAAQH,SACRA,OAAOgG,UAAY7F,KAAKe,OAG5B+E,wCAmoBQC,WAAajG,SAASC,eAAe,gCACrCgG,YACAA,WAAWlF,iBAAiB,QAAQ,WAChCkF,WAAWC,gBAAgB,cACvBf,OAASgB,SAASF,WAAWG,UAAUjB,QACvCD,MAAQe,WAAWG,UAAUlB,0BACtBmB,wBAAwBnB,MAAOC,QAC1CmB,MAAM5F,aAAa,UAAW,OAAS4B,oBAAW4C,MAAQ,IAAM5C,oBAAW6C,QAC3Ec,WAAWvF,aAAa,QAASwE,OACjCe,WAAWvF,aAAa,SAAUyE,QAClC1D,gBA5oBZ8E,GACA9E,iBAGI6E,MAAQtG,SAASC,eAAe,sBAAwBqC,oBAAWkE,sBAgHhDC,IACnBtH,OAASsH,GACLA,KACAA,GAAG1F,iBAAiB,YAAa2F,WACjCD,GAAG1F,iBAAiB,YAAa4F,MACjCF,GAAG1F,iBAAiB,UAAW6F,SAC/BH,GAAG1F,iBAAiB,aAAc6F,SAClCH,GAAG1F,iBAAiB,uBA8HJ8F,KACZA,IAAIC,YACJD,IAAIE,iBAGJF,IAAIG,OAAO3F,UAAU4F,SAAS,0BACP,QAAvBJ,IAAIG,OAAOE,UACY,QAAvBL,IAAIG,OAAOE,UAENtH,YAsBDuH,gBAAgBN,KAChBjH,YAAa,IAtBbA,YAAa,EACbE,UAAY,EACZD,UAAW,EACXe,YACKiG,MACO/G,UAAY,IAAMD,WACdgH,IAAIO,UACJP,IAAMA,IAAIO,QAAQ,IAEtBC,gBAAgBR,QAGxB,IACAA,KAEJjG,YACI,KACIhB,YAAa,IAErB,MAKJ8G,UAAUG,MAELjH,YAUDuH,gBAAgBN,KAChBjH,YAAa,IAVbA,YAAa,EACbC,UAAW,EACXC,UAAY,EACZc,YACI,KACIhB,YAAa,IAErB,SAzKR6G,GAAG1F,iBAAiB,YAAa4F,MACjCF,GAAG1F,iBAAiB,WAAYuG,UAChCb,GAAG1F,iBAAiB,aAAcuG,UAClCb,GAAG1F,iBAAiB,cAAeuG,oBAO9BZ,UAAUG,QACXA,IAAIC,YACJD,IAAIE,iBAER3H,wBAA0B,GAC1BC,yBAA2B,GACvBwH,IAAIG,OAAO3F,UAAU4F,SAAS,yBAA0B,KAEpDX,MAAQtB,YADZzF,gBAAkBsH,IAAIG,SAEtB9H,OAASqI,iBAAiBV,MACnBW,GAAKlB,MAAM5B,KAClBxF,OAAOuI,GAAKnB,MAAM3B,KAElBvF,wBAA0BkD,oBAAWoF,gBAAgBb,IAAIG,OAAO3C,IAChEhF,yBAA2BiD,oBAAWqF,gBAAgBd,IAAIG,OAAO3C,SAC9D,GAA2B,QAAvBwC,IAAIG,OAAOE,SAAoB,KAElCZ,MAAQtB,YADZzF,gBAAkBsH,IAAIG,QAElB5C,MAAQwD,iBAAiBrI,gBAAgB8E,KAC7CnF,OAASqI,iBAAiBV,MACnBW,GAAKlB,MAAMuB,KAAK,MAAQzD,MAAMM,KACrCxF,OAAOuI,GAAKnB,MAAMuB,KAAK,MAAQzD,MAAMO,UAClC,GAA2B,QAAvBkC,IAAIG,OAAOE,SAAoB,CACtC3H,gBAAkBsH,IAAIG,OACtB9H,OAASqI,iBAAiBV,SACtBiB,UAAYC,qBAAqBlB,IAAImB,OAAQnB,IAAIoB,QACrD/I,OAAOsI,GAAKM,UAAUN,EACtBtI,OAAOuI,GAAKK,UAAUL,YASrBd,KAAKE,QACNA,IAAIC,YACJD,IAAIE,iBAGRjH,YACIP,gBAAiB,KACb2I,MAAQX,iBAAiBV,SACzBnC,GAAKwD,MAAMV,EAAItI,OAAOsI,EACtB7C,GAAKuD,MAAMT,EAAIvI,OAAOuI,KACtBlI,gBAAgB8B,UAAU4F,SAAS,qBAAsB,CAC3C/C,OAAOC,QAAQ,IAAM5E,gBAAgB8E,IAC3CiB,OAAOZ,GAAIC,QACfwD,SAAWjE,OAAOC,QAAQ,QAAU5E,gBAAgB8E,IACvC,OAAb8D,UACAA,SAASC,MAAM1D,GAAIC,IAEvBvF,wBAAwBiJ,SAAQ,SAASC,UACjCC,YAAcvD,YAAYsD,MACV,OAAhBC,cACwB,QAApBA,YAAYtD,KACZsD,YAAYV,KACR,GAAMW,sBAAsBD,YAAYV,KAAK,KAAMnD,GAAIC,GAAI5F,2BAG/DwJ,YAAYV,KAAK,IAAOnD,MAAUC,SAK9CtF,yBAAyBgJ,SAAQ,SAASC,UAClCC,YAAcvD,YAAYsD,MACV,OAAhBC,cACwB,QAApBA,YAAYtD,KACZsD,YAAYV,KACR,GAAMW,sBAAsBD,YAAYV,KAAK,KAAMnD,GAAIC,GAAI5F,4BAG/DwJ,YAAYV,KAAK,IAAOnD,MAAUC,cAI3C,GAAgC,QAA5BpF,gBAAgB2H,SAAoB,KACvCuB,OAASzD,YAAYzF,iBACrB6E,MAAQwD,iBAAiBrI,gBAAgB8E,IAIzCqE,GAAKhE,GAAKN,MAAMM,KAChBiE,GAAKhE,GAAKP,MAAMO,KAGpB8D,OAAOZ,KAAK,CAACa,GAAIA,GAAIC,GAAIA,SACU,QAA5BpJ,gBAAgB2H,UACvB3H,gBAAgBmB,aACZ,IACA8H,sBAAsBjJ,gBAAgBqJ,aAAa,KAAMV,MAAMV,EAAGU,MAAMT,EAAG1I,qCAUlF6H,QAAQC,KACTA,IAAIC,YACJD,IAAIE,iBAERxH,gBAAkB,KAClBsJ,cACApH,sBA+DK6F,SAAST,KACdtH,gBAAkB,KAClBM,UAAW,EAEPC,UAAY,GAAKF,WACjBkJ,aAAajC,KAEbD,QAAQC,KAERA,IAAIC,YACJD,IAAIE,0BAYHyB,sBAAsBO,cAAeC,QAASC,aAASC,+DAAUnK,wBAClEoK,MAAQJ,cAAcK,MAAM,KAC5BC,MAAQ,EACRC,MAAQ,EACRC,IAAM,EACNC,IAAM,EACNC,QAAU,EACVC,QAAU,EACVC,SAAW3K,mBAKV,IAAI4K,EAAI,EAAGA,EAAIT,MAAMU,OAAQD,IAEd,KAAZT,MAAMS,KACNP,MAAQlD,SAASgD,MAAMS,EAAI,IAC3BN,MAAQnD,SAASgD,MAAMS,EAAI,IAC3BA,GAAK,GAGO,KAAZT,MAAMS,KACNL,IAAMpD,SAASgD,MAAMS,EAAI,IACzBJ,IAAMrD,SAASgD,MAAMS,EAAI,IACzBA,GAAK,GAGO,KAAZT,MAAMS,KACNH,QAAUtD,SAASgD,MAAMS,EAAI,IAC7BF,QAAUvD,SAASgD,MAAMS,EAAI,IAC7BL,IAAMpD,SAASgD,MAAMS,EAAI,IACzBJ,IAAMrD,SAASgD,MAAMS,EAAI,IACzBA,GAAK,EACLD,SAAW3K,kCAIXkK,cACCnK,wBACDsK,MAAQL,QACRM,MAAQL,mBAEPlK,yBACDwK,IAAMP,QACNQ,IAAMP,mBAELlK,yBAED0K,QAAoB,EAAVT,QAA8B,IAAfK,MAAQE,KACjCG,QAAoB,EAAVT,QAA8B,IAAfK,MAAQE,KACjCG,SAAW3K,iCAIf2K,UAAY3K,0BACL,KAAOqK,MAAQ,IAAMC,MAAQ,MAAQG,QAAU,IAAMC,QAAU,KAAOH,IAAM,IAAMC,IAElF,KAAOH,MAAQ,IAAMC,MAAQ,MAAQC,IAAM,IAAMC,KA3XpEM,CAAcxD,WACVpC,QAAS,kBAAQ6F,IAAI,uBAAyBzH,oBAAWkE,qBAmBpDa,gBAAgB2C,MACrBnB,cACAoB,iBAEI9J,iBAA4D,OAAzCH,SAASC,eAAe+J,EAAEhD,OAAO3C,OAChD2F,EAAE5C,UACF4C,EAAIA,EAAE5C,QAAQ,IAEd4C,EAAEhD,OAAO3F,UAAU4F,SAAS,qBAAsB,KAC9CiD,QAAUlF,YAAYgF,EAAEhD,OAAO3C,IACnC2F,EAAEhD,OAAO3F,UAAUE,IAAI,8CACnB4I,WAAa7H,oBAAW8H,cAAcJ,EAAEhD,OAAO3C,IAC/CgG,cAAgBtK,OAAOuK,YAAc,IACzCnK,gBAAgBoK,MAAMC,YAAY,UAAWN,QAAQxF,KAAO2F,cAAgB,MAC5ElK,gBAAgBoK,MAAMC,YAAY,UAAWN,QAAQvF,KAAO0F,cAAgB,MAC5ElK,gBAAgBoK,MAAMC,YAAY,cAAezK,OAAOuK,YAAc,MACtEnK,gBAAgBoK,MAAMC,YAAY,eAAgBzK,OAAO0K,aAAe,MACxEtK,gBAAgBoK,MAAMG,QAAU,QAChC1K,SAASC,eAAe,iCAAiCgB,MAAQkJ,WACjEnK,SAASC,eAAe,iCAAiCyB,QAAUY,oBAAWqI,gBAAgBX,EAAEhD,OAAO3C,IACvGrE,SAASC,eAAe,+BAA+ByB,QAAUY,oBAAWsI,cAAcZ,EAAEhD,OAAO3C,IACnG1E,2BAA6BqK,EAAEhD,OAAO3C,GACtC7C,wBAEAqJ,kBACAZ,0BAQHY,sBACDb,EAAIhK,SAASC,eAAeN,4BAC5BqK,GACAA,EAAE3I,UAAUC,OAAO,0CAEvBnB,gBAAgBoK,MAAMG,QAAU,OAtDpCI,YAGI/K,SACAA,OAAOgB,iBAAiB,WAAYoG,iBACpCpH,OAAOgB,iBAAiB,QAAS+H,cAEjC/I,OAAOgB,iBAAiB,eAAe,SAASiJ,GAC5CA,EAAEjD,iBACFM,gBAAgB2C,MACjB,QA+CHe,mBAAqB/K,SAASC,eAAe,iCAC7C8K,mBAAoB,CACL,IAAIC,iBAAiBhF,wBAC3BiF,QAAQF,mBAAoB,CAACG,YAAY,EAAMC,WAAW,EAAMC,SAAS,aAQ7E7D,iBAAiBV,YAClBA,IAAIO,UACJP,IAAMA,IAAIO,QAAQ,IAEfW,qBAAqBlB,IAAIwE,QAASxE,IAAIyE,kBASxCvD,qBAAqBP,EAAGC,OACzB8D,IAAMpM,OAAOqM,qBACV,CACHhE,GAAIA,EAAI+D,IAAIvB,GAAKuB,IAAIE,EACrBhE,GAAIA,EAAI8D,IAAIG,GAAKH,IAAII,YAUpB3G,YAAYkF,eACM,iBAAZA,QACAhG,OAAOC,QAAQ,IAAM+F,QAAQ7F,IAE7BH,OAAOC,QAAQ,IAAM+F,kBA4R3BzI,aACDvB,MAAQH,SACRG,KAAK6F,UAAYhG,OAAOgG,WAExBhE,kBACA/B,SAASgC,kBAAkB,cAAc,GAAGf,MAAQ2K,KAAKC,UAAUvJ,oBAAWwJ,2BAQ7E3E,gBAAgB4E,OACrBlB,kBACAZ,iBACApB,cACIkD,MAAM/E,OAAO3F,UAAU4F,SAAS,6BAChC8E,MAAM/E,OAAO3F,UAAU4F,SAAS,yCAmEtB8E,WACVC,YAAc9H,OAAOC,QAAQ,6BAC7BF,UAAYC,OAAOC,QAAQ,2BAC3B8H,QAAU,IAAM3J,oBAAW4J,QAC3BC,OAAS,IAAM7J,oBAAW4J,YAC1BX,IAAMQ,MAAM/E,OAAOwE,eACnBO,MAAM3E,UACN2E,MAAQA,MAAM3E,QAAQ,QAEtB1C,IAAMqH,MAAMV,QAAUE,IAAIvB,GAAKuB,IAAIE,EACnC9G,IAAMoH,MAAMT,QAAUC,IAAIG,GAAKH,IAAII,EACnCS,iBApBMC,MAAOhI,QAAIjD,6DAAQ,YACtB8C,OAAOoI,KAAK,IAAIjI,GAAGA,IAAI9C,IAAI8K,OAAO9K,IAAIH,OAmB/BkL,CACVC,gBAAOC,OAAOtI,OAAQQ,GAAIC,GAAIrF,aAAc,iEAAkE2M,SAC9GE,QA5DO9H,GA6DD,QAAU4H,QA5Db/H,OAAOgG,QAAQ,SAAS7F,GAAGA,UADvBA,GA+DX+H,QAAQxH,MAAMoH,aACC9K,KAAK,OAAS+K,QAAS,GAAIvH,GAAIC,IACrCC,MAAMX,+BACJwI,SAASR,QAASE,OAAQ,KAAMC,QAAQM,QArF/CD,CAASV,OACFA,MAAM/E,OAAO3F,UAAU4F,SAAS,qBACnCvH,YAAcqM,MAAM/E,OAAO3C,IAC3B3E,WAAa,KACboJ,aAAaiD,iBAwKJA,WACb3H,MAAQY,YAAY+G,MAAM/E,OAAO3C,IAgBPA,GAfL0H,MAAM/E,OAAO3C,uBAgB3BsI,iBAAiBtI,IAAIgE,SAC5B,SAAS2B,GACL4C,WAAW5C,EAAE3F,2BAjBVwI,YAAYd,MAAM/E,OAAO3C,IACpCD,MAAM0I,SAASxL,aAae+C,OAZ1B8D,SAAWnI,SAASC,eAAe,OAAS8L,MAAM/E,OAAO3C,IACzD8D,UACAA,SAAS7G,SAGbG,aAhLQoL,CAAYd,OAETA,MAAM/E,OAAO3F,UAAU4F,SAAS,qBACvC2F,WAAWb,MAAM/E,OAAO3C,IAE5B5C,sBAoBMP,KAAKmD,GAAIC,QAASkD,EAAGC,UACpBvD,OAAOhD,OAAO2G,KAAK,CAACa,GAAmB,IAAfpJ,aAAoBqJ,GAAmB,IAAfrJ,eAAqByN,MAAMzI,SAAS0I,KAAKxF,EAAGC,GAAGpD,GAAGA,aA6DpGyE,aAAaiD,UAClBA,MAAMhF,iBACN8D,kBACAZ,iBACI8B,MAAM/E,OAAO3F,UAAU4F,SAAS,sBAA4C,OAApB1H,mBACrC,OAAfC,WACAA,WAAauM,MAAM/E,OAAO3C,GAC1BrE,SAASC,eAAeT,YAAY6B,UAAUE,IAAI,4BAC/C,CACH9B,YAAcsM,MAAM/E,OAAO3C,OACvB4I,IAAM9G,SAAS3G,WAAW0N,QAAQ,IAAK,KACvCC,IAAMhH,SAAS1G,YAAYyN,QAAQ,IAAK,QACxCC,KAAOF,cAGPE,IAAMF,IAAK,KACPG,EAAID,IACRA,IAAMF,IACNA,IAAMG,YAkCLH,IAAKE,SACdE,IAAM,IAAMJ,IAAM,IAAME,OACS,OAAjCnN,SAASC,eAAeoN,KAAe,KACnCC,WAAapJ,OAAOC,QAAQ,2BAC5BoJ,MAAQrJ,OAAOC,QAAQ,KAAO8I,KAC9BO,OAAStJ,OAAOC,QAAQ,KAAOgJ,QAC/BG,YAAcC,OAASC,OAAQ,EA1G5BC,GA4GCF,MAAM7I,KA5GHgJ,GA6GHH,MAAM5I,KA7GCgJ,GA8GPH,OAAO9I,KA9GIkJ,GA+GXJ,OAAO7I,KA/GQkJ,QAgHf,mBAhHwBxJ,GAiHxBgJ,IAhHLnJ,OAAOoE,KAAK,KAAOmF,GAAK,IAAMC,GAAK,MAAQC,GAAK,IAAMC,IAAI/F,KAAK,OAAUgG,UAAUxJ,GAAGA,KAkH7EO,MAAM0I,gCACHQ,QAAQT,IAAK,IAAMJ,IAAK,IAAME,UApHtCM,GAAIC,GAAIC,GAAIC,GAAIC,QAASxJ,GAoE5ByJ,CAAQb,IAAKE,SACTI,MAAQvN,SAASC,eAAeT,YAChC+N,OACAA,MAAMlM,UAAUC,OAAO,wBAE3B9B,WAAa,KACbE,WAAaD,YACbA,YAAc,UAGlBoJ,cACArJ,WAAa,cAOZqJ,cACLjF,MAAMC,KAAK7D,SAAS+N,uBAAuB,yBAAyB1F,SAAQ,SAAS2B,GACjFA,EAAE3I,UAAUC,OAAO,2BAEvBsC,MAAMC,KAAK7D,SAAS+N,uBAAuB,2CAA2C1F,SAAQ,SAAS2B,GACnGA,EAAE3I,UAAUC,OAAO,sDAiElBsL,WAAWvI,QACZiE,KAAOtD,YAAYX,IACV,OAATiE,OACAA,KAAKhH,6BACMsL,WAAWvI,cAOrB2B,6BACDgI,aAAehO,SAAS+N,uBAAuB,kBAC/CC,aAAanE,OAAS,EAAG,KACrB5D,WAAajG,SAASC,eAAe,gCACrCgO,cAAgBD,aAAa,GAAGpF,aAAa,OAAOQ,MAAM,KAAK,GAG/D4E,aAAa,GAAGpF,aAAa,OAAOQ,MAAM,KAAK,GAAG8E,SAAS,WAC3DD,eAAiB,QAAUD,aAAa,GAAGpF,aAAa,OAAOQ,MAAM,SAAS,IAElFnD,WAAWvF,aAAa,aAAcuN,yBA4BrCnD,+BACKqD,iBAAiB,8BAA+B7L,oBAAWwJ,iBAChEsC,MAAKC,WAACC,KAACA,KAADC,GAAOA,mCACAC,YAAY,wBAAyBF,KAAMC,IACrD9M,cACO,KAEVgN,OAAMC,KAAM,2BAAiBA,UAC9BC,eAAiBrM,oBAAWwJ,gBAChC6C,eAAeC,MAAQ,UACvBD,eAAeE,MAAQ,+BACvBF,eAAeG,UAAW,qBAChBX,iBAAiB,8BAA+BQ,gBACrDP,MAAKW,YAACT,KAACA,KAADC,GAAOA,oCACAC,YAAY,gCAAiCF,KAAMC,KACtD,KAEVE,OAAMC,KAAM,2BAAiBA,eAO7BlN,uBACDwN,WAAa1M,oBAAW2M,mBACxBtL,QAAUC,MAAMC,KAAKzD,iBAAiB0D,qBAAqB,WAC/DvD,sBAAsBG,aAAa,SAAU,IAC7CiD,QAAQ0E,SAAQ,SAAS6G,GACjBF,WAAWd,SAASgB,EAAEjO,QACtBiO,EAAE7N,UAAUE,IAAI,6BACZ2N,EAAEC,UAC4C,GAA1CD,EAAEtG,aAAa,yBACfrI,sBAAsB2F,gBAAgB,WAI9CgJ,EAAE7N,UAAUC,OAAO,yCAyDtBa,SAASC,KAAMgN,cAChBC,KAAOrP,SAASC,eAAe,eAAiBmC,KAAO,YACvDiN,KAAM,CACNA,KAAKtO,iBAAiB,SAAS,qBAwBjBqB,UACdkN,KAAOtP,SAASC,eAAe,eAAiBmC,KAAO,YACvDkN,YACuC,OAAhCA,KAAK1G,aAAa,iBAEtB,EA5BK2G,CAAanN,MAGboN,SAASpN,eAwDPA,UACVkN,KAAOtP,SAASC,eAAe,eAAiBmC,KAAO,SACvDkN,OACAA,KAAKpJ,gBAAgB,UACrBhE,qBACA+H,eAAe7H,MACfyI,mBAhEQ4E,CAASrN,aAKbsN,MAAQ1P,SAASC,eAAe,eAAiBmC,KAAO,UACxDsN,OACAA,MAAM3O,iBAAiB,SAAS,WAC5ByO,SAASpN,SAIrBgN,SAAS/G,SAAQ,SAASsH,mBAgEP1K,KAAM7C,KAAMwN,QAASC,aAASnM,gEAAW,KACxDoM,SAAW9P,SAASC,eAAe,eAAiBgF,KAAO,IAAM7C,SACjE0N,YAES,aADDA,SAAS5E,WAAWjG,KAAK8K,UAEzBD,SAASpO,QAAUkO,QAAQI,KAAK1N,qBAChCwN,SAAS/O,iBAAiB,SAAS,WAC/B8O,QAAQG,KAAK1N,oBAAYwN,SAASpO,SACjB,OAAbgC,UACAA,WAEJoH,oBAIJgF,SAAS7O,MAAQ2O,QAAQI,KAAK1N,qBAC9BwN,SAAS/O,iBAAiB,SAAS,WAC/B8O,QAAQG,KAAK1N,oBAAYwN,SAAS7O,OACjB,OAAbyC,UACAA,WAEJoH,eApFZmF,CAAc7N,KAAMuN,QAAQvN,KAAMuN,QAAQtN,IAAKsN,QAAQnN,IAAKmN,QAAQjM,SAAUiM,QAAQnC,oBAqBrFgC,SAASpN,UACVkN,KAAOtP,SAASC,eAAe,eAAiBmC,KAAO,SACvDkN,MACAA,KAAK5O,aAAa,SAAU,aAQ3BuJ,qBAAe7H,4DAAO,GACvB8N,WAAalQ,SAASmQ,iBAAiB,qBAC3CD,WAAW7H,SAAQ,SAASiH,MACpBA,KAAKjL,IAAM,eAAiBjC,KAAO,SACnCkN,KAAK5O,aAAa,SAAU,gBA0D/BwB,qBACclC,SAASmQ,iBAAiB,+CAChC9H,SAAQ,SAAS+H,aACtBA,YAAYC,SACZD,YAAYC,QAAQC,WAAWhO,oBAAW8N,YAAY/L,GAAG+E,MAAM,YAAY,iBAU9ExB,iBAAiB2I,YAClBC,UAAYD,OAAOrD,QAAQ,OAAQ,WAChChJ,OAAOC,QAAQ,IAAMqM"} \ No newline at end of file diff --git a/amd/build/placestore.min.js b/amd/build/placestore.min.js index 40f6ec0..251c1c7 100644 --- a/amd/build/placestore.min.js +++ b/amd/build/placestore.min.js @@ -1,3 +1,3 @@ -define("mod_learningmap/placestore",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;let placestore={version:2024072201,id:0,places:[],paths:[],startingplaces:[],targetplaces:[],placecolor:"#c01c28ff",strokecolor:"#ffffffff",strokeopacity:1,textcolor:"#ffffffff",visitedcolor:"#26a269ff",height:100,width:800,hidepaths:!1,mapid:"",usecheckmark:!1,editmode:!0,pulse:!1,hover:!1,showall:!1,showtext:!1,slicemode:!1,showwaygone:!1,placesize:10,loadJSON:function(json){try{let fromjson=JSON.parse(json);null===fromjson.textcolor&&(fromjson.textcolor=fromjson.strokecolor),Object.assign(this,fromjson)}catch{}this.version=2024072201},buildJSON:function(){return JSON.stringify(this.getPlacestore())},addPlace:function(id,linkId){let linkedActivity=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,bbox=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};this.places.push({id:id,linkId:linkId,linkedActivity:linkedActivity,placecolor:null,visitedcolor:null,bbox:bbox||{}}),1==this.places.length&&this.addStartingPlace(id),this.id++},removePlace:function(id){this.removeStartingPlace(id),this.removeTargetPlace(id),this.places=this.places.filter((function(p){return p.id!=id}))},addStartingPlace:function(id){this.startingplaces.push(id)},removeStartingPlace:function(id){this.startingplaces=this.startingplaces.filter((function(e){return e!=id}))},isStartingPlace:function(id){return this.startingplaces.includes(id)},addTargetPlace:function(id){this.targetplaces.push(id)},removeTargetPlace:function(id){this.targetplaces=this.targetplaces.filter((function(e){return e!=id}))},isTargetPlace:function(id){return this.targetplaces.includes(id)},addPath:function(pid,fid,sid){this.paths.push({id:pid,fid:fid,sid:sid,strokecolor:null,strokedasharray:null,hidepath:null})},removePath:function(id){this.paths=this.paths.filter((function(p){return p.id!=id}))},getTouchingPaths:function(id){return this.paths.filter((function(p){return p.fid==id||p.sid==id}))},getActivityId:function(id){let place=this.places.filter((function(e){return id==e.id}));return place.length>0?place[0].linkedActivity:null},setActivityId:function(id,linkedActivity){let place=this.places.filter((function(e){return id==e.id}));place.length>0&&(place[0].linkedActivity=linkedActivity)},getId:function(){return this.id},setBackgroundDimensions:function(width,height){this.width=width,this.height=height},getPathsWithFid:function(id){return this.paths.filter((function(p){return p.fid==id}))},getPathsWithSid:function(id){return this.paths.filter((function(p){return p.sid==id}))},getPlacestore:function(){return{id:this.id,places:this.places,paths:this.paths,startingplaces:this.startingplaces,targetplaces:this.targetplaces,placecolor:this.placecolor,strokecolor:this.strokecolor,strokeopacity:this.strokeopacity,textcolor:this.textcolor,visitedcolor:this.visitedcolor,height:this.height,width:this.width,hidepaths:this.hidepaths,mapid:this.mapid,usecheckmark:this.usecheckmark,editmode:this.editmode,version:this.version,pulse:this.pulse,hover:this.hover,showall:this.showall,showtext:this.showtext,slicemode:this.slicemode,showwaygone:this.showwaygone,placesize:this.placesize}},setHidePaths:function(value){this.hidepaths=value},getHidePaths:function(){return this.hidepaths},setPulse:function(value){this.pulse=value},getPulse:function(){return this.pulse},setHover:function(value){this.hover=value},getHover:function(){return this.hover},setShowall:function(value){this.showall=value},getShowall:function(){return this.showall},getMapid:function(){return this.mapid},getUseCheckmark:function(){return this.usecheckmark},setUseCheckmark:function(value){this.usecheckmark=value},getAllActivities:function(){let activities=[];return this.places.forEach((function(p){p.linkedActivity&&activities.push(p.linkedActivity)})),activities},setStrokeOpacity:function(value){this.strokeopacity=value},getStrokeOpacity:function(){return this.strokeopacity},setHideStroke:function(value){this.strokeopacity=value?0:1},getHideStroke:function(){return this.strokeopacity<1},getShowText:function(){return this.showtext},setShowText:function(value){this.showtext=value},getPlaces:function(){return this.places},getSliceMode:function(){return this.slicemode},setSliceMode:function(value){this.slicemode=value},getShowWayGone:function(){return this.showwaygone},setShowWayGone:function(value){this.showwaygone=value},getPlaceSize:function(){return this.placesize},setPlaceSize:function(value){value>0&&(this.placesize=value)},setPlaceColor:function(color){this.placecolor=color},getPlaceColor:function(){return this.placecolor},setVisitedColor:function(color){this.visitedcolor=color},getVisitedColor:function(){return this.visitedcolor},setStrokeColor:function(color){this.strokecolor=color,this.textcolor=color},getStrokeColor:function(){return this.strokecolor},setBbox:function(id,bbox){let place=this.places.filter((function(e){return id==e.id}));place.length>0&&(place[0].bbox=bbox)}};var _default=placestore;return _exports.default=_default,_exports.default})); +define("mod_learningmap/placestore",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;let placestore={version:2024072201,id:0,places:[],paths:[],startingplaces:[],targetplaces:[],placecolor:"#c01c28ff",strokecolor:"#ffffffff",strokeopacity:1,textcolor:"#ffffffff",visitedcolor:"#26a269ff",height:100,width:800,hidepaths:!1,mapid:"",usecheckmark:!1,editmode:!0,pulse:!1,hover:!1,showall:!1,showtext:!1,slicemode:!1,showwaygone:!1,placesize:10,loadJSON:function(json){try{let fromjson=JSON.parse(json);null===fromjson.textcolor&&(fromjson.textcolor=fromjson.strokecolor),Object.assign(this,fromjson)}catch{}this.version=2024072201},buildJSON:function(){return JSON.stringify(this.getPlacestore())},addPlace:function(id,linkId){let linkedActivity=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null,bbox=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{};this.places.push({id:id,linkId:linkId,linkedActivity:linkedActivity,placecolor:null,visitedcolor:null,bbox:bbox||{}}),1==this.places.length&&this.addStartingPlace(id),this.id++},removePlace:function(id){this.removeStartingPlace(id),this.removeTargetPlace(id),this.places=this.places.filter((function(p){return p.id!=id}))},addStartingPlace:function(id){this.startingplaces.push(id)},removeStartingPlace:function(id){this.startingplaces=this.startingplaces.filter((function(e){return e!=id}))},isStartingPlace:function(id){return this.startingplaces.includes(id)},addTargetPlace:function(id){this.targetplaces.push(id)},removeTargetPlace:function(id){this.targetplaces=this.targetplaces.filter((function(e){return e!=id}))},isTargetPlace:function(id){return this.targetplaces.includes(id)},addPath:function(pid,fid,sid){this.paths.push({id:pid,fid:fid,sid:sid,strokecolor:null,strokedasharray:null,hidepath:null})},removePath:function(id){this.paths=this.paths.filter((function(p){return p.id!=id}))},getTouchingPaths:function(id){return this.paths.filter((function(p){return p.fid==id||p.sid==id}))},getActivityId:function(id){let place=this.places.filter((function(e){return id==e.id}));return place.length>0?place[0].linkedActivity:null},setActivityId:function(id,linkedActivity){let place=this.places.filter((function(e){return id==e.id}));place.length>0&&(place[0].linkedActivity=linkedActivity)},getId:function(){return this.id},setBackgroundDimensions:function(width,height){this.width=width,this.height=height},getPathsWithFid:function(id){return this.paths.filter((function(p){return p.fid==id}))},getPathsWithSid:function(id){return this.paths.filter((function(p){return p.sid==id}))},getPlacestore:function(){return{id:this.id,places:this.places,paths:this.paths,startingplaces:this.startingplaces,targetplaces:this.targetplaces,placecolor:this.placecolor,strokecolor:this.strokecolor,strokeopacity:this.strokeopacity,textcolor:this.textcolor,visitedcolor:this.visitedcolor,height:this.height,width:this.width,hidepaths:this.hidepaths,mapid:this.mapid,usecheckmark:this.usecheckmark,editmode:this.editmode,version:this.version,pulse:this.pulse,hover:this.hover,showall:this.showall,showtext:this.showtext,slicemode:this.slicemode,showwaygone:this.showwaygone,placesize:this.placesize}},setHidePaths:function(value){this.hidepaths=value},getHidePaths:function(){return this.hidepaths},setPulse:function(value){this.pulse=value},getPulse:function(){return this.pulse},setHover:function(value){this.hover=value},getHover:function(){return this.hover},setShowall:function(value){this.showall=value},getShowall:function(){return this.showall},getMapid:function(){return this.mapid},getUseCheckmark:function(){return this.usecheckmark},setUseCheckmark:function(value){this.usecheckmark=value},getAllActivities:function(){let activities=[];return this.places.forEach((function(p){p.linkedActivity&&activities.push(p.linkedActivity)})),activities},setStrokeOpacity:function(value){this.strokeopacity=value},getStrokeOpacity:function(){return this.strokeopacity},setHideStroke:function(value){this.strokeopacity=value?0:1},getHideStroke:function(){return this.strokeopacity<1},getShowText:function(){return this.showtext},setShowText:function(value){this.showtext=value},getPlaces:function(){return this.places},getSliceMode:function(){return this.slicemode},setSliceMode:function(value){this.slicemode=value},getShowWayGone:function(){return this.showwaygone},setShowWayGone:function(value){this.showwaygone=value},getPlaceSize:function(){return this.placesize},setPlaceSize:function(value){value>0&&(this.placesize=value)},setPlaceColor:function(color){this.placecolor=color},getPlaceColor:function(){return this.placecolor},setVisitedColor:function(color){this.visitedcolor=color},getVisitedColor:function(){return this.visitedcolor},setStrokeColor:function(color){this.strokecolor=color},getStrokeColor:function(){return this.strokecolor},getTextColor:function(){return this.textcolor},setTextColor:function(color){this.textcolor=color}};var _default=placestore;return _exports.default=_default,_exports.default})); //# sourceMappingURL=placestore.min.js.map \ No newline at end of file diff --git a/amd/build/placestore.min.js.map b/amd/build/placestore.min.js.map index d6e9de3..98f0728 100644 --- a/amd/build/placestore.min.js.map +++ b/amd/build/placestore.min.js.map @@ -1 +1 @@ -{"version":3,"file":"placestore.min.js","sources":["../src/placestore.js"],"sourcesContent":["let placestore = {\n version: 2024072201,\n id: 0,\n places: [],\n paths: [],\n startingplaces: [],\n targetplaces: [],\n placecolor: '#c01c28ff',\n strokecolor: '#ffffffff',\n strokeopacity: 1,\n textcolor: '#ffffffff',\n visitedcolor: '#26a269ff',\n height: 100,\n width: 800,\n hidepaths: false,\n mapid: '',\n usecheckmark: false,\n editmode: true,\n pulse: false,\n hover: false,\n showall: false,\n showtext: false,\n slicemode: false,\n showwaygone: false,\n placesize: 10,\n /**\n * Loads attributes from JSON into placestore\n * @param {*} json\n */\n loadJSON: function(json) {\n try {\n let fromjson = JSON.parse(json);\n if (fromjson.textcolor === null) {\n fromjson.textcolor = fromjson.strokecolor;\n }\n Object.assign(this, fromjson);\n // eslint-disable-next-line no-empty\n } catch { }\n // Update version (only relevant if learning map is saved)\n this.version = 2024072201;\n },\n /**\n * Returns placestore as a JSON string ()\n * @returns {string}\n */\n buildJSON: function() {\n return JSON.stringify(this.getPlacestore());\n },\n /**\n * Adds a place. If it is the only place, it is set as starting place\n * @param {*} id id of the place\n * @param {*} linkId id of the corresponding link\n * @param {*} linkedActivity course module id of linked activity\n * @param {*} bbox bounding box of the place (including text)\n */\n addPlace: function(id, linkId, linkedActivity = null, bbox = {}) {\n this.places.push({\n id: id,\n linkId: linkId,\n linkedActivity: linkedActivity,\n placecolor: null,\n visitedcolor: null,\n bbox: bbox || {},\n });\n if (this.places.length == 1) {\n this.addStartingPlace(id);\n }\n this.id++;\n },\n /**\n * Removes a place\n * @param {*} id id of the place\n */\n removePlace: function(id) {\n this.removeStartingPlace(id);\n this.removeTargetPlace(id);\n this.places = this.places.filter(\n function(p) {\n return p.id != id;\n }\n );\n },\n /**\n * Adds a place to the array of starting places\n * @param {*} id id of the place\n */\n addStartingPlace: function(id) {\n this.startingplaces.push(id);\n },\n /**\n * Removes a place from the array of starting places\n * @param {*} id id of the place\n */\n removeStartingPlace: function(id) {\n this.startingplaces = this.startingplaces.filter(\n function(e) {\n return e != id;\n }\n );\n },\n /**\n * Returns whether a place is in the array of starting places\n * @param {*} id id of the place\n * @returns {boolean}\n */\n isStartingPlace: function(id) {\n return this.startingplaces.includes(id);\n },\n /**\n * Adds a place to the array of target places\n * @param {*} id id of the place\n */\n addTargetPlace: function(id) {\n this.targetplaces.push(id);\n },\n /**\n * Removes a place from the array of target places\n * @param {*} id id of the place\n */\n removeTargetPlace: function(id) {\n this.targetplaces = this.targetplaces.filter(\n function(e) {\n return e != id;\n }\n );\n },\n /**\n * Returns whether a place is in the array of target places\n * @param {number} id id of the place\n * @returns {boolean}\n */\n isTargetPlace: function(id) {\n return this.targetplaces.includes(id);\n },\n /**\n * Adds a path between two places\n * @param {*} pid id of the path\n * @param {*} fid id of the first place\n * @param {*} sid id of the second place\n */\n addPath: function(pid, fid, sid) {\n this.paths.push({\n id: pid,\n fid: fid,\n sid: sid,\n strokecolor: null,\n strokedasharray: null,\n hidepath: null\n });\n },\n /**\n * Removes a path\n * @param {*} id id of the place\n */\n removePath: function(id) {\n this.paths = this.paths.filter(\n function(p) {\n return p.id != id;\n }\n );\n },\n /**\n * Returns an array of paths touching a place\n * @param {*} id id of the place\n * @returns {array}\n */\n getTouchingPaths: function(id) {\n return this.paths.filter(\n function(p) {\n return p.fid == id || p.sid == id;\n }\n );\n },\n /**\n * Returns the course module id linked to a place\n * @param {*} id id of the place\n * @returns {number} id of the linked course module\n */\n getActivityId: function(id) {\n let place = this.places.filter(\n function(e) {\n return id == e.id;\n }\n );\n if (place.length > 0) {\n return place[0].linkedActivity;\n } else {\n return null;\n }\n },\n /**\n * Sets the id of the linked course module\n * @param {*} id id of the place\n * @param {*} linkedActivity course module id\n */\n setActivityId: function(id, linkedActivity) {\n let place = this.places.filter(\n function(e) {\n return id == e.id;\n }\n );\n if (place.length > 0) {\n place[0].linkedActivity = linkedActivity;\n }\n },\n /**\n * Returns the current id\n * @returns {number}\n */\n getId: function() {\n return this.id;\n },\n /**\n * Sets the dimensions of the background image\n * @param {*} width\n * @param {*} height\n */\n setBackgroundDimensions: function(width, height) {\n this.width = width;\n this.height = height;\n },\n /**\n * Returns all paths starting at a place\n * @param {*} id id of the place\n * @returns {array}\n */\n getPathsWithFid: function(id) {\n return this.paths.filter(function(p) {\n return p.fid == id;\n });\n },\n /**\n * Returns all paths ending at a place\n * @param {*} id id of the place\n * @returns {array}\n */\n getPathsWithSid: function(id) {\n return this.paths.filter(function(p) {\n return p.sid == id;\n });\n },\n /**\n * Returns the attributes of placestore\n * @returns {object}\n */\n getPlacestore: function() {\n return {\n id: this.id,\n places: this.places,\n paths: this.paths,\n startingplaces: this.startingplaces,\n targetplaces: this.targetplaces,\n placecolor: this.placecolor,\n strokecolor: this.strokecolor,\n strokeopacity: this.strokeopacity,\n textcolor: this.textcolor,\n visitedcolor: this.visitedcolor,\n height: this.height,\n width: this.width,\n hidepaths: this.hidepaths,\n mapid: this.mapid,\n usecheckmark: this.usecheckmark,\n editmode: this.editmode,\n version: this.version,\n pulse: this.pulse,\n hover: this.hover,\n showall: this.showall,\n showtext: this.showtext,\n slicemode: this.slicemode,\n showwaygone: this.showwaygone,\n placesize: this.placesize,\n };\n },\n /**\n * Sets hidepaths attribute\n * @param {boolean} value\n */\n setHidePaths: function(value) {\n this.hidepaths = value;\n },\n /**\n * Returns the value of hidepaths attribute\n * @returns {boolean}\n */\n getHidePaths: function() {\n return this.hidepaths;\n },\n /**\n * Sets pulse attribute\n * @param {boolean} value\n */\n setPulse: function(value) {\n this.pulse = value;\n },\n /**\n * Returns the value of pulse attribute\n * @returns {boolean}\n */\n getPulse: function() {\n return this.pulse;\n },\n /**\n * Sets hover attribute\n * @param {boolean} value\n */\n setHover: function(value) {\n this.hover = value;\n },\n /**\n * Returns the value of hover attribute\n * @returns {boolean}\n */\n getHover: function() {\n return this.hover;\n },\n /**\n * Sets showall attribute\n * @param {boolean} value\n */\n setShowall: function(value) {\n this.showall = value;\n },\n /**\n * Returns the value of showall attribute\n * @returns {boolean}\n */\n getShowall: function() {\n return this.showall;\n },\n /**\n * Returns the mapid\n * @returns {string}\n */\n getMapid: function() {\n return this.mapid;\n },\n /**\n * Returns the value of usecheckmark attribute\n * @returns {boolean}\n */\n getUseCheckmark: function() {\n return this.usecheckmark;\n },\n /**\n * Sets the value of usecheckmark attribute\n * @param {boolean} value\n */\n setUseCheckmark: function(value) {\n this.usecheckmark = value;\n },\n /**\n * Returns an array with all activity ids\n * @returns {array}\n */\n getAllActivities: function() {\n let activities = [];\n this.places.forEach(function(p) {\n if (p.linkedActivity) {\n activities.push(p.linkedActivity);\n }\n });\n return activities;\n },\n /**\n * Sets stroke opacity\n * @param {number} value\n */\n setStrokeOpacity: function(value) {\n this.strokeopacity = value;\n },\n /**\n * Returns the current stroke opacity\n * @returns {number}\n */\n getStrokeOpacity: function() {\n return this.strokeopacity;\n },\n /**\n * Sets stroke opacity to 0\n * @param {number} value\n */\n setHideStroke: function(value) {\n this.strokeopacity = (value ? 0 : 1);\n },\n /**\n * Returns the current stroke opacity\n * @returns {number}\n */\n getHideStroke: function() {\n return this.strokeopacity < 1;\n },\n /**\n * Returns the value of showtext attribute\n * @returns {boolean}\n */\n getShowText: function() {\n return this.showtext;\n },\n /**\n * Sets the value of showtext attribute\n * @param {boolean} value\n */\n setShowText: function(value) {\n this.showtext = value;\n },\n /**\n * Returns an array with all place identifiers\n * @returns {array}\n */\n getPlaces: function() {\n return this.places;\n },\n /**\n * Returns if slicemode is enabled\n * @returns {boolean}\n */\n getSliceMode: function() {\n return this.slicemode;\n },\n /**\n * Sets state of slicemode\n * @param {boolean} value\n */\n setSliceMode: function(value) {\n this.slicemode = value;\n },\n /**\n * Returns if showwaygone is enabled\n * @returns {boolean}\n */\n getShowWayGone: function() {\n return this.showwaygone;\n },\n /**\n * Sets state of showwaygone\n * @param {boolean} value\n */\n setShowWayGone: function(value) {\n this.showwaygone = value;\n },\n /**\n * Returns the size of places\n * @returns {number}\n */\n getPlaceSize: function() {\n return this.placesize;\n },\n /**\n * Sets the size of places\n * @param {number} value\n */\n setPlaceSize: function(value) {\n if (value > 0) {\n this.placesize = value;\n }\n },\n /**\n * Sets the color of places\n * @param {*} color\n */\n setPlaceColor: function(color) {\n this.placecolor = color;\n },\n /**\n * Returns the color of places\n * @returns {string}\n */\n getPlaceColor: function() {\n return this.placecolor;\n },\n /**\n * Sets the color of visited places\n * @param {*} color\n */\n setVisitedColor: function(color) {\n this.visitedcolor = color;\n },\n /**\n * Returns the color of visited places\n * @returns {string}\n */\n getVisitedColor: function() {\n return this.visitedcolor;\n },\n /**\n * Sets the color of strokes and the text\n * @param {*} color\n */\n setStrokeColor: function(color) {\n this.strokecolor = color;\n // Until there is a separate text color, set it to the same color as the stroke.\n this.textcolor = color;\n },\n /**\n * Returns the color of strokes\n * @returns {string}\n */\n getStrokeColor: function() {\n return this.strokecolor;\n },\n /**\n * Sets the bbox of the place\n * @param {*} id id of the place\n * @param {*} bbox bounding box of the place (including text)\n */\n setBbox: function(id, bbox) {\n let place = this.places.filter(\n function(e) {\n return id == e.id;\n }\n );\n if (place.length > 0) {\n place[0].bbox = bbox;\n }\n },\n};\n\nexport default placestore;\n"],"names":["placestore","version","id","places","paths","startingplaces","targetplaces","placecolor","strokecolor","strokeopacity","textcolor","visitedcolor","height","width","hidepaths","mapid","usecheckmark","editmode","pulse","hover","showall","showtext","slicemode","showwaygone","placesize","loadJSON","json","fromjson","JSON","parse","Object","assign","this","buildJSON","stringify","getPlacestore","addPlace","linkId","linkedActivity","bbox","push","length","addStartingPlace","removePlace","removeStartingPlace","removeTargetPlace","filter","p","e","isStartingPlace","includes","addTargetPlace","isTargetPlace","addPath","pid","fid","sid","strokedasharray","hidepath","removePath","getTouchingPaths","getActivityId","place","setActivityId","getId","setBackgroundDimensions","getPathsWithFid","getPathsWithSid","setHidePaths","value","getHidePaths","setPulse","getPulse","setHover","getHover","setShowall","getShowall","getMapid","getUseCheckmark","setUseCheckmark","getAllActivities","activities","forEach","setStrokeOpacity","getStrokeOpacity","setHideStroke","getHideStroke","getShowText","setShowText","getPlaces","getSliceMode","setSliceMode","getShowWayGone","setShowWayGone","getPlaceSize","setPlaceSize","setPlaceColor","color","getPlaceColor","setVisitedColor","getVisitedColor","setStrokeColor","getStrokeColor","setBbox"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"placestore.min.js","sources":["../src/placestore.js"],"sourcesContent":["let placestore = {\n version: 2024072201,\n id: 0,\n places: [],\n paths: [],\n startingplaces: [],\n targetplaces: [],\n placecolor: '#c01c28ff',\n strokecolor: '#ffffffff',\n strokeopacity: 1,\n textcolor: '#ffffffff',\n visitedcolor: '#26a269ff',\n height: 100,\n width: 800,\n hidepaths: false,\n mapid: '',\n usecheckmark: false,\n editmode: true,\n pulse: false,\n hover: false,\n showall: false,\n showtext: false,\n slicemode: false,\n showwaygone: false,\n placesize: 10,\n /**\n * Loads attributes from JSON into placestore\n * @param {*} json\n */\n loadJSON: function(json) {\n try {\n let fromjson = JSON.parse(json);\n if (fromjson.textcolor === null) {\n fromjson.textcolor = fromjson.strokecolor;\n }\n Object.assign(this, fromjson);\n // eslint-disable-next-line no-empty\n } catch { }\n // Update version (only relevant if learning map is saved)\n this.version = 2024072201;\n },\n /**\n * Returns placestore as a JSON string ()\n * @returns {string}\n */\n buildJSON: function() {\n return JSON.stringify(this.getPlacestore());\n },\n /**\n * Adds a place. If it is the only place, it is set as starting place\n * @param {*} id id of the place\n * @param {*} linkId id of the corresponding link\n * @param {*} linkedActivity course module id of linked activity\n * @param {*} bbox bounding box of the place (including text)\n */\n addPlace: function(id, linkId, linkedActivity = null, bbox = {}) {\n this.places.push({\n id: id,\n linkId: linkId,\n linkedActivity: linkedActivity,\n placecolor: null,\n visitedcolor: null,\n bbox: bbox || {},\n });\n if (this.places.length == 1) {\n this.addStartingPlace(id);\n }\n this.id++;\n },\n /**\n * Removes a place\n * @param {*} id id of the place\n */\n removePlace: function(id) {\n this.removeStartingPlace(id);\n this.removeTargetPlace(id);\n this.places = this.places.filter(\n function(p) {\n return p.id != id;\n }\n );\n },\n /**\n * Adds a place to the array of starting places\n * @param {*} id id of the place\n */\n addStartingPlace: function(id) {\n this.startingplaces.push(id);\n },\n /**\n * Removes a place from the array of starting places\n * @param {*} id id of the place\n */\n removeStartingPlace: function(id) {\n this.startingplaces = this.startingplaces.filter(\n function(e) {\n return e != id;\n }\n );\n },\n /**\n * Returns whether a place is in the array of starting places\n * @param {*} id id of the place\n * @returns {boolean}\n */\n isStartingPlace: function(id) {\n return this.startingplaces.includes(id);\n },\n /**\n * Adds a place to the array of target places\n * @param {*} id id of the place\n */\n addTargetPlace: function(id) {\n this.targetplaces.push(id);\n },\n /**\n * Removes a place from the array of target places\n * @param {*} id id of the place\n */\n removeTargetPlace: function(id) {\n this.targetplaces = this.targetplaces.filter(\n function(e) {\n return e != id;\n }\n );\n },\n /**\n * Returns whether a place is in the array of target places\n * @param {number} id id of the place\n * @returns {boolean}\n */\n isTargetPlace: function(id) {\n return this.targetplaces.includes(id);\n },\n /**\n * Adds a path between two places\n * @param {*} pid id of the path\n * @param {*} fid id of the first place\n * @param {*} sid id of the second place\n */\n addPath: function(pid, fid, sid) {\n this.paths.push({\n id: pid,\n fid: fid,\n sid: sid,\n strokecolor: null,\n strokedasharray: null,\n hidepath: null\n });\n },\n /**\n * Removes a path\n * @param {*} id id of the place\n */\n removePath: function(id) {\n this.paths = this.paths.filter(\n function(p) {\n return p.id != id;\n }\n );\n },\n /**\n * Returns an array of paths touching a place\n * @param {*} id id of the place\n * @returns {array}\n */\n getTouchingPaths: function(id) {\n return this.paths.filter(\n function(p) {\n return p.fid == id || p.sid == id;\n }\n );\n },\n /**\n * Returns the course module id linked to a place\n * @param {*} id id of the place\n * @returns {number} id of the linked course module\n */\n getActivityId: function(id) {\n let place = this.places.filter(\n function(e) {\n return id == e.id;\n }\n );\n if (place.length > 0) {\n return place[0].linkedActivity;\n } else {\n return null;\n }\n },\n /**\n * Sets the id of the linked course module\n * @param {*} id id of the place\n * @param {*} linkedActivity course module id\n */\n setActivityId: function(id, linkedActivity) {\n let place = this.places.filter(\n function(e) {\n return id == e.id;\n }\n );\n if (place.length > 0) {\n place[0].linkedActivity = linkedActivity;\n }\n },\n /**\n * Returns the current id\n * @returns {number}\n */\n getId: function() {\n return this.id;\n },\n /**\n * Sets the dimensions of the background image\n * @param {*} width\n * @param {*} height\n */\n setBackgroundDimensions: function(width, height) {\n this.width = width;\n this.height = height;\n },\n /**\n * Returns all paths starting at a place\n * @param {*} id id of the place\n * @returns {array}\n */\n getPathsWithFid: function(id) {\n return this.paths.filter(function(p) {\n return p.fid == id;\n });\n },\n /**\n * Returns all paths ending at a place\n * @param {*} id id of the place\n * @returns {array}\n */\n getPathsWithSid: function(id) {\n return this.paths.filter(function(p) {\n return p.sid == id;\n });\n },\n /**\n * Returns the attributes of placestore\n * @returns {object}\n */\n getPlacestore: function() {\n return {\n id: this.id,\n places: this.places,\n paths: this.paths,\n startingplaces: this.startingplaces,\n targetplaces: this.targetplaces,\n placecolor: this.placecolor,\n strokecolor: this.strokecolor,\n strokeopacity: this.strokeopacity,\n textcolor: this.textcolor,\n visitedcolor: this.visitedcolor,\n height: this.height,\n width: this.width,\n hidepaths: this.hidepaths,\n mapid: this.mapid,\n usecheckmark: this.usecheckmark,\n editmode: this.editmode,\n version: this.version,\n pulse: this.pulse,\n hover: this.hover,\n showall: this.showall,\n showtext: this.showtext,\n slicemode: this.slicemode,\n showwaygone: this.showwaygone,\n placesize: this.placesize,\n };\n },\n /**\n * Sets hidepaths attribute\n * @param {boolean} value\n */\n setHidePaths: function(value) {\n this.hidepaths = value;\n },\n /**\n * Returns the value of hidepaths attribute\n * @returns {boolean}\n */\n getHidePaths: function() {\n return this.hidepaths;\n },\n /**\n * Sets pulse attribute\n * @param {boolean} value\n */\n setPulse: function(value) {\n this.pulse = value;\n },\n /**\n * Returns the value of pulse attribute\n * @returns {boolean}\n */\n getPulse: function() {\n return this.pulse;\n },\n /**\n * Sets hover attribute\n * @param {boolean} value\n */\n setHover: function(value) {\n this.hover = value;\n },\n /**\n * Returns the value of hover attribute\n * @returns {boolean}\n */\n getHover: function() {\n return this.hover;\n },\n /**\n * Sets showall attribute\n * @param {boolean} value\n */\n setShowall: function(value) {\n this.showall = value;\n },\n /**\n * Returns the value of showall attribute\n * @returns {boolean}\n */\n getShowall: function() {\n return this.showall;\n },\n /**\n * Returns the mapid\n * @returns {string}\n */\n getMapid: function() {\n return this.mapid;\n },\n /**\n * Returns the value of usecheckmark attribute\n * @returns {boolean}\n */\n getUseCheckmark: function() {\n return this.usecheckmark;\n },\n /**\n * Sets the value of usecheckmark attribute\n * @param {boolean} value\n */\n setUseCheckmark: function(value) {\n this.usecheckmark = value;\n },\n /**\n * Returns an array with all activity ids\n * @returns {array}\n */\n getAllActivities: function() {\n let activities = [];\n this.places.forEach(function(p) {\n if (p.linkedActivity) {\n activities.push(p.linkedActivity);\n }\n });\n return activities;\n },\n /**\n * Sets stroke opacity\n * @param {number} value\n */\n setStrokeOpacity: function(value) {\n this.strokeopacity = value;\n },\n /**\n * Returns the current stroke opacity\n * @returns {number}\n */\n getStrokeOpacity: function() {\n return this.strokeopacity;\n },\n /**\n * Sets stroke opacity to 0\n * @param {number} value\n */\n setHideStroke: function(value) {\n this.strokeopacity = (value ? 0 : 1);\n },\n /**\n * Returns the current stroke opacity\n * @returns {number}\n */\n getHideStroke: function() {\n return this.strokeopacity < 1;\n },\n /**\n * Returns the value of showtext attribute\n * @returns {boolean}\n */\n getShowText: function() {\n return this.showtext;\n },\n /**\n * Sets the value of showtext attribute\n * @param {boolean} value\n */\n setShowText: function(value) {\n this.showtext = value;\n },\n /**\n * Returns an array with all place identifiers\n * @returns {array}\n */\n getPlaces: function() {\n return this.places;\n },\n /**\n * Returns if slicemode is enabled\n * @returns {boolean}\n */\n getSliceMode: function() {\n return this.slicemode;\n },\n /**\n * Sets state of slicemode\n * @param {boolean} value\n */\n setSliceMode: function(value) {\n this.slicemode = value;\n },\n /**\n * Returns if showwaygone is enabled\n * @returns {boolean}\n */\n getShowWayGone: function() {\n return this.showwaygone;\n },\n /**\n * Sets state of showwaygone\n * @param {boolean} value\n */\n setShowWayGone: function(value) {\n this.showwaygone = value;\n },\n /**\n * Returns the size of places\n * @returns {number}\n */\n getPlaceSize: function() {\n return this.placesize;\n },\n /**\n * Sets the size of places\n * @param {number} value\n */\n setPlaceSize: function(value) {\n if (value > 0) {\n this.placesize = value;\n }\n },\n /**\n * Sets the color of places\n * @param {*} color\n */\n setPlaceColor: function(color) {\n this.placecolor = color;\n },\n /**\n * Returns the color of places\n * @returns {string}\n */\n getPlaceColor: function() {\n return this.placecolor;\n },\n /**\n * Sets the color of visited places\n * @param {*} color\n */\n setVisitedColor: function(color) {\n this.visitedcolor = color;\n },\n /**\n * Returns the color of visited places\n * @returns {string}\n */\n getVisitedColor: function() {\n return this.visitedcolor;\n },\n /**\n * Sets the color of strokes and the text\n * @param {*} color\n */\n setStrokeColor: function(color) {\n this.strokecolor = color;\n },\n /**\n * Returns the color of strokes\n * @returns {string}\n */\n getStrokeColor: function() {\n return this.strokecolor;\n },\n /**\n * Returns the color of the text\n * @returns {string}\n */\n getTextColor: function() {\n return this.textcolor;\n },\n /**\n * Sets the color of the text\n * @param {*} color\n */\n setTextColor: function(color) {\n this.textcolor = color;\n },\n};\n\nexport default placestore;\n"],"names":["placestore","version","id","places","paths","startingplaces","targetplaces","placecolor","strokecolor","strokeopacity","textcolor","visitedcolor","height","width","hidepaths","mapid","usecheckmark","editmode","pulse","hover","showall","showtext","slicemode","showwaygone","placesize","loadJSON","json","fromjson","JSON","parse","Object","assign","this","buildJSON","stringify","getPlacestore","addPlace","linkId","linkedActivity","bbox","push","length","addStartingPlace","removePlace","removeStartingPlace","removeTargetPlace","filter","p","e","isStartingPlace","includes","addTargetPlace","isTargetPlace","addPath","pid","fid","sid","strokedasharray","hidepath","removePath","getTouchingPaths","getActivityId","place","setActivityId","getId","setBackgroundDimensions","getPathsWithFid","getPathsWithSid","setHidePaths","value","getHidePaths","setPulse","getPulse","setHover","getHover","setShowall","getShowall","getMapid","getUseCheckmark","setUseCheckmark","getAllActivities","activities","forEach","setStrokeOpacity","getStrokeOpacity","setHideStroke","getHideStroke","getShowText","setShowText","getPlaces","getSliceMode","setSliceMode","getShowWayGone","setShowWayGone","getPlaceSize","setPlaceSize","setPlaceColor","color","getPlaceColor","setVisitedColor","getVisitedColor","setStrokeColor","getStrokeColor","getTextColor","setTextColor"],"mappings":"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"} \ No newline at end of file diff --git a/amd/src/learningmap.js b/amd/src/learningmap.js index 288337f..b4bfda5 100644 --- a/amd/src/learningmap.js +++ b/amd/src/learningmap.js @@ -3,6 +3,7 @@ import Templates from 'core/templates'; import placestore from 'mod_learningmap/placestore'; import svgjs from 'mod_learningmap/svg'; import shapes from './shapes'; +import emojiPicker from 'core/emoji/picker'; // Constants for updatePathDeclaration. const targetPoints = { @@ -148,6 +149,7 @@ export const init = () => { {name: 'placecolor', get: placestore.getPlaceColor, set: placestore.setPlaceColor}, {name: 'visitedcolor', get: placestore.getVisitedColor, set: placestore.setVisitedColor}, {name: 'strokecolor', get: placestore.getStrokeColor, set: placestore.setStrokeColor}, + {name: 'textcolor', get: placestore.getTextColor, set: placestore.setTextColor}, ]); // Get SVG code from the (hidden) textarea field @@ -308,7 +310,7 @@ export const init = () => { } else if (evt.target.nodeName == 'text') { selectedElement = evt.target; let svgel = getSVGShape(selectedElement); - let place = svgel.parent().findOne('.learningmap-place'); + let place = findPlaceForText(selectedElement.id); offset = getMousePosition(evt); offset.x -= svgel.attr('dx') + place.cx(); offset.y -= svgel.attr('dy') + place.cy(); @@ -368,10 +370,9 @@ export const init = () => { } } }); - placestore.setBbox(selectedElement.id, placeel.parent().bbox()); } else if (selectedElement.nodeName == 'text') { let textel = getSVGShape(selectedElement); - let place = textel.parent().findOne('.learningmap-place'); + let place = findPlaceForText(selectedElement.id); // Calculate the delta from the current mouse position to the corresponding place. // coord: current mouse position // offset: delta from the mouse position to the coordinates of the text node @@ -380,7 +381,6 @@ export const init = () => { // We cannot use the dx() and dy() functions of the text node, because they are not // setting the attributes dx and dy. textel.attr({dx: dx, dy: dy}); - placestore.setBbox(place.node.id, textel.parent().bbox()); } else if (selectedElement.nodeName == 'path') { selectedElement.setAttribute( 'd', @@ -624,11 +624,10 @@ export const init = () => { * @param {*} child child item to set the link on * @param {*} id id of the link * @param {*} title title of the link - * @param {*} text text to describe the link * @returns {any} */ - function link(child, id, title = null, text = null) { - return mapsvg.link('').id(id).add(child).add(title).add(text); + function link(child, id, title = null) { + return mapsvg.link('').id(id).add(child).add(title); } /** @@ -637,7 +636,8 @@ export const init = () => { * @param {*} event event causing the command */ function addPlace(event) { - let placesgroup = mapsvg.findOne('#placesGroup'); + let placesgroup = mapsvg.findOne('.learningmap-places-group'); + let textgroup = mapsvg.findOne('.learningmap-text-group'); let placeId = 'p' + placestore.getId(); let linkId = 'a' + placestore.getId(); var CTM = event.target.getScreenCTM(); @@ -647,12 +647,13 @@ export const init = () => { let cx = (event.clientX - CTM.e) / CTM.a; let cy = (event.clientY - CTM.f) / CTM.d; let svglink = link( - shapes.emoji(mapsvg, cx, cy, circleRadius, 'learningmap-place learningmap-draggable learningmap-emptyplace', placeId), + shapes.circle(mapsvg, cx, cy, circleRadius, 'learningmap-place learningmap-draggable learningmap-emptyplace', placeId), linkId, - title('title' + placeId), - text('text' + placeId, '', cx, cy) + title('title' + placeId) ); svglink.addTo(placesgroup); + let textNode = text('text' + placeId, '', cx, cy); + textNode.addTo(textgroup); placestore.addPlace(placeId, linkId, null, svglink.bbox()); } @@ -716,7 +717,7 @@ export const init = () => { function addPath(fid, sid) { let pid = 'p' + fid + '_' + sid; if (document.getElementById(pid) === null) { - let pathsgroup = mapsvg.findOne('#pathsGroup'); + let pathsgroup = mapsvg.findOne('.learningmap-pathsgroup'); let first = mapsvg.findOne('#p' + fid); let second = mapsvg.findOne('#p' + sid); if (pathsgroup && first && second) { @@ -745,6 +746,10 @@ export const init = () => { removePathsTouchingPlace(event.target.id); placestore.removePlace(event.target.id); place.parent().remove(); + let textNode = document.getElementById('text' + event.target.id); + if (textNode) { + textNode.remove(); + } updateCode(); } @@ -862,6 +867,7 @@ export const init = () => { function fixPlaceLabels() { let options = Array.from(activitySelector.getElementsByTagName('option')); let places = placestore.getPlaces(); + let textgroup = mapsvg.findOne('.learningmap-text-group'); for (const place of places) { if (document.getElementById('text' + place.id) === null) { let content = ''; @@ -873,7 +879,10 @@ export const init = () => { } let placeNode = mapsvg.findOne('#' + place.id); let textNode = text('text' + place.id, content, placeNode.cx(), placeNode.cy()); - textNode.addTo(placeNode.parent()); + textNode.addTo(textgroup); + } else { + let textNode = mapsvg.findOne('#text' + place.id); + textNode.addTo(textgroup); } } } @@ -1024,4 +1033,14 @@ export const init = () => { } }); } + + /** + * Returns the place that belongs to the given text id. + * @param {*} textId + * @returns + */ + function findPlaceForText(textId) { + let placename = textId.replace('text', ''); + return mapsvg.findOne('#' + placename); + } }; diff --git a/amd/src/placestore.js b/amd/src/placestore.js index 2ebed17..971fd19 100644 --- a/amd/src/placestore.js +++ b/amd/src/placestore.js @@ -488,8 +488,6 @@ let placestore = { */ setStrokeColor: function(color) { this.strokecolor = color; - // Until there is a separate text color, set it to the same color as the stroke. - this.textcolor = color; }, /** * Returns the color of strokes @@ -499,19 +497,18 @@ let placestore = { return this.strokecolor; }, /** - * Sets the bbox of the place - * @param {*} id id of the place - * @param {*} bbox bounding box of the place (including text) + * Returns the color of the text + * @returns {string} */ - setBbox: function(id, bbox) { - let place = this.places.filter( - function(e) { - return id == e.id; - } - ); - if (place.length > 0) { - place[0].bbox = bbox; - } + getTextColor: function() { + return this.textcolor; + }, + /** + * Sets the color of the text + * @param {*} color + */ + setTextColor: function(color) { + this.textcolor = color; }, }; diff --git a/classes/mapworker.php b/classes/mapworker.php index b14d2b0..d8d16a1 100644 --- a/classes/mapworker.php +++ b/classes/mapworker.php @@ -110,7 +110,7 @@ public function replace_stylesheet(array $placestoreoverride = []): void { * @return void */ public function replace_defs(): void { - $this->svgmap->replace_defs(); + $this->svgmap->replace_defs(['mapid' => $this->placestore['mapid']]); } /** diff --git a/classes/svgmap.php b/classes/svgmap.php index 3219d41..e2ee2ce 100644 --- a/classes/svgmap.php +++ b/classes/svgmap.php @@ -102,14 +102,14 @@ public function replace_stylesheet(array $placestoreoverride = []): void { /** * Replaces the svg defs (e.g.) filters or patterns that are defined for use in the document without being directly visible. - * + * @param array $context Context for the template * @return void */ - public function replace_defs(): void { + public function replace_defs($context = []): void { global $OUTPUT; $this->svgcode = preg_replace( '//i', - $OUTPUT->render_from_template('mod_learningmap/svgdefs', []), + $OUTPUT->render_from_template('mod_learningmap/svgdefs', $context), $this->svgcode ); $this->load_dom(); @@ -121,9 +121,34 @@ public function replace_defs(): void { * @return void */ public function fix_svg(): void { - $placesgroup = $this->dom->getElementById('pathsGroup'); + $placesgroup = $this->dom->getElementById('placesGroup'); if ($placesgroup) { - $placesgroup->setAttribute('mask', 'url(#placemask)'); + $placesgroup->setAttribute('id', 'placesGroup-' . $this->placestore['mapid']); + $placesgroup->setAttribute('class', 'learningmap-places-group'); + } + $pathsgroup = $this->dom->getElementById('pathsGroup'); + if ($pathsgroup) { + $pathsgroup->setAttribute('mask', 'url(#placemask-' . $this->placestore['mapid'] . ')'); + $pathsgroup->setAttribute('id', 'pathsGroup-' . $this->placestore['mapid']); + $pathsgroup->setAttribute('class', 'learningmap-paths-group'); + } + $backgroundgroup = $this->dom->getElementById('backgroundGroup'); + if ($backgroundgroup) { + $backgroundgroup->setAttribute('id', 'backgroundGroup-' . $this->placestore['mapid']); + $backgroundgroup->setAttribute('class', 'learningmap-background-group'); + } + $textgroup = $this->dom->getElementById('textGroup-' . $this->placestore['mapid']); + if (!$textgroup) { + $textgroup = $this->dom->createElement('g'); + $textgroup->setAttribute('id', 'textGroup-' . $this->placestore['mapid']); + $textgroup->setAttribute('class', 'learningmap-text-group'); + $this->dom->getElementById('learningmap-svgmap-' . $this->placestore['mapid'])->appendChild($textgroup); + } + $textelements = $this->dom->getElementsByTagName('text'); + foreach ($textelements as $textelement) { + if (str_starts_with($textelement->getAttribute('id'), 'textp')) { + $textgroup->appendChild($textelement); + } } $this->save_svg_data(); } @@ -196,6 +221,11 @@ public function remove_place_or_path(string $id): void { $this->remove_place_or_path($path['id']); } } + // Remove text. + $text = $this->dom->getElementById('text' . $id); + if ($text) { + $text->parentNode->removeChild($text); + } // Make sure that also the link node is removed. $placeorpath = $placeorpath->parentNode; } @@ -332,7 +362,13 @@ public function get_coordinates(): array { global $CFG; $coordinates = []; $pathsgroup = $this->dom->getElementById('pathsGroup'); + if (!$pathsgroup) { + $pathsgroup = $this->dom->getElementById('pathsGroup-' . $this->placestore['mapid']); + } $placesgroup = $this->dom->getElementById('placesGroup'); + if (!$placesgroup) { + $placesgroup = $this->dom->getElementById('placesGroup-' . $this->placestore['mapid']); + } if (empty($this->placestore['hidepaths'])) { // Only processing quadratic bezier curves here as other paths are already handled // via the coordinates of the corresponding places. @@ -415,6 +451,9 @@ public function add_overlay(): void { $maxy = min($height, $maxy + $padding); $placesgroup = $this->dom->getElementById('placesGroup'); + if (!$placesgroup) { + $placesgroup = $this->dom->getElementById('placesGroup-' . $this->placestore['mapid']); + } // Create the overlay for slicemode. $overlay = $this->dom->createElement('path'); diff --git a/lang/en/learningmap.php b/lang/en/learningmap.php index 2cace05..cfb047a 100644 --- a/lang/en/learningmap.php +++ b/lang/en/learningmap.php @@ -79,6 +79,8 @@ $string['placecolor_help'] = 'This color will be used for the places (if it is unvisited).'; $string['places'] = 'Places'; $string['placesettings'] = 'Place settings'; +$string['placeemoji'] = 'Place emoji'; +$string['placeemoji_help'] = 'This emoji will be used for unvisited places.'; $string['placesize'] = 'Place size'; $string['placesize_help'] = 'This size will be used for the places.'; $string['pluginadministration'] = 'Learning map administration'; @@ -103,6 +105,8 @@ $string['strokecolor_help'] = 'This color will be used for the stroke of the places, for the paths and the text.'; $string['svgcode'] = 'SVG code'; $string['targetplace'] = 'Target place'; +$string['textcolor'] = 'Text color'; +$string['textcolor_help'] = 'This color will be used for the activity names.'; $string['usecasehelp'] = 'How to use learning maps'; $string['usecaselink'] = 'Link to a page explaining the use of the learning map'; $string['usecheckmark'] = 'Checkmark for visited places'; @@ -110,3 +114,5 @@ $string['visited'] = 'Visited'; $string['visitedcolor'] = 'Visited place color'; $string['visitedcolor_help'] = 'This color will be used for the places (if it is visited).'; +$string['visitedemoji'] = 'Visited place emoji'; +$string['visitedemoji_help'] = 'This emoji will be used for visited places.'; diff --git a/lib.php b/lib.php index 1b64b7f..576ce70 100644 --- a/lib.php +++ b/lib.php @@ -45,6 +45,9 @@ 'placecolor' => 'color', 'visitedcolor' => 'color', 'strokecolor' => 'color', + 'textcolor' => 'color', + 'placeemoji' => 'emoji', + 'visitedemoji' => 'emoji', 'placesize' => 'range', 'showtext' => 'checkbox', 'hidestroke' => 'checkbox', @@ -53,6 +56,15 @@ 'hover' => 'checkbox', ]); +/** + * Array with all place types. + */ +define('LEARNINGMAP_PLACETYPES', [ + 'circle', + 'square', + 'emoji', +]); + /** * Adds a new learningmap instance * diff --git a/mod_form.php b/mod_form.php index a14aad2..8abe6ba 100644 --- a/mod_form.php +++ b/mod_form.php @@ -284,6 +284,8 @@ public function data_preprocessing(&$defaultvalues): void { ); $mapworker->process_map_objects(); $mapworker->replace_stylesheet(); + $mapworker->replace_defs(); + $mapworker->fix_svg(); $defaultvalues['svgcode'] = $mapworker->get_svgcode(); $draftitemid = file_get_submitted_draft_itemid('backgroundfile'); diff --git a/templates/cssskeleton.mustache b/templates/cssskeleton.mustache index 7c1da9c..e09edc3 100644 --- a/templates/cssskeleton.mustache +++ b/templates/cssskeleton.mustache @@ -52,6 +52,11 @@ }}