Fixed appear disappear of sidebar not going properly

This commit is contained in:
PMKuipers 2024-08-15 09:47:40 +02:00
parent fd9d50873e
commit 743cb82cc9
9 changed files with 154 additions and 88 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
define("local_treestudyplan/util/psidebar-vue",["exports","./debugger"],(function(_exports,_debugger){var obj;Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;let debug=new(_debugger=(obj=_debugger)&&obj.__esModule?obj:{default:obj}).default("p-sidebar");var _default={install(Vue){Vue.component("p-sidebar",{props:{value:{type:Boolean,default:!0},right:{type:Boolean,default:!1},shadow:{type:Boolean,default:!1},target:{type:String,default:"body"},offsetRef:{type:String,default:""}},data:()=>({wrapper:null,contentwrapper:null,resizeobserver:null}),computed:{},methods:{initWrappers(target){let initializeWrapperContent=!1;if(this.wrapper=document.querySelector("#p-sidebar-wrapper"),this.wrapper||(initializeWrapperContent=!0,this.wrapper=document.createElement("div"),this.wrapper.setAttribute("id","p-sidebar-wrapper")),this.contentwrapper=document.querySelector("#p-sidebar-contentwrapper"),this.contentwrapper||(initializeWrapperContent=!0,this.contentwrapper=document.createElement("div"),this.contentwrapper.setAttribute("id","p-sidebar-contentwrapper"),this.wrapper.appendChild(this.contentwrapper)),initializeWrapperContent){let targetEl=document.querySelector(target);for(console.info(`Targeting '${target}' to `,targetEl),targetEl&&"HTML"!=targetEl.nodeType||(targetEl=document.querySelector("body")),debug.warn("Initializing wrappers with content of target ",targetEl);targetEl.childNodes.length>0;)this.contentwrapper.appendChild(targetEl.childNodes[0]);targetEl.appendChild(this.wrapper)}},rePosition(right){const el=this.$refs.container;right?this.wrapper.insertBefore(el,this.contentwrapper.nextSibling):this.wrapper.insertBefore(el,this.contentwrapper)},setOffset(reference){const ref=reference?document.querySelector(reference):null;console.info(`Setting offset from '${reference}'`,ref);let offsetTop=ref?ref.offsetTop:0;offsetTop+=0!=offsetTop?"px":"";const el=this.$refs.container;el.style.height=`calc( 100vh - ${offsetTop})`,el.style.marginTop=offsetTop}},watch:{right(newVal){this.rePosition(newVal)},offsetRef(reference){this.setOffset(reference)}},mounted(){const el=this.$refs.container;this.initWrappers(this.target),this.setOffset(this.offsetRef),this.rePosition(this.right,this.besides),this.resizeObserver=new ResizeObserver((()=>{let wx=0-el.getBoundingClientRect().width;wx+=0!=wx?"px":"",el.style.setProperty("--p-sidebar-hideoffset",wx)})),this.resizeObserver.observe(el)},unmounted(){this.resizeObserver&&this.resizeObserver.disconnect()},template:"\n <div>\n <div ref='container' \n :class=\"'p-sidebar ' + (right?'p-sidebar-right ':'') + (shadow?'p-sidebar-shadow ':'') + (value?'shown ':'hidden ')\"\n ><slot></slot></div>\n </div>\n "})}};return _exports.default=_default,_exports.default}));
define("local_treestudyplan/util/psidebar-vue",["exports","../portal-vue/portal-vue.esm","./debugger"],(function(_exports,_portalVue,_debugger){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_portalVue=_interopRequireDefault(_portalVue);let wrapper,contentwrapper,resizeObserver,debug=new((_debugger=_interopRequireDefault(_debugger)).default)("p-sidebar");function rePosition(right){let el=document.querySelector("#p-sidebar-mount");el||(el=document.createElement("div"),el.setAttribute("id","p-sidebar-mount"),resizeObserver=new ResizeObserver((()=>{let wx=0-el.getBoundingClientRect().width;wx+=0!=wx?"px":"",el.style.setProperty("--p-sidebar-hideoffset",wx)})),resizeObserver.observe(el)),right?wrapper.insertBefore(el,contentwrapper.nextSibling):wrapper.insertBefore(el,contentwrapper)}function setOffset(reference){const ref=reference?document.querySelector(reference):null;if(ref){let offsetTop=ref?ref.offsetTop:0;offsetTop+=0!=offsetTop?"px":"";const el=document.querySelector("#p-sidebar-mount");el.style.height=`calc( 100vh - ${offsetTop})`,el.style.marginTop=offsetTop}}var _default={install(Vue){Vue.use(_portalVue.default),window.addEventListener("load",(()=>{!function(target,offsetref){let initializeWrapperContent=!1;if(wrapper=document.querySelector("#p-sidebar-wrapper"),wrapper||(initializeWrapperContent=!0,wrapper=document.createElement("div"),wrapper.setAttribute("id","p-sidebar-wrapper")),contentwrapper=document.querySelector("#p-sidebar-contentwrapper"),contentwrapper||(initializeWrapperContent=!0,contentwrapper=document.createElement("div"),contentwrapper.setAttribute("id","p-sidebar-contentwrapper"),wrapper.appendChild(contentwrapper)),initializeWrapperContent){let targetEl=document.querySelector(target);for(console.info(`Targeting '${target}' to `,targetEl),targetEl&&"HTML"!=targetEl.nodeType||(targetEl=document.querySelector("body"));targetEl.childNodes.length>0;)contentwrapper.appendChild(targetEl.childNodes[0]);targetEl.appendChild(wrapper)}rePosition(!1),setOffset(offsetref)}()})),Vue.component("p-sidebar",{props:{value:{type:Boolean,default:!0},right:{type:Boolean,default:!1},shadow:{type:Boolean,default:!1},target:{type:String,default:"body"},offsetRef:{type:String,default:""}},data:()=>({wrapper:null,contentwrapper:null,resizeobserver:null}),computed:{},methods:{},watch:{right(newVal){rePosition(newVal)},offsetRef(reference){setOffset(reference,this.$refs.portal)}},mounted(){debug.info("OffsetRef",this.offsetRef),setOffset(this.offsetRef),debug.info("Right",this.right),rePosition(this.right)},unmounted(){},template:"\n <div><mounting-portal ref='portal'\n mount-to=\"#p-sidebar-mount\"\n append\n ><div ref='container'\n :class=\"'p-sidebar ' + (right?'p-sidebar-right ':'') + (shadow?'p-sidebar-shadow ':'') + ((!value)?'hidden ':'')\"\n ><slot></slot></div></mounting-portal>\n </div>\n "})}};return _exports.default=_default,_exports.default}));
//# sourceMappingURL=psidebar-vue.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -4518,12 +4518,14 @@ export default {
initialize() {
const self = this;
self.loadingcourses = true;
debug.info("Toolbox Loading courses and categories");
call([{
methodname: 'local_treestudyplan_map_categories',
args: {
'studyplan_id': self.studyplanid,
}
}])[0].then((response) => {
debug.info("Toolbox got courses and categories",response);
self.courses = response;
self.loadingcourses = false;
return;
@ -4581,7 +4583,7 @@ export default {
v-model="value"
offsetRef="#page"
>
<div class="m-3 border-bottom-1 border-primary"><h3>{{text.toolbox}}</h3></div>
<div class="pt-3 pl-3 pr-3 border-bottom-1 border-primary"><h3>{{text.toolbox}}</h3></div>
<div class='t-toolbox-preface'>
<b-form-checkbox v-model="toolboxright" switch>{{text.toolbarRight}}</b-form-checkbox>
</div>

View File

@ -3,12 +3,117 @@
/* eslint-disable no-trailing-spaces */
/* eslint-disable no-console */
/* eslint-env es6*/
import PortalVue from '../portal-vue/portal-vue.esm';
import Debugger from './debugger';
let debug = new Debugger("p-sidebar");
let wrapper;
let contentwrapper;
let resizeObserver;
/**
* Create a new wrapper Around the
* @param {String} target Query string to select root element next to which the sidebar will be placed.
* Defaults to body
* @param {String} offsetref Query string to select element that should appear above the sidebar.
* Defaults to none
*/
function createPortalTarget(target,offsetref) {
let initializeWrapperContent = false;
// First check if the sidebar wrapper already exists.
// Creating the wrappers over and over again is a recipe for disaster.
wrapper = document.querySelector("#p-sidebar-wrapper");
if (!wrapper) {
initializeWrapperContent = true;
// Otherwise, create it.
wrapper = document.createElement("div");
wrapper.setAttribute("id", "p-sidebar-wrapper");
}
// First check if the contentwrapper already exists
contentwrapper = document.querySelector("#p-sidebar-contentwrapper");
if (!contentwrapper) {
initializeWrapperContent = true;
// Otherwise, create it.
contentwrapper = document.createElement("div");
contentwrapper.setAttribute("id", "p-sidebar-contentwrapper");
wrapper.appendChild(contentwrapper);
}
if (initializeWrapperContent) {
// Find containing target (otherwise use body)
let targetEl = document.querySelector(target);
console.info(`Targeting '${target}' to `, targetEl);
if (!targetEl || targetEl.nodeType == "HTML") {
targetEl = document.querySelector("body");
}
// Move all target content parts to content wrapper....
while (targetEl.childNodes.length > 0) {
contentwrapper.appendChild(targetEl.childNodes[0]);
}
// Add sidebar wrapper to target Element
targetEl.appendChild(wrapper);
}
// The actual target is created in a reposition call
rePosition(false);
// The
setOffset(offsetref);
}
/**
* Position a (new) sidebar element on the left or right
* @param {Boolean} right Set to true to put the sidebar on the right
*/
function rePosition(right) {
// Place the portal target on the right place in the DOM.
// Find or create the portal target.
let el = document.querySelector(`#p-sidebar-mount`);
if (!el) {
el = document.createElement("div");
el.setAttribute("id", `p-sidebar-mount`);
// Initialize a resizeObser
resizeObserver = new ResizeObserver(() => {
let wx = 0 - el.getBoundingClientRect().width;
wx += (wx != 0) ? "px" : "";
el.style.setProperty("--p-sidebar-hideoffset", wx);
});
resizeObserver.observe(el);
}
if (right) {
wrapper.insertBefore(el, contentwrapper.nextSibling);
} else {
wrapper.insertBefore(el, contentwrapper);
}
}
/**
* Set the proper offset from the top on the sidebar related to the reference element
* @param {String} reference Reference target for setting view height
*/
function setOffset(reference) {
const ref = reference ? document.querySelector(reference) : null;
if (ref) {
let offsetTop = (ref ? ref.offsetTop : 0);
offsetTop += (offsetTop != 0) ? "px" : "";
const el = document.querySelector(`#p-sidebar-mount`);
el.style.height = `calc( 100vh - ${offsetTop})`;
el.style.marginTop = offsetTop;
}
}
export default {
install(Vue /* ,options */) {
Vue.use(PortalVue);
/* Create the portal target on initialization.
Defaults to body. Offset and final position set through sidebar parameter.
*/
window.addEventListener("load", () => {
createPortalTarget();
});
Vue.component('p-sidebar', {
props: {
value: {
@ -42,95 +147,32 @@ export default {
computed: {
},
methods: {
initWrappers(target) {
let initializeWrapperContent = false;
// First check if the sidebar wrapper already exists.
// Creating the wrappers over and over again is a recipe for disaster.
this.wrapper = document.querySelector("#p-sidebar-wrapper");
if (!this.wrapper) {
initializeWrapperContent = true;
// Otherwise, create it.
this.wrapper = document.createElement("div");
this.wrapper.setAttribute("id", "p-sidebar-wrapper");
}
// First check if the contentwrapper already exists
this.contentwrapper = document.querySelector("#p-sidebar-contentwrapper");
if (!this.contentwrapper) {
initializeWrapperContent = true;
// Otherwise, create it.
this.contentwrapper = document.createElement("div");
this.contentwrapper.setAttribute("id", "p-sidebar-contentwrapper");
this.wrapper.appendChild(this.contentwrapper);
}
if (initializeWrapperContent) {
// Find containing target (otherwise use body)
let targetEl = document.querySelector(target);
console.info(`Targeting '${target}' to `, targetEl);
if (!targetEl || targetEl.nodeType == "HTML") {
targetEl = document.querySelector("body");
}
debug.warn(`Initializing wrappers with content of target `, targetEl);
// Move all target content parts to content wrapper....
while (targetEl.childNodes.length > 0) {
this.contentwrapper.appendChild(targetEl.childNodes[0]);
}
// Add sidebar wrapper to target Element
targetEl.appendChild(this.wrapper);
}
},
rePosition(right) {
// Place the container elsewhere in the DOM.
const el = this.$refs.container;
if (right) {
this.wrapper.insertBefore(el, this.contentwrapper.nextSibling);
} else {
this.wrapper.insertBefore(el, this.contentwrapper);
}
},
setOffset(reference) {
const ref = reference ? document.querySelector(reference) : null;
console.info(`Setting offset from '${reference}'`, ref);
let offsetTop = (ref ? ref.offsetTop : 0);
offsetTop += (offsetTop != 0) ? "px" : "";
const el = this.$refs.container;
el.style.height = `calc( 100vh - ${offsetTop})`;
el.style.marginTop = offsetTop;
}
},
watch: {
right(newVal) {
this.rePosition(newVal);
rePosition(newVal);
},
offsetRef(reference) {
this.setOffset(reference);
setOffset(reference,this.$refs.portal);
}
},
mounted() {
const self = this;
const el = self.$refs.container;
this.initWrappers(this.target);
this.setOffset(this.offsetRef);
this.rePosition(this.right, this.besides);
this.resizeObserver = new ResizeObserver(() => {
let wx = 0 - el.getBoundingClientRect().width;
wx += (wx != 0) ? "px" : "";
el.style.setProperty("--p-sidebar-hideoffset", wx);
});
this.resizeObserver.observe(el);
debug.info("OffsetRef",this.offsetRef);
setOffset(this.offsetRef);
debug.info("Right",this.right);
rePosition(this.right);
},
unmounted() {
if (this.resizeObserver) {
this.resizeObserver.disconnect();
}
},
template: `
<div>
<div ref='container'
:class="'p-sidebar ' + (right?'p-sidebar-right ':'') + (shadow?'p-sidebar-shadow ':'') + (value?'shown ':'hidden ')"
><slot></slot></div>
<div><mounting-portal ref='portal'
mount-to="#p-sidebar-mount"
append
><div ref='container'
:class="'p-sidebar ' + (right?'p-sidebar-right ':'') + (shadow?'p-sidebar-shadow ':'') + ((!value)?'hidden ':'')"
><slot></slot></div></mounting-portal>
</div>
`,
});

View File

@ -2042,20 +2042,24 @@ body.path-local-treestudyplan .editmode-switch-form > * {
transition: all 0.3s ease-in-out;
overflow-y: auto;
}
#p-sidebar-wrapper .vue-portal-target {
height: 100%;
}
#p-sidebar-wrapper .p-sidebar {
position: relative;
top: 0;
min-width: 320px;
width: auto;
max-width: 430px;
height: 100vh;
height: 100%;
max-height: 100%;
margin: 0;
outline: 0;
-webkit-transform: translateX(0);
transform: translateX(0);
background-color: var(--light);
display: block;
display: flex;
flex-direction: column;
transition: all 0.3s ease-in-out;
z-index: 100;
--p-sidebar-hideoffset: -320px;
@ -2071,4 +2075,7 @@ body.path-local-treestudyplan .editmode-switch-form > * {
}
#p-sidebar-wrapper .p-sidebar.p-sidebar-right.hidden {
margin-right: var(--p-sidebar-hideoffset);
}
#p-sidebar-wrapper .p-sidebar .t-toolbox-tabs {
flex: 1; /* Make sure it grows to fill the space */
}

View File

@ -10,20 +10,24 @@
overflow-y: auto;
}
.vue-portal-target {
height: 100%;
}
.p-sidebar {
position: relative;
top: 0;
min-width: 320px;
width: auto;
max-width: 430px;
height: 100vh;
height: 100%;
max-height: 100%;
margin: 0;
outline: 0;
-webkit-transform: translateX(0);
transform: translateX(0);
background-color: var(--light);
display: block;
display: flex;
flex-direction: column;
transition: all 0.3s ease-in-out;
z-index: 100;
--p-sidebar-hideoffset: -320px;
@ -41,6 +45,10 @@
&.p-sidebar-right.hidden {
margin-right: var(--p-sidebar-hideoffset);
}
.t-toolbox-tabs {
flex: 1; /* Make sure it grows to fill the space */
}
}
}

View File

@ -2042,20 +2042,24 @@ body.path-local-treestudyplan .editmode-switch-form > * {
transition: all 0.3s ease-in-out;
overflow-y: auto;
}
#p-sidebar-wrapper .vue-portal-target {
height: 100%;
}
#p-sidebar-wrapper .p-sidebar {
position: relative;
top: 0;
min-width: 320px;
width: auto;
max-width: 430px;
height: 100vh;
height: 100%;
max-height: 100%;
margin: 0;
outline: 0;
-webkit-transform: translateX(0);
transform: translateX(0);
background-color: var(--light);
display: block;
display: flex;
flex-direction: column;
transition: all 0.3s ease-in-out;
z-index: 100;
--p-sidebar-hideoffset: -320px;
@ -2071,4 +2075,7 @@ body.path-local-treestudyplan .editmode-switch-form > * {
}
#p-sidebar-wrapper .p-sidebar.p-sidebar-right.hidden {
margin-right: var(--p-sidebar-hideoffset);
}
#p-sidebar-wrapper .p-sidebar .t-toolbox-tabs {
flex: 1; /* Make sure it grows to fill the space */
}