From 2a845a961a3348db3aab06cb0e79ed501404bbbf Mon Sep 17 00:00:00 2001 From: PMKuipers Date: Mon, 17 Jul 2023 23:04:21 +0200 Subject: [PATCH] implemented Simpleline in studyplan editor --- amd/src/simpleline.js | 27 ++++++- amd/src/studyplan-editor-components.js | 102 +++++++------------------ css/devstyles.css | 1 + version.php | 2 +- 4 files changed, 53 insertions(+), 79 deletions(-) diff --git a/amd/src/simpleline.js b/amd/src/simpleline.js index 6836062..ef8aa3c 100644 --- a/amd/src/simpleline.js +++ b/amd/src/simpleline.js @@ -124,10 +124,28 @@ export class SimpleLine { this.resizeObserver.observe(this.start); this.resizeObserver.observe(this.end); + // Setup the mutationobserver so we can remove the line if it's start or end is removed. + this.mutationObserver = new MutationObserver(function(mutations_list) { + mutations_list.forEach(function(mutation) { + mutation.removedNodes.forEach(function(removed_node) { + if(removed_node == this.start || removed_node == this.end) { + console.warning("Element removed",removed_node); + this.remove(); + } + }); + }); + }); + + this.mutationObserver.observe(this.start.parentElement, { subtree: false, childList: true }); + this.mutationObserver.observe(this.end.parentElement, { subtree: false, childList: true }); + + + // Setup the position checker this.positionCheck(); // Initialize refresh if(this.specs.autorefresh > 0){ this.refreshTimer = setInterval(()=>{this.positionCheck();},this.specs.autorefresh); } + this.active = true; this.update(); // fist draw } @@ -213,7 +231,7 @@ export class SimpleLine { // Validate or determine container let container = this.start.offsetParent; if(!container) { - if(document.getComputedStyle(this.start).position == "fixed"){ + if(getComputedStyle(this.start).position == "fixed"){ container = document.querySelector("body"); } else { console.error("Start element has no offsetParent. likely "); @@ -276,6 +294,8 @@ export class SimpleLine { update(){ + if(!this.active){ return;} // don't do this if we are no longer active + const container = this.getContainer(); if (!container) { return; } // Do not create any svg if container is empty @@ -401,7 +421,8 @@ export class SimpleLine { // clear the refresh timer clearInterval(this.refreshTimer); // stop the observers - this.resizeObserver.unobserve(this.start); - this.resizeObserver.unobserve(this.end); + this.resizeObserver.disconnect(); + this.mutationObserver.disconnect(); + this.active = false; } } diff --git a/amd/src/studyplan-editor-components.js b/amd/src/studyplan-editor-components.js index b1e6c14..172b408 100644 --- a/amd/src/studyplan-editor-components.js +++ b/amd/src/studyplan-editor-components.js @@ -6,7 +6,7 @@ /*eslint-env es6*/ // Put this file in path/to/plugin/amd/src -import LeaderLine from './leaderline'; +import {SimpleLine} from "./simpleline"; import {call} from 'core/ajax'; import notification from 'core/notification'; import {debounce} from './debounce'; @@ -43,7 +43,6 @@ export default { // Create new eventbus for interaction between item components const ItemEventBus = new Vue(); - const LineGravity = 70; let string_keys = load_stringkeys({ conditions: [ @@ -1895,13 +1894,8 @@ export default { dragelement.style.position = 'fixed'; dragelement.style.left = event.position.x+'px'; dragelement.style.top = event.position.y+'px'; - this.dragLine = new LeaderLine(start,dragelement,{ - color: '#777', - positionByWindowResize: false, - startSocket: 'right', - endSocket: 'left', - startSocketGravity: LineGravity, - endSocketGravity: LineGravity, + this.dragLine = new SimpleLine(start,dragelement,{ + color: "#777" }); // Add separate event listener to reposition mouse move document.addEventListener("mousemove",this.onMouseMove); @@ -1921,12 +1915,12 @@ export default { dragelement.style.position = 'fixed'; dragelement.style.left = event.clientX+'px'; dragelement.style.top = event.clientY+'px'; - this.dragLine.position(); - },5), + // line will follow automatically + },20), onDrop(event){ let from_id = event.data.id; let to_id = this.value.id; - + this.redrawLines(); call([{ methodname: 'local_treestudyplan_connect_studyitems', args: { 'from_id': from_id, 'to_id': to_id } @@ -1938,49 +1932,21 @@ export default { }).fail(notification.exception); }, redrawLine(conn){ - let lineColor = "#383"; + const lineColor = "var(--success)"; + const start = document.getElementById(`studyitem-${conn.from_id}`); + const end = document.getElementById(`studyitem-${conn.to_id}`); - // prepare lineinfo link or delete old line - let lineinfo = this.lines[conn.to_id]; - if(lineinfo){ - if(lineinfo.line){ - if(lineinfo.lineElm ){ - lineinfo.lineElm.parentNode.removeChild(lineinfo.lineElm); - lineinfo.lineElm = undefined; - } else { - lineinfo.line.remove(); - } - lineinfo.line = undefined; - } - } else { - lineinfo = {}; - this.lines[conn.to_id] = lineinfo; - } - // draw new line - let start = document.getElementById('studyitem-'+conn.from_id); - let end= document.getElementById('studyitem-'+conn.to_id); - LeaderLine.positionByWindowResize = false; + // delete old line + if(this.lines[conn.to_id]){ + this.lines[conn.to_id].remove(); + delete this.lines[conn.to_id]; + } + // create a new line if the start and finish items are visible if(start !== null && end !== null && isVisible(start) && isVisible(end)){ - lineinfo.line = new LeaderLine(start,end,{ - color: lineColor, - startSocket: 'right', - endSocket: 'left', - startSocketGravity: LineGravity, - endSocketGravity: LineGravity, - }); - - let elmWrapper = (this.plan.id >=0)?document.getElementById('studyplan-linewrapper-'+this.plan.id):null; - if(elmWrapper !== null){ - let elmLine = document.querySelector('body > .leader-line:last-child'); - elmWrapper.appendChild(elmLine); - lineinfo.lineElm = elmLine; // store line element so it can more easily be removed from the dom - } - setTimeout(function(){ - if(lineinfo.line !== undefined){ - lineinfo.line.position(); - } - },1); + this.lines[conn.to_id] = new SimpleLine( start,end,{color: lineColor,} + ); } + }, deleteLine(conn){ const self = this; @@ -2000,15 +1966,13 @@ export default { }).fail(notification.exception); }, highlight(conn){ - let lineinfo = this.lines[conn.to_id]; - if(lineinfo && lineinfo.line){ - lineinfo.line.setOptions({color:"#f33",}); + if(this.lines[conn.to_id]){ + this.lines[conn.to_id].setConfig({color:"var(--danger)",}); } }, normalize(conn){ - let lineinfo = this.lines[conn.to_id]; - if(lineinfo && lineinfo.line){ - lineinfo.line.setOptions({color:"#383",}); + if(this.lines[conn.to_id]){ + this.lines[conn.to_id].setConfig({color:"var(--success)",}); } }, updateItem() { @@ -2056,9 +2020,7 @@ export default { onRePositioned(){ for(let i in this.value.connections.out){ let conn = this.value.connections.out[i]; - //if(conn.to_id == re_id){ - this.redrawLine(conn); - //} + this.redrawLine(conn); } }, // When an item is disPositioned - (temporarily) removed from the list, @@ -2068,9 +2030,7 @@ export default { let conn = this.value.connections.out[i]; if(conn.to_id == re_id){ this.removeLine(conn); - } else { - this.redrawLine(conn); - } + } } }, @@ -2098,17 +2058,9 @@ export default { }, removeLine(conn){ - let lineinfo = this.lines[conn.to_id]; - if(lineinfo){ - if(lineinfo.line){ - if(lineinfo.lineElm ){ - lineinfo.lineElm.parentNode.removeChild(lineinfo.lineElm); - lineinfo.lineElm = undefined; - } else { - lineinfo.line.remove(); - } - lineinfo.line = undefined; - } + if(this.lines[conn.to_id]){ + this.lines[conn.to_id].remove(); + delete this.lines[conn.to_id]; } }, diff --git a/css/devstyles.css b/css/devstyles.css index 95de660..5747e0c 100644 --- a/css/devstyles.css +++ b/css/devstyles.css @@ -23,6 +23,7 @@ .t-studyplan-timeline { display: grid; + position: relative; /* make sure this grid is the offset for all arrows that are drawn by SimpleLine */ /* grid-template-columns will be set in the style attribute */ /* Use the variables below to specify width for filter spots and course spots */ --studyplan-filter-width: auto; /* better leave this at auto for now*/ diff --git a/version.php b/version.php index dbb9800..4652d55 100644 --- a/version.php +++ b/version.php @@ -1,6 +1,6 @@ component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494) -$plugin->version = 2023071400; // YYYYMMDDHH (year, month, day, iteration) +$plugin->version = 2023071700; // YYYYMMDDHH (year, month, day, iteration) $plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11) $plugin->dependencies = [