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: 1px solid black;
transition: opacity 500ms;
opacity: 0.0;
transition: opacity 300ms linear;
pointer-events: none;
}
div.ln-tooltip[VISIBLE] {
opacity: 1.0;
}
body {
@ -143,10 +149,14 @@ div.ln-select::after {
border-top: 1px solid black;
border-bottom: 1px solid black;
padding-top: 4px;
padding-bottom: 4px;
margin-bottom: 2em;
}
.ln-navitem {
position: relative;
display: inline-block;
font-family: Arial, Helvetica, sans-serif;
@ -160,8 +170,41 @@ div.ln-select::after {
.ln-navitem > a {
font-style: normal;
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 {
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-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.table.js"></script>
@ -23,22 +23,55 @@
<div id="frame">
<h1>ln.vue Demo Application</h1>
<ln-navbar
:navitems="[
{ href: '/', label: 'HOME' },
{ href: '/controls', label: 'Simple Form Controls' },
{ href: '/table', label: 'Table View Control' },
{ href: '/state', label: 'Current State' },
]"></ln-navbar>
<div v-if="false">
<h2>Please wait for application to be loaded...</h2>
</div>
<ln-navbar></ln-navbar>
<router-view></router-view>
</div>
<script type="text/javascript">
LNVue.addRouteTemplate(
"/",
`<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>`
);
LNVue.addRouteTemplate(
let core = {
navigation: {
core: {
label: "HOME",
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",
`<div>Current User Input object:<br><br>
<span class="json">{{ JSON.stringify(controls,null,4) }}</span>
@ -47,7 +80,7 @@
LNVue.addRoute("/controls","/controls.html");
LNVue.addRoute("/table","/table.html");
*/
let message = { value: "" };
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(()=>{
message.value = "idle time reached. Message written.";
setTimeout(()=>{

View File

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

View File

@ -8,45 +8,93 @@
routes: [],
data: {},
}, options );
this._el = el;
this.data = Object.assign({}, options.data, { LNVue: this, msg: "Hello World" });
this.promises = [];
Vue.prototype.$LNVue = this;
LNVue.$_ = this;
console.log("LNVue: preparing");
this.navigation = {};
Promise
.all(LNVue.promises)
.then(()=>{
console.log("LNVue: starting");
let routes = LNVue.routes
.concat(this.options.routes)
.concat([{
LNVue.vueRouter.addRoutes([{
path: "*",
component: {
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"; };
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.onidle = function(cb,thisval = null){
let scheduled = LNVue.$idles.length > 0;
@ -69,6 +117,34 @@
},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){
let el = document.createElement("parse");
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;
})();