JSFiddle - React, Tailwind, and code Playground
by FANTAzeRus
HTML
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">
<div id="propertyBox">
<div class="propertyBoxWrapper">
<propbox :model="propData"></propbox>
</div>
<div class="debug">{{ propData }}</div>
</div>
CSS
body {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
font-size: 14px;
}
.propertyBoxWrapper {
display: block;
position: relative;
max-width: 400px;
border: 1px solid #999;
border-radius: 4px;
}
.propLine {
border-bottom: 1px solid #999;
}
#propertyBox > div > span > div:last-child > div > div.propertyGroupBody > div:last-child {
border-bottom: none;
}
.open-group {
color: #97cd76;
}
.close-group {
color: #ed6c63;
}
.propertyGroupTitle i {
margin-right: 1px;
cursor: pointer;
line-height: 20px;
}
.propertyGroupTitle {
font-weight: bold;
padding-left: 5px;
border-left: 5px solid tomato;
border-bottom: 1px solid #999;
}
.propertyGroupBody {
}
.propNameWrapper {
display: inline-block;
width: 150px;
border-right: 1px solid #999;
height: 20px;
}
.propName {
padding: 0 4px;
line-height: 20px;
}
.propValueWrapper {
display: inline-block;
height: 20px;
}
.propValue {
padding: 0;
line-height: 20px;
}
.propValue span input {
border: none;
font-size: 14px;
}
.propValue span input:focus {
outline:none;
}
.propValue span select {
font-size: 14px;
border: none;
}
.propValue span select:focus {
outline:none;
}
.debug {
margin-top: 20px;
border: 1px solid #999;
border-radius: 4px;
padding: 5px;
}
JavaScript
Vue.directive('focus', {
inserted: function (el) {
el.focus();
el.select();
}
});
//Текстовые поля
Vue.component('stringfield', {
template: '\
<span>\
<strong v-if="!edit"\
@click="editField"\
>{{ value }}</strong>\
<input v-if="edit"\
type="text"\
v-focus\
:value="value"\
@input="onInput"\
@blur="saveField"\
@keyup.enter.esc="saveField"\
>\
</span>\
',
data: function() {
return {
edit: false
}
},
props: {
'value': String
},
methods: {
onInput: function (event) {
this.$emit('input', event.target.value);
},
editField: function () {
this.edit = true;
},
saveField: function () {
this.edit = false;
}
}
});
//Числа
Vue.component('numberfield', {
template: '\
<span>\
<strong v-if="!edit"\
@click="editField"\
>{{ value }}</strong>\
<input v-if="edit"\
type="text"\
v-focus\
:value="value"\
@input="onInput"\
@blur="saveField"\
@keyup.enter.esc="saveField"\
>\
</span>\
',
data: function() {
return {
edit: false
}
},
props: {
'value': Number
},
methods: {
onInput: function (event) {
this.$emit('input', event.target.value);
},
editField: function () {
this.edit = true;
},
saveField: function () {
this.edit = false;
}
}
});
//Логика
Vue.component('checkbox', {
template: '\
<input type="checkbox" :checked="value" :value="value" @change="onChange">\
',
props: {
value:...