PDA

View Full Version : Paste Splitter


glenngv
04-12-2005, 08:17 AM
Inspired by this thread (http://www.codingforums.com/showthread.php?t=56367).

<html>
<head>
<title>Paste Splitter v1.0</title>
<style type="text/css">
body, input {
font: normal 12px Verdana;
}
</style>
<script type="text/javascript">
/************************
Paste Splitter v1.0
Glenn G. Vergara
glenngv@yahoo.com
Philippines


NOTE:
Please make this intact
if you want to use this
script. Thanks.
*************************/

function PasteSplitter(origMaxlen){ //you can also pass as many field references as needed in the argument
var me = this;
var arglen = arguments.length;
this.flds = new Array();
this.maxlen = origMaxlen;
this.filter = this.NUMERIC; //default filter
for (var i=1; i<arglen; i++){
this.flds[i-1] = arguments[i];
}
if (this.flds.length > 0){
var fld1 = this.flds[0];
fld1.onkeydown = function(event){
extendMaxLength(me.flds, me.maxlen, event);
}
fld1.onkeyup = function(event){
splitPaste(me.flds, me.maxlen, event)
}
if (typeof fld1.onbeforepaste != "undefined"){
fld1.onbeforepaste = function(event){
extendMaxLength(me.flds, me.maxlen, event);
}
}
if (typeof fld1.onpaste != "undefined"){
fld1.onpaste = function(event){
//we need a little delay here before calling the function
setTimeout(function(){
splitPaste(me.flds, me.maxlen, event);
}, 10);
}
}
}

function extendMaxLength(arrFlds, maxlen1, evt){
if (!evt) evt = event;
if (evt.ctrlKey || evt.type=="beforepaste"){
var len = maxlen1;
var arrlen = arrFlds.length;
for (var i=1; i<arrlen; i++){
len += arrFlds[i].maxLength;
}
arrFlds[0].maxLength = len + arrlen - 1; //allow separators in beetween sets (e.g. - . /)
}
}

function splitPaste(arrFlds, maxlen1, evt){
var s = arrFlds[0].value;
//apply filter
switch (me.filter){
case me.NUMERIC:
s = s.replace(/\D/g, "");
break;
case me.ALPHANUMERIC:
s = s.replace(/\W/g, "");
break;
case me.ALPHA:
s = s.replace(/[^a-zA-Z]/g, "");
break;
default: //custom filter
s = s.replace(me.filter, "");
}
var len = s.length;
if (len <= maxlen1){
arrFlds[0].value = s;
if (arrFlds.length > 1 && len==maxlen1){
arrFlds[1].focus();
}
return;
}
else {
var len=0, start=0, arrlen=arrFlds.length, el;
for (var i=0; i<arrlen; i++){
el = arrFlds[i];
len = (i>0) ? el.maxLength:maxlen1;
el.value = s.substr(start, len);
if (el.value=="" || el.value.length < len){
el.focus();
el.value = el.value; //this trick puts cursor at the end of value after focusing on the field first
return;
}
start += len;
}
}
arrFlds[0].maxLength = maxlen1; //change back to original maxlength
}
}

//filters
PasteSplitter.prototype.NUMERIC = 1;
PasteSplitter.prototype.ALPHANUMERIC = 2;
PasteSplitter.prototype.ALPHA = 3;

PasteSplitter.prototype.setFilter = function(filter){ //custom filter (regexp) may be specified
this.filter = filter;
}
/***************end of script******************/



//SAMPLE USAGE
function init(){
var f = document.forms[0];

//serial number
var ser = new PasteSplitter(f.ser1.maxLength, f.ser1, f.ser2, f.ser3); //pass the original maxlength of the first field and all the references of as many fields as needed
ser.setFilter(ser.ALPHANUMERIC); //set filter to alpha-numeric

//sss number
var sss = new PasteSplitter(f.sss1.maxLength, f.sss1, f.sss2, f.sss3, f.sss4); //default filter (numeric) will be used
}
window.onload = init;
//END OF SAMPLE USAGE

</script>
</head>
<body>
<form>
<h1>Paste Splitter v1.0</h1>
<p>Copy any alpha, numeric or alphanumeric characters, even including separators such as slash (/), hyphen (-), dot (.) or anything, and then paste it in the first field. The characters will be split to all the fields automatically excluding the separator. Very useful for fields like serial number, Social Security number, telephone number and the like. The script works on the basis of the <code>maxlength</code> attribute of the field. It degrades well for JavaScript-disabled browsers, making the <code>maxlength</code> attribute untouched. It works well for IE for all paste commands (<code>CTRL+V</code>, <code>Edit->Paste</code>, <code>right-click->Paste</code>) and partially works for Firefox (<code>CTRL+V</code> only).</p>
<fieldset>
<legend>Information</legend>
<label for="ser1">Serial No.</label> <input type="text" maxlength="5" size="5" id="ser1" name="ser1" /> - <input type="text" maxlength="4" size="4" id="ser2" name="ser2" /> - <input type="text" maxlength="6" size="6" id="ser3" name="ser3" /><br />
<label for="sss1">SSS No.</label> <input type="text" maxlength="2" size="2" id="sss1" name="sss1" /> - <input type="text" maxlength="7" size="7" id="sss2" name="sss2" /> - <input type="text" maxlength="2" size="2" id="sss3" name="sss3" /> - <input type="text" maxlength="1" size="1" id="sss4" name="sss4" />
</fieldset>
</form>
</body>
</html>

If you have any comments, suggestion, bugs found, please feel free to post them here.

codegoboom
04-12-2005, 09:01 AM
Hmm... either the instructions or UI are confusing, because nothing I expect to happen (when pasting or typing) happens!
Is this limited to a specific format (#of chars per seperator) or what?

glenngv
04-12-2005, 09:26 AM
Thanks for the feedback.

What did you exactly paste in the first field?
For serial number, the fields are divided into 3 each having 5, 4, and 6 maxlengths respectively.
So if you copy the text 12345-67AB-012CDE somewhere else and paste it in the first field, the numbers will be automatically split to the 3 fields with the first field having a value of 12345, 2nd field 67AB and 3rd field 012CDE. This only happens when you paste the text, no special thing happens when you type, just the normal way.

For SSS number, all non-numeric text will be filtered out.

codegoboom
04-12-2005, 09:41 AM
Well, I pasted something other than the correct format--which got mixed up and distributed in a strange way--and when typing, the first field's input jumped into the next, but subsequent entry did not, and separators were erased upon typing in the first field, only...

As far as the UI confusion went, I'd suggest labeling the fields to signify expected formatting, or using one input (and hiding the actual targets).

glenngv
04-12-2005, 10:43 AM
Well, I pasted something other than the correct format--which got mixed up and distributed in a strange wayThat's specification.
--and when typing, the first field's input jumped into the next, but subsequent entry did not, and separators were erased upon typing in the first field, only...Only the first field has the event listeners.

As far as the UI confusion went, I'd suggest labeling the fields to signify expected formatting, or using one input (and hiding the actual targets).I will post the updated code after this. I put a label for the format to use. BTW, what do you exactly mean by using one input and hiding the targets? Show only one field and when the user paste the text, show the other fields and divide the text among them?

glenngv
04-12-2005, 10:51 AM
Updated version. Changes:
1. supported drag n' drop style of pasting for IE.
2. added label for format to be used (codegoboom's suggestion)
3. removed unused 'evt' parameter for splitPaste function.
<html>
<head>
<title>Paste Splitter v1.1</title>
<style type="text/css">
body, input {
font: normal 12px Verdana;
}
.comment {
font-style:italic;
}
</style>
<script type="text/javascript">
/************************
Paste Splitter v1.1
Glenn G. Vergara
glenngv@yahoo.com
Philippines


NOTE:
Please make this intact
if you want to use this
script. Thanks.
*************************/

/************************
Change History:
v1.1 - 04/12/2005 - supported drag n' drop style of pasting for IE.
- added label for format to be used.
- removed unused 'evt' parameter for splitPaste function.
v1.0 - 04/12/2005 - initial version.
*************************/

function PasteSplitter(origMaxlen){ //you can also pass as many field references as needed in the argument
var me = this;
var arglen = arguments.length;
this.flds = new Array();
this.maxlen = origMaxlen;
this.filter = this.NUMERIC; //default filter
for (var i=1; i<arglen; i++){
this.flds[i-1] = arguments[i];
}
if (this.flds.length > 0){
var fld1 = this.flds[0];
fld1.onkeydown = function(event){
extendMaxLength(me.flds, me.maxlen, event);
}
fld1.onkeyup = function(){
splitPaste(me.flds, me.maxlen)
}
if (typeof fld1.onbeforepaste != "undefined"){
fld1.onbeforepaste = function(event){
extendMaxLength(me.flds, me.maxlen, event);
}
}
if (typeof fld1.onpaste != "undefined"){
fld1.onpaste = function(){
//we need a little delay here before calling the function
setTimeout(function(){
splitPaste(me.flds, me.maxlen);
}, 10);
}
}
if (typeof fld1.ondragenter != "undefined"){
fld1.ondragenter = function(event){
extendMaxLength(me.flds, me.maxlen, event);
}
}
if (typeof fld1.ondrop != "undefined"){
fld1.ondrop = function(){
//we need a little delay here before calling the function
setTimeout(function(){
splitPaste(me.flds, me.maxlen);
}, 10);
}
}
}

function extendMaxLength(arrFlds, maxlen1, evt){
if (!evt) evt = event;
if (evt.ctrlKey || evt.type=="beforepaste" || evt.type=="dragenter"){
var len = maxlen1;
var arrlen = arrFlds.length;
for (var i=1; i<arrlen; i++){
len += arrFlds[i].maxLength;
}
arrFlds[0].maxLength = len + arrlen - 1; //allow separators in beetween sets (e.g. - . /)
}
}

function splitPaste(arrFlds, maxlen1){
var s = arrFlds[0].value;
//apply filter
switch (me.filter){
case me.NUMERIC:
s = s.replace(/\D/g, "");
break;
case me.ALPHANUMERIC:
s = s.replace(/\W/g, "");
break;
case me.ALPHA:
s = s.replace(/[^a-zA-Z]/g, "");
break;
default: //custom filter
s = s.replace(me.filter, "");
}
var len = s.length;window.status+=','+len;
if (len <= maxlen1){
arrFlds[0].value = s;
if (arrFlds.length > 1 && len==maxlen1){window.status+='here'+len
arrFlds[1].focus();
}
return;
}
else {
var len=0, start=0, arrlen=arrFlds.length, el;
for (var i=0; i<arrlen; i++){
el = arrFlds[i];
len = (i>0) ? el.maxLength:maxlen1;
el.value = s.substr(start, len);
if (el.value=="" || el.value.length < len){
el.focus();
el.value = el.value; //this trick puts cursor at the end of value after focusing on the field first
return;
}
start += len;
}
}
arrFlds[0].maxLength = maxlen1; //change back to original maxlength
}
}

//filters
PasteSplitter.prototype.NUMERIC = 1;
PasteSplitter.prototype.ALPHANUMERIC = 2;
PasteSplitter.prototype.ALPHA = 3;

PasteSplitter.prototype.setFilter = function(filter){ //custom filter (regexp) may be specified
this.filter = filter;
}
/***************end of script******************/



//SAMPLE USAGE
function init(){
var f = document.forms[0];

//serial number
var ser = new PasteSplitter(f.ser1.maxLength, f.ser1, f.ser2, f.ser3); //pass the original maxlength of the first field and all the references of as many fields as needed
ser.setFilter(ser.ALPHANUMERIC); //set filter to alpha-numeric

//sss number
var sss = new PasteSplitter(f.sss1.maxLength, f.sss1, f.sss2, f.sss3, f.sss4); //default filter (numeric) will be used
}
window.onload = init;
//END OF SAMPLE USAGE

</script>
</head>
<body>
<form>
<h1>Paste Splitter v1.1</h1>
<p>Copy any alpha, numeric or alphanumeric characters, even including separators such as slash (/), hyphen (-), dot (.) or anything, and then paste it in the first field. The characters will be split to all the fields automatically excluding the separator. Very useful for fields like serial number, Social Security number, telephone number and the like. The script works on the basis of the <code>maxlength</code> attribute of the field. It degrades well for JavaScript-disabled browsers, making the <code>maxlength</code> attribute untouched. It works well for IE for all paste commands (<code>CTRL+V</code>, <code>Edit->Paste</code>, <code>right-click->Paste</code>) and partially works for Firefox (<code>CTRL+V</code> only).</p>
<fieldset>
<legend>Information</legend>
<label for="ser1">Serial No.</label> <input type="text" maxlength="5" size="5" id="ser1" name="ser1" /> - <input type="text" maxlength="4" size="4" id="ser2" name="ser2" /> - <input type="text" maxlength="6" size="6" id="ser3" name="ser3" /> <span class="comment" title="alphanumeric only">(XXXXX-XXXX-XXXXXX)</span><br />
<label for="sss1">SSS No.</label> <input type="text" maxlength="2" size="2" id="sss1" name="sss1" /> - <input type="text" maxlength="7" size="7" id="sss2" name="sss2" /> - <input type="text" maxlength="2" size="2" id="sss3" name="sss3" /> - <input type="text" maxlength="1" size="1" id="sss4" name="sss4" /> <span class="comment" title="numbers only">(99-9999999-99-9)</span>
</fieldset>
</form>
</body>
</html>

codegoboom
04-12-2005, 10:58 AM
That's specification.
Oh, excuse my not knowing the spec... ;)
Forget my comment about using one field, because that would negate the whole point of the script... sorry! :rolleyes:

glenngv
04-12-2005, 11:57 AM
Last edited by codegoboom : 04-12-2005 at 05:08 PM. Reason: You may want to make the other fields readonly, by the way...c(",)

codegoboom
04-12-2005, 12:29 PM
What if the user wants to edit the other fields?
Nope: might violate specification! :D

glenngv
04-22-2005, 10:34 AM
Nope: might violate specification! :D
So why did you suggest it? Making fields readonly as you suggested will make them unusable if the user wants to manually type the values.

codegoboom
04-22-2005, 10:40 AM
Exactly... ;)