Skip to content

Instantly share code, notes, and snippets.

Created December 24, 2013 17:06
Show Gist options
  • Save anonymous/8115746 to your computer and use it in GitHub Desktop.
Save anonymous/8115746 to your computer and use it in GitHub Desktop.
<html ng-app="Test" >
<head>
<title>Field splitter directive - Demo page</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" ></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
<script type="text/javascript" src="angular-field-splitter.js" ></script>
<script type="text/javascript">
angular.module('Test', ['fieldSplitter']);
function TestCtrl($scope) {
$scope.formData = {};
$scope.submit = function() {
alert($scope.formData.testField);
}
$scope.test = function() {
return '||';
}
}
</script>
<style type="text/css">
* { font-family: "Lucida Sans Unicode","Lucida Grande",Verdana,Arial,Helvetica,sans-serif; color:#333;}
#main-wrapper {
width:70%;
margin:0 auto;
}
h3 { color: #999; border-bottom:2px solid #999;}
.footer {
padding:10px;
}
.footer b{
font-size:11px;
}
.demo_boxes .demo {
padding:10px;
border-bottom: 3px dashed #999;
}
.demo p {
color:#333;
}
.part1, .part2, .part3 {
color:#aaa;
}
.part1.active, .part2.active, .part3.active {
color:black;
}
.code {
background-color:#999;
padding:5px;
font-size:12px;
}
.method { font-weight:bold;}
.option { color:white;}
input { width:80px;}
</style>
</head>
<body ng-controller="TestCtrl">
<div id="main-wrapper">
<h1>Field Splitter directive v0.1</h1>
<h3>Demo page for the directive</h3>
<div class="demo_boxes">
<div class="demo">
<p>Basic example, using all default values </p>
<b>Example #1: </b>
<p>
<input type="text" id="test" ng-model="formData.testField_1" split-field/>
</p>
<br/><b>Data saved on ng-model</b>: {{formData.testField_1}}<br/>
<i>HTML Code</i>
<xmp data-ng-non-bindable>
<input type="text" id="test" ng-model="formData.testField_1" split-field/>
</xmp>
</div>
<div class="demo">
<b>Example #2: </b>
<p>Some static configuration</p>
<P>
<input type="text" id="test2" split-field split-glue="/" split-max-length="2" split-into="2" split-default-value="___" ng-model="formData.testField"/>
</p><br/>
Data saved on ng-model: {{formData.testField}}
<br/>
<i>HTML Code</i>
<xmp data-ng-non-bindable>
<input type="text" id="test2" split-field split-glue="/" split-max-length="2" split-into="2" split-default-value="___" ng-model="formData.testField"/>
</xmp>
</div>
<div class="demo">
<p>Dynamic example. Using functions instead of static values for some of the configuration options</p>
<b>Example #3: </b>
<p>
<input type="text" id="test4" split-field split-glue="-" split-glue-original="false" split-default-value="{{test()}}" ng-model="formData.testField_3"/></p>
<br/>
Data svaed on ng-model: {{formData.testField_3}}<br/>
<i>HTML Code</i>
<xmp ng-non-bindable>
<input type="text" id="test4" split-field split-glue="-" split-glue-original="false" split-default-value="{{test()}}" ng-model="formData.testField_3"/>
</xmp>
</div>
</div>
<div class="footer">
<span class="contact">Contact the author: <b>[email protected]</b></span>
</body>
</html>
var module = angular.module('app', []);
angular.module("fieldSplitter", []).
directive("partialField", function() {
/**
* Gets the combined input from all of the parts
*/
function getCombinedInput(scope, glueOriginal, glue) {
var inputs = [];
$(scope.fields).each(function(i, e) {
inputs.push($(e).children().first().val());
});
glueOriginal = (glueOriginal.toLowerCase() === "true");
return inputs.join((glueOriginal)? glue : "");
}
return {
restrict: 'E',
scope: {
pfType: "@",
pfDefaultValue: "@",
pfMaxLength: "@",
pfGlue: "@",
pfGlueOriginal: "@"
},
template: '<input data-ng-keyup="handleKeyup();" data-ng-focus="handleFocus();" data-ng-blur="handleBlur()" type="{{pfType}}" value="{{pfDefaultValue}}" pf-default-value="{{pfDefaultValue}}" maxlength="{{pfMaxLength}}" />',
link: function(scope, element, attrs) {
scope.handleKeyup = function(){
var field = $(element.children()[0]);
$(scope.$parent.originalElement).val(getCombinedInput(scope.$parent, scope.pfGlueOriginal, scope.pfGlue)); //Every time the user adds input, the original field is updated
setTimeout(function() { $(scope.$parent.originalElement).trigger("input"); }, 10);
if(field.val().length == field.attr("maxlength")) {
if(!field.hasClass("last-field")) {
setTimeout(function() {
field.parent().next().children().first().focus();
}, 10);
}
}
};
scope.handleFocus = function() {
var $this = $(element.children()[0]);
$this.addClass("active");
if($this.val() == $this.attr("pf-default-value")) {
$this.val("");
}
};
scope.handleBlur = function() {
var $this = $(element.children()[0]);
if($this.val() === "") {
$this.removeClass("active");
$this.val($this.attr("pf-default-value"));
}
};
}
};
}).directive('splitField', function($compile) {
function createPartialFields(container, opts, scope) {
var totalFields = opts.numberOfFields;
scope.fields = [];
for(var idx = 0; idx < totalFields; idx++) {
var f = getPartialField(opts, scope, idx);
scope.fields.push(f);
container.append(f);
if(idx < totalFields - 1) {
container.append(opts.glue);
}
}
}
/**
Returns the code for a partial field (using the partial-field directive)
*/
function getPartialField(opts, scope, idx) {
var newField = '<partial-field pf-type="'+opts.type+'" pf-default-value="'+opts.defaultValue+'" pf-max-length="'+opts.maxLength+'" pf-glue="'+opts.glue+'" pf-glue-original="'+opts.glueOriginal+'"/>';
var elem = $compile(newField)(scope);
return elem;
}
return {
scope: true,
link: function(scope, elem, attrs) {
/** Default values */
var DEFAULT_NUMBER_OF_FIELDS = 3;
var DEFAULT_VALUE = "XXX";
var DEFAULT_MAX_LENGTH = 3;
var DEFAULT_GLUE = "-";
var DEFAULT_GLUE_ORIGINAL = true;
var $elem = $(elem);
var options = {
type: $(elem).attr("type"),
defaultValue: attrs.splitDefaultValue ? attrs.splitDefaultValue : DEFAULT_VALUE,
maxLength: attrs.splitMaxLength ? attrs.splitMaxLength : DEFAULT_MAX_LENGTH,
numberOfFields: attrs.splitInto ? attrs.splitInto : DEFAULT_NUMBER_OF_FIELDS,
glue: attrs.splitGlue ? attrs.splitGlue : DEFAULT_GLUE,
glueOriginal: attrs.splitGlueOriginal ? attrs.splitGlueOriginal : DEFAULT_GLUE_ORIGINAL
};
scope.originalElement = $elem;
var parentElement = $elem.parent();
$elem.hide(); //we hide the original element
createPartialFields(parentElement, options, scope);
}
};
});
function PageController($scope, $templateCache) {
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment