From fe447d3f511ead5ee9938da7d573b09256affaeb Mon Sep 17 00:00:00 2001 From: xgui3783 <xgui3783@gmail.com> Date: Wed, 1 Aug 2018 21:45:10 +1000 Subject: [PATCH] Pr bugfixes (#80) * fixes + updates on api * built in plugin dev * fixes #77 #79 --- .../atlasViewer.apiService.service.ts | 16 +- .../atlasViewer.constantService.service.ts | 11 +- .../atlasViewer.dataService.service.ts | 15 +- src/plugin_examples/newWebJugex/app.js | 2 + src/plugin_examples/newWebJugex/app.js.map | 1 + src/plugin_examples/newWebJugex/manifest.js | 2 + .../newWebJugex/manifest.js.map | 1 + src/plugin_examples/newWebJugex/manifest.json | 6 + src/plugin_examples/newWebJugex/script.js | 228 ++++++++++++++++ src/plugin_examples/newWebJugex/template.html | 248 ++++++++++++++++++ src/plugin_examples/newWebJugex/vendor.js | 2 + src/plugin_examples/newWebJugex/vendor.js.map | 1 + src/plugin_examples/plugin_api.md | 2 +- src/res/css/plugin_styles.css | 20 +- .../nehubaContainer.component.ts | 52 ++-- .../nehubaViewer/nehubaViewer.component.ts | 25 +- 16 files changed, 574 insertions(+), 58 deletions(-) create mode 100644 src/plugin_examples/newWebJugex/app.js create mode 100644 src/plugin_examples/newWebJugex/app.js.map create mode 100644 src/plugin_examples/newWebJugex/manifest.js create mode 100644 src/plugin_examples/newWebJugex/manifest.js.map create mode 100644 src/plugin_examples/newWebJugex/manifest.json create mode 100644 src/plugin_examples/newWebJugex/script.js create mode 100644 src/plugin_examples/newWebJugex/template.html create mode 100644 src/plugin_examples/newWebJugex/vendor.js create mode 100644 src/plugin_examples/newWebJugex/vendor.js.map diff --git a/src/atlasViewer/atlasViewer.apiService.service.ts b/src/atlasViewer/atlasViewer.apiService.service.ts index efa52221e..cdd6fb3c3 100644 --- a/src/atlasViewer/atlasViewer.apiService.service.ts +++ b/src/atlasViewer/atlasViewer.apiService.service.ts @@ -1,8 +1,8 @@ import { Injectable } from "@angular/core"; import { Store, select } from "@ngrx/store"; -import { ViewerStateInterface, safeFilter } from "../services/stateStore.service"; +import { ViewerStateInterface, safeFilter, getLabelIndexMap } from "../services/stateStore.service"; import { Observable } from "rxjs"; -import { map } from "rxjs/operators"; +import { map, distinctUntilChanged } from "rxjs/operators"; declare var window @@ -13,6 +13,7 @@ declare var window export class AtlasViewerAPIServices{ private loadedTemplates$ : Observable<any> + private selectParcellation$ : Observable<any> public interactiveViewer : InteractiveViewerInterface public loadedLibraries : Map<string,{counter:number,src:HTMLElement|null}> = new Map() @@ -27,6 +28,12 @@ export class AtlasViewerAPIServices{ map(state=>state.fetchedTemplates) ) + this.selectParcellation$ = this.store.pipe( + select('viewerState'), + safeFilter('parcellationSelected'), + map(state => state.parcellationSelected) + ) + this.interactiveViewer = { metadata : { selectedTemplateBSubject : this.store.pipe( @@ -42,7 +49,9 @@ export class AtlasViewerAPIServices{ selectedRegionsBSubject : this.store.pipe( select('viewerState'), safeFilter('regionsSelected'), - map(state=>state.regionsSelected)), + map(state=>state.regionsSelected), + distinctUntilChanged((arr1, arr2) => arr1.length === arr2.length && (arr1 as any[]).every((item, index) => item.name === arr2[index].name)) + ), loadedTemplates : [], @@ -69,6 +78,7 @@ export class AtlasViewerAPIServices{ private init(){ this.loadedTemplates$.subscribe(templates=>this.interactiveViewer.metadata.loadedTemplates = templates) + this.selectParcellation$.subscribe(parcellation => this.interactiveViewer.metadata.regionsLabelIndexMap = getLabelIndexMap(parcellation.regions)) } } diff --git a/src/atlasViewer/atlasViewer.constantService.service.ts b/src/atlasViewer/atlasViewer.constantService.service.ts index 64759d6d9..80e4ca6cb 100644 --- a/src/atlasViewer/atlasViewer.constantService.service.ts +++ b/src/atlasViewer/atlasViewer.constantService.service.ts @@ -103,9 +103,10 @@ const parseURLToElement = (url:string):HTMLElement=>{ } export const SUPPORT_LIBRARY_MAP : Map<string,HTMLElement> = new Map([ - ['jquery3',parseURLToElement('http://code.jquery.com/jquery-3.3.1.min.js')], - ['jquery2',parseURLToElement('http://code.jquery.com/jquery-2.2.4.min.js')], - ['webcomponentsLite',parseURLToElement('https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.1.0/webcomponents-lite.js')], - ['react16',parseURLToElement('https://unpkg.com/react@16/umd/react.development.js')], - ['reactdom16',parseURLToElement('https://unpkg.com/react-dom@16/umd/react-dom.development.js')], + ['jquery@3',parseURLToElement('http://code.jquery.com/jquery-3.3.1.min.js')], + ['jquery@2',parseURLToElement('http://code.jquery.com/jquery-2.2.4.min.js')], + ['webcomponentsLite@1.1.0',parseURLToElement('https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.1.0/webcomponents-lite.js')], + ['react@16',parseURLToElement('https://unpkg.com/react@16/umd/react.development.js')], + ['reactdom@16',parseURLToElement('https://unpkg.com/react-dom@16/umd/react-dom.development.js')], + ['vue@2.5.16',parseURLToElement('https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js')], ]) diff --git a/src/atlasViewer/atlasViewer.dataService.service.ts b/src/atlasViewer/atlasViewer.dataService.service.ts index cd1704da8..97e5ff75b 100644 --- a/src/atlasViewer/atlasViewer.dataService.service.ts +++ b/src/atlasViewer/atlasViewer.dataService.service.ts @@ -14,21 +14,14 @@ export class AtlasViewerDataService implements OnDestroy{ private subscriptions : Subscription[] = [] public promiseFetchedPluginManifests : Promise<PluginManifest[]> = new Promise((resolve,reject)=>{ - // fetch('http://medpc055.ime.kfa-juelich.de:5080/collectPlugins') - // .then(res=>res.json()) - // .then(json=>resolve(json)) - // .catch(err=>reject(err)) if(PLUGINDEV){ - + fetch('http://localhost:10080/allPluginmanifests') + .then(res=>res.json()) + .then(json=>resolve(json)) + .catch(reject) }else{ resolve([]) } - Promise.all([ - fetch('http://localhost:10080/jugex/manifest.json').then(res=>res.json()), - fetch('http://localhost:10080/testPlugin/manifest.json').then(res=>res.json()) - ]) - .then(arr=>resolve(arr)) - .catch(e=>reject(e)) }) public promiseFetchedTemplates : Promise<any[]> = Promise.all(this.constantService.templateUrls.map(url=> diff --git a/src/plugin_examples/newWebJugex/app.js b/src/plugin_examples/newWebJugex/app.js new file mode 100644 index 000000000..ed622b39c --- /dev/null +++ b/src/plugin_examples/newWebJugex/app.js @@ -0,0 +1,2 @@ +webpackJsonp([0],{AjZS:function(n,e,t){(n.exports=t("FZ+f")(!0)).push([n.i,"\ndiv.v-pill-container[data-v-94d8f66e]\n{\n display:inline-block;\n white-space: nowrap;\n margin:5px;\n padding:0.2em 0.6em;\n border-radius: 0.8em;\n}\ndiv.v-pill-container[data-v-94d8f66e]\n{\n cursor: default;\n -webkit-transition: all 300ms;\n transition: all 300ms;\n background-color:rgba(50,50,50,0.2);\n}\ndiv.v-pill-container[data-v-94d8f66e]:hover\n{\n background-color:rgba(150,150,150,0.2);\n}\nspan.v-pill-name[data-v-94d8f66e]\n{\n cursor: default;\n display:inline-block;\n}\nspan.v-pill-remove[data-v-94d8f66e]\n{\n cursor: default;\n display:inline-block;\n}\nspan.v-pill-remove[data-v-94d8f66e]:hover\n{\n font-weight: 900;\n color:rgba(200,30,30,1);\n}\n","",{version:3,sources:["/home/xgui3783/dev/projects/vue-components/src/components/src/components/pill.vue"],names:[],mappings:";AAuBA;;EAEA,qBAAA;EACA,oBAAA;EACA,WAAA;EACA,oBAAA;EACA,qBAAA;CACA;AAEA;;EAEA,gBAAA;EACA,8BAAA;EAAA,sBAAA;EACA,oCAAA;CACA;AAEA;;EAEA,uCAAA;CACA;AAEA;;EAEA,gBAAA;EACA,qBAAA;CACA;AACA;;EAEA,gBAAA;EACA,qBAAA;CACA;AAEA;;EAEA,iBAAA;EACA,wBAAA;CACA",file:"pill.vue",sourcesContent:['<template>\n<div @click.stop.prevent = "$emit(\'select-pill\')" class = "v-pill-container">\n <span class = "v-pill-name">{{ name }}</span>\n <span v-if = "closable" @click.stop.prevent = "$emit(\'remove-pill\')" class = "v-pill-remove">×</span>\n</div>\n</template>\n\n<script>\nmodule.exports = {\n props: {\n name: {\n type: String,\n default: \'Untitled\'\n },\n closable: {\n type: Boolean,\n default: true\n }\n }\n}\n<\/script>\n\n<style scoped>\ndiv.v-pill-container\n{\n display:inline-block;\n white-space: nowrap;\n margin:5px;\n padding:0.2em 0.6em;\n border-radius: 0.8em;\n}\n\ndiv.v-pill-container\n{\n cursor: default;\n transition: all 300ms;\n background-color:rgba(50,50,50,0.2);\n}\n\ndiv.v-pill-container:hover\n{\n background-color:rgba(150,150,150,0.2);\n}\n\nspan.v-pill-name\n{\n cursor: default;\n display:inline-block;\n}\nspan.v-pill-remove\n{\n cursor: default;\n display:inline-block;\n}\n\nspan.v-pill-remove:hover\n{\n font-weight: 900;\n color:rgba(200,30,30,1);\n}\n</style>\n'],sourceRoot:""}])},B6Kj:function(n,e,t){var o=t("RpWc");"string"==typeof o&&(o=[[n.i,o,""]]),o.locals&&(n.exports=o.locals);t("rjj0")("9aafbbb6",o,!1,{})},CJjv:function(n,e,t){var o=t("n8WV");"string"==typeof o&&(o=[[n.i,o,""]]),o.locals&&(n.exports=o.locals);t("rjj0")("6decef42",o,!1,{})},E8lD:function(n,e,t){var o=t("fKQA");"string"==typeof o&&(o=[[n.i,o,""]]),o.locals&&(n.exports=o.locals);t("rjj0")("041522c3",o,!1,{})},"KU0+":function(n,e,t){var o=t("R6Sg");"string"==typeof o&&(o=[[n.i,o,""]]),o.locals&&(n.exports=o.locals);t("rjj0")("c9be660c",o,!1,{})},NHnr:function(n,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=t("lRwf"),i=t.n(o),r={props:{top:Number,left:Number},data:function(){return{show:{type:Boolean,default:!1}}},computed:{contentContainerLeft:function(){return this.top&&this.left&&this.$refs.content&&this.$refs.screen?Math.min(this.left,this.$refs.screen.clientWidth-this.$refs.content.clientWidth)+"px":"0px"},contentContainerTop:function(){return this.top&&this.left&&this.$refs.content&&this.$refs.screen?Math.min(this.top,this.$refs.screen.clientHeight-this.$refs.content.clientHeight)+"px":"0px"},contentContainerWidth:function(){return this.top&&this.left&&this.$refs.content&&this.$refs.screen?"auto":"100%"},contentContainerHeight:function(){return this.top&&this.left&&this.$refs.content&&this.$refs.screen?"auto":"100%"}}},a=function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("div",[t("div",{staticClass:"v-modal-container"},[t("div",{ref:"screen",staticClass:"v-modal-screen",on:{click:function(e){n.$emit("close-modal")}}}),n._v(" "),t("div",{staticClass:"v-modal-content-container",style:{top:n.contentContainerTop,left:n.contentContainerLeft,width:n.contentContainerWidth,height:n.contentContainerHeight}},[t("div",{ref:"content",staticClass:"v-modal-content"},[t("div",{staticClass:"v-modal-header"},[n._t("v-modal-header")],2),n._v(" "),t("div",{staticClass:"v-modal-body"},[n._t("v-modal-body")],2),n._v(" "),t("div",{staticClass:"v-modal-footer"},[n._t("v-modal-footer")],2)])])])])};a._withStripped=!0;var s={render:a,staticRenderFns:[]},l=s;var A=!1;var c=t("VU/8")(r,l,!1,function(n){A||t("CJjv")},"data-v-0eaeaf66",null);c.options.__file="src/components/modal.vue";var d=c.exports,p=t("u0wG"),u={props:{placeholder:{type:String,default:"Start typing to search ..."},rawarray:{type:Array,default:function(){return[]}},rendermax:{type:Number,default:25}},data:function(){return{showSuggestions:!1,typedText:"",highlightIndex:0}},methods:{selectSlice:function(n){this.$emit("selectslice",n)},hitEnter:function(){switch(event.key){case"ArrowDown":this.highlightIndex+=1;break;case"Escape":this.$refs.input.blur();break;case"ArrowUp":this.highlightIndex-=1,this.highlightIndex<=0&&(this.highlightIndex+=this.filteredArray.length);break;case"Enter":var n=this.filteredArray.slice();if(n.length>0){this.typedText="";var e=document.querySelector(":focus");e&&e.blur(),this.selectSlice(n[0])}break;default:this.highlightIndex=0}}},computed:{rawArrayLowerCase:function(){return this.rawarray.map(function(n){return n.toLowerCase()})},typedTextLowerCase:function(){return this.typedText.toLowerCase()},filteredArray:function(){var n=this,e=new RegExp(this.typedText,"i"),t=this.rawarray.find(function(e){return e.toLowerCase()===n.typedTextLowerCase}),o=this.rawarray.filter(function(n){return e.test(n)}).filter(function(e){return e.toLowerCase()!==n.typedTextLowerCase}).filter(function(e,t){return t<=n.rendermax});return t?[t].concat(o.slice(0,o.length>=this.rendermax?o.length-1:o.length)):o}}},h=function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("div",{staticClass:"autocomplete-container"},[t("input",{directives:[{name:"model",rawName:"v-model",value:n.typedText,expression:"typedText"}],ref:"input",attrs:{type:"text",placeholder:n.placeholder},domProps:{value:n.typedText},on:{keydown:function(e){return e.stopPropagation(),n.hitEnter(e)},focus:function(e){n.showSuggestions=!0},blur:function(e){n.showSuggestions=!1},input:function(e){e.target.composing||(n.typedText=e.target.value)}}}),n._v(" "),t("transition",{attrs:{name:"fade"}},[n.showSuggestions?t("div",{staticClass:"autocomplete-suggestion-container"},n._l(n.filteredArray,function(e,o){return t("div",{key:o,staticClass:"autocomplete-suggestions",class:{active:n.highlightIndex%n.filteredArray.length===o},on:{mousedown:function(t){n.selectSlice(e)}}},[n._v("\n "+n._s(e)+"\n ")])})):n._e()])],1)};h._withStripped=!0;var f={render:h,staticRenderFns:[]},m=f;var v=!1;var g=t("VU/8")(u,m,!1,function(n){v||t("B6Kj")},"data-v-8351e810",null);g.options.__file="src/components/autocomplete.vue";var C=g.exports,y={props:{value:{type:String,default:"default value"},copyable:{type:Boolean,default:!0}},data:function(){return{copiedFlag:!1,timeoutRef:0,copyBtnShown:!1}},methods:{copyToClipBoard:function(){var n=this;this.copiedFlag=!0,this.timeoutRef&&clearTimeout(this.timeoutRef),setTimeout(function(){n.copiedFlag=!1,n.timeoutRef=0},2e3),this.$refs.inputEl.focus(),this.$refs.inputEl.select(),document.execCommand("copy",!1)},methodGetCopyText:function(){return this.copiedFlag?"Copied!":"Copy"}}},E=function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("div",{staticClass:"copy-field-root"},[t("input",{ref:"inputEl",attrs:{readonly:"",type:"text"},domProps:{value:n.value}}),n._v(" "),t("div",{attrs:{hidden:!n.copyable},on:{click:function(e){return e.stopPropagation(),n.copyToClipBoard(e)}}},[n._v(n._s(n.methodGetCopyText())+"\n ")])])};E._withStripped=!0;var b={render:E,staticRenderFns:[]},x=b;var w=!1;var k=t("VU/8")(y,x,!1,function(n){w||t("E8lD")},null,null);k.options.__file="src/components/copyfield.vue";var B=k.exports,_={props:{collapsedHeight:{type:Number,default:25}},data:function(){return{collapsed:{type:Boolean,default:!0},actualHeight:{type:Number,default:25}}},mounted:function(){this.actualHeight=this.$refs.readmoreContentContainer.clientHeight},methods:{toggle:function(){this.collapsed=!this.collapsed}},computed:{computedHeight:function(){return(this.collapsed?this.collapsedHeight:this.actualHeight)+"px"}}},$=function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("div",{staticClass:"readmore-container"},[t("div",{staticClass:"readmore-content",style:{height:n.computedHeight}},[t("div",{ref:"readmoreContentContainer"},[n._t("readmoreContent")],2)]),n._v(" "),t("div",{staticClass:"readmore-sliver",on:{click:n.toggle}},[n.collapsed?n._t("resizeSliverContentCollapsed"):n._e(),n._v(" "),n.collapsed?n._e():n._t("resizeSliverContentShown")],2)])};$._withStripped=!0;var S={render:$,staticRenderFns:[]},T=S;var R=!1;var H=t("VU/8")(_,T,!1,function(n){R||t("KU0+")},"data-v-92448f0a",null);H.options.__file="src/components/readmore.vue";var j=H.exports;i.a.config.productionTip=!1,i.a.component("vue-modal",d),i.a.component("vue-pill",p.default),i.a.component("vue-autocomplete",C),i.a.component("vue-copyfield",B),i.a.component("vue-readmore",j)},R6Sg:function(n,e,t){(n.exports=t("FZ+f")(!0)).push([n.i,"\n.readmore-content[data-v-92448f0a]\n{\n -webkit-transition: all 0.3s;\n transition: all 0.3s;\n overflow-y : hidden;\n}\n.readmore-sliver[data-v-92448f0a]\n{\n min-height: 0.5em;\n -webkit-transition: all 0.3s;\n transition: all 0.3s;\n background-color: rgba(128,128,128,0.2);\n}\n.readmore-sliver[data-v-92448f0a]:hover\n{\n -webkit-transform: translateY(-2px);\n transform: translateY(-2px);\n background-color: rgba(128,128,128,0.4);\n}\n","",{version:3,sources:["/home/xgui3783/dev/projects/vue-components/src/components/src/components/readmore.vue"],names:[],mappings:";AAiDA;;EAEA,6BAAA;EAAA,qBAAA;EACA,oBAAA;CACA;AACA;;EAEA,kBAAA;EACA,6BAAA;EAAA,qBAAA;EACA,wCAAA;CACA;AACA;;EAEA,oCAAA;UAAA,4BAAA;EACA,wCAAA;CACA",file:"readmore.vue",sourcesContent:['<template>\n<div class = "readmore-container">\n <div :style = "{ height : computedHeight }" class = "readmore-content">\n <div ref = "readmoreContentContainer">\n <slot name = "readmoreContent"></slot>\n </div>\n </div>\n <div @click = "toggle" class = "readmore-sliver">\n <slot v-if = "collapsed" name = "resizeSliverContentCollapsed">\n </slot>\n <slot v-if = "!collapsed" name = "resizeSliverContentShown">\n </slot>\n </div>\n</div>\n</template>\n<script>\nexport default {\n props: {\n collapsedHeight: {\n type: Number,\n default: 25\n }\n },\n data: () => ({\n collapsed: {\n type: Boolean,\n default: true\n },\n actualHeight: {\n type: Number,\n default: 25\n }\n }),\n mounted: function () {\n this.actualHeight = this.$refs.readmoreContentContainer.clientHeight\n },\n methods: {\n toggle: function () {\n this.collapsed = !this.collapsed\n }\n },\n computed: {\n computedHeight: function () {\n return `${this.collapsed ? this.collapsedHeight : this.actualHeight}px`\n }\n }\n}\n<\/script>\n<style scoped>\n.readmore-content\n{\n transition: all 0.3s;\n overflow-y : hidden;\n}\n.readmore-sliver\n{\n min-height: 0.5em;\n transition: all 0.3s;\n background-color: rgba(128,128,128,0.2);\n}\n.readmore-sliver:hover\n{\n transform: translateY(-2px);\n background-color: rgba(128,128,128,0.4);\n}\n</style>\n'],sourceRoot:""}])},RQup:function(n,e){n.exports={props:{name:{type:String,default:"Untitled"},closable:{type:Boolean,default:!0}}}},RpWc:function(n,e,t){(n.exports=t("FZ+f")(!0)).push([n.i,'\ndiv.autocomplete-container[data-v-8351e810]\n{\n cursor:default;\n}\n.autocomplete-suggestions[data-v-8351e810]\n{\n width:100%;\n display:block;\n padding:0.1em 0.3em;\n -webkit-transition: all 200ms;\n transition: all 200ms;\n background-color:rgba(230,230,230,0.5);\n}\n.autocomplete-suggestions.active[data-v-8351e810]\n{\n background-color:rgba(230,230,230,0.95);\n}\n.autocomplete-suggestions[data-v-8351e810]:hover\n{\n background-color:rgba(230,230,230,0.95);\n}\ndiv.autocomplete-container:focus-within .autocomplete-suggestions[data-v-8351e810]\n{\n display: block;\n}\ndiv.autocomplete-suggestion-container[data-v-8351e810]\n{\n width: 100%;\n max-height:10em;\n overflow-y:auto;\n overflow-x:hidden;\n z-index:2;\n}\ninput[type="text"][data-v-8351e810]\n{\n width:100%;\n height:100%;\n z-index:1;\n}\n',"",{version:3,sources:["/home/xgui3783/dev/projects/vue-components/src/components/src/components/autocomplete.vue"],names:[],mappings:";AAoGA;;EAEA,eAAA;CACA;AAEA;;EAEA,WAAA;EACA,cAAA;EACA,oBAAA;EACA,8BAAA;EAAA,sBAAA;EACA,uCAAA;CACA;AAEA;;EAEA,wCAAA;CACA;AAEA;;EAEA,wCAAA;CACA;AAEA;;EAEA,eAAA;CACA;AAEA;;EAEA,YAAA;EACA,gBAAA;EACA,gBAAA;EACA,kBAAA;EACA,UAAA;CACA;AACA;;EAEA,WAAA;EACA,YAAA;EACA,UAAA;CACA",file:"autocomplete.vue",sourcesContent:['<template>\n<div class = "autocomplete-container">\n <input\n ref = "input"\n @keydown.stop = "hitEnter"\n type = "text"\n @focus = "showSuggestions = true"\n @blur = "showSuggestions = false"\n v-model = "typedText"\n :placeholder = "placeholder"/>\n <transition name = "fade">\n <div v-if = "showSuggestions" class = "autocomplete-suggestion-container">\n <div\n @mousedown="selectSlice(item)"\n class = "autocomplete-suggestions"\n :class = "{active : ((highlightIndex % filteredArray.length) === index)}"\n v-bind:key = "index"\n v-for = "(item,index) in filteredArray">\n {{ item }}\n </div>\n </div>\n </transition>\n</div>\n</template>\n\n<script>\nexport default {\n props: {\n placeholder: {\n type: String,\n default: \'Start typing to search ...\'\n },\n rawarray: {\n type: Array,\n default: () => ([])\n },\n rendermax: {\n type: Number,\n default: 25\n }\n },\n data: () => ({\n showSuggestions: false,\n typedText: \'\',\n highlightIndex: 0\n }),\n methods: {\n selectSlice: function (item) {\n this.$emit(\'selectslice\', item)\n },\n hitEnter: function () {\n switch (event.key) {\n case \'ArrowDown\':\n this.highlightIndex += 1\n break\n case \'Escape\':\n this.$refs.input.blur()\n break\n case \'ArrowUp\':\n this.highlightIndex -= 1\n if (this.highlightIndex <= 0) this.highlightIndex += this.filteredArray.length\n break\n case \'Enter\':\n const array = this.filteredArray.slice()\n if (array.length > 0) {\n this.typedText = \'\'\n const el = document.querySelector(\':focus\')\n if (el) el.blur()\n this.selectSlice(array[0])\n }\n break\n default:\n this.highlightIndex = 0\n break\n }\n }\n },\n computed: {\n rawArrayLowerCase: function () {\n return this.rawarray.map(item => item.toLowerCase())\n },\n typedTextLowerCase: function () {\n return this.typedText.toLowerCase()\n },\n filteredArray: function () {\n const regex = new RegExp(this.typedText, \'i\')\n const completeMatch = this.rawarray.find(item => item.toLowerCase() === this.typedTextLowerCase)\n const othermatches = this.rawarray\n .filter(item => regex.test(item))\n .filter(item => item.toLowerCase() !== this.typedTextLowerCase)\n .filter((_, idx) => idx <= this.rendermax)\n return completeMatch\n ? [completeMatch].concat(othermatches.slice(0, othermatches.length >= this.rendermax ? othermatches.length - 1 : othermatches.length))\n : othermatches\n }\n }\n}\n<\/script>\n\n<style scoped>\ndiv.autocomplete-container\n{\n cursor:default;\n}\n\n.autocomplete-suggestions\n{\n width:100%;\n display:block;\n padding:0.1em 0.3em;\n transition: all 200ms;\n background-color:rgba(230,230,230,0.5);\n}\n\n.autocomplete-suggestions.active\n{\n background-color:rgba(230,230,230,0.95);\n}\n\n.autocomplete-suggestions:hover\n{\n background-color:rgba(230,230,230,0.95);\n}\n\ndiv.autocomplete-container:focus-within .autocomplete-suggestions\n{\n display: block;\n}\n\ndiv.autocomplete-suggestion-container\n{\n width: 100%;\n max-height:10em;\n overflow-y:auto;\n overflow-x:hidden;\n z-index:2;\n}\ninput[type="text"]\n{\n width:100%;\n height:100%;\n z-index:1;\n}\n</style>\n'],sourceRoot:""}])},ck25:function(n,e,t){"use strict";var o=function(){var n=this,e=n.$createElement,t=n._self._c||e;return t("div",{staticClass:"v-pill-container",on:{click:function(e){e.stopPropagation(),e.preventDefault(),n.$emit("select-pill")}}},[t("span",{staticClass:"v-pill-name"},[n._v(n._s(n.name))]),n._v(" "),n.closable?t("span",{staticClass:"v-pill-remove",on:{click:function(e){e.stopPropagation(),e.preventDefault(),n.$emit("remove-pill")}}},[n._v("×")]):n._e()])};o._withStripped=!0;var i={render:o,staticRenderFns:[]};e.a=i},fKQA:function(n,e,t){(n.exports=t("FZ+f")(!0)).push([n.i,"\n.copy-field-root\n{\n width: 100%;\n white-space: nowrap;\n}\n.copy-field-root *\n{\n color:black\n}\n.copy-field-root > input\n{\n width : 100%;\n height:2.0em;\n display: inline-block;\n vertical-align : middle;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n position : relative;\n\n border : solid 1px rgba(128,128,128,0.6);\n z-index: 8;\n}\n.copy-field-root > div:not([hidden])\n{\n position : relative;\n z-index: 9;\n cursor:default;\n display: inline-block;\n -webkit-box-sizing:border-box;\n box-sizing:border-box;\n margin : 0.2em;\n height : 1.6em;\n margin-left:-4em;\n font-size:100%;\n vertical-align : middle;\n text-align: center;\n font-size:0.9em;\n padding : 0.2em;\n\n color:rgba(0,0,0,0.8);\n border : solid 1px rgba(0,0,0,0.5);\n\n background-color:rgba(230,230,230,0.9);\n}\n.copy-field-root > div:hover\n{\n background-color:rgba(240,240,240,1.0);\n}\n","",{version:3,sources:["/home/xgui3783/dev/projects/vue-components/src/components/src/components/copyfield.vue"],names:[],mappings:";AAiDA;;EAEA,YAAA;EACA,oBAAA;CACA;AAEA;;EAEA,WAAA;CACA;AAEA;;EAEA,aAAA;EACA,aAAA;EACA,sBAAA;EACA,wBAAA;EACA,+BAAA;UAAA,uBAAA;EACA,oBAAA;;EAEA,yCAAA;EACA,WAAA;CACA;AAEA;;EAEA,oBAAA;EACA,WAAA;EACA,eAAA;EACA,sBAAA;EACA,8BAAA;UAAA,sBAAA;EACA,eAAA;EACA,eAAA;EACA,iBAAA;EACA,eAAA;EACA,wBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;;EAEA,sBAAA;EACA,mCAAA;;EAEA,uCAAA;CACA;AAEA;;EAEA,uCAAA;CACA",file:"copyfield.vue",sourcesContent:['<template>\n<div class = "copy-field-root">\n <input ref = "inputEl" readonly v-bind:value = "value" type = "text" />\n <div\n v-bind:hidden = "!copyable"\n @click.stop = "copyToClipBoard">{{ methodGetCopyText() }}\n </div>\n</div>\n</template>\n\n<script>\nexport default {\n props: {\n value: {\n type: String,\n default: \'default value\'\n },\n copyable: {\n type: Boolean,\n default: true\n }\n },\n data: () => ({\n copiedFlag: false,\n timeoutRef: 0,\n copyBtnShown: false\n }),\n methods: {\n copyToClipBoard: function () {\n this.copiedFlag = true\n if (this.timeoutRef) {\n clearTimeout(this.timeoutRef)\n }\n setTimeout(() => {\n this.copiedFlag = false\n this.timeoutRef = 0\n }, 2000)\n\n this.$refs.inputEl.focus()\n this.$refs.inputEl.select()\n document.execCommand(\'copy\', false)\n },\n methodGetCopyText: function () {\n return this.copiedFlag ? \'Copied!\' : \'Copy\'\n }\n }\n}\n<\/script>\n<style>\n.copy-field-root\n{\n width: 100%;\n white-space: nowrap;\n}\n\n.copy-field-root *\n{\n color:black\n}\n\n.copy-field-root > input\n{\n width : 100%;\n height:2.0em;\n display: inline-block;\n vertical-align : middle;\n box-sizing: border-box;\n position : relative;\n\n border : solid 1px rgba(128,128,128,0.6);\n z-index: 8;\n}\n\n.copy-field-root > div:not([hidden])\n{\n position : relative;\n z-index: 9;\n cursor:default;\n display: inline-block;\n box-sizing:border-box;\n margin : 0.2em;\n height : 1.6em;\n margin-left:-4em;\n font-size:100%;\n vertical-align : middle;\n text-align: center;\n font-size:0.9em;\n padding : 0.2em;\n\n color:rgba(0,0,0,0.8);\n border : solid 1px rgba(0,0,0,0.5);\n\n background-color:rgba(230,230,230,0.9);\n}\n\n.copy-field-root > div:hover\n{\n background-color:rgba(240,240,240,1.0);\n}\n</style>\n'],sourceRoot:""}])},lRwf:function(n,e){n.exports=Vue},n8WV:function(n,e,t){(n.exports=t("FZ+f")(!0)).push([n.i,"\n.v-modal-container[data-v-0eaeaf66]\n{\n top: 0;\n width:100%;\n height:100%;\n position : absolute;\n z-index:999;\n}\n.v-modal-screen[data-v-0eaeaf66]\n{\n top : 0;\n position : absolute;\n width:100%;\n height:100%;\n background-color:rgba(30,30,30,0.2);\n}\n.v-modal-content-container[data-v-0eaeaf66]\n{\n top : 0;\n position : absolute;\n display : -webkit-box;\n display : -ms-flexbox;\n display : flex;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n -ms-flex-line-pack: center;\n align-content: center;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center;\n\n pointer-events: none;\n}\n.v-modal-content[data-v-0eaeaf66]\n{\n -webkit-box-flex : 0;\n -ms-flex : 0 0 auto;\n flex : 0 0 auto;\n pointer-events: all;\n}\n\n","",{version:3,sources:["/home/xgui3783/dev/projects/vue-components/src/components/src/components/modal.vue"],names:[],mappings:";AA4DA;;EAEA,OAAA;EACA,WAAA;EACA,YAAA;EACA,oBAAA;EACA,YAAA;CACA;AACA;;EAEA,QAAA;EACA,oBAAA;EACA,WAAA;EACA,YAAA;EACA,oCAAA;CACA;AAEA;;EAEA,QAAA;EACA,oBAAA;EACA,sBAAA;EAAA,sBAAA;EAAA,eAAA;EACA,0BAAA;MAAA,uBAAA;UAAA,oBAAA;EACA,2BAAA;MAAA,sBAAA;EACA,yBAAA;MAAA,sBAAA;UAAA,wBAAA;;EAEA,qBAAA;CACA;AACA;;EAEA,qBAAA;MAAA,oBAAA;UAAA,gBAAA;EACA,oBAAA;CACA",file:"modal.vue",sourcesContent:['<template>\n<div>\n <div class = "v-modal-container">\n <div\n ref = "screen"\n v-on:click = "$emit(\'close-modal\')"\n class = "v-modal-screen">\n </div>\n <div\n v-bind:style = "{top:contentContainerTop,left:contentContainerLeft,width:contentContainerWidth,height:contentContainerHeight,}"\n class = "v-modal-content-container">\n <div\n ref = "content"\n class = "v-modal-content">\n <div class = "v-modal-header">\n <slot name = "v-modal-header">\n </slot>\n </div>\n <div class = "v-modal-body">\n <slot name = "v-modal-body">\n </slot>\n </div>\n <div class = "v-modal-footer">\n <slot name = "v-modal-footer">\n </slot>\n </div>\n </div>\n </div>\n </div>\n</div>\n</template>\n<script>\nexport default {\n props: {\n top: Number,\n left: Number\n },\n data: () => ({\n show: {\n type: Boolean,\n default: false\n }\n }),\n computed: {\n contentContainerLeft: function () {\n return this.top && this.left && this.$refs.content && this.$refs.screen ? Math.min(this.left, this.$refs.screen.clientWidth - this.$refs.content.clientWidth) + \'px\' : `0px`\n },\n contentContainerTop: function () {\n return this.top && this.left && this.$refs.content && this.$refs.screen ? Math.min(this.top, this.$refs.screen.clientHeight - this.$refs.content.clientHeight) + \'px\' : `0px`\n },\n contentContainerWidth: function () {\n return this.top && this.left && this.$refs.content && this.$refs.screen ? \'auto\' : `100%`\n },\n contentContainerHeight: function () {\n return this.top && this.left && this.$refs.content && this.$refs.screen ? \'auto\' : `100%`\n }\n }\n}\n<\/script>\n<style scoped>\n.v-modal-container\n{\n top: 0;\n width:100%;\n height:100%;\n position : absolute;\n z-index:999;\n}\n.v-modal-screen\n{\n top : 0;\n position : absolute;\n width:100%;\n height:100%;\n background-color:rgba(30,30,30,0.2);\n}\n\n.v-modal-content-container\n{\n top : 0;\n position : absolute;\n display : flex;\n align-items: center;\n align-content: center;\n justify-content: center;\n\n pointer-events: none;\n}\n.v-modal-content\n{\n flex : 0 0 auto;\n pointer-events: all;\n}\n\n</style>\n'],sourceRoot:""}])},"nFT+":function(n,e,t){var o=t("AjZS");"string"==typeof o&&(o=[[n.i,o,""]]),o.locals&&(n.exports=o.locals);t("rjj0")("12958e8c",o,!1,{})},u0wG:function(n,e,t){"use strict";var o=t("RQup"),i=t.n(o),r=t("ck25"),a=!1;var s=function(n){a||t("nFT+")},l=t("VU/8")(i.a,r.a,!1,s,"data-v-94d8f66e",null);l.options.__file="src/components/pill.vue",e.default=l.exports}},["NHnr"]); +//# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/src/plugin_examples/newWebJugex/app.js.map b/src/plugin_examples/newWebJugex/app.js.map new file mode 100644 index 000000000..b676d7239 --- /dev/null +++ b/src/plugin_examples/newWebJugex/app.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./src/components/pill.vue?058a","webpack:///./src/components/autocomplete.vue?d5dc","webpack:///./src/components/modal.vue?b3b0","webpack:///./src/components/copyfield.vue?5b43","webpack:///./src/components/readmore.vue?f84b","webpack:///src/components/modal.vue","webpack:///./src/components/modal.vue?3efc","webpack:///./src/components/modal.vue","webpack:///src/components/autocomplete.vue","webpack:///./src/components/autocomplete.vue?220c","webpack:///./src/components/autocomplete.vue","webpack:///src/components/copyfield.vue","webpack:///./src/components/copyfield.vue?d3b4","webpack:///./src/components/copyfield.vue","webpack:///src/components/readmore.vue","webpack:///./src/components/readmore.vue?fad6","webpack:///./src/components/readmore.vue","webpack:///./src/main.js","webpack:///./src/components/readmore.vue?2a65","webpack:///src/components/pill.vue","webpack:///./src/components/autocomplete.vue?905f","webpack:///./src/components/pill.vue?c6c2","webpack:///./src/components/copyfield.vue?23c7","webpack:///external \"Vue\"","webpack:///./src/components/modal.vue?2409","webpack:///./src/components/pill.vue?5a83","webpack:///./src/components/pill.vue"],"names":["module","exports","__webpack_require__","push","i","version","sources","names","mappings","file","sourcesContent","sourceRoot","content","locals","modal","props","top","Number","left","data","show","type","Boolean","default","computed","contentContainerLeft","this","$refs","screen","Math","min","clientWidth","contentContainerTop","clientHeight","contentContainerWidth","contentContainerHeight","render","_vm","_h","$createElement","_c","_self","staticClass","ref","on","click","$event","$emit","_v","style","width","height","_t","_withStripped","esExports","staticRenderFns","components_modal","disposed","Component","normalizeComponent","ssrContext","options","__file","src_components_modal","autocomplete","placeholder","String","rawarray","Array","rendermax","showSuggestions","typedText","highlightIndex","methods","selectSlice","item","hitEnter","event","key","input","blur","filteredArray","length","array","slice","el","document","querySelector","rawArrayLowerCase","map","toLowerCase","typedTextLowerCase","_this","regex","RegExp","completeMatch","find","othermatches","filter","test","_","idx","concat","autocomplete_render","directives","name","rawName","value","expression","attrs","domProps","keydown","stopPropagation","focus","target","composing","_l","index","class","active","mousedown","_s","_e","autocomplete_esExports","components_autocomplete","autocomplete_disposed","autocomplete_Component","autocomplete_normalizeComponent","src_components_autocomplete","copyfield","copyable","copiedFlag","timeoutRef","copyBtnShown","copyToClipBoard","clearTimeout","setTimeout","inputEl","select","execCommand","methodGetCopyText","copyfield_render","readonly","hidden","copyfield_esExports","components_copyfield","copyfield_disposed","copyfield_Component","copyfield_normalizeComponent","src_components_copyfield","readmore","collapsedHeight","collapsed","actualHeight","mounted","readmoreContentContainer","toggle","computedHeight","readmore_render","readmore_esExports","components_readmore","readmore_disposed","readmore_Component","readmore_normalizeComponent","src_components_readmore","external__Vue__default","a","config","productionTip","component","pill","closable","preventDefault","__webpack_exports__","Vue","__WEBPACK_IMPORTED_MODULE_1__node_modules_vue_loader_lib_template_compiler_index_id_data_v_94d8f66e_hasScoped_true_transformToRequire_video_src_poster_source_src_img_src_image_xlink_href_buble_transforms_node_modules_vue_loader_lib_selector_type_template_index_0_pill_vue__","__vue_styles__","__WEBPACK_IMPORTED_MODULE_0__babel_loader_node_modules_vue_loader_lib_selector_type_script_index_0_pill_vue___default"],"mappings":"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","file":"static/js/app.js","sourcesContent":["exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(true);\n// imports\n\n\n// module\nexports.push([module.id, \"\\ndiv.v-pill-container[data-v-94d8f66e]\\n{\\n display:inline-block;\\n white-space: nowrap;\\n margin:5px;\\n padding:0.2em 0.6em;\\n border-radius: 0.8em;\\n}\\ndiv.v-pill-container[data-v-94d8f66e]\\n{\\n cursor: default;\\n -webkit-transition: all 300ms;\\n transition: all 300ms;\\n background-color:rgba(50,50,50,0.2);\\n}\\ndiv.v-pill-container[data-v-94d8f66e]:hover\\n{\\n background-color:rgba(150,150,150,0.2);\\n}\\nspan.v-pill-name[data-v-94d8f66e]\\n{\\n cursor: default;\\n display:inline-block;\\n}\\nspan.v-pill-remove[data-v-94d8f66e]\\n{\\n cursor: default;\\n display:inline-block;\\n}\\nspan.v-pill-remove[data-v-94d8f66e]:hover\\n{\\n font-weight: 900;\\n color:rgba(200,30,30,1);\\n}\\n\", \"\", {\"version\":3,\"sources\":[\"/home/xgui3783/dev/projects/vue-components/src/components/src/components/pill.vue\"],\"names\":[],\"mappings\":\";AAuBA;;EAEA,qBAAA;EACA,oBAAA;EACA,WAAA;EACA,oBAAA;EACA,qBAAA;CACA;AAEA;;EAEA,gBAAA;EACA,8BAAA;EAAA,sBAAA;EACA,oCAAA;CACA;AAEA;;EAEA,uCAAA;CACA;AAEA;;EAEA,gBAAA;EACA,qBAAA;CACA;AACA;;EAEA,gBAAA;EACA,qBAAA;CACA;AAEA;;EAEA,iBAAA;EACA,wBAAA;CACA\",\"file\":\"pill.vue\",\"sourcesContent\":[\"<template>\\n<div @click.stop.prevent = \\\"$emit('select-pill')\\\" class = \\\"v-pill-container\\\">\\n <span class = \\\"v-pill-name\\\">{{ name }}</span>\\n <span v-if = \\\"closable\\\" @click.stop.prevent = \\\"$emit('remove-pill')\\\" class = \\\"v-pill-remove\\\">×</span>\\n</div>\\n</template>\\n\\n<script>\\nmodule.exports = {\\n props: {\\n name: {\\n type: String,\\n default: 'Untitled'\\n },\\n closable: {\\n type: Boolean,\\n default: true\\n }\\n }\\n}\\n</script>\\n\\n<style scoped>\\ndiv.v-pill-container\\n{\\n display:inline-block;\\n white-space: nowrap;\\n margin:5px;\\n padding:0.2em 0.6em;\\n border-radius: 0.8em;\\n}\\n\\ndiv.v-pill-container\\n{\\n cursor: default;\\n transition: all 300ms;\\n background-color:rgba(50,50,50,0.2);\\n}\\n\\ndiv.v-pill-container:hover\\n{\\n background-color:rgba(150,150,150,0.2);\\n}\\n\\nspan.v-pill-name\\n{\\n cursor: default;\\n display:inline-block;\\n}\\nspan.v-pill-remove\\n{\\n cursor: default;\\n display:inline-block;\\n}\\n\\nspan.v-pill-remove:hover\\n{\\n font-weight: 900;\\n color:rgba(200,30,30,1);\\n}\\n</style>\\n\"],\"sourceRoot\":\"\"}]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/css-loader?{\"sourceMap\":true}!./node_modules/vue-loader/lib/style-compiler?{\"vue\":true,\"id\":\"data-v-94d8f66e\",\"scoped\":true,\"hasInlineConfig\":false}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/pill.vue\n// module id = AjZS\n// module chunks = 0","// style-loader: Adds some css to the DOM by adding a <style> tag\n\n// load the styles\nvar content = require(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-8351e810\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./autocomplete.vue\");\nif(typeof content === 'string') content = [[module.id, content, '']];\nif(content.locals) module.exports = content.locals;\n// add the styles to the DOM\nvar update = require(\"!../../node_modules/vue-style-loader/lib/addStylesClient.js\")(\"9aafbbb6\", content, false, {});\n// Hot Module Replacement\nif(module.hot) {\n // When the styles change, update the <style> tags\n if(!content.locals) {\n module.hot.accept(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-8351e810\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./autocomplete.vue\", function() {\n var newContent = require(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-8351e810\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./autocomplete.vue\");\n if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n update(newContent);\n });\n }\n // When the module is disposed, remove the <style> tags\n module.hot.dispose(function() { update(); });\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-style-loader!./node_modules/css-loader?{\"sourceMap\":true}!./node_modules/vue-loader/lib/style-compiler?{\"vue\":true,\"id\":\"data-v-8351e810\",\"scoped\":true,\"hasInlineConfig\":false}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/autocomplete.vue\n// module id = B6Kj\n// module chunks = 0","// style-loader: Adds some css to the DOM by adding a <style> tag\n\n// load the styles\nvar content = require(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-0eaeaf66\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./modal.vue\");\nif(typeof content === 'string') content = [[module.id, content, '']];\nif(content.locals) module.exports = content.locals;\n// add the styles to the DOM\nvar update = require(\"!../../node_modules/vue-style-loader/lib/addStylesClient.js\")(\"6decef42\", content, false, {});\n// Hot Module Replacement\nif(module.hot) {\n // When the styles change, update the <style> tags\n if(!content.locals) {\n module.hot.accept(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-0eaeaf66\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./modal.vue\", function() {\n var newContent = require(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-0eaeaf66\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./modal.vue\");\n if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n update(newContent);\n });\n }\n // When the module is disposed, remove the <style> tags\n module.hot.dispose(function() { update(); });\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-style-loader!./node_modules/css-loader?{\"sourceMap\":true}!./node_modules/vue-loader/lib/style-compiler?{\"vue\":true,\"id\":\"data-v-0eaeaf66\",\"scoped\":true,\"hasInlineConfig\":false}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/modal.vue\n// module id = CJjv\n// module chunks = 0","// style-loader: Adds some css to the DOM by adding a <style> tag\n\n// load the styles\nvar content = require(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-1d7c4045\\\",\\\"scoped\\\":false,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./copyfield.vue\");\nif(typeof content === 'string') content = [[module.id, content, '']];\nif(content.locals) module.exports = content.locals;\n// add the styles to the DOM\nvar update = require(\"!../../node_modules/vue-style-loader/lib/addStylesClient.js\")(\"041522c3\", content, false, {});\n// Hot Module Replacement\nif(module.hot) {\n // When the styles change, update the <style> tags\n if(!content.locals) {\n module.hot.accept(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-1d7c4045\\\",\\\"scoped\\\":false,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./copyfield.vue\", function() {\n var newContent = require(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-1d7c4045\\\",\\\"scoped\\\":false,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./copyfield.vue\");\n if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n update(newContent);\n });\n }\n // When the module is disposed, remove the <style> tags\n module.hot.dispose(function() { update(); });\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-style-loader!./node_modules/css-loader?{\"sourceMap\":true}!./node_modules/vue-loader/lib/style-compiler?{\"vue\":true,\"id\":\"data-v-1d7c4045\",\"scoped\":false,\"hasInlineConfig\":false}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/copyfield.vue\n// module id = E8lD\n// module chunks = 0","// style-loader: Adds some css to the DOM by adding a <style> tag\n\n// load the styles\nvar content = require(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-92448f0a\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./readmore.vue\");\nif(typeof content === 'string') content = [[module.id, content, '']];\nif(content.locals) module.exports = content.locals;\n// add the styles to the DOM\nvar update = require(\"!../../node_modules/vue-style-loader/lib/addStylesClient.js\")(\"c9be660c\", content, false, {});\n// Hot Module Replacement\nif(module.hot) {\n // When the styles change, update the <style> tags\n if(!content.locals) {\n module.hot.accept(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-92448f0a\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./readmore.vue\", function() {\n var newContent = require(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-92448f0a\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./readmore.vue\");\n if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n update(newContent);\n });\n }\n // When the module is disposed, remove the <style> tags\n module.hot.dispose(function() { update(); });\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-style-loader!./node_modules/css-loader?{\"sourceMap\":true}!./node_modules/vue-loader/lib/style-compiler?{\"vue\":true,\"id\":\"data-v-92448f0a\",\"scoped\":true,\"hasInlineConfig\":false}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/readmore.vue\n// module id = KU0+\n// module chunks = 0","<template>\n<div>\n <div class = \"v-modal-container\">\n <div\n ref = \"screen\"\n v-on:click = \"$emit('close-modal')\"\n class = \"v-modal-screen\">\n </div>\n <div\n v-bind:style = \"{top:contentContainerTop,left:contentContainerLeft,width:contentContainerWidth,height:contentContainerHeight,}\"\n class = \"v-modal-content-container\">\n <div\n ref = \"content\"\n class = \"v-modal-content\">\n <div class = \"v-modal-header\">\n <slot name = \"v-modal-header\">\n </slot>\n </div>\n <div class = \"v-modal-body\">\n <slot name = \"v-modal-body\">\n </slot>\n </div>\n <div class = \"v-modal-footer\">\n <slot name = \"v-modal-footer\">\n </slot>\n </div>\n </div>\n </div>\n </div>\n</div>\n</template>\n<script>\nexport default {\n props: {\n top: Number,\n left: Number\n },\n data: () => ({\n show: {\n type: Boolean,\n default: false\n }\n }),\n computed: {\n contentContainerLeft: function () {\n return this.top && this.left && this.$refs.content && this.$refs.screen ? Math.min(this.left, this.$refs.screen.clientWidth - this.$refs.content.clientWidth) + 'px' : `0px`\n },\n contentContainerTop: function () {\n return this.top && this.left && this.$refs.content && this.$refs.screen ? Math.min(this.top, this.$refs.screen.clientHeight - this.$refs.content.clientHeight) + 'px' : `0px`\n },\n contentContainerWidth: function () {\n return this.top && this.left && this.$refs.content && this.$refs.screen ? 'auto' : `100%`\n },\n contentContainerHeight: function () {\n return this.top && this.left && this.$refs.content && this.$refs.screen ? 'auto' : `100%`\n }\n }\n}\n</script>\n<style scoped>\n.v-modal-container\n{\n top: 0;\n width:100%;\n height:100%;\n position : absolute;\n z-index:999;\n}\n.v-modal-screen\n{\n top : 0;\n position : absolute;\n width:100%;\n height:100%;\n background-color:rgba(30,30,30,0.2);\n}\n\n.v-modal-content-container\n{\n top : 0;\n position : absolute;\n display : flex;\n align-items: center;\n align-content: center;\n justify-content: center;\n\n pointer-events: none;\n}\n.v-modal-content\n{\n flex : 0 0 auto;\n pointer-events: all;\n}\n\n</style>\n\n\n\n// WEBPACK FOOTER //\n// src/components/modal.vue","var render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", [\n _c(\"div\", { staticClass: \"v-modal-container\" }, [\n _c(\"div\", {\n ref: \"screen\",\n staticClass: \"v-modal-screen\",\n on: {\n click: function($event) {\n _vm.$emit(\"close-modal\")\n }\n }\n }),\n _vm._v(\" \"),\n _c(\n \"div\",\n {\n staticClass: \"v-modal-content-container\",\n style: {\n top: _vm.contentContainerTop,\n left: _vm.contentContainerLeft,\n width: _vm.contentContainerWidth,\n height: _vm.contentContainerHeight\n }\n },\n [\n _c(\"div\", { ref: \"content\", staticClass: \"v-modal-content\" }, [\n _c(\n \"div\",\n { staticClass: \"v-modal-header\" },\n [_vm._t(\"v-modal-header\")],\n 2\n ),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"v-modal-body\" },\n [_vm._t(\"v-modal-body\")],\n 2\n ),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"v-modal-footer\" },\n [_vm._t(\"v-modal-footer\")],\n 2\n )\n ])\n ]\n )\n ])\n ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\nvar esExports = { render: render, staticRenderFns: staticRenderFns }\nexport default esExports\nif (module.hot) {\n module.hot.accept()\n if (module.hot.data) {\n require(\"vue-hot-reload-api\") .rerender(\"data-v-0eaeaf66\", esExports)\n }\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-loader/lib/template-compiler?{\"id\":\"data-v-0eaeaf66\",\"hasScoped\":true,\"transformToRequire\":{\"video\":[\"src\",\"poster\"],\"source\":\"src\",\"img\":\"src\",\"image\":\"xlink:href\"},\"buble\":{\"transforms\":{}}}!./node_modules/vue-loader/lib/selector.js?type=template&index=0!./src/components/modal.vue\n// module id = null\n// module chunks = ","var disposed = false\nfunction injectStyle (ssrContext) {\n if (disposed) return\n require(\"!!vue-style-loader!css-loader?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-0eaeaf66\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector?type=styles&index=0!./modal.vue\")\n}\nvar normalizeComponent = require(\"!../../node_modules/vue-loader/lib/component-normalizer\")\n/* script */\nexport * from \"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./modal.vue\"\nimport __vue_script__ from \"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./modal.vue\"\n/* template */\nimport __vue_template__ from \"!!../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-0eaeaf66\\\",\\\"hasScoped\\\":true,\\\"transformToRequire\\\":{\\\"video\\\":[\\\"src\\\",\\\"poster\\\"],\\\"source\\\":\\\"src\\\",\\\"img\\\":\\\"src\\\",\\\"image\\\":\\\"xlink:href\\\"},\\\"buble\\\":{\\\"transforms\\\":{}}}!../../node_modules/vue-loader/lib/selector?type=template&index=0!./modal.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = \"data-v-0eaeaf66\"\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_template__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\nComponent.options.__file = \"src/components/modal.vue\"\n\n/* hot reload */\nif (module.hot) {(function () {\n var hotAPI = require(\"vue-hot-reload-api\")\n hotAPI.install(require(\"vue\"), false)\n if (!hotAPI.compatible) return\n module.hot.accept()\n if (!module.hot.data) {\n hotAPI.createRecord(\"data-v-0eaeaf66\", Component.options)\n } else {\n hotAPI.reload(\"data-v-0eaeaf66\", Component.options)\n }\n module.hot.dispose(function (data) {\n disposed = true\n })\n})()}\n\nexport default Component.exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/components/modal.vue\n// module id = null\n// module chunks = ","<template>\n<div class = \"autocomplete-container\">\n <input\n ref = \"input\"\n @keydown.stop = \"hitEnter\"\n type = \"text\"\n @focus = \"showSuggestions = true\"\n @blur = \"showSuggestions = false\"\n v-model = \"typedText\"\n :placeholder = \"placeholder\"/>\n <transition name = \"fade\">\n <div v-if = \"showSuggestions\" class = \"autocomplete-suggestion-container\">\n <div\n @mousedown=\"selectSlice(item)\"\n class = \"autocomplete-suggestions\"\n :class = \"{active : ((highlightIndex % filteredArray.length) === index)}\"\n v-bind:key = \"index\"\n v-for = \"(item,index) in filteredArray\">\n {{ item }}\n </div>\n </div>\n </transition>\n</div>\n</template>\n\n<script>\nexport default {\n props: {\n placeholder: {\n type: String,\n default: 'Start typing to search ...'\n },\n rawarray: {\n type: Array,\n default: () => ([])\n },\n rendermax: {\n type: Number,\n default: 25\n }\n },\n data: () => ({\n showSuggestions: false,\n typedText: '',\n highlightIndex: 0\n }),\n methods: {\n selectSlice: function (item) {\n this.$emit('selectslice', item)\n },\n hitEnter: function () {\n switch (event.key) {\n case 'ArrowDown':\n this.highlightIndex += 1\n break\n case 'Escape':\n this.$refs.input.blur()\n break\n case 'ArrowUp':\n this.highlightIndex -= 1\n if (this.highlightIndex <= 0) this.highlightIndex += this.filteredArray.length\n break\n case 'Enter':\n const array = this.filteredArray.slice()\n if (array.length > 0) {\n this.typedText = ''\n const el = document.querySelector(':focus')\n if (el) el.blur()\n this.selectSlice(array[0])\n }\n break\n default:\n this.highlightIndex = 0\n break\n }\n }\n },\n computed: {\n rawArrayLowerCase: function () {\n return this.rawarray.map(item => item.toLowerCase())\n },\n typedTextLowerCase: function () {\n return this.typedText.toLowerCase()\n },\n filteredArray: function () {\n const regex = new RegExp(this.typedText, 'i')\n const completeMatch = this.rawarray.find(item => item.toLowerCase() === this.typedTextLowerCase)\n const othermatches = this.rawarray\n .filter(item => regex.test(item))\n .filter(item => item.toLowerCase() !== this.typedTextLowerCase)\n .filter((_, idx) => idx <= this.rendermax)\n return completeMatch\n ? [completeMatch].concat(othermatches.slice(0, othermatches.length >= this.rendermax ? othermatches.length - 1 : othermatches.length))\n : othermatches\n }\n }\n}\n</script>\n\n<style scoped>\ndiv.autocomplete-container\n{\n cursor:default;\n}\n\n.autocomplete-suggestions\n{\n width:100%;\n display:block;\n padding:0.1em 0.3em;\n transition: all 200ms;\n background-color:rgba(230,230,230,0.5);\n}\n\n.autocomplete-suggestions.active\n{\n background-color:rgba(230,230,230,0.95);\n}\n\n.autocomplete-suggestions:hover\n{\n background-color:rgba(230,230,230,0.95);\n}\n\ndiv.autocomplete-container:focus-within .autocomplete-suggestions\n{\n display: block;\n}\n\ndiv.autocomplete-suggestion-container\n{\n width: 100%;\n max-height:10em;\n overflow-y:auto;\n overflow-x:hidden;\n z-index:2;\n}\ninput[type=\"text\"]\n{\n width:100%;\n height:100%;\n z-index:1;\n}\n</style>\n\n\n\n// WEBPACK FOOTER //\n// src/components/autocomplete.vue","var render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n { staticClass: \"autocomplete-container\" },\n [\n _c(\"input\", {\n directives: [\n {\n name: \"model\",\n rawName: \"v-model\",\n value: _vm.typedText,\n expression: \"typedText\"\n }\n ],\n ref: \"input\",\n attrs: { type: \"text\", placeholder: _vm.placeholder },\n domProps: { value: _vm.typedText },\n on: {\n keydown: function($event) {\n $event.stopPropagation()\n return _vm.hitEnter($event)\n },\n focus: function($event) {\n _vm.showSuggestions = true\n },\n blur: function($event) {\n _vm.showSuggestions = false\n },\n input: function($event) {\n if ($event.target.composing) {\n return\n }\n _vm.typedText = $event.target.value\n }\n }\n }),\n _vm._v(\" \"),\n _c(\"transition\", { attrs: { name: \"fade\" } }, [\n _vm.showSuggestions\n ? _c(\n \"div\",\n { staticClass: \"autocomplete-suggestion-container\" },\n _vm._l(_vm.filteredArray, function(item, index) {\n return _c(\n \"div\",\n {\n key: index,\n staticClass: \"autocomplete-suggestions\",\n class: {\n active:\n _vm.highlightIndex % _vm.filteredArray.length === index\n },\n on: {\n mousedown: function($event) {\n _vm.selectSlice(item)\n }\n }\n },\n [_vm._v(\"\\n \" + _vm._s(item) + \"\\n \")]\n )\n })\n )\n : _vm._e()\n ])\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\nvar esExports = { render: render, staticRenderFns: staticRenderFns }\nexport default esExports\nif (module.hot) {\n module.hot.accept()\n if (module.hot.data) {\n require(\"vue-hot-reload-api\") .rerender(\"data-v-8351e810\", esExports)\n }\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-loader/lib/template-compiler?{\"id\":\"data-v-8351e810\",\"hasScoped\":true,\"transformToRequire\":{\"video\":[\"src\",\"poster\"],\"source\":\"src\",\"img\":\"src\",\"image\":\"xlink:href\"},\"buble\":{\"transforms\":{}}}!./node_modules/vue-loader/lib/selector.js?type=template&index=0!./src/components/autocomplete.vue\n// module id = null\n// module chunks = ","var disposed = false\nfunction injectStyle (ssrContext) {\n if (disposed) return\n require(\"!!vue-style-loader!css-loader?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-8351e810\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector?type=styles&index=0!./autocomplete.vue\")\n}\nvar normalizeComponent = require(\"!../../node_modules/vue-loader/lib/component-normalizer\")\n/* script */\nexport * from \"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./autocomplete.vue\"\nimport __vue_script__ from \"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./autocomplete.vue\"\n/* template */\nimport __vue_template__ from \"!!../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-8351e810\\\",\\\"hasScoped\\\":true,\\\"transformToRequire\\\":{\\\"video\\\":[\\\"src\\\",\\\"poster\\\"],\\\"source\\\":\\\"src\\\",\\\"img\\\":\\\"src\\\",\\\"image\\\":\\\"xlink:href\\\"},\\\"buble\\\":{\\\"transforms\\\":{}}}!../../node_modules/vue-loader/lib/selector?type=template&index=0!./autocomplete.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = \"data-v-8351e810\"\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_template__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\nComponent.options.__file = \"src/components/autocomplete.vue\"\n\n/* hot reload */\nif (module.hot) {(function () {\n var hotAPI = require(\"vue-hot-reload-api\")\n hotAPI.install(require(\"vue\"), false)\n if (!hotAPI.compatible) return\n module.hot.accept()\n if (!module.hot.data) {\n hotAPI.createRecord(\"data-v-8351e810\", Component.options)\n } else {\n hotAPI.reload(\"data-v-8351e810\", Component.options)\n }\n module.hot.dispose(function (data) {\n disposed = true\n })\n})()}\n\nexport default Component.exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/components/autocomplete.vue\n// module id = null\n// module chunks = ","<template>\n<div class = \"copy-field-root\">\n <input ref = \"inputEl\" readonly v-bind:value = \"value\" type = \"text\" />\n <div\n v-bind:hidden = \"!copyable\"\n @click.stop = \"copyToClipBoard\">{{ methodGetCopyText() }}\n </div>\n</div>\n</template>\n\n<script>\nexport default {\n props: {\n value: {\n type: String,\n default: 'default value'\n },\n copyable: {\n type: Boolean,\n default: true\n }\n },\n data: () => ({\n copiedFlag: false,\n timeoutRef: 0,\n copyBtnShown: false\n }),\n methods: {\n copyToClipBoard: function () {\n this.copiedFlag = true\n if (this.timeoutRef) {\n clearTimeout(this.timeoutRef)\n }\n setTimeout(() => {\n this.copiedFlag = false\n this.timeoutRef = 0\n }, 2000)\n\n this.$refs.inputEl.focus()\n this.$refs.inputEl.select()\n document.execCommand('copy', false)\n },\n methodGetCopyText: function () {\n return this.copiedFlag ? 'Copied!' : 'Copy'\n }\n }\n}\n</script>\n<style>\n.copy-field-root\n{\n width: 100%;\n white-space: nowrap;\n}\n\n.copy-field-root *\n{\n color:black\n}\n\n.copy-field-root > input\n{\n width : 100%;\n height:2.0em;\n display: inline-block;\n vertical-align : middle;\n box-sizing: border-box;\n position : relative;\n\n border : solid 1px rgba(128,128,128,0.6);\n z-index: 8;\n}\n\n.copy-field-root > div:not([hidden])\n{\n position : relative;\n z-index: 9;\n cursor:default;\n display: inline-block;\n box-sizing:border-box;\n margin : 0.2em;\n height : 1.6em;\n margin-left:-4em;\n font-size:100%;\n vertical-align : middle;\n text-align: center;\n font-size:0.9em;\n padding : 0.2em;\n\n color:rgba(0,0,0,0.8);\n border : solid 1px rgba(0,0,0,0.5);\n\n background-color:rgba(230,230,230,0.9);\n}\n\n.copy-field-root > div:hover\n{\n background-color:rgba(240,240,240,1.0);\n}\n</style>\n\n\n\n// WEBPACK FOOTER //\n// src/components/copyfield.vue","var render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { staticClass: \"copy-field-root\" }, [\n _c(\"input\", {\n ref: \"inputEl\",\n attrs: { readonly: \"\", type: \"text\" },\n domProps: { value: _vm.value }\n }),\n _vm._v(\" \"),\n _c(\n \"div\",\n {\n attrs: { hidden: !_vm.copyable },\n on: {\n click: function($event) {\n $event.stopPropagation()\n return _vm.copyToClipBoard($event)\n }\n }\n },\n [_vm._v(_vm._s(_vm.methodGetCopyText()) + \"\\n \")]\n )\n ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\nvar esExports = { render: render, staticRenderFns: staticRenderFns }\nexport default esExports\nif (module.hot) {\n module.hot.accept()\n if (module.hot.data) {\n require(\"vue-hot-reload-api\") .rerender(\"data-v-1d7c4045\", esExports)\n }\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-loader/lib/template-compiler?{\"id\":\"data-v-1d7c4045\",\"hasScoped\":false,\"transformToRequire\":{\"video\":[\"src\",\"poster\"],\"source\":\"src\",\"img\":\"src\",\"image\":\"xlink:href\"},\"buble\":{\"transforms\":{}}}!./node_modules/vue-loader/lib/selector.js?type=template&index=0!./src/components/copyfield.vue\n// module id = null\n// module chunks = ","var disposed = false\nfunction injectStyle (ssrContext) {\n if (disposed) return\n require(\"!!vue-style-loader!css-loader?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-1d7c4045\\\",\\\"scoped\\\":false,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector?type=styles&index=0!./copyfield.vue\")\n}\nvar normalizeComponent = require(\"!../../node_modules/vue-loader/lib/component-normalizer\")\n/* script */\nexport * from \"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./copyfield.vue\"\nimport __vue_script__ from \"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./copyfield.vue\"\n/* template */\nimport __vue_template__ from \"!!../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-1d7c4045\\\",\\\"hasScoped\\\":false,\\\"transformToRequire\\\":{\\\"video\\\":[\\\"src\\\",\\\"poster\\\"],\\\"source\\\":\\\"src\\\",\\\"img\\\":\\\"src\\\",\\\"image\\\":\\\"xlink:href\\\"},\\\"buble\\\":{\\\"transforms\\\":{}}}!../../node_modules/vue-loader/lib/selector?type=template&index=0!./copyfield.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_template__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\nComponent.options.__file = \"src/components/copyfield.vue\"\n\n/* hot reload */\nif (module.hot) {(function () {\n var hotAPI = require(\"vue-hot-reload-api\")\n hotAPI.install(require(\"vue\"), false)\n if (!hotAPI.compatible) return\n module.hot.accept()\n if (!module.hot.data) {\n hotAPI.createRecord(\"data-v-1d7c4045\", Component.options)\n } else {\n hotAPI.reload(\"data-v-1d7c4045\", Component.options)\n }\n module.hot.dispose(function (data) {\n disposed = true\n })\n})()}\n\nexport default Component.exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/components/copyfield.vue\n// module id = null\n// module chunks = ","<template>\n<div class = \"readmore-container\">\n <div :style = \"{ height : computedHeight }\" class = \"readmore-content\">\n <div ref = \"readmoreContentContainer\">\n <slot name = \"readmoreContent\"></slot>\n </div>\n </div>\n <div @click = \"toggle\" class = \"readmore-sliver\">\n <slot v-if = \"collapsed\" name = \"resizeSliverContentCollapsed\">\n </slot>\n <slot v-if = \"!collapsed\" name = \"resizeSliverContentShown\">\n </slot>\n </div>\n</div>\n</template>\n<script>\nexport default {\n props: {\n collapsedHeight: {\n type: Number,\n default: 25\n }\n },\n data: () => ({\n collapsed: {\n type: Boolean,\n default: true\n },\n actualHeight: {\n type: Number,\n default: 25\n }\n }),\n mounted: function () {\n this.actualHeight = this.$refs.readmoreContentContainer.clientHeight\n },\n methods: {\n toggle: function () {\n this.collapsed = !this.collapsed\n }\n },\n computed: {\n computedHeight: function () {\n return `${this.collapsed ? this.collapsedHeight : this.actualHeight}px`\n }\n }\n}\n</script>\n<style scoped>\n.readmore-content\n{\n transition: all 0.3s;\n overflow-y : hidden;\n}\n.readmore-sliver\n{\n min-height: 0.5em;\n transition: all 0.3s;\n background-color: rgba(128,128,128,0.2);\n}\n.readmore-sliver:hover\n{\n transform: translateY(-2px);\n background-color: rgba(128,128,128,0.4);\n}\n</style>\n\n\n\n// WEBPACK FOOTER //\n// src/components/readmore.vue","var render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\"div\", { staticClass: \"readmore-container\" }, [\n _c(\n \"div\",\n {\n staticClass: \"readmore-content\",\n style: { height: _vm.computedHeight }\n },\n [\n _c(\n \"div\",\n { ref: \"readmoreContentContainer\" },\n [_vm._t(\"readmoreContent\")],\n 2\n )\n ]\n ),\n _vm._v(\" \"),\n _c(\n \"div\",\n { staticClass: \"readmore-sliver\", on: { click: _vm.toggle } },\n [\n _vm.collapsed ? _vm._t(\"resizeSliverContentCollapsed\") : _vm._e(),\n _vm._v(\" \"),\n !_vm.collapsed ? _vm._t(\"resizeSliverContentShown\") : _vm._e()\n ],\n 2\n )\n ])\n}\nvar staticRenderFns = []\nrender._withStripped = true\nvar esExports = { render: render, staticRenderFns: staticRenderFns }\nexport default esExports\nif (module.hot) {\n module.hot.accept()\n if (module.hot.data) {\n require(\"vue-hot-reload-api\") .rerender(\"data-v-92448f0a\", esExports)\n }\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-loader/lib/template-compiler?{\"id\":\"data-v-92448f0a\",\"hasScoped\":true,\"transformToRequire\":{\"video\":[\"src\",\"poster\"],\"source\":\"src\",\"img\":\"src\",\"image\":\"xlink:href\"},\"buble\":{\"transforms\":{}}}!./node_modules/vue-loader/lib/selector.js?type=template&index=0!./src/components/readmore.vue\n// module id = null\n// module chunks = ","var disposed = false\nfunction injectStyle (ssrContext) {\n if (disposed) return\n require(\"!!vue-style-loader!css-loader?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-92448f0a\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector?type=styles&index=0!./readmore.vue\")\n}\nvar normalizeComponent = require(\"!../../node_modules/vue-loader/lib/component-normalizer\")\n/* script */\nexport * from \"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./readmore.vue\"\nimport __vue_script__ from \"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./readmore.vue\"\n/* template */\nimport __vue_template__ from \"!!../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-92448f0a\\\",\\\"hasScoped\\\":true,\\\"transformToRequire\\\":{\\\"video\\\":[\\\"src\\\",\\\"poster\\\"],\\\"source\\\":\\\"src\\\",\\\"img\\\":\\\"src\\\",\\\"image\\\":\\\"xlink:href\\\"},\\\"buble\\\":{\\\"transforms\\\":{}}}!../../node_modules/vue-loader/lib/selector?type=template&index=0!./readmore.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = \"data-v-92448f0a\"\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_template__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\nComponent.options.__file = \"src/components/readmore.vue\"\n\n/* hot reload */\nif (module.hot) {(function () {\n var hotAPI = require(\"vue-hot-reload-api\")\n hotAPI.install(require(\"vue\"), false)\n if (!hotAPI.compatible) return\n module.hot.accept()\n if (!module.hot.data) {\n hotAPI.createRecord(\"data-v-92448f0a\", Component.options)\n } else {\n hotAPI.reload(\"data-v-92448f0a\", Component.options)\n }\n module.hot.dispose(function (data) {\n disposed = true\n })\n})()}\n\nexport default Component.exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/components/readmore.vue\n// module id = null\n// module chunks = ","import Vue from 'vue'\n// import App from './App'\nimport Modal from './components/modal.vue'\nimport Pill from './components/pill.vue'\nimport AutoComplete from './components/autocomplete.vue'\nimport CopyField from './components/copyfield.vue'\nimport Readmore from './components/readmore.vue'\n\nVue.config.productionTip = false\n\n/* eslint-disable no-new */\n// new Vue({\n// el: '#app',\n// render: h => h(App)\n// })\nVue.component('vue-modal', Modal)\nVue.component('vue-pill', Pill)\nVue.component('vue-autocomplete', AutoComplete)\nVue.component('vue-copyfield', CopyField)\nVue.component('vue-readmore', Readmore)\n\n\n\n// WEBPACK FOOTER //\n// ./src/main.js","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(true);\n// imports\n\n\n// module\nexports.push([module.id, \"\\n.readmore-content[data-v-92448f0a]\\n{\\n -webkit-transition: all 0.3s;\\n transition: all 0.3s;\\n overflow-y : hidden;\\n}\\n.readmore-sliver[data-v-92448f0a]\\n{\\n min-height: 0.5em;\\n -webkit-transition: all 0.3s;\\n transition: all 0.3s;\\n background-color: rgba(128,128,128,0.2);\\n}\\n.readmore-sliver[data-v-92448f0a]:hover\\n{\\n -webkit-transform: translateY(-2px);\\n transform: translateY(-2px);\\n background-color: rgba(128,128,128,0.4);\\n}\\n\", \"\", {\"version\":3,\"sources\":[\"/home/xgui3783/dev/projects/vue-components/src/components/src/components/readmore.vue\"],\"names\":[],\"mappings\":\";AAiDA;;EAEA,6BAAA;EAAA,qBAAA;EACA,oBAAA;CACA;AACA;;EAEA,kBAAA;EACA,6BAAA;EAAA,qBAAA;EACA,wCAAA;CACA;AACA;;EAEA,oCAAA;UAAA,4BAAA;EACA,wCAAA;CACA\",\"file\":\"readmore.vue\",\"sourcesContent\":[\"<template>\\n<div class = \\\"readmore-container\\\">\\n <div :style = \\\"{ height : computedHeight }\\\" class = \\\"readmore-content\\\">\\n <div ref = \\\"readmoreContentContainer\\\">\\n <slot name = \\\"readmoreContent\\\"></slot>\\n </div>\\n </div>\\n <div @click = \\\"toggle\\\" class = \\\"readmore-sliver\\\">\\n <slot v-if = \\\"collapsed\\\" name = \\\"resizeSliverContentCollapsed\\\">\\n </slot>\\n <slot v-if = \\\"!collapsed\\\" name = \\\"resizeSliverContentShown\\\">\\n </slot>\\n </div>\\n</div>\\n</template>\\n<script>\\nexport default {\\n props: {\\n collapsedHeight: {\\n type: Number,\\n default: 25\\n }\\n },\\n data: () => ({\\n collapsed: {\\n type: Boolean,\\n default: true\\n },\\n actualHeight: {\\n type: Number,\\n default: 25\\n }\\n }),\\n mounted: function () {\\n this.actualHeight = this.$refs.readmoreContentContainer.clientHeight\\n },\\n methods: {\\n toggle: function () {\\n this.collapsed = !this.collapsed\\n }\\n },\\n computed: {\\n computedHeight: function () {\\n return `${this.collapsed ? this.collapsedHeight : this.actualHeight}px`\\n }\\n }\\n}\\n</script>\\n<style scoped>\\n.readmore-content\\n{\\n transition: all 0.3s;\\n overflow-y : hidden;\\n}\\n.readmore-sliver\\n{\\n min-height: 0.5em;\\n transition: all 0.3s;\\n background-color: rgba(128,128,128,0.2);\\n}\\n.readmore-sliver:hover\\n{\\n transform: translateY(-2px);\\n background-color: rgba(128,128,128,0.4);\\n}\\n</style>\\n\"],\"sourceRoot\":\"\"}]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/css-loader?{\"sourceMap\":true}!./node_modules/vue-loader/lib/style-compiler?{\"vue\":true,\"id\":\"data-v-92448f0a\",\"scoped\":true,\"hasInlineConfig\":false}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/readmore.vue\n// module id = R6Sg\n// module chunks = 0","<template>\n<div @click.stop.prevent = \"$emit('select-pill')\" class = \"v-pill-container\">\n <span class = \"v-pill-name\">{{ name }}</span>\n <span v-if = \"closable\" @click.stop.prevent = \"$emit('remove-pill')\" class = \"v-pill-remove\">×</span>\n</div>\n</template>\n\n<script>\nmodule.exports = {\n props: {\n name: {\n type: String,\n default: 'Untitled'\n },\n closable: {\n type: Boolean,\n default: true\n }\n }\n}\n</script>\n\n<style scoped>\ndiv.v-pill-container\n{\n display:inline-block;\n white-space: nowrap;\n margin:5px;\n padding:0.2em 0.6em;\n border-radius: 0.8em;\n}\n\ndiv.v-pill-container\n{\n cursor: default;\n transition: all 300ms;\n background-color:rgba(50,50,50,0.2);\n}\n\ndiv.v-pill-container:hover\n{\n background-color:rgba(150,150,150,0.2);\n}\n\nspan.v-pill-name\n{\n cursor: default;\n display:inline-block;\n}\nspan.v-pill-remove\n{\n cursor: default;\n display:inline-block;\n}\n\nspan.v-pill-remove:hover\n{\n font-weight: 900;\n color:rgba(200,30,30,1);\n}\n</style>\n\n\n\n// WEBPACK FOOTER //\n// src/components/pill.vue","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(true);\n// imports\n\n\n// module\nexports.push([module.id, \"\\ndiv.autocomplete-container[data-v-8351e810]\\n{\\n cursor:default;\\n}\\n.autocomplete-suggestions[data-v-8351e810]\\n{\\n width:100%;\\n display:block;\\n padding:0.1em 0.3em;\\n -webkit-transition: all 200ms;\\n transition: all 200ms;\\n background-color:rgba(230,230,230,0.5);\\n}\\n.autocomplete-suggestions.active[data-v-8351e810]\\n{\\n background-color:rgba(230,230,230,0.95);\\n}\\n.autocomplete-suggestions[data-v-8351e810]:hover\\n{\\n background-color:rgba(230,230,230,0.95);\\n}\\ndiv.autocomplete-container:focus-within .autocomplete-suggestions[data-v-8351e810]\\n{\\n display: block;\\n}\\ndiv.autocomplete-suggestion-container[data-v-8351e810]\\n{\\n width: 100%;\\n max-height:10em;\\n overflow-y:auto;\\n overflow-x:hidden;\\n z-index:2;\\n}\\ninput[type=\\\"text\\\"][data-v-8351e810]\\n{\\n width:100%;\\n height:100%;\\n z-index:1;\\n}\\n\", \"\", {\"version\":3,\"sources\":[\"/home/xgui3783/dev/projects/vue-components/src/components/src/components/autocomplete.vue\"],\"names\":[],\"mappings\":\";AAoGA;;EAEA,eAAA;CACA;AAEA;;EAEA,WAAA;EACA,cAAA;EACA,oBAAA;EACA,8BAAA;EAAA,sBAAA;EACA,uCAAA;CACA;AAEA;;EAEA,wCAAA;CACA;AAEA;;EAEA,wCAAA;CACA;AAEA;;EAEA,eAAA;CACA;AAEA;;EAEA,YAAA;EACA,gBAAA;EACA,gBAAA;EACA,kBAAA;EACA,UAAA;CACA;AACA;;EAEA,WAAA;EACA,YAAA;EACA,UAAA;CACA\",\"file\":\"autocomplete.vue\",\"sourcesContent\":[\"<template>\\n<div class = \\\"autocomplete-container\\\">\\n <input\\n ref = \\\"input\\\"\\n @keydown.stop = \\\"hitEnter\\\"\\n type = \\\"text\\\"\\n @focus = \\\"showSuggestions = true\\\"\\n @blur = \\\"showSuggestions = false\\\"\\n v-model = \\\"typedText\\\"\\n :placeholder = \\\"placeholder\\\"/>\\n <transition name = \\\"fade\\\">\\n <div v-if = \\\"showSuggestions\\\" class = \\\"autocomplete-suggestion-container\\\">\\n <div\\n @mousedown=\\\"selectSlice(item)\\\"\\n class = \\\"autocomplete-suggestions\\\"\\n :class = \\\"{active : ((highlightIndex % filteredArray.length) === index)}\\\"\\n v-bind:key = \\\"index\\\"\\n v-for = \\\"(item,index) in filteredArray\\\">\\n {{ item }}\\n </div>\\n </div>\\n </transition>\\n</div>\\n</template>\\n\\n<script>\\nexport default {\\n props: {\\n placeholder: {\\n type: String,\\n default: 'Start typing to search ...'\\n },\\n rawarray: {\\n type: Array,\\n default: () => ([])\\n },\\n rendermax: {\\n type: Number,\\n default: 25\\n }\\n },\\n data: () => ({\\n showSuggestions: false,\\n typedText: '',\\n highlightIndex: 0\\n }),\\n methods: {\\n selectSlice: function (item) {\\n this.$emit('selectslice', item)\\n },\\n hitEnter: function () {\\n switch (event.key) {\\n case 'ArrowDown':\\n this.highlightIndex += 1\\n break\\n case 'Escape':\\n this.$refs.input.blur()\\n break\\n case 'ArrowUp':\\n this.highlightIndex -= 1\\n if (this.highlightIndex <= 0) this.highlightIndex += this.filteredArray.length\\n break\\n case 'Enter':\\n const array = this.filteredArray.slice()\\n if (array.length > 0) {\\n this.typedText = ''\\n const el = document.querySelector(':focus')\\n if (el) el.blur()\\n this.selectSlice(array[0])\\n }\\n break\\n default:\\n this.highlightIndex = 0\\n break\\n }\\n }\\n },\\n computed: {\\n rawArrayLowerCase: function () {\\n return this.rawarray.map(item => item.toLowerCase())\\n },\\n typedTextLowerCase: function () {\\n return this.typedText.toLowerCase()\\n },\\n filteredArray: function () {\\n const regex = new RegExp(this.typedText, 'i')\\n const completeMatch = this.rawarray.find(item => item.toLowerCase() === this.typedTextLowerCase)\\n const othermatches = this.rawarray\\n .filter(item => regex.test(item))\\n .filter(item => item.toLowerCase() !== this.typedTextLowerCase)\\n .filter((_, idx) => idx <= this.rendermax)\\n return completeMatch\\n ? [completeMatch].concat(othermatches.slice(0, othermatches.length >= this.rendermax ? othermatches.length - 1 : othermatches.length))\\n : othermatches\\n }\\n }\\n}\\n</script>\\n\\n<style scoped>\\ndiv.autocomplete-container\\n{\\n cursor:default;\\n}\\n\\n.autocomplete-suggestions\\n{\\n width:100%;\\n display:block;\\n padding:0.1em 0.3em;\\n transition: all 200ms;\\n background-color:rgba(230,230,230,0.5);\\n}\\n\\n.autocomplete-suggestions.active\\n{\\n background-color:rgba(230,230,230,0.95);\\n}\\n\\n.autocomplete-suggestions:hover\\n{\\n background-color:rgba(230,230,230,0.95);\\n}\\n\\ndiv.autocomplete-container:focus-within .autocomplete-suggestions\\n{\\n display: block;\\n}\\n\\ndiv.autocomplete-suggestion-container\\n{\\n width: 100%;\\n max-height:10em;\\n overflow-y:auto;\\n overflow-x:hidden;\\n z-index:2;\\n}\\ninput[type=\\\"text\\\"]\\n{\\n width:100%;\\n height:100%;\\n z-index:1;\\n}\\n</style>\\n\"],\"sourceRoot\":\"\"}]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/css-loader?{\"sourceMap\":true}!./node_modules/vue-loader/lib/style-compiler?{\"vue\":true,\"id\":\"data-v-8351e810\",\"scoped\":true,\"hasInlineConfig\":false}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/autocomplete.vue\n// module id = RpWc\n// module chunks = 0","var render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n \"div\",\n {\n staticClass: \"v-pill-container\",\n on: {\n click: function($event) {\n $event.stopPropagation()\n $event.preventDefault()\n _vm.$emit(\"select-pill\")\n }\n }\n },\n [\n _c(\"span\", { staticClass: \"v-pill-name\" }, [_vm._v(_vm._s(_vm.name))]),\n _vm._v(\" \"),\n _vm.closable\n ? _c(\n \"span\",\n {\n staticClass: \"v-pill-remove\",\n on: {\n click: function($event) {\n $event.stopPropagation()\n $event.preventDefault()\n _vm.$emit(\"remove-pill\")\n }\n }\n },\n [_vm._v(\"×\")]\n )\n : _vm._e()\n ]\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\nvar esExports = { render: render, staticRenderFns: staticRenderFns }\nexport default esExports\nif (module.hot) {\n module.hot.accept()\n if (module.hot.data) {\n require(\"vue-hot-reload-api\") .rerender(\"data-v-94d8f66e\", esExports)\n }\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-loader/lib/template-compiler?{\"id\":\"data-v-94d8f66e\",\"hasScoped\":true,\"transformToRequire\":{\"video\":[\"src\",\"poster\"],\"source\":\"src\",\"img\":\"src\",\"image\":\"xlink:href\"},\"buble\":{\"transforms\":{}}}!./node_modules/vue-loader/lib/selector.js?type=template&index=0!./src/components/pill.vue\n// module id = ck25\n// module chunks = 0","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(true);\n// imports\n\n\n// module\nexports.push([module.id, \"\\n.copy-field-root\\n{\\n width: 100%;\\n white-space: nowrap;\\n}\\n.copy-field-root *\\n{\\n color:black\\n}\\n.copy-field-root > input\\n{\\n width : 100%;\\n height:2.0em;\\n display: inline-block;\\n vertical-align : middle;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n position : relative;\\n\\n border : solid 1px rgba(128,128,128,0.6);\\n z-index: 8;\\n}\\n.copy-field-root > div:not([hidden])\\n{\\n position : relative;\\n z-index: 9;\\n cursor:default;\\n display: inline-block;\\n -webkit-box-sizing:border-box;\\n box-sizing:border-box;\\n margin : 0.2em;\\n height : 1.6em;\\n margin-left:-4em;\\n font-size:100%;\\n vertical-align : middle;\\n text-align: center;\\n font-size:0.9em;\\n padding : 0.2em;\\n\\n color:rgba(0,0,0,0.8);\\n border : solid 1px rgba(0,0,0,0.5);\\n\\n background-color:rgba(230,230,230,0.9);\\n}\\n.copy-field-root > div:hover\\n{\\n background-color:rgba(240,240,240,1.0);\\n}\\n\", \"\", {\"version\":3,\"sources\":[\"/home/xgui3783/dev/projects/vue-components/src/components/src/components/copyfield.vue\"],\"names\":[],\"mappings\":\";AAiDA;;EAEA,YAAA;EACA,oBAAA;CACA;AAEA;;EAEA,WAAA;CACA;AAEA;;EAEA,aAAA;EACA,aAAA;EACA,sBAAA;EACA,wBAAA;EACA,+BAAA;UAAA,uBAAA;EACA,oBAAA;;EAEA,yCAAA;EACA,WAAA;CACA;AAEA;;EAEA,oBAAA;EACA,WAAA;EACA,eAAA;EACA,sBAAA;EACA,8BAAA;UAAA,sBAAA;EACA,eAAA;EACA,eAAA;EACA,iBAAA;EACA,eAAA;EACA,wBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;;EAEA,sBAAA;EACA,mCAAA;;EAEA,uCAAA;CACA;AAEA;;EAEA,uCAAA;CACA\",\"file\":\"copyfield.vue\",\"sourcesContent\":[\"<template>\\n<div class = \\\"copy-field-root\\\">\\n <input ref = \\\"inputEl\\\" readonly v-bind:value = \\\"value\\\" type = \\\"text\\\" />\\n <div\\n v-bind:hidden = \\\"!copyable\\\"\\n @click.stop = \\\"copyToClipBoard\\\">{{ methodGetCopyText() }}\\n </div>\\n</div>\\n</template>\\n\\n<script>\\nexport default {\\n props: {\\n value: {\\n type: String,\\n default: 'default value'\\n },\\n copyable: {\\n type: Boolean,\\n default: true\\n }\\n },\\n data: () => ({\\n copiedFlag: false,\\n timeoutRef: 0,\\n copyBtnShown: false\\n }),\\n methods: {\\n copyToClipBoard: function () {\\n this.copiedFlag = true\\n if (this.timeoutRef) {\\n clearTimeout(this.timeoutRef)\\n }\\n setTimeout(() => {\\n this.copiedFlag = false\\n this.timeoutRef = 0\\n }, 2000)\\n\\n this.$refs.inputEl.focus()\\n this.$refs.inputEl.select()\\n document.execCommand('copy', false)\\n },\\n methodGetCopyText: function () {\\n return this.copiedFlag ? 'Copied!' : 'Copy'\\n }\\n }\\n}\\n</script>\\n<style>\\n.copy-field-root\\n{\\n width: 100%;\\n white-space: nowrap;\\n}\\n\\n.copy-field-root *\\n{\\n color:black\\n}\\n\\n.copy-field-root > input\\n{\\n width : 100%;\\n height:2.0em;\\n display: inline-block;\\n vertical-align : middle;\\n box-sizing: border-box;\\n position : relative;\\n\\n border : solid 1px rgba(128,128,128,0.6);\\n z-index: 8;\\n}\\n\\n.copy-field-root > div:not([hidden])\\n{\\n position : relative;\\n z-index: 9;\\n cursor:default;\\n display: inline-block;\\n box-sizing:border-box;\\n margin : 0.2em;\\n height : 1.6em;\\n margin-left:-4em;\\n font-size:100%;\\n vertical-align : middle;\\n text-align: center;\\n font-size:0.9em;\\n padding : 0.2em;\\n\\n color:rgba(0,0,0,0.8);\\n border : solid 1px rgba(0,0,0,0.5);\\n\\n background-color:rgba(230,230,230,0.9);\\n}\\n\\n.copy-field-root > div:hover\\n{\\n background-color:rgba(240,240,240,1.0);\\n}\\n</style>\\n\"],\"sourceRoot\":\"\"}]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/css-loader?{\"sourceMap\":true}!./node_modules/vue-loader/lib/style-compiler?{\"vue\":true,\"id\":\"data-v-1d7c4045\",\"scoped\":false,\"hasInlineConfig\":false}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/copyfield.vue\n// module id = fKQA\n// module chunks = 0","module.exports = Vue;\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"Vue\"\n// module id = lRwf\n// module chunks = 0","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(true);\n// imports\n\n\n// module\nexports.push([module.id, \"\\n.v-modal-container[data-v-0eaeaf66]\\n{\\n top: 0;\\n width:100%;\\n height:100%;\\n position : absolute;\\n z-index:999;\\n}\\n.v-modal-screen[data-v-0eaeaf66]\\n{\\n top : 0;\\n position : absolute;\\n width:100%;\\n height:100%;\\n background-color:rgba(30,30,30,0.2);\\n}\\n.v-modal-content-container[data-v-0eaeaf66]\\n{\\n top : 0;\\n position : absolute;\\n display : -webkit-box;\\n display : -ms-flexbox;\\n display : flex;\\n -webkit-box-align: center;\\n -ms-flex-align: center;\\n align-items: center;\\n -ms-flex-line-pack: center;\\n align-content: center;\\n -webkit-box-pack: center;\\n -ms-flex-pack: center;\\n justify-content: center;\\n\\n pointer-events: none;\\n}\\n.v-modal-content[data-v-0eaeaf66]\\n{\\n -webkit-box-flex : 0;\\n -ms-flex : 0 0 auto;\\n flex : 0 0 auto;\\n pointer-events: all;\\n}\\n\\n\", \"\", {\"version\":3,\"sources\":[\"/home/xgui3783/dev/projects/vue-components/src/components/src/components/modal.vue\"],\"names\":[],\"mappings\":\";AA4DA;;EAEA,OAAA;EACA,WAAA;EACA,YAAA;EACA,oBAAA;EACA,YAAA;CACA;AACA;;EAEA,QAAA;EACA,oBAAA;EACA,WAAA;EACA,YAAA;EACA,oCAAA;CACA;AAEA;;EAEA,QAAA;EACA,oBAAA;EACA,sBAAA;EAAA,sBAAA;EAAA,eAAA;EACA,0BAAA;MAAA,uBAAA;UAAA,oBAAA;EACA,2BAAA;MAAA,sBAAA;EACA,yBAAA;MAAA,sBAAA;UAAA,wBAAA;;EAEA,qBAAA;CACA;AACA;;EAEA,qBAAA;MAAA,oBAAA;UAAA,gBAAA;EACA,oBAAA;CACA\",\"file\":\"modal.vue\",\"sourcesContent\":[\"<template>\\n<div>\\n <div class = \\\"v-modal-container\\\">\\n <div\\n ref = \\\"screen\\\"\\n v-on:click = \\\"$emit('close-modal')\\\"\\n class = \\\"v-modal-screen\\\">\\n </div>\\n <div\\n v-bind:style = \\\"{top:contentContainerTop,left:contentContainerLeft,width:contentContainerWidth,height:contentContainerHeight,}\\\"\\n class = \\\"v-modal-content-container\\\">\\n <div\\n ref = \\\"content\\\"\\n class = \\\"v-modal-content\\\">\\n <div class = \\\"v-modal-header\\\">\\n <slot name = \\\"v-modal-header\\\">\\n </slot>\\n </div>\\n <div class = \\\"v-modal-body\\\">\\n <slot name = \\\"v-modal-body\\\">\\n </slot>\\n </div>\\n <div class = \\\"v-modal-footer\\\">\\n <slot name = \\\"v-modal-footer\\\">\\n </slot>\\n </div>\\n </div>\\n </div>\\n </div>\\n</div>\\n</template>\\n<script>\\nexport default {\\n props: {\\n top: Number,\\n left: Number\\n },\\n data: () => ({\\n show: {\\n type: Boolean,\\n default: false\\n }\\n }),\\n computed: {\\n contentContainerLeft: function () {\\n return this.top && this.left && this.$refs.content && this.$refs.screen ? Math.min(this.left, this.$refs.screen.clientWidth - this.$refs.content.clientWidth) + 'px' : `0px`\\n },\\n contentContainerTop: function () {\\n return this.top && this.left && this.$refs.content && this.$refs.screen ? Math.min(this.top, this.$refs.screen.clientHeight - this.$refs.content.clientHeight) + 'px' : `0px`\\n },\\n contentContainerWidth: function () {\\n return this.top && this.left && this.$refs.content && this.$refs.screen ? 'auto' : `100%`\\n },\\n contentContainerHeight: function () {\\n return this.top && this.left && this.$refs.content && this.$refs.screen ? 'auto' : `100%`\\n }\\n }\\n}\\n</script>\\n<style scoped>\\n.v-modal-container\\n{\\n top: 0;\\n width:100%;\\n height:100%;\\n position : absolute;\\n z-index:999;\\n}\\n.v-modal-screen\\n{\\n top : 0;\\n position : absolute;\\n width:100%;\\n height:100%;\\n background-color:rgba(30,30,30,0.2);\\n}\\n\\n.v-modal-content-container\\n{\\n top : 0;\\n position : absolute;\\n display : flex;\\n align-items: center;\\n align-content: center;\\n justify-content: center;\\n\\n pointer-events: none;\\n}\\n.v-modal-content\\n{\\n flex : 0 0 auto;\\n pointer-events: all;\\n}\\n\\n</style>\\n\"],\"sourceRoot\":\"\"}]);\n\n// exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/css-loader?{\"sourceMap\":true}!./node_modules/vue-loader/lib/style-compiler?{\"vue\":true,\"id\":\"data-v-0eaeaf66\",\"scoped\":true,\"hasInlineConfig\":false}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/modal.vue\n// module id = n8WV\n// module chunks = 0","// style-loader: Adds some css to the DOM by adding a <style> tag\n\n// load the styles\nvar content = require(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-94d8f66e\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./pill.vue\");\nif(typeof content === 'string') content = [[module.id, content, '']];\nif(content.locals) module.exports = content.locals;\n// add the styles to the DOM\nvar update = require(\"!../../node_modules/vue-style-loader/lib/addStylesClient.js\")(\"12958e8c\", content, false, {});\n// Hot Module Replacement\nif(module.hot) {\n // When the styles change, update the <style> tags\n if(!content.locals) {\n module.hot.accept(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-94d8f66e\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./pill.vue\", function() {\n var newContent = require(\"!!../../node_modules/css-loader/index.js?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index.js?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-94d8f66e\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector.js?type=styles&index=0!./pill.vue\");\n if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n update(newContent);\n });\n }\n // When the module is disposed, remove the <style> tags\n module.hot.dispose(function() { update(); });\n}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-style-loader!./node_modules/css-loader?{\"sourceMap\":true}!./node_modules/vue-loader/lib/style-compiler?{\"vue\":true,\"id\":\"data-v-94d8f66e\",\"scoped\":true,\"hasInlineConfig\":false}!./node_modules/vue-loader/lib/selector.js?type=styles&index=0!./src/components/pill.vue\n// module id = nFT+\n// module chunks = 0","var disposed = false\nfunction injectStyle (ssrContext) {\n if (disposed) return\n require(\"!!vue-style-loader!css-loader?{\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index?{\\\"vue\\\":true,\\\"id\\\":\\\"data-v-94d8f66e\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector?type=styles&index=0!./pill.vue\")\n}\nvar normalizeComponent = require(\"!../../node_modules/vue-loader/lib/component-normalizer\")\n/* script */\nexport * from \"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./pill.vue\"\nimport __vue_script__ from \"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./pill.vue\"\n/* template */\nimport __vue_template__ from \"!!../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-94d8f66e\\\",\\\"hasScoped\\\":true,\\\"transformToRequire\\\":{\\\"video\\\":[\\\"src\\\",\\\"poster\\\"],\\\"source\\\":\\\"src\\\",\\\"img\\\":\\\"src\\\",\\\"image\\\":\\\"xlink:href\\\"},\\\"buble\\\":{\\\"transforms\\\":{}}}!../../node_modules/vue-loader/lib/selector?type=template&index=0!./pill.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = \"data-v-94d8f66e\"\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_template__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\nComponent.options.__file = \"src/components/pill.vue\"\n\n/* hot reload */\nif (module.hot) {(function () {\n var hotAPI = require(\"vue-hot-reload-api\")\n hotAPI.install(require(\"vue\"), false)\n if (!hotAPI.compatible) return\n module.hot.accept()\n if (!module.hot.data) {\n hotAPI.createRecord(\"data-v-94d8f66e\", Component.options)\n } else {\n hotAPI.reload(\"data-v-94d8f66e\", Component.options)\n }\n module.hot.dispose(function (data) {\n disposed = true\n })\n})()}\n\nexport default Component.exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/components/pill.vue\n// module id = u0wG\n// module chunks = 0"],"sourceRoot":""} \ No newline at end of file diff --git a/src/plugin_examples/newWebJugex/manifest.js b/src/plugin_examples/newWebJugex/manifest.js new file mode 100644 index 000000000..1f3bed735 --- /dev/null +++ b/src/plugin_examples/newWebJugex/manifest.js @@ -0,0 +1,2 @@ +!function(r){var n=window.webpackJsonp;window.webpackJsonp=function(e,u,c){for(var f,i,p,a=0,l=[];a<e.length;a++)i=e[a],o[i]&&l.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(n&&n(e,u,c);l.length;)l.shift()();if(c)for(a=0;a<c.length;a++)p=t(t.s=c[a]);return p};var e={},o={2:0};function t(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=r,t.c=e,t.d=function(r,n,e){t.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:e})},t.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return t.d(n,"a",n),n},t.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},t.p="",t.oe=function(r){throw console.error(r),r}}([]); +//# sourceMappingURL=manifest.js.map \ No newline at end of file diff --git a/src/plugin_examples/newWebJugex/manifest.js.map b/src/plugin_examples/newWebJugex/manifest.js.map new file mode 100644 index 000000000..0bd52be68 --- /dev/null +++ b/src/plugin_examples/newWebJugex/manifest.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/bootstrap 5735c67e542cf68358f5"],"names":["parentJsonpFunction","window","chunkIds","moreModules","executeModules","moduleId","chunkId","result","i","resolves","length","installedChunks","push","Object","prototype","hasOwnProperty","call","modules","shift","__webpack_require__","s","installedModules","2","exports","module","l","m","c","d","name","getter","o","defineProperty","configurable","enumerable","get","n","__esModule","object","property","p","oe","err","console","error"],"mappings":"aACA,IAAAA,EAAAC,OAAA,aACAA,OAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,IAAAC,EAAAC,EAAAC,EAAAC,EAAA,EAAAC,KACQD,EAAAN,EAAAQ,OAAoBF,IAC5BF,EAAAJ,EAAAM,GACAG,EAAAL,IACAG,EAAAG,KAAAD,EAAAL,GAAA,IAEAK,EAAAL,GAAA,EAEA,IAAAD,KAAAF,EACAU,OAAAC,UAAAC,eAAAC,KAAAb,EAAAE,KACAY,EAAAZ,GAAAF,EAAAE,IAIA,IADAL,KAAAE,EAAAC,EAAAC,GACAK,EAAAC,QACAD,EAAAS,OAAAT,GAEA,GAAAL,EACA,IAAAI,EAAA,EAAYA,EAAAJ,EAAAM,OAA2BF,IACvCD,EAAAY,IAAAC,EAAAhB,EAAAI,IAGA,OAAAD,GAIA,IAAAc,KAGAV,GACAW,EAAA,GAIA,SAAAH,EAAAd,GAGA,GAAAgB,EAAAhB,GACA,OAAAgB,EAAAhB,GAAAkB,QAGA,IAAAC,EAAAH,EAAAhB,IACAG,EAAAH,EACAoB,GAAA,EACAF,YAUA,OANAN,EAAAZ,GAAAW,KAAAQ,EAAAD,QAAAC,IAAAD,QAAAJ,GAGAK,EAAAC,GAAA,EAGAD,EAAAD,QAKAJ,EAAAO,EAAAT,EAGAE,EAAAQ,EAAAN,EAGAF,EAAAS,EAAA,SAAAL,EAAAM,EAAAC,GACAX,EAAAY,EAAAR,EAAAM,IACAhB,OAAAmB,eAAAT,EAAAM,GACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMAX,EAAAiB,EAAA,SAAAZ,GACA,IAAAM,EAAAN,KAAAa,WACA,WAA2B,OAAAb,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAL,EAAAS,EAAAE,EAAA,IAAAA,GACAA,GAIAX,EAAAY,EAAA,SAAAO,EAAAC,GAAsD,OAAA1B,OAAAC,UAAAC,eAAAC,KAAAsB,EAAAC,IAGtDpB,EAAAqB,EAAA,GAGArB,EAAAsB,GAAA,SAAAC,GAA8D,MAApBC,QAAAC,MAAAF,GAAoBA","file":"static/js/manifest.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n \t\tif(executeModules) {\n \t\t\tfor(i=0; i < executeModules.length; i++) {\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n \t\t\t}\n \t\t}\n \t\treturn result;\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// objects to store loaded and loading chunks\n \tvar installedChunks = {\n \t\t2: 0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 5735c67e542cf68358f5"],"sourceRoot":""} \ No newline at end of file diff --git a/src/plugin_examples/newWebJugex/manifest.json b/src/plugin_examples/newWebJugex/manifest.json new file mode 100644 index 000000000..afb5f7c49 --- /dev/null +++ b/src/plugin_examples/newWebJugex/manifest.json @@ -0,0 +1,6 @@ +{ + "name" : "fzj.xg.webjugex", + "type" : "plugin", + "templateURL" : "http://localhost:10080/newWebJugex/template.html", + "scriptURL" : "http://localhost:10080/newWebJugex/script.js" +} \ No newline at end of file diff --git a/src/plugin_examples/newWebJugex/script.js b/src/plugin_examples/newWebJugex/script.js new file mode 100644 index 000000000..95046c5f1 --- /dev/null +++ b/src/plugin_examples/newWebJugex/script.js @@ -0,0 +1,228 @@ +(() => { + + const backendRoot = `http://medpc055.ime.kfa-juelich.de:8005` + const srcRoot = 'http://localhost:10080/newWebJugex' + + /* so that on shutdown, we could unload these libraries */ + const onshutdownCB = [] + const loadedExternalLibraries = [] + const subscriptions = [] + + const loadExternalJsLibrary = (url) => new Promise((resolve,reject) => { + const el = document.createElement('script') + el.setAttribute('src',url) + el.onload = () => { + loadedExternalLibraries.push(el) + resolve() + } + el.onerror = () => reject() + document.head.appendChild(el) + }) + + const parseCoordToFile = (json) => { + return Object.keys(json).reduce((acc, curr) => { + const newRows = json[curr].map(item => { + return `${curr},${item.xyz.join(',')},${item.winsorzed_mean.join(',')}` + }) + return acc.concat(newRows) + }, []).join('\n') + } + + const parsePvalToFile = (json) => { + return Object.keys(json).map(key => `${key},${json[key]}`).join('\n') + } + + const jugexResponseParser = (json) => { + const pval = json[1] + const coord = json[0] + const stringCoordFile = parseCoordToFile(coord) + const stringPvalFile = parsePvalToFile(pval) + const stringTitledCoordFile = Object.keys(pval).join(',').concat('\n').concat(stringCoordFile) + return { + pval : stringPvalFile, + coord : stringTitledCoordFile + } + } + + interactiveViewer.pluginControl.loadExternalLibraries(['vue@2.5.16']) + .then(() => loadExternalJsLibrary(`${srcRoot}/manifest.js`)) + .then(() => loadExternalJsLibrary(`${srcRoot}/vendor.js`)) + .then(() => loadExternalJsLibrary(`${srcRoot}/app.js`)) + .then(() => { + + const controller = new Vue({ + el: '#fzj\\.xg\\.newWebJugex\\.container', + props: { + regionNameToPMapURLMap: { + type: Map, + default: () => new Map() + } + }, + data: { + allgenes: [], + chosengenes: [], + roi1: '', + roi2: '', + regions: [], + singleProbeMode:true, + simpleMode:true, + ignoreCustomProbe:false, + nPermutations:1000 + }, + methods: { + removeGene: function (gene) { + this.chosengenes = this.chosengenes.filter(g => g !== gene) + }, + startAnalysis: function () { + const body = { + area1: { + name: this.roi1, + PMapURL: this.regionNameToPMapURLMap.get(this.roi1) + }, + mode: false, + area2: { + name: this.roi2, + PMapURL: this.regionNameToPMapURLMap.get(this.roi2) + }, + hemisphere: 'left', + selectedGenes: this.chosengenes, + threshold: '0.2' + } + + this.$emit('start-analysis', Object.assign({}, body)) + } + }, + computed: { + placeholderTextRoi1: function () { + return this.roi1 === '' ? 'Start typing to search ...': this.roi1 + }, + placeholderTextRoi2: function () { + return this.roi2 === '' ? 'Start typing to search ...': this.roi2 + }, + getAllgenes: function () { + return this.allgenes + } + }, + mounted: function () { + fetch(backendRoot) + .then(res => res.json()) + .then(array => this.allgenes = array) + .catch(console.warn) + } + }) + + interactiveViewer.metadata.datasetsBSubject.subscribe(array => + controller.regionNameToPMapURLMap = new Map(array + .filter(item => item.type === 'Cytoarchitectonic Probabilistic Map' + && typeof item.regionName !== 'undefined' + && item.regionName.constructor === Array + && item.regionName.length > 0 + && typeof item.files !== 'undefined' + && item.files.constructor === Array + && item.files.length > 0 + && typeof item.files[0].url !== 'undefined') + .map(item => [item.regionName[0].regionName, item.files[0].url]))) + + controller.regions = Array.from(interactiveViewer.metadata.regionsLabelIndexMap.values()) + .map(item=>item.name) + + const normaliseToTwoDigit = (input) => `${input.toString().length > 1 ? '' : '0'}${input.toString()}` + + Vue.component('fzj-xg-newwebjugex-analysis-card',{ + template: ` + <div class = "panel panel-default"> + <div + @click = "showbody = !showbody" + class = "panel-header btn btn-default btn-block"> + <span + v-if = "status"> + Analysis complete. {{ dateString }} + </span> + <div + v-if = "!status"> + <div class = "fzj.xg.newWebJugex.spinner">•</div> + <div>Analysing</div> + </div> + <span + @click.stop = "$emit('remove-card')" + class = "pull-right close"> + × + </span> + </div> + <div + v-if = "showbody" + class = "panel-body"> + <div v-if = "error"> + {{ error }} + </div> + <div v-else-if = "pvaldata && coorddata"> + <a download = "pval.csv" :href = "'data:text/csv;charset=utf-8,' + pvaldata">download pvals</a><br /> + <a download = "coord.csv" :href = "'data:text/csv;charset=utf-8,' + coorddata">download coord data</a> + </div> + <div v-else> + We are still working on on analysing your data ... + </div> + </div> + </div> + `, + props: { + querydata: { + type: Object, + default: () => ({}) + } + }, + data: () => ({ + status: false, + showbody: false, + datenow : new Date(), + error : null, + pvaldata : null, + coorddata : null + }), + computed: { + dateString: function () { + return `${this.datenow.getFullYear().toString()}${normaliseToTwoDigit(this.datenow.getMonth() + 1)}${normaliseToTwoDigit(this.datenow.getDate())}_${normaliseToTwoDigit(this.datenow.getHours())}${normaliseToTwoDigit(this.datenow.getMinutes())}` + } + }, + mounted: function () { + fetch(`${backendRoot}/jugex`,{ + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(this.querydata) + }) + .then(res=>res.json()) + .then(json => { + this.status = true + const rjson = jugexResponseParser(json) + this.pvaldata = rjson.pval + this.coorddata = rjson.coord + }) + .catch(e => { + this.status = true + this.error = JSON.stringify(e) + }) + } + }) + + const result = new Vue({ + el: '#fzj\\.xg\\.newWebJugex\\.result', + data: { + analyses: [] + }, + methods: { + addAnalysis: function (json) { + this.analyses.push(json) + }, + removeAnalysis: function (index) { + this.analyses.splice(index, 1) + } + } + }) + + controller.$on('start-analysis', (data) => { + result.addAnalysis(data) + }) + }) +})() \ No newline at end of file diff --git a/src/plugin_examples/newWebJugex/template.html b/src/plugin_examples/newWebJugex/template.html new file mode 100644 index 000000000..f820797a2 --- /dev/null +++ b/src/plugin_examples/newWebJugex/template.html @@ -0,0 +1,248 @@ +<div v-cloak id = "fzj.xg.newWebJugex.container"> + <vue-readmore + :collapsed-height = "40"> + <template slot = "readmoreContent"> + <small id = "fzj.xg.newWebJugex.desc"> + Find a set of differentially expressed genes between two user defined volumes of interest based on JuBrain maps. <br /> + The tool downloads expression values of user specified sets of genes from Allen Brain API.<br /> + Then, it uses zscores to find which genes are expressed differentially between the user specified regions of interests.<br /> + After the analysis is finished, the genes and their calculated p values are displayed. There is also an option of downloading the gene names and their p values<br /> + and the roi coordinates used in the analysis. + Please select two regions of interest, and at least one gene : + </small> + </template> + <template slot = "resizeSliverContentCollapsed"> + <div class = "text-center"> + <i class = "glyphicon glyphicon-chevron-down"></i> + </div> + </template> + <template slot = "resizeSliverContentShown"> + <div class = "text-center"> + <i class = "glyphicon glyphicon-chevron-up"></i> + </div> + </template> + </vue-readmore> + + <div class="fzj.xg.newWebJugex.spacer"></div> + + <div class="btn-group"> + <div + @click = "simpleMode = true" + :class = "{'btn-active': simpleMode === true}" + class = "btn btn-default"> + Simple + </div> + <div + @click = "simpleMode = false" + :class = "{'btn-active': simpleMode === false}" + class = "btn btn-default"> + Advanced + </div> + </div> + + <div class="fzj.xg.newWebJugex.spacer"></div> + + <div style = "z-index:5" class="input-group"> + <div class="input-group-addon"> + ROI1: + </div> + <vue-autocomplete + ref = "roi1" + @selectslice = "roi1 = $event" + class = "form-control fzj.xg.newWebJugex.vueAutocompleteFormControl" + :rawarray = "regions" + :placeholder = "placeholderTextRoi1"> + + </vue-autocomplete> + </div> + <div style = "z-index:4" class="input-group"> + <div class="input-group-addon"> + ROI2: + </div> + <vue-autocomplete + ref = "roi2" + @selectslice = "roi2 = $event" + class = "form-control fzj.xg.newWebJugex.vueAutocompleteFormControl" + :rawarray = "regions" + :placeholder = "placeholderTextRoi2"> + + </vue-autocomplete> + </div> + + <div class="fzj.xg.newWebJugex.spacer"></div> + + <div style = "z-index:3" class = "input-group"> + <vue-autocomplete + ref = "genelist" + @selectslice = "chosengenes.push( $event );$refs.genelist.$refs.input.focus()" + class = "form-control fzj.xg.newWebJugex.vueAutocompleteFormControl" + :rawarray = "getAllgenes" + :placeholder = "'Search for genes of interest ...'"> + + </vue-autocomplete> + + <div class = "input-group-btn"> + <div webjugex-tooltip = "accepts a comma delimited utf-8 encoded file" class = "btn btn-default fzj.xg.newWebJugex.geneBtns"> + Import + </div> + </div> + <div class = "input-group-btn"> + <div webjugex-tooltip = "saves the gene list as a comma delimited, utf8 encoded csv file" class = "btn btn-default fzj.xg.newWebJugex.geneBtns"> + Export + </div> + </div> + + </div> + + <vue-pill + class = "fzj.xg.newWebJugex.pill" + @remove-pill = "removeGene(item)" + v-for = "(item,index) in chosengenes" + :key = "index" + :name = "item"> + </vue-pill> + + <div class="fzj.xg.newWebJugex.spacer"></div> + + <div + @click = "singleProbeMode = !singleProbeMode" + class = "btn btn-default" + :class = "{'btn-active': singleProbeMode === true}"> + <small> + Single Probe Mode + </small> + </div> + + <div + @click = "ignoreCustomProbe = !ignoreCustomProbe" + class = "btn btn-default" + :class = "{'btn-active': ignoreCustomProbe === true}"> + <small> + Ignore Custom Probe + </small> + </div> + + <div class="fzj.xg.newWebJugex.spacer"></div> + + <div + @click = "startAnalysis" + class="btn btn-default btn-block"> + Start Differential Analysis + </div> + +</div> +<div v-cloak id = "fzj.xg.newWebJugex.result"> + <fzj-xg-newwebjugex-analysis-card + class = "fzj.xg.newWebJugex.analysisCard.container" + @remove-card = "removeAnalysis(index)" + :querydata = "item" + :key = "index" + v-for = "(item, index) in analyses"> + + </fzj-xg-newwebjugex-analysis-card> +</div> +<div class = "fzj.xg.newWebJugex.padding"></div> +<style> +[v-cloak] +{ + display:none; +} +#fzj\.xg\.newWebJugex\.container +{ + padding: 0.5em; +} +#fzj\.xg\.newWebJugex\.desc +{ + display:block; +} +.fzj\.xg\.newWebJugex\.autocomplete +{ + border : 1px rgba(0,0,0,0.1) solid; + width:10em; + padding:1em; + box-sizing: border-box; + position:absolute; +} + +.fzj\.xg\.newWebJugex\.autocomplete input +{ + width:100%; +} + +.fzj\.xg\.newWebJugex\.vueAutocompleteFormControl +{ + padding:0; +} +.fzj\.xg\.newWebJugex\.padding +{ + height:10em; +} + +.fzj\.xg\.newWebJugex\.spacer +{ + height: 0.5em; +} + +.fzj\.xg\.newWebJugex\.geneBtns +{ + height:34px; +} + +#fzj\.xg\.newWebJugex\.container [webjugex-tooltip] +{ + position: relative; +} + +#fzj\.xg\.newWebJugex\.container [webjugex-tooltip]:after +{ + content: attr(webjugex-tooltip); + position: absolute; + top: 3em; + right: 0; + color:white; + background-color:rgba(0,0,0,0.7); + width: 10em; + white-space: normal; + display: inline-block; + padding: 0.2em; + pointer-events: none; + transition: all 0.2s; + opacity: 0; +} + +#fzj\.xg\.newWebJugex\.container [webjugex-tooltip]:hover:after +{ + opacity: 1; +} + +#fzj\.xg\.newWebJugex\.container .btn-active +{ + color:rgba(255, 255, 255, 1.0); + text-shadow: 1px 0 0 rgba(0, 255, 0, 0.15), + -1px 0 0 rgba(0, 255, 0, 0.15), + 0 1px 0 rgba(0, 255, 0, 0.15), + 0 -1px 0 rgba(0, 255, 0, 0.15); +} + +#fzj\.xg\.newWebJugex\.result +{ + padding: 0.5em; +} + +#fzj\.xg\.newWebJugex\.result .fzj\.xg\.newWebJugex\.spinner +{ + animation: slidein 0.7s ease-in-out 0s infinite both; +} + +@keyframes slidein { + 0% { transform: translateX(0px); } + 50% { transform: translateX(10px); } + 100% { transform: translateX(0px); } +} + + +.fzj\.xg\.newWebJugex\.analysisCard\.container +{ + margin-bottom: 0; +} +</style> \ No newline at end of file diff --git a/src/plugin_examples/newWebJugex/vendor.js b/src/plugin_examples/newWebJugex/vendor.js new file mode 100644 index 000000000..5fb83edbb --- /dev/null +++ b/src/plugin_examples/newWebJugex/vendor.js @@ -0,0 +1,2 @@ +webpackJsonp([1],{"FZ+f":function(e,t){e.exports=function(e){var t=[];return t.toString=function(){return this.map(function(t){var n=function(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var o=(i=r,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(i))))+" */"),s=r.sources.map(function(e){return"/*# sourceURL="+r.sourceRoot+e+" */"});return[n].concat(s).concat([o]).join("\n")}var i;return[n].join("\n")}(t,e);return t[2]?"@media "+t[2]+"{"+n+"}":n}).join("")},t.i=function(e,n){"string"==typeof e&&(e=[[null,e,""]]);for(var r={},o=0;o<this.length;o++){var s=this[o][0];"number"==typeof s&&(r[s]=!0)}for(o=0;o<e.length;o++){var i=e[o];"number"==typeof i[0]&&r[i[0]]||(n&&!i[2]?i[2]=n:n&&(i[2]="("+i[2]+") and ("+n+")"),t.push(i))}},t}},"VU/8":function(e,t){e.exports=function(e,t,n,r,o,s){var i,a=e=e||{},u=typeof e.default;"object"!==u&&"function"!==u||(i=e,a=e.default);var c,d="function"==typeof a?a.options:a;if(t&&(d.render=t.render,d.staticRenderFns=t.staticRenderFns,d._compiled=!0),n&&(d.functional=!0),o&&(d._scopeId=o),s?(c=function(e){(e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),r&&r.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(s)},d._ssrRegister=c):r&&(c=r),c){var f=d.functional,p=f?d.render:d.beforeCreate;f?(d._injectStyles=c,d.render=function(e,t){return c.call(t),p(e,t)}):d.beforeCreate=p?[].concat(p,c):[c]}return{esModule:i,exports:a,options:d}}},rjj0:function(e,t,n){var r="undefined"!=typeof document;if("undefined"!=typeof DEBUG&&DEBUG&&!r)throw new Error("vue-style-loader cannot be used in a non-browser environment. Use { target: 'node' } in your Webpack config to indicate a server-rendering environment.");var o=n("tTVk"),s={},i=r&&(document.head||document.getElementsByTagName("head")[0]),a=null,u=0,c=!1,d=function(){},f=null,p="data-vue-ssr-id",l="undefined"!=typeof navigator&&/msie [6-9]\b/.test(navigator.userAgent.toLowerCase());function h(e){for(var t=0;t<e.length;t++){var n=e[t],r=s[n.id];if(r){r.refs++;for(var o=0;o<r.parts.length;o++)r.parts[o](n.parts[o]);for(;o<n.parts.length;o++)r.parts.push(g(n.parts[o]));r.parts.length>n.parts.length&&(r.parts.length=n.parts.length)}else{var i=[];for(o=0;o<n.parts.length;o++)i.push(g(n.parts[o]));s[n.id]={id:n.id,refs:1,parts:i}}}}function v(){var e=document.createElement("style");return e.type="text/css",i.appendChild(e),e}function g(e){var t,n,r=document.querySelector("style["+p+'~="'+e.id+'"]');if(r){if(c)return d;r.parentNode.removeChild(r)}if(l){var o=u++;r=a||(a=v()),t=b.bind(null,r,o,!1),n=b.bind(null,r,o,!0)}else r=v(),t=function(e,t){var n=t.css,r=t.media,o=t.sourceMap;r&&e.setAttribute("media",r);f.ssrId&&e.setAttribute(p,t.id);o&&(n+="\n/*# sourceURL="+o.sources[0]+" */",n+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(o))))+" */");if(e.styleSheet)e.styleSheet.cssText=n;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(n))}}.bind(null,r),n=function(){r.parentNode.removeChild(r)};return t(e),function(r){if(r){if(r.css===e.css&&r.media===e.media&&r.sourceMap===e.sourceMap)return;t(e=r)}else n()}}e.exports=function(e,t,n,r){c=n,f=r||{};var i=o(e,t);return h(i),function(t){for(var n=[],r=0;r<i.length;r++){var a=i[r];(u=s[a.id]).refs--,n.push(u)}t?h(i=o(e,t)):i=[];for(r=0;r<n.length;r++){var u;if(0===(u=n[r]).refs){for(var c=0;c<u.parts.length;c++)u.parts[c]();delete s[u.id]}}}};var m,y=(m=[],function(e,t){return m[e]=t,m.filter(Boolean).join("\n")});function b(e,t,n,r){var o=n?"":r.css;if(e.styleSheet)e.styleSheet.cssText=y(t,o);else{var s=document.createTextNode(o),i=e.childNodes;i[t]&&e.removeChild(i[t]),i.length?e.insertBefore(s,i[t]):e.appendChild(s)}}},tTVk:function(e,t){e.exports=function(e,t){for(var n=[],r={},o=0;o<t.length;o++){var s=t[o],i=s[0],a={id:e+":"+o,css:s[1],media:s[2],sourceMap:s[3]};r[i]?r[i].parts.push(a):n.push(r[i]={id:i,parts:[a]})}return n}}}); +//# sourceMappingURL=vendor.js.map \ No newline at end of file diff --git a/src/plugin_examples/newWebJugex/vendor.js.map b/src/plugin_examples/newWebJugex/vendor.js.map new file mode 100644 index 000000000..a131d0fce --- /dev/null +++ b/src/plugin_examples/newWebJugex/vendor.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./node_modules/css-loader/lib/css-base.js","webpack:///./node_modules/vue-loader/lib/component-normalizer.js","webpack:///./node_modules/vue-style-loader/lib/addStylesClient.js","webpack:///./node_modules/vue-style-loader/lib/listToStyles.js"],"names":["module","exports","useSourceMap","list","toString","this","map","item","content","cssMapping","btoa","sourceMapping","sourceMap","unescape","encodeURIComponent","JSON","stringify","sourceURLs","sources","source","sourceRoot","concat","join","cssWithMappingToString","i","modules","mediaQuery","alreadyImportedModules","length","id","push","rawScriptExports","compiledTemplate","functionalTemplate","injectStyles","scopeId","moduleIdentifier","esModule","scriptExports","type","default","hook","options","render","staticRenderFns","_compiled","functional","_scopeId","context","$vnode","ssrContext","parent","__VUE_SSR_CONTEXT__","call","_registeredComponents","add","_ssrRegister","existing","beforeCreate","_injectStyles","h","hasDocument","document","DEBUG","Error","listToStyles","__webpack_require__","stylesInDom","head","getElementsByTagName","singletonElement","singletonCounter","isProduction","noop","ssrIdKey","isOldIE","navigator","test","userAgent","toLowerCase","addStylesToDom","styles","domStyle","refs","j","parts","addStyle","createStyleElement","styleElement","createElement","appendChild","obj","update","remove","querySelector","parentNode","removeChild","styleIndex","applyToSingletonTag","bind","css","media","setAttribute","ssrId","styleSheet","cssText","firstChild","createTextNode","newObj","parentId","_isProduction","_options","newList","mayRemove","textStore","replaceText","index","replacement","filter","Boolean","cssNode","childNodes","insertBefore","newStyles","part"],"mappings":"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","file":"static/js/vendor.js","sourcesContent":["/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\nmodule.exports = function(useSourceMap) {\n\tvar list = [];\n\n\t// return the list of modules as css string\n\tlist.toString = function toString() {\n\t\treturn this.map(function (item) {\n\t\t\tvar content = cssWithMappingToString(item, useSourceMap);\n\t\t\tif(item[2]) {\n\t\t\t\treturn \"@media \" + item[2] + \"{\" + content + \"}\";\n\t\t\t} else {\n\t\t\t\treturn content;\n\t\t\t}\n\t\t}).join(\"\");\n\t};\n\n\t// import a list of modules into the list\n\tlist.i = function(modules, mediaQuery) {\n\t\tif(typeof modules === \"string\")\n\t\t\tmodules = [[null, modules, \"\"]];\n\t\tvar alreadyImportedModules = {};\n\t\tfor(var i = 0; i < this.length; i++) {\n\t\t\tvar id = this[i][0];\n\t\t\tif(typeof id === \"number\")\n\t\t\t\talreadyImportedModules[id] = true;\n\t\t}\n\t\tfor(i = 0; i < modules.length; i++) {\n\t\t\tvar item = modules[i];\n\t\t\t// skip already imported module\n\t\t\t// this implementation is not 100% perfect for weird media query combinations\n\t\t\t// when a module is imported multiple times with different media queries.\n\t\t\t// I hope this will never occur (Hey this way we have smaller bundles)\n\t\t\tif(typeof item[0] !== \"number\" || !alreadyImportedModules[item[0]]) {\n\t\t\t\tif(mediaQuery && !item[2]) {\n\t\t\t\t\titem[2] = mediaQuery;\n\t\t\t\t} else if(mediaQuery) {\n\t\t\t\t\titem[2] = \"(\" + item[2] + \") and (\" + mediaQuery + \")\";\n\t\t\t\t}\n\t\t\t\tlist.push(item);\n\t\t\t}\n\t\t}\n\t};\n\treturn list;\n};\n\nfunction cssWithMappingToString(item, useSourceMap) {\n\tvar content = item[1] || '';\n\tvar cssMapping = item[3];\n\tif (!cssMapping) {\n\t\treturn content;\n\t}\n\n\tif (useSourceMap && typeof btoa === 'function') {\n\t\tvar sourceMapping = toComment(cssMapping);\n\t\tvar sourceURLs = cssMapping.sources.map(function (source) {\n\t\t\treturn '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'\n\t\t});\n\n\t\treturn [content].concat(sourceURLs).concat([sourceMapping]).join('\\n');\n\t}\n\n\treturn [content].join('\\n');\n}\n\n// Adapted from convert-source-map (MIT)\nfunction toComment(sourceMap) {\n\t// eslint-disable-next-line no-undef\n\tvar base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\n\tvar data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;\n\n\treturn '/*# ' + data + ' */';\n}\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/css-loader/lib/css-base.js\n// module id = FZ+f\n// module chunks = 1","/* globals __VUE_SSR_CONTEXT__ */\n\n// IMPORTANT: Do NOT use ES2015 features in this file.\n// This module is a runtime utility for cleaner component module output and will\n// be included in the final webpack user bundle.\n\nmodule.exports = function normalizeComponent (\n rawScriptExports,\n compiledTemplate,\n functionalTemplate,\n injectStyles,\n scopeId,\n moduleIdentifier /* server only */\n) {\n var esModule\n var scriptExports = rawScriptExports = rawScriptExports || {}\n\n // ES6 modules interop\n var type = typeof rawScriptExports.default\n if (type === 'object' || type === 'function') {\n esModule = rawScriptExports\n scriptExports = rawScriptExports.default\n }\n\n // Vue.extend constructor export interop\n var options = typeof scriptExports === 'function'\n ? scriptExports.options\n : scriptExports\n\n // render functions\n if (compiledTemplate) {\n options.render = compiledTemplate.render\n options.staticRenderFns = compiledTemplate.staticRenderFns\n options._compiled = true\n }\n\n // functional template\n if (functionalTemplate) {\n options.functional = true\n }\n\n // scopedId\n if (scopeId) {\n options._scopeId = scopeId\n }\n\n var hook\n if (moduleIdentifier) { // server build\n hook = function (context) {\n // 2.3 injection\n context =\n context || // cached call\n (this.$vnode && this.$vnode.ssrContext) || // stateful\n (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional\n // 2.2 with runInNewContext: true\n if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') {\n context = __VUE_SSR_CONTEXT__\n }\n // inject component styles\n if (injectStyles) {\n injectStyles.call(this, context)\n }\n // register component module identifier for async chunk inferrence\n if (context && context._registeredComponents) {\n context._registeredComponents.add(moduleIdentifier)\n }\n }\n // used by ssr in case component is cached and beforeCreate\n // never gets called\n options._ssrRegister = hook\n } else if (injectStyles) {\n hook = injectStyles\n }\n\n if (hook) {\n var functional = options.functional\n var existing = functional\n ? options.render\n : options.beforeCreate\n\n if (!functional) {\n // inject component registration as beforeCreate hook\n options.beforeCreate = existing\n ? [].concat(existing, hook)\n : [hook]\n } else {\n // for template-only hot-reload because in that case the render fn doesn't\n // go through the normalizer\n options._injectStyles = hook\n // register for functioal component in vue file\n options.render = function renderWithStyleInjection (h, context) {\n hook.call(context)\n return existing(h, context)\n }\n }\n }\n\n return {\n esModule: esModule,\n exports: scriptExports,\n options: options\n }\n}\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-loader/lib/component-normalizer.js\n// module id = VU/8\n// module chunks = 1","/*\n MIT License http://www.opensource.org/licenses/mit-license.php\n Author Tobias Koppers @sokra\n Modified by Evan You @yyx990803\n*/\n\nvar hasDocument = typeof document !== 'undefined'\n\nif (typeof DEBUG !== 'undefined' && DEBUG) {\n if (!hasDocument) {\n throw new Error(\n 'vue-style-loader cannot be used in a non-browser environment. ' +\n \"Use { target: 'node' } in your Webpack config to indicate a server-rendering environment.\"\n ) }\n}\n\nvar listToStyles = require('./listToStyles')\n\n/*\ntype StyleObject = {\n id: number;\n parts: Array<StyleObjectPart>\n}\n\ntype StyleObjectPart = {\n css: string;\n media: string;\n sourceMap: ?string\n}\n*/\n\nvar stylesInDom = {/*\n [id: number]: {\n id: number,\n refs: number,\n parts: Array<(obj?: StyleObjectPart) => void>\n }\n*/}\n\nvar head = hasDocument && (document.head || document.getElementsByTagName('head')[0])\nvar singletonElement = null\nvar singletonCounter = 0\nvar isProduction = false\nvar noop = function () {}\nvar options = null\nvar ssrIdKey = 'data-vue-ssr-id'\n\n// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>\n// tags it will allow on a page\nvar isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase())\n\nmodule.exports = function (parentId, list, _isProduction, _options) {\n isProduction = _isProduction\n\n options = _options || {}\n\n var styles = listToStyles(parentId, list)\n addStylesToDom(styles)\n\n return function update (newList) {\n var mayRemove = []\n for (var i = 0; i < styles.length; i++) {\n var item = styles[i]\n var domStyle = stylesInDom[item.id]\n domStyle.refs--\n mayRemove.push(domStyle)\n }\n if (newList) {\n styles = listToStyles(parentId, newList)\n addStylesToDom(styles)\n } else {\n styles = []\n }\n for (var i = 0; i < mayRemove.length; i++) {\n var domStyle = mayRemove[i]\n if (domStyle.refs === 0) {\n for (var j = 0; j < domStyle.parts.length; j++) {\n domStyle.parts[j]()\n }\n delete stylesInDom[domStyle.id]\n }\n }\n }\n}\n\nfunction addStylesToDom (styles /* Array<StyleObject> */) {\n for (var i = 0; i < styles.length; i++) {\n var item = styles[i]\n var domStyle = stylesInDom[item.id]\n if (domStyle) {\n domStyle.refs++\n for (var j = 0; j < domStyle.parts.length; j++) {\n domStyle.parts[j](item.parts[j])\n }\n for (; j < item.parts.length; j++) {\n domStyle.parts.push(addStyle(item.parts[j]))\n }\n if (domStyle.parts.length > item.parts.length) {\n domStyle.parts.length = item.parts.length\n }\n } else {\n var parts = []\n for (var j = 0; j < item.parts.length; j++) {\n parts.push(addStyle(item.parts[j]))\n }\n stylesInDom[item.id] = { id: item.id, refs: 1, parts: parts }\n }\n }\n}\n\nfunction createStyleElement () {\n var styleElement = document.createElement('style')\n styleElement.type = 'text/css'\n head.appendChild(styleElement)\n return styleElement\n}\n\nfunction addStyle (obj /* StyleObjectPart */) {\n var update, remove\n var styleElement = document.querySelector('style[' + ssrIdKey + '~=\"' + obj.id + '\"]')\n\n if (styleElement) {\n if (isProduction) {\n // has SSR styles and in production mode.\n // simply do nothing.\n return noop\n } else {\n // has SSR styles but in dev mode.\n // for some reason Chrome can't handle source map in server-rendered\n // style tags - source maps in <style> only works if the style tag is\n // created and inserted dynamically. So we remove the server rendered\n // styles and inject new ones.\n styleElement.parentNode.removeChild(styleElement)\n }\n }\n\n if (isOldIE) {\n // use singleton mode for IE9.\n var styleIndex = singletonCounter++\n styleElement = singletonElement || (singletonElement = createStyleElement())\n update = applyToSingletonTag.bind(null, styleElement, styleIndex, false)\n remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true)\n } else {\n // use multi-style-tag mode in all other cases\n styleElement = createStyleElement()\n update = applyToTag.bind(null, styleElement)\n remove = function () {\n styleElement.parentNode.removeChild(styleElement)\n }\n }\n\n update(obj)\n\n return function updateStyle (newObj /* StyleObjectPart */) {\n if (newObj) {\n if (newObj.css === obj.css &&\n newObj.media === obj.media &&\n newObj.sourceMap === obj.sourceMap) {\n return\n }\n update(obj = newObj)\n } else {\n remove()\n }\n }\n}\n\nvar replaceText = (function () {\n var textStore = []\n\n return function (index, replacement) {\n textStore[index] = replacement\n return textStore.filter(Boolean).join('\\n')\n }\n})()\n\nfunction applyToSingletonTag (styleElement, index, remove, obj) {\n var css = remove ? '' : obj.css\n\n if (styleElement.styleSheet) {\n styleElement.styleSheet.cssText = replaceText(index, css)\n } else {\n var cssNode = document.createTextNode(css)\n var childNodes = styleElement.childNodes\n if (childNodes[index]) styleElement.removeChild(childNodes[index])\n if (childNodes.length) {\n styleElement.insertBefore(cssNode, childNodes[index])\n } else {\n styleElement.appendChild(cssNode)\n }\n }\n}\n\nfunction applyToTag (styleElement, obj) {\n var css = obj.css\n var media = obj.media\n var sourceMap = obj.sourceMap\n\n if (media) {\n styleElement.setAttribute('media', media)\n }\n if (options.ssrId) {\n styleElement.setAttribute(ssrIdKey, obj.id)\n }\n\n if (sourceMap) {\n // https://developer.chrome.com/devtools/docs/javascript-debugging\n // this makes source maps inside style tags work properly in Chrome\n css += '\\n/*# sourceURL=' + sourceMap.sources[0] + ' */'\n // http://stackoverflow.com/a/26603875\n css += '\\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + ' */'\n }\n\n if (styleElement.styleSheet) {\n styleElement.styleSheet.cssText = css\n } else {\n while (styleElement.firstChild) {\n styleElement.removeChild(styleElement.firstChild)\n }\n styleElement.appendChild(document.createTextNode(css))\n }\n}\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-style-loader/lib/addStylesClient.js\n// module id = rjj0\n// module chunks = 1","/**\n * Translates the list format produced by css-loader into something\n * easier to manipulate.\n */\nmodule.exports = function listToStyles (parentId, list) {\n var styles = []\n var newStyles = {}\n for (var i = 0; i < list.length; i++) {\n var item = list[i]\n var id = item[0]\n var css = item[1]\n var media = item[2]\n var sourceMap = item[3]\n var part = {\n id: parentId + ':' + i,\n css: css,\n media: media,\n sourceMap: sourceMap\n }\n if (!newStyles[id]) {\n styles.push(newStyles[id] = { id: id, parts: [part] })\n } else {\n newStyles[id].parts.push(part)\n }\n }\n return styles\n}\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./node_modules/vue-style-loader/lib/listToStyles.js\n// module id = tTVk\n// module chunks = 1"],"sourceRoot":""} \ No newline at end of file diff --git a/src/plugin_examples/plugin_api.md b/src/plugin_examples/plugin_api.md index 1ea94a644..bbf95aeca 100644 --- a/src/plugin_examples/plugin_api.md +++ b/src/plugin_examples/plugin_api.md @@ -124,7 +124,7 @@ window.interactiveViewer - *loadExternalLibraries([LIBRARY_NAME_1,LIBRARY_NAME_2])* Function that loads external libraries. Pass the name of the libraries as an Array of string, and returns a Promise. When promise resolves, the libraries are loaded. **n.b.** while unlikely, there is a possibility that multiple requests to load external libraries in quick succession can cause the promise to resolve before the library is actually loaded. ```js - const currentlySupportedLibraries = ['jquery2','jquery3','webcomponentsLite','react16','reactdom16'] + const currentlySupportedLibraries = ['jquery@2','jquery@3','webcomponentsLite@1.1.0','react@16','reactdom@16','vue@2.5.16'] window.interactivewViewer.loadExternalLibraries(currentlySupportedLibraries) .then(()=>{ diff --git a/src/res/css/plugin_styles.css b/src/res/css/plugin_styles.css index 3fbdf3457..e2c75f3ba 100644 --- a/src/res/css/plugin_styles.css +++ b/src/res/css/plugin_styles.css @@ -23,6 +23,12 @@ box-shadow : rgba(5, 5, 5, 0.25) 0px 4px 6px 0px; } +[plugincontainer] .form-control +{ + background:none; + border:none; +} + /* colour */ [darktheme="true"] [plugincontainer] .btn, [darktheme="true"] [plugincontainer] .input-group-addon, @@ -30,6 +36,18 @@ [darktheme="true"] [plugincontainer] .panel { background-color:rgba(80,80,80,0.8); - color:white; + color:rgba(255,255,255,0.8); } +[darktheme="true"] [plugincontainer] hr +{ + border-color:rgba(100,100,100,0.5); +} + +[darktheme="true"] [plugincontainer] .btn.btn-active +{ + background-color:rgba(65,65,65,0.8); + transform: translateY(2px); + color:rgba(255,255,255,1.0); + box-shadow: inset 0 2px 2px -2px rgba(0,0,0,0.2); +} \ No newline at end of file diff --git a/src/ui/nehubaContainer/nehubaContainer.component.ts b/src/ui/nehubaContainer/nehubaContainer.component.ts index cc6ca1b4e..df92d5321 100644 --- a/src/ui/nehubaContainer/nehubaContainer.component.ts +++ b/src/ui/nehubaContainer/nehubaContainer.component.ts @@ -4,7 +4,6 @@ import { Store, select } from "@ngrx/store"; import { ViewerStateInterface, safeFilter, SELECT_REGIONS, getLabelIndexMap, DataEntry, CHANGE_NAVIGATION, isDefined, MOUSE_OVER_SEGMENT } from "../../services/stateStore.service"; import { Observable, Subscription, fromEvent, combineLatest, merge } from "rxjs"; import { filter,map, take, scan, debounceTime, distinctUntilChanged, switchMap } from "rxjs/operators"; -import * as export_nehuba from 'export_nehuba' import { AtlasViewerAPIServices } from "../../atlasViewer/atlasViewer.apiService.service"; import { timedValues } from "../../util/generator"; @@ -142,12 +141,10 @@ export class NehubaContainer implements OnInit,OnDestroy,AfterViewInit{ distinctUntilChanged() ) - /* patch NG */ - this.patchNG() - /* each time a new viewer is initialised, take the first event to get the translation function */ this.newViewer$.pipe( - switchMap(()=>fromEvent(this.elementRef.nativeElement,'sliceRenderEvent').pipe( + switchMap(() => fromEvent(this.elementRef.nativeElement, 'sliceRenderEvent') + .pipe( scan((acc:Event[],event:Event)=>{ const target = (event as Event).target as HTMLElement const key = target.offsetLeft < 5 && target.offsetTop < 5 ? @@ -286,37 +283,6 @@ export class NehubaContainer implements OnInit,OnDestroy,AfterViewInit{ spatialData.highlight = false } - private patchNG(){ - - const { LayerManager, UrlHashBinding } = export_nehuba.getNgPatchableObj() - - UrlHashBinding.prototype.setUrlHash = ()=>{ - // console.log('seturl hash') - // console.log('setting url hash') - } - - UrlHashBinding.prototype.updateFromUrlHash = ()=>{ - // console.log('update hash binding') - } - - /* TODO find a more permanent fix to disable double click */ - LayerManager.prototype.invokeAction = (arg) => { - const region = this.regionsLabelIndexMap.get(this.nehubaViewer.mouseOverSegment) - // const foundRegion = INTERACTIVE_VIEWER.viewerHandle.mouseOverNehuba.getValue().foundRegion - if(arg=='select'&& region ){ - this.selectedRegionIndexSet.has(region.labelIndex) ? - this.store.dispatch({ - type : SELECT_REGIONS, - selectRegions : [...this.selectedRegionIndexSet].filter(idx=>idx!==region.labelIndex).map(idx=>this.regionsLabelIndexMap.get(idx)) - }) : - this.store.dispatch({ - type : SELECT_REGIONS, - selectRegions : [...this.selectedRegionIndexSet].map(idx=>this.regionsLabelIndexMap.get(idx)).concat(region) - }) - } - } - } - private handleParcellation(parcellation:any){ this.regionsLabelIndexMap = getLabelIndexMap(parcellation.regions) this.nehubaViewer.regionsLabelIndexMap = this.regionsLabelIndexMap @@ -376,6 +342,20 @@ export class NehubaContainer implements OnInit,OnDestroy,AfterViewInit{ this.nehubaViewer.mouseoverSegmentEmitter.subscribe(this.handleEmittedMouseoverSegment.bind(this)) ) + this.nehubaViewerSubscriptions.push( + this.nehubaViewer.regionSelectionEmitter.subscribe(region => { + this.selectedRegionIndexSet.has(region.labelIndex) ? + this.store.dispatch({ + type : SELECT_REGIONS, + selectRegions : [...this.selectedRegionIndexSet].filter(idx=>idx!==region.labelIndex).map(idx=>this.regionsLabelIndexMap.get(idx)) + }) : + this.store.dispatch({ + type : SELECT_REGIONS, + selectRegions : [...this.selectedRegionIndexSet].map(idx=>this.regionsLabelIndexMap.get(idx)).concat(region) + }) + }) + ) + this.setupViewerHandleApi() } diff --git a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts b/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts index 6163d3e1e..6dab59b59 100644 --- a/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts +++ b/src/ui/nehubaContainer/nehubaViewer/nehubaViewer.component.ts @@ -15,6 +15,7 @@ export class NehubaViewerUnit implements AfterViewInit,OnDestroy{ @Output() debouncedViewerPositionChange : EventEmitter<any> = new EventEmitter() @Output() mouseoverSegmentEmitter : EventEmitter<any | number | null> = new EventEmitter() + @Output() regionSelectionEmitter : EventEmitter<any> = new EventEmitter() /* only used to set initial navigation state */ initNav : any @@ -46,7 +47,7 @@ export class NehubaViewerUnit implements AfterViewInit,OnDestroy{ ] constructor(public elementRef:ElementRef){ - + this.patchNG() } private _parcellationId : string @@ -104,6 +105,28 @@ export class NehubaViewerUnit implements AfterViewInit,OnDestroy{ }) } + private patchNG(){ + + const { LayerManager, UrlHashBinding } = export_nehuba.getNgPatchableObj() + + UrlHashBinding.prototype.setUrlHash = () => { + // console.log('seturl hash') + // console.log('setting url hash') + } + + UrlHashBinding.prototype.updateFromUrlHash = () => { + // console.log('update hash binding') + } + + /* TODO find a more permanent fix to disable double click */ + LayerManager.prototype.invokeAction = (arg) => { + const region = this.regionsLabelIndexMap.get(this.mouseOverSegment) + if (arg === 'select' && region) { + this.regionSelectionEmitter.emit(region) + } + } + } + private filterLayers(l:any,layerObj:any):boolean{ return Object.keys(layerObj).length == 0 && layerObj.constructor == Object ? true : -- GitLab