Skip to content

Instantly share code, notes, and snippets.

@tfwio
Last active August 29, 2015 14:05
Show Gist options
  • Save tfwio/eba214df1c80fab76396 to your computer and use it in GitHub Desktop.
Save tfwio/eba214df1c80fab76396 to your computer and use it in GitHub Desktop.
needs consolidation, cleanup ... more
function __formatter(){
//console.log("Formatter prototype initialized.");
return this;
}
/**
* Believe it or not, this is of huge help to our table-sorting algo.
* What it is still doing here is beyond me.
* ---ahh, I was rendering tables in ASPNET/MVC and validating content?
*/
__formatter.prototype.findParent = function (tag, breaker)
{
var x = $(this);
var t;
while ((t = (x = x.parent())[0].tagName) !== tag) { if (t === breaker) break; }
console.log(x[0].tagName);
return x;
};
__formatter.prototype.dayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
__formatter.prototype.dayNamesShort = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
/**
* Regular Expressions
*/
__formatter.prototype.exp =
{
// phone
// guess I still have the 80's somewhere in me.
// we'll strip this
phone7: /^(\d{3})?[- ]?(\d{4})$/,
phone10: /^\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/,
phone11: /^(\d{1})?[- ]?\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/,
socSecNo: /^(\d{3})?[- ]?(\d{2})?[- ]?(\d{4})$/,
rdate: /[0-9]{1,2}(\\|\/|-| )[0-9]{1,2}(\\|\/|-| )[0-9]{4}/,
dater: /[0-9]{4}(\\|\/|-| )[0-9]{1,2}(\\|\/|-| )[0-9]{1,2}/,
// time
ampm: /(AM|PM|A|P)/i,
time1: /^([0-9]{1,2})\:?([0-9]{1,2})[ ]?(AM|PM|A|P)?/i,
time: /^([0-9]{1,2})\:?([0-9]{1,2})[ ]?(AM|PM|A|P)/i,
tim: /^([0-9]{1,2})\:?([0-9]{1,2})[ ]?(a|p)?/i,
//
price: /(\$)?([0-9,]*).([0-9]{0,2})/i
};
// three-part date
__formatter.prototype.cvt =
{
time: '$1:$2 $3'
};
__formatter.prototype.fmt = { s_date: 'y/M/d', date: 'M/d/y' };
__formatter.prototype.rex = { year: /y/g, month: /M/g, day: /d/g };
var Formatter = new __formatter;
/**
* PROTOTYPE NOTES
* 2012-02-24
* - Moved all prototypes and related functions down here, and organized them
* - Added the Number.prototype.roundPercision and round functions.
* - Note that any Dollar and currency related method should from this
* point use the round methods provided to the Number Prototype.
*/
// NUMBER PROTOTYPES
// @summary Number Prototype — roundPercision
Number.prototype.roundPercision = function(percision)
{
var p = percision || 100;
return new Number(Math.round(Number(this * p)) / p);
}
// Number Prototype — round
Number.prototype.round = function()
{
return Number( this )
.roundPercision(1000)
.roundPercision();
};
// @returns String
// @summary for Time formats that require two-digit-format.
// @see String.prototype.dpad()
Number.prototype.dpad = function()
{
return this > 9 ? this : '0'+this;
};
// STRING PROTOTYPE (dpad, isNativeDate, toTime)
// dpad function for Time formats that require two-digit-format.
// see: Number.prototype.dpad()
String.prototype.dpad = function()
{
return parseInt(this) > 9 ? this : '0'+this;
};
// Strip non-numeric characters from string
String.prototype.strip = function (no)
{
var newstr = new String();
var xstring = '0123456789';
for (var i = 0; i < no.length; i++)
{
if (/[0-9]/.test(no.charAt(i)))
newstr += String(no.charAt(i));
}
return newstr;
};
/**
* isNativeDate method returns weather or not the date
* can be parsed by the default ‘new Date(input_value)’
* call.
* see: $.fn.shortDate()
* Note: This method is particularly used to prevent an error
* from halting the script if a date string does not comply
* with Javascript.Date Object.
*/
String.prototype.isNativeDate = function()
{
var datevalue, r = true;
try { datevalue = new Date(this); }
catch (Error) { r = false; }
finally { delete datevalue; }
return r;
};
// utility function
String.prototype.toTime = function()
{
var t = null;
if (Formatter.exp.time.test(this)&&Formatter.exp.ampm.test(this))
{
return new Time(
this.replace(Formatter.exp.time,'$1'),
this.replace(Formatter.exp.time,'$2'),
this.replace(Formatter.exp.time,'$3')
);
} else if (Formatter.exp.tim.test(this)) {
return new Time(
this.replace(Formatter.exp.tim,'$1'),
this.replace(Formatter.exp.tim,'$2'),
"AM"
);
}
return false;
};
String.prototype.toDec = function (dec)
{
var s = new String(dec);
if (s=='') return '00';
return s.length == 1 ? String(dec)+'0' : dec;
};
String.prototype.toThou=function()
{
var x = this.valueOf();
var xs = String(Number(x).toFixed(9)).split('.');
x = xs[0];
var d = String(xs[1]);
xs = null;
var a=[];
var s = x.length % 3;
console.log(s)
var sx = x.substr(0,x.length %3);
x = x.substr(x.length %3,x.length - x.length%3);
if (sx.length) a.push(sx);
while (x.length > 0)
{
var str =x.substr(0,3);
if (str.length) a.push(str);
x = x.substr(3,x.length-3);
console.log(x.length > 0, x);
}
return a.join(',')+"."+String(d).substr(0,2);
};
// DATE PROROTYPE REF
// This method is added to the date prototype.
// See Date.prototype.Simplify(), below.
var DTransform = function(datetime)
{
try
{
this.Hour = datetime.getMinutes();
this.Minute = datetime.getMinutes();
this.Month = datetime.getMonth()+1;
this.Day = datetime.getDay();
this.Year = datetime.getFullYear();
}
catch (Exception)
{
console.log(Exception);
}
this.Filter = function(input)
{
return String(input)
.replace("{h}",this.Hour)
.replace("{m}",this.Minute)
.replace("{M}",this.Month)
.replace("{d}",this.Day)
.replace("{Y}",this.Year)
;
}
};
// DATE PROTOTYPE
// ¿
// Date Prototype — Simplify
Date.prototype.Simplify = function()
{
var transformer = new DTransform(this);
var str = transformer.Filter("{y}/{M}{y} {h}:{m}")
};
//toLocaleTimeString
//toLocaleDateString
// a quick-clean date string.
Date.prototype.shortDateString = function()
{
var d = this;
var date = String(d.getDate());
return fmt.date
.replace(rex.year, d.getFullYear())
.replace(rex.month, d.getMonth() + 1)
.replace(rex.day, date.length > 1 ? date : '0' + date)
;
//return this.get
};
// a quick parse overload from the context of a date
Date.prototype.bin = function()
{
return Date.parse(this);
//return this.get
};
Date.prototype.toBtnFormat = function(format)
{
var da = this.getDate(), mo = this.getMonth(), yy = this.getFullYear(),
day = this.getDay(), dddd = dayNames[day], ddd = dayNamesShort[day];
var fmt = "{3} {1}/{2}/{0}"
.replace("{0}", yy)
.replace("{1}", Number(mo + 1).dpad())
.replace("{2}", Number(da).dpad())
.replace('{3}', ddd);
return fmt.toUpperCase();
};
// TIME
/**
* The following time object is not finished and needs a little bit of work.
* A new time object would first be split by a colon and deal with
* SMPTE or similar notion of dealing with 00:00:00.000 (hh:mm:ss.ttt).
* The format would first have to be parsed (if sent in as a string format)
* Formatting rules will (in the future) be more pertinant to the date
* object such as that we might recieve a format such as 00-00-00-000 +N
* (plus|minus N for GMT or UTC modification values). I think that it should
* generally deal with Localle for default local (machine) time.
*/
var Time = function(h,m,ampm)
{
this.h = Number(h).toFixed(0);
this.m = Number(m).toFixed(0);
this.ampm = String(ampm||"AM").toUpperCase();
this.update();
this.hasError = this.checkError();
this.g11 = this.h > 11;
};
Time.prototype.update = function()
{
if (this.ampm=='A') this.ampm = 'AM';
else if (this.ampm=='P') this.ampm = 'PM';
this.imod = this.h % 12;
this.hmod = this.ampm=='PM' ? this.h + 12 : this.h;
this.ampm = this.g11 ? 'PM' : this.ampm;
this.h = this.h % 12;
};
Time.prototype.checkError = function()
{
if ((typeof this.h)!=='Number') return false;
if ((typeof this.m)!=='Number') return false;
return false;
};
Time.prototype.str = function()
{
return (this.h).dpad()+':'+(this.m).dpad()+' '+this.ampm.toUpperCase();
};
//# jquery.formatter.js
/**
* input validation and formatting kit
* ===================================
*
* 06/2011 — 'reformatted' 20140814
* - uses jquery >= v1.11.1
* - Most methods depend on 'formatter-prototypes.js'
* - Date/Time correction/validation
* - sorting algorithm is included though not currently supported.
*
* Usage #1
* --------
*
* - automatically checks/converts targets.
* - Dates, Date/Time objects, Currency objects and Etc are
* cleaned and/or converted.
*
* Usage #2
* --------
* - using the option 'action' such as
* - currency: `$(elementId).noFormat({action: 'currency'});`
* - fixphoneno: `$(elementId).noFormat({action: 'fixphoneno'});`
*
*/
(function($){
'use strict';
var sorter = [].sort;
var tCompare =
{
string: function(a,b) { return String(a).localeCompare(String(b)); },
numeric: function(a,b) { if (a===b) return 0; return a - b; },
stringDate: function(a,b)
{
var da = (typeof a === 'Date') ? a : new Date(a),
db = (typeof b === 'Date') ? a : new Date(b);
}
};
var target =
{
elementPhone: undefined,
phone: "input.phone, input[fmt='ph']",
currency: "input.currency, input[fmt='c']",
soc: "input.soc-sec, input[fmt='soc']",
date: "input.date, input[fmt=date]",
time: "input.time, input[fmt=time]"
};
var strings=
{
validationTip:'<span class="tip">{} isn\'t valid. </span>',
tip: '<span class="tip">{} isn\'t valid. </span>',
textBoxInvalidColor: '#FF0000',
noOptions: 'No options provided. Entering global mode.'
};
/**
* @param $this
* Currently not supported (to my knowledge)
*/
$.noFormat = function($this,options)
{
var xoptions;
var
/**
* initialization is lossy.
* In the future, all bound methods should use the
* ‘jQuery.live(e,f)’ methods.
*/
initialize = function ()
{
$(target.elementPhone).each(elmPhoneValue);
$(target.phone).off ('blur',formatter);
$(target.phone) .on('blur', formatter);
$(target.phone).each(formatter);
//
$(target.currency).off ('blur',dcformatter);
$(target.currency).on('blur',dcformatter);
$(target.currency).each(dcformatter);
//
$(target.soc).off('blur',socsec);
$(target.soc).on('blur',socsec);
$(target.soc).each(socsec);
// then we'll apply the filter
// (new) trigger dates to be parsed
$(target.time)
.on('focus', checkTime)
.on('blur', checkTime2)
.on('load', keytrigger).blur();
// (new) trigger dates to be parsed
$(target.date)
.on('keyup', checkDate)
.on('blur', checkDate)
.on('focus', checkDate)
.on('load', keytrigger)
.keyup();
},
keytrigger = function() { $(this).keyup(); },
uninit = function()
{
$('input.date')
.off('keyup',checkDate)
.off('load',keytrigger);
},
dollar = function (value)
{
if (value==null) return '';
else if (value=='') return '';
var rX=/(\$)(\d+)\.(\d{2})/;
return value.replace(rX,"$2.$3");
},
fixPhoneNo = function (phoneNo)
{
var len = phoneNo.length;
var newStr = null;
if /*(len==7) newStr = phoneNo.replace(exp.phone7,"$1-$2");
else if*/ (len==10) newStr = phoneNo.replace(Formatter.exp.phone10,"($1) $2-$3");
else if (len==11) newStr = phoneNo.replace(Formatter.exp.phone11,"$1 ($2) $3-$4");
else return new String(phoneNo);
return newStr;
},
toDec = function (dec)
{
var s = new String(dec);
if (s=='') return '00';
return s.length == 1 ? String(dec)+'0' : dec;
},
toInt = function (dec)
{
var s = new String(dec);
if (s=='') return 0;
return new Number(s).toFixed(0);
},
formatPrice = function (inputString)
{
var d=String(toDec(Number(inputString).toFixed(2)));
return String('$'+d);
},
//
getPercent = function (input)
{
var n1 = input.replace(Formatter.exp.rxPercent, "$1");
var n2 = input.replace(Formatter.exp.rxPercent, "$2");
return n1;
},
// remove non-number characters
stripit = function (no)
{
var newstr = new String();
var xstring = '0123456789';
for (var i = 0; i < no.length; i++)
{
if (/[0-9]/.test(no.charAt(i)))
newstr += String(no.charAt(i));
}
return newstr;
},
//
elmPhoneValue = function(input,object)
{
var oldNo = $(object).text();
window.alert(oldNo);
if (oldNo==='') return;
var strip;
strip=stripit(oldNo);
var newNo = fixPhoneNo(strip);
$(this).val(newNo);
$('.tip').remove();
var length = strip.length;
var invalid = false;
if (length== 0) invalid = false;
// else if (length<=9) invalid = false;
else if (length==10) invalid = false;
else if (length==11) invalid = false;
else invalid = true;
if (invalid)
{
$(this)
.css("background", strings.textBoxInvalidColor )
.after(strings.tip.replace("{}",strip))
;
}
else
{
$(this).removeAttr('style');
}
},
/**
* This call is used to format phone numbers within
* text-input form-elements that have been assigned
* by the initializer.
*/
formatter = function ()
{
var oldNo = $(this).val();
if (oldNo==='') return;
var strip=stripit(oldNo);
var newNo = fixPhoneNo(strip);
$(this).val(newNo);
$('.tip').remove();
var length = strip.length;
var invalid = true;
if (length==10) invalid = false;
else if (length==11) invalid = false;
if (invalid)
{
$(this).after(strings.tip.replace("{}",strip));
$(this).css({ background: "red" });
}
else
{
$(this).css({ background: "" });
}
},
// See Options
fixSocNo = function (socNo)
{
var len = socNo.length;
var newStr = null;
if (len==9) newStr = socNo.replace(Formatter.exp.socSecNo,"$1-$2-$3");
else return new String(socNo);
return newStr;
},
socsec = function ()
{
var oldNo = $(this).val();
if (oldNo==='') return;
var strip = stripit(oldNo);
var newNo = fixSocNo(strip);
$(this).val(newNo);
$('.tip').remove();
var length = strip.length;
var invalid = false;
if (length==9) invalid = false;
else invalid = true;
if (invalid)
{
$(this).after('<span class="tip">'+strip+' isn\'t valid. </span>');
$(this).attr('style','background:red');
}
else
{
$(this).removeAttr('style');
}
},
cformatter = function ()
{
var oldNo = $(this).val();
if (oldNo==='') return;
var newNo = formatPrice(oldNo);
$(this).val(newNo);
return;
},
dcformatter = function ()
{
var oldNo = $(this).val().replace("$",'');
if (oldNo==='') { oldNo = "0"; }
var newNo = "$"+oldNo.toThou();
$(this).val(newNo);
return;
},
/**
* - google results for time-picker (updown)
* - http://wiki.jqueryui.com/w/page/12138077/Spinner
* - http://stefanoverna.com/assets/other/ical_like_calendar/demo.html
* - jQueryUI
* - http://fgelinas.com/code/timepicker/
* - http://blogs.uct.ac.za/blog/lovemores-world/2009/02/25/an-effective-jquery-date-time-picker
**/
checkTime = function(opt)
{
console.log(this);
var $o = $(this);
var v = $o.val();
var t = String(v).toTime();
console.log(t);
if (opt.log) try {console.log(t.str());} catch(Error) {}
if (opt.set)
{
try{
$o.val(t.str());
} catch (Error)
{
$o.val(v);
}
}
return true;
},
//
checkTime2 = function()
{
console.log("what is this? ", this);
return checkTime.call(this,{log:true,set:true});
},
// Date Addon Methods
// ———————————————————————————————————————————————————————————————————
checkDate = function ()
{
var $o = $(this);
var v = $o.val();
try {
var d = new Date(v);
{
var f1 = Formatter.exp.rdate.test(v);
var f2 = Formatter.exp.dater.test(v);
if ((f1 || f2)==false)
{
console.log("rdate: ",f1,"dater: ",f2);
throw new Error('format not recognized');
}
}
}
catch (xoxo)
{
console.log(xoxo);
$o.css('background', strings.textBoxInvalidColor);
return;
}
finally
{
}
$o.css('background', "white");
};
if (options===undefined)
{
console.log(strings.noOptions);
}
else if (options.action=='currency')
{
var xo = $(this);
xo.val(dcformatter(xo.val()));
return;
}
else if (options.action=='fixphoneno')
{
var noValue,newNo,xo = $($this);
try {
noValue = String(xo.text());
} catch (Err) {
console.log(Err);
console.log("there was an error.");
}
try
{
if ( noValue=="") { noValue = "…"; }
newNo = fixPhoneNo(noValue) || "…";
} catch (Err) {
console.log(Err);
console.log("2: there was an error.");
}
xo.text(newNo);
return;
}
initialize();
};
// ———————————————————————————————————————————————————————————————————————
$.fn.noFormat = function(options)
{
// testing…
options = options || {};
options.value = options.value || 0;
options.action = options.action || undefined;
// the following would be applicable on a input tag
// such as <input type='text' type='[attrPhone]' />
options.targetPhone = options.attrPhone || 'ph'; // or <tag type='ph' />
options.targetPhone = options.attrCurrency || 'c'; // or <tag type='c' />
this.each(function(){ new $.noFormat(this,options); });
};
// Date Addon Methods
// ———————————————————————————————————————————————————————————————————————
/**
* @returns
* javascript Date Object if it exists, or
* the original value on the exception.
* @see $(text-input).getDate()
*/
$.fn.shortDate = function ()
{
if (this.hasClass('date') && String(this.val()).isNativeDate())
{
var d = this.dateValue();
var date = d.getDate();
return fmt.date
.replace(rex.month, d.getMonth() + 1)
.replace(rex.day, date > 9 ? date : '0' + date)
.replace(rex.year, d.getFullYear());
}
return this.val();
};
/**
* @returns
* javascript Date Object if it exists, or
* the original value on the exception.
* @see $(text-input).getDate()
*/
$.fn.dateValue = function ()
{
if (this.hasClass('date') && this.isDate()) return new Date(this.getDate());
return this.val();
};
$.fn.getDate = function ()
{
if (this.hasClass('date')) {
var d;
try { d = new Date(this.val()); }
catch (Error){ return this.val(); }/**/
}
return this.val();
};
$.fn.isDate = function(value)
{
var date;
try { date = value ? value : this.getDate(); }
catch (Error) { return false; }
return true;
};
$.fn.findParent = function(tag,breaker)
{
return findParent.call(this[0],tag,breaker);
};
// SORT EM
/**
* Our sorting plugin is used like a standard function
* within the jquery namespace.
*/
$.fn.sortem = function(options)
{
'use strict';
var o = {
/**
* if multicolumn is set, we would provide an array of strings
* where each string represents a column-name.
*/
comparer: [ tCompare.numeric, tCompare.string ],
compare: function(a,b)
{
var i = 0;
var ca = comp.call(a), cb = comp.call(b), rv = o.comparer[i](ca[i],cb[i]);
console.log("len: {0}, value: {1}"
.replace("{0}",ca.length)
.replace("{1}",ca[i])
);
while (rv!==0) {
if (ca.length == i) break;
i++;
rv = o.comparer[i](ca[i],cb[i]);
console.log('i: {0}, on = {1}'.replace('{0}',i).replace('{1}',a));
break;
}
return rv;
},
// this property should be an array of methods
// so that we can sort on multiple entities
// such as separate table columns.
targetValue:
//[
function() { return [$(this).find('td > input.date').dateValue().bin()]; },
//],
callb: false
};
// 'o' our options
o = $.extend([],o,options);
// for string compare we would do: tCompare.string()
var comp = o.targetValue;
var cp = o.compare;
var sortObj = this.parent().children().get();
// uses [].sort as the function, and our provided comparison method.
sorter.call(sortObj,cp);
// update the target's html
this.parent().html(sortObj);
if (o.callb) o.callb();
return this;
};
})(jQuery);
<!DOCTYPE HTML>
<html lang="en" charset="utf8">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="encoding" content="utf8">
<title>jquery.formatter test</title>
<STYLE>
HTML>BODY,
H1,H2,H3,H4,H5,H6
{
FONT-FAMILY: "FreeSans" !IMPORTANT;
}
H1
{
border-bottom: 2px solid gray;
}
H2,H3
{
border-bottom: 1px solid gray;
}
BUTTON,
INPUT[TYPE=TEXT]
{
BORDER: 1PX SOLID SILVER;
BACKGROUND: NONE;
font-size: 14pt;
}
BUTTON
{
FONT-FAMILY: "Open Sans";
FONT-WEIGHT: 700;
BORDER: 1PX SOLID SILVER;
BACKGROUND: NONE;
}
BUTTON>SPAN:ACTIVE
{
POSITION: RELATIVE;
TOP: 1PX;
}
BUTTON:HOVER
{
background-color: blue;
color: white;
}
INPUT[TYPE=TEXT]
{
FONT-FAMILY: CONSOLAS;
BACKGROUND-COLOR: WHITE;
}
</STYLE>
</head>
<body>
<H1>Phone Number</H1>
<h2>Validates on.blur()</H2>
<p>
validate on .blur()
</p>
<input type="text" id="phone" fmt='ph' value="123 456 789 0" />
<!-- <button><SPAN>VALIDATE PHONE NUMBER</SPAN></button> -->
<H3>Usage</H3>
<pre>
<code>
&lt;input type="text" id="phone" <font color=red>fmt='ph'</font> value="123 456 789 0" /&gt;
&lt;script>
setTimeout($.noFormat,3000);
&lt;/script>
</code>
</pre>
<H1>Date</H1>
<input type="text" fmt='date' value="" placeholder="2014-01-20" />
<H1>Time</H1>
<input type="text" fmt='time' value="" placeholder="11:20 AM" />
<H1>Social Security</H1>
<input type="text" fmt='soc' value="" placeholder="333-22-4444" />
<H1>USD</H1>
<input type="text" fmt='c' value="" placeholder="$1,200.00" />
<script language="javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<!-- <script language="javascript" src="..\lib\jquery-1.11.1.min.js"></script> -->
<script language="javascript" src="formatter-prototypes.js?v=201408140925"></script>
<script language="javascript" src="jquery.formatter.js"></script>
<script>
var x = "12345678901";
setTimeout($.noFormat,3000);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment