Improved NavBar, added LNVue().Start(), etc.

master
Harald Wolff 2019-10-16 22:00:03 +02:00
parent 51df83f9e7
commit bcce34d170
4 changed files with 254 additions and 100 deletions

View File

@ -58,7 +58,13 @@ div.ln-tooltip {
border-radius: 0px 6px 6px 6px; border-radius: 0px 6px 6px 6px;
border: 1px solid black; border: 1px solid black;
transition: opacity 500ms; opacity: 0.0;
transition: opacity 300ms linear;
pointer-events: none;
}
div.ln-tooltip[VISIBLE] {
opacity: 1.0;
} }
body { body {
@ -143,10 +149,14 @@ div.ln-select::after {
border-top: 1px solid black; border-top: 1px solid black;
border-bottom: 1px solid black; border-bottom: 1px solid black;
padding-top: 4px;
padding-bottom: 4px;
margin-bottom: 2em; margin-bottom: 2em;
} }
.ln-navitem { .ln-navitem {
position: relative;
display: inline-block; display: inline-block;
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
@ -160,8 +170,41 @@ div.ln-select::after {
.ln-navitem > a { .ln-navitem > a {
font-style: normal; font-style: normal;
text-decoration: none; text-decoration: none;
color: black;
} }
div.ln-navitem > div.ln-nav-children {
position: absolute;
white-space: pre;
left: 0px;
top: 100%;
opacity: 0.0;
transition: opacity 200ms;
border: 1px solid black;
border-top: none;
background-color: white;
padding: 8px;
}
div.ln-navitem:hover > div.ln-nav-children {
opacity: 1.0;
transition: opacity 200ms;
}
div.ln-nav-children > .ln-navitem {
display: block;
margin-top: 4px;
padding-top: 4px;
border-top: 1px solid #C0C0C0;
}
div.ln-nav-children > .ln-navitem:first-of-type {
margin-top: 0px;
border-top: none;
}
div.ln-upload { div.ln-upload {
display: inline-block; display: inline-block;

View File

@ -8,7 +8,7 @@
<script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript" src="js/vue-router.js"></script> <script type="text/javascript" src="js/vue-router.js"></script>
<script type="text/javascript" src="js/ln.vue.application.js"></script> <script type="text/javascript" src="js/ln.vue.js"></script>
<script type="text/javascript" src="js/ln.vue.components.js"></script> <script type="text/javascript" src="js/ln.vue.components.js"></script>
<script type="text/javascript" src="js/ln.vue.table.js"></script> <script type="text/javascript" src="js/ln.vue.table.js"></script>
@ -23,22 +23,55 @@
<div id="frame"> <div id="frame">
<h1>ln.vue Demo Application</h1> <h1>ln.vue Demo Application</h1>
<ln-navbar <div v-if="false">
:navitems="[ <h2>Please wait for application to be loaded...</h2>
{ href: '/', label: 'HOME' }, </div>
{ href: '/controls', label: 'Simple Form Controls' },
{ href: '/table', label: 'Table View Control' }, <ln-navbar></ln-navbar>
{ href: '/state', label: 'Current State' },
]"></ln-navbar>
<router-view></router-view> <router-view></router-view>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
LNVue.addRouteTemplate( let core = {
"/", navigation: {
`<div>This is the ln.vue demo application. Feel free to test all the features, you can find.<br>Here should be a message:<br><i>{{ message.value }}</i></div>` core: {
); label: "HOME",
LNVue.addRouteTemplate( path: '/',
},
},
routes: {
'/': {
template: `<div>This is the ln.vue demo application. Feel free to test all the features, you can find.<br>Here should be a message:<br><i>{{ message.value }}</i></div>`,
},
}
};
let controls = {
navigation: {
controls: {
label: "Controls",
navigation: {
simple: {
label: "Simple Form Controls",
path: '/controls',
},
table: {
label: "Table Contol",
path: '/table',
}
},
},
},
routes: {
'/controls': {
url: '/controls.html',
},
'/table': {
url: '/table.html',
},
}
};
/* LNVue.addRouteTemplate(
"/state", "/state",
`<div>Current User Input object:<br><br> `<div>Current User Input object:<br><br>
<span class="json">{{ JSON.stringify(controls,null,4) }}</span> <span class="json">{{ JSON.stringify(controls,null,4) }}</span>
@ -47,7 +80,7 @@
LNVue.addRoute("/controls","/controls.html"); LNVue.addRoute("/controls","/controls.html");
LNVue.addRoute("/table","/table.html"); LNVue.addRoute("/table","/table.html");
*/
let message = { value: "" }; let message = { value: "" };
app = new LNVue("#frame",{ app = new LNVue("#frame",{
@ -127,6 +160,25 @@
} }
}); });
app.addModule(core);
app.addModule(controls);
app.addModule({
navigation: {
state: {
label: "State",
path: '/state',
},
},
routes: {
'/state': `<div>Current User Input object:<br><br>
<span class="json">{{ JSON.stringify(controls,null,4) }}</span>
</div>`,
}
});
app.Start();
LNVue.onidle(()=>{ LNVue.onidle(()=>{
message.value = "idle time reached. Message written."; message.value = "idle time reached. Message written.";
setTimeout(()=>{ setTimeout(()=>{

View File

@ -18,24 +18,19 @@ function findTooltipData(el){
} }
function tooltipShow(ev,tooltip){ function tooltipShow(ev,tooltip){
if (!tooltipEl.parentElement) if (tooltipEl.parentElement)
{ document.body.appendChild(tooltipEl);
tooltipEl.style.visibility = "hidden";
tooltipEl.style.opacity = 0.0;
tooltipEl.style.visibility = "visible";
}
document.body.appendChild(tooltipEl);
tooltipEl.innerText = tooltip.value; tooltipEl.innerText = tooltip.value;
tooltipEl.style.opacity = 1.0; tooltipEl.setAttribute("VISIBLE","");
tootlipVisible = true; tootlipVisible = true;
} }
function tooltipHide(ev,tooltip){ function tooltipHide(ev,tooltip){
tooltipEl.style.opacity = 0.0; tooltipEl.removeAttribute("VISIBLE");
setTimeout(()=>{ setTimeout(()=>{
document.body.removeChild(tooltipEl); //document.body.removeChild(tooltipEl);
}, 600); }, 600);
tootlipVisible = false; tootlipVisible = false;
@ -52,7 +47,7 @@ function tooltipMouseOver(ev){
else else
tooltip.timeout = setTimeout(() => { tooltip.timeout = setTimeout(() => {
tooltipShow(ev,tooltip); tooltipShow(ev,tooltip);
}, 800); }, tooltip.delay || 800);
if (tooltipEl){ if (tooltipEl){
tooltipEl.style.left = `${ev.x+3}px`; tooltipEl.style.left = `${ev.x+3}px`;
@ -72,7 +67,7 @@ Vue.directive('tooltip',{
let tooltip = { let tooltip = {
value: binding.value, value: binding.value,
timeout: null, timeout: null,
delay: null,
}; };
let tooltipKey = nextTooltipKey++; let tooltipKey = nextTooltipKey++;
tooltipData[tooltipKey] = tooltip; tooltipData[tooltipKey] = tooltip;
@ -81,15 +76,10 @@ Vue.directive('tooltip',{
el.addEventListener('mousemove',tooltipMouseOver); el.addEventListener('mousemove',tooltipMouseOver);
el.addEventListener('mouseout',tooltipMouseOut); el.addEventListener('mouseout',tooltipMouseOut);
},
inserted: function(el, binding, vnode){
}, },
update: function(el, binding, vnode, oldVnode){ update: function(el, binding, vnode, oldVnode){
let tooltip = findTooltipData(el);
}, tooltip.value = binding.value;
componentUpdated: function(el, binding, vnode, oldVnode){
}, },
unbind: function(el, binding, vnode){ unbind: function(el, binding, vnode){
el.removeEventListener('mouseover',tooltipMouseOver); el.removeEventListener('mouseover',tooltipMouseOver);
@ -99,40 +89,66 @@ Vue.directive('tooltip',{
Vue.component('ln-navitem',{ Vue.component('ln-navitem',{
props: { props: {
href: { value: {
type: String, type: Object,
required: true, required: true,
}, },
key: String,
}, },
template: ` template: `
<router-link <div
:to="href" class="ln-navitem"
class="ln-navitem"unbind :id="'nav-' + key"
v-slot="{ href, route, navigate, isActive, isExactActive }"
> >
<div class="ln-navitem"> <router-link
<a :href="href" @click="navigate"> class="ln-navitem"
<slot></slot> v-if="value.path"
</a> :to="value.path"
<slot name="children"></slot> v-slot="{ href, route, navigate, isActive, isExactActive }"
>
<a
:href="href"
@click="navigate"
>{{ value.label || value.path }}</a>
</router-link>
<span
v-if="!value.path"
class="ln-navitem"
>{{ value.label }}</span>
<div class="ln-nav-children"
v-if="value.navigation"
>
<ln-navitem
v-for="(item,key) in value.navigation"
v-bind:value="item"
v-bind:key="key"
></ln-navitem>
</div> </div>
</router-link> </div>
`, `,
}); });
Vue.component('ln-navbar',{ Vue.component('ln-navbar',{
props: { props: {
navitems: { value: {
type: Object, type: Object,
required: true, default: function(){
} return LNVue.$_.navigation;
}
},
component: {
type: [ Object, String ],
default: 'ln-navitem',
},
}, },
template: ` template: `
<div class="ln-navbar"> <div class="ln-navbar">
<ln-navitem <div
v-for="navitem in navitems" :is="component"
v-bind:href="navitem.href" v-for="(item,key) in value"
>{{ navitem.label || navitem.href }}</ln-navitem> v-bind:value="item"
v-bind:key="key"
>{{ item.label || item.path }}</div>
</div>` </div>`
}); });

View File

@ -8,45 +8,93 @@
routes: [], routes: [],
data: {}, data: {},
}, options ); }, options );
this._el = el;
this.data = Object.assign({}, options.data, { LNVue: this, msg: "Hello World" }); this.data = Object.assign({}, options.data, { LNVue: this, msg: "Hello World" });
this.promises = [];
Vue.prototype.$LNVue = this; Vue.prototype.$LNVue = this;
LNVue.$_ = this;
console.log("LNVue: preparing"); console.log("LNVue: preparing");
this.navigation = {};
Promise Promise
.all(LNVue.promises) .all(LNVue.promises)
.then(()=>{ .then(()=>{
console.log("LNVue: starting"); console.log("LNVue: starting");
let routes = LNVue.routes LNVue.vueRouter.addRoutes([{
.concat(this.options.routes)
.concat([{
path: "*", path: "*",
component: { component: {
template: `<h2>404 Not Found</h2>The URL you tried to reach is not existing.`, template: `<h2>404 Not Found</h2>The URL you tried to reach is not existing.`,
}, },
}]); }]);
let router = new VueRouter({
routes,
});
let vue = new Vue({ });
el,
data: this.data,
router: router,
});
this.vue = function(){ return vue; }
this.vue = null;
}
Start(){
Promise
.all(this.promises)
.then(()=>{
LNVue.onidle(()=>{
this.vue = new Vue({
el: this._el,
data: this.data,
router: LNVue.vueRouter,
});
});
}); });
} }
Version(){ return "0.1alpha"; }; Version(){ return "0.1alpha"; };
addModule(modSpec){
if (modSpec.navigation instanceof Object){
LNVue.deepAssign(modSpec.navigation,this.navigation);
}
LNVue.$each(modSpec.routes,(key,route)=>{
if ((route instanceof Object) && route.url)
{
let p = new Promise((resolve,reject)=>{
LNVue
.fetch(route.url)
.then((src)=>{
this.addRoute(key,{ template: src, data: ()=>{ return this.data; }, });
resolve();
});
});
this.promises.push(p);
} else if (route instanceof Object){
this.addRoute(key,{ template: route.template, data: ()=>{ return this.data; }, } );
} else {
this.addRoute(key,{ template: route, data: ()=>{ return this.data; }, } );
}
});
}
addRoute(path,component){
let self = this;
LNVue.vueRouter.addRoutes([
{ path, component, },
]);
}
} }
Object.defineProperty( LNVue, '$LNVue', {
get: ()=>{ return LNVue.$_; },
});
LNVue.vueRouter = new VueRouter({
routes: [],
});
LNVue.$idles = []; LNVue.$idles = [];
LNVue.onidle = function(cb,thisval = null){ LNVue.onidle = function(cb,thisval = null){
let scheduled = LNVue.$idles.length > 0; let scheduled = LNVue.$idles.length > 0;
@ -69,6 +117,34 @@
},0); },0);
} }
LNVue.$each = function(oa,cb){
if (oa instanceof Array){
let result = [];
oa.forEach((value,index)=>{
result.push(cb.call(value,index,value));
});
return result;
} else if (oa instanceof Object){
let result = {};
Object.keys(oa).forEach((key)=>{
if (oa.hasOwnProperty(key)){
result[key] = cb.call(oa[key],key,oa[key]);
}
});
return result;
}
}
LNVue.deepAssign = function(source,target){
LNVue.$each(source,function(key){
if (target[key] instanceof Object){
LNVue.deepAssign(src[key],target[key]);
} else {
target[key] = source[key];
}
});
}
LNVue.$ = function(src){ LNVue.$ = function(src){
let el = document.createElement("parse"); let el = document.createElement("parse");
el.innerHTML = src; el.innerHTML = src;
@ -106,38 +182,5 @@
}); });
}; };
LNVue.addRouteTemplate = function(path,template){
LNVue.routes.push({
path,
component: {
data: function(){
return this.$LNVue.data;
},
template,
}
});
}
LNVue.addRoute = function(path,url){
let p = new Promise((resolve,reject) => {
LNVue
.fetch(url)
.then((src)=>{
LNVue.routes.push({
path,
component: {
data: function(){
return this.$LNVue.data;
},
template: src,
},
});
resolve();
});
});
LNVue.promises.push(p);
return p;
}
return LNVue; return LNVue;
})(); })();