diff --git a/CHANGELOG.txt b/CHANGELOG.txt index e1861d31..34288986 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,20 @@ Angular-xeditable changelog ============================= +Version 0.2.0 Jun 28, 2016 + +---------------------------- +[enh #491] Added popover functionality (ckosloski) +[fix #489] Fix - Memory leak when ending editing by destroying the scope (kenfdev) +[enh #479] Added ability to add a label to an input (ckosloski) +[enh #473] Added support for datetime-local input (ckosloski) +[bug #464] Added ability to add more then one editable-ui-select component on the same page (julia-k) +[enh #463] Added on-change support for bsdate and placeholder support for editable-select (ckosloski) +[bug #456] Fixed bsdate warnings with latest ui-bootstrap (ckosloski) +[bug #454] Fix finding form controller when elements not yet in DOM (bostrom) +[bug #366] Make 'e-form' publish local $form even if specify object property (hshn) + + Version 0.1.12 Apr 14, 2016 ---------------------------- [enh #448] Add support for ui-select (ckosloski) diff --git a/bower.json b/bower.json index 73c0cc6a..b91990a8 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-xeditable", - "version": "0.1.12", + "version": "0.2.0", "description": "Edit in place for AngularJS", "author": "https://github.com/vitalets", "license": "MIT", diff --git a/dist/css/xeditable.css b/dist/css/xeditable.css index 8919a903..ae9d4642 100644 --- a/dist/css/xeditable.css +++ b/dist/css/xeditable.css @@ -113,4 +113,53 @@ a.editable-empty:focus { text-decoration: none; } +/* editable popover */ +.popover-wrapper a { + /* make the link always show up */ + display: inline !important; +} + +.popover-wrapper { + /* make absolutely positioned children constrained to this box*/ + display: inline; + position: relative; +} + +.popover-wrapper form { + position: absolute; + top: -53px; + background: #FFF; + border: 1px solid #AAA; + border-radius: 5px; + padding: 7px; + width: auto; + display: inline-block; + left: 50%; + margin-left: -110px; + z-index: 101; +} + +.popover-wrapper form:before { + content:""; + width: 0; + height: 0; + border-left: 10px solid transparent; + border-right: 10px solid transparent; + border-top: 10px solid #AAA; + position:absolute; + bottom:-10px; + left:100px; +} + +.popover-wrapper form:after { + content:""; + width:0; + height:0; + border-left: 9px solid transparent; + border-right: 9px solid transparent; + border-top: 9px solid #FFF; + position:absolute; + bottom:-9px; + left:101px; +} diff --git a/dist/css/xeditable.min.css b/dist/css/xeditable.min.css index 4590ae42..376e3dd2 100644 --- a/dist/css/xeditable.min.css +++ b/dist/css/xeditable.min.css @@ -1,7 +1,7 @@ /*! -angular-xeditable - 0.1.12 +angular-xeditable - 0.2.0 Edit-in-place for angular.js -Build date: 2016-04-14 +Build date: 2016-06-28 */ -.editable-wrap{display:inline-block;white-space:nowrap;margin:0}.editable-wrap .editable-controls,.editable-wrap .editable-error{margin-bottom:0}.editable-wrap .editable-controls>input,.editable-wrap .editable-controls>select,.editable-wrap .editable-controls>textarea{margin-bottom:0}.editable-wrap .editable-input{display:inline-block}.editable-buttons{display:inline-block;vertical-align:top}.editable-buttons button{margin-left:5px}.editable-input.editable-has-buttons{width:auto}.editable-bstime .editable-input input[type=text]{width:46px}.editable-bstime .well-small{margin-bottom:0;padding:10px}.editable-range output{display:inline-block;min-width:30px;vertical-align:top;text-align:center}.editable-color input[type=color]{width:50px}.editable-checkbox label span,.editable-checklist label span,.editable-radiolist label span{margin-left:7px;margin-right:10px}.editable-hide{display:none!important}.editable-click,a.editable-click{text-decoration:none;color:#428bca;border-bottom:dashed 1px #428bca}.editable-click:hover,a.editable-click:hover{text-decoration:none;color:#2a6496;border-bottom-color:#2a6496}.editable-empty,.editable-empty:hover,.editable-empty:focus,a.editable-empty,a.editable-empty:hover,a.editable-empty:focus{font-style:italic;color:#D14;text-decoration:none} \ No newline at end of file +.editable-wrap{display:inline-block;white-space:nowrap;margin:0}.editable-wrap .editable-controls,.editable-wrap .editable-error{margin-bottom:0}.editable-wrap .editable-controls>input,.editable-wrap .editable-controls>select,.editable-wrap .editable-controls>textarea{margin-bottom:0}.editable-wrap .editable-input{display:inline-block}.editable-buttons{display:inline-block;vertical-align:top}.editable-buttons button{margin-left:5px}.editable-input.editable-has-buttons{width:auto}.editable-bstime .editable-input input[type=text]{width:46px}.editable-bstime .well-small{margin-bottom:0;padding:10px}.editable-range output{display:inline-block;min-width:30px;vertical-align:top;text-align:center}.editable-color input[type=color]{width:50px}.editable-checkbox label span,.editable-checklist label span,.editable-radiolist label span{margin-left:7px;margin-right:10px}.editable-hide{display:none!important}.editable-click,a.editable-click{text-decoration:none;color:#428bca;border-bottom:dashed 1px #428bca}.editable-click:hover,a.editable-click:hover{text-decoration:none;color:#2a6496;border-bottom-color:#2a6496}.editable-empty,.editable-empty:hover,.editable-empty:focus,a.editable-empty,a.editable-empty:hover,a.editable-empty:focus{font-style:italic;color:#D14;text-decoration:none}.popover-wrapper a{display:inline!important}.popover-wrapper{display:inline;position:relative}.popover-wrapper form{position:absolute;top:-53px;background:#FFF;border:1px solid #AAA;border-radius:5px;padding:7px;width:auto;display:inline-block;left:50%;margin-left:-110px;z-index:101}.popover-wrapper form:before{content:"";width:0;height:0;border-left:10px solid transparent;border-right:10px solid transparent;border-top:10px solid #AAA;position:absolute;bottom:-10px;left:100px}.popover-wrapper form:after{content:"";width:0;height:0;border-left:9px solid transparent;border-right:9px solid transparent;border-top:9px solid #FFF;position:absolute;bottom:-9px;left:101px} \ No newline at end of file diff --git a/dist/js/xeditable.js b/dist/js/xeditable.js index 2bc855e5..8817d68b 100644 --- a/dist/js/xeditable.js +++ b/dist/js/xeditable.js @@ -1,7 +1,7 @@ /*! -angular-xeditable - 0.1.12 +angular-xeditable - 0.2.0 Edit-in-place for angular.js -Build date: 2016-04-14 +Build date: 2016-06-28 */ /** * Angular-xeditable module @@ -97,16 +97,12 @@ angular.module('xeditable').directive('editableBsdate', ['editableDirectiveFacto **/ this.parent.render.call(this); - var inputDatePicker = angular.element(''); - var buttonDatePicker = angular.element(''); - var buttonWrapper = angular.element(''); + var inputDatePicker = angular.element(''); inputDatePicker.attr('uib-datepicker-popup', this.attrs.eDatepickerPopupXEditable || 'yyyy/MM/dd' ); inputDatePicker.attr('is-open', this.attrs.eIsOpen); inputDatePicker.attr('date-disabled', this.attrs.eDateDisabled); inputDatePicker.attr('uib-datepicker-popup', this.attrs.eDatepickerPopup); - inputDatePicker.attr('min-date', this.attrs.eMinDate); - inputDatePicker.attr('max-date', this.attrs.eMaxDate); inputDatePicker.attr('year-range', this.attrs.eYearRange || 20); inputDatePicker.attr('show-button-bar', this.attrs.eShowButtonBar || true); inputDatePicker.attr('current-text', this.attrs.eCurrentText || 'Today'); @@ -116,6 +112,13 @@ angular.module('xeditable').directive('editableBsdate', ['editableDirectiveFacto inputDatePicker.attr('datepicker-append-to-body', this.attrs.eDatePickerAppendToBody || false); inputDatePicker.attr('date-disabled', this.attrs.eDateDisabled); inputDatePicker.attr('name', this.attrs.eName); + inputDatePicker.attr('on-open-focus', this.attrs.eOnOpenFocus || true); + inputDatePicker.attr('ng-readonly', this.attrs.eReadonly || false); + + if (this.attrs.eNgChange) { + inputDatePicker.attr('ng-change', this.attrs.eNgChange); + this.inputEl.removeAttr('ng-change'); + } this.scope.dateOptions = { formatDay: this.attrs.eFormatDay || 'dd', @@ -128,17 +131,32 @@ angular.module('xeditable').directive('editableBsdate', ['editableDirectiveFacto startingDay: this.attrs.eStartingDay || 0, minMode: this.attrs.eMinMode || 'day', maxMode: this.attrs.eMaxMode || 'year', - initDate: this.attrs.eInitDate || new Date(), - datepickerMode: this.attrs.eDatepickerMode || 'day' + initDate: this.scope.$eval(this.attrs.eInitDate) || new Date(), + datepickerMode: this.attrs.eDatepickerMode || 'day', + maxDate: this.scope.$eval(this.attrs.eMaxDate) || null, + minDate: this.scope.$eval(this.attrs.eMinDate) || null }; - inputDatePicker.attr('datepicker-options', "dateOptions"); + var showCalendarButton = angular.isDefined(this.attrs.eShowCalendarButton) ? this.attrs.eShowCalendarButton : "true"; + + //See if calendar button should be displayed + if (showCalendarButton === "true") { + var buttonDatePicker = angular.element(''); + var buttonWrapper = angular.element(''); + + buttonDatePicker.attr('ng-click', this.attrs.eNgClick); + + buttonWrapper.append(buttonDatePicker); - buttonDatePicker.attr('ng-click',this.attrs.eNgClick); + this.inputEl.append(buttonWrapper); + } else { + //If no calendar button, display calendar popup on click of input field + inputDatePicker.attr('ng-click', this.attrs.eNgClick); + } + + inputDatePicker.attr('datepicker-options', "dateOptions"); - buttonWrapper.append(buttonDatePicker); this.inputEl.prepend(inputDatePicker); - this.inputEl.append(buttonWrapper); this.inputEl.removeAttr('class'); this.inputEl.removeAttr('ng-click'); @@ -224,7 +242,7 @@ angular.module('xeditable').directive('editableChecklist', [ this.parent.render.call(this); var parsed = editableNgOptionsParser(this.attrs.eNgOptions); var html = ''; this.inputEl.removeAttr('ng-model'); @@ -264,23 +282,43 @@ angular.module('xeditable').directive('editableCombodate', ['editableDirectiveFa ]); /* -Input types: text|email|tel|number|url|search|color|date|datetime|time|month|week +Input types: text|password|email|tel|number|url|search|color|date|datetime|datetime-local|time|month|week|file */ (function() { - var types = 'text|password|email|tel|number|url|search|color|date|datetime|time|month|week|file'.split('|'); + var camelCase = function(dashDelimitedString) { + return dashDelimitedString.toLowerCase().replace(/-(.)/g, function(match, word) { + return word.toUpperCase(); + }); + }; + + var types = 'text|password|email|tel|number|url|search|color|date|datetime|datetime-local|time|month|week|file'.split('|'); //todo: datalist // generate directives angular.forEach(types, function(type) { - var directiveName = 'editable'+type.charAt(0).toUpperCase() + type.slice(1); + var directiveName = camelCase('editable' + '-' + type); angular.module('xeditable').directive(directiveName, ['editableDirectiveFactory', function(editableDirectiveFactory) { return editableDirectiveFactory({ directiveName: directiveName, - inputTpl: '' + inputTpl: '', + render: function() { + this.parent.render.call(this); + + // Add label to the input + if (this.attrs.eLabel) { + var label = angular.element(''); + this.inputEl.parent().prepend(label); + } + + // Add classes to the form + if (this.attrs.eFormclass) { + this.editorEl.addClass(this.attrs.eFormclass); + } + } }); }]); }); @@ -312,9 +350,10 @@ angular.module('xeditable').directive('editableRadiolist', [ render: function() { this.parent.render.call(this); var parsed = editableNgOptionsParser(this.attrs.eNgOptions); - var html = ''; + + var html = ''; this.inputEl.removeAttr('ng-model'); this.inputEl.removeAttr('ng-options'); @@ -339,6 +378,14 @@ angular.module('xeditable').directive('editableSelect', ['editableDirectiveFacto return editableDirectiveFactory({ directiveName: 'editableSelect', inputTpl: '', + render: function() { + this.parent.render.call(this); + + if (this.attrs.ePlaceholder) { + var placeholder = angular.element(''); + this.inputEl.append(placeholder); + } + }, autosubmit: function() { var self = this; self.inputEl.bind('change', function() { @@ -392,17 +439,27 @@ angular.module('xeditable').directive('editableUiSelect',['editableDirectiveFact return newEl; }; - var match = null; - var choices = null; + var findElement = function(name) { + for(var i = 0, len = match.length; i < len; i++) { + if (match[i].name === name) { + return i; + } + } + }; + + var match = []; + var choices = []; + var dir = editableDirectiveFactory({ directiveName: 'editableUiSelect', inputTpl: '', render: function () { + var index = findElement(this.name); this.parent.render.call(this); - this.inputEl.append(rename('ui-select-match', match)); - this.inputEl.append(rename('ui-select-choices', choices)); + this.inputEl.append(rename('ui-select-match', match[index].element)); + this.inputEl.append(rename('ui-select-choices', choices[index].element)); this.inputEl.removeAttr('ng-model'); - this.inputEl.attr('ng-model', '$parent.$data'); + this.inputEl.attr('ng-model', '$parent.$parent.$data'); } }); @@ -412,8 +469,8 @@ angular.module('xeditable').directive('editableUiSelect',['editableDirectiveFact var matchEl = el.find('editable-ui-select-match'); var choicesEl = el.find('editable-ui-select-choices'); - match = matchEl.clone(); - choices = choicesEl.clone(); + match.push({name : attrs.name || attrs.editableUiSelect, element : matchEl.clone()}); + choices.push({name : attrs.name || attrs.editableUiSelect, element : choicesEl.clone()}); matchEl.remove(); choicesEl.remove(); @@ -670,7 +727,7 @@ angular.module('xeditable').factory('editableController', } self.inputEl.addClass('editable-input'); - self.inputEl.attr('ng-model', '$data'); + self.inputEl.attr('ng-model', '$parent.$data'); // add directiveName class to editor, e.g. `editable-text` self.editorEl.addClass(editableUtils.camelToDash(self.directiveName)); @@ -697,6 +754,8 @@ angular.module('xeditable').factory('editableController', valueGetter($scope.$parent); }; + // reference of the scope to use for $compile + var newScope = null; //show self.show = function() { // set value of scope.$data @@ -713,7 +772,8 @@ angular.module('xeditable').factory('editableController', $element.after(self.editorEl); // compile (needed to attach ng-* events from markup) - $compile(self.editorEl)($scope); + newScope = $scope.$new(); + $compile(self.editorEl)(newScope); // attach listeners (`escape`, autosubmit, etc) self.addListeners(); @@ -727,10 +787,23 @@ angular.module('xeditable').factory('editableController', //hide self.hide = function() { - + + // destroy the scope to prevent memory leak + newScope.$destroy(); + + self.controlsEl.remove(); self.editorEl.remove(); $element.removeClass('editable-hide'); + // Manually remove the watcher on 'has-error' to prevent a memory leak on it. + for (var i = 0, len = $scope.$$watchers.length; i < len; i++) { + if ($scope.$$watchers[i] !== undefined && $scope.$$watchers[i].last && $scope.$$watchers[i].last !== undefined && + typeof $scope.$$watchers[i].last === 'object' && "has-error" in $scope.$$watchers[i].last) { + $scope.$$watchers.splice(i, 1); + break; + } + } + // onhide return self.onhide(); }; @@ -921,23 +994,28 @@ function($parse, $compile, editableThemes, $rootScope, $document, editableContro // form controller var eFormCtrl; - // this variable indicates is element is bound to some existing form, + // this variable indicates is element is bound to some existing form, // or it's single element who's form will be generated automatically // By default consider single element without any linked form.ß var hasForm = false; - + // element wrapped by form - if(ctrl[1]) { + if (ctrl[1]) { eFormCtrl = ctrl[1]; hasForm = attrs.eSingle === undefined; - } else if(attrs.eForm) { // element not wrapped by
, but we hane `e-form` attr + } else if (attrs.eForm) { // element not wrapped by , but we hane `e-form` attr var getter = $parse(attrs.eForm)(scope); - if(getter) { // form exists in scope (above), e.g. editable column + if (getter) { // form exists in scope (above), e.g. editable column eFormCtrl = getter; hasForm = true; - } else { // form exists below or not exist at all: check document.forms - for(var i=0; i<$document[0].forms.length;i++){ - if($document[0].forms[i].name === attrs.eForm) { + } else if (elem && typeof elem.parents === "function" && elem.parents().last().find('form[name='+attrs.eForm+']').length) { // form exists below or not exist at all: check document.forms + // form is below and not processed yet + eFormCtrl = null; + hasForm = true; + } else { + // form exists below or not exist at all: check document.forms + for (var i=0; i<$document[0].forms.length;i++) { + if ($document[0].forms[i].name === attrs.eForm) { // form is below and not processed yet eFormCtrl = null; hasForm = true; @@ -978,7 +1056,7 @@ function($parse, $compile, editableThemes, $rootScope, $document, editableContro if (disabled) { return; } - + // init editable ctrl eCtrl.init(!hasForm); @@ -1012,7 +1090,7 @@ function($parse, $compile, editableThemes, $rootScope, $document, editableContro // if `e-form` provided, publish local $form in scope if(attrs.eForm) { - scope.$parent[attrs.eForm] = scope.$form; + ($parse(attrs.eForm).assign || angular.noop)(scope.$parent, scope.$form); } // bind click - if no external form defined @@ -1194,7 +1272,8 @@ angular.module('xeditable').factory('editableFormController', }, /** - * Sets focus on form field specified by `name`. + * Sets focus on form field specified by `name`.
+ * When trying to set the focus on a form field of a new row in the editable table, the `$activate` call needs to be wrapped in a `$timeout` call so that the form is rendered before the `$activate` function is called. * * @method $activate(name) * @param {string} name name of field @@ -2225,7 +2304,7 @@ angular.module('xeditable').factory('editableThemes', function() { noformTpl: '', controlsTpl: '', inputTpl: '', - errorTpl: '
', + errorTpl: '
', buttonsTpl: '', submitTpl: '', cancelTpl: '' @@ -2237,7 +2316,7 @@ angular.module('xeditable').factory('editableThemes', function() { noformTpl: '', controlsTpl: '
', inputTpl: '', - errorTpl: '
', + errorTpl: '
', buttonsTpl: '', submitTpl: '', cancelTpl: '', cancelTpl: '', cancelTpl: ''),c=angular.element('');a.attr("uib-datepicker-popup",this.attrs.eDatepickerPopupXEditable||"yyyy/MM/dd"),a.attr("is-open",this.attrs.eIsOpen),a.attr("date-disabled",this.attrs.eDateDisabled),a.attr("uib-datepicker-popup",this.attrs.eDatepickerPopup),a.attr("min-date",this.attrs.eMinDate),a.attr("max-date",this.attrs.eMaxDate),a.attr("year-range",this.attrs.eYearRange||20),a.attr("show-button-bar",this.attrs.eShowButtonBar||!0),a.attr("current-text",this.attrs.eCurrentText||"Today"),a.attr("clear-text",this.attrs.eClearText||"Clear"),a.attr("close-text",this.attrs.eCloseText||"Done"),a.attr("close-on-date-selection",this.attrs.eCloseOnDateSelection||!0),a.attr("datepicker-append-to-body",this.attrs.eDatePickerAppendToBody||!1),a.attr("date-disabled",this.attrs.eDateDisabled),a.attr("name",this.attrs.eName),this.scope.dateOptions={formatDay:this.attrs.eFormatDay||"dd",formatMonth:this.attrs.eFormatMonth||"MMMM",formatYear:this.attrs.eFormatYear||"yyyy",formatDayHeader:this.attrs.eFormatDayHeader||"EEE",formatDayTitle:this.attrs.eFormatDayTitle||"MMMM yyyy",formatMonthTitle:this.attrs.eFormatMonthTitle||"yyyy",showWeeks:this.attrs.eShowWeeks?"true"===this.attrs.eShowWeeks.toLowerCase():!0,startingDay:this.attrs.eStartingDay||0,minMode:this.attrs.eMinMode||"day",maxMode:this.attrs.eMaxMode||"year",initDate:this.attrs.eInitDate||new Date,datepickerMode:this.attrs.eDatepickerMode||"day"},a.attr("datepicker-options","dateOptions"),b.attr("ng-click",this.attrs.eNgClick),c.append(b),this.inputEl.prepend(a),this.inputEl.append(c),this.inputEl.removeAttr("class"),this.inputEl.removeAttr("ng-click"),this.inputEl.removeAttr("is-open"),this.inputEl.removeAttr("init-date"),this.inputEl.removeAttr("datepicker-popup"),this.inputEl.removeAttr("required"),this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("date-picker-append-to-body"),this.inputEl.removeAttr("name"),this.inputEl.attr("class","input-group")}})}]),angular.module("xeditable").directive("editableBstime",["editableDirectiveFactory",function(a){return a({directiveName:"editableBstime",inputTpl:"",render:function(){this.parent.render.call(this);var a=angular.element('
');a.attr("ng-model",this.inputEl.attr("ng-model")),this.inputEl.removeAttr("ng-model"),this.attrs.eNgChange&&(a.attr("ng-change",this.inputEl.attr("ng-change")),this.inputEl.removeAttr("ng-change")),this.inputEl.wrap(a)}})}]),angular.module("xeditable").directive("editableCheckbox",["editableDirectiveFactory",function(a){return a({directiveName:"editableCheckbox",inputTpl:'',render:function(){this.parent.render.call(this),this.attrs.eTitle&&(this.inputEl.wrap(""),this.inputEl.parent().append(this.attrs.eTitle))},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableChecklist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableChecklist",inputTpl:"",useCopy:!0,render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)}})}]),angular.module("xeditable").directive("editableCombodate",["editableDirectiveFactory","editableCombodate",function(a,b){return a({directiveName:"editableCombodate",inputTpl:'',render:function(){this.parent.render.call(this);var a={value:new Date(this.scope.$data)},c=this;angular.forEach(["format","template","minYear","maxYear","yearDescending","minuteStep","secondStep","firstItem","errorClass","customClass","roundTime","smartDays"],function(b){var d="e"+b.charAt(0).toUpperCase()+b.slice(1);d in c.attrs&&(a[b]=c.attrs[d])});var d=b.getInstance(this.inputEl,a);d.$widget.find("select").bind("change",function(a){c.scope.$data=new Date(d.getValue()).toISOString()})}})}]),function(){var a="text|password|email|tel|number|url|search|color|date|datetime|time|month|week|file".split("|");angular.forEach(a,function(a){var b="editable"+a.charAt(0).toUpperCase()+a.slice(1);angular.module("xeditable").directive(b,["editableDirectiveFactory",function(c){return c({directiveName:b,inputTpl:''})}])}),angular.module("xeditable").directive("editableRange",["editableDirectiveFactory",function(a){return a({directiveName:"editableRange",inputTpl:'',render:function(){this.parent.render.call(this),this.inputEl.after("{{$data}}")}})}])}(),angular.module("xeditable").directive("editableRadiolist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableRadiolist",inputTpl:"",render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableSelect",["editableDirectiveFactory",function(a){return a({directiveName:"editableSelect",inputTpl:"",autosubmit:function(){var a=this;a.inputEl.bind("change",function(){a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").directive("editableTextarea",["editableDirectiveFactory",function(a){return a({directiveName:"editableTextarea",inputTpl:"",addListeners:function(){var a=this;a.parent.addListeners.call(a),a.single&&"no"!==a.buttons&&a.autosubmit()},autosubmit:function(){var a=this;a.inputEl.bind("keydown",function(b){(b.ctrlKey||b.metaKey)&&13===b.keyCode&&a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").directive("editableUiSelect",["editableDirectiveFactory",function(a){var b=function(a,b){var c=angular.element("<"+a+"/>");c.html(b.html());for(var d=b[0].attributes,e=0;e",render:function(){this.parent.render.call(this),this.inputEl.append(b("ui-select-match",c)),this.inputEl.append(b("ui-select-choices",d)),this.inputEl.removeAttr("ng-model"),this.inputEl.attr("ng-model","$parent.$data")}}),f=e.link;return e.link=function(a,b,e,g){var h=b.find("editable-ui-select-match"),i=b.find("editable-ui-select-choices");return c=h.clone(),d=i.clone(),h.remove(),i.remove(),f(a,b,e,g)},e}]),angular.module("xeditable").factory("editableController",["$q","editableUtils",function(a,b){function c(a,c,d,e,f,g,h,i,j,k){var l,m,n=this;n.scope=a,n.elem=d,n.attrs=c,n.inputEl=null,n.editorEl=null,n.single=!0,n.error="",n.theme=f[h.theme]||f["default"],n.parent={},n.icon_set="default"===h.icon_set?g["default"][h.theme]:g.external[h.icon_set],n.inputTpl="",n.directiveName="",n.useCopy=!1,n.single=null,n.buttons="right",n.init=function(b){if(n.single=b,n.name=c.eName||c[n.directiveName],!c[n.directiveName])throw"You should provide value for `"+n.directiveName+"` in editable element!";l=e(c[n.directiveName]),n.single?n.buttons=n.attrs.buttons||h.buttons:n.buttons="no",c.eName&&n.scope.$watch("$data",function(a){n.scope.$form.$data[c.eName]=a}),c.onshow&&(n.onshow=function(){return n.catchError(e(c.onshow)(a))}),c.onhide&&(n.onhide=function(){return e(c.onhide)(a)}),c.oncancel&&(n.oncancel=function(){return e(c.oncancel)(a)}),c.onbeforesave&&(n.onbeforesave=function(){return n.catchError(e(c.onbeforesave)(a))}),c.onaftersave&&(n.onaftersave=function(){return n.catchError(e(c.onaftersave)(a))}),a.$parent.$watch(c[n.directiveName],function(a,b){n.setLocalValue(),n.handleEmpty()})},n.render=function(){var a=n.theme;n.inputEl=angular.element(n.inputTpl),n.controlsEl=angular.element(a.controlsTpl),n.controlsEl.append(n.inputEl),"no"!==n.buttons&&(n.buttonsEl=angular.element(a.buttonsTpl),n.submitEl=angular.element(a.submitTpl),n.cancelEl=angular.element(a.cancelTpl),n.icon_set&&(n.submitEl.find("span").addClass(n.icon_set.ok),n.cancelEl.find("span").addClass(n.icon_set.cancel)),n.buttonsEl.append(n.submitEl).append(n.cancelEl),n.controlsEl.append(n.buttonsEl),n.inputEl.addClass("editable-has-buttons")),n.errorEl=angular.element(a.errorTpl),n.controlsEl.append(n.errorEl),n.editorEl=angular.element(n.single?a.formTpl:a.noformTpl),n.editorEl.append(n.controlsEl);for(var d in c.$attr)if(!(d.length<=1)){var e=!1,f=d.substring(1,2);if("e"===d.substring(0,1)&&f===f.toUpperCase()&&(e=d.substring(1),"Form"!==e&&"NgSubmit"!==e)){e=e.substring(0,1).toLowerCase()+b.camelToDash(e.substring(1));var g="value"!==e&&""===c[d]?e:c[d];n.inputEl.attr(e,g)}}n.inputEl.addClass("editable-input"),n.inputEl.attr("ng-model","$data"),n.editorEl.addClass(b.camelToDash(n.directiveName)),n.single&&(n.editorEl.attr("editable-form","$form"),n.editorEl.attr("blur",n.attrs.blur||("no"===n.buttons?"cancel":h.blurElem))),angular.isFunction(a.postrender)&&a.postrender.call(n)},n.setLocalValue=function(){n.scope.$data=n.useCopy?angular.copy(l(a.$parent)):l(a.$parent)},n.show=function(){return n.setLocalValue(),n.render(),d.after(n.editorEl),j(n.editorEl)(a),n.addListeners(),d.addClass("editable-hide"),n.onshow()},n.hide=function(){return n.editorEl.remove(),d.removeClass("editable-hide"),n.onhide()},n.cancel=function(){n.oncancel()},n.addListeners=function(){n.inputEl.bind("keyup",function(a){if(n.single)switch(a.keyCode){case 27:n.scope.$apply(function(){n.scope.$form.$cancel()})}}),n.single&&"no"===n.buttons&&n.autosubmit(),n.editorEl.bind("click",function(a){a.which&&1!==a.which||n.scope.$form.$visible&&(n.scope.$form._clicked=!0)})},n.setWaiting=function(a){a?(m=!n.inputEl.attr("disabled")&&!n.inputEl.attr("ng-disabled")&&!n.inputEl.attr("ng-enabled"),m&&(n.inputEl.attr("disabled","disabled"),n.buttonsEl&&n.buttonsEl.find("button").attr("disabled","disabled"))):m&&(n.inputEl.removeAttr("disabled"),n.buttonsEl&&n.buttonsEl.find("button").removeAttr("disabled"))},n.activate=function(a,b){setTimeout(function(){var c=n.inputEl[0];"focus"===h.activate&&c.focus&&(a&&(b=b||a,c.onfocus=function(){var c=this;setTimeout(function(){c.setSelectionRange(a,b)})}),c.focus()),"select"===h.activate&&c.select&&c.select()},0)},n.setError=function(b){angular.isObject(b)||(a.$error=b,n.error=b)},n.catchError=function(a,b){return angular.isObject(a)&&b!==!0?k.when(a).then(angular.bind(this,function(a){this.catchError(a,!0)}),angular.bind(this,function(a){this.catchError(a,!0)})):b&&angular.isObject(a)&&a.status&&200!==a.status&&a.data&&angular.isString(a.data)?(this.setError(a.data),a=a.data):angular.isString(a)&&this.setError(a),a},n.save=function(){l.assign(a.$parent,n.useCopy?angular.copy(n.scope.$data):n.scope.$data)},n.handleEmpty=function(){var b=l(a.$parent),c=null===b||void 0===b||""===b||angular.isArray(b)&&0===b.length;d.toggleClass("editable-empty",c)},n.autosubmit=angular.noop,n.onshow=angular.noop,n.onhide=angular.noop,n.oncancel=angular.noop,n.onbeforesave=angular.noop,n.onaftersave=angular.noop}return c.$inject=["$scope","$attrs","$element","$parse","editableThemes","editableIcons","editableOptions","$rootScope","$compile","$q"],c}]),angular.module("xeditable").factory("editableDirectiveFactory",["$parse","$compile","editableThemes","$rootScope","$document","editableController","editableFormController","editableOptions",function(a,b,c,d,e,f,g,h){return function(b){return{restrict:"A",scope:!0,require:[b.directiveName,"?^form"],controller:f,link:function(c,f,i,j){var k,l=j[0],m=!1;if(j[1])k=j[1],m=void 0===i.eSingle;else if(i.eForm){var n=a(i.eForm)(c);if(n)k=n,m=!0;else for(var o=0;o=0&&a.splice(c,1),b},camelToDash:function(a){var b=/[A-Z]/g;return a.replace(b,function(a,b){return(b?"-":"")+a.toLowerCase()})},dashToCamel:function(a){var b=/([\:\-\_]+(.))/g,c=/^moz([A-Z])/;return a.replace(b,function(a,b,c,d){return d?c.toUpperCase():c}).replace(c,"Moz$1")}}}]),angular.module("xeditable").factory("editableNgOptionsParser",[function(){function a(a){var c;if(!(c=a.match(b)))throw"ng-options parse error";var d,e=c[2]||c[1],f=c[4]||c[6],g=c[5],h=(c[3]||"",c[2]?c[1]:f),i=c[7],j=c[8],k=j?c[8]:null;return void 0===g?(d=f+" in "+i,void 0!==j&&(d+=" track by "+k)):d="("+g+", "+f+") in "+i,{ngRepeat:d,locals:{valueName:f,keyName:g,valueFn:h,displayFn:e}}}var b=/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/;return a}]),angular.module("xeditable").factory("editableCombodate",[function(){function a(a,b){if(this.$element=angular.element(a),"INPUT"!=this.$element[0].nodeName)throw"Combodate should be applied to INPUT element";var c=(new Date).getFullYear();this.defaults={format:"YYYY-MM-DD HH:mm",template:"D / MMM / YYYY H : mm",value:null,minYear:1970,maxYear:c,yearDescending:!0,minuteStep:5,secondStep:1,firstItem:"empty",errorClass:null,customClass:"",roundTime:!0,smartDays:!0},this.options=angular.extend({},this.defaults,b),this.init()}return a.prototype={constructor:a,init:function(){if(this.map={day:["D","date"],month:["M","month"],year:["Y","year"],hour:["[Hh]","hours"],minute:["m","minutes"],second:["s","seconds"],ampm:["[Aa]",""]},this.$widget=angular.element('').html(this.getTemplate()),this.initCombos(),this.options.smartDays){var a=this;this.$widget.find("select").bind("change",function(b){(angular.element(b.target).hasClass("month")||angular.element(b.target).hasClass("year"))&&a.fillCombo("day")})}this.$widget.find("select").css("width","auto"),this.$element.css("display","none").after(this.$widget),this.setValue(this.$element.val()||this.options.value)},getTemplate:function(){var a=this.options.template,b=this.options.customClass;return angular.forEach(this.map,function(b,c){b=b[0];var d=new RegExp(b+"+"),e=b.length>1?b.substring(1,2):b;a=a.replace(d,"{"+e+"}")}),a=a.replace(/ /g," "),angular.forEach(this.map,function(c,d){c=c[0];var e=c.length>1?c.substring(1,2):c;a=a.replace("{"+e+"}",'')}),a},initCombos:function(){for(var a in this.map){var b=this.$widget[0].querySelectorAll("."+a);this["$"+a]=b.length?angular.element(b):null,this.fillCombo(a)}},fillCombo:function(a){var b=this["$"+a];if(b){var c="fill"+a.charAt(0).toUpperCase()+a.slice(1),d=this[c](),e=b.val();b.html("");for(var f=0;f'+d[f][1]+"");b.val(e)}},fillCommon:function(a){var b,c=[];if("name"===this.options.firstItem){b=moment.relativeTime||moment.langData()._relativeTime;var d="function"==typeof b[a]?b[a](1,!0,a,!1):b[a];d=d.split(" ").reverse()[0],c.push(["",d])}else"empty"===this.options.firstItem&&c.push(["",""]);return c},fillDay:function(){var a,b,c=this.fillCommon("d"),d=-1!==this.options.template.indexOf("DD"),e=31;if(this.options.smartDays&&this.$month&&this.$year){var f=parseInt(this.$month.val(),10),g=parseInt(this.$year.val(),10);isNaN(f)||isNaN(g)||(e=moment([g,f]).daysInMonth())}for(b=1;e>=b;b++)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillMonth:function(){var a,b,c=this.fillCommon("M"),d=-1!==this.options.template.indexOf("MMMM"),e=-1!==this.options.template.indexOf("MMM"),f=-1!==this.options.template.indexOf("MM");for(b=0;11>=b;b++)a=d?moment().date(1).month(b).format("MMMM"):e?moment().date(1).month(b).format("MMM"):f?this.leadZero(b+1):b+1,c.push([b,a]);return c},fillYear:function(){var a,b,c=[],d=-1!==this.options.template.indexOf("YYYY");for(b=this.options.maxYear;b>=this.options.minYear;b--)a=d?b:(b+"").substring(2),c[this.options.yearDescending?"push":"unshift"]([b,a]);return c=this.fillCommon("y").concat(c)},fillHour:function(){var a,b,c=this.fillCommon("h"),d=-1!==this.options.template.indexOf("h"),e=(-1!==this.options.template.indexOf("H"),-1!==this.options.template.toLowerCase().indexOf("hh")),f=d?1:0,g=d?12:23;for(b=f;g>=b;b++)a=e?this.leadZero(b):b,c.push([b,a]);return c},fillMinute:function(){var a,b,c=this.fillCommon("m"),d=-1!==this.options.template.indexOf("mm");for(b=0;59>=b;b+=this.options.minuteStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillSecond:function(){var a,b,c=this.fillCommon("s"),d=-1!==this.options.template.indexOf("ss");for(b=0;59>=b;b+=this.options.secondStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillAmpm:function(){var a=-1!==this.options.template.indexOf("a"),b=(-1!==this.options.template.indexOf("A"),[["am",a?"am":"AM"],["pm",a?"pm":"PM"]]);return b},getValue:function(a){var b,c={},d=this,e=!1;return angular.forEach(this.map,function(a,b){if("ampm"!==b){var f="day"===b?1:0;return c[b]=d["$"+b]?parseInt(d["$"+b].val(),10):f,isNaN(c[b])?(e=!0,!1):void 0}}),e?"":(this.$ampm&&(12===c.hour?c.hour="am"===this.$ampm.val()?0:12:c.hour="am"===this.$ampm.val()?c.hour:c.hour+12),b=moment([c.year,c.month,c.day,c.hour,c.minute,c.second]),this.highlight(b),a=void 0===a?this.options.format:a,null===a?b.isValid()?b:null:b.isValid()?b.format(a):"")},setValue:function(a){function b(a,b){var c={};return angular.forEach(a.children("option"),function(a,d){var e=angular.element(a).attr("value");if(""!==e){var f=Math.abs(e-b);("undefined"==typeof c.distance||f=12?(e.ampm="pm",e.hour>12&&(e.hour-=12)):(e.ampm="am",0===e.hour&&(e.hour=12))),angular.forEach(e,function(a,c){d["$"+c]&&("minute"===c&&d.options.minuteStep>1&&d.options.roundTime&&(a=b(d["$"+c],a)),"second"===c&&d.options.secondStep>1&&d.options.roundTime&&(a=b(d["$"+c],a)),d["$"+c].val(a))}),this.options.smartDays&&this.fillCombo("day"),this.$element.val(c.format(this.options.format)).triggerHandler("change"))}},highlight:function(a){a.isValid()?this.options.errorClass?this.$widget.removeClass(this.options.errorClass):this.$widget.find("select").css("border-color",this.borderColor):this.options.errorClass?this.$widget.addClass(this.options.errorClass):(this.borderColor||(this.borderColor=this.$widget.find("select").css("border-color")),this.$widget.find("select").css("border-color","red"))},leadZero:function(a){return 9>=a?"0"+a:a},destroy:function(){this.$widget.remove(),this.$element.removeData("combodate").show()}},{getInstance:function(b,c){return new a(b,c)}}}]),angular.module("xeditable").factory("editableIcons",function(){var a={"default":{bs2:{ok:"icon-ok icon-white",cancel:"icon-remove"},bs3:{ok:"glyphicon glyphicon-ok",cancel:"glyphicon glyphicon-remove"}},external:{"font-awesome":{ok:"fa fa-check",cancel:"fa fa-times"}}};return a}),angular.module("xeditable").factory("editableThemes",function(){var a={"default":{formTpl:'',noformTpl:'',controlsTpl:'',inputTpl:"",errorTpl:'
',buttonsTpl:'',submitTpl:'',cancelTpl:''},bs2:{formTpl:'
',noformTpl:'',controlsTpl:'
',inputTpl:"",errorTpl:'
',buttonsTpl:'',submitTpl:'',cancelTpl:''},bs3:{formTpl:'
',noformTpl:'',controlsTpl:'
',inputTpl:"",errorTpl:'
',buttonsTpl:'',submitTpl:'',cancelTpl:'',buttonsClass:"",inputClass:"",postrender:function(){switch(this.directiveName){case"editableText":case"editableSelect":case"editableTextarea":case"editableEmail":case"editableTel":case"editableNumber":case"editableUrl":case"editableSearch":case"editableDate":case"editableDatetime":case"editableBsdate":case"editableTime":case"editableMonth":case"editableWeek":case"editablePassword":if(this.inputEl.addClass("form-control"),this.theme.inputClass){if(this.inputEl.attr("multiple")&&("input-sm"===this.theme.inputClass||"input-lg"===this.theme.inputClass))break;this.inputEl.addClass(this.theme.inputClass)}break;case"editableCheckbox":this.editorEl.addClass("checkbox")}this.buttonsEl&&this.theme.buttonsClass&&this.buttonsEl.find("button").addClass(this.theme.buttonsClass)}},semantic:{formTpl:'
',noformTpl:'',controlsTpl:'
',inputTpl:"",errorTpl:'
',buttonsTpl:'',submitTpl:'',cancelTpl:''}};return a}); \ No newline at end of file +angular.module("xeditable",[]).value("editableOptions",{theme:"default",icon_set:"default",buttons:"right",blurElem:"cancel",blurForm:"ignore",activate:"focus",isDisabled:!1,activationEvent:"click"}),angular.module("xeditable").directive("editableBsdate",["editableDirectiveFactory",function(a){return a({directiveName:"editableBsdate",inputTpl:"
",render:function(){this.parent.render.call(this);var a=angular.element('');a.attr("uib-datepicker-popup",this.attrs.eDatepickerPopupXEditable||"yyyy/MM/dd"),a.attr("is-open",this.attrs.eIsOpen),a.attr("date-disabled",this.attrs.eDateDisabled),a.attr("uib-datepicker-popup",this.attrs.eDatepickerPopup),a.attr("year-range",this.attrs.eYearRange||20),a.attr("show-button-bar",this.attrs.eShowButtonBar||!0),a.attr("current-text",this.attrs.eCurrentText||"Today"),a.attr("clear-text",this.attrs.eClearText||"Clear"),a.attr("close-text",this.attrs.eCloseText||"Done"),a.attr("close-on-date-selection",this.attrs.eCloseOnDateSelection||!0),a.attr("datepicker-append-to-body",this.attrs.eDatePickerAppendToBody||!1),a.attr("date-disabled",this.attrs.eDateDisabled),a.attr("name",this.attrs.eName),a.attr("on-open-focus",this.attrs.eOnOpenFocus||!0),a.attr("ng-readonly",this.attrs.eReadonly||!1),this.attrs.eNgChange&&(a.attr("ng-change",this.attrs.eNgChange),this.inputEl.removeAttr("ng-change")),this.scope.dateOptions={formatDay:this.attrs.eFormatDay||"dd",formatMonth:this.attrs.eFormatMonth||"MMMM",formatYear:this.attrs.eFormatYear||"yyyy",formatDayHeader:this.attrs.eFormatDayHeader||"EEE",formatDayTitle:this.attrs.eFormatDayTitle||"MMMM yyyy",formatMonthTitle:this.attrs.eFormatMonthTitle||"yyyy",showWeeks:this.attrs.eShowWeeks?"true"===this.attrs.eShowWeeks.toLowerCase():!0,startingDay:this.attrs.eStartingDay||0,minMode:this.attrs.eMinMode||"day",maxMode:this.attrs.eMaxMode||"year",initDate:this.scope.$eval(this.attrs.eInitDate)||new Date,datepickerMode:this.attrs.eDatepickerMode||"day",maxDate:this.scope.$eval(this.attrs.eMaxDate)||null,minDate:this.scope.$eval(this.attrs.eMinDate)||null};var b=angular.isDefined(this.attrs.eShowCalendarButton)?this.attrs.eShowCalendarButton:"true";if("true"===b){var c=angular.element(''),d=angular.element('');c.attr("ng-click",this.attrs.eNgClick),d.append(c),this.inputEl.append(d)}else a.attr("ng-click",this.attrs.eNgClick);a.attr("datepicker-options","dateOptions"),this.inputEl.prepend(a),this.inputEl.removeAttr("class"),this.inputEl.removeAttr("ng-click"),this.inputEl.removeAttr("is-open"),this.inputEl.removeAttr("init-date"),this.inputEl.removeAttr("datepicker-popup"),this.inputEl.removeAttr("required"),this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("date-picker-append-to-body"),this.inputEl.removeAttr("name"),this.inputEl.attr("class","input-group")}})}]),angular.module("xeditable").directive("editableBstime",["editableDirectiveFactory",function(a){return a({directiveName:"editableBstime",inputTpl:"",render:function(){this.parent.render.call(this);var a=angular.element('
');a.attr("ng-model",this.inputEl.attr("ng-model")),this.inputEl.removeAttr("ng-model"),this.attrs.eNgChange&&(a.attr("ng-change",this.inputEl.attr("ng-change")),this.inputEl.removeAttr("ng-change")),this.inputEl.wrap(a)}})}]),angular.module("xeditable").directive("editableCheckbox",["editableDirectiveFactory",function(a){return a({directiveName:"editableCheckbox",inputTpl:'',render:function(){this.parent.render.call(this),this.attrs.eTitle&&(this.inputEl.wrap(""),this.inputEl.parent().append(this.attrs.eTitle))},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableChecklist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableChecklist",inputTpl:"",useCopy:!0,render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)}})}]),angular.module("xeditable").directive("editableCombodate",["editableDirectiveFactory","editableCombodate",function(a,b){return a({directiveName:"editableCombodate",inputTpl:'',render:function(){this.parent.render.call(this);var a={value:new Date(this.scope.$data)},c=this;angular.forEach(["format","template","minYear","maxYear","yearDescending","minuteStep","secondStep","firstItem","errorClass","customClass","roundTime","smartDays"],function(b){var d="e"+b.charAt(0).toUpperCase()+b.slice(1);d in c.attrs&&(a[b]=c.attrs[d])});var d=b.getInstance(this.inputEl,a);d.$widget.find("select").bind("change",function(a){c.scope.$data=new Date(d.getValue()).toISOString()})}})}]),function(){var a=function(a){return a.toLowerCase().replace(/-(.)/g,function(a,b){return b.toUpperCase()})},b="text|password|email|tel|number|url|search|color|date|datetime|datetime-local|time|month|week|file".split("|");angular.forEach(b,function(b){var c=a("editable-"+b);angular.module("xeditable").directive(c,["editableDirectiveFactory",function(a){return a({directiveName:c,inputTpl:'',render:function(){if(this.parent.render.call(this),this.attrs.eLabel){var a=angular.element("");this.inputEl.parent().prepend(a)}this.attrs.eFormclass&&this.editorEl.addClass(this.attrs.eFormclass)}})}])}),angular.module("xeditable").directive("editableRange",["editableDirectiveFactory",function(a){return a({directiveName:"editableRange",inputTpl:'',render:function(){this.parent.render.call(this),this.inputEl.after("{{$data}}")}})}])}(),angular.module("xeditable").directive("editableRadiolist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableRadiolist",inputTpl:"",render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableSelect",["editableDirectiveFactory",function(a){return a({directiveName:"editableSelect",inputTpl:"",render:function(){if(this.parent.render.call(this),this.attrs.ePlaceholder){var a=angular.element('");this.inputEl.append(a)}},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").directive("editableTextarea",["editableDirectiveFactory",function(a){return a({directiveName:"editableTextarea",inputTpl:"",addListeners:function(){var a=this;a.parent.addListeners.call(a),a.single&&"no"!==a.buttons&&a.autosubmit()},autosubmit:function(){var a=this;a.inputEl.bind("keydown",function(b){(b.ctrlKey||b.metaKey)&&13===b.keyCode&&a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").directive("editableUiSelect",["editableDirectiveFactory",function(a){var b=function(a,b){var c=angular.element("<"+a+"/>");c.html(b.html());for(var d=b[0].attributes,e=0;eb;b++)if(d[b].name===a)return b},d=[],e=[],f=a({directiveName:"editableUiSelect",inputTpl:"",render:function(){var a=c(this.name);this.parent.render.call(this),this.inputEl.append(b("ui-select-match",d[a].element)),this.inputEl.append(b("ui-select-choices",e[a].element)),this.inputEl.removeAttr("ng-model"),this.inputEl.attr("ng-model","$parent.$parent.$data")}}),g=f.link;return f.link=function(a,b,c,f){var h=b.find("editable-ui-select-match"),i=b.find("editable-ui-select-choices");return d.push({name:c.name||c.editableUiSelect,element:h.clone()}),e.push({name:c.name||c.editableUiSelect,element:i.clone()}),h.remove(),i.remove(),g(a,b,c,f)},f}]),angular.module("xeditable").factory("editableController",["$q","editableUtils",function(a,b){function c(a,c,d,e,f,g,h,i,j,k){var l,m,n=this;n.scope=a,n.elem=d,n.attrs=c,n.inputEl=null,n.editorEl=null,n.single=!0,n.error="",n.theme=f[h.theme]||f["default"],n.parent={},n.icon_set="default"===h.icon_set?g["default"][h.theme]:g.external[h.icon_set],n.inputTpl="",n.directiveName="",n.useCopy=!1,n.single=null,n.buttons="right",n.init=function(b){if(n.single=b,n.name=c.eName||c[n.directiveName],!c[n.directiveName])throw"You should provide value for `"+n.directiveName+"` in editable element!";l=e(c[n.directiveName]),n.single?n.buttons=n.attrs.buttons||h.buttons:n.buttons="no",c.eName&&n.scope.$watch("$data",function(a){n.scope.$form.$data[c.eName]=a}),c.onshow&&(n.onshow=function(){return n.catchError(e(c.onshow)(a))}),c.onhide&&(n.onhide=function(){return e(c.onhide)(a)}),c.oncancel&&(n.oncancel=function(){return e(c.oncancel)(a)}),c.onbeforesave&&(n.onbeforesave=function(){return n.catchError(e(c.onbeforesave)(a))}),c.onaftersave&&(n.onaftersave=function(){return n.catchError(e(c.onaftersave)(a))}),a.$parent.$watch(c[n.directiveName],function(a,b){n.setLocalValue(),n.handleEmpty()})},n.render=function(){var a=n.theme;n.inputEl=angular.element(n.inputTpl),n.controlsEl=angular.element(a.controlsTpl),n.controlsEl.append(n.inputEl),"no"!==n.buttons&&(n.buttonsEl=angular.element(a.buttonsTpl),n.submitEl=angular.element(a.submitTpl),n.cancelEl=angular.element(a.cancelTpl),n.icon_set&&(n.submitEl.find("span").addClass(n.icon_set.ok),n.cancelEl.find("span").addClass(n.icon_set.cancel)),n.buttonsEl.append(n.submitEl).append(n.cancelEl),n.controlsEl.append(n.buttonsEl),n.inputEl.addClass("editable-has-buttons")),n.errorEl=angular.element(a.errorTpl),n.controlsEl.append(n.errorEl),n.editorEl=angular.element(n.single?a.formTpl:a.noformTpl),n.editorEl.append(n.controlsEl);for(var d in c.$attr)if(!(d.length<=1)){var e=!1,f=d.substring(1,2);if("e"===d.substring(0,1)&&f===f.toUpperCase()&&(e=d.substring(1),"Form"!==e&&"NgSubmit"!==e)){e=e.substring(0,1).toLowerCase()+b.camelToDash(e.substring(1));var g="value"!==e&&""===c[d]?e:c[d];n.inputEl.attr(e,g)}}n.inputEl.addClass("editable-input"),n.inputEl.attr("ng-model","$parent.$data"),n.editorEl.addClass(b.camelToDash(n.directiveName)),n.single&&(n.editorEl.attr("editable-form","$form"),n.editorEl.attr("blur",n.attrs.blur||("no"===n.buttons?"cancel":h.blurElem))),angular.isFunction(a.postrender)&&a.postrender.call(n)},n.setLocalValue=function(){n.scope.$data=n.useCopy?angular.copy(l(a.$parent)):l(a.$parent)};var o=null;n.show=function(){return n.setLocalValue(),n.render(),d.after(n.editorEl),o=a.$new(),j(n.editorEl)(o),n.addListeners(),d.addClass("editable-hide"),n.onshow()},n.hide=function(){o.$destroy(),n.controlsEl.remove(),n.editorEl.remove(),d.removeClass("editable-hide");for(var b=0,c=a.$$watchers.length;c>b;b++)if(void 0!==a.$$watchers[b]&&a.$$watchers[b].last&&void 0!==a.$$watchers[b].last&&"object"==typeof a.$$watchers[b].last&&"has-error"in a.$$watchers[b].last){a.$$watchers.splice(b,1);break}return n.onhide()},n.cancel=function(){n.oncancel()},n.addListeners=function(){n.inputEl.bind("keyup",function(a){if(n.single)switch(a.keyCode){case 27:n.scope.$apply(function(){n.scope.$form.$cancel()})}}),n.single&&"no"===n.buttons&&n.autosubmit(),n.editorEl.bind("click",function(a){a.which&&1!==a.which||n.scope.$form.$visible&&(n.scope.$form._clicked=!0)})},n.setWaiting=function(a){a?(m=!n.inputEl.attr("disabled")&&!n.inputEl.attr("ng-disabled")&&!n.inputEl.attr("ng-enabled"),m&&(n.inputEl.attr("disabled","disabled"),n.buttonsEl&&n.buttonsEl.find("button").attr("disabled","disabled"))):m&&(n.inputEl.removeAttr("disabled"),n.buttonsEl&&n.buttonsEl.find("button").removeAttr("disabled"))},n.activate=function(a,b){setTimeout(function(){var c=n.inputEl[0];"focus"===h.activate&&c.focus&&(a&&(b=b||a,c.onfocus=function(){var c=this;setTimeout(function(){c.setSelectionRange(a,b)})}),c.focus()),"select"===h.activate&&c.select&&c.select()},0)},n.setError=function(b){angular.isObject(b)||(a.$error=b,n.error=b)},n.catchError=function(a,b){return angular.isObject(a)&&b!==!0?k.when(a).then(angular.bind(this,function(a){this.catchError(a,!0)}),angular.bind(this,function(a){this.catchError(a,!0)})):b&&angular.isObject(a)&&a.status&&200!==a.status&&a.data&&angular.isString(a.data)?(this.setError(a.data),a=a.data):angular.isString(a)&&this.setError(a),a},n.save=function(){l.assign(a.$parent,n.useCopy?angular.copy(n.scope.$data):n.scope.$data)},n.handleEmpty=function(){var b=l(a.$parent),c=null===b||void 0===b||""===b||angular.isArray(b)&&0===b.length;d.toggleClass("editable-empty",c)},n.autosubmit=angular.noop,n.onshow=angular.noop,n.onhide=angular.noop,n.oncancel=angular.noop,n.onbeforesave=angular.noop,n.onaftersave=angular.noop}return c.$inject=["$scope","$attrs","$element","$parse","editableThemes","editableIcons","editableOptions","$rootScope","$compile","$q"],c}]),angular.module("xeditable").factory("editableDirectiveFactory",["$parse","$compile","editableThemes","$rootScope","$document","editableController","editableFormController","editableOptions",function(a,b,c,d,e,f,g,h){return function(b){return{restrict:"A",scope:!0,require:[b.directiveName,"?^form"],controller:f,link:function(c,f,i,j){var k,l=j[0],m=!1;if(j[1])k=j[1],m=void 0===i.eSingle;else if(i.eForm){var n=a(i.eForm)(c);if(n)k=n,m=!0;else if(f&&"function"==typeof f.parents&&f.parents().last().find("form[name="+i.eForm+"]").length)k=null,m=!0;else for(var o=0;o=0&&a.splice(c,1),b},camelToDash:function(a){var b=/[A-Z]/g;return a.replace(b,function(a,b){return(b?"-":"")+a.toLowerCase()})},dashToCamel:function(a){var b=/([\:\-\_]+(.))/g,c=/^moz([A-Z])/;return a.replace(b,function(a,b,c,d){return d?c.toUpperCase():c}).replace(c,"Moz$1")}}}]),angular.module("xeditable").factory("editableNgOptionsParser",[function(){function a(a){var c;if(!(c=a.match(b)))throw"ng-options parse error";var d,e=c[2]||c[1],f=c[4]||c[6],g=c[5],h=(c[3]||"",c[2]?c[1]:f),i=c[7],j=c[8],k=j?c[8]:null;return void 0===g?(d=f+" in "+i,void 0!==j&&(d+=" track by "+k)):d="("+g+", "+f+") in "+i,{ngRepeat:d,locals:{valueName:f,keyName:g,valueFn:h,displayFn:e}}}var b=/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/;return a}]),angular.module("xeditable").factory("editableCombodate",[function(){function a(a,b){if(this.$element=angular.element(a),"INPUT"!=this.$element[0].nodeName)throw"Combodate should be applied to INPUT element";var c=(new Date).getFullYear();this.defaults={format:"YYYY-MM-DD HH:mm",template:"D / MMM / YYYY H : mm",value:null,minYear:1970,maxYear:c,yearDescending:!0,minuteStep:5,secondStep:1,firstItem:"empty",errorClass:null,customClass:"",roundTime:!0,smartDays:!0},this.options=angular.extend({},this.defaults,b),this.init()}return a.prototype={constructor:a,init:function(){if(this.map={day:["D","date"],month:["M","month"],year:["Y","year"],hour:["[Hh]","hours"],minute:["m","minutes"],second:["s","seconds"],ampm:["[Aa]",""]},this.$widget=angular.element('').html(this.getTemplate()),this.initCombos(),this.options.smartDays){var a=this;this.$widget.find("select").bind("change",function(b){(angular.element(b.target).hasClass("month")||angular.element(b.target).hasClass("year"))&&a.fillCombo("day")})}this.$widget.find("select").css("width","auto"),this.$element.css("display","none").after(this.$widget),this.setValue(this.$element.val()||this.options.value)},getTemplate:function(){var a=this.options.template,b=this.options.customClass;return angular.forEach(this.map,function(b,c){b=b[0];var d=new RegExp(b+"+"),e=b.length>1?b.substring(1,2):b;a=a.replace(d,"{"+e+"}")}),a=a.replace(/ /g," "),angular.forEach(this.map,function(c,d){c=c[0];var e=c.length>1?c.substring(1,2):c;a=a.replace("{"+e+"}",'')}),a},initCombos:function(){for(var a in this.map){var b=this.$widget[0].querySelectorAll("."+a);this["$"+a]=b.length?angular.element(b):null,this.fillCombo(a)}},fillCombo:function(a){var b=this["$"+a];if(b){var c="fill"+a.charAt(0).toUpperCase()+a.slice(1),d=this[c](),e=b.val();b.html("");for(var f=0;f'+d[f][1]+"");b.val(e)}},fillCommon:function(a){var b,c=[];if("name"===this.options.firstItem){b=moment.relativeTime||moment.langData()._relativeTime;var d="function"==typeof b[a]?b[a](1,!0,a,!1):b[a];d=d.split(" ").reverse()[0],c.push(["",d])}else"empty"===this.options.firstItem&&c.push(["",""]);return c},fillDay:function(){var a,b,c=this.fillCommon("d"),d=-1!==this.options.template.indexOf("DD"),e=31;if(this.options.smartDays&&this.$month&&this.$year){var f=parseInt(this.$month.val(),10),g=parseInt(this.$year.val(),10);isNaN(f)||isNaN(g)||(e=moment([g,f]).daysInMonth())}for(b=1;e>=b;b++)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillMonth:function(){var a,b,c=this.fillCommon("M"),d=-1!==this.options.template.indexOf("MMMM"),e=-1!==this.options.template.indexOf("MMM"),f=-1!==this.options.template.indexOf("MM");for(b=0;11>=b;b++)a=d?moment().date(1).month(b).format("MMMM"):e?moment().date(1).month(b).format("MMM"):f?this.leadZero(b+1):b+1,c.push([b,a]);return c},fillYear:function(){var a,b,c=[],d=-1!==this.options.template.indexOf("YYYY");for(b=this.options.maxYear;b>=this.options.minYear;b--)a=d?b:(b+"").substring(2),c[this.options.yearDescending?"push":"unshift"]([b,a]);return c=this.fillCommon("y").concat(c)},fillHour:function(){var a,b,c=this.fillCommon("h"),d=-1!==this.options.template.indexOf("h"),e=(-1!==this.options.template.indexOf("H"),-1!==this.options.template.toLowerCase().indexOf("hh")),f=d?1:0,g=d?12:23;for(b=f;g>=b;b++)a=e?this.leadZero(b):b,c.push([b,a]);return c},fillMinute:function(){var a,b,c=this.fillCommon("m"),d=-1!==this.options.template.indexOf("mm");for(b=0;59>=b;b+=this.options.minuteStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillSecond:function(){var a,b,c=this.fillCommon("s"),d=-1!==this.options.template.indexOf("ss");for(b=0;59>=b;b+=this.options.secondStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillAmpm:function(){var a=-1!==this.options.template.indexOf("a"),b=(-1!==this.options.template.indexOf("A"),[["am",a?"am":"AM"],["pm",a?"pm":"PM"]]);return b},getValue:function(a){var b,c={},d=this,e=!1;return angular.forEach(this.map,function(a,b){if("ampm"!==b){var f="day"===b?1:0;return c[b]=d["$"+b]?parseInt(d["$"+b].val(),10):f,isNaN(c[b])?(e=!0,!1):void 0}}),e?"":(this.$ampm&&(12===c.hour?c.hour="am"===this.$ampm.val()?0:12:c.hour="am"===this.$ampm.val()?c.hour:c.hour+12),b=moment([c.year,c.month,c.day,c.hour,c.minute,c.second]),this.highlight(b),a=void 0===a?this.options.format:a,null===a?b.isValid()?b:null:b.isValid()?b.format(a):"")},setValue:function(a){function b(a,b){var c={};return angular.forEach(a.children("option"),function(a,d){var e=angular.element(a).attr("value");if(""!==e){var f=Math.abs(e-b);("undefined"==typeof c.distance||f=12?(e.ampm="pm",e.hour>12&&(e.hour-=12)):(e.ampm="am",0===e.hour&&(e.hour=12))),angular.forEach(e,function(a,c){d["$"+c]&&("minute"===c&&d.options.minuteStep>1&&d.options.roundTime&&(a=b(d["$"+c],a)),"second"===c&&d.options.secondStep>1&&d.options.roundTime&&(a=b(d["$"+c],a)),d["$"+c].val(a))}),this.options.smartDays&&this.fillCombo("day"),this.$element.val(c.format(this.options.format)).triggerHandler("change"))}},highlight:function(a){a.isValid()?this.options.errorClass?this.$widget.removeClass(this.options.errorClass):this.$widget.find("select").css("border-color",this.borderColor):this.options.errorClass?this.$widget.addClass(this.options.errorClass):(this.borderColor||(this.borderColor=this.$widget.find("select").css("border-color")),this.$widget.find("select").css("border-color","red"))},leadZero:function(a){return 9>=a?"0"+a:a},destroy:function(){this.$widget.remove(),this.$element.removeData("combodate").show()}},{getInstance:function(b,c){return new a(b,c)}}}]),angular.module("xeditable").factory("editableIcons",function(){var a={"default":{bs2:{ok:"icon-ok icon-white",cancel:"icon-remove"},bs3:{ok:"glyphicon glyphicon-ok",cancel:"glyphicon glyphicon-remove"}},external:{"font-awesome":{ok:"fa fa-check",cancel:"fa fa-times"}}};return a}),angular.module("xeditable").factory("editableThemes",function(){var a={"default":{formTpl:'
',noformTpl:'',controlsTpl:'',inputTpl:"",errorTpl:'
',buttonsTpl:'',submitTpl:'',cancelTpl:''},bs2:{formTpl:'
',noformTpl:'',controlsTpl:'
',inputTpl:"",errorTpl:'
',buttonsTpl:'',submitTpl:'',cancelTpl:''},bs3:{formTpl:'
',noformTpl:'',controlsTpl:'
',inputTpl:"",errorTpl:'
',buttonsTpl:'',submitTpl:'',cancelTpl:'',buttonsClass:"",inputClass:"",postrender:function(){switch(this.directiveName){case"editableText":case"editableSelect":case"editableTextarea":case"editableEmail":case"editableTel":case"editableNumber":case"editableUrl":case"editableSearch":case"editableDate":case"editableDatetime":case"editableBsdate":case"editableTime":case"editableMonth":case"editableWeek":case"editablePassword":case"editableDatetimeLocal":if(this.inputEl.addClass("form-control"),this.theme.inputClass){if(this.inputEl.attr("multiple")&&("input-sm"===this.theme.inputClass||"input-lg"===this.theme.inputClass))break;this.inputEl.addClass(this.theme.inputClass)}break;case"editableCheckbox":this.editorEl.addClass("checkbox")}this.buttonsEl&&this.theme.buttonsClass&&this.buttonsEl.find("button").addClass(this.theme.buttonsClass)}},semantic:{formTpl:'
',noformTpl:'',controlsTpl:'
',inputTpl:"",errorTpl:'
',buttonsTpl:'',submitTpl:'',cancelTpl:''}};return a}); \ No newline at end of file diff --git a/index.html b/index.html index a88f692a..579092a3 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,7 @@ - + @@ -20,11 +20,11 @@ - + - + - + @@ -45,7 +45,7 @@
  • Home
  • GitHub
  • - +
    @@ -124,6 +124,8 @@
  • Select multiple
  • Validate local
  • Validate remote
  • +
  • Disable editing
  • +
  • Editable Popover
  • Submit @@ -210,7 +212,7 @@

    Get started

    <link href="https://netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
  • -
  • Install angular-xeditable via bower or download latest zip +
  • Install angular-xeditable via bower or download latest zip
    bower install angular-xeditable 
  • Include angular-xeditable into your project @@ -248,7 +250,7 @@

    Text

    demo

    jsFiddle
    {{ debug["text-simple"] | json }}

    To make element editable via textbox just add editable-text="model.field" attribute.

    @@ -261,7 +263,7 @@

    demo

    html

    <div ng-controller="TextSimpleCtrl">
    -  <a href="#" editable-text="user.name">{{ user.name || 'empty' }}</a>
    +  <a href="#" editable-text="user.name" e-label="User Name">{{ user.name || 'empty' }}</a>
     </div>

    controller.js

    app.controller('TextSimpleCtrl', function($scope) {
    @@ -282,7 +284,8 @@ 

    demo

    To create editable select (dropdown) just set editable-select attribute pointing to model. To pass dropdown options you should define e-ng-options attribute -that works like normal angular ng-options but is transfered to underlying <select> from original element.

    +that works like normal angular ng-options but is transfered to underlying <select> from original element. +To set a default option in the list add the e-placeholder attribute.

    html

    @@ -462,6 +468,7 @@

    html

    <div>Month: <a href="#" editable-month="user.month">{{ (user.month | date: "yyyy-MM") || 'empty' }}</a></div> <div>Week: <a href="#" editable-week="user.week">{{ (user.week | date: "yyyy-Www") || 'empty'}}</a></div> <div>Password: <a href="#" editable-password="user.password">{{ user.password || 'empty' }}</a></div> + <div>Datetime-local: <a href="#" editable-datetime-local="user.datetimeLocal">{{ (user.datetimeLocal | date: "yyyy-MM-ddTHH:mm:ss") || 'empty' }}</a></div> </div>

    controller.js

    app.controller('Html5InputsCtrl', function($scope) {
    @@ -478,7 +485,8 @@ 

    controller.js

    datetime: null, month: null, week: null, - password: 'password' + password: 'password', + datetimeLocal: null }; });
    @@ -623,7 +631,7 @@

    Radiolist

    demo

    @@ -653,7 +661,7 @@

    demo

    $scope.$watch("user", function(v) { $scope.$parent.debug["radiolist"]=v; }); });

    html

    <div ng-controller="RadiolistCtrl">
    -  <a href="#" editable-radiolist="user.status" e-ng-options="s.value as s.text for s in statuses">
    +  <a href="#" editable-radiolist="user.status" e-ng-options="s.value as s.text for s in ::statuses track by s.value">
         {{ showStatus() }}
       </a>
     </div>
    @@ -685,11 +693,10 @@

    demo

    Date control is implemented via Angular-ui bootstrap datepicker.
    You should include additional ui-bootstrap-tpls.min.js:

    -
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.2.4/ui-bootstrap-tpls.min.js"></script>
    +
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.1/ui-bootstrap-tpls.min.js"></script>

    Add ui.bootstrap as module dependency:

    var app = angular.module("app", ["xeditable", "ui.bootstrap"]);
    -

    And set editable-bsdate attribute in editable element. -Other parameters can be defined via e-* syntax, e.g. e-datepicker-popup="dd-MMMM-yyyy".

    +

    And set editable-bsdate attribute in editable element.
    To make the input field read-only and force the date to be selected from the popup, add the e-readonly="true" attribute.
    Add e-ng-change attribute to call a function when the value of the datepicker is changed.
    To hide the calendar button and display the calendar popup on click of the input field, set the e-show-calendar-button attribute to false.
    Other parameters can be defined via e-* syntax, e.g. e-datepicker-popup="dd-MMMM-yyyy".

    html

    <div ng-controller="TextCustomizeCtrl">
    -  <a href="#" editable-text="user.name" e-style="color: green" e-required e-placeholder="Enter name">
    +  <a href="#" editable-text="user.name" e-style="color: green" e-required e-placeholder="Enter name" e-formclass="class1 class2">
         {{ (user.name || 'empty') | uppercase }}
       </a>
     </div>
    @@ -1246,6 +1252,64 @@

    controller.js

    }); return d.promise; }; +}); + +
    +

    Disable editing

    + +

    demo

    + +
    {{ debug["edit-disabled"] | json }}
    +

    To disable an element from being editable, just add the edit-disabled="true" attribute. Additionally, you can disable all elements at a global level by setting editableOptions.isDisabled=true.

    +

    + + +

    html

    +
    <div ng-controller="EditDisabledCtrl">
    +  <a href="#" editable-text="user.name" edit-disabled="{{user && user.name == 'awesome user'}}">{{user.name || 'empty' }}</a>
    +</div>
    +

    controller.js

    +
    app.controller('EditDisabledCtrl', function($scope) {
    +  $scope.user = {
    +    name: 'awesome user'
    +  };  
    +});
    +
    +
    +

    Editable Popover

    + +

    demo

    + +
    {{ debug["editable-popover"] | json }}
    +

    To made an editable field display in a popover, wrap the editable in <div class="item-wrapper">.

    +

    + + +

    html

    +
    <div ng-controller="EditPopoverCtrl">
    +  <div class="popover-wrapper">
    +    <a href="#" editable-text="user.name">{{user.name || 'empty' }}</a>
    +  </div>
    +</div>
    +

    controller.js

    +
    app.controller('EditPopoverCtrl', function($scope) {
    +  $scope.user = {
    +    name: 'awesome user'
    +  };  
     });
    @@ -1437,6 +1501,7 @@

    demo

    - + {{ user.name || 'empty' }} @@ -1720,7 +1785,7 @@

    html

    <tr ng-repeat="user in users"> <td> <!-- editable username (text with validation) --> - <span editable-text="user.name" e-name="name" e-form="rowform" onbeforesave="checkName($data, user.id)" e-required> + <span editable-text="user.name" e-name="name" e-form="rowform" onbeforesave="checkName($data, user.id)"> {{ user.name || 'empty' }} </span> </td> @@ -2644,7 +2709,8 @@

    Methods

    Methods are available when you set name attribut $activate(name) name (string) name of field
    -

    Sets focus on form field specified by name.

    +

    Sets focus on form field specified by name.
    +When trying to set the focus on a form field of a new row in the editable table, the $activate call needs to be wrapped in a $timeout call so that the form is rendered before the $activate function is called.

    diff --git a/package.json b/package.json index 964d0fc6..4512d5ef 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-xeditable", "description": "Edit-in-place for angular.js", - "version": "0.1.12", + "version": "0.2.0", "homepage": "https://vitalets.github.io/angular-xeditable", "author": { "name": "Vitaliy Potapov", diff --git a/starter/angular-xeditable/css/xeditable.css b/starter/angular-xeditable/css/xeditable.css index 8919a903..ae9d4642 100644 --- a/starter/angular-xeditable/css/xeditable.css +++ b/starter/angular-xeditable/css/xeditable.css @@ -113,4 +113,53 @@ a.editable-empty:focus { text-decoration: none; } +/* editable popover */ +.popover-wrapper a { + /* make the link always show up */ + display: inline !important; +} + +.popover-wrapper { + /* make absolutely positioned children constrained to this box*/ + display: inline; + position: relative; +} + +.popover-wrapper form { + position: absolute; + top: -53px; + background: #FFF; + border: 1px solid #AAA; + border-radius: 5px; + padding: 7px; + width: auto; + display: inline-block; + left: 50%; + margin-left: -110px; + z-index: 101; +} + +.popover-wrapper form:before { + content:""; + width: 0; + height: 0; + border-left: 10px solid transparent; + border-right: 10px solid transparent; + border-top: 10px solid #AAA; + position:absolute; + bottom:-10px; + left:100px; +} + +.popover-wrapper form:after { + content:""; + width:0; + height:0; + border-left: 9px solid transparent; + border-right: 9px solid transparent; + border-top: 9px solid #FFF; + position:absolute; + bottom:-9px; + left:101px; +} diff --git a/starter/angular-xeditable/css/xeditable.min.css b/starter/angular-xeditable/css/xeditable.min.css index 4590ae42..376e3dd2 100644 --- a/starter/angular-xeditable/css/xeditable.min.css +++ b/starter/angular-xeditable/css/xeditable.min.css @@ -1,7 +1,7 @@ /*! -angular-xeditable - 0.1.12 +angular-xeditable - 0.2.0 Edit-in-place for angular.js -Build date: 2016-04-14 +Build date: 2016-06-28 */ -.editable-wrap{display:inline-block;white-space:nowrap;margin:0}.editable-wrap .editable-controls,.editable-wrap .editable-error{margin-bottom:0}.editable-wrap .editable-controls>input,.editable-wrap .editable-controls>select,.editable-wrap .editable-controls>textarea{margin-bottom:0}.editable-wrap .editable-input{display:inline-block}.editable-buttons{display:inline-block;vertical-align:top}.editable-buttons button{margin-left:5px}.editable-input.editable-has-buttons{width:auto}.editable-bstime .editable-input input[type=text]{width:46px}.editable-bstime .well-small{margin-bottom:0;padding:10px}.editable-range output{display:inline-block;min-width:30px;vertical-align:top;text-align:center}.editable-color input[type=color]{width:50px}.editable-checkbox label span,.editable-checklist label span,.editable-radiolist label span{margin-left:7px;margin-right:10px}.editable-hide{display:none!important}.editable-click,a.editable-click{text-decoration:none;color:#428bca;border-bottom:dashed 1px #428bca}.editable-click:hover,a.editable-click:hover{text-decoration:none;color:#2a6496;border-bottom-color:#2a6496}.editable-empty,.editable-empty:hover,.editable-empty:focus,a.editable-empty,a.editable-empty:hover,a.editable-empty:focus{font-style:italic;color:#D14;text-decoration:none} \ No newline at end of file +.editable-wrap{display:inline-block;white-space:nowrap;margin:0}.editable-wrap .editable-controls,.editable-wrap .editable-error{margin-bottom:0}.editable-wrap .editable-controls>input,.editable-wrap .editable-controls>select,.editable-wrap .editable-controls>textarea{margin-bottom:0}.editable-wrap .editable-input{display:inline-block}.editable-buttons{display:inline-block;vertical-align:top}.editable-buttons button{margin-left:5px}.editable-input.editable-has-buttons{width:auto}.editable-bstime .editable-input input[type=text]{width:46px}.editable-bstime .well-small{margin-bottom:0;padding:10px}.editable-range output{display:inline-block;min-width:30px;vertical-align:top;text-align:center}.editable-color input[type=color]{width:50px}.editable-checkbox label span,.editable-checklist label span,.editable-radiolist label span{margin-left:7px;margin-right:10px}.editable-hide{display:none!important}.editable-click,a.editable-click{text-decoration:none;color:#428bca;border-bottom:dashed 1px #428bca}.editable-click:hover,a.editable-click:hover{text-decoration:none;color:#2a6496;border-bottom-color:#2a6496}.editable-empty,.editable-empty:hover,.editable-empty:focus,a.editable-empty,a.editable-empty:hover,a.editable-empty:focus{font-style:italic;color:#D14;text-decoration:none}.popover-wrapper a{display:inline!important}.popover-wrapper{display:inline;position:relative}.popover-wrapper form{position:absolute;top:-53px;background:#FFF;border:1px solid #AAA;border-radius:5px;padding:7px;width:auto;display:inline-block;left:50%;margin-left:-110px;z-index:101}.popover-wrapper form:before{content:"";width:0;height:0;border-left:10px solid transparent;border-right:10px solid transparent;border-top:10px solid #AAA;position:absolute;bottom:-10px;left:100px}.popover-wrapper form:after{content:"";width:0;height:0;border-left:9px solid transparent;border-right:9px solid transparent;border-top:9px solid #FFF;position:absolute;bottom:-9px;left:101px} \ No newline at end of file diff --git a/starter/angular-xeditable/js/xeditable.js b/starter/angular-xeditable/js/xeditable.js index 2bc855e5..8817d68b 100644 --- a/starter/angular-xeditable/js/xeditable.js +++ b/starter/angular-xeditable/js/xeditable.js @@ -1,7 +1,7 @@ /*! -angular-xeditable - 0.1.12 +angular-xeditable - 0.2.0 Edit-in-place for angular.js -Build date: 2016-04-14 +Build date: 2016-06-28 */ /** * Angular-xeditable module @@ -97,16 +97,12 @@ angular.module('xeditable').directive('editableBsdate', ['editableDirectiveFacto **/ this.parent.render.call(this); - var inputDatePicker = angular.element(''); - var buttonDatePicker = angular.element(''); - var buttonWrapper = angular.element(''); + var inputDatePicker = angular.element(''); inputDatePicker.attr('uib-datepicker-popup', this.attrs.eDatepickerPopupXEditable || 'yyyy/MM/dd' ); inputDatePicker.attr('is-open', this.attrs.eIsOpen); inputDatePicker.attr('date-disabled', this.attrs.eDateDisabled); inputDatePicker.attr('uib-datepicker-popup', this.attrs.eDatepickerPopup); - inputDatePicker.attr('min-date', this.attrs.eMinDate); - inputDatePicker.attr('max-date', this.attrs.eMaxDate); inputDatePicker.attr('year-range', this.attrs.eYearRange || 20); inputDatePicker.attr('show-button-bar', this.attrs.eShowButtonBar || true); inputDatePicker.attr('current-text', this.attrs.eCurrentText || 'Today'); @@ -116,6 +112,13 @@ angular.module('xeditable').directive('editableBsdate', ['editableDirectiveFacto inputDatePicker.attr('datepicker-append-to-body', this.attrs.eDatePickerAppendToBody || false); inputDatePicker.attr('date-disabled', this.attrs.eDateDisabled); inputDatePicker.attr('name', this.attrs.eName); + inputDatePicker.attr('on-open-focus', this.attrs.eOnOpenFocus || true); + inputDatePicker.attr('ng-readonly', this.attrs.eReadonly || false); + + if (this.attrs.eNgChange) { + inputDatePicker.attr('ng-change', this.attrs.eNgChange); + this.inputEl.removeAttr('ng-change'); + } this.scope.dateOptions = { formatDay: this.attrs.eFormatDay || 'dd', @@ -128,17 +131,32 @@ angular.module('xeditable').directive('editableBsdate', ['editableDirectiveFacto startingDay: this.attrs.eStartingDay || 0, minMode: this.attrs.eMinMode || 'day', maxMode: this.attrs.eMaxMode || 'year', - initDate: this.attrs.eInitDate || new Date(), - datepickerMode: this.attrs.eDatepickerMode || 'day' + initDate: this.scope.$eval(this.attrs.eInitDate) || new Date(), + datepickerMode: this.attrs.eDatepickerMode || 'day', + maxDate: this.scope.$eval(this.attrs.eMaxDate) || null, + minDate: this.scope.$eval(this.attrs.eMinDate) || null }; - inputDatePicker.attr('datepicker-options', "dateOptions"); + var showCalendarButton = angular.isDefined(this.attrs.eShowCalendarButton) ? this.attrs.eShowCalendarButton : "true"; + + //See if calendar button should be displayed + if (showCalendarButton === "true") { + var buttonDatePicker = angular.element(''); + var buttonWrapper = angular.element(''); + + buttonDatePicker.attr('ng-click', this.attrs.eNgClick); + + buttonWrapper.append(buttonDatePicker); - buttonDatePicker.attr('ng-click',this.attrs.eNgClick); + this.inputEl.append(buttonWrapper); + } else { + //If no calendar button, display calendar popup on click of input field + inputDatePicker.attr('ng-click', this.attrs.eNgClick); + } + + inputDatePicker.attr('datepicker-options', "dateOptions"); - buttonWrapper.append(buttonDatePicker); this.inputEl.prepend(inputDatePicker); - this.inputEl.append(buttonWrapper); this.inputEl.removeAttr('class'); this.inputEl.removeAttr('ng-click'); @@ -224,7 +242,7 @@ angular.module('xeditable').directive('editableChecklist', [ this.parent.render.call(this); var parsed = editableNgOptionsParser(this.attrs.eNgOptions); var html = ''; this.inputEl.removeAttr('ng-model'); @@ -264,23 +282,43 @@ angular.module('xeditable').directive('editableCombodate', ['editableDirectiveFa ]); /* -Input types: text|email|tel|number|url|search|color|date|datetime|time|month|week +Input types: text|password|email|tel|number|url|search|color|date|datetime|datetime-local|time|month|week|file */ (function() { - var types = 'text|password|email|tel|number|url|search|color|date|datetime|time|month|week|file'.split('|'); + var camelCase = function(dashDelimitedString) { + return dashDelimitedString.toLowerCase().replace(/-(.)/g, function(match, word) { + return word.toUpperCase(); + }); + }; + + var types = 'text|password|email|tel|number|url|search|color|date|datetime|datetime-local|time|month|week|file'.split('|'); //todo: datalist // generate directives angular.forEach(types, function(type) { - var directiveName = 'editable'+type.charAt(0).toUpperCase() + type.slice(1); + var directiveName = camelCase('editable' + '-' + type); angular.module('xeditable').directive(directiveName, ['editableDirectiveFactory', function(editableDirectiveFactory) { return editableDirectiveFactory({ directiveName: directiveName, - inputTpl: '' + inputTpl: '', + render: function() { + this.parent.render.call(this); + + // Add label to the input + if (this.attrs.eLabel) { + var label = angular.element(''); + this.inputEl.parent().prepend(label); + } + + // Add classes to the form + if (this.attrs.eFormclass) { + this.editorEl.addClass(this.attrs.eFormclass); + } + } }); }]); }); @@ -312,9 +350,10 @@ angular.module('xeditable').directive('editableRadiolist', [ render: function() { this.parent.render.call(this); var parsed = editableNgOptionsParser(this.attrs.eNgOptions); - var html = ''; + + var html = ''; this.inputEl.removeAttr('ng-model'); this.inputEl.removeAttr('ng-options'); @@ -339,6 +378,14 @@ angular.module('xeditable').directive('editableSelect', ['editableDirectiveFacto return editableDirectiveFactory({ directiveName: 'editableSelect', inputTpl: '', + render: function() { + this.parent.render.call(this); + + if (this.attrs.ePlaceholder) { + var placeholder = angular.element(''); + this.inputEl.append(placeholder); + } + }, autosubmit: function() { var self = this; self.inputEl.bind('change', function() { @@ -392,17 +439,27 @@ angular.module('xeditable').directive('editableUiSelect',['editableDirectiveFact return newEl; }; - var match = null; - var choices = null; + var findElement = function(name) { + for(var i = 0, len = match.length; i < len; i++) { + if (match[i].name === name) { + return i; + } + } + }; + + var match = []; + var choices = []; + var dir = editableDirectiveFactory({ directiveName: 'editableUiSelect', inputTpl: '', render: function () { + var index = findElement(this.name); this.parent.render.call(this); - this.inputEl.append(rename('ui-select-match', match)); - this.inputEl.append(rename('ui-select-choices', choices)); + this.inputEl.append(rename('ui-select-match', match[index].element)); + this.inputEl.append(rename('ui-select-choices', choices[index].element)); this.inputEl.removeAttr('ng-model'); - this.inputEl.attr('ng-model', '$parent.$data'); + this.inputEl.attr('ng-model', '$parent.$parent.$data'); } }); @@ -412,8 +469,8 @@ angular.module('xeditable').directive('editableUiSelect',['editableDirectiveFact var matchEl = el.find('editable-ui-select-match'); var choicesEl = el.find('editable-ui-select-choices'); - match = matchEl.clone(); - choices = choicesEl.clone(); + match.push({name : attrs.name || attrs.editableUiSelect, element : matchEl.clone()}); + choices.push({name : attrs.name || attrs.editableUiSelect, element : choicesEl.clone()}); matchEl.remove(); choicesEl.remove(); @@ -670,7 +727,7 @@ angular.module('xeditable').factory('editableController', } self.inputEl.addClass('editable-input'); - self.inputEl.attr('ng-model', '$data'); + self.inputEl.attr('ng-model', '$parent.$data'); // add directiveName class to editor, e.g. `editable-text` self.editorEl.addClass(editableUtils.camelToDash(self.directiveName)); @@ -697,6 +754,8 @@ angular.module('xeditable').factory('editableController', valueGetter($scope.$parent); }; + // reference of the scope to use for $compile + var newScope = null; //show self.show = function() { // set value of scope.$data @@ -713,7 +772,8 @@ angular.module('xeditable').factory('editableController', $element.after(self.editorEl); // compile (needed to attach ng-* events from markup) - $compile(self.editorEl)($scope); + newScope = $scope.$new(); + $compile(self.editorEl)(newScope); // attach listeners (`escape`, autosubmit, etc) self.addListeners(); @@ -727,10 +787,23 @@ angular.module('xeditable').factory('editableController', //hide self.hide = function() { - + + // destroy the scope to prevent memory leak + newScope.$destroy(); + + self.controlsEl.remove(); self.editorEl.remove(); $element.removeClass('editable-hide'); + // Manually remove the watcher on 'has-error' to prevent a memory leak on it. + for (var i = 0, len = $scope.$$watchers.length; i < len; i++) { + if ($scope.$$watchers[i] !== undefined && $scope.$$watchers[i].last && $scope.$$watchers[i].last !== undefined && + typeof $scope.$$watchers[i].last === 'object' && "has-error" in $scope.$$watchers[i].last) { + $scope.$$watchers.splice(i, 1); + break; + } + } + // onhide return self.onhide(); }; @@ -921,23 +994,28 @@ function($parse, $compile, editableThemes, $rootScope, $document, editableContro // form controller var eFormCtrl; - // this variable indicates is element is bound to some existing form, + // this variable indicates is element is bound to some existing form, // or it's single element who's form will be generated automatically // By default consider single element without any linked form.ß var hasForm = false; - + // element wrapped by form - if(ctrl[1]) { + if (ctrl[1]) { eFormCtrl = ctrl[1]; hasForm = attrs.eSingle === undefined; - } else if(attrs.eForm) { // element not wrapped by
    , but we hane `e-form` attr + } else if (attrs.eForm) { // element not wrapped by , but we hane `e-form` attr var getter = $parse(attrs.eForm)(scope); - if(getter) { // form exists in scope (above), e.g. editable column + if (getter) { // form exists in scope (above), e.g. editable column eFormCtrl = getter; hasForm = true; - } else { // form exists below or not exist at all: check document.forms - for(var i=0; i<$document[0].forms.length;i++){ - if($document[0].forms[i].name === attrs.eForm) { + } else if (elem && typeof elem.parents === "function" && elem.parents().last().find('form[name='+attrs.eForm+']').length) { // form exists below or not exist at all: check document.forms + // form is below and not processed yet + eFormCtrl = null; + hasForm = true; + } else { + // form exists below or not exist at all: check document.forms + for (var i=0; i<$document[0].forms.length;i++) { + if ($document[0].forms[i].name === attrs.eForm) { // form is below and not processed yet eFormCtrl = null; hasForm = true; @@ -978,7 +1056,7 @@ function($parse, $compile, editableThemes, $rootScope, $document, editableContro if (disabled) { return; } - + // init editable ctrl eCtrl.init(!hasForm); @@ -1012,7 +1090,7 @@ function($parse, $compile, editableThemes, $rootScope, $document, editableContro // if `e-form` provided, publish local $form in scope if(attrs.eForm) { - scope.$parent[attrs.eForm] = scope.$form; + ($parse(attrs.eForm).assign || angular.noop)(scope.$parent, scope.$form); } // bind click - if no external form defined @@ -1194,7 +1272,8 @@ angular.module('xeditable').factory('editableFormController', }, /** - * Sets focus on form field specified by `name`. + * Sets focus on form field specified by `name`.
    + * When trying to set the focus on a form field of a new row in the editable table, the `$activate` call needs to be wrapped in a `$timeout` call so that the form is rendered before the `$activate` function is called. * * @method $activate(name) * @param {string} name name of field @@ -2225,7 +2304,7 @@ angular.module('xeditable').factory('editableThemes', function() { noformTpl: '', controlsTpl: '', inputTpl: '', - errorTpl: '
    ', + errorTpl: '
    ', buttonsTpl: '', submitTpl: '', cancelTpl: '' @@ -2237,7 +2316,7 @@ angular.module('xeditable').factory('editableThemes', function() { noformTpl: '', controlsTpl: '
    ', inputTpl: '', - errorTpl: '
    ', + errorTpl: '
    ', buttonsTpl: '', submitTpl: '', cancelTpl: '', cancelTpl: '', cancelTpl: ''),c=angular.element('');a.attr("uib-datepicker-popup",this.attrs.eDatepickerPopupXEditable||"yyyy/MM/dd"),a.attr("is-open",this.attrs.eIsOpen),a.attr("date-disabled",this.attrs.eDateDisabled),a.attr("uib-datepicker-popup",this.attrs.eDatepickerPopup),a.attr("min-date",this.attrs.eMinDate),a.attr("max-date",this.attrs.eMaxDate),a.attr("year-range",this.attrs.eYearRange||20),a.attr("show-button-bar",this.attrs.eShowButtonBar||!0),a.attr("current-text",this.attrs.eCurrentText||"Today"),a.attr("clear-text",this.attrs.eClearText||"Clear"),a.attr("close-text",this.attrs.eCloseText||"Done"),a.attr("close-on-date-selection",this.attrs.eCloseOnDateSelection||!0),a.attr("datepicker-append-to-body",this.attrs.eDatePickerAppendToBody||!1),a.attr("date-disabled",this.attrs.eDateDisabled),a.attr("name",this.attrs.eName),this.scope.dateOptions={formatDay:this.attrs.eFormatDay||"dd",formatMonth:this.attrs.eFormatMonth||"MMMM",formatYear:this.attrs.eFormatYear||"yyyy",formatDayHeader:this.attrs.eFormatDayHeader||"EEE",formatDayTitle:this.attrs.eFormatDayTitle||"MMMM yyyy",formatMonthTitle:this.attrs.eFormatMonthTitle||"yyyy",showWeeks:this.attrs.eShowWeeks?"true"===this.attrs.eShowWeeks.toLowerCase():!0,startingDay:this.attrs.eStartingDay||0,minMode:this.attrs.eMinMode||"day",maxMode:this.attrs.eMaxMode||"year",initDate:this.attrs.eInitDate||new Date,datepickerMode:this.attrs.eDatepickerMode||"day"},a.attr("datepicker-options","dateOptions"),b.attr("ng-click",this.attrs.eNgClick),c.append(b),this.inputEl.prepend(a),this.inputEl.append(c),this.inputEl.removeAttr("class"),this.inputEl.removeAttr("ng-click"),this.inputEl.removeAttr("is-open"),this.inputEl.removeAttr("init-date"),this.inputEl.removeAttr("datepicker-popup"),this.inputEl.removeAttr("required"),this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("date-picker-append-to-body"),this.inputEl.removeAttr("name"),this.inputEl.attr("class","input-group")}})}]),angular.module("xeditable").directive("editableBstime",["editableDirectiveFactory",function(a){return a({directiveName:"editableBstime",inputTpl:"",render:function(){this.parent.render.call(this);var a=angular.element('
    ');a.attr("ng-model",this.inputEl.attr("ng-model")),this.inputEl.removeAttr("ng-model"),this.attrs.eNgChange&&(a.attr("ng-change",this.inputEl.attr("ng-change")),this.inputEl.removeAttr("ng-change")),this.inputEl.wrap(a)}})}]),angular.module("xeditable").directive("editableCheckbox",["editableDirectiveFactory",function(a){return a({directiveName:"editableCheckbox",inputTpl:'',render:function(){this.parent.render.call(this),this.attrs.eTitle&&(this.inputEl.wrap(""),this.inputEl.parent().append(this.attrs.eTitle))},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableChecklist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableChecklist",inputTpl:"",useCopy:!0,render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)}})}]),angular.module("xeditable").directive("editableCombodate",["editableDirectiveFactory","editableCombodate",function(a,b){return a({directiveName:"editableCombodate",inputTpl:'',render:function(){this.parent.render.call(this);var a={value:new Date(this.scope.$data)},c=this;angular.forEach(["format","template","minYear","maxYear","yearDescending","minuteStep","secondStep","firstItem","errorClass","customClass","roundTime","smartDays"],function(b){var d="e"+b.charAt(0).toUpperCase()+b.slice(1);d in c.attrs&&(a[b]=c.attrs[d])});var d=b.getInstance(this.inputEl,a);d.$widget.find("select").bind("change",function(a){c.scope.$data=new Date(d.getValue()).toISOString()})}})}]),function(){var a="text|password|email|tel|number|url|search|color|date|datetime|time|month|week|file".split("|");angular.forEach(a,function(a){var b="editable"+a.charAt(0).toUpperCase()+a.slice(1);angular.module("xeditable").directive(b,["editableDirectiveFactory",function(c){return c({directiveName:b,inputTpl:''})}])}),angular.module("xeditable").directive("editableRange",["editableDirectiveFactory",function(a){return a({directiveName:"editableRange",inputTpl:'',render:function(){this.parent.render.call(this),this.inputEl.after("{{$data}}")}})}])}(),angular.module("xeditable").directive("editableRadiolist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableRadiolist",inputTpl:"",render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableSelect",["editableDirectiveFactory",function(a){return a({directiveName:"editableSelect",inputTpl:"",autosubmit:function(){var a=this;a.inputEl.bind("change",function(){a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").directive("editableTextarea",["editableDirectiveFactory",function(a){return a({directiveName:"editableTextarea",inputTpl:"",addListeners:function(){var a=this;a.parent.addListeners.call(a),a.single&&"no"!==a.buttons&&a.autosubmit()},autosubmit:function(){var a=this;a.inputEl.bind("keydown",function(b){(b.ctrlKey||b.metaKey)&&13===b.keyCode&&a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").directive("editableUiSelect",["editableDirectiveFactory",function(a){var b=function(a,b){var c=angular.element("<"+a+"/>");c.html(b.html());for(var d=b[0].attributes,e=0;e",render:function(){this.parent.render.call(this),this.inputEl.append(b("ui-select-match",c)),this.inputEl.append(b("ui-select-choices",d)),this.inputEl.removeAttr("ng-model"),this.inputEl.attr("ng-model","$parent.$data")}}),f=e.link;return e.link=function(a,b,e,g){var h=b.find("editable-ui-select-match"),i=b.find("editable-ui-select-choices");return c=h.clone(),d=i.clone(),h.remove(),i.remove(),f(a,b,e,g)},e}]),angular.module("xeditable").factory("editableController",["$q","editableUtils",function(a,b){function c(a,c,d,e,f,g,h,i,j,k){var l,m,n=this;n.scope=a,n.elem=d,n.attrs=c,n.inputEl=null,n.editorEl=null,n.single=!0,n.error="",n.theme=f[h.theme]||f["default"],n.parent={},n.icon_set="default"===h.icon_set?g["default"][h.theme]:g.external[h.icon_set],n.inputTpl="",n.directiveName="",n.useCopy=!1,n.single=null,n.buttons="right",n.init=function(b){if(n.single=b,n.name=c.eName||c[n.directiveName],!c[n.directiveName])throw"You should provide value for `"+n.directiveName+"` in editable element!";l=e(c[n.directiveName]),n.single?n.buttons=n.attrs.buttons||h.buttons:n.buttons="no",c.eName&&n.scope.$watch("$data",function(a){n.scope.$form.$data[c.eName]=a}),c.onshow&&(n.onshow=function(){return n.catchError(e(c.onshow)(a))}),c.onhide&&(n.onhide=function(){return e(c.onhide)(a)}),c.oncancel&&(n.oncancel=function(){return e(c.oncancel)(a)}),c.onbeforesave&&(n.onbeforesave=function(){return n.catchError(e(c.onbeforesave)(a))}),c.onaftersave&&(n.onaftersave=function(){return n.catchError(e(c.onaftersave)(a))}),a.$parent.$watch(c[n.directiveName],function(a,b){n.setLocalValue(),n.handleEmpty()})},n.render=function(){var a=n.theme;n.inputEl=angular.element(n.inputTpl),n.controlsEl=angular.element(a.controlsTpl),n.controlsEl.append(n.inputEl),"no"!==n.buttons&&(n.buttonsEl=angular.element(a.buttonsTpl),n.submitEl=angular.element(a.submitTpl),n.cancelEl=angular.element(a.cancelTpl),n.icon_set&&(n.submitEl.find("span").addClass(n.icon_set.ok),n.cancelEl.find("span").addClass(n.icon_set.cancel)),n.buttonsEl.append(n.submitEl).append(n.cancelEl),n.controlsEl.append(n.buttonsEl),n.inputEl.addClass("editable-has-buttons")),n.errorEl=angular.element(a.errorTpl),n.controlsEl.append(n.errorEl),n.editorEl=angular.element(n.single?a.formTpl:a.noformTpl),n.editorEl.append(n.controlsEl);for(var d in c.$attr)if(!(d.length<=1)){var e=!1,f=d.substring(1,2);if("e"===d.substring(0,1)&&f===f.toUpperCase()&&(e=d.substring(1),"Form"!==e&&"NgSubmit"!==e)){e=e.substring(0,1).toLowerCase()+b.camelToDash(e.substring(1));var g="value"!==e&&""===c[d]?e:c[d];n.inputEl.attr(e,g)}}n.inputEl.addClass("editable-input"),n.inputEl.attr("ng-model","$data"),n.editorEl.addClass(b.camelToDash(n.directiveName)),n.single&&(n.editorEl.attr("editable-form","$form"),n.editorEl.attr("blur",n.attrs.blur||("no"===n.buttons?"cancel":h.blurElem))),angular.isFunction(a.postrender)&&a.postrender.call(n)},n.setLocalValue=function(){n.scope.$data=n.useCopy?angular.copy(l(a.$parent)):l(a.$parent)},n.show=function(){return n.setLocalValue(),n.render(),d.after(n.editorEl),j(n.editorEl)(a),n.addListeners(),d.addClass("editable-hide"),n.onshow()},n.hide=function(){return n.editorEl.remove(),d.removeClass("editable-hide"),n.onhide()},n.cancel=function(){n.oncancel()},n.addListeners=function(){n.inputEl.bind("keyup",function(a){if(n.single)switch(a.keyCode){case 27:n.scope.$apply(function(){n.scope.$form.$cancel()})}}),n.single&&"no"===n.buttons&&n.autosubmit(),n.editorEl.bind("click",function(a){a.which&&1!==a.which||n.scope.$form.$visible&&(n.scope.$form._clicked=!0)})},n.setWaiting=function(a){a?(m=!n.inputEl.attr("disabled")&&!n.inputEl.attr("ng-disabled")&&!n.inputEl.attr("ng-enabled"),m&&(n.inputEl.attr("disabled","disabled"),n.buttonsEl&&n.buttonsEl.find("button").attr("disabled","disabled"))):m&&(n.inputEl.removeAttr("disabled"),n.buttonsEl&&n.buttonsEl.find("button").removeAttr("disabled"))},n.activate=function(a,b){setTimeout(function(){var c=n.inputEl[0];"focus"===h.activate&&c.focus&&(a&&(b=b||a,c.onfocus=function(){var c=this;setTimeout(function(){c.setSelectionRange(a,b)})}),c.focus()),"select"===h.activate&&c.select&&c.select()},0)},n.setError=function(b){angular.isObject(b)||(a.$error=b,n.error=b)},n.catchError=function(a,b){return angular.isObject(a)&&b!==!0?k.when(a).then(angular.bind(this,function(a){this.catchError(a,!0)}),angular.bind(this,function(a){this.catchError(a,!0)})):b&&angular.isObject(a)&&a.status&&200!==a.status&&a.data&&angular.isString(a.data)?(this.setError(a.data),a=a.data):angular.isString(a)&&this.setError(a),a},n.save=function(){l.assign(a.$parent,n.useCopy?angular.copy(n.scope.$data):n.scope.$data)},n.handleEmpty=function(){var b=l(a.$parent),c=null===b||void 0===b||""===b||angular.isArray(b)&&0===b.length;d.toggleClass("editable-empty",c)},n.autosubmit=angular.noop,n.onshow=angular.noop,n.onhide=angular.noop,n.oncancel=angular.noop,n.onbeforesave=angular.noop,n.onaftersave=angular.noop}return c.$inject=["$scope","$attrs","$element","$parse","editableThemes","editableIcons","editableOptions","$rootScope","$compile","$q"],c}]),angular.module("xeditable").factory("editableDirectiveFactory",["$parse","$compile","editableThemes","$rootScope","$document","editableController","editableFormController","editableOptions",function(a,b,c,d,e,f,g,h){return function(b){return{restrict:"A",scope:!0,require:[b.directiveName,"?^form"],controller:f,link:function(c,f,i,j){var k,l=j[0],m=!1;if(j[1])k=j[1],m=void 0===i.eSingle;else if(i.eForm){var n=a(i.eForm)(c);if(n)k=n,m=!0;else for(var o=0;o=0&&a.splice(c,1),b},camelToDash:function(a){var b=/[A-Z]/g;return a.replace(b,function(a,b){return(b?"-":"")+a.toLowerCase()})},dashToCamel:function(a){var b=/([\:\-\_]+(.))/g,c=/^moz([A-Z])/;return a.replace(b,function(a,b,c,d){return d?c.toUpperCase():c}).replace(c,"Moz$1")}}}]),angular.module("xeditable").factory("editableNgOptionsParser",[function(){function a(a){var c;if(!(c=a.match(b)))throw"ng-options parse error";var d,e=c[2]||c[1],f=c[4]||c[6],g=c[5],h=(c[3]||"",c[2]?c[1]:f),i=c[7],j=c[8],k=j?c[8]:null;return void 0===g?(d=f+" in "+i,void 0!==j&&(d+=" track by "+k)):d="("+g+", "+f+") in "+i,{ngRepeat:d,locals:{valueName:f,keyName:g,valueFn:h,displayFn:e}}}var b=/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/;return a}]),angular.module("xeditable").factory("editableCombodate",[function(){function a(a,b){if(this.$element=angular.element(a),"INPUT"!=this.$element[0].nodeName)throw"Combodate should be applied to INPUT element";var c=(new Date).getFullYear();this.defaults={format:"YYYY-MM-DD HH:mm",template:"D / MMM / YYYY H : mm",value:null,minYear:1970,maxYear:c,yearDescending:!0,minuteStep:5,secondStep:1,firstItem:"empty",errorClass:null,customClass:"",roundTime:!0,smartDays:!0},this.options=angular.extend({},this.defaults,b),this.init()}return a.prototype={constructor:a,init:function(){if(this.map={day:["D","date"],month:["M","month"],year:["Y","year"],hour:["[Hh]","hours"],minute:["m","minutes"],second:["s","seconds"],ampm:["[Aa]",""]},this.$widget=angular.element('').html(this.getTemplate()),this.initCombos(),this.options.smartDays){var a=this;this.$widget.find("select").bind("change",function(b){(angular.element(b.target).hasClass("month")||angular.element(b.target).hasClass("year"))&&a.fillCombo("day")})}this.$widget.find("select").css("width","auto"),this.$element.css("display","none").after(this.$widget),this.setValue(this.$element.val()||this.options.value)},getTemplate:function(){var a=this.options.template,b=this.options.customClass;return angular.forEach(this.map,function(b,c){b=b[0];var d=new RegExp(b+"+"),e=b.length>1?b.substring(1,2):b;a=a.replace(d,"{"+e+"}")}),a=a.replace(/ /g," "),angular.forEach(this.map,function(c,d){c=c[0];var e=c.length>1?c.substring(1,2):c;a=a.replace("{"+e+"}",'')}),a},initCombos:function(){for(var a in this.map){var b=this.$widget[0].querySelectorAll("."+a);this["$"+a]=b.length?angular.element(b):null,this.fillCombo(a)}},fillCombo:function(a){var b=this["$"+a];if(b){var c="fill"+a.charAt(0).toUpperCase()+a.slice(1),d=this[c](),e=b.val();b.html("");for(var f=0;f'+d[f][1]+"");b.val(e)}},fillCommon:function(a){var b,c=[];if("name"===this.options.firstItem){b=moment.relativeTime||moment.langData()._relativeTime;var d="function"==typeof b[a]?b[a](1,!0,a,!1):b[a];d=d.split(" ").reverse()[0],c.push(["",d])}else"empty"===this.options.firstItem&&c.push(["",""]);return c},fillDay:function(){var a,b,c=this.fillCommon("d"),d=-1!==this.options.template.indexOf("DD"),e=31;if(this.options.smartDays&&this.$month&&this.$year){var f=parseInt(this.$month.val(),10),g=parseInt(this.$year.val(),10);isNaN(f)||isNaN(g)||(e=moment([g,f]).daysInMonth())}for(b=1;e>=b;b++)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillMonth:function(){var a,b,c=this.fillCommon("M"),d=-1!==this.options.template.indexOf("MMMM"),e=-1!==this.options.template.indexOf("MMM"),f=-1!==this.options.template.indexOf("MM");for(b=0;11>=b;b++)a=d?moment().date(1).month(b).format("MMMM"):e?moment().date(1).month(b).format("MMM"):f?this.leadZero(b+1):b+1,c.push([b,a]);return c},fillYear:function(){var a,b,c=[],d=-1!==this.options.template.indexOf("YYYY");for(b=this.options.maxYear;b>=this.options.minYear;b--)a=d?b:(b+"").substring(2),c[this.options.yearDescending?"push":"unshift"]([b,a]);return c=this.fillCommon("y").concat(c)},fillHour:function(){var a,b,c=this.fillCommon("h"),d=-1!==this.options.template.indexOf("h"),e=(-1!==this.options.template.indexOf("H"),-1!==this.options.template.toLowerCase().indexOf("hh")),f=d?1:0,g=d?12:23;for(b=f;g>=b;b++)a=e?this.leadZero(b):b,c.push([b,a]);return c},fillMinute:function(){var a,b,c=this.fillCommon("m"),d=-1!==this.options.template.indexOf("mm");for(b=0;59>=b;b+=this.options.minuteStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillSecond:function(){var a,b,c=this.fillCommon("s"),d=-1!==this.options.template.indexOf("ss");for(b=0;59>=b;b+=this.options.secondStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillAmpm:function(){var a=-1!==this.options.template.indexOf("a"),b=(-1!==this.options.template.indexOf("A"),[["am",a?"am":"AM"],["pm",a?"pm":"PM"]]);return b},getValue:function(a){var b,c={},d=this,e=!1;return angular.forEach(this.map,function(a,b){if("ampm"!==b){var f="day"===b?1:0;return c[b]=d["$"+b]?parseInt(d["$"+b].val(),10):f,isNaN(c[b])?(e=!0,!1):void 0}}),e?"":(this.$ampm&&(12===c.hour?c.hour="am"===this.$ampm.val()?0:12:c.hour="am"===this.$ampm.val()?c.hour:c.hour+12),b=moment([c.year,c.month,c.day,c.hour,c.minute,c.second]),this.highlight(b),a=void 0===a?this.options.format:a,null===a?b.isValid()?b:null:b.isValid()?b.format(a):"")},setValue:function(a){function b(a,b){var c={};return angular.forEach(a.children("option"),function(a,d){var e=angular.element(a).attr("value");if(""!==e){var f=Math.abs(e-b);("undefined"==typeof c.distance||f=12?(e.ampm="pm",e.hour>12&&(e.hour-=12)):(e.ampm="am",0===e.hour&&(e.hour=12))),angular.forEach(e,function(a,c){d["$"+c]&&("minute"===c&&d.options.minuteStep>1&&d.options.roundTime&&(a=b(d["$"+c],a)),"second"===c&&d.options.secondStep>1&&d.options.roundTime&&(a=b(d["$"+c],a)),d["$"+c].val(a))}),this.options.smartDays&&this.fillCombo("day"),this.$element.val(c.format(this.options.format)).triggerHandler("change"))}},highlight:function(a){a.isValid()?this.options.errorClass?this.$widget.removeClass(this.options.errorClass):this.$widget.find("select").css("border-color",this.borderColor):this.options.errorClass?this.$widget.addClass(this.options.errorClass):(this.borderColor||(this.borderColor=this.$widget.find("select").css("border-color")),this.$widget.find("select").css("border-color","red"))},leadZero:function(a){return 9>=a?"0"+a:a},destroy:function(){this.$widget.remove(),this.$element.removeData("combodate").show()}},{getInstance:function(b,c){return new a(b,c)}}}]),angular.module("xeditable").factory("editableIcons",function(){var a={"default":{bs2:{ok:"icon-ok icon-white",cancel:"icon-remove"},bs3:{ok:"glyphicon glyphicon-ok",cancel:"glyphicon glyphicon-remove"}},external:{"font-awesome":{ok:"fa fa-check",cancel:"fa fa-times"}}};return a}),angular.module("xeditable").factory("editableThemes",function(){var a={"default":{formTpl:'',noformTpl:'',controlsTpl:'',inputTpl:"",errorTpl:'
    ',buttonsTpl:'',submitTpl:'',cancelTpl:''},bs2:{formTpl:'
    ',noformTpl:'',controlsTpl:'
    ',inputTpl:"",errorTpl:'
    ',buttonsTpl:'',submitTpl:'',cancelTpl:''},bs3:{formTpl:'
    ',noformTpl:'',controlsTpl:'
    ',inputTpl:"",errorTpl:'
    ',buttonsTpl:'',submitTpl:'',cancelTpl:'',buttonsClass:"",inputClass:"",postrender:function(){switch(this.directiveName){case"editableText":case"editableSelect":case"editableTextarea":case"editableEmail":case"editableTel":case"editableNumber":case"editableUrl":case"editableSearch":case"editableDate":case"editableDatetime":case"editableBsdate":case"editableTime":case"editableMonth":case"editableWeek":case"editablePassword":if(this.inputEl.addClass("form-control"),this.theme.inputClass){if(this.inputEl.attr("multiple")&&("input-sm"===this.theme.inputClass||"input-lg"===this.theme.inputClass))break;this.inputEl.addClass(this.theme.inputClass)}break;case"editableCheckbox":this.editorEl.addClass("checkbox")}this.buttonsEl&&this.theme.buttonsClass&&this.buttonsEl.find("button").addClass(this.theme.buttonsClass)}},semantic:{formTpl:'
    ',noformTpl:'',controlsTpl:'
    ',inputTpl:"",errorTpl:'
    ',buttonsTpl:'',submitTpl:'',cancelTpl:''}};return a}); \ No newline at end of file +angular.module("xeditable",[]).value("editableOptions",{theme:"default",icon_set:"default",buttons:"right",blurElem:"cancel",blurForm:"ignore",activate:"focus",isDisabled:!1,activationEvent:"click"}),angular.module("xeditable").directive("editableBsdate",["editableDirectiveFactory",function(a){return a({directiveName:"editableBsdate",inputTpl:"
    ",render:function(){this.parent.render.call(this);var a=angular.element('');a.attr("uib-datepicker-popup",this.attrs.eDatepickerPopupXEditable||"yyyy/MM/dd"),a.attr("is-open",this.attrs.eIsOpen),a.attr("date-disabled",this.attrs.eDateDisabled),a.attr("uib-datepicker-popup",this.attrs.eDatepickerPopup),a.attr("year-range",this.attrs.eYearRange||20),a.attr("show-button-bar",this.attrs.eShowButtonBar||!0),a.attr("current-text",this.attrs.eCurrentText||"Today"),a.attr("clear-text",this.attrs.eClearText||"Clear"),a.attr("close-text",this.attrs.eCloseText||"Done"),a.attr("close-on-date-selection",this.attrs.eCloseOnDateSelection||!0),a.attr("datepicker-append-to-body",this.attrs.eDatePickerAppendToBody||!1),a.attr("date-disabled",this.attrs.eDateDisabled),a.attr("name",this.attrs.eName),a.attr("on-open-focus",this.attrs.eOnOpenFocus||!0),a.attr("ng-readonly",this.attrs.eReadonly||!1),this.attrs.eNgChange&&(a.attr("ng-change",this.attrs.eNgChange),this.inputEl.removeAttr("ng-change")),this.scope.dateOptions={formatDay:this.attrs.eFormatDay||"dd",formatMonth:this.attrs.eFormatMonth||"MMMM",formatYear:this.attrs.eFormatYear||"yyyy",formatDayHeader:this.attrs.eFormatDayHeader||"EEE",formatDayTitle:this.attrs.eFormatDayTitle||"MMMM yyyy",formatMonthTitle:this.attrs.eFormatMonthTitle||"yyyy",showWeeks:this.attrs.eShowWeeks?"true"===this.attrs.eShowWeeks.toLowerCase():!0,startingDay:this.attrs.eStartingDay||0,minMode:this.attrs.eMinMode||"day",maxMode:this.attrs.eMaxMode||"year",initDate:this.scope.$eval(this.attrs.eInitDate)||new Date,datepickerMode:this.attrs.eDatepickerMode||"day",maxDate:this.scope.$eval(this.attrs.eMaxDate)||null,minDate:this.scope.$eval(this.attrs.eMinDate)||null};var b=angular.isDefined(this.attrs.eShowCalendarButton)?this.attrs.eShowCalendarButton:"true";if("true"===b){var c=angular.element(''),d=angular.element('');c.attr("ng-click",this.attrs.eNgClick),d.append(c),this.inputEl.append(d)}else a.attr("ng-click",this.attrs.eNgClick);a.attr("datepicker-options","dateOptions"),this.inputEl.prepend(a),this.inputEl.removeAttr("class"),this.inputEl.removeAttr("ng-click"),this.inputEl.removeAttr("is-open"),this.inputEl.removeAttr("init-date"),this.inputEl.removeAttr("datepicker-popup"),this.inputEl.removeAttr("required"),this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("date-picker-append-to-body"),this.inputEl.removeAttr("name"),this.inputEl.attr("class","input-group")}})}]),angular.module("xeditable").directive("editableBstime",["editableDirectiveFactory",function(a){return a({directiveName:"editableBstime",inputTpl:"",render:function(){this.parent.render.call(this);var a=angular.element('
    ');a.attr("ng-model",this.inputEl.attr("ng-model")),this.inputEl.removeAttr("ng-model"),this.attrs.eNgChange&&(a.attr("ng-change",this.inputEl.attr("ng-change")),this.inputEl.removeAttr("ng-change")),this.inputEl.wrap(a)}})}]),angular.module("xeditable").directive("editableCheckbox",["editableDirectiveFactory",function(a){return a({directiveName:"editableCheckbox",inputTpl:'',render:function(){this.parent.render.call(this),this.attrs.eTitle&&(this.inputEl.wrap(""),this.inputEl.parent().append(this.attrs.eTitle))},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableChecklist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableChecklist",inputTpl:"",useCopy:!0,render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)}})}]),angular.module("xeditable").directive("editableCombodate",["editableDirectiveFactory","editableCombodate",function(a,b){return a({directiveName:"editableCombodate",inputTpl:'',render:function(){this.parent.render.call(this);var a={value:new Date(this.scope.$data)},c=this;angular.forEach(["format","template","minYear","maxYear","yearDescending","minuteStep","secondStep","firstItem","errorClass","customClass","roundTime","smartDays"],function(b){var d="e"+b.charAt(0).toUpperCase()+b.slice(1);d in c.attrs&&(a[b]=c.attrs[d])});var d=b.getInstance(this.inputEl,a);d.$widget.find("select").bind("change",function(a){c.scope.$data=new Date(d.getValue()).toISOString()})}})}]),function(){var a=function(a){return a.toLowerCase().replace(/-(.)/g,function(a,b){return b.toUpperCase()})},b="text|password|email|tel|number|url|search|color|date|datetime|datetime-local|time|month|week|file".split("|");angular.forEach(b,function(b){var c=a("editable-"+b);angular.module("xeditable").directive(c,["editableDirectiveFactory",function(a){return a({directiveName:c,inputTpl:'',render:function(){if(this.parent.render.call(this),this.attrs.eLabel){var a=angular.element("");this.inputEl.parent().prepend(a)}this.attrs.eFormclass&&this.editorEl.addClass(this.attrs.eFormclass)}})}])}),angular.module("xeditable").directive("editableRange",["editableDirectiveFactory",function(a){return a({directiveName:"editableRange",inputTpl:'',render:function(){this.parent.render.call(this),this.inputEl.after("{{$data}}")}})}])}(),angular.module("xeditable").directive("editableRadiolist",["editableDirectiveFactory","editableNgOptionsParser",function(a,b){return a({directiveName:"editableRadiolist",inputTpl:"",render:function(){this.parent.render.call(this);var a=b(this.attrs.eNgOptions),c='';this.inputEl.removeAttr("ng-model"),this.inputEl.removeAttr("ng-options"),this.inputEl.html(c)},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){setTimeout(function(){a.scope.$apply(function(){a.scope.$form.$submit()})},500)})}})}]),angular.module("xeditable").directive("editableSelect",["editableDirectiveFactory",function(a){return a({directiveName:"editableSelect",inputTpl:"",render:function(){if(this.parent.render.call(this),this.attrs.ePlaceholder){var a=angular.element('");this.inputEl.append(a)}},autosubmit:function(){var a=this;a.inputEl.bind("change",function(){a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").directive("editableTextarea",["editableDirectiveFactory",function(a){return a({directiveName:"editableTextarea",inputTpl:"",addListeners:function(){var a=this;a.parent.addListeners.call(a),a.single&&"no"!==a.buttons&&a.autosubmit()},autosubmit:function(){var a=this;a.inputEl.bind("keydown",function(b){(b.ctrlKey||b.metaKey)&&13===b.keyCode&&a.scope.$apply(function(){a.scope.$form.$submit()})})}})}]),angular.module("xeditable").directive("editableUiSelect",["editableDirectiveFactory",function(a){var b=function(a,b){var c=angular.element("<"+a+"/>");c.html(b.html());for(var d=b[0].attributes,e=0;eb;b++)if(d[b].name===a)return b},d=[],e=[],f=a({directiveName:"editableUiSelect",inputTpl:"",render:function(){var a=c(this.name);this.parent.render.call(this),this.inputEl.append(b("ui-select-match",d[a].element)),this.inputEl.append(b("ui-select-choices",e[a].element)),this.inputEl.removeAttr("ng-model"),this.inputEl.attr("ng-model","$parent.$parent.$data")}}),g=f.link;return f.link=function(a,b,c,f){var h=b.find("editable-ui-select-match"),i=b.find("editable-ui-select-choices");return d.push({name:c.name||c.editableUiSelect,element:h.clone()}),e.push({name:c.name||c.editableUiSelect,element:i.clone()}),h.remove(),i.remove(),g(a,b,c,f)},f}]),angular.module("xeditable").factory("editableController",["$q","editableUtils",function(a,b){function c(a,c,d,e,f,g,h,i,j,k){var l,m,n=this;n.scope=a,n.elem=d,n.attrs=c,n.inputEl=null,n.editorEl=null,n.single=!0,n.error="",n.theme=f[h.theme]||f["default"],n.parent={},n.icon_set="default"===h.icon_set?g["default"][h.theme]:g.external[h.icon_set],n.inputTpl="",n.directiveName="",n.useCopy=!1,n.single=null,n.buttons="right",n.init=function(b){if(n.single=b,n.name=c.eName||c[n.directiveName],!c[n.directiveName])throw"You should provide value for `"+n.directiveName+"` in editable element!";l=e(c[n.directiveName]),n.single?n.buttons=n.attrs.buttons||h.buttons:n.buttons="no",c.eName&&n.scope.$watch("$data",function(a){n.scope.$form.$data[c.eName]=a}),c.onshow&&(n.onshow=function(){return n.catchError(e(c.onshow)(a))}),c.onhide&&(n.onhide=function(){return e(c.onhide)(a)}),c.oncancel&&(n.oncancel=function(){return e(c.oncancel)(a)}),c.onbeforesave&&(n.onbeforesave=function(){return n.catchError(e(c.onbeforesave)(a))}),c.onaftersave&&(n.onaftersave=function(){return n.catchError(e(c.onaftersave)(a))}),a.$parent.$watch(c[n.directiveName],function(a,b){n.setLocalValue(),n.handleEmpty()})},n.render=function(){var a=n.theme;n.inputEl=angular.element(n.inputTpl),n.controlsEl=angular.element(a.controlsTpl),n.controlsEl.append(n.inputEl),"no"!==n.buttons&&(n.buttonsEl=angular.element(a.buttonsTpl),n.submitEl=angular.element(a.submitTpl),n.cancelEl=angular.element(a.cancelTpl),n.icon_set&&(n.submitEl.find("span").addClass(n.icon_set.ok),n.cancelEl.find("span").addClass(n.icon_set.cancel)),n.buttonsEl.append(n.submitEl).append(n.cancelEl),n.controlsEl.append(n.buttonsEl),n.inputEl.addClass("editable-has-buttons")),n.errorEl=angular.element(a.errorTpl),n.controlsEl.append(n.errorEl),n.editorEl=angular.element(n.single?a.formTpl:a.noformTpl),n.editorEl.append(n.controlsEl);for(var d in c.$attr)if(!(d.length<=1)){var e=!1,f=d.substring(1,2);if("e"===d.substring(0,1)&&f===f.toUpperCase()&&(e=d.substring(1),"Form"!==e&&"NgSubmit"!==e)){e=e.substring(0,1).toLowerCase()+b.camelToDash(e.substring(1));var g="value"!==e&&""===c[d]?e:c[d];n.inputEl.attr(e,g)}}n.inputEl.addClass("editable-input"),n.inputEl.attr("ng-model","$parent.$data"),n.editorEl.addClass(b.camelToDash(n.directiveName)),n.single&&(n.editorEl.attr("editable-form","$form"),n.editorEl.attr("blur",n.attrs.blur||("no"===n.buttons?"cancel":h.blurElem))),angular.isFunction(a.postrender)&&a.postrender.call(n)},n.setLocalValue=function(){n.scope.$data=n.useCopy?angular.copy(l(a.$parent)):l(a.$parent)};var o=null;n.show=function(){return n.setLocalValue(),n.render(),d.after(n.editorEl),o=a.$new(),j(n.editorEl)(o),n.addListeners(),d.addClass("editable-hide"),n.onshow()},n.hide=function(){o.$destroy(),n.controlsEl.remove(),n.editorEl.remove(),d.removeClass("editable-hide");for(var b=0,c=a.$$watchers.length;c>b;b++)if(void 0!==a.$$watchers[b]&&a.$$watchers[b].last&&void 0!==a.$$watchers[b].last&&"object"==typeof a.$$watchers[b].last&&"has-error"in a.$$watchers[b].last){a.$$watchers.splice(b,1);break}return n.onhide()},n.cancel=function(){n.oncancel()},n.addListeners=function(){n.inputEl.bind("keyup",function(a){if(n.single)switch(a.keyCode){case 27:n.scope.$apply(function(){n.scope.$form.$cancel()})}}),n.single&&"no"===n.buttons&&n.autosubmit(),n.editorEl.bind("click",function(a){a.which&&1!==a.which||n.scope.$form.$visible&&(n.scope.$form._clicked=!0)})},n.setWaiting=function(a){a?(m=!n.inputEl.attr("disabled")&&!n.inputEl.attr("ng-disabled")&&!n.inputEl.attr("ng-enabled"),m&&(n.inputEl.attr("disabled","disabled"),n.buttonsEl&&n.buttonsEl.find("button").attr("disabled","disabled"))):m&&(n.inputEl.removeAttr("disabled"),n.buttonsEl&&n.buttonsEl.find("button").removeAttr("disabled"))},n.activate=function(a,b){setTimeout(function(){var c=n.inputEl[0];"focus"===h.activate&&c.focus&&(a&&(b=b||a,c.onfocus=function(){var c=this;setTimeout(function(){c.setSelectionRange(a,b)})}),c.focus()),"select"===h.activate&&c.select&&c.select()},0)},n.setError=function(b){angular.isObject(b)||(a.$error=b,n.error=b)},n.catchError=function(a,b){return angular.isObject(a)&&b!==!0?k.when(a).then(angular.bind(this,function(a){this.catchError(a,!0)}),angular.bind(this,function(a){this.catchError(a,!0)})):b&&angular.isObject(a)&&a.status&&200!==a.status&&a.data&&angular.isString(a.data)?(this.setError(a.data),a=a.data):angular.isString(a)&&this.setError(a),a},n.save=function(){l.assign(a.$parent,n.useCopy?angular.copy(n.scope.$data):n.scope.$data)},n.handleEmpty=function(){var b=l(a.$parent),c=null===b||void 0===b||""===b||angular.isArray(b)&&0===b.length;d.toggleClass("editable-empty",c)},n.autosubmit=angular.noop,n.onshow=angular.noop,n.onhide=angular.noop,n.oncancel=angular.noop,n.onbeforesave=angular.noop,n.onaftersave=angular.noop}return c.$inject=["$scope","$attrs","$element","$parse","editableThemes","editableIcons","editableOptions","$rootScope","$compile","$q"],c}]),angular.module("xeditable").factory("editableDirectiveFactory",["$parse","$compile","editableThemes","$rootScope","$document","editableController","editableFormController","editableOptions",function(a,b,c,d,e,f,g,h){return function(b){return{restrict:"A",scope:!0,require:[b.directiveName,"?^form"],controller:f,link:function(c,f,i,j){var k,l=j[0],m=!1;if(j[1])k=j[1],m=void 0===i.eSingle;else if(i.eForm){var n=a(i.eForm)(c);if(n)k=n,m=!0;else if(f&&"function"==typeof f.parents&&f.parents().last().find("form[name="+i.eForm+"]").length)k=null,m=!0;else for(var o=0;o=0&&a.splice(c,1),b},camelToDash:function(a){var b=/[A-Z]/g;return a.replace(b,function(a,b){return(b?"-":"")+a.toLowerCase()})},dashToCamel:function(a){var b=/([\:\-\_]+(.))/g,c=/^moz([A-Z])/;return a.replace(b,function(a,b,c,d){return d?c.toUpperCase():c}).replace(c,"Moz$1")}}}]),angular.module("xeditable").factory("editableNgOptionsParser",[function(){function a(a){var c;if(!(c=a.match(b)))throw"ng-options parse error";var d,e=c[2]||c[1],f=c[4]||c[6],g=c[5],h=(c[3]||"",c[2]?c[1]:f),i=c[7],j=c[8],k=j?c[8]:null;return void 0===g?(d=f+" in "+i,void 0!==j&&(d+=" track by "+k)):d="("+g+", "+f+") in "+i,{ngRepeat:d,locals:{valueName:f,keyName:g,valueFn:h,displayFn:e}}}var b=/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/;return a}]),angular.module("xeditable").factory("editableCombodate",[function(){function a(a,b){if(this.$element=angular.element(a),"INPUT"!=this.$element[0].nodeName)throw"Combodate should be applied to INPUT element";var c=(new Date).getFullYear();this.defaults={format:"YYYY-MM-DD HH:mm",template:"D / MMM / YYYY H : mm",value:null,minYear:1970,maxYear:c,yearDescending:!0,minuteStep:5,secondStep:1,firstItem:"empty",errorClass:null,customClass:"",roundTime:!0,smartDays:!0},this.options=angular.extend({},this.defaults,b),this.init()}return a.prototype={constructor:a,init:function(){if(this.map={day:["D","date"],month:["M","month"],year:["Y","year"],hour:["[Hh]","hours"],minute:["m","minutes"],second:["s","seconds"],ampm:["[Aa]",""]},this.$widget=angular.element('').html(this.getTemplate()),this.initCombos(),this.options.smartDays){var a=this;this.$widget.find("select").bind("change",function(b){(angular.element(b.target).hasClass("month")||angular.element(b.target).hasClass("year"))&&a.fillCombo("day")})}this.$widget.find("select").css("width","auto"),this.$element.css("display","none").after(this.$widget),this.setValue(this.$element.val()||this.options.value)},getTemplate:function(){var a=this.options.template,b=this.options.customClass;return angular.forEach(this.map,function(b,c){b=b[0];var d=new RegExp(b+"+"),e=b.length>1?b.substring(1,2):b;a=a.replace(d,"{"+e+"}")}),a=a.replace(/ /g," "),angular.forEach(this.map,function(c,d){c=c[0];var e=c.length>1?c.substring(1,2):c;a=a.replace("{"+e+"}",'')}),a},initCombos:function(){for(var a in this.map){var b=this.$widget[0].querySelectorAll("."+a);this["$"+a]=b.length?angular.element(b):null,this.fillCombo(a)}},fillCombo:function(a){var b=this["$"+a];if(b){var c="fill"+a.charAt(0).toUpperCase()+a.slice(1),d=this[c](),e=b.val();b.html("");for(var f=0;f'+d[f][1]+"");b.val(e)}},fillCommon:function(a){var b,c=[];if("name"===this.options.firstItem){b=moment.relativeTime||moment.langData()._relativeTime;var d="function"==typeof b[a]?b[a](1,!0,a,!1):b[a];d=d.split(" ").reverse()[0],c.push(["",d])}else"empty"===this.options.firstItem&&c.push(["",""]);return c},fillDay:function(){var a,b,c=this.fillCommon("d"),d=-1!==this.options.template.indexOf("DD"),e=31;if(this.options.smartDays&&this.$month&&this.$year){var f=parseInt(this.$month.val(),10),g=parseInt(this.$year.val(),10);isNaN(f)||isNaN(g)||(e=moment([g,f]).daysInMonth())}for(b=1;e>=b;b++)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillMonth:function(){var a,b,c=this.fillCommon("M"),d=-1!==this.options.template.indexOf("MMMM"),e=-1!==this.options.template.indexOf("MMM"),f=-1!==this.options.template.indexOf("MM");for(b=0;11>=b;b++)a=d?moment().date(1).month(b).format("MMMM"):e?moment().date(1).month(b).format("MMM"):f?this.leadZero(b+1):b+1,c.push([b,a]);return c},fillYear:function(){var a,b,c=[],d=-1!==this.options.template.indexOf("YYYY");for(b=this.options.maxYear;b>=this.options.minYear;b--)a=d?b:(b+"").substring(2),c[this.options.yearDescending?"push":"unshift"]([b,a]);return c=this.fillCommon("y").concat(c)},fillHour:function(){var a,b,c=this.fillCommon("h"),d=-1!==this.options.template.indexOf("h"),e=(-1!==this.options.template.indexOf("H"),-1!==this.options.template.toLowerCase().indexOf("hh")),f=d?1:0,g=d?12:23;for(b=f;g>=b;b++)a=e?this.leadZero(b):b,c.push([b,a]);return c},fillMinute:function(){var a,b,c=this.fillCommon("m"),d=-1!==this.options.template.indexOf("mm");for(b=0;59>=b;b+=this.options.minuteStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillSecond:function(){var a,b,c=this.fillCommon("s"),d=-1!==this.options.template.indexOf("ss");for(b=0;59>=b;b+=this.options.secondStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillAmpm:function(){var a=-1!==this.options.template.indexOf("a"),b=(-1!==this.options.template.indexOf("A"),[["am",a?"am":"AM"],["pm",a?"pm":"PM"]]);return b},getValue:function(a){var b,c={},d=this,e=!1;return angular.forEach(this.map,function(a,b){if("ampm"!==b){var f="day"===b?1:0;return c[b]=d["$"+b]?parseInt(d["$"+b].val(),10):f,isNaN(c[b])?(e=!0,!1):void 0}}),e?"":(this.$ampm&&(12===c.hour?c.hour="am"===this.$ampm.val()?0:12:c.hour="am"===this.$ampm.val()?c.hour:c.hour+12),b=moment([c.year,c.month,c.day,c.hour,c.minute,c.second]),this.highlight(b),a=void 0===a?this.options.format:a,null===a?b.isValid()?b:null:b.isValid()?b.format(a):"")},setValue:function(a){function b(a,b){var c={};return angular.forEach(a.children("option"),function(a,d){var e=angular.element(a).attr("value");if(""!==e){var f=Math.abs(e-b);("undefined"==typeof c.distance||f=12?(e.ampm="pm",e.hour>12&&(e.hour-=12)):(e.ampm="am",0===e.hour&&(e.hour=12))),angular.forEach(e,function(a,c){d["$"+c]&&("minute"===c&&d.options.minuteStep>1&&d.options.roundTime&&(a=b(d["$"+c],a)),"second"===c&&d.options.secondStep>1&&d.options.roundTime&&(a=b(d["$"+c],a)),d["$"+c].val(a))}),this.options.smartDays&&this.fillCombo("day"),this.$element.val(c.format(this.options.format)).triggerHandler("change"))}},highlight:function(a){a.isValid()?this.options.errorClass?this.$widget.removeClass(this.options.errorClass):this.$widget.find("select").css("border-color",this.borderColor):this.options.errorClass?this.$widget.addClass(this.options.errorClass):(this.borderColor||(this.borderColor=this.$widget.find("select").css("border-color")),this.$widget.find("select").css("border-color","red"))},leadZero:function(a){return 9>=a?"0"+a:a},destroy:function(){this.$widget.remove(),this.$element.removeData("combodate").show()}},{getInstance:function(b,c){return new a(b,c)}}}]),angular.module("xeditable").factory("editableIcons",function(){var a={"default":{bs2:{ok:"icon-ok icon-white",cancel:"icon-remove"},bs3:{ok:"glyphicon glyphicon-ok",cancel:"glyphicon glyphicon-remove"}},external:{"font-awesome":{ok:"fa fa-check",cancel:"fa fa-times"}}};return a}),angular.module("xeditable").factory("editableThemes",function(){var a={"default":{formTpl:'
    ',noformTpl:'',controlsTpl:'',inputTpl:"",errorTpl:'
    ',buttonsTpl:'',submitTpl:'',cancelTpl:''},bs2:{formTpl:'
    ',noformTpl:'',controlsTpl:'
    ',inputTpl:"",errorTpl:'
    ',buttonsTpl:'',submitTpl:'',cancelTpl:''},bs3:{formTpl:'
    ',noformTpl:'',controlsTpl:'
    ',inputTpl:"",errorTpl:'
    ',buttonsTpl:'',submitTpl:'',cancelTpl:'',buttonsClass:"",inputClass:"",postrender:function(){switch(this.directiveName){case"editableText":case"editableSelect":case"editableTextarea":case"editableEmail":case"editableTel":case"editableNumber":case"editableUrl":case"editableSearch":case"editableDate":case"editableDatetime":case"editableBsdate":case"editableTime":case"editableMonth":case"editableWeek":case"editablePassword":case"editableDatetimeLocal":if(this.inputEl.addClass("form-control"),this.theme.inputClass){if(this.inputEl.attr("multiple")&&("input-sm"===this.theme.inputClass||"input-lg"===this.theme.inputClass))break;this.inputEl.addClass(this.theme.inputClass)}break;case"editableCheckbox":this.editorEl.addClass("checkbox")}this.buttonsEl&&this.theme.buttonsClass&&this.buttonsEl.find("button").addClass(this.theme.buttonsClass)}},semantic:{formTpl:'
    ',noformTpl:'',controlsTpl:'
    ',inputTpl:"",errorTpl:'
    ',buttonsTpl:'',submitTpl:'',cancelTpl:''}};return a}); \ No newline at end of file diff --git a/zip/angular-xeditable-0.2.0.zip b/zip/angular-xeditable-0.2.0.zip new file mode 100644 index 00000000..f7e9150d Binary files /dev/null and b/zip/angular-xeditable-0.2.0.zip differ diff --git a/zip/angular-xeditable-starter.zip b/zip/angular-xeditable-starter.zip index 3e943700..1abfcd50 100644 Binary files a/zip/angular-xeditable-starter.zip and b/zip/angular-xeditable-starter.zip differ