bootstrap-editable-rails 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
- /*! X-editable - v1.1.1
1
+ /*! X-editable - v1.3.0
2
2
  * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3
3
  * http://github.com/vitalets/x-editable
4
4
  * Copyright (c) 2012 Vitaliy Potapov; Licensed MIT */
5
- (function(e){var t=function(t,n){this.options=e.extend({},e.fn.editableform.defaults,n),this.$element=e(t),this.initInput()};t.prototype={constructor:t,initInput:function(){var t,n;if(typeof e.fn.editableform.types[this.options.type]!="function"){e.error("Unknown type: "+this.options.type);return}t=e.fn.editableform.types[this.options.type],n=e.fn.editableform.utils.sliceObj(this.options,e.fn.editableform.utils.objectKeys(t.defaults)),this.input=new t(n),this.value=this.input.str2value(this.options.value)},initTemplate:function(){this.$form=e(e.fn.editableform.template)},initButtons:function(){this.$form.find(".editable-buttons").append(e.fn.editableform.buttons)},render:function(){this.$loading=e(e.fn.editableform.loading),this.$element.empty().append(this.$loading),this.showLoading(),this.initTemplate(),this.options.showbuttons?this.initButtons():this.$form.find(".editable-buttons").remove(),this.$element.triggerHandler("rendering"),e.when(this.input.render()).then(e.proxy(function(){this.$form.find("div.editable-input").append(this.input.$input),this.options.showbuttons||this.input.autosubmit(),this.input.$clear&&this.$form.find("div.editable-input").append(e('<div class="editable-clear">').append(this.input.$clear)),this.$element.append(this.$form),this.$form.find(".editable-cancel").click(e.proxy(this.cancel,this)),this.input.error?(this.error(this.input.error),this.$form.find(".editable-submit").attr("disabled",!0),this.input.$input.attr("disabled",!0)):(this.error(!1),this.input.$input.removeAttr("disabled"),this.$form.find(".editable-submit").removeAttr("disabled"),this.input.value2input(this.value),this.$form.submit(e.proxy(this.submit,this))),this.$element.triggerHandler("rendered"),this.showForm()},this))},cancel:function(){this.$element.triggerHandler("cancel")},showLoading:function(){var e;this.$form?(this.$loading.width(this.$form.outerWidth()),this.$loading.height(this.$form.outerHeight()),this.$form.hide()):(e=this.$loading.parent().width(),e&&this.$loading.width(e)),this.$loading.show()},showForm:function(){this.$loading.hide(),this.$form.show(),this.input.activate(),this.$element.triggerHandler("show")},error:function(t){var n=this.$form.find(".control-group"),r=this.$form.find(".editable-error-block");t===!1?(n.removeClass(e.fn.editableform.errorGroupClass),r.removeClass(e.fn.editableform.errorBlockClass).empty().hide()):(n.addClass(e.fn.editableform.errorGroupClass),r.addClass(e.fn.editableform.errorBlockClass).text(t).show())},submit:function(t){t.stopPropagation(),t.preventDefault();var n,r=this.input.input2value(),i;if(n=this.validate(r)){this.error(n),this.showForm();return}i=this.input.value2str(r);if(i==this.input.value2str(this.value)){this.cancel();return}e.when(this.save(i)).done(e.proxy(function(e){var t=typeof this.options.success=="function"?this.options.success.call(this,e,r):null;if(t&&typeof t=="string"){this.error(t),this.showForm();return}t&&typeof t=="object"&&t.hasOwnProperty("newValue")&&(r=t.newValue),this.error(!1),this.value=r,this.$element.triggerHandler("save",{newValue:r,response:e})},this)).fail(e.proxy(function(e){this.error(typeof e=="string"?e:e.responseText||e.statusText||"Unknown error!"),this.showForm()},this))},save:function(t){var n=typeof this.options.pk=="function"?this.options.pk.call(this):this.options.pk,r=!!(typeof this.options.url=="function"||this.options.url&&(this.options.send==="always"||this.options.send==="auto"&&n)),i,s;if(r)return this.showLoading(),i={name:this.options.name||"",value:t,pk:n},typeof this.options.params=="function"?e.extend(i,this.options.params.call(this,i)):(this.options.params=e.fn.editableform.utils.tryParseJson(this.options.params,!0),e.extend(i,this.options.params)),typeof this.options.url=="function"?this.options.url.call(this,i):(s=e.extend({url:this.options.url,data:i,type:"post",dataType:"json"},this.options.ajaxOptions),e.ajax(s))},validate:function(e){e===undefined&&(e=this.value);if(typeof this.options.validate=="function")return this.options.validate.call(this,e)},option:function(e,t){this.options[e]=t,e==="value"&&this.setValue(t)},setValue:function(e,t){t?this.value=this.input.str2value(e):this.value=e}},e.fn.editableform=function(n){var r=arguments;return this.each(function(){var i=e(this),s=i.data("editableform"),o=typeof n=="object"&&n;s||i.data("editableform",s=new t(this,o)),typeof n=="string"&&s[n].apply(s,Array.prototype.slice.call(r,1))})},e.fn.editableform.Constructor=t,e.fn.editableform.defaults={type:"text",url:null,params:null,name:null,pk:null,value:null,send:"auto",validate:null,success:function(e,t){},ajaxOptions:null,showbuttons:!0},e.fn.editableform.template='<form class="form-inline editableform"><div class="control-group"><div><div class="editable-input"></div><div class="editable-buttons"></div></div><div class="editable-error-block"></div></div></form>',e.fn.editableform.loading='<div class="editableform-loading"></div>',e.fn.editableform.buttons='<button type="submit" class="editable-submit">ok</button><button type="button" class="editable-cancel">cancel</button>',e.fn.editableform.errorGroupClass=null,e.fn.editableform.errorBlockClass="editable-error",e.fn.editableform.types={},e.fn.editableform.utils={}})(window.jQuery),function(e){e.fn.editableform.utils={inherit:function(e,t){var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e,e.superclass=t.prototype},setCursorPosition:function(e,t){if(e.setSelectionRange)e.setSelectionRange(t,t);else if(e.createTextRange){var n=e.createTextRange();n.collapse(!0),n.moveEnd("character",t),n.moveStart("character",t),n.select()}},tryParseJson:function(e,t){if(typeof e=="string"&&e.length&&e.match(/^[\{\[].*[\}\]]$/))if(t)try{e=(new Function("return "+e))()}catch(n){}finally{return e}else e=(new Function("return "+e))();return e},sliceObj:function(t,n,r){var i,s,o={};if(!e.isArray(n)||!n.length)return o;for(var u=0;u<n.length;u++){i=n[u],t.hasOwnProperty(i)&&(o[i]=t[i]);if(r===!0)continue;s=i.toLowerCase(),t.hasOwnProperty(s)&&(o[i]=t[s])}return o},getConfigData:function(t){var n={};return e.each(t.data(),function(e,t){if(typeof t!="object"||t&&typeof t=="object"&&t.constructor===Object)n[e]=t}),n},objectKeys:function(e){if(Object.keys)return Object.keys(e);if(e!==Object(e))throw new TypeError("Object.keys called on a non-object");var t=[],n;for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.push(n);return t}}}(window.jQuery),function(e){var t=function(e,t){this.init(e,t)};t.prototype={containerName:null,innerCss:null,init:function(n,r){this.$element=e(n),this.options=e.extend({},e.fn.editableContainer.defaults,e.fn.editableform.utils.getConfigData(this.$element),r),this.splitOptions(),this.initContainer(),this.$element.on("destroyed",e.proxy(function(){this.destroy()},this)),e(document).data("editable-handlers-attached")||(e(document).on("keyup.editable",function(t){t.which===27&&e(".editable-open").editableContainer("hide")}),e(document).on("click.editable",function(n){var r=e(n.target);if(r.is(".editable-container")||r.parents(".editable-container").length||r.parents(".ui-datepicker-header").length)return;t.prototype.closeOthers(n.target)}),e(document).data("editable-handlers-attached",!0))},splitOptions:function(){this.containerOptions={},this.formOptions={};var t=e.fn[this.containerName].defaults;for(var n in this.options)n in t?this.containerOptions[n]=this.options[n]:this.formOptions[n]=this.options[n]},initContainer:function(){this.call(this.containerOptions)},initForm:function(){return this.$form=e("<div>").editableform(this.formOptions).on({save:e.proxy(this.save,this),cancel:e.proxy(this.cancel,this),show:e.proxy(this.setPosition,this),rendering:e.proxy(this.setPosition,this),rendered:e.proxy(function(){this.$element.triggerHandler("shown")},this)}),this.$form},tip:function(){return this.container().$tip},container:function(){return this.$element.data(this.containerName)},call:function(){this.$element[this.containerName].apply(this.$element,arguments)},show:function(e){this.$element.addClass("editable-open"),e!==!1&&this.closeOthers(this.$element[0]),this.innerShow()},innerShow:function(){this.call("show"),this.tip().addClass("editable-container"),this.initForm(),this.tip().find(this.innerCss).empty().append(this.$form),this.$form.editableform("render")},hide:function(){if(!this.tip()||!this.tip().is(":visible")||!this.$element.hasClass("editable-open"))return;this.$element.removeClass("editable-open"),this.innerHide(),this.$element.triggerHandler("hidden")},innerHide:function(){this.call("hide")},toggle:function(e){this.tip&&this.tip().is(":visible")?this.hide():this.show(e)},setPosition:function(){},cancel:function(){this.options.autohide&&this.hide(),this.$element.triggerHandler("cancel")},save:function(e,t){this.options.autohide&&this.hide(),this.$element.triggerHandler("save",t)},option:function(e,t){this.options[e]=t,e in this.containerOptions?(this.containerOptions[e]=t,this.setContainerOption(e,t)):(this.formOptions[e]=t,this.$form&&this.$form.editableform("option",e,t))},setContainerOption:function(e,t){this.call("option",e,t)},destroy:function(){this.call("destroy")},closeOthers:function(t){e(".editable-open").each(function(n,r){if(r===t)return;var i=e(r),s=i.data("editableContainer");if(!s)return;s.options.onblur==="cancel"?i.data("editableContainer").hide():s.options.onblur==="submit"&&i.data("editableContainer").tip().find("form").submit()})},activate:function(){this.tip&&this.tip().is(":visible")&&this.$form&&this.$form.data("editableform").input.activate()}},e.fn.editableContainer=function(n){var r=arguments;return this.each(function(){var i=e(this),s="editableContainer",o=i.data(s),u=typeof n=="object"&&n;o||i.data(s,o=new t(this,u)),typeof n=="string"&&o[n].apply(o,Array.prototype.slice.call(r,1))})},e.fn.editableContainer.Constructor=t,e.fn.editableContainer.defaults={value:null,placement:"top",autohide:!0,onblur:"cancel"},jQuery.event.special.destroyed={remove:function(e){e.handler&&e.handler()}}}(window.jQuery),function(e){var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.editable.defaults,e.fn.editableform.utils.getConfigData(this.$element),n),this.init()};t.prototype={constructor:t,init:function(){var t,n=!1,r,i;this.isInit=!0;if(!e.fn.editableContainer){e.error("You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)");return}this.options.name=this.options.name||this.$element.attr("id");if(typeof e.fn.editableform.types[this.options.type]!="function"){e.error("Unknown type: "+this.options.type);return}t=e.fn.editableform.types[this.options.type],this.typeOptions=e.fn.editableform.utils.sliceObj(this.options,e.fn.editableform.utils.objectKeys(t.defaults)),this.input=new t(this.typeOptions),this.options.value===undefined||this.options.value===null?(this.value=this.input.html2value(e.trim(this.$element.html())),n=!0):(typeof this.options.value=="string"&&(this.options.value=e.trim(this.options.value)),this.value=this.input.str2value(this.options.value)),this.$element.addClass("editable"),this.options.toggle!=="manual"?(this.$element.addClass("editable-click"),this.$element.on(this.options.toggle+".editable",e.proxy(function(e){e.preventDefault();if(this.options.toggle==="mouseenter")this.show();else{var t=this.options.toggle!=="click";this.toggle(t)}},this))):this.$element.attr("tabindex",-1),r=!n&&this.value!==null&&this.value!==undefined,r&=this.options.autotext==="always"||this.options.autotext==="auto"&&!this.$element.text().length,e.when(r?this.input.value2html(this.value,this.$element):!0).then(e.proxy(function(){this.options.disabled?this.disable():this.enable(),this.$element.triggerHandler("render",this),this.isInit=!1},this))},enable:function(){this.options.disabled=!1,this.$element.removeClass("editable-disabled"),this.handleEmpty(),this.options.toggle!=="manual"&&this.$element.attr("tabindex")==="-1"&&this.$element.removeAttr("tabindex")},disable:function(){this.options.disabled=!0,this.hide(),this.$element.addClass("editable-disabled"),this.handleEmpty(),this.$element.attr("tabindex",-1)},toggleDisabled:function(){this.options.disabled?this.enable():this.disable()},option:function(t,n){if(t&&typeof t=="object"){e.each(t,e.proxy(function(t,n){this.option(e.trim(t),n)},this));return}this.options[t]=n;if(t==="disabled"){n?this.disable():this.enable();return}t==="value"&&this.setValue(n),this.container&&this.container.option(t,n)},handleEmpty:function(){var t="editable-empty";this.options.disabled?this.$element.hasClass(t)&&(this.$element.empty(),this.$element.removeClass(t)):e.trim(this.$element.text())===""?this.$element.addClass(t).text(this.options.emptytext):this.$element.removeClass(t)},show:function(t){if(this.options.disabled)return;if(!this.container){var n=e.extend({},this.options,{value:this.value,autohide:!1});this.$element.editableContainer(n),this.$element.on({save:e.proxy(this.save,this),cancel:e.proxy(this.hide,this)}),this.container=this.$element.data("editableContainer")}else if(this.container.tip().is(":visible"))return;this.container.show(t)},hide:function(){this.container&&this.container.hide(),this.options.enablefocus&&this.options.toggle==="click"&&this.$element.focus()},toggle:function(e){this.container&&this.container.tip().is(":visible")?this.hide():this.show(e)},save:function(e,t){typeof this.options.url!="function"&&t.response===undefined&&this.input.value2str(this.value)!==this.input.value2str(t.newValue)?this.$element.addClass("editable-unsaved"):this.$element.removeClass("editable-unsaved"),this.hide(),this.setValue(t.newValue)},validate:function(){if(typeof this.options.validate=="function")return this.options.validate.call(this,this.value)},setValue:function(t,n){n?this.value=this.input.str2value(t):this.value=t,this.container&&this.container.option("value",this.value),e.when(this.input.value2html(this.value,this.$element)).then(e.proxy(function(){this.handleEmpty(),this.$element.triggerHandler("render",this)},this))},activate:function(){this.container&&this.container.activate()}},e.fn.editable=function(n){var r={},i=arguments,s="editable";switch(n){case"validate":return this.each(function(){var t=e(this),n=t.data(s),i;n&&(i=n.validate())&&(r[n.options.name]=i)}),r;case"getValue":return this.each(function(){var t=e(this),n=t.data(s);n&&n.value!==undefined&&n.value!==null&&(r[n.options.name]=n.input.value2str(n.value))}),r;case"submit":var o=arguments[1]||{},u=this,a=this.editable("validate"),f;return typeof o.error!="function"&&(o.error=function(){}),e.isEmptyObject(a)?(f=this.editable("getValue"),o.data&&e.extend(f,o.data),e.ajax({type:"POST",url:o.url,data:f,dataType:"json"}).success(function(e){typeof e=="object"&&e.id?(u.editable("option","pk",e.id),u.removeClass("editable-unsaved"),typeof o.success=="function"&&o.success.apply(u,arguments)):o.error.apply(u,arguments)}).error(function(){o.error.apply(u,arguments)})):o.error.call(u,{errors:a}),this}return this.each(function(){var r=e(this),o=r.data(s),u=typeof n=="object"&&n;o||r.data(s,o=new t(this,u)),typeof n=="string"&&o[n].apply(o,Array.prototype.slice.call(i,1))})},e.fn.editable.defaults={type:"text",disabled:!1,toggle:"click",emptytext:"Empty",autotext:"auto",enablefocus:!1,value:null}}(window.jQuery),function(e){var t=function(){};t.prototype={init:function(t,n,r){this.type=t,this.options=e.extend({},r,n),this.$input=null,this.$clear=null,this.error=null},render:function(){this.$input=e(this.options.tpl),this.options.inputclass&&this.$input.addClass(this.options.inputclass),this.options.placeholder&&this.$input.attr("placeholder",this.options.placeholder)},value2html:function(t,n){var r=this.escape(t);e(n).html(r)},html2value:function(t){return e("<div>").html(t).text()},value2str:function(e){return e},str2value:function(e){return e},value2input:function(e){this.$input.val(e)},input2value:function(){return this.$input.val()},activate:function(){this.$input.is(":visible")&&this.$input.focus()},clear:function(){this.$input.val(null)},escape:function(t){return e("<div>").text(t).html()},autosubmit:function(){}},t.defaults={tpl:"",inputclass:"span2",name:null},e.extend(e.fn.editableform.types,{"abstract":t})}(window.jQuery),function(e){var t=function(e){};e.fn.editableform.utils.inherit(t,e.fn.editableform.types.abstract),e.extend(t.prototype,{render:function(){t.superclass.render.call(this);var n=e.Deferred();return this.error=null,this.sourceData=null,this.prependData=null,this.onSourceReady(function(){this.renderList(),n.resolve()},function(){this.error=this.options.sourceError,n.resolve()}),n.promise()},html2value:function(e){return null},value2html:function(n,r){var i=e.Deferred();return this.onSourceReady(function(){this.value2htmlFinal(n,r),i.resolve()},function(){t.superclass.value2html(this.options.sourceError,r),i.resolve()}),i.promise()},onSourceReady:function(t,n){if(e.isArray(this.sourceData)){t.call(this);return}try{this.options.source=e.fn.editableform.utils.tryParseJson(this.options.source,!1)}catch(r){n.call(this);return}if(typeof this.options.source=="string"){var i=this.options.source+(this.options.name?"-"+this.options.name:""),s;e(document).data(i)||e(document).data(i,{}),s=e(document).data(i);if(s.loading===!1&&s.sourceData){this.sourceData=s.sourceData,t.call(this);return}if(s.loading===!0){s.callbacks.push(e.proxy(function(){this.sourceData=s.sourceData,t.call(this)},this)),s.err_callbacks.push(e.proxy(n,this));return}s.loading=!0,s.callbacks=[],s.err_callbacks=[],e.ajax({url:this.options.source,type:"get",cache:!1,data:this.options.name?{name:this.options.name}:{},dataType:"json",success:e.proxy(function(r){s.loading=!1,this.sourceData=this.makeArray(r),e.isArray(this.sourceData)?(this.doPrepend(),s.sourceData=this.sourceData,t.call(this),e.each(s.callbacks,function(){this.call()})):(n.call(this),e.each(s.err_callbacks,function(){this.call()}))},this),error:e.proxy(function(){s.loading=!1,n.call(this),e.each(s.err_callbacks,function(){this.call()})},this)})}else this.sourceData=this.makeArray(this.options.source),e.isArray(this.sourceData)?(this.doPrepend(),t.call(this)):n.call(this)},doPrepend:function(){if(this.options.prepend===null||this.options.prepend===undefined)return;e.isArray(this.prependData)||(this.options.prepend=e.fn.editableform.utils.tryParseJson(this.options.prepend,!0),typeof this.options.prepend=="string"&&(this.options.prepend={"":this.options.prepend}),this.prependData=this.makeArray(this.options.prepend)),e.isArray(this.prependData)&&e.isArray(this.sourceData)&&(this.sourceData=this.prependData.concat(this.sourceData))},renderList:function(){},value2htmlFinal:function(e,t){},makeArray:function(t){var n,r,i=[],s;if(!t||typeof t=="string")return null;if(e.isArray(t)){s=function(e,t){r={value:e,text:t};if(n++>=2)return!1};for(var o=0;o<t.length;o++)typeof t[o]=="object"?(n=0,e.each(t[o],s),n===1?i.push(r):n>1&&t[o].hasOwnProperty("value")&&t[o].hasOwnProperty("text")&&i.push(t[o])):i.push({value:t[o],text:t[o]})}else e.each(t,function(e,t){i.push({value:e,text:t})});return i},itemByVal:function(t){if(e.isArray(this.sourceData))for(var n=0;n<this.sourceData.length;n++)if(this.sourceData[n].value==t)return this.sourceData[n]}}),t.defaults=e.extend({},e.fn.editableform.types.abstract.defaults,{source:null,prepend:!1,sourceError:"Error when loading list"}),e.fn.editableform.types.list=t}(window.jQuery),function(e){var t=function(e){this.init("text",e,t.defaults)};e.fn.editableform.utils.inherit(t,e.fn.editableform.types.abstract),e.extend(t.prototype,{activate:function(){this.$input.is(":visible")&&(this.$input.focus(),e.fn.editableform.utils.setCursorPosition(this.$input.get(0),this.$input.val().length))}}),t.defaults=e.extend({},e.fn.editableform.types.abstract.defaults,{tpl:'<input type="text">',placeholder:null}),e.fn.editableform.types.text=t}(window.jQuery),function(e){var t=function(e){this.init("textarea",e,t.defaults)};e.fn.editableform.utils.inherit(t,e.fn.editableform.types.abstract),e.extend(t.prototype,{render:function(){t.superclass.render.call(this),this.$input.keydown(function(t){t.ctrlKey&&t.which===13&&e(this).closest("form").submit()})},value2html:function(t,n){var r="",i;if(t){i=t.split("\n");for(var s=0;s<i.length;s++)i[s]=e("<div>").text(i[s]).html();r=i.join("<br>")}e(n).html(r)},html2value:function(t){if(!t)return"";var n=t.split(/<br\s*\/?>/i);for(var r=0;r<n.length;r++)n[r]=e("<div>").html(n[r]).text();return n.join("\n")},activate:function(){this.$input.is(":visible")&&(e.fn.editableform.utils.setCursorPosition(this.$input.get(0),this.$input.val().length),this.$input.focus())}}),t.defaults=e.extend({},e.fn.editableform.types.abstract.defaults,{tpl:"<textarea></textarea>",inputclass:"span3",placeholder:null}),e.fn.editableform.types.textarea=t}(window.jQuery),function(e){var t=function(e){this.init("select",e,t.defaults)};e.fn.editableform.utils.inherit(t,e.fn.editableform.types.list),e.extend(t.prototype,{renderList:function(){if(!e.isArray(this.sourceData))return;for(var t=0;t<this.sourceData.length;t++)this.$input.append(e("<option>",{value:this.sourceData[t].value}).text(this.sourceData[t].text))},value2htmlFinal:function(e,n){var r="",i=this.itemByVal(e);i&&(r=i.text),t.superclass.constructor.superclass.value2html(r,n)},autosubmit:function(){this.$input.on("change",function(){e(this).closest("form").submit()})}}),t.defaults=e.extend({},e.fn.editableform.types.list.defaults,{tpl:"<select></select>"}),e.fn.editableform.types.select=t}(window.jQuery),function(e){var t=function(e){this.init("checklist",e,t.defaults)};e.fn.editableform.utils.inherit(t,e.fn.editableform.types.list),e.extend(t.prototype,{renderList:function(){var t,n;if(!e.isArray(this.sourceData))return;for(var r=0;r<this.sourceData.length;r++)t=e("<label>").append(e("<input>",{type:"checkbox",value:this.sourceData[r].value,name:this.options.name})).append(e("<span>").text(" "+this.sourceData[r].text)),e("<div>").append(t).appendTo(this.$input)},value2str:function(t){return e.isArray(t)?t.join(e.trim(this.options.separator)):""},str2value:function(t){var n,r=null;return typeof t=="string"&&t.length?(n=new RegExp("\\s*"+e.trim(this.options.separator)+"\\s*"),r=t.split(n)):e.isArray(t)&&(r=t),r},value2input:function(t){var n=this.$input.find('input[type="checkbox"]');n.removeAttr("checked"),e.isArray(t)&&t.length&&n.each(function(n,r){var i=e(r);e.each(t,function(e,t){i.val()==t&&i.attr("checked","checked")})})},input2value:function(){var t=[];return this.$input.find("input:checked").each(function(n,r){t.push(e(r).val())}),t},value2htmlFinal:function(t,n){var r=[],i,s,o="";if(e.isArray(t)&&t.length<=this.options.limit){for(s=0;s<t.length;s++)i=this.itemByVal(t[s]),i&&r.push(e("<div>").text(i.text).html());o=r.join(this.options.viewseparator)}else o=this.options.limitText.replace("{checked}",e.isArray(t)?t.length:0).replace("{count}",this.sourceData.length);e(n).html(o)},activate:function(){this.$input.find('input[type="checkbox"]').first().focus()},autosubmit:function(){this.$input.find('input[type="checkbox"]').on("keydown",function(t){t.which===13&&e(this).closest("form").submit()})}}),t.defaults=e.extend({},e.fn.editableform.types.list.defaults,{tpl:"<div></div>",inputclass:"span2 editable-checklist",separator:",",viewseparator:"<br>",limit:4,limitText:"Selected {checked} of {count}"}),e.fn.editableform.types.checklist=t}(window.jQuery),function(e){e.extend(e.fn.editableform.Constructor.prototype,{initTemplate:function(){this.$form=e(e.fn.editableform.template),this.$form.find(".editable-error-block").addClass("help-block")}}),e.fn.editableform.buttons='<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button><button type="button" class="btn editable-cancel"><i class="icon-remove"></i></button>',e.fn.editableform.errorGroupClass="error",e.fn.editableform.errorBlockClass=null}(window.jQuery),function(e){e.extend(e.fn.editableContainer.Constructor.prototype,{containerName:"editableform",innerCss:null,initContainer:function(){this.options.anim||(this.options.anim=0)},splitOptions:function(){this.containerOptions={},this.formOptions=this.options},tip:function(){return this.$form},innerShow:function(){this.$element.hide(),this.$form&&this.$form.remove(),this.initForm(),this.tip().addClass("editable-container").addClass("editable-inline"),this.$form.insertAfter(this.$element),this.$form.show(this.options.anim),this.$form.editableform("render")},innerHide:function(){this.$form.hide(this.options.anim,e.proxy(function(){this.$element.show(),this.options.enablefocus&&this.$element.focus()},this))},destroy:function(){this.tip().remove()}}),e.fn.editableContainer.defaults=e.extend({},e.fn.editableContainer.defaults,{anim:"fast",enablefocus:!1})}(window.jQuery),function(e){var t=function(n){this.init("date",n,t.defaults);var r=e.fn.editableform.utils.sliceObj(this.options,["format"]);this.options.datepicker=e.extend({},t.defaults.datepicker,r,n.datepicker),this.options.viewformat||(this.options.viewformat=this.options.datepicker.format),this.options.datepicker.language=this.options.datepicker.language||"en",this.dpg=e.fn.datepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.datepicker.format),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat)};e.fn.editableform.utils.inherit(t,e.fn.editableform.types.abstract),e.extend(t.prototype,{render:function(){t.superclass.render.call(this),this.$input.datepicker(this.options.datepicker),this.options.clear&&(this.$clear=e('<a href="#"></a>').html(this.options.clear).click(e.proxy(function(e){e.preventDefault(),e.stopPropagation(),this.clear()},this)))},value2html:function(e,n){var r=e?this.dpg.formatDate(e,this.parsedViewFormat,this.options.datepicker.language):"";t.superclass.value2html(r,n)},html2value:function(e){return e?this.dpg.parseDate(e,this.parsedViewFormat,this.options.datepicker.language):null},value2str:function(e){return e?this.dpg.formatDate(e,this.parsedFormat,this.options.datepicker.language):""},str2value:function(e){return e?this.dpg.parseDate(e,this.parsedFormat,this.options.datepicker.language):null},value2input:function(e){this.$input.datepicker("update",e)},input2value:function(){return this.$input.data("datepicker").date},activate:function(){},clear:function(){this.$input.data("datepicker").date=null,this.$input.find(".active").removeClass("active")},autosubmit:function(){this.$input.on("changeDate",function(t){var n=e(this).closest("form");setTimeout(function(){n.submit()},200)})}}),t.defaults=e.extend({},e.fn.editableform.types.abstract.defaults,{tpl:"<div></div>",inputclass:"editable-date well",format:"yyyy-mm-dd",viewformat:null,datepicker:{weekStart:0,startView:0,autoclose:!1},clear:"&times; clear"}),e.fn.editableform.types.date=t}(window.jQuery),!function(e){function t(){return new Date(Date.UTC.apply(Date,arguments))}function n(){var e=new Date;return t(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate())}var r=function(t,n){var r=this;this.element=e(t),this.language=n.language||this.element.data("date-language")||"en",this.language=this.language in i?this.language:"en",this.format=s.parseFormat(n.format||this.element.data("date-format")||"mm/dd/yyyy"),this.isInline=!1,this.isInput=this.element.is("input"),this.component=this.element.is(".date")?this.element.find(".add-on"):!1,this.hasInput=this.component&&this.element.find("input").length,this.component&&this.component.length===0&&(this.component=!1),this.isInput?this.element.on({focus:e.proxy(this.show,this),keyup:e.proxy(this.update,this),keydown:e.proxy(this.keydown,this)}):this.component&&this.hasInput?(this.element.find("input").on({focus:e.proxy(this.show,this),keyup:e.proxy(this.update,this),keydown:e.proxy(this.keydown,this)}),this.component.on("click",e.proxy(this.show,this))):this.element.is("div")?this.isInline=!0:this.element.on("click",e.proxy(this.show,this)),this.picker=e(s.template).appendTo(this.isInline?this.element:"body").on({click:e.proxy(this.click,this),mousedown:e.proxy(this.mousedown,this)}),this.isInline?this.picker.addClass("datepicker-inline"):this.picker.addClass("dropdown-menu"),e(document).on("mousedown",function(t){e(t.target).closest(".datepicker").length==0&&r.hide()}),this.autoclose=!1,"autoclose"in n?this.autoclose=n.autoclose:"dateAutoclose"in this.element.data()&&(this.autoclose=this.element.data("date-autoclose")),this.keyboardNavigation=!0,"keyboardNavigation"in n?this.keyboardNavigation=n.keyboardNavigation:"dateKeyboardNavigation"in this.element.data()&&(this.keyboardNavigation=this.element.data("date-keyboard-navigation"));switch(n.startView||this.element.data("date-start-view")){case 2:case"decade":this.viewMode=this.startViewMode=2;break;case 1:case"year":this.viewMode=this.startViewMode=1;break;case 0:case"month":default:this.viewMode=this.startViewMode=0}this.todayBtn=n.todayBtn||this.element.data("date-today-btn")||!1,this.todayHighlight=n.todayHighlight||this.element.data("date-today-highlight")||!1,this.weekStart=(n.weekStart||this.element.data("date-weekstart")||i[this.language].weekStart||0)%7,this.weekEnd=(this.weekStart+6)%7,this.startDate=-Infinity,this.endDate=Infinity,this.setStartDate(n.startDate||this.element.data("date-startdate")),this.setEndDate(n.endDate||this.element.data("date-enddate")),this.fillDow(),this.fillMonths(),this.update(),this.showMode(),this.isInline&&this.show()};r.prototype={constructor:r,show:function(t){this.picker.show(),this.height=this.component?this.component.outerHeight():this.element.outerHeight(),this.update(),this.place(),e(window).on("resize",e.proxy(this.place,this)),t&&(t.stopPropagation(),t.preventDefault()),this.element.trigger({type:"show",date:this.date})},hide:function(t){if(this.isInline)return;this.picker.hide(),e(window).off("resize",this.place),this.viewMode=this.startViewMode,this.showMode(),this.isInput||e(document).off("mousedown",this.hide),t&&t.currentTarget.value&&this.setValue(),this.element.trigger({type:"hide",date:this.date})},getDate:function(){var e=this.getUTCDate();return new Date(e.getTime()+e.getTimezoneOffset()*6e4)},getUTCDate:function(){return this.date},setDate:function(e){this.setUTCDate(new Date(e.getTime()-e.getTimezoneOffset()*6e4))},setUTCDate:function(e){this.date=e,this.setValue()},setValue:function(){var e=this.getFormattedDate();this.isInput?this.element.prop("value",e):(this.component&&this.element.find("input").prop("value",e),this.element.data("date",e))},getFormattedDate:function(e){return e==undefined&&(e=this.format),s.formatDate(this.date,e,this.language)},setStartDate:function(e){this.startDate=e||-Infinity,this.startDate!==-Infinity&&(this.startDate=s.parseDate(this.startDate,this.format,this.language)),this.update(),this.updateNavArrows()},setEndDate:function(e){this.endDate=e||Infinity,this.endDate!==Infinity&&(this.endDate=s.parseDate(this.endDate,this.format,this.language)),this.update(),this.updateNavArrows()},place:function(){if(this.isInline)return;var t=parseInt(this.element.parents().filter(function(){return e(this).css("z-index")!="auto"}).first().css("z-index"))+10,n=this.component?this.component.offset():this.element.offset();this.picker.css({top:n.top+this.height,left:n.left,zIndex:t})},update:function(){var e,t=!1;arguments&&arguments.length&&(typeof arguments[0]=="string"||arguments[0]instanceof Date)?(e=arguments[0],t=!0):e=this.isInput?this.element.prop("value"):this.element.data("date")||this.element.find("input").prop("value"),this.date=s.parseDate(e,this.format,this.language),t&&this.setValue(),this.date<this.startDate?this.viewDate=new Date(this.startDate):this.date>this.endDate?this.viewDate=new Date(this.endDate):this.viewDate=new Date(this.date),this.fill()},fillDow:function(){var e=this.weekStart,t="<tr>";while(e<this.weekStart+7)t+='<th class="dow">'+i[this.language].daysMin[e++%7]+"</th>";t+="</tr>",this.picker.find(".datepicker-days thead").append(t)},fillMonths:function(){var e="",t=0;while(t<12)e+='<span class="month">'+i[this.language].monthsShort[t++]+"</span>";this.picker.find(".datepicker-months td").html(e)},fill:function(){var e=new Date(this.viewDate),n=e.getUTCFullYear(),r=e.getUTCMonth(),o=this.startDate!==-Infinity?this.startDate.getUTCFullYear():-Infinity,u=this.startDate!==-Infinity?this.startDate.getUTCMonth():-Infinity,a=this.endDate!==Infinity?this.endDate.getUTCFullYear():Infinity,f=this.endDate!==Infinity?this.endDate.getUTCMonth():Infinity,l=this.date.valueOf(),c=new Date;this.picker.find(".datepicker-days thead th:eq(1)").text(i[this.language].months[r]+" "+n),this.picker.find("tfoot th.today").text(i[this.language].today).toggle(this.todayBtn),this.updateNavArrows(),this.fillMonths();var h=t(n,r-1,28,0,0,0,0),p=s.getDaysInMonth(h.getUTCFullYear(),h.getUTCMonth());h.setUTCDate(p),h.setUTCDate(p-(h.getUTCDay()-this.weekStart+7)%7);var d=new Date(h);d.setUTCDate(d.getUTCDate()+42),d=d.valueOf();var v=[],m;while(h.valueOf()<d){h.getUTCDay()==this.weekStart&&v.push("<tr>"),m="";if(h.getUTCFullYear()<n||h.getUTCFullYear()==n&&h.getUTCMonth()<r)m+=" old";else if(h.getUTCFullYear()>n||h.getUTCFullYear()==n&&h.getUTCMonth()>r)m+=" new";this.todayHighlight&&h.getUTCFullYear()==c.getFullYear()&&h.getUTCMonth()==c.getMonth()&&h.getUTCDate()==c.getDate()&&(m+=" today"),h.valueOf()==l&&(m+=" active");if(h.valueOf()<this.startDate||h.valueOf()>this.endDate)m+=" disabled";v.push('<td class="day'+m+'">'+h.getUTCDate()+"</td>"),h.getUTCDay()==this.weekEnd&&v.push("</tr>"),h.setUTCDate(h.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(v.join(""));var g=this.date.getUTCFullYear(),y=this.picker.find(".datepicker-months").find("th:eq(1)").text(n).end().find("span").removeClass("active");g==n&&y.eq(this.date.getUTCMonth()).addClass("active"),(n<o||n>a)&&y.addClass("disabled"),n==o&&y.slice(0,u).addClass("disabled"),n==a&&y.slice(f+1).addClass("disabled"),v="",n=parseInt(n/10,10)*10;var b=this.picker.find(".datepicker-years").find("th:eq(1)").text(n+"-"+(n+9)).end().find("td");n-=1;for(var w=-1;w<11;w++)v+='<span class="year'+(w==-1||w==10?" old":"")+(g==n?" active":"")+(n<o||n>a?" disabled":"")+'">'+n+"</span>",n+=1;b.html(v)},updateNavArrows:function(){var e=new Date(this.viewDate),t=e.getUTCFullYear(),n=e.getUTCMonth();switch(this.viewMode){case 0:this.startDate!==-Infinity&&t<=this.startDate.getUTCFullYear()&&n<=this.startDate.getUTCMonth()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==Infinity&&t>=this.endDate.getUTCFullYear()&&n>=this.endDate.getUTCMonth()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 1:case 2:this.startDate!==-Infinity&&t<=this.startDate.getUTCFullYear()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==Infinity&&t>=this.endDate.getUTCFullYear()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"})}},click:function(n){n.stopPropagation(),n.preventDefault();var r=e(n.target).closest("span, td, th");if(r.length==1)switch(r[0].nodeName.toLowerCase()){case"th":switch(r[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var i=s.modes[this.viewMode].navStep*(r[0].className=="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,i);break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,i)}this.fill();break;case"today":var o=new Date;o.setUTCHours(0),o.setUTCMinutes(0),o.setUTCSeconds(0),o.setUTCMilliseconds(0),this.showMode(-2);var u=this.todayBtn=="linked"?null:"view";this._setDate(o,u)}break;case"span":if(!r.is(".disabled")){this.viewDate.setUTCDate(1);if(r.is(".month")){var a=r.parent().find("span").index(r);this.viewDate.setUTCMonth(a),this.element.trigger({type:"changeMonth",date:this.viewDate})}else{var f=parseInt(r.text(),10)||0;this.viewDate.setUTCFullYear(f),this.element.trigger({type:"changeYear",date:this.viewDate})}this.showMode(-1),this.fill()}break;case"td":if(r.is(".day")&&!r.is(".disabled")){var l=parseInt(r.text(),10)||1,f=this.viewDate.getUTCFullYear(),a=this.viewDate.getUTCMonth();r.is(".old")?a==0?(a=11,f-=1):a-=1:r.is(".new")&&(a==11?(a=0,f+=1):a+=1),this._setDate(t(f,a,l,0,0,0,0))}}},_setDate:function(e,t){if(!t||t=="date")this.date=e;if(!t||t=="view")this.viewDate=e;this.fill(),this.setValue(),this.element.trigger({type:"changeDate",date:this.date});var n;this.isInput?n=this.element:this.component&&(n=this.element.find("input")),n&&(n.change(),this.autoclose&&this.hide())},moveMonth:function(e,t){if(!t)return e;var n=new Date(e.valueOf()),r=n.getUTCDate(),i=n.getUTCMonth(),s=Math.abs(t),o,u;t=t>0?1:-1;if(s==1){u=t==-1?function(){return n.getUTCMonth()==i}:function(){return n.getUTCMonth()!=o},o=i+t,n.setUTCMonth(o);if(o<0||o>11)o=(o+12)%12}else{for(var a=0;a<s;a++)n=this.moveMonth(n,t);o=n.getUTCMonth(),n.setUTCDate(r),u=function(){return o!=n.getUTCMonth()}}while(u())n.setUTCDate(--r),n.setUTCMonth(o);return n},moveYear:function(e,t){return this.moveMonth(e,t*12)},dateWithinRange:function(e){return e>=this.startDate&&e<=this.endDate},keydown:function(e){if(this.picker.is(":not(:visible)")){e.keyCode==27&&this.show();return}var t=!1,n,r,i,s,o;switch(e.keyCode){case 27:this.hide(),e.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation)break;n=e.keyCode==37?-1:1,e.ctrlKey?(s=this.moveYear(this.date,n),o=this.moveYear(this.viewDate,n)):e.shiftKey?(s=this.moveMonth(this.date,n),o=this.moveMonth(this.viewDate,n)):(s=new Date(this.date),s.setUTCDate(this.date.getUTCDate()+n),o=new Date(this.viewDate),o.setUTCDate(this.viewDate.getUTCDate()+n)),this.dateWithinRange(s)&&(this.date=s,this.viewDate=o,this.setValue(),this.update(),e.preventDefault(),t=!0);break;case 38:case 40:if(!this.keyboardNavigation)break;n=e.keyCode==38?-1:1,e.ctrlKey?(s=this.moveYear(this.date,n),o=this.moveYear(this.viewDate,n)):e.shiftKey?(s=this.moveMonth(this.date,n),o=this.moveMonth(this.viewDate,n)):(s=new Date(this.date),s.setUTCDate(this.date.getUTCDate()+n*7),o=new Date(this.viewDate),o.setUTCDate(this.viewDate.getUTCDate()+n*7)),this.dateWithinRange(s)&&(this.date=s,this.viewDate=o,this.setValue(),this.update(),e.preventDefault(),t=!0);break;case 13:this.hide(),e.preventDefault();break;case 9:this.hide()}if(t){this.element.trigger({type:"changeDate",date:this.date});var u;this.isInput?u=this.element:this.component&&(u=this.element.find("input")),u&&u.change()}},showMode:function(e){e&&(this.viewMode=Math.max(0,Math.min(2,this.viewMode+e))),this.picker.find(">div").hide().filter(".datepicker-"+s.modes[this.viewMode].clsName).show(),this.updateNavArrows()}},e.fn.datepicker=function(t){var n=Array.apply(null,arguments);return n.shift(),this.each(function(){var i=e(this),s=i.data("datepicker"),o=typeof t=="object"&&t;s||i.data("datepicker",s=new r(this,e.extend({},e.fn.datepicker.defaults,o))),typeof t=="string"&&typeof s[t]=="function"&&s[t].apply(s,n)})},e.fn.datepicker.defaults={},e.fn.datepicker.Constructor=r;var i=e.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today"}},s={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(e){return e%4===0&&e%100!==0||e%400===0},getDaysInMonth:function(e,t){return[31,s.isLeapYear(e)?29:28,31,30,31,30,31,31,30,31,30,31][t]},validParts:/dd?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\r]+/g,parseFormat:function(e){var t=e.replace(this.validParts,"\0").split("\0"),n=e.match(this.validParts);if(!t||!t.length||!n||n.length==0)throw new Error("Invalid date format.");return{separators:t,parts:n}},parseDate:function(n,s,o){if(n instanceof Date)return n;if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(n)){var u=/([-+]\d+)([dmwy])/,a=n.match(/([-+]\d+)([dmwy])/g),f,l;n=new Date;for(var c=0;c<a.length;c++){f=u.exec(a[c]),l=parseInt(f[1]);switch(f[2]){case"d":n.setUTCDate(n.getUTCDate()+l);break;case"m":n=r.prototype.moveMonth.call(r.prototype,n,l);break;case"w":n.setUTCDate(n.getUTCDate()+l*7);break;case"y":n=r.prototype.moveYear.call(r.prototype,n,l)}}return t(n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate(),0,0,0)}var a=n&&n.match(this.nonpunctuation)||[],n=new Date,h={},p=["yyyy","yy","M","MM","m","mm","d","dd"],d={yyyy:function(e,t){return e.setUTCFullYear(t)},yy:function(e,t){return e.setUTCFullYear(2e3+t)},m:function(e,t){t-=1;while(t<0)t+=12;t%=12,e.setUTCMonth(t);while(e.getUTCMonth()!=t)e.setUTCDate(e.getUTCDate()-1);return e},d:function(e,t){return e.setUTCDate(t)}},v,m,f;d.M=d.MM=d.mm=d.m,d.dd=d.d,n=t(n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate(),0,0,0);if(a.length==s.parts.length){for(var c=0,g=s.parts.length;c<g;c++){v=parseInt(a[c],10),f=s.parts[c];if(isNaN(v))switch(f){case"MM":m=e(i[o].months).filter(function(){var e=this.slice(0,a[c].length),t=a[c].slice(0,e.length);return e==t}),v=e.inArray(m[0],i[o].months)+1;break;case"M":m=e(i[o].monthsShort).filter(function(){var e=this.slice(0,a[c].length),t=a[c].slice(0,e.length);return e==t}),v=e.inArray(m[0],i[o].monthsShort)+1}h[f]=v}for(var c=0,y;c<p.length;c++)y=p[c],y in h&&d[y](n,h[y])}return n},formatDate:function(t,n,r){var s={d:t.getUTCDate(),m:t.getUTCMonth()+1,M:i[r].monthsShort[t.getUTCMonth()],MM:i[r].months[t.getUTCMonth()],yy:t.getUTCFullYear().toString().substring(2),yyyy:t.getUTCFullYear()};s.dd=(s.d<10?"0":"")+s.d,s.mm=(s.m<10?"0":"")+s.m;var t=[],o=e.extend([],n.separators);for(var u=0,a=n.parts.length;u<a;u++)o.length&&t.push(o.shift()),t.push(s[n.parts[u]]);return t.join("")},headTemplate:'<thead><tr><th class="prev"><i class="icon-arrow-left"/></th><th colspan="5" class="switch"></th><th class="next"><i class="icon-arrow-right"/></th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'};s.template='<div class="datepicker"><div class="datepicker-days"><table class=" table-condensed">'+s.headTemplate+"<tbody></tbody>"+s.footTemplate+"</table>"+"</div>"+'<div class="datepicker-months">'+'<table class="table-condensed">'+s.headTemplate+s.contTemplate+s.footTemplate+"</table>"+"</div>"+'<div class="datepicker-years">'+'<table class="table-condensed">'+s.headTemplate+s.contTemplate+s.footTemplate+"</table>"+"</div>"+"</div>",e.fn.datepicker.DPGlobal=s}(window.jQuery);
5
+ (function(e){var t=function(t,n){this.options=e.extend({},e.fn.editableform.defaults,n),this.$div=e(t),this.options.scope||(this.options.scope=this),this.initInput()};t.prototype={constructor:t,initInput:function(){var t,n;if(typeof e.fn.editabletypes[this.options.type]!="function"){e.error("Unknown type: "+this.options.type);return}t=e.fn.editabletypes[this.options.type],n=e.fn.editableutils.sliceObj(this.options,e.fn.editableutils.objectKeys(t.defaults)),this.input=new t(n),this.value=this.input.str2value(this.options.value)},initTemplate:function(){this.$form=e(e.fn.editableform.template)},initButtons:function(){this.$form.find(".editable-buttons").append(e.fn.editableform.buttons)},render:function(){this.$loading=e(e.fn.editableform.loading),this.$div.empty().append(this.$loading),this.showLoading(),this.initTemplate(),this.options.showbuttons?this.initButtons():this.$form.find(".editable-buttons").remove(),this.$div.triggerHandler("rendering"),e.when(this.input.render()).then(e.proxy(function(){this.$form.find("div.editable-input").append(this.input.$input),this.options.showbuttons||this.input.autosubmit(),this.input.$clear&&this.$form.find("div.editable-input").append(e('<div class="editable-clear">').append(this.input.$clear)),this.$div.append(this.$form),this.$form.find(".editable-cancel").click(e.proxy(this.cancel,this)),this.input.error?(this.error(this.input.error),this.$form.find(".editable-submit").attr("disabled",!0),this.input.$input.attr("disabled",!0),this.$form.submit(function(e){e.preventDefault()})):(this.error(!1),this.input.$input.removeAttr("disabled"),this.$form.find(".editable-submit").removeAttr("disabled"),this.input.value2input(this.value),this.$form.submit(e.proxy(this.submit,this))),this.$div.triggerHandler("rendered"),this.showForm()},this))},cancel:function(){this.$div.triggerHandler("cancel")},showLoading:function(){var e;this.$form?(this.$loading.width(this.$form.outerWidth()),this.$loading.height(this.$form.outerHeight()),this.$form.hide()):(e=this.$loading.parent().width(),e&&this.$loading.width(e)),this.$loading.show()},showForm:function(e){this.$loading.hide(),this.$form.show(),e!==!1&&this.input.activate(),this.$div.triggerHandler("show")},error:function(t){var n=this.$form.find(".control-group"),r=this.$form.find(".editable-error-block");t===!1?(n.removeClass(e.fn.editableform.errorGroupClass),r.removeClass(e.fn.editableform.errorBlockClass).empty().hide()):(n.addClass(e.fn.editableform.errorGroupClass),r.addClass(e.fn.editableform.errorBlockClass).text(t).show())},submit:function(t){t.stopPropagation(),t.preventDefault();var n,r=this.input.input2value();if(n=this.validate(r)){this.error(n),this.showForm();return}if(!this.options.savenochange&&this.input.value2str(r)==this.input.value2str(this.value)){this.$div.triggerHandler("nochange");return}e.when(this.save(r)).done(e.proxy(function(e){var t=typeof this.options.success=="function"?this.options.success.call(this.options.scope,e,r):null;if(t===!1){this.error(!1),this.showForm(!1);return}if(typeof t=="string"){this.error(t),this.showForm();return}t&&typeof t=="object"&&t.hasOwnProperty("newValue")&&(r=t.newValue),this.error(!1),this.value=r,this.$div.triggerHandler("save",{newValue:r,response:e})},this)).fail(e.proxy(function(e){this.error(typeof e=="string"?e:e.responseText||e.statusText||"Unknown error!"),this.showForm()},this))},save:function(t){var n=this.input.value2submit(t);this.options.pk=e.fn.editableutils.tryParseJson(this.options.pk,!0);var r=typeof this.options.pk=="function"?this.options.pk.call(this.options.scope):this.options.pk,i=!!(typeof this.options.url=="function"||this.options.url&&(this.options.send==="always"||this.options.send==="auto"&&r)),s;if(i)return this.showLoading(),s={name:this.options.name||"",value:n,pk:r},typeof this.options.params=="function"?s=this.options.params.call(this.options.scope,s):(this.options.params=e.fn.editableutils.tryParseJson(this.options.params,!0),e.extend(s,this.options.params)),typeof this.options.url=="function"?this.options.url.call(this.options.scope,s):e.ajax(e.extend({url:this.options.url,data:s,type:"POST"},this.options.ajaxOptions))},validate:function(e){e===undefined&&(e=this.value);if(typeof this.options.validate=="function")return this.options.validate.call(this.options.scope,e)},option:function(e,t){this.options[e]=t,e==="value"&&this.setValue(t)},setValue:function(e,t){t?this.value=this.input.str2value(e):this.value=e}},e.fn.editableform=function(n){var r=arguments;return this.each(function(){var i=e(this),s=i.data("editableform"),o=typeof n=="object"&&n;s||i.data("editableform",s=new t(this,o)),typeof n=="string"&&s[n].apply(s,Array.prototype.slice.call(r,1))})},e.fn.editableform.Constructor=t,e.fn.editableform.defaults={type:"text",url:null,params:null,name:null,pk:null,value:null,send:"auto",validate:null,success:null,ajaxOptions:null,showbuttons:!0,scope:null,savenochange:!1},e.fn.editableform.template='<form class="form-inline editableform"><div class="control-group"><div><div class="editable-input"></div><div class="editable-buttons"></div></div><div class="editable-error-block"></div></div></form>',e.fn.editableform.loading='<div class="editableform-loading"></div>',e.fn.editableform.buttons='<button type="submit" class="editable-submit">ok</button><button type="button" class="editable-cancel">cancel</button>',e.fn.editableform.errorGroupClass=null,e.fn.editableform.errorBlockClass="editable-error"})(window.jQuery),function(e){e.fn.editableutils={inherit:function(e,t){var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e,e.superclass=t.prototype},setCursorPosition:function(e,t){if(e.setSelectionRange)e.setSelectionRange(t,t);else if(e.createTextRange){var n=e.createTextRange();n.collapse(!0),n.moveEnd("character",t),n.moveStart("character",t),n.select()}},tryParseJson:function(e,t){if(typeof e=="string"&&e.length&&e.match(/^[\{\[].*[\}\]]$/))if(t)try{e=(new Function("return "+e))()}catch(n){}finally{return e}else e=(new Function("return "+e))();return e},sliceObj:function(t,n,r){var i,s,o={};if(!e.isArray(n)||!n.length)return o;for(var u=0;u<n.length;u++){i=n[u],t.hasOwnProperty(i)&&(o[i]=t[i]);if(r===!0)continue;s=i.toLowerCase(),t.hasOwnProperty(s)&&(o[i]=t[s])}return o},getConfigData:function(t){var n={};return e.each(t.data(),function(e,t){if(typeof t!="object"||t&&typeof t=="object"&&t.constructor===Object)n[e]=t}),n},objectKeys:function(e){if(Object.keys)return Object.keys(e);if(e!==Object(e))throw new TypeError("Object.keys called on a non-object");var t=[],n;for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.push(n);return t},escape:function(t){return e("<div>").text(t).html()}}}(window.jQuery),function(e){var t=function(e,t){this.init(e,t)};t.prototype={containerName:null,innerCss:null,init:function(n,r){this.$element=e(n),this.options=e.extend({},e.fn.editableContainer.defaults,e.fn.editableutils.getConfigData(this.$element),r),this.splitOptions(),this.initContainer(),this.$element.on("destroyed",e.proxy(function(){this.destroy()},this)),e(document).data("editable-handlers-attached")||(e(document).on("keyup.editable",function(t){t.which===27&&e(".editable-open").editableContainer("hide")}),e(document).on("click.editable",function(n){var r=e(n.target);if(r.is(".editable-container")||r.parents(".editable-container").length||r.parents(".ui-datepicker-header").length)return;t.prototype.closeOthers(n.target)}),e(document).data("editable-handlers-attached",!0))},splitOptions:function(){this.containerOptions={},this.formOptions={};var t=e.fn[this.containerName].defaults;for(var n in this.options)n in t?this.containerOptions[n]=this.options[n]:this.formOptions[n]=this.options[n]},initContainer:function(){this.call(this.containerOptions)},initForm:function(){return this.formOptions.scope=this.$element[0],this.$form=e("<div>").editableform(this.formOptions).on({save:e.proxy(this.save,this),cancel:e.proxy(function(){this.hide("cancel")},this),nochange:e.proxy(function(){this.hide("nochange")},this),show:e.proxy(this.setPosition,this),rendering:e.proxy(this.setPosition,this),rendered:e.proxy(function(){this.$element.triggerHandler("shown")},this)}),this.$form},tip:function(){return this.container().$tip},container:function(){return this.$element.data(this.containerName)},call:function(){this.$element[this.containerName].apply(this.$element,arguments)},show:function(e){this.$element.addClass("editable-open"),e!==!1&&this.closeOthers(this.$element[0]),this.innerShow()},innerShow:function(){this.call("show"),this.tip().addClass("editable-container"),this.initForm(),this.tip().find(this.innerCss).empty().append(this.$form),this.$form.editableform("render")},hide:function(e){if(!this.tip()||!this.tip().is(":visible")||!this.$element.hasClass("editable-open"))return;this.$element.removeClass("editable-open"),this.innerHide(),this.$element.triggerHandler("hidden",e)},innerHide:function(){this.call("hide")},toggle:function(e){this.tip&&this.tip().is(":visible")?this.hide():this.show(e)},setPosition:function(){},save:function(e,t){this.hide("save"),this.$element.triggerHandler("save",t)},option:function(e,t){this.options[e]=t,e in this.containerOptions?(this.containerOptions[e]=t,this.setContainerOption(e,t)):(this.formOptions[e]=t,this.$form&&this.$form.editableform("option",e,t))},setContainerOption:function(e,t){this.call("option",e,t)},destroy:function(){this.call("destroy")},closeOthers:function(t){e(".editable-open").each(function(n,r){if(r===t||e(r).find(t).length)return;var i=e(r),s=i.data("editableContainer");if(!s)return;s.options.onblur==="cancel"?i.data("editableContainer").hide("onblur"):s.options.onblur==="submit"&&i.data("editableContainer").tip().find("form").submit()})},activate:function(){this.tip&&this.tip().is(":visible")&&this.$form&&this.$form.data("editableform").input.activate()}},e.fn.editableContainer=function(n){var r=arguments;return this.each(function(){var i=e(this),s="editableContainer",o=i.data(s),u=typeof n=="object"&&n;o||i.data(s,o=new t(this,u)),typeof n=="string"&&o[n].apply(o,Array.prototype.slice.call(r,1))})},e.fn.editableContainer.Constructor=t,e.fn.editableContainer.defaults={value:null,placement:"top",autohide:!0,onblur:"cancel"},jQuery.event.special.destroyed={remove:function(e){e.handler&&e.handler()}}}(window.jQuery),function(e){var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.editable.defaults,e.fn.editableutils.getConfigData(this.$element),n),this.init()};t.prototype={constructor:t,init:function(){var t,n=!1,r,i;if(!e.fn.editableContainer){e.error("You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)");return}this.options.name=this.options.name||this.$element.attr("id");if(typeof e.fn.editabletypes[this.options.type]!="function"){e.error("Unknown type: "+this.options.type);return}t=e.fn.editabletypes[this.options.type],this.typeOptions=e.fn.editableutils.sliceObj(this.options,e.fn.editableutils.objectKeys(t.defaults)),this.input=new t(this.typeOptions),this.options.value===undefined||this.options.value===null?(this.value=this.input.html2value(e.trim(this.$element.html())),n=!0):(this.options.value=e.fn.editableutils.tryParseJson(this.options.value,!0),typeof this.options.value=="string"?this.value=this.input.str2value(this.options.value):this.value=this.options.value),this.$element.addClass("editable"),this.options.toggle!=="manual"?(this.$element.addClass("editable-click"),this.$element.on(this.options.toggle+".editable",e.proxy(function(e){e.preventDefault();if(this.options.toggle==="mouseenter")this.show();else{var t=this.options.toggle!=="click";this.toggle(t)}},this))):this.$element.attr("tabindex",-1),r=!n&&this.value!==null&&this.value!==undefined,r&=this.options.autotext==="always"||this.options.autotext==="auto"&&!this.$element.text().length,e.when(r?this.render():!0).then(e.proxy(function(){this.options.disabled?this.disable():this.enable(),this.$element.triggerHandler("init",this)},this))},render:function(){if(this.options.display===!1)return;return this.input.options.hasOwnProperty("source")?this.input.value2html(this.value,this.$element[0],this.options.display):typeof this.options.display=="function"?this.options.display.call(this.$element[0],this.value):this.input.value2html(this.value,this.$element[0])},enable:function(){this.options.disabled=!1,this.$element.removeClass("editable-disabled"),this.handleEmpty(),this.options.toggle!=="manual"&&this.$element.attr("tabindex")==="-1"&&this.$element.removeAttr("tabindex")},disable:function(){this.options.disabled=!0,this.hide(),this.$element.addClass("editable-disabled"),this.handleEmpty(),this.$element.attr("tabindex",-1)},toggleDisabled:function(){this.options.disabled?this.enable():this.disable()},option:function(t,n){if(t&&typeof t=="object"){e.each(t,e.proxy(function(t,n){this.option(e.trim(t),n)},this));return}this.options[t]=n;if(t==="disabled"){n?this.disable():this.enable();return}t==="value"&&this.setValue(n),this.container&&this.container.option(t,n)},handleEmpty:function(){if(this.options.display===!1)return;var t="editable-empty";this.options.disabled?this.$element.hasClass(t)&&(this.$element.empty(),this.$element.removeClass(t)):e.trim(this.$element.text())===""?this.$element.addClass(t).text(this.options.emptytext):this.$element.removeClass(t)},show:function(t){if(this.options.disabled)return;if(!this.container){var n=e.extend({},this.options,{value:this.value});this.$element.editableContainer(n),this.$element.on("save.internal",e.proxy(this.save,this)),this.container=this.$element.data("editableContainer")}else if(this.container.tip().is(":visible"))return;this.container.show(t)},hide:function(){this.container&&this.container.hide()},toggle:function(e){this.container&&this.container.tip().is(":visible")?this.hide():this.show(e)},save:function(e,t){typeof this.options.url!="function"&&this.options.display!==!1&&t.response===undefined&&this.input.value2str(this.value)!==this.input.value2str(t.newValue)?this.$element.addClass("editable-unsaved"):this.$element.removeClass("editable-unsaved"),this.setValue(t.newValue)},validate:function(){if(typeof this.options.validate=="function")return this.options.validate.call(this,this.value)},setValue:function(t,n){n?this.value=this.input.str2value(t):this.value=t,this.container&&this.container.option("value",this.value),e.when(this.render()).then(e.proxy(function(){this.handleEmpty()},this))},activate:function(){this.container&&this.container.activate()}},e.fn.editable=function(n){var r={},i=arguments,s="editable";switch(n){case"validate":return this.each(function(){var t=e(this),n=t.data(s),i;n&&(i=n.validate())&&(r[n.options.name]=i)}),r;case"getValue":return this.each(function(){var t=e(this),n=t.data(s);n&&n.value!==undefined&&n.value!==null&&(r[n.options.name]=n.input.value2submit(n.value))}),r;case"submit":var o=arguments[1]||{},u=this,a=this.editable("validate"),f;return e.isEmptyObject(a)?(f=this.editable("getValue"),o.data&&e.extend(f,o.data),e.ajax(e.extend({url:o.url,data:f,type:"POST"},o.ajaxOptions)).success(function(e){typeof o.success=="function"&&o.success.call(u,e,o)}).error(function(){typeof o.error=="function"&&o.error.apply(u,arguments)})):typeof o.error=="function"&&o.error.call(u,a),this}return this.each(function(){var r=e(this),o=r.data(s),u=typeof n=="object"&&n;o||r.data(s,o=new t(this,u)),typeof n=="string"&&o[n].apply(o,Array.prototype.slice.call(i,1))})},e.fn.editable.defaults={type:"text",disabled:!1,toggle:"click",emptytext:"Empty",autotext:"auto",value:null,display:null}}(window.jQuery),function(e){e.fn.editabletypes={};var t=function(){};t.prototype={init:function(t,n,r){this.type=t,this.options=e.extend({},r,n),this.$input=null,this.$clear=null,this.error=null},render:function(){this.$input=e(this.options.tpl),this.options.inputclass&&this.$input.addClass(this.options.inputclass),this.options.placeholder&&this.$input.attr("placeholder",this.options.placeholder)},value2html:function(t,n){e(n).text(t)},html2value:function(t){return e("<div>").html(t).text()},value2str:function(e){return e},str2value:function(e){return e},value2submit:function(e){return e},value2input:function(e){this.$input.val(e)},input2value:function(){return this.$input.val()},activate:function(){this.$input.is(":visible")&&this.$input.focus()},clear:function(){this.$input.val(null)},escape:function(t){return e("<div>").text(t).html()},autosubmit:function(){}},t.defaults={tpl:"",inputclass:"input-medium",name:null},e.extend(e.fn.editabletypes,{abstractinput:t})}(window.jQuery),function(e){var t=function(e){};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{render:function(){t.superclass.render.call(this);var n=e.Deferred();return this.error=null,this.sourceData=null,this.prependData=null,this.onSourceReady(function(){this.renderList(),n.resolve()},function(){this.error=this.options.sourceError,n.resolve()}),n.promise()},html2value:function(e){return null},value2html:function(t,n,r){var i=e.Deferred();return this.onSourceReady(function(){typeof r=="function"?r.call(n,t,this.sourceData):this.value2htmlFinal(t,n),i.resolve()},function(){i.resolve()}),i.promise()},onSourceReady:function(t,n){if(e.isArray(this.sourceData)){t.call(this);return}try{this.options.source=e.fn.editableutils.tryParseJson(this.options.source,!1)}catch(r){n.call(this);return}if(typeof this.options.source=="string"){if(this.options.sourceCache){var i=this.options.source+(this.options.name?"-"+this.options.name:""),s;e(document).data(i)||e(document).data(i,{}),s=e(document).data(i);if(s.loading===!1&&s.sourceData){this.sourceData=s.sourceData,t.call(this);return}if(s.loading===!0){s.callbacks.push(e.proxy(function(){this.sourceData=s.sourceData,t.call(this)},this)),s.err_callbacks.push(e.proxy(n,this));return}s.loading=!0,s.callbacks=[],s.err_callbacks=[]}e.ajax({url:this.options.source,type:"get",cache:!1,data:this.options.name?{name:this.options.name}:{},dataType:"json",success:e.proxy(function(r){s&&(s.loading=!1),this.sourceData=this.makeArray(r),e.isArray(this.sourceData)?(this.doPrepend(),t.call(this),s&&(s.sourceData=this.sourceData,e.each(s.callbacks,function(){this.call()}))):(n.call(this),s&&e.each(s.err_callbacks,function(){this.call()}))},this),error:e.proxy(function(){n.call(this),s&&(s.loading=!1,e.each(s.err_callbacks,function(){this.call()}))},this)})}else this.sourceData=this.makeArray(this.options.source),e.isArray(this.sourceData)?(this.doPrepend(),t.call(this)):n.call(this)},doPrepend:function(){if(this.options.prepend===null||this.options.prepend===undefined)return;e.isArray(this.prependData)||(this.options.prepend=e.fn.editableutils.tryParseJson(this.options.prepend,!0),typeof this.options.prepend=="string"&&(this.options.prepend={"":this.options.prepend}),this.prependData=this.makeArray(this.options.prepend)),e.isArray(this.prependData)&&e.isArray(this.sourceData)&&(this.sourceData=this.prependData.concat(this.sourceData))},renderList:function(){},value2htmlFinal:function(e,t){},makeArray:function(t){var n,r,i=[],s;if(!t||typeof t=="string")return null;if(e.isArray(t)){s=function(e,t){r={value:e,text:t};if(n++>=2)return!1};for(var o=0;o<t.length;o++)typeof t[o]=="object"?(n=0,e.each(t[o],s),n===1?i.push(r):n>1&&t[o].hasOwnProperty("value")&&t[o].hasOwnProperty("text")&&i.push(t[o])):i.push({value:t[o],text:t[o]})}else e.each(t,function(e,t){i.push({value:e,text:t})});return i},itemByVal:function(t){if(e.isArray(this.sourceData))for(var n=0;n<this.sourceData.length;n++)if(this.sourceData[n].value==t)return this.sourceData[n]}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{source:null,prepend:!1,sourceError:"Error when loading list",sourceCache:!0}),e.fn.editabletypes.list=t}(window.jQuery),function(e){var t=function(e){this.init("text",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{activate:function(){this.$input.is(":visible")&&(this.$input.focus(),e.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length))}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',placeholder:null}),e.fn.editabletypes.text=t}(window.jQuery),function(e){var t=function(e){this.init("textarea",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{render:function(){t.superclass.render.call(this),this.$input.keydown(function(t){t.ctrlKey&&t.which===13&&e(this).closest("form").submit()})},value2html:function(t,n){var r="",i;if(t){i=t.split("\n");for(var s=0;s<i.length;s++)i[s]=e("<div>").text(i[s]).html();r=i.join("<br>")}e(n).html(r)},html2value:function(t){if(!t)return"";var n=t.split(/<br\s*\/?>/i);for(var r=0;r<n.length;r++)n[r]=e("<div>").html(n[r]).text();return n.join("\n")},activate:function(){this.$input.is(":visible")&&(e.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length),this.$input.focus())}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{tpl:"<textarea></textarea>",inputclass:"input-large",placeholder:null}),e.fn.editabletypes.textarea=t}(window.jQuery),function(e){var t=function(e){this.init("select",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.list),e.extend(t.prototype,{renderList:function(){if(!e.isArray(this.sourceData))return;for(var t=0;t<this.sourceData.length;t++)this.$input.append(e("<option>",{value:this.sourceData[t].value}).text(this.sourceData[t].text));this.$input.on("keydown.editable",function(t){t.which===13&&e(this).closest("form").submit()})},value2htmlFinal:function(e,n){var r="",i=this.itemByVal(e);i&&(r=i.text),t.superclass.constructor.superclass.value2html(r,n)},autosubmit:function(){this.$input.off("keydown.editable").on("change.editable",function(){e(this).closest("form").submit()})}}),t.defaults=e.extend({},e.fn.editabletypes.list.defaults,{tpl:"<select></select>"}),e.fn.editabletypes.select=t}(window.jQuery),function(e){var t=function(e){this.init("checklist",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.list),e.extend(t.prototype,{renderList:function(){var t,n;if(!e.isArray(this.sourceData))return;for(var r=0;r<this.sourceData.length;r++)t=e("<label>").append(e("<input>",{type:"checkbox",value:this.sourceData[r].value,name:this.options.name})).append(e("<span>").text(" "+this.sourceData[r].text)),e("<div>").append(t).appendTo(this.$input)},value2str:function(t){return e.isArray(t)?t.sort().join(e.trim(this.options.separator)):""},str2value:function(t){var n,r=null;return typeof t=="string"&&t.length?(n=new RegExp("\\s*"+e.trim(this.options.separator)+"\\s*"),r=t.split(n)):e.isArray(t)&&(r=t),r},value2input:function(t){var n=this.$input.find('input[type="checkbox"]');n.removeAttr("checked"),e.isArray(t)&&t.length&&n.each(function(n,r){var i=e(r);e.each(t,function(e,t){i.val()==t&&i.attr("checked","checked")})})},input2value:function(){var t=[];return this.$input.find("input:checked").each(function(n,r){t.push(e(r).val())}),t},value2htmlFinal:function(t,n){var r=[],i=e.grep(this.sourceData,function(n){return e.grep(t,function(e){return e==n.value}).length});i.length?(e.each(i,function(t,n){r.push(e.fn.editableutils.escape(n.text))}),e(n).html(r.join("<br>"))):e(n).empty()},activate:function(){this.$input.find('input[type="checkbox"]').first().focus()},autosubmit:function(){this.$input.find('input[type="checkbox"]').on("keydown",function(t){t.which===13&&e(this).closest("form").submit()})}}),t.defaults=e.extend({},e.fn.editabletypes.list.defaults,{tpl:"<div></div>",inputclass:"editable-checklist",separator:","}),e.fn.editabletypes.checklist=t}(window.jQuery),function(e){var t=function(e){this.init("password",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),e.extend(t.prototype,{value2html:function(t,n){t?e(n).text("[hidden]"):e(n).empty()},html2value:function(e){return null}}),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="password">'}),e.fn.editabletypes.password=t}(window.jQuery),function(e){var t=function(e){this.init("email",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="email">'}),e.fn.editabletypes.email=t}(window.jQuery),function(e){var t=function(e){this.init("url",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="url">'}),e.fn.editabletypes.url=t}(window.jQuery),function(e){var t=function(e){this.init("tel",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="tel">'}),e.fn.editabletypes.tel=t}(window.jQuery),function(e){var t=function(e){this.init("number",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),e.extend(t.prototype,{render:function(){t.superclass.render.call(this),this.options.min!==null&&this.$input.attr("min",this.options.min),this.options.max!==null&&this.$input.attr("max",this.options.max),this.options.step!==null&&this.$input.attr("step",this.options.step)}}),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="number">',inputclass:"input-mini",min:null,max:null,step:null}),e.fn.editabletypes.number=t}(window.jQuery),function(e){var t=function(e){this.init("range",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.number),e.extend(t.prototype,{render:function(){this.$input=e(this.options.tpl);var t=this.$input.filter("input");this.options.inputclass&&t.addClass(this.options.inputclass),this.options.min!==null&&t.attr("min",this.options.min),this.options.max!==null&&t.attr("max",this.options.max),this.options.step!==null&&t.attr("step",this.options.step),t.on("input",function(){e(this).siblings("output").text(e(this).val())})},activate:function(){this.$input.filter("input").focus()}}),t.defaults=e.extend({},e.fn.editabletypes.number.defaults,{tpl:'<input type="range"><output style="width: 30px; display: inline-block"></output>',inputclass:"input-medium"}),e.fn.editabletypes.range=t}(window.jQuery),function(e){e.extend(e.fn.editableform.Constructor.prototype,{initTemplate:function(){this.$form=e(e.fn.editableform.template),this.$form.find(".editable-error-block").addClass("help-block")}}),e.fn.editableform.buttons='<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button><button type="button" class="btn editable-cancel"><i class="icon-remove"></i></button>',e.fn.editableform.errorGroupClass="error",e.fn.editableform.errorBlockClass=null}(window.jQuery),function(e){e.extend(e.fn.editableContainer.Constructor.prototype,{containerName:"editableform",innerCss:null,initContainer:function(){this.options.anim||(this.options.anim=0)},splitOptions:function(){this.containerOptions={},this.formOptions=this.options},tip:function(){return this.$form},innerShow:function(){this.$element.hide(),this.$form&&this.$form.remove(),this.initForm(),this.tip().addClass("editable-container").addClass("editable-inline"),this.$form.insertAfter(this.$element),this.$form.show(this.options.anim),this.$form.editableform("render")},innerHide:function(){this.$form.hide(this.options.anim,e.proxy(function(){this.$element.show()},this))},destroy:function(){this.tip().remove()}}),e.fn.editableContainer.defaults=e.extend({},e.fn.editableContainer.defaults,{anim:"fast"})}(window.jQuery),function(e){var t=function(n){this.init("date",n,t.defaults);var r=e.fn.editableutils.sliceObj(this.options,["format"]);this.options.datepicker=e.extend({},t.defaults.datepicker,r,n.datepicker),this.options.viewformat||(this.options.viewformat=this.options.datepicker.format),this.options.datepicker.language=this.options.datepicker.language||"en",this.dpg=e.fn.datepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.datepicker.format),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat)};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{render:function(){t.superclass.render.call(this),this.$input.datepicker(this.options.datepicker),this.options.clear&&(this.$clear=e('<a href="#"></a>').html(this.options.clear).click(e.proxy(function(e){e.preventDefault(),e.stopPropagation(),this.clear()},this)))},value2html:function(e,n){var r=e?this.dpg.formatDate(e,this.parsedViewFormat,this.options.datepicker.language):"";t.superclass.value2html(r,n)},html2value:function(e){return e?this.dpg.parseDate(e,this.parsedViewFormat,this.options.datepicker.language):null},value2str:function(e){return e?this.dpg.formatDate(e,this.parsedFormat,this.options.datepicker.language):""},str2value:function(e){return e?this.dpg.parseDate(e,this.parsedFormat,this.options.datepicker.language):null},value2submit:function(e){return this.value2str(e)},value2input:function(e){this.$input.datepicker("update",e)},input2value:function(){return this.$input.data("datepicker").date},activate:function(){},clear:function(){this.$input.data("datepicker").date=null,this.$input.find(".active").removeClass("active")},autosubmit:function(){this.$input.on("changeDate",function(t){var n=e(this).closest("form");setTimeout(function(){n.submit()},200)})}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{tpl:"<div></div>",inputclass:"editable-date well",format:"yyyy-mm-dd",viewformat:null,datepicker:{weekStart:0,startView:0,autoclose:!1},clear:"&times; clear"}),e.fn.editabletypes.date=t}(window.jQuery),!function(e){function t(){return new Date(Date.UTC.apply(Date,arguments))}function n(){var e=new Date;return t(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate())}var r=function(t,n){var r=this;this.element=e(t),this.language=n.language||this.element.data("date-language")||"en",this.language=this.language in i?this.language:"en",this.format=s.parseFormat(n.format||this.element.data("date-format")||"mm/dd/yyyy"),this.isInline=!1,this.isInput=this.element.is("input"),this.component=this.element.is(".date")?this.element.find(".add-on"):!1,this.hasInput=this.component&&this.element.find("input").length,this.component&&this.component.length===0&&(this.component=!1),this.isInput?this.element.on({focus:e.proxy(this.show,this),keyup:e.proxy(this.update,this),keydown:e.proxy(this.keydown,this)}):this.component&&this.hasInput?(this.element.find("input").on({focus:e.proxy(this.show,this),keyup:e.proxy(this.update,this),keydown:e.proxy(this.keydown,this)}),this.component.on("click",e.proxy(this.show,this))):this.element.is("div")?this.isInline=!0:this.element.on("click",e.proxy(this.show,this)),this.picker=e(s.template).appendTo(this.isInline?this.element:"body").on({click:e.proxy(this.click,this),mousedown:e.proxy(this.mousedown,this)}),this.isInline?this.picker.addClass("datepicker-inline"):this.picker.addClass("dropdown-menu"),e(document).on("mousedown",function(t){e(t.target).closest(".datepicker").length==0&&r.hide()}),this.autoclose=!1,"autoclose"in n?this.autoclose=n.autoclose:"dateAutoclose"in this.element.data()&&(this.autoclose=this.element.data("date-autoclose")),this.keyboardNavigation=!0,"keyboardNavigation"in n?this.keyboardNavigation=n.keyboardNavigation:"dateKeyboardNavigation"in this.element.data()&&(this.keyboardNavigation=this.element.data("date-keyboard-navigation"));switch(n.startView||this.element.data("date-start-view")){case 2:case"decade":this.viewMode=this.startViewMode=2;break;case 1:case"year":this.viewMode=this.startViewMode=1;break;case 0:case"month":default:this.viewMode=this.startViewMode=0}this.todayBtn=n.todayBtn||this.element.data("date-today-btn")||!1,this.todayHighlight=n.todayHighlight||this.element.data("date-today-highlight")||!1,this.weekStart=(n.weekStart||this.element.data("date-weekstart")||i[this.language].weekStart||0)%7,this.weekEnd=(this.weekStart+6)%7,this.startDate=-Infinity,this.endDate=Infinity,this.setStartDate(n.startDate||this.element.data("date-startdate")),this.setEndDate(n.endDate||this.element.data("date-enddate")),this.fillDow(),this.fillMonths(),this.update(),this.showMode(),this.isInline&&this.show()};r.prototype={constructor:r,show:function(t){this.picker.show(),this.height=this.component?this.component.outerHeight():this.element.outerHeight(),this.update(),this.place(),e(window).on("resize",e.proxy(this.place,this)),t&&(t.stopPropagation(),t.preventDefault()),this.element.trigger({type:"show",date:this.date})},hide:function(t){if(this.isInline)return;this.picker.hide(),e(window).off("resize",this.place),this.viewMode=this.startViewMode,this.showMode(),this.isInput||e(document).off("mousedown",this.hide),t&&t.currentTarget.value&&this.setValue(),this.element.trigger({type:"hide",date:this.date})},getDate:function(){var e=this.getUTCDate();return new Date(e.getTime()+e.getTimezoneOffset()*6e4)},getUTCDate:function(){return this.date},setDate:function(e){this.setUTCDate(new Date(e.getTime()-e.getTimezoneOffset()*6e4))},setUTCDate:function(e){this.date=e,this.setValue()},setValue:function(){var e=this.getFormattedDate();this.isInput?this.element.prop("value",e):(this.component&&this.element.find("input").prop("value",e),this.element.data("date",e))},getFormattedDate:function(e){return e==undefined&&(e=this.format),s.formatDate(this.date,e,this.language)},setStartDate:function(e){this.startDate=e||-Infinity,this.startDate!==-Infinity&&(this.startDate=s.parseDate(this.startDate,this.format,this.language)),this.update(),this.updateNavArrows()},setEndDate:function(e){this.endDate=e||Infinity,this.endDate!==Infinity&&(this.endDate=s.parseDate(this.endDate,this.format,this.language)),this.update(),this.updateNavArrows()},place:function(){if(this.isInline)return;var t=parseInt(this.element.parents().filter(function(){return e(this).css("z-index")!="auto"}).first().css("z-index"))+10,n=this.component?this.component.offset():this.element.offset();this.picker.css({top:n.top+this.height,left:n.left,zIndex:t})},update:function(){var e,t=!1;arguments&&arguments.length&&(typeof arguments[0]=="string"||arguments[0]instanceof Date)?(e=arguments[0],t=!0):e=this.isInput?this.element.prop("value"):this.element.data("date")||this.element.find("input").prop("value"),this.date=s.parseDate(e,this.format,this.language),t&&this.setValue(),this.date<this.startDate?this.viewDate=new Date(this.startDate):this.date>this.endDate?this.viewDate=new Date(this.endDate):this.viewDate=new Date(this.date),this.fill()},fillDow:function(){var e=this.weekStart,t="<tr>";while(e<this.weekStart+7)t+='<th class="dow">'+i[this.language].daysMin[e++%7]+"</th>";t+="</tr>",this.picker.find(".datepicker-days thead").append(t)},fillMonths:function(){var e="",t=0;while(t<12)e+='<span class="month">'+i[this.language].monthsShort[t++]+"</span>";this.picker.find(".datepicker-months td").html(e)},fill:function(){var e=new Date(this.viewDate),n=e.getUTCFullYear(),r=e.getUTCMonth(),o=this.startDate!==-Infinity?this.startDate.getUTCFullYear():-Infinity,u=this.startDate!==-Infinity?this.startDate.getUTCMonth():-Infinity,a=this.endDate!==Infinity?this.endDate.getUTCFullYear():Infinity,f=this.endDate!==Infinity?this.endDate.getUTCMonth():Infinity,l=this.date&&this.date.valueOf(),c=new Date;this.picker.find(".datepicker-days thead th:eq(1)").text(i[this.language].months[r]+" "+n),this.picker.find("tfoot th.today").text(i[this.language].today).toggle(this.todayBtn!==!1),this.updateNavArrows(),this.fillMonths();var h=t(n,r-1,28,0,0,0,0),p=s.getDaysInMonth(h.getUTCFullYear(),h.getUTCMonth());h.setUTCDate(p),h.setUTCDate(p-(h.getUTCDay()-this.weekStart+7)%7);var d=new Date(h);d.setUTCDate(d.getUTCDate()+42),d=d.valueOf();var v=[],m;while(h.valueOf()<d){h.getUTCDay()==this.weekStart&&v.push("<tr>"),m="";if(h.getUTCFullYear()<n||h.getUTCFullYear()==n&&h.getUTCMonth()<r)m+=" old";else if(h.getUTCFullYear()>n||h.getUTCFullYear()==n&&h.getUTCMonth()>r)m+=" new";this.todayHighlight&&h.getUTCFullYear()==c.getFullYear()&&h.getUTCMonth()==c.getMonth()&&h.getUTCDate()==c.getDate()&&(m+=" today"),l&&h.valueOf()==l&&(m+=" active");if(h.valueOf()<this.startDate||h.valueOf()>this.endDate)m+=" disabled";v.push('<td class="day'+m+'">'+h.getUTCDate()+"</td>"),h.getUTCDay()==this.weekEnd&&v.push("</tr>"),h.setUTCDate(h.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(v.join(""));var g=this.date&&this.date.getUTCFullYear(),y=this.picker.find(".datepicker-months").find("th:eq(1)").text(n).end().find("span").removeClass("active");g&&g==n&&y.eq(this.date.getUTCMonth()).addClass("active"),(n<o||n>a)&&y.addClass("disabled"),n==o&&y.slice(0,u).addClass("disabled"),n==a&&y.slice(f+1).addClass("disabled"),v="",n=parseInt(n/10,10)*10;var b=this.picker.find(".datepicker-years").find("th:eq(1)").text(n+"-"+(n+9)).end().find("td");n-=1;for(var w=-1;w<11;w++)v+='<span class="year'+(w==-1||w==10?" old":"")+(g==n?" active":"")+(n<o||n>a?" disabled":"")+'">'+n+"</span>",n+=1;b.html(v)},updateNavArrows:function(){var e=new Date(this.viewDate),t=e.getUTCFullYear(),n=e.getUTCMonth();switch(this.viewMode){case 0:this.startDate!==-Infinity&&t<=this.startDate.getUTCFullYear()&&n<=this.startDate.getUTCMonth()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==Infinity&&t>=this.endDate.getUTCFullYear()&&n>=this.endDate.getUTCMonth()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 1:case 2:this.startDate!==-Infinity&&t<=this.startDate.getUTCFullYear()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==Infinity&&t>=this.endDate.getUTCFullYear()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"})}},click:function(n){n.stopPropagation(),n.preventDefault();var r=e(n.target).closest("span, td, th");if(r.length==1)switch(r[0].nodeName.toLowerCase()){case"th":switch(r[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var i=s.modes[this.viewMode].navStep*(r[0].className=="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,i);break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,i)}this.fill();break;case"today":var o=new Date;o=t(o.getFullYear(),o.getMonth(),o.getDate(),0,0,0),this.showMode(-2);var u=this.todayBtn=="linked"?null:"view";this._setDate(o,u)}break;case"span":if(!r.is(".disabled")){this.viewDate.setUTCDate(1);if(r.is(".month")){var a=r.parent().find("span").index(r);this.viewDate.setUTCMonth(a),this.element.trigger({type:"changeMonth",date:this.viewDate})}else{var f=parseInt(r.text(),10)||0;this.viewDate.setUTCFullYear(f),this.element.trigger({type:"changeYear",date:this.viewDate})}this.showMode(-1),this.fill()}break;case"td":if(r.is(".day")&&!r.is(".disabled")){var l=parseInt(r.text(),10)||1,f=this.viewDate.getUTCFullYear(),a=this.viewDate.getUTCMonth();r.is(".old")?a==0?(a=11,f-=1):a-=1:r.is(".new")&&(a==11?(a=0,f+=1):a+=1),this._setDate(t(f,a,l,0,0,0,0))}}},_setDate:function(e,t){if(!t||t=="date")this.date=e;if(!t||t=="view")this.viewDate=e;this.fill(),this.setValue(),this.element.trigger({type:"changeDate",date:this.date});var n;this.isInput?n=this.element:this.component&&(n=this.element.find("input")),n&&(n.change(),this.autoclose&&this.hide())},moveMonth:function(e,t){if(!t)return e;var n=new Date(e.valueOf()),r=n.getUTCDate(),i=n.getUTCMonth(),s=Math.abs(t),o,u;t=t>0?1:-1;if(s==1){u=t==-1?function(){return n.getUTCMonth()==i}:function(){return n.getUTCMonth()!=o},o=i+t,n.setUTCMonth(o);if(o<0||o>11)o=(o+12)%12}else{for(var a=0;a<s;a++)n=this.moveMonth(n,t);o=n.getUTCMonth(),n.setUTCDate(r),u=function(){return o!=n.getUTCMonth()}}while(u())n.setUTCDate(--r),n.setUTCMonth(o);return n},moveYear:function(e,t){return this.moveMonth(e,t*12)},dateWithinRange:function(e){return e>=this.startDate&&e<=this.endDate},keydown:function(e){if(this.picker.is(":not(:visible)")){e.keyCode==27&&this.show();return}var t=!1,n,r,i,s,o;switch(e.keyCode){case 27:this.hide(),e.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation)break;n=e.keyCode==37?-1:1,e.ctrlKey?(s=this.moveYear(this.date,n),o=this.moveYear(this.viewDate,n)):e.shiftKey?(s=this.moveMonth(this.date,n),o=this.moveMonth(this.viewDate,n)):(s=new Date(this.date),s.setUTCDate(this.date.getUTCDate()+n),o=new Date(this.viewDate),o.setUTCDate(this.viewDate.getUTCDate()+n)),this.dateWithinRange(s)&&(this.date=s,this.viewDate=o,this.setValue(),this.update(),e.preventDefault(),t=!0);break;case 38:case 40:if(!this.keyboardNavigation)break;n=e.keyCode==38?-1:1,e.ctrlKey?(s=this.moveYear(this.date,n),o=this.moveYear(this.viewDate,n)):e.shiftKey?(s=this.moveMonth(this.date,n),o=this.moveMonth(this.viewDate,n)):(s=new Date(this.date),s.setUTCDate(this.date.getUTCDate()+n*7),o=new Date(this.viewDate),o.setUTCDate(this.viewDate.getUTCDate()+n*7)),this.dateWithinRange(s)&&(this.date=s,this.viewDate=o,this.setValue(),this.update(),e.preventDefault(),t=!0);break;case 13:this.hide(),e.preventDefault();break;case 9:this.hide()}if(t){this.element.trigger({type:"changeDate",date:this.date});var u;this.isInput?u=this.element:this.component&&(u=this.element.find("input")),u&&u.change()}},showMode:function(e){e&&(this.viewMode=Math.max(0,Math.min(2,this.viewMode+e))),this.picker.find(">div").hide().filter(".datepicker-"+s.modes[this.viewMode].clsName).css("display","block"),this.updateNavArrows()}},e.fn.datepicker=function(t){var n=Array.apply(null,arguments);return n.shift(),this.each(function(){var i=e(this),s=i.data("datepicker"),o=typeof t=="object"&&t;s||i.data("datepicker",s=new r(this,e.extend({},e.fn.datepicker.defaults,o))),typeof t=="string"&&typeof s[t]=="function"&&s[t].apply(s,n)})},e.fn.datepicker.defaults={},e.fn.datepicker.Constructor=r;var i=e.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today"}},s={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(e){return e%4===0&&e%100!==0||e%400===0},getDaysInMonth:function(e,t){return[31,s.isLeapYear(e)?29:28,31,30,31,30,31,31,30,31,30,31][t]},validParts:/dd?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\r]+/g,parseFormat:function(e){var t=e.replace(this.validParts,"\0").split("\0"),n=e.match(this.validParts);if(!t||!t.length||!n||n.length==0)throw new Error("Invalid date format.");return{separators:t,parts:n}},parseDate:function(n,s,o){if(n instanceof Date)return n;if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(n)){var u=/([-+]\d+)([dmwy])/,a=n.match(/([-+]\d+)([dmwy])/g),f,l;n=new Date;for(var c=0;c<a.length;c++){f=u.exec(a[c]),l=parseInt(f[1]);switch(f[2]){case"d":n.setUTCDate(n.getUTCDate()+l);break;case"m":n=r.prototype.moveMonth.call(r.prototype,n,l);break;case"w":n.setUTCDate(n.getUTCDate()+l*7);break;case"y":n=r.prototype.moveYear.call(r.prototype,n,l)}}return t(n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate(),0,0,0)}var a=n&&n.match(this.nonpunctuation)||[],n=new Date,h={},p=["yyyy","yy","M","MM","m","mm","d","dd"],d={yyyy:function(e,t){return e.setUTCFullYear(t)},yy:function(e,t){return e.setUTCFullYear(2e3+t)},m:function(e,t){t-=1;while(t<0)t+=12;t%=12,e.setUTCMonth(t);while(e.getUTCMonth()!=t)e.setUTCDate(e.getUTCDate()-1);return e},d:function(e,t){return e.setUTCDate(t)}},v,m,f;d.M=d.MM=d.mm=d.m,d.dd=d.d,n=t(n.getFullYear(),n.getMonth(),n.getDate(),0,0,0);if(a.length==s.parts.length){for(var c=0,g=s.parts.length;c<g;c++){v=parseInt(a[c],10),f=s.parts[c];if(isNaN(v))switch(f){case"MM":m=e(i[o].months).filter(function(){var e=this.slice(0,a[c].length),t=a[c].slice(0,e.length);return e==t}),v=e.inArray(m[0],i[o].months)+1;break;case"M":m=e(i[o].monthsShort).filter(function(){var e=this.slice(0,a[c].length),t=a[c].slice(0,e.length);return e==t}),v=e.inArray(m[0],i[o].monthsShort)+1}h[f]=v}for(var c=0,y;c<p.length;c++)y=p[c],y in h&&d[y](n,h[y])}return n},formatDate:function(t,n,r){var s={d:t.getUTCDate(),m:t.getUTCMonth()+1,M:i[r].monthsShort[t.getUTCMonth()],MM:i[r].months[t.getUTCMonth()],yy:t.getUTCFullYear().toString().substring(2),yyyy:t.getUTCFullYear()};s.dd=(s.d<10?"0":"")+s.d,s.mm=(s.m<10?"0":"")+s.m;var t=[],o=e.extend([],n.separators);for(var u=0,a=n.parts.length;u<a;u++)o.length&&t.push(o.shift()),t.push(s[n.parts[u]]);return t.join("")},headTemplate:'<thead><tr><th class="prev"><i class="icon-arrow-left"/></th><th colspan="5" class="switch"></th><th class="next"><i class="icon-arrow-right"/></th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'};s.template='<div class="datepicker"><div class="datepicker-days"><table class=" table-condensed">'+s.headTemplate+"<tbody></tbody>"+s.footTemplate+"</table>"+"</div>"+'<div class="datepicker-months">'+'<table class="table-condensed">'+s.headTemplate+s.contTemplate+s.footTemplate+"</table>"+"</div>"+'<div class="datepicker-years">'+'<table class="table-condensed">'+s.headTemplate+s.contTemplate+s.footTemplate+"</table>"+"</div>"+"</div>",e.fn.datepicker.DPGlobal=s}(window.jQuery);
@@ -6,22 +6,21 @@ jQuery ($) ->
6
6
  EditableForm.prototype.saveWithUrlHook = (value) ->
7
7
  originalUrl = @options.url
8
8
  resource = @options.resource
9
- @options.url = (params) ->
9
+ @options.url = (params) =>
10
10
  # TODO: should not send when create new object
11
11
  if typeof originalUrl == 'function' # user's function
12
- originalUrl.call(@, params)
12
+ originalUrl.call(@options.scope, params)
13
13
  else # send ajax to server and return deferred object
14
14
  obj = {}
15
15
  data = {}
16
16
  obj[params.name] = params.value
17
17
  data[resource] = obj
18
- ajaxOptions = $.extend({
18
+ $.ajax($.extend({
19
19
  url : originalUrl
20
20
  data : data
21
21
  type : 'PUT' # TODO: should be 'POST' when create new object
22
22
  dataType: 'json'
23
- }, @options.ajaxOptions)
24
- $.ajax(ajaxOptions)
23
+ }, @options.ajaxOptions))
25
24
  @saveWithoutUrlHook(value)
26
25
  EditableForm.prototype.saveWithoutUrlHook = EditableForm.prototype.save
27
26
  EditableForm.prototype.save = EditableForm.prototype.saveWithUrlHook
@@ -1,12 +1,12 @@
1
- /*! X-editable - v1.1.1
1
+ /*! X-editable - v1.3.0
2
2
  * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3
3
  * http://github.com/vitalets/x-editable
4
4
  * Copyright (c) 2012 Vitaliy Potapov; Licensed MIT */
5
5
 
6
6
  /**
7
7
  Form with single input element, two buttons and two states: normal/loading.
8
- Applied as jQuery method to DIV tag (not to form tag!)
9
- Editableform is linked with one of input types, e.g. 'text' or 'select'.
8
+ Applied as jQuery method to DIV tag (not to form tag!). This is because form can be in loading state when spinner shown.
9
+ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
10
10
 
11
11
  @class editableform
12
12
  @uses text
@@ -14,9 +14,12 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
14
14
  **/
15
15
  (function ($) {
16
16
 
17
- var EditableForm = function (element, options) {
17
+ var EditableForm = function (div, options) {
18
18
  this.options = $.extend({}, $.fn.editableform.defaults, options);
19
- this.$element = $(element); //div, containing form. Not form tag! Not editable-element.
19
+ this.$div = $(div); //div, containing form. Not form tag! Not editable-element.
20
+ if(!this.options.scope) {
21
+ this.options.scope = this;
22
+ }
20
23
  this.initInput();
21
24
  };
22
25
 
@@ -26,9 +29,9 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
26
29
  var TypeConstructor, typeOptions;
27
30
 
28
31
  //create input of specified type
29
- if(typeof $.fn.editableform.types[this.options.type] === 'function') {
30
- TypeConstructor = $.fn.editableform.types[this.options.type];
31
- typeOptions = $.fn.editableform.utils.sliceObj(this.options, $.fn.editableform.utils.objectKeys(TypeConstructor.defaults));
32
+ if(typeof $.fn.editabletypes[this.options.type] === 'function') {
33
+ TypeConstructor = $.fn.editabletypes[this.options.type];
34
+ typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults));
32
35
  this.input = new TypeConstructor(typeOptions);
33
36
  } else {
34
37
  $.error('Unknown type: '+ this.options.type);
@@ -50,7 +53,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
50
53
  **/
51
54
  render: function() {
52
55
  this.$loading = $($.fn.editableform.loading);
53
- this.$element.empty().append(this.$loading);
56
+ this.$div.empty().append(this.$loading);
54
57
  this.showLoading();
55
58
 
56
59
  //init form template and buttons
@@ -66,7 +69,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
66
69
  @event rendering
67
70
  @param {Object} event event object
68
71
  **/
69
- this.$element.triggerHandler('rendering');
72
+ this.$div.triggerHandler('rendering');
70
73
 
71
74
  //render input
72
75
  $.when(this.input.render())
@@ -85,21 +88,23 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
85
88
  }
86
89
 
87
90
  //append form to container
88
- this.$element.append(this.$form);
89
-
91
+ this.$div.append(this.$form);
92
+
90
93
  //attach 'cancel' handler
91
94
  this.$form.find('.editable-cancel').click($.proxy(this.cancel, this));
92
- // this.$form.find('.editable-buttons button').eq(1).click($.proxy(this.cancel, this));
93
95
 
94
96
  if(this.input.error) {
95
97
  this.error(this.input.error);
96
98
  this.$form.find('.editable-submit').attr('disabled', true);
97
99
  this.input.$input.attr('disabled', true);
100
+ //prevent form from submitting
101
+ this.$form.submit(function(e){ e.preventDefault(); });
98
102
  } else {
99
103
  this.error(false);
100
104
  this.input.$input.removeAttr('disabled');
101
105
  this.$form.find('.editable-submit').removeAttr('disabled');
102
106
  this.input.value2input(this.value);
107
+ //attach submit handler
103
108
  this.$form.submit($.proxy(this.submit, this));
104
109
  }
105
110
 
@@ -108,7 +113,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
108
113
  @event rendered
109
114
  @param {Object} event event object
110
115
  **/
111
- this.$element.triggerHandler('rendered');
116
+ this.$div.triggerHandler('rendered');
112
117
 
113
118
  this.showForm();
114
119
  }, this));
@@ -119,7 +124,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
119
124
  @event cancel
120
125
  @param {Object} event event object
121
126
  **/
122
- this.$element.triggerHandler('cancel');
127
+ this.$div.triggerHandler('cancel');
123
128
  },
124
129
  showLoading: function() {
125
130
  var w;
@@ -138,16 +143,18 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
138
143
  this.$loading.show();
139
144
  },
140
145
 
141
- showForm: function() {
146
+ showForm: function(activate) {
142
147
  this.$loading.hide();
143
148
  this.$form.show();
144
- this.input.activate();
149
+ if(activate !== false) {
150
+ this.input.activate();
151
+ }
145
152
  /**
146
153
  Fired when form is shown
147
154
  @event show
148
155
  @param {Object} event event object
149
156
  **/
150
- this.$element.triggerHandler('show');
157
+ this.$div.triggerHandler('show');
151
158
  },
152
159
 
153
160
  error: function(msg) {
@@ -168,8 +175,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
168
175
  e.preventDefault();
169
176
 
170
177
  var error,
171
- newValue = this.input.input2value(), //get new value from input
172
- newValueStr;
178
+ newValue = this.input.input2value(); //get new value from input
173
179
 
174
180
  //validation
175
181
  if (error = this.validate(newValue)) {
@@ -178,25 +184,34 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
178
184
  return;
179
185
  }
180
186
 
181
- //value as string
182
- newValueStr = this.input.value2str(newValue);
183
-
184
- //if value not changed --> cancel
187
+ //if value not changed --> trigger 'nochange' event and return
185
188
  /*jslint eqeq: true*/
186
- if (newValueStr == this.input.value2str(this.value)) {
189
+ if (!this.options.savenochange && this.input.value2str(newValue) == this.input.value2str(this.value)) {
187
190
  /*jslint eqeq: false*/
188
- this.cancel();
191
+ /**
192
+ Fired when value not changed but form is submitted. Requires savenochange = false.
193
+ @event nochange
194
+ @param {Object} event event object
195
+ **/
196
+ this.$div.triggerHandler('nochange');
189
197
  return;
190
198
  }
191
199
 
192
200
  //sending data to server
193
- $.when(this.save(newValueStr))
201
+ $.when(this.save(newValue))
194
202
  .done($.proxy(function(response) {
195
203
  //run success callback
196
- var res = typeof this.options.success === 'function' ? this.options.success.call(this, response, newValue) : null;
204
+ var res = typeof this.options.success === 'function' ? this.options.success.call(this.options.scope, response, newValue) : null;
197
205
 
198
- //if success callback returns string --> show error
199
- if(res && typeof res === 'string') {
206
+ //if success callback returns false --> keep form open and do not activate input
207
+ if(res === false) {
208
+ this.error(false);
209
+ this.showForm(false);
210
+ return;
211
+ }
212
+
213
+ //if success callback returns string --> keep form open, show error and activate input
214
+ if(typeof res === 'string') {
200
215
  this.error(res);
201
216
  this.showForm();
202
217
  return;
@@ -223,7 +238,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
223
238
  if(params.newValue === 'username') {...}
224
239
  });
225
240
  **/
226
- this.$element.triggerHandler('save', {newValue: newValue, response: response});
241
+ this.$div.triggerHandler('save', {newValue: newValue, response: response});
227
242
  }, this))
228
243
  .fail($.proxy(function(xhr) {
229
244
  this.error(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!');
@@ -231,10 +246,16 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
231
246
  }, this));
232
247
  },
233
248
 
234
- save: function(value) {
235
- var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this) : this.options.pk,
249
+ save: function(newValue) {
250
+ //convert value for submitting to server
251
+ var submitValue = this.input.value2submit(newValue);
252
+
253
+ //try parse composite pk defined as json string in data-pk
254
+ this.options.pk = $.fn.editableutils.tryParseJson(this.options.pk, true);
255
+
256
+ var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this.options.scope) : this.options.pk,
236
257
  send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk)))),
237
- params, ajaxOptions;
258
+ params;
238
259
 
239
260
  if (send) { //send to server
240
261
  this.showLoading();
@@ -242,30 +263,28 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
242
263
  //standard params
243
264
  params = {
244
265
  name: this.options.name || '',
245
- value: value,
266
+ value: submitValue,
246
267
  pk: pk
247
268
  };
248
269
 
249
270
  //additional params
250
271
  if(typeof this.options.params === 'function') {
251
- $.extend(params, this.options.params.call(this, params));
272
+ params = this.options.params.call(this.options.scope, params);
252
273
  } else {
253
274
  //try parse json in single quotes (from data-params attribute)
254
- this.options.params = $.fn.editableform.utils.tryParseJson(this.options.params, true);
275
+ this.options.params = $.fn.editableutils.tryParseJson(this.options.params, true);
255
276
  $.extend(params, this.options.params);
256
277
  }
257
278
 
258
279
  if(typeof this.options.url === 'function') { //user's function
259
- return this.options.url.call(this, params);
260
- } else { //send ajax to server and return deferred object
261
- ajaxOptions = $.extend({
280
+ return this.options.url.call(this.options.scope, params);
281
+ } else {
282
+ //send ajax to server and return deferred object
283
+ return $.ajax($.extend({
262
284
  url : this.options.url,
263
285
  data : params,
264
- type : 'post',
265
- dataType: 'json'
266
- }, this.options.ajaxOptions);
267
-
268
- return $.ajax(ajaxOptions);
286
+ type : 'POST'
287
+ }, this.options.ajaxOptions));
269
288
  }
270
289
  }
271
290
  },
@@ -275,7 +294,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
275
294
  value = this.value;
276
295
  }
277
296
  if (typeof this.options.validate === 'function') {
278
- return this.options.validate.call(this, value);
297
+ return this.options.validate.call(this.options.scope, value);
279
298
  }
280
299
  },
281
300
 
@@ -361,10 +380,13 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
361
380
  **/
362
381
  url:null,
363
382
  /**
364
- Additional params for submit. Function can be used to calculate params dynamically
383
+ Additional params for submit. If defined as <code>object</code> - it is **appended** to original ajax data (pk, name and value).
384
+ If defined as <code>function</code> - returned object **overwrites** original ajax data.
365
385
  @example
366
386
  params: function(params) {
367
- return { a: 1 };
387
+ //originally params contain pk, name and value
388
+ params.a = 1;
389
+ return params;
368
390
  }
369
391
 
370
392
  @property params
@@ -382,7 +404,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
382
404
  name: null,
383
405
  /**
384
406
  Primary key of editable object (e.g. record id in database). For composite keys use object, e.g. <code>{id: 1, lang: 'en'}</code>.
385
- Can be calculated dinamically via function.
407
+ Can be calculated dynamically via function.
386
408
 
387
409
  @property pk
388
410
  @type string|object|function
@@ -423,7 +445,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
423
445
  validate: null,
424
446
  /**
425
447
  Success callback. Called when value successfully sent on server and **response status = 200**.
426
- Usefull to work with json response. For example, if your backend response can be <code>{success: true}</code>
448
+ Useful to work with json response. For example, if your backend response can be <code>{success: true}</code>
427
449
  or <code>{success: false, msg: "server error"}</code> you can check it inside this callback.
428
450
  If it returns **string** - means error occured and string is shown as error message.
429
451
  If it returns **object like** <code>{newValue: &lt;something&gt;}</code> - it overwrites value, submitted by user.
@@ -437,7 +459,7 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
437
459
  if(!response.success) return response.msg;
438
460
  }
439
461
  **/
440
- success: function(response, newValue) {},
462
+ success: null,
441
463
  /**
442
464
  Additional options for ajax request.
443
465
  List of values: http://api.jquery.com/jQuery.ajax
@@ -445,28 +467,44 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
445
467
  @property ajaxOptions
446
468
  @type object
447
469
  @default null
470
+ @since 1.1.1
448
471
  **/
449
472
  ajaxOptions: null,
450
473
  /**
451
- Wether to show buttons or not.
474
+ Whether to show buttons or not.
452
475
  Form without buttons can be auto-submitted by input or by onblur = 'submit'.
476
+ @example
477
+ ajaxOptions: {
478
+ method: 'PUT',
479
+ dataType: 'xml'
480
+ }
453
481
 
454
482
  @property showbuttons
455
483
  @type boolean
456
484
  @default true
485
+ @since 1.1.1
457
486
  **/
458
- showbuttons: true
459
-
460
- /*todo:
461
- Submit strategy. Can be <code>normal|never</code>
462
- <code>submitmode='never'</code> usefull for turning into classic form several inputs and submitting them together manually.
463
- Works pretty with <code>showbuttons=false</code>
487
+ showbuttons: true,
488
+ /**
489
+ Scope for callback methods (success, validate).
490
+ If <code>null</code> means editableform instance itself.
464
491
 
465
- @property submitmode
466
- @type string
467
- @default normal
468
- */
469
- // submitmode: 'normal'
492
+ @property scope
493
+ @type DOMElement|object
494
+ @default null
495
+ @since 1.2.0
496
+ @private
497
+ **/
498
+ scope: null,
499
+ /**
500
+ Whether to save or cancel value when it was not changed but form was submitted
501
+
502
+ @property savenochange
503
+ @type boolean
504
+ @default false
505
+ @since 1.2.0
506
+ **/
507
+ savenochange: false
470
508
  };
471
509
 
472
510
  /*
@@ -487,26 +525,21 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
487
525
  $.fn.editableform.buttons = '<button type="submit" class="editable-submit">ok</button>'+
488
526
  '<button type="button" class="editable-cancel">cancel</button>';
489
527
 
490
- //error class attahced to control-group
528
+ //error class attached to control-group
491
529
  $.fn.editableform.errorGroupClass = null;
492
530
 
493
- //error class attahced to editable-error-block
531
+ //error class attached to editable-error-block
494
532
  $.fn.editableform.errorBlockClass = 'editable-error';
495
-
496
- //input types
497
- $.fn.editableform.types = {};
498
- //utils
499
- $.fn.editableform.utils = {};
500
-
501
533
  }(window.jQuery));
502
534
  /**
503
535
  * EditableForm utilites
504
536
  */
505
537
  (function ($) {
506
- $.fn.editableform.utils = {
538
+ //utils
539
+ $.fn.editableutils = {
507
540
  /**
508
541
  * classic JS inheritance function
509
- */
542
+ */
510
543
  inherit: function (Child, Parent) {
511
544
  var F = function() { };
512
545
  F.prototype = Parent.prototype;
@@ -617,7 +650,14 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
617
650
  return k;
618
651
  }
619
652
 
620
- }
653
+ },
654
+
655
+ /**
656
+ method to escape html.
657
+ **/
658
+ escape: function(str) {
659
+ return $('<div>').text(str).html();
660
+ }
621
661
  };
622
662
  }(window.jQuery));
623
663
  /**
@@ -642,7 +682,7 @@ Applied as jQuery method.
642
682
  init: function(element, options) {
643
683
  this.$element = $(element);
644
684
  //todo: what is in priority: data or js?
645
- this.options = $.extend({}, $.fn.editableContainer.defaults, $.fn.editableform.utils.getConfigData(this.$element), options);
685
+ this.options = $.extend({}, $.fn.editableContainer.defaults, $.fn.editableutils.getConfigData(this.$element), options);
646
686
  this.splitOptions();
647
687
  this.initContainer();
648
688
 
@@ -697,12 +737,14 @@ Applied as jQuery method.
697
737
  },
698
738
 
699
739
  initForm: function() {
740
+ this.formOptions.scope = this.$element[0]; //set scope of form callbacks to element
700
741
  this.$form = $('<div>')
701
742
  .editableform(this.formOptions)
702
743
  .on({
703
744
  save: $.proxy(this.save, this),
704
- cancel: $.proxy(this.cancel, this),
705
- show: $.proxy(this.setPosition, this), //re-position container every time form is shown (after loading state)
745
+ cancel: $.proxy(function(){ this.hide('cancel'); }, this),
746
+ nochange: $.proxy(function(){ this.hide('nochange'); }, this),
747
+ show: $.proxy(this.setPosition, this), //re-position container every time form is shown (occurs each time after loading state)
706
748
  rendering: $.proxy(this.setPosition, this), //this allows to place container correctly when loading shown
707
749
  rendered: $.proxy(function(){
708
750
  /**
@@ -741,7 +783,7 @@ Applied as jQuery method.
741
783
  /**
742
784
  Shows container with form
743
785
  @method show()
744
- @param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true.
786
+ @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
745
787
  **/
746
788
  show: function (closeAll) {
747
789
  this.$element.addClass('editable-open');
@@ -765,8 +807,9 @@ Applied as jQuery method.
765
807
  /**
766
808
  Hides container with form
767
809
  @method hide()
810
+ @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|undefined (=manual)</code>
768
811
  **/
769
- hide: function() {
812
+ hide: function(reason) {
770
813
  if(!this.tip() || !this.tip().is(':visible') || !this.$element.hasClass('editable-open')) {
771
814
  return;
772
815
  }
@@ -776,9 +819,17 @@ Applied as jQuery method.
776
819
  Fired when container was hidden. It occurs on both save or cancel.
777
820
 
778
821
  @event hidden
779
- @param {Object} event event object
822
+ @param {object} event event object
823
+ @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|undefined (=manual)</code>
824
+ @example
825
+ $('#username').on('hidden', function(e, reason) {
826
+ if(reason === 'save' || reason === 'cancel') {
827
+ //auto-open next editable
828
+ $(this).closest('tr').next().find('.editable').editable('show');
829
+ }
830
+ });
780
831
  **/
781
- this.$element.triggerHandler('hidden');
832
+ this.$element.triggerHandler('hidden', reason);
782
833
  },
783
834
 
784
835
  /* internal hide method. To be overwritten in child classes */
@@ -789,7 +840,7 @@ Applied as jQuery method.
789
840
  /**
790
841
  Toggles container visibility (show / hide)
791
842
  @method toggle()
792
- @param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true.
843
+ @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
793
844
  **/
794
845
  toggle: function(closeAll) {
795
846
  if(this.tip && this.tip().is(':visible')) {
@@ -807,23 +858,8 @@ Applied as jQuery method.
807
858
  //tbd in child class
808
859
  },
809
860
 
810
- cancel: function() {
811
- if(this.options.autohide) {
812
- this.hide();
813
- }
814
- /**
815
- Fired when form was cancelled by user
816
-
817
- @event cancel
818
- @param {Object} event event object
819
- **/
820
- this.$element.triggerHandler('cancel');
821
- },
822
-
823
861
  save: function(e, params) {
824
- if(this.options.autohide) {
825
- this.hide();
826
- }
862
+ this.hide('save');
827
863
  /**
828
864
  Fired when new value was submitted. You can use <code>$(this).data('editableContainer')</code> inside handler to access to editableContainer instance
829
865
 
@@ -884,8 +920,8 @@ Applied as jQuery method.
884
920
  */
885
921
  closeOthers: function(element) {
886
922
  $('.editable-open').each(function(i, el){
887
- //do nothing with passed element
888
- if(el === element) {
923
+ //do nothing with passed element and it's children
924
+ if(el === element || $(el).find(element).length) {
889
925
  return;
890
926
  }
891
927
 
@@ -898,7 +934,7 @@ Applied as jQuery method.
898
934
  }
899
935
 
900
936
  if(ec.options.onblur === 'cancel') {
901
- $el.data('editableContainer').hide();
937
+ $el.data('editableContainer').hide('onblur');
902
938
  } else if(ec.options.onblur === 'submit') {
903
939
  $el.data('editableContainer').tip().find('form').submit();
904
940
  }
@@ -972,7 +1008,7 @@ Applied as jQuery method.
972
1008
  **/
973
1009
  placement: 'top',
974
1010
  /**
975
- Wether to hide container on save/cancel.
1011
+ Whether to hide container on save/cancel.
976
1012
 
977
1013
  @property autohide
978
1014
  @type boolean
@@ -987,6 +1023,7 @@ Applied as jQuery method.
987
1023
  @property onblur
988
1024
  @type string
989
1025
  @default 'cancel'
1026
+ @since 1.1.1
990
1027
  **/
991
1028
  onblur: 'cancel'
992
1029
  };
@@ -1015,7 +1052,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1015
1052
 
1016
1053
  var Editable = function (element, options) {
1017
1054
  this.$element = $(element);
1018
- this.options = $.extend({}, $.fn.editable.defaults, $.fn.editableform.utils.getConfigData(this.$element), options);
1055
+ this.options = $.extend({}, $.fn.editable.defaults, $.fn.editableutils.getConfigData(this.$element), options);
1019
1056
  this.init();
1020
1057
  };
1021
1058
 
@@ -1027,9 +1064,6 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1027
1064
  doAutotext,
1028
1065
  finalize;
1029
1066
 
1030
- //initialization flag
1031
- this.isInit = true;
1032
-
1033
1067
  //editableContainer must be defined
1034
1068
  if(!$.fn.editableContainer) {
1035
1069
  $.error('You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)');
@@ -1040,9 +1074,9 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1040
1074
  this.options.name = this.options.name || this.$element.attr('id');
1041
1075
 
1042
1076
  //create input of specified type. Input will be used for converting value, not in form
1043
- if(typeof $.fn.editableform.types[this.options.type] === 'function') {
1044
- TypeConstructor = $.fn.editableform.types[this.options.type];
1045
- this.typeOptions = $.fn.editableform.utils.sliceObj(this.options, $.fn.editableform.utils.objectKeys(TypeConstructor.defaults));
1077
+ if(typeof $.fn.editabletypes[this.options.type] === 'function') {
1078
+ TypeConstructor = $.fn.editabletypes[this.options.type];
1079
+ this.typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults));
1046
1080
  this.input = new TypeConstructor(this.typeOptions);
1047
1081
  } else {
1048
1082
  $.error('Unknown type: '+ this.options.type);
@@ -1054,13 +1088,20 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1054
1088
  this.value = this.input.html2value($.trim(this.$element.html()));
1055
1089
  isValueByText = true;
1056
1090
  } else {
1091
+ /*
1092
+ value can be string when received from 'data-value' attribute
1093
+ for complext objects value can be set as json string in data-value attribute,
1094
+ e.g. data-value="{city: 'Moscow', street: 'Lenina'}"
1095
+ */
1096
+ this.options.value = $.fn.editableutils.tryParseJson(this.options.value, true);
1057
1097
  if(typeof this.options.value === 'string') {
1058
- this.options.value = $.trim(this.options.value);
1098
+ this.value = this.input.str2value(this.options.value);
1099
+ } else {
1100
+ this.value = this.options.value;
1059
1101
  }
1060
- this.value = this.input.str2value(this.options.value);
1061
1102
  }
1062
1103
 
1063
- //add 'editable' class
1104
+ //add 'editable' class to every editable element
1064
1105
  this.$element.addClass('editable');
1065
1106
 
1066
1107
  //attach handler activating editable. In disabled mode it just prevent default action (useful for links)
@@ -1088,29 +1129,46 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1088
1129
  //if value was generated by text or value is empty, no sense to run autotext
1089
1130
  doAutotext = !isValueByText && this.value !== null && this.value !== undefined;
1090
1131
  doAutotext &= (this.options.autotext === 'always') || (this.options.autotext === 'auto' && !this.$element.text().length);
1091
- $.when(doAutotext ? this.input.value2html(this.value, this.$element) : true).then($.proxy(function() {
1132
+ $.when(doAutotext ? this.render() : true).then($.proxy(function() {
1092
1133
  if(this.options.disabled) {
1093
1134
  this.disable();
1094
1135
  } else {
1095
1136
  this.enable();
1096
1137
  }
1097
1138
  /**
1098
- Fired each time when element's text is rendered. Occurs on initialization and on each update of value.
1099
- Can be used for display customization.
1139
+ Fired when element was initialized by editable method.
1100
1140
 
1101
- @event render
1141
+ @event init
1102
1142
  @param {Object} event event object
1103
1143
  @param {Object} editable editable instance
1104
- @example
1105
- $('#action').on('render', function(e, editable) {
1106
- var colors = {0: "gray", 1: "green", 2: "blue", 3: "red"};
1107
- $(this).css("color", colors[editable.value]);
1108
- });
1144
+ @since 1.2.0
1109
1145
  **/
1110
- this.$element.triggerHandler('render', this);
1111
- this.isInit = false;
1146
+ this.$element.triggerHandler('init', this);
1112
1147
  }, this));
1113
1148
  },
1149
+
1150
+ /*
1151
+ Renders value into element's text.
1152
+ Can call custom display method from options.
1153
+ Can return deferred object.
1154
+ @method render()
1155
+ */
1156
+ render: function() {
1157
+ //do not display anything
1158
+ if(this.options.display === false) {
1159
+ return;
1160
+ }
1161
+ //if it is input with source, we pass callback in third param to be called when source is loaded
1162
+ if(this.input.options.hasOwnProperty('source')) {
1163
+ return this.input.value2html(this.value, this.$element[0], this.options.display);
1164
+ //if display method defined --> use it
1165
+ } else if(typeof this.options.display === 'function') {
1166
+ return this.options.display.call(this.$element[0], this.value);
1167
+ //else use input's original value2html() method
1168
+ } else {
1169
+ return this.input.value2html(this.value, this.$element[0]);
1170
+ }
1171
+ },
1114
1172
 
1115
1173
  /**
1116
1174
  Enables editable
@@ -1198,6 +1256,11 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1198
1256
  * set emptytext if element is empty (reverse: remove emptytext if needed)
1199
1257
  */
1200
1258
  handleEmpty: function () {
1259
+ //do not handle empty if we do not display anything
1260
+ if(this.options.display === false) {
1261
+ return;
1262
+ }
1263
+
1201
1264
  var emptyClass = 'editable-empty';
1202
1265
  //emptytext shown only for enabled
1203
1266
  if(!this.options.disabled) {
@@ -1218,7 +1281,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1218
1281
  /**
1219
1282
  Shows container with form
1220
1283
  @method show()
1221
- @param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true.
1284
+ @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
1222
1285
  **/
1223
1286
  show: function (closeAll) {
1224
1287
  if(this.options.disabled) {
@@ -1228,14 +1291,10 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1228
1291
  //init editableContainer: popover, tooltip, inline, etc..
1229
1292
  if(!this.container) {
1230
1293
  var containerOptions = $.extend({}, this.options, {
1231
- value: this.value,
1232
- autohide: false //element will take care to show/hide container
1294
+ value: this.value
1233
1295
  });
1234
1296
  this.$element.editableContainer(containerOptions);
1235
- this.$element.on({
1236
- save: $.proxy(this.save, this),
1237
- cancel: $.proxy(this.hide, this)
1238
- });
1297
+ this.$element.on("save.internal", $.proxy(this.save, this));
1239
1298
  this.container = this.$element.data('editableContainer');
1240
1299
  } else if(this.container.tip().is(':visible')) {
1241
1300
  return;
@@ -1253,17 +1312,12 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1253
1312
  if(this.container) {
1254
1313
  this.container.hide();
1255
1314
  }
1256
-
1257
- //return focus on element
1258
- if (this.options.enablefocus && this.options.toggle === 'click') {
1259
- this.$element.focus();
1260
- }
1261
1315
  },
1262
1316
 
1263
1317
  /**
1264
1318
  Toggles container visibility (show / hide)
1265
1319
  @method toggle()
1266
- @param {boolean} closeAll Wether to close all other editable containers when showing this one. Default true.
1320
+ @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
1267
1321
  **/
1268
1322
  toggle: function(closeAll) {
1269
1323
  if(this.container && this.container.tip().is(':visible')) {
@@ -1278,13 +1332,13 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1278
1332
  */
1279
1333
  save: function(e, params) {
1280
1334
  //if url is not user's function and value was not sent to server and value changed --> mark element with unsaved css.
1281
- if(typeof this.options.url !== 'function' && params.response === undefined && this.input.value2str(this.value) !== this.input.value2str(params.newValue)) {
1335
+ if(typeof this.options.url !== 'function' && this.options.display !== false && params.response === undefined && this.input.value2str(this.value) !== this.input.value2str(params.newValue)) {
1282
1336
  this.$element.addClass('editable-unsaved');
1283
1337
  } else {
1284
1338
  this.$element.removeClass('editable-unsaved');
1285
1339
  }
1286
1340
 
1287
- this.hide();
1341
+ // this.hide();
1288
1342
  this.setValue(params.newValue);
1289
1343
 
1290
1344
  /**
@@ -1319,7 +1373,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1319
1373
  Sets new value of editable
1320
1374
  @method setValue(value, convertStr)
1321
1375
  @param {mixed} value new value
1322
- @param {boolean} convertStr wether to convert value from string to internal format
1376
+ @param {boolean} convertStr whether to convert value from string to internal format
1323
1377
  **/
1324
1378
  setValue: function(value, convertStr) {
1325
1379
  if(convertStr) {
@@ -1330,10 +1384,9 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1330
1384
  if(this.container) {
1331
1385
  this.container.option('value', this.value);
1332
1386
  }
1333
- $.when(this.input.value2html(this.value, this.$element))
1387
+ $.when(this.render())
1334
1388
  .then($.proxy(function() {
1335
1389
  this.handleEmpty();
1336
- this.$element.triggerHandler('render', this);
1337
1390
  }, this));
1338
1391
  },
1339
1392
 
@@ -1345,7 +1398,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1345
1398
  if(this.container) {
1346
1399
  this.container.activate();
1347
1400
  }
1348
- }
1401
+ }
1349
1402
  };
1350
1403
 
1351
1404
  /* EDITABLE PLUGIN DEFINITION
@@ -1376,7 +1429,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1376
1429
  $('#username, #fullname').editable('validate');
1377
1430
  // possible result:
1378
1431
  {
1379
- username: "username is requied",
1432
+ username: "username is required",
1380
1433
  fullname: "fullname should be minimum 3 letters length"
1381
1434
  }
1382
1435
  **/
@@ -1405,21 +1458,23 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1405
1458
  this.each(function () {
1406
1459
  var $this = $(this), data = $this.data(datakey);
1407
1460
  if (data && data.value !== undefined && data.value !== null) {
1408
- result[data.options.name] = data.input.value2str(data.value);
1461
+ result[data.options.name] = data.input.value2submit(data.value);
1409
1462
  }
1410
1463
  });
1411
1464
  return result;
1412
1465
 
1413
1466
  /**
1414
- This method collects values from several editable elements and submit them all to server.
1415
- It is designed mainly for <a href="#newrecord">creating new records</a>.
1467
+ This method collects values from several editable elements and submit them all to server.
1468
+ Internally it runs client-side validation for all fields and submits only in case of success.
1469
+ See <a href="#newrecord">creating new records</a> for details.
1416
1470
 
1417
1471
  @method submit(options)
1418
1472
  @param {object} options
1419
1473
  @param {object} options.url url to submit data
1420
1474
  @param {object} options.data additional data to submit
1421
- @param {function} options.error(obj) error handler (called on both client-side and server-side validation errors)
1422
- @param {function} options.success(obj) success handler
1475
+ @param {object} options.ajaxOptions additional ajax options
1476
+ @param {function} options.error(obj) error handler
1477
+ @param {function} options.success(obj,config) success handler
1423
1478
  @returns {Object} jQuery object
1424
1479
  **/
1425
1480
  case 'submit': //collects value, validate and submit to server for creating new record
@@ -1428,35 +1483,32 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1428
1483
  errors = this.editable('validate'),
1429
1484
  values;
1430
1485
 
1431
- if(typeof config.error !== 'function') {
1432
- config.error = function() {};
1433
- }
1434
-
1435
1486
  if($.isEmptyObject(errors)) {
1436
1487
  values = this.editable('getValue');
1437
1488
  if(config.data) {
1438
1489
  $.extend(values, config.data);
1439
- }
1440
- $.ajax({
1441
- type: 'POST',
1490
+ }
1491
+
1492
+ $.ajax($.extend({
1442
1493
  url: config.url,
1443
1494
  data: values,
1444
- dataType: 'json'
1445
- }).success(function(response) {
1446
- if(typeof response === 'object' && response.id) {
1447
- $elems.editable('option', 'pk', response.id);
1448
- $elems.removeClass('editable-unsaved');
1449
- if(typeof config.success === 'function') {
1450
- config.success.apply($elems, arguments);
1451
- }
1452
- } else { //server-side validation error
1495
+ type: 'POST'
1496
+ }, config.ajaxOptions))
1497
+ .success(function(response) {
1498
+ //successful response 200 OK
1499
+ if(typeof config.success === 'function') {
1500
+ config.success.call($elems, response, config);
1501
+ }
1502
+ })
1503
+ .error(function(){ //ajax error
1504
+ if(typeof config.error === 'function') {
1453
1505
  config.error.apply($elems, arguments);
1454
1506
  }
1455
- }).error(function(){ //ajax error
1456
- config.error.apply($elems, arguments);
1457
1507
  });
1458
1508
  } else { //client-side validation error
1459
- config.error.call($elems, {errors: errors});
1509
+ if(typeof config.error === 'function') {
1510
+ config.error.call($elems, errors);
1511
+ }
1460
1512
  }
1461
1513
  return this;
1462
1514
  }
@@ -1512,7 +1564,6 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1512
1564
  @default 'click'
1513
1565
  **/
1514
1566
  toggle: 'click',
1515
-
1516
1567
  /**
1517
1568
  Text shown when element is empty.
1518
1569
 
@@ -1522,7 +1573,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1522
1573
  **/
1523
1574
  emptytext: 'Empty',
1524
1575
  /**
1525
- Allows to automatically set element's text based on it's value. Can be <code>auto|always|never</code>. Usefull for select and date.
1576
+ Allows to automatically set element's text based on it's value. Can be <code>auto|always|never</code>. Useful for select and date.
1526
1577
  For example, if dropdown list is <code>{1: 'a', 2: 'b'}</code> and element's value set to <code>1</code>, it's html will be automatically set to <code>'a'</code>.
1527
1578
  <code>auto</code> - text will be automatically set only if element is empty.
1528
1579
  <code>always|never</code> - always(never) try to set element's text.
@@ -1533,38 +1584,52 @@ Makes editable any HTML element on the page. Applied as jQuery method.
1533
1584
  **/
1534
1585
  autotext: 'auto',
1535
1586
  /**
1536
- Wether to return focus on element after form is closed.
1537
- This allows fully keyboard input.
1538
-
1539
- @property enablefocus
1540
- @type boolean
1541
- @default false
1542
- **/
1543
- enablefocus: false,
1544
- /**
1545
1587
  Initial value of input. Taken from <code>data-value</code> or element's text.
1546
1588
 
1547
1589
  @property value
1548
1590
  @type mixed
1549
1591
  @default element's text
1550
1592
  **/
1551
- value: null
1593
+ value: null,
1594
+ /**
1595
+ Callback to perform custom displaying of value in element's text.
1596
+ If <code>null</code>, default input's value2html() will be called.
1597
+ If <code>false</code>, no displaying methods will be called, element's text will no change.
1598
+ Runs under element's scope.
1599
+ Second parameter __sourceData__ is passed for inputs with source (select, checklist).
1600
+
1601
+ @property display
1602
+ @type function|boolean
1603
+ @default null
1604
+ @since 1.2.0
1605
+ @example
1606
+ display: function(value, sourceData) {
1607
+ var escapedValue = $('<div>').text(value).html();
1608
+ $(this).html('<b>'+escapedValue+'</b>');
1609
+ }
1610
+ **/
1611
+ display: null
1552
1612
  };
1553
1613
 
1554
- }(window.jQuery));
1614
+ }(window.jQuery));
1615
+
1555
1616
  /**
1556
- Abstract editable input class.
1557
- To create your own input you should inherit from this class.
1617
+ AbstractInput - base class for all editable inputs.
1618
+ It defines interface to be implemented by any input type.
1619
+ To create your own input you can inherit from this class.
1558
1620
 
1559
- @class abstract
1621
+ @class abstractinput
1560
1622
  **/
1561
1623
  (function ($) {
1562
1624
 
1563
- var Abstract = function () { };
1625
+ //types
1626
+ $.fn.editabletypes = {};
1627
+
1628
+ var AbstractInput = function () { };
1564
1629
 
1565
- Abstract.prototype = {
1630
+ AbstractInput.prototype = {
1566
1631
  /**
1567
- Iinitializes input
1632
+ Initializes input
1568
1633
 
1569
1634
  @method init()
1570
1635
  **/
@@ -1577,7 +1642,7 @@ To create your own input you should inherit from this class.
1577
1642
  },
1578
1643
 
1579
1644
  /**
1580
- Renders input. Can return jQuery deferred object.
1645
+ Renders input from tpl. Can return jQuery deferred object.
1581
1646
 
1582
1647
  @method render()
1583
1648
  **/
@@ -1600,8 +1665,7 @@ To create your own input you should inherit from this class.
1600
1665
  @param {DOMElement} element
1601
1666
  **/
1602
1667
  value2html: function(value, element) {
1603
- var html = this.escape(value);
1604
- $(element).html(html);
1668
+ $(element).text(value);
1605
1669
  },
1606
1670
 
1607
1671
  /**
@@ -1616,7 +1680,7 @@ To create your own input you should inherit from this class.
1616
1680
  },
1617
1681
 
1618
1682
  /**
1619
- Converts value to string (for submiting to server)
1683
+ Converts value to string (for internal compare). For submitting to server used value2submit().
1620
1684
 
1621
1685
  @method value2str(value)
1622
1686
  @param {mixed} value
@@ -1637,6 +1701,17 @@ To create your own input you should inherit from this class.
1637
1701
  return str;
1638
1702
  },
1639
1703
 
1704
+ /**
1705
+ Converts value for submitting to server
1706
+
1707
+ @method value2submit(value)
1708
+ @param {mixed} value
1709
+ @returns {mixed}
1710
+ **/
1711
+ value2submit: function(value) {
1712
+ return value;
1713
+ },
1714
+
1640
1715
  /**
1641
1716
  Sets value of input.
1642
1717
 
@@ -1668,11 +1743,11 @@ To create your own input you should inherit from this class.
1668
1743
  },
1669
1744
 
1670
1745
  /**
1671
- Creares input.
1746
+ Creates input.
1672
1747
 
1673
1748
  @method clear()
1674
1749
  **/
1675
- clear: function() {
1750
+ clear: function() {
1676
1751
  this.$input.val(null);
1677
1752
  },
1678
1753
 
@@ -1684,14 +1759,14 @@ To create your own input you should inherit from this class.
1684
1759
  },
1685
1760
 
1686
1761
  /**
1687
- attach handler to automatically submit form when value changed (usefull when buttons not shown)
1762
+ attach handler to automatically submit form when value changed (useful when buttons not shown)
1688
1763
  **/
1689
1764
  autosubmit: function() {
1690
1765
 
1691
1766
  }
1692
1767
  };
1693
1768
 
1694
- Abstract.defaults = {
1769
+ AbstractInput.defaults = {
1695
1770
  /**
1696
1771
  HTML template of input. Normally you should not change it.
1697
1772
 
@@ -1702,12 +1777,12 @@ To create your own input you should inherit from this class.
1702
1777
  tpl: '',
1703
1778
  /**
1704
1779
  CSS class automatically applied to input
1705
-
1780
+
1706
1781
  @property inputclass
1707
1782
  @type string
1708
- @default span2
1783
+ @default input-medium
1709
1784
  **/
1710
- inputclass: 'span2',
1785
+ inputclass: 'input-medium',
1711
1786
  /**
1712
1787
  Name attribute of input
1713
1788
 
@@ -1718,14 +1793,15 @@ To create your own input you should inherit from this class.
1718
1793
  name: null
1719
1794
  };
1720
1795
 
1721
- $.extend($.fn.editableform.types, {abstract: Abstract});
1796
+ $.extend($.fn.editabletypes, {abstractinput: AbstractInput});
1722
1797
 
1723
- }(window.jQuery));
1798
+ }(window.jQuery));
1799
+
1724
1800
  /**
1725
1801
  List - abstract class for inputs that have source option loaded from js array or via ajax
1726
1802
 
1727
1803
  @class list
1728
- @extends abstract
1804
+ @extends abstractinput
1729
1805
  **/
1730
1806
  (function ($) {
1731
1807
 
@@ -1733,7 +1809,7 @@ List - abstract class for inputs that have source option loaded from js array or
1733
1809
 
1734
1810
  };
1735
1811
 
1736
- $.fn.editableform.utils.inherit(List, $.fn.editableform.types.abstract);
1812
+ $.fn.editableutils.inherit(List, $.fn.editabletypes.abstractinput);
1737
1813
 
1738
1814
  $.extend(List.prototype, {
1739
1815
  render: function () {
@@ -1757,13 +1833,18 @@ List - abstract class for inputs that have source option loaded from js array or
1757
1833
  return null; //can't set value by text
1758
1834
  },
1759
1835
 
1760
- value2html: function (value, element) {
1836
+ value2html: function (value, element, display) {
1761
1837
  var deferred = $.Deferred();
1762
1838
  this.onSourceReady(function () {
1763
- this.value2htmlFinal(value, element);
1839
+ if(typeof display === 'function') {
1840
+ //custom display method
1841
+ display.call(element, value, this.sourceData);
1842
+ } else {
1843
+ this.value2htmlFinal(value, element);
1844
+ }
1764
1845
  deferred.resolve();
1765
1846
  }, function () {
1766
- List.superclass.value2html(this.options.sourceError, element);
1847
+ //do nothing with element
1767
1848
  deferred.resolve();
1768
1849
  });
1769
1850
 
@@ -1781,7 +1862,7 @@ List - abstract class for inputs that have source option loaded from js array or
1781
1862
 
1782
1863
  // try parse json in single quotes (for double quotes jquery does automatically)
1783
1864
  try {
1784
- this.options.source = $.fn.editableform.utils.tryParseJson(this.options.source, false);
1865
+ this.options.source = $.fn.editableutils.tryParseJson(this.options.source, false);
1785
1866
  } catch (e) {
1786
1867
  error.call(this);
1787
1868
  return;
@@ -1789,32 +1870,35 @@ List - abstract class for inputs that have source option loaded from js array or
1789
1870
 
1790
1871
  //loading from url
1791
1872
  if (typeof this.options.source === 'string') {
1792
- var cacheID = this.options.source + (this.options.name ? '-' + this.options.name : ''),
1793
- cache;
1873
+ //try to get from cache
1874
+ if(this.options.sourceCache) {
1875
+ var cacheID = this.options.source + (this.options.name ? '-' + this.options.name : ''),
1876
+ cache;
1794
1877
 
1795
- if (!$(document).data(cacheID)) {
1796
- $(document).data(cacheID, {});
1797
- }
1798
- cache = $(document).data(cacheID);
1878
+ if (!$(document).data(cacheID)) {
1879
+ $(document).data(cacheID, {});
1880
+ }
1881
+ cache = $(document).data(cacheID);
1799
1882
 
1800
- //check for cached data
1801
- if (cache.loading === false && cache.sourceData) { //take source from cache
1802
- this.sourceData = cache.sourceData;
1803
- success.call(this);
1804
- return;
1805
- } else if (cache.loading === true) { //cache is loading, put callback in stack to be called later
1806
- cache.callbacks.push($.proxy(function () {
1883
+ //check for cached data
1884
+ if (cache.loading === false && cache.sourceData) { //take source from cache
1807
1885
  this.sourceData = cache.sourceData;
1808
1886
  success.call(this);
1809
- }, this));
1887
+ return;
1888
+ } else if (cache.loading === true) { //cache is loading, put callback in stack to be called later
1889
+ cache.callbacks.push($.proxy(function () {
1890
+ this.sourceData = cache.sourceData;
1891
+ success.call(this);
1892
+ }, this));
1810
1893
 
1811
- //also collecting error callbacks
1812
- cache.err_callbacks.push($.proxy(error, this));
1813
- return;
1814
- } else { //no cache yet, activate it
1815
- cache.loading = true;
1816
- cache.callbacks = [];
1817
- cache.err_callbacks = [];
1894
+ //also collecting error callbacks
1895
+ cache.err_callbacks.push($.proxy(error, this));
1896
+ return;
1897
+ } else { //no cache yet, activate it
1898
+ cache.loading = true;
1899
+ cache.callbacks = [];
1900
+ cache.err_callbacks = [];
1901
+ }
1818
1902
  }
1819
1903
 
1820
1904
  //loading sourceData from server
@@ -1825,23 +1909,32 @@ List - abstract class for inputs that have source option loaded from js array or
1825
1909
  data: this.options.name ? {name: this.options.name} : {},
1826
1910
  dataType: 'json',
1827
1911
  success: $.proxy(function (data) {
1828
- cache.loading = false;
1912
+ if(cache) {
1913
+ cache.loading = false;
1914
+ }
1829
1915
  this.sourceData = this.makeArray(data);
1830
1916
  if($.isArray(this.sourceData)) {
1831
1917
  this.doPrepend();
1832
- //store result in cache
1833
- cache.sourceData = this.sourceData;
1834
1918
  success.call(this);
1835
- $.each(cache.callbacks, function () { this.call(); }); //run success callbacks for other fields
1919
+ if(cache) {
1920
+ //store result in cache
1921
+ cache.sourceData = this.sourceData;
1922
+ $.each(cache.callbacks, function () { this.call(); }); //run success callbacks for other fields
1923
+ }
1836
1924
  } else {
1837
1925
  error.call(this);
1838
- $.each(cache.err_callbacks, function () { this.call(); }); //run error callbacks for other fields
1926
+ if(cache) {
1927
+ $.each(cache.err_callbacks, function () { this.call(); }); //run error callbacks for other fields
1928
+ }
1839
1929
  }
1840
1930
  }, this),
1841
1931
  error: $.proxy(function () {
1842
- cache.loading = false;
1843
1932
  error.call(this);
1844
- $.each(cache.err_callbacks, function () { this.call(); }); //run error callbacks for other fields
1933
+ if(cache) {
1934
+ cache.loading = false;
1935
+ //run error callbacks for other fields
1936
+ $.each(cache.err_callbacks, function () { this.call(); });
1937
+ }
1845
1938
  }, this)
1846
1939
  });
1847
1940
  } else { //options as json/array
@@ -1862,7 +1955,7 @@ List - abstract class for inputs that have source option loaded from js array or
1862
1955
 
1863
1956
  if(!$.isArray(this.prependData)) {
1864
1957
  //try parse json in single quotes
1865
- this.options.prepend = $.fn.editableform.utils.tryParseJson(this.options.prepend, true);
1958
+ this.options.prepend = $.fn.editableutils.tryParseJson(this.options.prepend, true);
1866
1959
  if (typeof this.options.prepend === 'string') {
1867
1960
  this.options.prepend = {'': this.options.prepend};
1868
1961
  }
@@ -1943,19 +2036,20 @@ List - abstract class for inputs that have source option loaded from js array or
1943
2036
 
1944
2037
  });
1945
2038
 
1946
- List.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
2039
+ List.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
1947
2040
  /**
1948
2041
  Source data for list. If string - considered ajax url to load items. Otherwise should be an array.
1949
2042
  Array format is: <code>[{value: 1, text: "text"}, {...}]</code><br>
1950
2043
  For compability it also supports format <code>{value1: "text1", value2: "text2" ...}</code> but it does not guarantee elements order.
1951
-
2044
+ If source is **string**, results will be cached for fields with the same source and name. See also <code>sourceCache</code> option.
2045
+
1952
2046
  @property source
1953
2047
  @type string|array|object
1954
2048
  @default null
1955
2049
  **/
1956
2050
  source:null,
1957
2051
  /**
1958
- Data automatically prepended to the begining of dropdown list.
2052
+ Data automatically prepended to the beginning of dropdown list.
1959
2053
 
1960
2054
  @property prepend
1961
2055
  @type string|array|object
@@ -1969,17 +2063,27 @@ List - abstract class for inputs that have source option loaded from js array or
1969
2063
  @type string
1970
2064
  @default Error when loading list
1971
2065
  **/
1972
- sourceError: 'Error when loading list'
2066
+ sourceError: 'Error when loading list',
2067
+ /**
2068
+ if <code>true</code> and source is **string url** - results will be cached for fields with the same source and name.
2069
+ Usefull for editable grids.
2070
+
2071
+ @property sourceCache
2072
+ @type boolean
2073
+ @default true
2074
+ @since 1.2.0
2075
+ **/
2076
+ sourceCache: true
1973
2077
  });
1974
2078
 
1975
- $.fn.editableform.types.list = List;
2079
+ $.fn.editabletypes.list = List;
1976
2080
 
1977
2081
  }(window.jQuery));
1978
2082
  /**
1979
2083
  Text input
1980
2084
 
1981
2085
  @class text
1982
- @extends abstract
2086
+ @extends abstractinput
1983
2087
  @final
1984
2088
  @example
1985
2089
  <a href="#" id="username" data-type="text" data-pk="1">awesome</a>
@@ -1997,18 +2101,18 @@ $(function(){
1997
2101
  this.init('text', options, Text.defaults);
1998
2102
  };
1999
2103
 
2000
- $.fn.editableform.utils.inherit(Text, $.fn.editableform.types.abstract);
2104
+ $.fn.editableutils.inherit(Text, $.fn.editabletypes.abstractinput);
2001
2105
 
2002
2106
  $.extend(Text.prototype, {
2003
2107
  activate: function() {
2004
2108
  if(this.$input.is(':visible')) {
2005
2109
  this.$input.focus();
2006
- $.fn.editableform.utils.setCursorPosition(this.$input.get(0), this.$input.val().length);
2110
+ $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length);
2007
2111
  }
2008
2112
  }
2009
2113
  });
2010
2114
 
2011
- Text.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
2115
+ Text.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
2012
2116
  /**
2013
2117
  @property tpl
2014
2118
  @default <input type="text">
@@ -2024,7 +2128,7 @@ $(function(){
2024
2128
  placeholder: null
2025
2129
  });
2026
2130
 
2027
- $.fn.editableform.types.text = Text;
2131
+ $.fn.editabletypes.text = Text;
2028
2132
 
2029
2133
  }(window.jQuery));
2030
2134
 
@@ -2032,7 +2136,7 @@ $(function(){
2032
2136
  Textarea input
2033
2137
 
2034
2138
  @class textarea
2035
- @extends abstract
2139
+ @extends abstractinput
2036
2140
  @final
2037
2141
  @example
2038
2142
  <a href="#" id="comments" data-type="textarea" data-pk="1">awesome comment!</a>
@@ -2051,7 +2155,7 @@ $(function(){
2051
2155
  this.init('textarea', options, Textarea.defaults);
2052
2156
  };
2053
2157
 
2054
- $.fn.editableform.utils.inherit(Textarea, $.fn.editableform.types.abstract);
2158
+ $.fn.editableutils.inherit(Textarea, $.fn.editabletypes.abstractinput);
2055
2159
 
2056
2160
  $.extend(Textarea.prototype, {
2057
2161
  render: function () {
@@ -2090,13 +2194,13 @@ $(function(){
2090
2194
 
2091
2195
  activate: function() {
2092
2196
  if(this.$input.is(':visible')) {
2093
- $.fn.editableform.utils.setCursorPosition(this.$input.get(0), this.$input.val().length);
2197
+ $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length);
2094
2198
  this.$input.focus();
2095
2199
  }
2096
2200
  }
2097
2201
  });
2098
2202
 
2099
- Textarea.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
2203
+ Textarea.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
2100
2204
  /**
2101
2205
  @property tpl
2102
2206
  @default <textarea></textarea>
@@ -2104,9 +2208,9 @@ $(function(){
2104
2208
  tpl:'<textarea></textarea>',
2105
2209
  /**
2106
2210
  @property inputclass
2107
- @default span3
2211
+ @default input-large
2108
2212
  **/
2109
- inputclass:'span3',
2213
+ inputclass: 'input-large',
2110
2214
  /**
2111
2215
  Placeholder attribute of input. Shown when input is empty.
2112
2216
 
@@ -2114,12 +2218,13 @@ $(function(){
2114
2218
  @type string
2115
2219
  @default null
2116
2220
  **/
2117
- placeholder: null
2221
+ placeholder: null
2118
2222
  });
2119
2223
 
2120
- $.fn.editableform.types.textarea = Textarea;
2224
+ $.fn.editabletypes.textarea = Textarea;
2121
2225
 
2122
- }(window.jQuery));
2226
+ }(window.jQuery));
2227
+
2123
2228
  /**
2124
2229
  Select (dropdown)
2125
2230
 
@@ -2148,7 +2253,7 @@ $(function(){
2148
2253
  this.init('select', options, Select.defaults);
2149
2254
  };
2150
2255
 
2151
- $.fn.editableform.utils.inherit(Select, $.fn.editableform.types.list);
2256
+ $.fn.editableutils.inherit(Select, $.fn.editabletypes.list);
2152
2257
 
2153
2258
  $.extend(Select.prototype, {
2154
2259
  renderList: function() {
@@ -2159,6 +2264,13 @@ $(function(){
2159
2264
  for(var i=0; i<this.sourceData.length; i++) {
2160
2265
  this.$input.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text));
2161
2266
  }
2267
+
2268
+ //enter submit
2269
+ this.$input.on('keydown.editable', function (e) {
2270
+ if (e.which === 13) {
2271
+ $(this).closest('form').submit();
2272
+ }
2273
+ });
2162
2274
  },
2163
2275
 
2164
2276
  value2htmlFinal: function(value, element) {
@@ -2170,13 +2282,13 @@ $(function(){
2170
2282
  },
2171
2283
 
2172
2284
  autosubmit: function() {
2173
- this.$input.on('change', function(){
2285
+ this.$input.off('keydown.editable').on('change.editable', function(){
2174
2286
  $(this).closest('form').submit();
2175
2287
  });
2176
2288
  }
2177
2289
  });
2178
2290
 
2179
- Select.defaults = $.extend({}, $.fn.editableform.types.list.defaults, {
2291
+ Select.defaults = $.extend({}, $.fn.editabletypes.list.defaults, {
2180
2292
  /**
2181
2293
  @property tpl
2182
2294
  @default <select></select>
@@ -2184,7 +2296,7 @@ $(function(){
2184
2296
  tpl:'<select></select>'
2185
2297
  });
2186
2298
 
2187
- $.fn.editableform.types.select = Select;
2299
+ $.fn.editabletypes.select = Select;
2188
2300
 
2189
2301
  }(window.jQuery));
2190
2302
  /**
@@ -2216,7 +2328,7 @@ $(function(){
2216
2328
  this.init('checklist', options, Checklist.defaults);
2217
2329
  };
2218
2330
 
2219
- $.fn.editableform.utils.inherit(Checklist, $.fn.editableform.types.list);
2331
+ $.fn.editableutils.inherit(Checklist, $.fn.editabletypes.list);
2220
2332
 
2221
2333
  $.extend(Checklist.prototype, {
2222
2334
  renderList: function() {
@@ -2238,10 +2350,8 @@ $(function(){
2238
2350
  },
2239
2351
 
2240
2352
  value2str: function(value) {
2241
- return $.isArray(value) ? value.join($.trim(this.options.separator)) : '';
2242
- //it is also possible to sent as array
2243
- //return value;
2244
- },
2353
+ return $.isArray(value) ? value.sort().join($.trim(this.options.separator)) : '';
2354
+ },
2245
2355
 
2246
2356
  //parse separated string
2247
2357
  str2value: function(str) {
@@ -2284,19 +2394,18 @@ $(function(){
2284
2394
 
2285
2395
  //collect text of checked boxes
2286
2396
  value2htmlFinal: function(value, element) {
2287
- var selected = [], item, i, html = '';
2288
- if($.isArray(value) && value.length <= this.options.limit) {
2289
- for(i=0; i<value.length; i++){
2290
- item = this.itemByVal(value[i]);
2291
- if(item) {
2292
- selected.push($('<div>').text(item.text).html());
2293
- }
2294
- }
2295
- html = selected.join(this.options.viewseparator);
2296
- } else {
2297
- html = this.options.limitText.replace('{checked}', $.isArray(value) ? value.length : 0).replace('{count}', this.sourceData.length);
2397
+ var html = [],
2398
+ /*jslint eqeq: true*/
2399
+ checked = $.grep(this.sourceData, function(o){
2400
+ return $.grep(value, function(v){ return v == o.value; }).length;
2401
+ });
2402
+ /*jslint eqeq: false*/
2403
+ if(checked.length) {
2404
+ $.each(checked, function(i, v) { html.push($.fn.editableutils.escape(v.text)); });
2405
+ $(element).html(html.join('<br>'));
2406
+ } else {
2407
+ $(element).empty();
2298
2408
  }
2299
- $(element).html(html);
2300
2409
  },
2301
2410
 
2302
2411
  activate: function() {
@@ -2312,7 +2421,7 @@ $(function(){
2312
2421
  }
2313
2422
  });
2314
2423
 
2315
- Checklist.defaults = $.extend({}, $.fn.editableform.types.list.defaults, {
2424
+ Checklist.defaults = $.extend({}, $.fn.editabletypes.list.defaults, {
2316
2425
  /**
2317
2426
  @property tpl
2318
2427
  @default <div></div>
@@ -2322,50 +2431,212 @@ $(function(){
2322
2431
  /**
2323
2432
  @property inputclass
2324
2433
  @type string
2325
- @default span2 editable-checklist
2434
+ @default editable-checklist
2326
2435
  **/
2327
- inputclass: 'span2 editable-checklist',
2436
+ inputclass: 'editable-checklist',
2328
2437
 
2329
2438
  /**
2330
- Separator of values in string when sending to server
2439
+ Separator of values when reading from 'data-value' string
2331
2440
 
2332
2441
  @property separator
2333
2442
  @type string
2334
2443
  @default ', '
2335
2444
  **/
2336
- separator: ',',
2337
- /**
2338
- Separator of text when display as element content.
2445
+ separator: ','
2446
+ });
2339
2447
 
2340
- @property viewseparator
2341
- @type string
2342
- @default '<br>'
2343
- **/
2344
- viewseparator: '<br>',
2345
- /**
2346
- Maximum number of items shown as element content.
2347
- If checked more items - <code>limitText</code> will be shown.
2448
+ $.fn.editabletypes.checklist = Checklist;
2348
2449
 
2349
- @property limit
2350
- @type integer
2351
- @default 4
2352
- **/
2353
- limit: 4,
2354
- /**
2355
- Text shown when count of checked items is greater than <code>limit</code> parameter.
2356
- You can use <code>{checked}</code> and <code>{count}</code> placeholders.
2450
+ }(window.jQuery));
2451
+
2452
+ /**
2453
+ HTML5 input types.
2454
+ Following types are supported:
2455
+
2456
+ * password
2457
+ * email
2458
+ * url
2459
+ * tel
2460
+ * number
2461
+ * range
2462
+
2463
+ Learn more about html5 inputs:
2464
+ http://www.w3.org/wiki/HTML5_form_additions
2465
+ To check browser compatibility please see:
2466
+ https://developer.mozilla.org/en-US/docs/HTML/Element/Input
2467
+
2468
+ @class html5types
2469
+ @extends text
2470
+ @final
2471
+ @since 1.3.0
2472
+ @example
2473
+ <a href="#" id="email" data-type="email" data-pk="1">admin@example.com</a>
2474
+ <script>
2475
+ $(function(){
2476
+ $('#email').editable({
2477
+ url: '/post',
2478
+ title: 'Enter email'
2479
+ });
2480
+ });
2481
+ </script>
2482
+ **/
2357
2483
 
2358
- @property limitText
2359
- @type string
2360
- @default 'Selected {checked} of {count}'
2361
- **/
2362
- limitText: 'Selected {checked} of {count}'
2484
+ /**
2485
+ @property tpl
2486
+ @default depends on type
2487
+ **/
2488
+
2489
+ /*
2490
+ Password
2491
+ */
2492
+ (function ($) {
2493
+ var Password = function (options) {
2494
+ this.init('password', options, Password.defaults);
2495
+ };
2496
+ $.fn.editableutils.inherit(Password, $.fn.editabletypes.text);
2497
+ $.extend(Password.prototype, {
2498
+ //do not display password, show '[hidden]' instead
2499
+ value2html: function(value, element) {
2500
+ if(value) {
2501
+ $(element).text('[hidden]');
2502
+ } else {
2503
+ $(element).empty();
2504
+ }
2505
+ },
2506
+ //as password not displayed, should not set value by html
2507
+ html2value: function(html) {
2508
+ return null;
2509
+ }
2510
+ });
2511
+ Password.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
2512
+ tpl: '<input type="password">'
2513
+ });
2514
+ $.fn.editabletypes.password = Password;
2515
+ }(window.jQuery));
2516
+
2517
+
2518
+ /*
2519
+ Email
2520
+ */
2521
+ (function ($) {
2522
+ var Email = function (options) {
2523
+ this.init('email', options, Email.defaults);
2524
+ };
2525
+ $.fn.editableutils.inherit(Email, $.fn.editabletypes.text);
2526
+ Email.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
2527
+ tpl: '<input type="email">'
2363
2528
  });
2529
+ $.fn.editabletypes.email = Email;
2530
+ }(window.jQuery));
2364
2531
 
2365
- $.fn.editableform.types.checklist = Checklist;
2366
2532
 
2533
+ /*
2534
+ Url
2535
+ */
2536
+ (function ($) {
2537
+ var Url = function (options) {
2538
+ this.init('url', options, Url.defaults);
2539
+ };
2540
+ $.fn.editableutils.inherit(Url, $.fn.editabletypes.text);
2541
+ Url.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
2542
+ tpl: '<input type="url">'
2543
+ });
2544
+ $.fn.editabletypes.url = Url;
2367
2545
  }(window.jQuery));
2368
-
2546
+
2547
+
2548
+ /*
2549
+ Tel
2550
+ */
2551
+ (function ($) {
2552
+ var Tel = function (options) {
2553
+ this.init('tel', options, Tel.defaults);
2554
+ };
2555
+ $.fn.editableutils.inherit(Tel, $.fn.editabletypes.text);
2556
+ Tel.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
2557
+ tpl: '<input type="tel">'
2558
+ });
2559
+ $.fn.editabletypes.tel = Tel;
2560
+ }(window.jQuery));
2561
+
2562
+
2563
+ /*
2564
+ Number
2565
+ */
2566
+ (function ($) {
2567
+ var NumberInput = function (options) {
2568
+ this.init('number', options, NumberInput.defaults);
2569
+ };
2570
+ $.fn.editableutils.inherit(NumberInput, $.fn.editabletypes.text);
2571
+ $.extend(NumberInput.prototype, {
2572
+ render: function () {
2573
+ NumberInput.superclass.render.call(this);
2574
+
2575
+ if (this.options.min !== null) {
2576
+ this.$input.attr('min', this.options.min);
2577
+ }
2578
+
2579
+ if (this.options.max !== null) {
2580
+ this.$input.attr('max', this.options.max);
2581
+ }
2582
+
2583
+ if (this.options.step !== null) {
2584
+ this.$input.attr('step', this.options.step);
2585
+ }
2586
+ }
2587
+ });
2588
+ NumberInput.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
2589
+ tpl: '<input type="number">',
2590
+ inputclass: 'input-mini',
2591
+ min: null,
2592
+ max: null,
2593
+ step: null
2594
+ });
2595
+ $.fn.editabletypes.number = NumberInput;
2596
+ }(window.jQuery));
2597
+
2598
+
2599
+ /*
2600
+ Range (inherit from number)
2601
+ */
2602
+ (function ($) {
2603
+ var Range = function (options) {
2604
+ this.init('range', options, Range.defaults);
2605
+ };
2606
+ $.fn.editableutils.inherit(Range, $.fn.editabletypes.number);
2607
+ $.extend(Range.prototype, {
2608
+ render: function () {
2609
+ this.$input = $(this.options.tpl);
2610
+ var $slider = this.$input.filter('input');
2611
+ if(this.options.inputclass) {
2612
+ $slider.addClass(this.options.inputclass);
2613
+ }
2614
+ if (this.options.min !== null) {
2615
+ $slider.attr('min', this.options.min);
2616
+ }
2617
+
2618
+ if (this.options.max !== null) {
2619
+ $slider.attr('max', this.options.max);
2620
+ }
2621
+
2622
+ if (this.options.step !== null) {
2623
+ $slider.attr('step', this.options.step);
2624
+ }
2625
+
2626
+ $slider.on('input', function(){
2627
+ $(this).siblings('output').text($(this).val());
2628
+ });
2629
+ },
2630
+ activate: function() {
2631
+ this.$input.filter('input').focus();
2632
+ }
2633
+ });
2634
+ Range.defaults = $.extend({}, $.fn.editabletypes.number.defaults, {
2635
+ tpl: '<input type="range"><output style="width: 30px; display: inline-block"></output>',
2636
+ inputclass: 'input-medium'
2637
+ });
2638
+ $.fn.editabletypes.range = Range;
2639
+ }(window.jQuery));
2369
2640
  /*
2370
2641
  Editableform based on Twitter Bootstrap
2371
2642
  */
@@ -2397,13 +2668,14 @@ Editableform based on Twitter Bootstrap
2397
2668
  //extend methods
2398
2669
  $.extend($.fn.editableContainer.Constructor.prototype, {
2399
2670
  containerName: 'popover',
2400
- innerCss: '.popover-content p',
2671
+ //for compatibility with bootstrap <= 2.2.1 (content inserted into <p> instead of directly .popover-content)
2672
+ innerCss: $($.fn.popover.defaults.template).find('p').length ? '.popover-content p' : '.popover-content',
2401
2673
 
2402
2674
  initContainer: function(){
2403
2675
  $.extend(this.containerOptions, {
2404
2676
  trigger: 'manual',
2405
2677
  selector: false,
2406
- content: 'dfgh'
2678
+ content: ' '
2407
2679
  });
2408
2680
  this.call(this.containerOptions);
2409
2681
  },
@@ -2484,7 +2756,7 @@ Description and examples: http://vitalets.github.com/bootstrap-datepicker.
2484
2756
  For localization you can include js file from here: https://github.com/eternicode/bootstrap-datepicker/tree/master/js/locales
2485
2757
 
2486
2758
  @class date
2487
- @extends abstract
2759
+ @extends abstractinput
2488
2760
  @final
2489
2761
  @example
2490
2762
  <a href="#" id="dob" data-type="date" data-pk="1" data-url="/post" data-original-title="Select date">15/05/1984</a>
@@ -2507,7 +2779,7 @@ $(function(){
2507
2779
  this.init('date', options, Date.defaults);
2508
2780
 
2509
2781
  //set popular options directly from settings or data-* attributes
2510
- var directOptions = $.fn.editableform.utils.sliceObj(this.options, ['format']);
2782
+ var directOptions = $.fn.editableutils.sliceObj(this.options, ['format']);
2511
2783
 
2512
2784
  //overriding datepicker config (as by default jQuery extend() is not recursive)
2513
2785
  this.options.datepicker = $.extend({}, Date.defaults.datepicker, directOptions, options.datepicker);
@@ -2528,7 +2800,7 @@ $(function(){
2528
2800
  this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat);
2529
2801
  };
2530
2802
 
2531
- $.fn.editableform.utils.inherit(Date, $.fn.editableform.types.abstract);
2803
+ $.fn.editableutils.inherit(Date, $.fn.editabletypes.abstractinput);
2532
2804
 
2533
2805
  $.extend(Date.prototype, {
2534
2806
  render: function () {
@@ -2559,7 +2831,11 @@ $(function(){
2559
2831
 
2560
2832
  str2value: function(str) {
2561
2833
  return str ? this.dpg.parseDate(str, this.parsedFormat, this.options.datepicker.language) : null;
2562
- },
2834
+ },
2835
+
2836
+ value2submit: function(value) {
2837
+ return this.value2str(value);
2838
+ },
2563
2839
 
2564
2840
  value2input: function(value) {
2565
2841
  this.$input.datepicker('update', value);
@@ -2588,7 +2864,7 @@ $(function(){
2588
2864
 
2589
2865
  });
2590
2866
 
2591
- Date.defaults = $.extend({}, $.fn.editableform.types.abstract.defaults, {
2867
+ Date.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
2592
2868
  /**
2593
2869
  @property tpl
2594
2870
  @default <div></div>
@@ -2645,7 +2921,7 @@ $(function(){
2645
2921
  clear: '&times; clear'
2646
2922
  });
2647
2923
 
2648
- $.fn.editableform.types.date = Date;
2924
+ $.fn.editabletypes.date = Date;
2649
2925
 
2650
2926
  }(window.jQuery));
2651
2927
 
@@ -2937,13 +3213,13 @@ $(function(){
2937
3213
  startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,
2938
3214
  endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,
2939
3215
  endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
2940
- currentDate = this.date.valueOf(),
3216
+ currentDate = this.date && this.date.valueOf(),
2941
3217
  today = new Date();
2942
3218
  this.picker.find('.datepicker-days thead th:eq(1)')
2943
3219
  .text(dates[this.language].months[month]+' '+year);
2944
3220
  this.picker.find('tfoot th.today')
2945
3221
  .text(dates[this.language].today)
2946
- .toggle(this.todayBtn);
3222
+ .toggle(this.todayBtn !== false);
2947
3223
  this.updateNavArrows();
2948
3224
  this.fillMonths();
2949
3225
  var prevMonth = UTCDate(year, month-1, 28,0,0,0,0),
@@ -2972,7 +3248,7 @@ $(function(){
2972
3248
  prevMonth.getUTCDate() == today.getDate()) {
2973
3249
  clsName += ' today';
2974
3250
  }
2975
- if (prevMonth.valueOf() == currentDate) {
3251
+ if (currentDate && prevMonth.valueOf() == currentDate) {
2976
3252
  clsName += ' active';
2977
3253
  }
2978
3254
  if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate) {
@@ -2985,14 +3261,14 @@ $(function(){
2985
3261
  prevMonth.setUTCDate(prevMonth.getUTCDate()+1);
2986
3262
  }
2987
3263
  this.picker.find('.datepicker-days tbody').empty().append(html.join(''));
2988
- var currentYear = this.date.getUTCFullYear();
3264
+ var currentYear = this.date && this.date.getUTCFullYear();
2989
3265
 
2990
3266
  var months = this.picker.find('.datepicker-months')
2991
3267
  .find('th:eq(1)')
2992
3268
  .text(year)
2993
3269
  .end()
2994
3270
  .find('span').removeClass('active');
2995
- if (currentYear == year) {
3271
+ if (currentYear && currentYear == year) {
2996
3272
  months.eq(this.date.getUTCMonth()).addClass('active');
2997
3273
  }
2998
3274
  if (year < startYear || year > endYear) {
@@ -3080,10 +3356,7 @@ $(function(){
3080
3356
  break;
3081
3357
  case 'today':
3082
3358
  var date = new Date();
3083
- date.setUTCHours(0);
3084
- date.setUTCMinutes(0);
3085
- date.setUTCSeconds(0);
3086
- date.setUTCMilliseconds(0);
3359
+ date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
3087
3360
 
3088
3361
  this.showMode(-2);
3089
3362
  var which = this.todayBtn == 'linked' ? null : 'view';
@@ -3306,7 +3579,17 @@ $(function(){
3306
3579
  if (dir) {
3307
3580
  this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir));
3308
3581
  }
3309
- this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
3582
+ /*
3583
+ vitalets: fixing bug of very special conditions:
3584
+ jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover.
3585
+ Method show() does not set display css correctly and datepicker is not shown.
3586
+ Changed to .css('display', 'block') solve the problem.
3587
+ See https://github.com/vitalets/x-editable/issues/37
3588
+
3589
+ In jquery 1.7.2+ everything works fine.
3590
+ */
3591
+ //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show();
3592
+ this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block');
3310
3593
  this.updateNavArrows();
3311
3594
  }
3312
3595
  };
@@ -3424,7 +3707,7 @@ $(function(){
3424
3707
  val, filtered, part;
3425
3708
  setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];
3426
3709
  setters_map['dd'] = setters_map['d'];
3427
- date = UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0);
3710
+ date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);
3428
3711
  if (parts.length == format.parts.length) {
3429
3712
  for (var i=0, cnt = format.parts.length; i < cnt; i++) {
3430
3713
  val = parseInt(parts[i], 10);