Vue - CSS Property Component

Property control for CSS dimensions (px/%/em/vw/ch etc)

by Ben Clayton

HTML

<script src="https://unpkg.com/vue"></script>
<div id="property-dialog"></div>


<hr>

<script id="tmpl-css-prop-dim" type="text/x-template">
  <div class="control">
    	{{ label() }} 
      <input class="number" v-model="number" @wheel="wheel" @keydown.enter="enter"  @keydown.up="up"  @keydown.down="down"/><span :class="classes">{{ unit }}</span>
    </div>
</script>


<script id="tmpl-property-dialog" type="text/x-template">
  <div>
	  try entering '23em' with return, also when input has focus spin mouse wheel.<br><br>
    {{ myprop.label }} - {{ myprop.value }}
    <br>
    <css-prop-dim :prop="myprop"  >
    </css-prop-dim>
	</div>
</script>

CSS

body {
  font-size: 20px;
}

.text {
  font-size: 24px;
}

.unit {
  font-family: 'Arial';
  font-size: 12px;
  background-color: gray;
  padding: 3.3px 0px;
  position: relative;
  left: -23px;
  top: 3px;
  width: 23px;
  max-height: 16px;
  vertical-align: top;
  color: white;
  display: inline-block;
  text-align:center;
}

.number {
  width: 34px;
  height:16px;
  padding-right:25px;
}

.control {
  margin-top: 20px;
  position: relative;
}

JavaScript

Vue.component('css-prop-dim', {
  template: "#tmpl-css-prop-dim",
  props: ['prop'],
  data: function() {
    return {
      number: 0,
      unit: ''
    }
  },
  created: function() {
    //console.log("article properties:",this.properties);
    this.split(this.prop.value);
  },
  methods: {
    split: function(v) {
      this.number = parseInt(v);
      v = v + '';
      var m = v.match(/(px|%|em|rem|vw|vh|ch|auto)/);
      if (m) {
      	if(m[0] === 'auto'){
          this.number = '';
        }
        this.unit = m[0];
        
      }
    },
    enter: function() {
      console.log("enter pressed");
      this.split(this.number);
      this.prop.value = this.number + this.unit;

    },
    get classes: function(){
    	return {'unit': true, 'auto': this.unit === 'auto'}
    },
    
    wheel: function(ev) {
      console.log("wheel", ev);
      if (ev.deltaY > 0) {
        this.number++;
      }
      if (ev.deltaY < 0) {
        this.number--;
      }
      this.prop.value = this.number + this.unit;
    },

    up: function(ev) {
      this.number++;
      this.prop.value = this.number + this.unit;
    },
    
    down: function(ev) {
      this.number--;
      this.prop.value = this.number + this.unit;
    },

    label: function() {
      return this.prop.label;
    }
  },
  watch: {
    number: function(newv) {
      console.log(newv);
      //this.prop.value = this.number + this.unit;
    }
  }
});


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

new Vue({ // create a root Vue instance
  el: '#property-dialog', // this div gets replaced when View is rendered
  template: '#tmpl-property-dialog',
  data: function() {
    return {
      myprop: {
        label: 'width',
        value: '10px'
      }
    }
  }
});