|
<div class={class} class:focused id={id} > |
|
<label for={name} on:click="refs.inp.focus()">$</label> |
|
<input ref:inp type="text" bind:value=rawVal name={name} on:focus="set({focused:true})" on:blur="set({focused:false})" /> |
|
</div> |
|
|
|
<script> |
|
|
|
export default { |
|
data(){return { |
|
precision:99, //default, but can be overwritten by passing in as parameter to the component |
|
rawVal:undefined, |
|
"class":"", |
|
id:"", |
|
focused:false |
|
}}, |
|
|
|
methods: { |
|
reformat(){ |
|
const inp=this.refs.inp |
|
var val=inp.value |
|
|
|
//remove non-numeric characters |
|
var newVal=val.replace(/[^\-\.0-9]/g,"") |
|
//remove any extra minus sign (only the front one is allowed) |
|
if(newVal.length>1) newVal=newVal[0]+newVal.substring(1).replace(/\-/g,"") |
|
//remove any extra dots |
|
var posx=0 |
|
if((posx=newVal.search(/\./))>=0) newVal=newVal.substring(0,posx+1)+newVal.substring(posx+1).replace(/\./g,"") |
|
//adding the commas |
|
if(posx<0) posx=newVal.length |
|
var strx="" |
|
var ctr=-1 |
|
for(var i=posx-1;i>=0;i--){ |
|
var x=newVal[i] |
|
if(x<="9" && x>="0"){ |
|
ctr++ |
|
if(ctr==3){ |
|
strx=","+strx |
|
ctr=0 |
|
} |
|
} |
|
strx=x+strx |
|
} |
|
newVal=strx+newVal.substring(posx,posx+1*this.get().precision+1) |
|
|
|
//updating the HTML input, and the data model |
|
//inp.value=newVal |
|
this.fRawVal=newVal //to prevent double updates |
|
this.caretP=inp.selectionStart+(newVal.length-val.length) |
|
if(this.caretP<0) this.caretP=0 |
|
this.set({rawVal:newVal}) |
|
|
|
//the return value is what gets converted to a number |
|
return 1*((newVal.search(/[0-9]/)<0) ? "" : newVal.replace(/\,/g,"")) |
|
}, |
|
|
|
}, |
|
|
|
onupdate({ changed, current, previous }) { |
|
if(changed.value && this.fValue!=this.get().value){ |
|
this.set({rawVal:current.value+""}) |
|
changed.rawVal=true //`set` inside this fn doesn't trigger another update cycle |
|
} |
|
if(changed.rawVal && this.fRawVal!=this.get().rawVal){ |
|
//adding a 0ms setTimout to run the code after the updates are all done |
|
setTimeout(function(){ |
|
this.fValue=this.reformat() |
|
this.refs.inp.selectionStart=this.caretP |
|
this.refs.inp.selectionEnd=this.caretP |
|
this.set({value:this.fValue}) |
|
}.bind(this),0) |
|
} |
|
}, |
|
oncreate() { |
|
var x=this.get().opts |
|
if(x && x.precision!=undefined) this.set({precision:x.precision}) |
|
}, |
|
} |
|
</script> |
|
|
|
<style> |
|
div { |
|
display: inline-flex; |
|
background: #fff; |
|
border:1px solid #ccc; |
|
padding: 0.2rem; |
|
position:relative; |
|
} |
|
input { |
|
flex:1; |
|
width:100%; |
|
padding:0; |
|
margin:0; |
|
border:none; |
|
background: transparent; |
|
} |
|
input:focus { |
|
outline:none; |
|
} |
|
div.focused:before { |
|
content:""; |
|
pointer-events: none; |
|
display:block; |
|
box-shadow: 0px 0px 2px 1px #0000FF80; |
|
position:absolute; |
|
top:0px; |
|
bottom:0px; |
|
left:0px; |
|
right:0px; |
|
} |
|
|
|
</style> |
any svelte 3 version of this around anywhere?