Vue - List
Accepts pasted data, Vue updates html outside of template
by Ben Clayton
HTML
<script src="https://unpkg.com/vue"></script>
=== Name Blocks ====<br/><br/>
<div id="outside"></div>
<div id="interface">
</div>
<script id="vue-tmpl-interface" type="text/x-template">
<div class="interface">
<div class="preview">
<div class="line1">{{ previewline('line1') }}
</div>
<div class="line2">{{ previewline('line2') }}
</div>
</div>
<div class="list-wrapper">
Names can be typed into the boxes below, or copy or drag from a two column Word table or Excel spreadsheet into box here.
<div tabindex=-1 id='pasteDiv' contenteditable='true'>Paste or Drop here</div>
<div class="header">
<div class="col">Line1</div>
<div class="col">Line2</div>
</div>
<div class="scrolling-list-wrapper">
<div v-for="(row,index) in rows" :key="index" :row="row" v-bind:class="{ selected: isSelected(index) }">
<input class="line1" v-bind:class="{ truncated: isTruncated(index,'line1') }" type="text" v-model="row['line1']" v-on:focus="focus(index)" maxlength="22" />
<input class="line2" v-bind:class="{ truncated: isTruncated(index,'line2') }" type="text" v-model="row['line2']" v-on:focus="focus(index)" maxlength="22" />
<button tabindex=-1 v-on:click="namedel(index)">Del</button>
</div>
<button tabindex=-1 v-on:click="nameadd">Add</button>
</div>
<div class="qtyofnames">Qty of Names: {{quantity}} (cost £{{quantityPrice}}) </div>
</div>
</div>
</script>
CSS
.interface {}
.qtyofnames {
margin-bottom: 15px;
}
.pastebutton {
margin-bottom: 15px;
}
.list-wrapper {
float: right;
width: 530px;
}
.scrolling-list-wrapper {
float: right;
border: 1px solid gray;
background-color: #F0F0F0;
padding: 10px;
width: 520px;
height: 100px;
overflow: auto;
margin-bottom: 10px;
}
.scrolling-list-wrapper .line1,
.scrolling-list-wrapper .line2 {
background-color: #E0E0E0;
margin-bottom: 5px;
width: 220px
}
.scrolling-list-wrapper .line1.truncated,
.scrolling-list-wrapper .line2.truncated {
background-color: red;
}
.scrolling-list-wrapper div.selected input {
background-color: #FFFFFF;
}
.scrolling-list-wrapper .line1:focus,
.scrolling-list-wrapper .line1:focus,
#pasteDiv:focus {
outline: none !important;
}
.preview {
margin-top: 20px;
float: left;
border: 1px solid gray;
width: 380px;
height: 100px;
padding: 20px;
}
.preview .line1,
.preview .line2 {
background-color: white;
width: 100%;
font-size: 22px;
font-family: "Times New Roman";
text-align: center;
margin: 5px auto;
}
.list-wrapper .header .col {
display: inline-block;
width: 200px;
margin-left: 30px;
}
#pasteDiv {
width: 100px;
height: 30px;
background-color: white;
border: 1px dashed gray;
padding: 10px;
text-align: center;
margin-bottom: 20px;
}
#pasteDiv:hover {
border: 1px solid green;
background-color: #D0D0FF;
color: black;
}
JavaScript
//---------------------------------------------------------
var vm = new Vue({ // create a root Vue instance
el: '#interface', // this div gets replaced when View is rendered
template: '#vue-tmpl-interface',
data: {
rows: [{
line1: "",
line2: ""
}],
selectedindex: 0
},
watch: {
rows: {
handler: function(val, oldVal) {
document.getElementById('outside').innerHTML = val[this.selectedindex].line1 + val[this.selectedindex].line2;
},
deep: true
},
selectedindex: {
handler: function(val, oldVal) {
document.getElementById('outside').innerHTML = this.rows[val].line1 + this.rows[val].line2;
},
deep: true
}
},
computed: {
quantity: function() {
return this.rows.length
},
quantityPrice: function() {
return this.rows.length * 35;
}
},
methods: {
isSelected: function(index) {
console.log("sle", index);
return this.selectedindex == index;
},
isTruncated: function(index, line) {
console.log("trunc", index);
return this.rows[index][line].length > 22;
},
previewline(line) {
return this.rows[this.selectedindex][line].substring(0, 22);
},
nameadd() {
console.log("Add");
this.rows.push({
line1: "",
line2: ""
});
},
namedel(index) {
console.log("Delete", index);
this.selectedindex = (index > 0) ? index - 1 : 0;
if (this.rows.length == 1) {
this.rows[0].line1 = "";
this.rows[0].line2 = "";
} else {
this.rows.splice(index, 1);
}
},
cleanlist() {
for (var x = this.rows.length - 1; x > -1; x--) {
if (this.rows[x].line1 == "" && this.rows[x].line2 == "") {
this.namedel(x)
}
}
},
focus(index) {
console.log(index);
this.selectedindex = index;
},
paste(data) {
console.log("Paste", data);
if (data) {
var...