Vue - PE block ideas

common template for frame

by Ben Clayton

HTML

<script src="https://unpkg.com/vue"></script>

<div style="border:1px solid red;font-size:12px;">
Header
</div>

<div id="page-editor">
  <div>
  
    <holo-htmltext v-bind:properties='blocks[0]'></holo-htmltext>

    <holo-htmltext v-bind:properties='blocks[0]'></holo-htmltext>

    <holo-newpicture v-bind:properties='blocks[1]'></holo-newpicture>

    <holo-group-wrapper v-bind:properties='blocks[2]'>
    
        <holo-newpicture v-bind:properties='blocks[1]'></holo-newpicture>
        <holo-newpicture v-bind:properties='blocks[1]'></holo-newpicture>
        <holo-newpicture v-bind:properties='blocks[1]'></holo-newpicture>
    
    </holo-group-wrapper>


</div>
 
</div>
<hr>

<script id="vue-tmpl-block-frame" type="text/x-template">
  <div ref="blockref" :data-block="block" v-bind:class="outerclasses()" >
		<div v-bind:class="innerclasses()" 
    		@click.stop="toggleselected">
        <div class="btncollapse" @click.stop="togglecollapse">V</div>
        <div class="title">{{block.type}} (class:{{block.class }})</div>
    </div>
		<div class="inner" v-if="!collapsed">
    	<slot></slot>
    </div>
    
</div>
</script>



<script id="vue-tmpl-newpicture" type="text/x-template">
	<holo-block-frame v-bind:block="properties">
  	<img :src="properties.picture" />
  </holo-block-frame>
</script>

<script id="vue-tmpl-group-wrapper" type="text/x-template">
	<holo-block-frame v-bind:block="properties">
  	<slot></slot>
  </holo-block-frame>
</script>

<script id="vue-tmpl-htmltext" type="text/x-template">
	<holo-block-frame v-bind:block="properties">
  	<h1 v-bindhtml="properties.text" contenteditable=true></h1>
  </holo-block-frame>
</script>

CSS

body {
	    font-size: 12px;
}

.text {
	font-size: 24px;
}

.block {
  background-color: #FEEEAA;
}
.block.selected {
  background-color: #A020FF;
}
.btncollapse  {
  width: 30px;
  display: inline-block;
  text-align: center;
}
.closed .btncollapse {
  transform: rotate(-90deg);
  transform-origin: 50% 50%;
}
.title {
  display: inline-block;
  text-align: center;
  width: 80%;
  }
  
  .blk_wrapper {
    border: 1px solid gray;
  }
  
.inner {
  padding: 10px;
}

JavaScript

//---------------------------------------------------------

class base{
	constructor(){
		this.selected=false;
	}
}

class picture extends base {
	constructor(){
  	super();
  	this.type = 'picture';
  	this.picture = "//holograph.digital/infxpageedit/img/default.gif";
		this.class = 'fred,bert';
	}
}


class htmltext extends base{
	constructor(){
  	super();
  	this.type = "htmltext";
  	this.text = "Heading...";
		this.class = 'fred,harry';
	}
}


class groupwrapper extends base{
	constructor(){
  	super();
  	this.type = "groupwrapper";
		this.class = 'sid,sam';
	}
}

//============================================================
Vue.directive('bindhtml', {
  bind: function (el, binding, vnode) {
    var select = $(el);
    select
      .html(binding.value)
      .trigger('change')
      .on('keyup', function () {
        var bits = binding.expression.split('.');
        var path = vnode.context;
        var i=0;
        while (i < bits.length -1) {
        	path = path[bits[i++]];
        }
        if ( typeof path[bits[i]] != 'undefined' ) {
          path[bits[i]] = select.html();     
        }
				vnode.context.$emit('change')
      })
    },
	update: function (el, binding, vnode) {
    if ( el.innerHTML != binding.value ){
    	// this damages the cursor position, a bit of a pain !!!!
    	el.innerHTML =binding.value
    }
  }
});

Vue.component('holo-block-frame', {
  template: "#vue-tmpl-block-frame",
  props: ['block'],
  data: function(){return {collapsed:false} },
  methods: {
  	outerclasses : function(){
  		var classes = {blk_wrapper:true,collapsed:this.collapsed,selected:this.block.selected};
      classes[this.block.type] = true;
      return classes;
    },
    innerclasses : function(){
  		var classes = {block:true,open:!this.collapsed,closed:this.collapsed,selected:this.block.selected};
      classes['blk_' + this.block.type] = true;
      return classes;
    },
		togglecollapse : function (e) {
    	this.collapsed = ! this.collapsed;
   ...