populate-me 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +655 -0
- data/Rakefile +14 -0
- data/example/config.ru +100 -0
- data/lib/populate_me.rb +2 -0
- data/lib/populate_me/admin.rb +157 -0
- data/lib/populate_me/admin/__assets__/css/asmselect.css +63 -0
- data/lib/populate_me/admin/__assets__/css/jquery-ui.min.css +6 -0
- data/lib/populate_me/admin/__assets__/css/main.css +244 -0
- data/lib/populate_me/admin/__assets__/img/help/children.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/create.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/delete.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/edit.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/form.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/list.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/login.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/logout.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/menu.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/overview.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/save.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/sort.png +0 -0
- data/lib/populate_me/admin/__assets__/img/help/sublist.png +0 -0
- data/lib/populate_me/admin/__assets__/js/asmselect.js +412 -0
- data/lib/populate_me/admin/__assets__/js/columnav.js +87 -0
- data/lib/populate_me/admin/__assets__/js/jquery-ui.min.js +7 -0
- data/lib/populate_me/admin/__assets__/js/main.js +388 -0
- data/lib/populate_me/admin/__assets__/js/mustache.js +578 -0
- data/lib/populate_me/admin/__assets__/js/sortable.js +2 -0
- data/lib/populate_me/admin/views/help.erb +94 -0
- data/lib/populate_me/admin/views/page.erb +189 -0
- data/lib/populate_me/api.rb +124 -0
- data/lib/populate_me/attachment.rb +186 -0
- data/lib/populate_me/document.rb +192 -0
- data/lib/populate_me/document_mixins/admin_adapter.rb +149 -0
- data/lib/populate_me/document_mixins/callbacks.rb +125 -0
- data/lib/populate_me/document_mixins/outcasting.rb +83 -0
- data/lib/populate_me/document_mixins/persistence.rb +95 -0
- data/lib/populate_me/document_mixins/schema.rb +198 -0
- data/lib/populate_me/document_mixins/typecasting.rb +70 -0
- data/lib/populate_me/document_mixins/validation.rb +44 -0
- data/lib/populate_me/file_system_attachment.rb +40 -0
- data/lib/populate_me/grid_fs_attachment.rb +103 -0
- data/lib/populate_me/mongo.rb +160 -0
- data/lib/populate_me/s3_attachment.rb +120 -0
- data/lib/populate_me/variation.rb +38 -0
- data/lib/populate_me/version.rb +4 -0
- data/populate-me.gemspec +34 -0
- data/test/helper.rb +37 -0
- data/test/test_admin.rb +183 -0
- data/test/test_api.rb +246 -0
- data/test/test_attachment.rb +167 -0
- data/test/test_document.rb +128 -0
- data/test/test_document_admin_adapter.rb +221 -0
- data/test/test_document_callbacks.rb +151 -0
- data/test/test_document_outcasting.rb +247 -0
- data/test/test_document_persistence.rb +83 -0
- data/test/test_document_schema.rb +280 -0
- data/test/test_document_typecasting.rb +128 -0
- data/test/test_grid_fs_attachment.rb +239 -0
- data/test/test_mongo.rb +324 -0
- data/test/test_s3_attachment.rb +281 -0
- data/test/test_variation.rb +91 -0
- data/test/test_version.rb +11 -0
- metadata +294 -0
@@ -0,0 +1,7 @@
|
|
1
|
+
/*! jQuery UI - v1.12.1 - 2018-02-23
|
2
|
+
* http://jqueryui.com
|
3
|
+
* Includes: widget.js, data.js, scroll-parent.js, widgets/sortable.js, widgets/mouse.js
|
4
|
+
* Copyright jQuery Foundation and other contributors; Licensed MIT */
|
5
|
+
|
6
|
+
(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){t.ui=t.ui||{},t.ui.version="1.12.1";var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},l=e.split(".")[0];e=e.split(".")[1];var h=l+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][h.toLowerCase()]=function(e){return!!t.data(e,h)},t[l]=t[l]||{},n=t[l][e],o=t[l][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:l,widgetName:e,widgetFullName:h}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var s,n,o=i.call(arguments,1),a=0,r=o.length;r>a;a++)for(s in o[a])n=o[a][s],o[a].hasOwnProperty(s)&&void 0!==n&&(e[s]=t.isPlainObject(n)?t.isPlainObject(e[s])?t.widget.extend({},e[s],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,s){var n=s.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=i.call(arguments,1),l=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(l=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(l=i&&i.jquery?l.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):l=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new s(o,this))})),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(i,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var l=s.match(/^([\w:-]*)\s*(.*)$/),h=l[1]+o.eventNamespace,c=l[2];c?n.on(h,c,r):i.on(h,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var s=!1;t(document).on("mouseup",function(){s=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!s){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,n=1===e.which,o="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return n&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),s=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,s=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.widget("ui.sortable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(t,e,i){return t>=e&&e+i>t},_isFloating:function(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))},_create:function(){this.containerCache={},this._addClass("ui-sortable"),this.refresh(),this.offset=this.element.offset(),this._mouseInit(),this._setHandleClassName(),this.ready=!0},_setOption:function(t,e){this._super(t,e),"handle"===t&&this._setHandleClassName()},_setHandleClassName:function(){var e=this;this._removeClass(this.element.find(".ui-sortable-handle"),"ui-sortable-handle"),t.each(this.items,function(){e._addClass(this.instance.options.handle?this.item.find(this.instance.options.handle):this.item,"ui-sortable-handle")})},_destroy:function(){this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_mouseCapture:function(e,i){var s=null,n=!1,o=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,o.widgetName+"-item")===o?(s=t(this),!1):void 0}),t.data(e.target,o.widgetName+"-item")===o&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,o,a=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,a.cursorAt&&this._adjustOffsetFromHelper(a.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),a.containment&&this._setContainment(),a.cursor&&"auto"!==a.cursor&&(o=this.document.find("body"),this.storedCursor=o.css("cursor"),o.css("cursor",a.cursor),this.storedStylesheet=t("<style>*{ cursor: "+a.cursor+" !important; }</style>").appendTo(o)),a.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",a.opacity)),a.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",a.zIndex)),this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this._addClass(this.helper,"ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,o,a=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY<a.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+a.scrollSpeed:e.pageY-this.overflowOffset.top<a.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-a.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-e.pageX<a.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+a.scrollSpeed:e.pageX-this.overflowOffset.left<a.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-a.scrollSpeed)):(e.pageY-this.document.scrollTop()<a.scrollSensitivity?r=this.document.scrollTop(this.document.scrollTop()-a.scrollSpeed):this.window.height()-(e.pageY-this.document.scrollTop())<a.scrollSensitivity&&(r=this.document.scrollTop(this.document.scrollTop()+a.scrollSpeed)),e.pageX-this.document.scrollLeft()<a.scrollSensitivity?r=this.document.scrollLeft(this.document.scrollLeft()-a.scrollSpeed):this.window.width()-(e.pageX-this.document.scrollLeft())<a.scrollSensitivity&&(r=this.document.scrollLeft(this.document.scrollLeft()+a.scrollSpeed))),r!==!1&&t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],o=this._intersectsWithPointer(s),o&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===o?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===o?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),o=this.options.axis,a={};o&&"x"!==o||(a.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollLeft)),o&&"y"!==o||(a.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(a,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp(new t.Event("mouseup",{target:null})),"original"===this.options.helper?(this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,l=r+t.height,h=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+h>r&&l>s+h,d="y"===this.options.axis||e+c>o&&a>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>o&&a>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&l>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var e,i,s="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),n="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),o=s&&n;return o?(e=this._getDragVerticalDirection(),i=this._getDragHorizontalDirection(),this.floating?"right"===i||"down"===e?2:1:e&&("down"===e?2:1)):!1},_intersectsWithSides:function(t){var e=this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),s=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?"right"===n&&i||"left"===n&&!i:s&&("down"===s&&e||"up"===s&&!e)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){function i(){r.push(this)}var s,n,o,a,r=[],l=[],h=this._connectWith();if(h&&e)for(s=h.length-1;s>=0;s--)for(o=t(h[s],this.document[0]),n=o.length-1;n>=0;n--)a=t.data(o[n],this.widgetFullName),a&&a!==this&&!a.options.disabled&&l.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(l.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=l.length-1;s>=0;s--)l[s][0].each(i);return t(r)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,o,a,r,l,h,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i],this.document[0]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&(u.push([t.isFunction(o.options.items)?o.options.items.call(o.element[0],e,{item:this.currentItem}):t(o.options.items,o.element),o]),this.containers.push(o));for(i=u.length-1;i>=0;i--)for(a=u[i][1],r=u[i][0],s=0,h=r.length;h>s;s++)l=t(r[s]),l.data(this.widgetName+"-item",a),c.push({item:l,instance:a,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.floating=this.items.length?"x"===this.options.axis||this._isFloating(this.items[0].item):!1,this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,o;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),o=n.offset(),s.left=o.left,s.top=o.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)o=this.containers[i].element.offset(),this.containers[i].containerCache.left=o.left,this.containers[i].containerCache.top=o.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]);return e._addClass(n,"ui-sortable-placeholder",i||e.currentItem[0].className)._removeClass(n,"ui-sortable-helper"),"tbody"===s?e._createTrPlaceholder(e.currentItem.find("tr").eq(0),t("<tr>",e.document[0]).appendTo(n)):"tr"===s?e._createTrPlaceholder(e.currentItem,n):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_createTrPlaceholder:function(e,i){var s=this;e.children().each(function(){t("<td> </td>",s.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(i)})},_contactContainers:function(e){var i,s,n,o,a,r,l,h,c,u,d=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!t.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(d&&t.contains(this.containers[i].element[0],d.element[0]))continue;d=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",e,this._uiHash(this)),this.containers[i].containerCache.over=0);if(d)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(n=1e4,o=null,c=d.floating||this._isFloating(this.currentItem),a=c?"left":"top",r=c?"width":"height",u=c?"pageX":"pageY",s=this.items.length-1;s>=0;s--)t.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(l=this.items[s].item.offset()[a],h=!1,e[u]-l>this.items[s][r]/2&&(h=!0),n>Math.abs(e[u]-l)&&(n=Math.abs(e[u]-l),o=this.items[s],this.direction=h?"up":"down"));if(!o&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;o?this._rearrange(e,o,null,!0):this._rearrange(e,null,this.containers[p].element,!0),this._trigger("change",e,this._uiHash()),this.containers[p]._trigger("change",e,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===this.document[0].body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,"document"===n.containment?this.document.width():this.window.width()-this.helperProportions.width-this.margins.left,("document"===n.containment?this.document.height()||document.body.parentNode.scrollHeight:this.window.height()||this.document[0].body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}
|
7
|
+
},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,l=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.left<this.containment[0]&&(o=this.containment[0]+this.offset.click.left),e.pageY-this.offset.click.top<this.containment[1]&&(a=this.containment[1]+this.offset.click.top),e.pageX-this.offset.click.left>this.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():l?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():l?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}})});
|
@@ -0,0 +1,388 @@
|
|
1
|
+
// Namespace
|
2
|
+
var PopulateMe = {};
|
3
|
+
|
4
|
+
// Returns a Mustache template from either
|
5
|
+
// the dom element itself, or the id of the dom element.
|
6
|
+
PopulateMe.init_template = function(obj_or_id) {
|
7
|
+
var obj = (typeof obj_or_id == 'object') ? obj_or_id : $(obj_or_id);
|
8
|
+
var template = obj.html();
|
9
|
+
Mustache.parse(template);
|
10
|
+
return template;
|
11
|
+
};
|
12
|
+
|
13
|
+
// Output a legible version of the size in bytes.
|
14
|
+
// 1024 => "1KB"
|
15
|
+
// 2097152 => "2MB"
|
16
|
+
PopulateMe.display_file_size = function(size) {
|
17
|
+
var unit = 'B';
|
18
|
+
if (size>1024) {
|
19
|
+
size = size / 1024;
|
20
|
+
unit = 'KB';
|
21
|
+
}
|
22
|
+
if (size>1024) {
|
23
|
+
size = size / 1024;
|
24
|
+
unit = 'MB';
|
25
|
+
}
|
26
|
+
if (size>1024) {
|
27
|
+
size = size / 1024;
|
28
|
+
unit = 'GB';
|
29
|
+
}
|
30
|
+
return size+unit;
|
31
|
+
};
|
32
|
+
|
33
|
+
// Add or update query string parameter on a URI
|
34
|
+
PopulateMe.update_query_parameter = function(uri, key, value) {
|
35
|
+
var sane_key = key.replace(/[\[\]]/g, "\\$&");
|
36
|
+
var re = new RegExp("([?&])" + sane_key + "=.*?(&|$)", "i");
|
37
|
+
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
|
38
|
+
if (uri.match(re)) {
|
39
|
+
return uri.replace(re, '$1' + key + "=" + encodeURIComponent(value) + '$2');
|
40
|
+
}
|
41
|
+
else {
|
42
|
+
return uri + separator + key + "=" + encodeURIComponent(value);
|
43
|
+
}
|
44
|
+
};
|
45
|
+
|
46
|
+
// Template helpers
|
47
|
+
PopulateMe.template_helpers = {
|
48
|
+
custom_partial_or_default: function() {
|
49
|
+
return function(text,render) {
|
50
|
+
return render('{{>'+(this.custom_template||text)+'}}');
|
51
|
+
}
|
52
|
+
},
|
53
|
+
adapted_field: function() {
|
54
|
+
return function(text,render) {
|
55
|
+
var tmpl;
|
56
|
+
if (this.custom_template) {
|
57
|
+
tmpl = this.custom_template;
|
58
|
+
} else {
|
59
|
+
tmpl = 'template_'+this.type+'_field';
|
60
|
+
if (!(tmpl in PopulateMe.templates)) tmpl = 'template_string_field';
|
61
|
+
}
|
62
|
+
return render('{{>'+tmpl+'}}');
|
63
|
+
}
|
64
|
+
},
|
65
|
+
build_input_attributes: function() {
|
66
|
+
var out = "";
|
67
|
+
$.each(this.input_attributes, function(k,v) {
|
68
|
+
if (v!==false) {
|
69
|
+
out = out+' '+k;
|
70
|
+
if (v!==true) out = out+'=\''+Mustache.escape(v)+'\'';
|
71
|
+
}
|
72
|
+
});
|
73
|
+
return out;
|
74
|
+
},
|
75
|
+
cache_buster: function() {
|
76
|
+
// Simple version which assumes the url has no query yet or hash
|
77
|
+
var buster = Math.random()*10000000000000000;
|
78
|
+
return '?cache_buster='+buster;
|
79
|
+
}
|
80
|
+
};
|
81
|
+
|
82
|
+
// Template render with helpers
|
83
|
+
PopulateMe.mustache_render = function(data) {
|
84
|
+
var data_and_helpers = $.extend(data,PopulateMe.template_helpers);
|
85
|
+
return Mustache.render(PopulateMe.templates[data.template],data_and_helpers,PopulateMe.templates);
|
86
|
+
};
|
87
|
+
|
88
|
+
// Make Sortable from element or css selector
|
89
|
+
PopulateMe.make_sortable = function(selector,context) {
|
90
|
+
var obj = (typeof selector == 'string') ? $(selector,context) : selector;
|
91
|
+
return obj.sortable({
|
92
|
+
forcePlaceholderSize: true,
|
93
|
+
handle: '.handle'
|
94
|
+
});
|
95
|
+
};
|
96
|
+
|
97
|
+
// Scroll to an element, possibly in a specific column.
|
98
|
+
PopulateMe.scroll_to = function(el, column) {
|
99
|
+
if (!column) {
|
100
|
+
column = el.closest('.column');
|
101
|
+
}
|
102
|
+
column.animate({scrollTop: el.position().top});
|
103
|
+
};
|
104
|
+
|
105
|
+
// Mark errors for report after form validation.
|
106
|
+
// It adds the .invalid class to invalid fields,
|
107
|
+
// and adds the report after the label of the field.
|
108
|
+
PopulateMe.mark_errors = function(context,report) {
|
109
|
+
$.each(report,function(k,v) {
|
110
|
+
var field = context.find('> [data-field-name='+k+']:first');
|
111
|
+
if (field.is('fieldset')) {
|
112
|
+
$.each(v, function(index,subreport) {
|
113
|
+
var subcontext = field.find('> .nested-documents > li:nth('+index+')');
|
114
|
+
PopulateMe.mark_errors(subcontext, subreport);
|
115
|
+
});
|
116
|
+
} else {
|
117
|
+
field.addClass('invalid');
|
118
|
+
var errors = "<span class='errors'>, "+v.join(', ')+"</span>";
|
119
|
+
field.find('> label').append(errors);
|
120
|
+
}
|
121
|
+
});
|
122
|
+
};
|
123
|
+
|
124
|
+
// JS Validations
|
125
|
+
// This adds validations that could happen before sending
|
126
|
+
// anything to the server and that cannot be done with
|
127
|
+
// browser form validations like "required".
|
128
|
+
// For example we can check the file size so that files are not sent
|
129
|
+
// to the server at all if they are too big.
|
130
|
+
// Returns a boolean.
|
131
|
+
PopulateMe.jsValidationsPassed = function(context) {
|
132
|
+
if (window.File && window.FileReader && window.FileList && window.Blob) {
|
133
|
+
try {
|
134
|
+
var max_size_fields = $('input[type=file][data-max-size]', context);
|
135
|
+
max_size_fields.each(function() {
|
136
|
+
var field = $(this);
|
137
|
+
var max_size = parseInt(field.data('max-size'));
|
138
|
+
if (field[0].files[0]) {
|
139
|
+
var fsize = field[0].files[0].size;
|
140
|
+
var fname = field[0].files[0].name;
|
141
|
+
if (fsize>max_size) {
|
142
|
+
alert('File too big: '+fname+' should be less than '+PopulateMe.display_file_size(max_size)+'.');
|
143
|
+
throw "Validation error";
|
144
|
+
}
|
145
|
+
}
|
146
|
+
});
|
147
|
+
} catch(e) {
|
148
|
+
if (e==='Validation error') {
|
149
|
+
return false;
|
150
|
+
} else {
|
151
|
+
throw(e);
|
152
|
+
}
|
153
|
+
}
|
154
|
+
}
|
155
|
+
return true;
|
156
|
+
};
|
157
|
+
|
158
|
+
// Init column
|
159
|
+
// Bind events and init things that need to happen when
|
160
|
+
// a new column is added to the finder.
|
161
|
+
// The callback `custom_init_column` is also called at the end
|
162
|
+
// in case you have things to put in your custom javascript.
|
163
|
+
PopulateMe.init_column = function(c) {
|
164
|
+
|
165
|
+
// Sort list item
|
166
|
+
PopulateMe.make_sortable('.documents',c).bind('sortupdate', function(e, ui) {
|
167
|
+
var list = $(ui.item).closest('.documents');
|
168
|
+
var ids = list.children().map(function() {
|
169
|
+
return $(this).data().id;
|
170
|
+
}).get();
|
171
|
+
$.ajax({
|
172
|
+
url: list.data().sortUrl,
|
173
|
+
type: 'put',
|
174
|
+
data: {
|
175
|
+
action: 'sort',
|
176
|
+
field: list.data().sortField,
|
177
|
+
ids: ids
|
178
|
+
}
|
179
|
+
});
|
180
|
+
/*
|
181
|
+
ui.item contains the current dragged element.
|
182
|
+
ui.item.index() contains the new index of the dragged element
|
183
|
+
ui.oldindex contains the old index of the dragged element
|
184
|
+
ui.startparent contains the element that the dragged item comes from
|
185
|
+
ui.endparent contains the element that the dragged item was added to
|
186
|
+
*/
|
187
|
+
});
|
188
|
+
|
189
|
+
// Sort nested documents
|
190
|
+
PopulateMe.make_sortable('.nested-documents',c);
|
191
|
+
|
192
|
+
// Init textareas
|
193
|
+
$('textarea',c).trigger('input');
|
194
|
+
|
195
|
+
// Init multiple select with asmSelect
|
196
|
+
$('select[multiple]', c).asmSelect({ sortable: true, removeLabel: '×' });
|
197
|
+
|
198
|
+
// Select with preview
|
199
|
+
$('select:not([multiple])', c).change(function() {
|
200
|
+
var $this = $(this);
|
201
|
+
var container;
|
202
|
+
if ($this.data('preview-container')) {
|
203
|
+
container = $($this.data('preview-container'), c);
|
204
|
+
} else {
|
205
|
+
container = $this.next('.preview-container');
|
206
|
+
}
|
207
|
+
if (container.size() == 0) return;
|
208
|
+
var path = $this.find(':selected:first').data('preview');
|
209
|
+
if (path) {
|
210
|
+
var img = container.find('img:first');
|
211
|
+
if (img.size() < 1) {
|
212
|
+
img = $("<img src='' alt='Preview' title='Preview' width='250' />");
|
213
|
+
container.html(img);
|
214
|
+
}
|
215
|
+
img.attr('src', path);
|
216
|
+
} else {
|
217
|
+
container.html('');
|
218
|
+
}
|
219
|
+
});
|
220
|
+
$('option:selected[data-preview]').parent().change();
|
221
|
+
|
222
|
+
// Polymorphic selector
|
223
|
+
$('select.polymorphic_type_values').change(function() {
|
224
|
+
var $this = $(this);
|
225
|
+
var link = $this.next();
|
226
|
+
link.attr('href', PopulateMe.update_query_parameter(link.attr('href'), 'data[polymorphic_type]', $this.val()));
|
227
|
+
}).change();
|
228
|
+
|
229
|
+
// Warning when date input not supported
|
230
|
+
var dateFields = $('[type="date"]', c);
|
231
|
+
if ( dateFields.size()>0 && dateFields.prop('type') != 'date' ) {
|
232
|
+
alert('Your browser does not support date fields. You will have to enter dates manually. If you want a better experience and have a date picker, use a modern browser like Chrome.');
|
233
|
+
}
|
234
|
+
|
235
|
+
// Possible callback from custom javascript file.
|
236
|
+
// If you need to do something on init_column,
|
237
|
+
// create this callback.
|
238
|
+
if (PopulateMe.custom_init_column) {
|
239
|
+
PopulateMe.custom_init_column(c);
|
240
|
+
}
|
241
|
+
|
242
|
+
}; // End - Init column
|
243
|
+
|
244
|
+
|
245
|
+
|
246
|
+
// Dom ready
|
247
|
+
$(function() {
|
248
|
+
|
249
|
+
// Dom elements.
|
250
|
+
PopulateMe.finder = $('#finder');
|
251
|
+
|
252
|
+
// Init templates
|
253
|
+
PopulateMe.templates = {};
|
254
|
+
$('[type=x-tmpl-mustache]').each(function() {
|
255
|
+
var $this = $(this);
|
256
|
+
PopulateMe.templates[$this.attr('id').replace(/-/g,'_')] = PopulateMe.init_template($this);
|
257
|
+
});
|
258
|
+
|
259
|
+
// Reactive text area
|
260
|
+
// It switches between online or longer depending on the amount
|
261
|
+
// of text.
|
262
|
+
// Long term, for this reason, it might be used for both
|
263
|
+
// :string and :text fields.
|
264
|
+
$('body').on('input propertychange', 'textarea', function() {
|
265
|
+
if (this.value.length>50 || this.value.match(/\n/)) {
|
266
|
+
$(this).removeClass('oneline');
|
267
|
+
} else {
|
268
|
+
$(this).addClass('oneline');
|
269
|
+
}
|
270
|
+
});
|
271
|
+
|
272
|
+
// Ajax form
|
273
|
+
$('body').on('submit','form.admin-post, form.admin-put', function(e) {
|
274
|
+
e.preventDefault();
|
275
|
+
var self = $(this);
|
276
|
+
if (PopulateMe.jsValidationsPassed(self)) {
|
277
|
+
|
278
|
+
var submit_button = $('input[type=submit]',self);
|
279
|
+
submit_button.hide();
|
280
|
+
$.ajax({
|
281
|
+
url: self.attr('action'),
|
282
|
+
type: (self.is('.admin-put') ? 'put' : 'post'),
|
283
|
+
data: new FormData(this),
|
284
|
+
processData: false,
|
285
|
+
contentType: false,
|
286
|
+
success: function(res) {
|
287
|
+
if (res.success==true) {
|
288
|
+
var reloader = PopulateMe.finder.find('> li:nth-last-child(3) .selected')
|
289
|
+
if (reloader.size()>0) {
|
290
|
+
reloader.trigger('click.columnav',[function(cb_object) {
|
291
|
+
var target = $('[data-id='+res.data.id+']', cb_object.column);
|
292
|
+
if (target.size()>0) {
|
293
|
+
PopulateMe.scroll_to(target, cb_object.column);
|
294
|
+
}
|
295
|
+
}]);
|
296
|
+
} else {
|
297
|
+
PopulateMe.finder.trigger('pop.columnav');
|
298
|
+
}
|
299
|
+
}
|
300
|
+
},
|
301
|
+
error: function(xhr) {
|
302
|
+
res = xhr.responseJSON;
|
303
|
+
if (res.success==false) {
|
304
|
+
$('.invalid',self).removeClass('invalid');
|
305
|
+
$('.errors',self).remove();
|
306
|
+
PopulateMe.mark_errors(self,res.data);
|
307
|
+
PopulateMe.scroll_to(self.find('.invalid:first'));
|
308
|
+
submit_button.show();
|
309
|
+
}
|
310
|
+
}
|
311
|
+
});
|
312
|
+
|
313
|
+
}
|
314
|
+
});
|
315
|
+
|
316
|
+
// Create nested document
|
317
|
+
$('body').on('click','.new-nested-document-btn', function(e) {
|
318
|
+
e.preventDefault();
|
319
|
+
var self = $(this);
|
320
|
+
$.get(this.href, function(data) {
|
321
|
+
var content = $(PopulateMe.mustache_render(data));
|
322
|
+
PopulateMe.make_sortable(self.closest('fieldset').find('> ol').append(content).sortable('destroy'));
|
323
|
+
PopulateMe.scroll_to(content);
|
324
|
+
});
|
325
|
+
});
|
326
|
+
|
327
|
+
// Ajax delete document
|
328
|
+
$('body').on('click', 'button.admin-delete', function(e) {
|
329
|
+
e.preventDefault();
|
330
|
+
var self = $(this);
|
331
|
+
if (confirm('Are you sure you want to delete this item? This operation is not reversible.')) {
|
332
|
+
$.ajax({
|
333
|
+
url: self.val(),
|
334
|
+
type: 'DELETE',
|
335
|
+
success: function() {
|
336
|
+
var li = self.parents('li.admin-list-item');
|
337
|
+
li.fadeOut(function() {
|
338
|
+
li.remove();
|
339
|
+
});
|
340
|
+
}
|
341
|
+
});
|
342
|
+
}
|
343
|
+
});
|
344
|
+
|
345
|
+
// Ajax delete nested document
|
346
|
+
$('body').on('click', 'button.admin-delete-nested', function(e) {
|
347
|
+
e.preventDefault();
|
348
|
+
var self = $(this);
|
349
|
+
if (confirm('Are you sure you want to delete this item? This operation is not reversible.')) {
|
350
|
+
var li = self.closest('li');
|
351
|
+
li.fadeOut(function() {
|
352
|
+
li.remove();
|
353
|
+
});
|
354
|
+
}
|
355
|
+
});
|
356
|
+
|
357
|
+
// Attachment deleter
|
358
|
+
$('body').on('click', 'button.attachment-deleter', function(e) {
|
359
|
+
e.preventDefault();
|
360
|
+
var self = $(this);
|
361
|
+
var input = self.parent().find('input');
|
362
|
+
if (input.attr('type')=='file') {
|
363
|
+
alert('The attachment will be deleted when you save the document.');
|
364
|
+
input.attr('type','hidden').val('');
|
365
|
+
self.text('Cancel attachment deletion');
|
366
|
+
} else {
|
367
|
+
input.attr('type','file');
|
368
|
+
self.text('x');
|
369
|
+
}
|
370
|
+
});
|
371
|
+
|
372
|
+
// Init finder
|
373
|
+
PopulateMe.finder.columnav({
|
374
|
+
on_push: function(data) {
|
375
|
+
PopulateMe.init_column(data.column);
|
376
|
+
},
|
377
|
+
process_data: function(data) {
|
378
|
+
if (typeof data == 'object') {
|
379
|
+
return PopulateMe.mustache_render(data);
|
380
|
+
} else {
|
381
|
+
return data;
|
382
|
+
}
|
383
|
+
}
|
384
|
+
});
|
385
|
+
PopulateMe.finder.trigger('getandpush.columnav',[window.admin_path+window.index_path]);
|
386
|
+
|
387
|
+
}); // End - DomReady
|
388
|
+
|
@@ -0,0 +1,578 @@
|
|
1
|
+
/*!
|
2
|
+
* mustache.js - Logic-less {{mustache}} templates with JavaScript
|
3
|
+
* http://github.com/janl/mustache.js
|
4
|
+
*/
|
5
|
+
|
6
|
+
/*global define: false*/
|
7
|
+
|
8
|
+
(function (global, factory) {
|
9
|
+
if (typeof exports === "object" && exports) {
|
10
|
+
factory(exports); // CommonJS
|
11
|
+
} else if (typeof define === "function" && define.amd) {
|
12
|
+
define(['exports'], factory); // AMD
|
13
|
+
} else {
|
14
|
+
factory(global.Mustache = {}); // <script>
|
15
|
+
}
|
16
|
+
}(this, function (mustache) {
|
17
|
+
|
18
|
+
var Object_toString = Object.prototype.toString;
|
19
|
+
var isArray = Array.isArray || function (object) {
|
20
|
+
return Object_toString.call(object) === '[object Array]';
|
21
|
+
};
|
22
|
+
|
23
|
+
function isFunction(object) {
|
24
|
+
return typeof object === 'function';
|
25
|
+
}
|
26
|
+
|
27
|
+
function escapeRegExp(string) {
|
28
|
+
return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
|
29
|
+
}
|
30
|
+
|
31
|
+
// Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
|
32
|
+
// See https://github.com/janl/mustache.js/issues/189
|
33
|
+
var RegExp_test = RegExp.prototype.test;
|
34
|
+
function testRegExp(re, string) {
|
35
|
+
return RegExp_test.call(re, string);
|
36
|
+
}
|
37
|
+
|
38
|
+
var nonSpaceRe = /\S/;
|
39
|
+
function isWhitespace(string) {
|
40
|
+
return !testRegExp(nonSpaceRe, string);
|
41
|
+
}
|
42
|
+
|
43
|
+
var entityMap = {
|
44
|
+
"&": "&",
|
45
|
+
"<": "<",
|
46
|
+
">": ">",
|
47
|
+
'"': '"',
|
48
|
+
"'": ''',
|
49
|
+
"/": '/'
|
50
|
+
};
|
51
|
+
|
52
|
+
function escapeHtml(string) {
|
53
|
+
return String(string).replace(/[&<>"'\/]/g, function (s) {
|
54
|
+
return entityMap[s];
|
55
|
+
});
|
56
|
+
}
|
57
|
+
|
58
|
+
var whiteRe = /\s*/;
|
59
|
+
var spaceRe = /\s+/;
|
60
|
+
var equalsRe = /\s*=/;
|
61
|
+
var curlyRe = /\s*\}/;
|
62
|
+
var tagRe = /#|\^|\/|>|\{|&|=|!/;
|
63
|
+
|
64
|
+
/**
|
65
|
+
* Breaks up the given `template` string into a tree of tokens. If the `tags`
|
66
|
+
* argument is given here it must be an array with two string values: the
|
67
|
+
* opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
|
68
|
+
* course, the default is to use mustaches (i.e. mustache.tags).
|
69
|
+
*
|
70
|
+
* A token is an array with at least 4 elements. The first element is the
|
71
|
+
* mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
|
72
|
+
* did not contain a symbol (i.e. {{myValue}}) this element is "name". For
|
73
|
+
* all text that appears outside a symbol this element is "text".
|
74
|
+
*
|
75
|
+
* The second element of a token is its "value". For mustache tags this is
|
76
|
+
* whatever else was inside the tag besides the opening symbol. For text tokens
|
77
|
+
* this is the text itself.
|
78
|
+
*
|
79
|
+
* The third and fourth elements of the token are the start and end indices,
|
80
|
+
* respectively, of the token in the original template.
|
81
|
+
*
|
82
|
+
* Tokens that are the root node of a subtree contain two more elements: 1) an
|
83
|
+
* array of tokens in the subtree and 2) the index in the original template at
|
84
|
+
* which the closing tag for that section begins.
|
85
|
+
*/
|
86
|
+
function parseTemplate(template, tags) {
|
87
|
+
if (!template)
|
88
|
+
return [];
|
89
|
+
|
90
|
+
var sections = []; // Stack to hold section tokens
|
91
|
+
var tokens = []; // Buffer to hold the tokens
|
92
|
+
var spaces = []; // Indices of whitespace tokens on the current line
|
93
|
+
var hasTag = false; // Is there a {{tag}} on the current line?
|
94
|
+
var nonSpace = false; // Is there a non-space char on the current line?
|
95
|
+
|
96
|
+
// Strips all whitespace tokens array for the current line
|
97
|
+
// if there was a {{#tag}} on it and otherwise only space.
|
98
|
+
function stripSpace() {
|
99
|
+
if (hasTag && !nonSpace) {
|
100
|
+
while (spaces.length)
|
101
|
+
delete tokens[spaces.pop()];
|
102
|
+
} else {
|
103
|
+
spaces = [];
|
104
|
+
}
|
105
|
+
|
106
|
+
hasTag = false;
|
107
|
+
nonSpace = false;
|
108
|
+
}
|
109
|
+
|
110
|
+
var openingTagRe, closingTagRe, closingCurlyRe;
|
111
|
+
function compileTags(tags) {
|
112
|
+
if (typeof tags === 'string')
|
113
|
+
tags = tags.split(spaceRe, 2);
|
114
|
+
|
115
|
+
if (!isArray(tags) || tags.length !== 2)
|
116
|
+
throw new Error('Invalid tags: ' + tags);
|
117
|
+
|
118
|
+
openingTagRe = new RegExp(escapeRegExp(tags[0]) + '\\s*');
|
119
|
+
closingTagRe = new RegExp('\\s*' + escapeRegExp(tags[1]));
|
120
|
+
closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tags[1]));
|
121
|
+
}
|
122
|
+
|
123
|
+
compileTags(tags || mustache.tags);
|
124
|
+
|
125
|
+
var scanner = new Scanner(template);
|
126
|
+
|
127
|
+
var start, type, value, chr, token, openSection;
|
128
|
+
while (!scanner.eos()) {
|
129
|
+
start = scanner.pos;
|
130
|
+
|
131
|
+
// Match any text between tags.
|
132
|
+
value = scanner.scanUntil(openingTagRe);
|
133
|
+
|
134
|
+
if (value) {
|
135
|
+
for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
|
136
|
+
chr = value.charAt(i);
|
137
|
+
|
138
|
+
if (isWhitespace(chr)) {
|
139
|
+
spaces.push(tokens.length);
|
140
|
+
} else {
|
141
|
+
nonSpace = true;
|
142
|
+
}
|
143
|
+
|
144
|
+
tokens.push([ 'text', chr, start, start + 1 ]);
|
145
|
+
start += 1;
|
146
|
+
|
147
|
+
// Check for whitespace on the current line.
|
148
|
+
if (chr === '\n')
|
149
|
+
stripSpace();
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
// Match the opening tag.
|
154
|
+
if (!scanner.scan(openingTagRe))
|
155
|
+
break;
|
156
|
+
|
157
|
+
hasTag = true;
|
158
|
+
|
159
|
+
// Get the tag type.
|
160
|
+
type = scanner.scan(tagRe) || 'name';
|
161
|
+
scanner.scan(whiteRe);
|
162
|
+
|
163
|
+
// Get the tag value.
|
164
|
+
if (type === '=') {
|
165
|
+
value = scanner.scanUntil(equalsRe);
|
166
|
+
scanner.scan(equalsRe);
|
167
|
+
scanner.scanUntil(closingTagRe);
|
168
|
+
} else if (type === '{') {
|
169
|
+
value = scanner.scanUntil(closingCurlyRe);
|
170
|
+
scanner.scan(curlyRe);
|
171
|
+
scanner.scanUntil(closingTagRe);
|
172
|
+
type = '&';
|
173
|
+
} else {
|
174
|
+
value = scanner.scanUntil(closingTagRe);
|
175
|
+
}
|
176
|
+
|
177
|
+
// Match the closing tag.
|
178
|
+
if (!scanner.scan(closingTagRe))
|
179
|
+
throw new Error('Unclosed tag at ' + scanner.pos);
|
180
|
+
|
181
|
+
token = [ type, value, start, scanner.pos ];
|
182
|
+
tokens.push(token);
|
183
|
+
|
184
|
+
if (type === '#' || type === '^') {
|
185
|
+
sections.push(token);
|
186
|
+
} else if (type === '/') {
|
187
|
+
// Check section nesting.
|
188
|
+
openSection = sections.pop();
|
189
|
+
|
190
|
+
if (!openSection)
|
191
|
+
throw new Error('Unopened section "' + value + '" at ' + start);
|
192
|
+
|
193
|
+
if (openSection[1] !== value)
|
194
|
+
throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
|
195
|
+
} else if (type === 'name' || type === '{' || type === '&') {
|
196
|
+
nonSpace = true;
|
197
|
+
} else if (type === '=') {
|
198
|
+
// Set the tags for the next time around.
|
199
|
+
compileTags(value);
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
// Make sure there are no open sections when we're done.
|
204
|
+
openSection = sections.pop();
|
205
|
+
|
206
|
+
if (openSection)
|
207
|
+
throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
|
208
|
+
|
209
|
+
return nestTokens(squashTokens(tokens));
|
210
|
+
}
|
211
|
+
|
212
|
+
/**
|
213
|
+
* Combines the values of consecutive text tokens in the given `tokens` array
|
214
|
+
* to a single token.
|
215
|
+
*/
|
216
|
+
function squashTokens(tokens) {
|
217
|
+
var squashedTokens = [];
|
218
|
+
|
219
|
+
var token, lastToken;
|
220
|
+
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
|
221
|
+
token = tokens[i];
|
222
|
+
|
223
|
+
if (token) {
|
224
|
+
if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
|
225
|
+
lastToken[1] += token[1];
|
226
|
+
lastToken[3] = token[3];
|
227
|
+
} else {
|
228
|
+
squashedTokens.push(token);
|
229
|
+
lastToken = token;
|
230
|
+
}
|
231
|
+
}
|
232
|
+
}
|
233
|
+
|
234
|
+
return squashedTokens;
|
235
|
+
}
|
236
|
+
|
237
|
+
/**
|
238
|
+
* Forms the given array of `tokens` into a nested tree structure where
|
239
|
+
* tokens that represent a section have two additional items: 1) an array of
|
240
|
+
* all tokens that appear in that section and 2) the index in the original
|
241
|
+
* template that represents the end of that section.
|
242
|
+
*/
|
243
|
+
function nestTokens(tokens) {
|
244
|
+
var nestedTokens = [];
|
245
|
+
var collector = nestedTokens;
|
246
|
+
var sections = [];
|
247
|
+
|
248
|
+
var token, section;
|
249
|
+
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
|
250
|
+
token = tokens[i];
|
251
|
+
|
252
|
+
switch (token[0]) {
|
253
|
+
case '#':
|
254
|
+
case '^':
|
255
|
+
collector.push(token);
|
256
|
+
sections.push(token);
|
257
|
+
collector = token[4] = [];
|
258
|
+
break;
|
259
|
+
case '/':
|
260
|
+
section = sections.pop();
|
261
|
+
section[5] = token[2];
|
262
|
+
collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
|
263
|
+
break;
|
264
|
+
default:
|
265
|
+
collector.push(token);
|
266
|
+
}
|
267
|
+
}
|
268
|
+
|
269
|
+
return nestedTokens;
|
270
|
+
}
|
271
|
+
|
272
|
+
/**
|
273
|
+
* A simple string scanner that is used by the template parser to find
|
274
|
+
* tokens in template strings.
|
275
|
+
*/
|
276
|
+
function Scanner(string) {
|
277
|
+
this.string = string;
|
278
|
+
this.tail = string;
|
279
|
+
this.pos = 0;
|
280
|
+
}
|
281
|
+
|
282
|
+
/**
|
283
|
+
* Returns `true` if the tail is empty (end of string).
|
284
|
+
*/
|
285
|
+
Scanner.prototype.eos = function () {
|
286
|
+
return this.tail === "";
|
287
|
+
};
|
288
|
+
|
289
|
+
/**
|
290
|
+
* Tries to match the given regular expression at the current position.
|
291
|
+
* Returns the matched text if it can match, the empty string otherwise.
|
292
|
+
*/
|
293
|
+
Scanner.prototype.scan = function (re) {
|
294
|
+
var match = this.tail.match(re);
|
295
|
+
|
296
|
+
if (!match || match.index !== 0)
|
297
|
+
return '';
|
298
|
+
|
299
|
+
var string = match[0];
|
300
|
+
|
301
|
+
this.tail = this.tail.substring(string.length);
|
302
|
+
this.pos += string.length;
|
303
|
+
|
304
|
+
return string;
|
305
|
+
};
|
306
|
+
|
307
|
+
/**
|
308
|
+
* Skips all text until the given regular expression can be matched. Returns
|
309
|
+
* the skipped string, which is the entire tail if no match can be made.
|
310
|
+
*/
|
311
|
+
Scanner.prototype.scanUntil = function (re) {
|
312
|
+
var index = this.tail.search(re), match;
|
313
|
+
|
314
|
+
switch (index) {
|
315
|
+
case -1:
|
316
|
+
match = this.tail;
|
317
|
+
this.tail = "";
|
318
|
+
break;
|
319
|
+
case 0:
|
320
|
+
match = "";
|
321
|
+
break;
|
322
|
+
default:
|
323
|
+
match = this.tail.substring(0, index);
|
324
|
+
this.tail = this.tail.substring(index);
|
325
|
+
}
|
326
|
+
|
327
|
+
this.pos += match.length;
|
328
|
+
|
329
|
+
return match;
|
330
|
+
};
|
331
|
+
|
332
|
+
/**
|
333
|
+
* Represents a rendering context by wrapping a view object and
|
334
|
+
* maintaining a reference to the parent context.
|
335
|
+
*/
|
336
|
+
function Context(view, parentContext) {
|
337
|
+
this.view = view == null ? {} : view;
|
338
|
+
this.cache = { '.': this.view };
|
339
|
+
this.parent = parentContext;
|
340
|
+
}
|
341
|
+
|
342
|
+
/**
|
343
|
+
* Creates a new context using the given view with this context
|
344
|
+
* as the parent.
|
345
|
+
*/
|
346
|
+
Context.prototype.push = function (view) {
|
347
|
+
return new Context(view, this);
|
348
|
+
};
|
349
|
+
|
350
|
+
/**
|
351
|
+
* Returns the value of the given name in this context, traversing
|
352
|
+
* up the context hierarchy if the value is absent in this context's view.
|
353
|
+
*/
|
354
|
+
Context.prototype.lookup = function (name) {
|
355
|
+
var cache = this.cache;
|
356
|
+
|
357
|
+
var value;
|
358
|
+
if (name in cache) {
|
359
|
+
value = cache[name];
|
360
|
+
} else {
|
361
|
+
var context = this, names, index;
|
362
|
+
|
363
|
+
while (context) {
|
364
|
+
if (name.indexOf('.') > 0) {
|
365
|
+
value = context.view;
|
366
|
+
names = name.split('.');
|
367
|
+
index = 0;
|
368
|
+
|
369
|
+
while (value != null && index < names.length)
|
370
|
+
value = value[names[index++]];
|
371
|
+
} else {
|
372
|
+
value = context.view[name];
|
373
|
+
}
|
374
|
+
|
375
|
+
if (value != null)
|
376
|
+
break;
|
377
|
+
|
378
|
+
context = context.parent;
|
379
|
+
}
|
380
|
+
|
381
|
+
cache[name] = value;
|
382
|
+
}
|
383
|
+
|
384
|
+
if (isFunction(value))
|
385
|
+
value = value.call(this.view);
|
386
|
+
|
387
|
+
return value;
|
388
|
+
};
|
389
|
+
|
390
|
+
/**
|
391
|
+
* A Writer knows how to take a stream of tokens and render them to a
|
392
|
+
* string, given a context. It also maintains a cache of templates to
|
393
|
+
* avoid the need to parse the same template twice.
|
394
|
+
*/
|
395
|
+
function Writer() {
|
396
|
+
this.cache = {};
|
397
|
+
}
|
398
|
+
|
399
|
+
/**
|
400
|
+
* Clears all cached templates in this writer.
|
401
|
+
*/
|
402
|
+
Writer.prototype.clearCache = function () {
|
403
|
+
this.cache = {};
|
404
|
+
};
|
405
|
+
|
406
|
+
/**
|
407
|
+
* Parses and caches the given `template` and returns the array of tokens
|
408
|
+
* that is generated from the parse.
|
409
|
+
*/
|
410
|
+
Writer.prototype.parse = function (template, tags) {
|
411
|
+
var cache = this.cache;
|
412
|
+
var tokens = cache[template];
|
413
|
+
|
414
|
+
if (tokens == null)
|
415
|
+
tokens = cache[template] = parseTemplate(template, tags);
|
416
|
+
|
417
|
+
return tokens;
|
418
|
+
};
|
419
|
+
|
420
|
+
/**
|
421
|
+
* High-level method that is used to render the given `template` with
|
422
|
+
* the given `view`.
|
423
|
+
*
|
424
|
+
* The optional `partials` argument may be an object that contains the
|
425
|
+
* names and templates of partials that are used in the template. It may
|
426
|
+
* also be a function that is used to load partial templates on the fly
|
427
|
+
* that takes a single argument: the name of the partial.
|
428
|
+
*/
|
429
|
+
Writer.prototype.render = function (template, view, partials) {
|
430
|
+
var tokens = this.parse(template);
|
431
|
+
var context = (view instanceof Context) ? view : new Context(view);
|
432
|
+
return this.renderTokens(tokens, context, partials, template);
|
433
|
+
};
|
434
|
+
|
435
|
+
/**
|
436
|
+
* Low-level method that renders the given array of `tokens` using
|
437
|
+
* the given `context` and `partials`.
|
438
|
+
*
|
439
|
+
* Note: The `originalTemplate` is only ever used to extract the portion
|
440
|
+
* of the original template that was contained in a higher-order section.
|
441
|
+
* If the template doesn't use higher-order sections, this argument may
|
442
|
+
* be omitted.
|
443
|
+
*/
|
444
|
+
Writer.prototype.renderTokens = function (tokens, context, partials, originalTemplate) {
|
445
|
+
var buffer = '';
|
446
|
+
|
447
|
+
// This function is used to render an arbitrary template
|
448
|
+
// in the current context by higher-order sections.
|
449
|
+
var self = this;
|
450
|
+
function subRender(template) {
|
451
|
+
return self.render(template, context, partials);
|
452
|
+
}
|
453
|
+
|
454
|
+
var token, value;
|
455
|
+
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
|
456
|
+
token = tokens[i];
|
457
|
+
|
458
|
+
switch (token[0]) {
|
459
|
+
case '#':
|
460
|
+
value = context.lookup(token[1]);
|
461
|
+
|
462
|
+
if (!value)
|
463
|
+
continue;
|
464
|
+
|
465
|
+
if (isArray(value)) {
|
466
|
+
for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
|
467
|
+
buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
|
468
|
+
}
|
469
|
+
} else if (typeof value === 'object' || typeof value === 'string') {
|
470
|
+
buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
|
471
|
+
} else if (isFunction(value)) {
|
472
|
+
if (typeof originalTemplate !== 'string')
|
473
|
+
throw new Error('Cannot use higher-order sections without the original template');
|
474
|
+
|
475
|
+
// Extract the portion of the original template that the section contains.
|
476
|
+
value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
|
477
|
+
|
478
|
+
if (value != null)
|
479
|
+
buffer += value;
|
480
|
+
} else {
|
481
|
+
buffer += this.renderTokens(token[4], context, partials, originalTemplate);
|
482
|
+
}
|
483
|
+
|
484
|
+
break;
|
485
|
+
case '^':
|
486
|
+
value = context.lookup(token[1]);
|
487
|
+
|
488
|
+
// Use JavaScript's definition of falsy. Include empty arrays.
|
489
|
+
// See https://github.com/janl/mustache.js/issues/186
|
490
|
+
if (!value || (isArray(value) && value.length === 0))
|
491
|
+
buffer += this.renderTokens(token[4], context, partials, originalTemplate);
|
492
|
+
|
493
|
+
break;
|
494
|
+
case '>':
|
495
|
+
if (!partials)
|
496
|
+
continue;
|
497
|
+
|
498
|
+
value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
|
499
|
+
|
500
|
+
if (value != null)
|
501
|
+
buffer += this.renderTokens(this.parse(value), context, partials, value);
|
502
|
+
|
503
|
+
break;
|
504
|
+
case '&':
|
505
|
+
value = context.lookup(token[1]);
|
506
|
+
|
507
|
+
if (value != null)
|
508
|
+
buffer += value;
|
509
|
+
|
510
|
+
break;
|
511
|
+
case 'name':
|
512
|
+
value = context.lookup(token[1]);
|
513
|
+
|
514
|
+
if (value != null)
|
515
|
+
buffer += mustache.escape(value);
|
516
|
+
|
517
|
+
break;
|
518
|
+
case 'text':
|
519
|
+
buffer += token[1];
|
520
|
+
break;
|
521
|
+
}
|
522
|
+
}
|
523
|
+
|
524
|
+
return buffer;
|
525
|
+
};
|
526
|
+
|
527
|
+
mustache.name = "mustache.js";
|
528
|
+
mustache.version = "0.8.1";
|
529
|
+
mustache.tags = [ "{{", "}}" ];
|
530
|
+
|
531
|
+
// All high-level mustache.* functions use this writer.
|
532
|
+
var defaultWriter = new Writer();
|
533
|
+
|
534
|
+
/**
|
535
|
+
* Clears all cached templates in the default writer.
|
536
|
+
*/
|
537
|
+
mustache.clearCache = function () {
|
538
|
+
return defaultWriter.clearCache();
|
539
|
+
};
|
540
|
+
|
541
|
+
/**
|
542
|
+
* Parses and caches the given template in the default writer and returns the
|
543
|
+
* array of tokens it contains. Doing this ahead of time avoids the need to
|
544
|
+
* parse templates on the fly as they are rendered.
|
545
|
+
*/
|
546
|
+
mustache.parse = function (template, tags) {
|
547
|
+
return defaultWriter.parse(template, tags);
|
548
|
+
};
|
549
|
+
|
550
|
+
/**
|
551
|
+
* Renders the `template` with the given `view` and `partials` using the
|
552
|
+
* default writer.
|
553
|
+
*/
|
554
|
+
mustache.render = function (template, view, partials) {
|
555
|
+
return defaultWriter.render(template, view, partials);
|
556
|
+
};
|
557
|
+
|
558
|
+
// This is here for backwards compatibility with 0.4.x.
|
559
|
+
mustache.to_html = function (template, view, partials, send) {
|
560
|
+
var result = mustache.render(template, view, partials);
|
561
|
+
|
562
|
+
if (isFunction(send)) {
|
563
|
+
send(result);
|
564
|
+
} else {
|
565
|
+
return result;
|
566
|
+
}
|
567
|
+
};
|
568
|
+
|
569
|
+
// Export the escaping function so that the user may override it.
|
570
|
+
// See https://github.com/janl/mustache.js/issues/244
|
571
|
+
mustache.escape = escapeHtml;
|
572
|
+
|
573
|
+
// Export these mainly for testing, but also for advanced usage.
|
574
|
+
mustache.Scanner = Scanner;
|
575
|
+
mustache.Context = Context;
|
576
|
+
mustache.Writer = Writer;
|
577
|
+
|
578
|
+
}));
|