Built motion from commit 3000230.|0.0.51
[motion.git] / public / bower_components / angular-form-builder / angular-form-builder.js
1 (function() {
2   var copyObjectToScope;
3
4   copyObjectToScope = function(object, scope) {
5
6     /*
7     Copy object (ng-repeat="object in objects") to scope without `hashKey`.
8      */
9     var key, value;
10     for (key in object) {
11       value = object[key];
12       if (key !== '$$hashKey') {
13         scope[key] = value;
14       }
15     }
16   };
17
18   angular.module('builder.controller', ['builder.provider']).controller('fbFormObjectEditableController', [
19     '$scope', '$injector', function($scope, $injector) {
20       var $builder;
21       $builder = $injector.get('$builder');
22       $scope.setupScope = function(formObject) {
23
24         /*
25         1. Copy origin formObject (ng-repeat="object in formObjects") to scope.
26         2. Setup optionsText with formObject.options.
27         3. Watch scope.label, .description, .placeholder, .required, .options then copy to origin formObject.
28         4. Watch scope.optionsText then convert to scope.options.
29         5. setup validationOptions
30          */
31         var component;
32         copyObjectToScope(formObject, $scope);
33         $scope.optionsText = formObject.options.join('\n');
34         $scope.$watch('[label, description, placeholder, required, options, validation]', function() {
35           formObject.label = $scope.label;
36           formObject.description = $scope.description;
37           formObject.placeholder = $scope.placeholder;
38           formObject.required = $scope.required;
39           formObject.options = $scope.options;
40           return formObject.validation = $scope.validation;
41         }, true);
42         $scope.$watch('optionsText', function(text) {
43           var x;
44           $scope.options = (function() {
45             var _i, _len, _ref, _results;
46             _ref = text.split('\n');
47             _results = [];
48             for (_i = 0, _len = _ref.length; _i < _len; _i++) {
49               x = _ref[_i];
50               if (x.length > 0) {
51                 _results.push(x);
52               }
53             }
54             return _results;
55           })();
56           return $scope.inputText = $scope.options[0];
57         });
58         component = $builder.components[formObject.component];
59         return $scope.validationOptions = component.validationOptions;
60       };
61       return $scope.data = {
62         model: null,
63         backup: function() {
64
65           /*
66           Backup input value.
67            */
68           return this.model = {
69             label: $scope.label,
70             description: $scope.description,
71             placeholder: $scope.placeholder,
72             required: $scope.required,
73             optionsText: $scope.optionsText,
74             validation: $scope.validation
75           };
76         },
77         rollback: function() {
78
79           /*
80           Rollback input value.
81            */
82           if (!this.model) {
83             return;
84           }
85           $scope.label = this.model.label;
86           $scope.description = this.model.description;
87           $scope.placeholder = this.model.placeholder;
88           $scope.required = this.model.required;
89           $scope.optionsText = this.model.optionsText;
90           return $scope.validation = this.model.validation;
91         }
92       };
93     }
94   ]).controller('fbComponentsController', [
95     '$scope', '$injector', function($scope, $injector) {
96       var $builder;
97       $builder = $injector.get('$builder');
98       $scope.selectGroup = function($event, group) {
99         var component, name, _ref, _results;
100         if ($event != null) {
101           $event.preventDefault();
102         }
103         $scope.activeGroup = group;
104         $scope.components = [];
105         _ref = $builder.components;
106         _results = [];
107         for (name in _ref) {
108           component = _ref[name];
109           if (component.group === group) {
110             _results.push($scope.components.push(component));
111           }
112         }
113         return _results;
114       };
115       $scope.groups = $builder.groups;
116       $scope.activeGroup = $scope.groups[0];
117       $scope.allComponents = $builder.components;
118       return $scope.$watch('allComponents', function() {
119         return $scope.selectGroup(null, $scope.activeGroup);
120       });
121     }
122   ]).controller('fbComponentController', [
123     '$scope', function($scope) {
124       return $scope.copyObjectToScope = function(object) {
125         return copyObjectToScope(object, $scope);
126       };
127     }
128   ]).controller('fbFormController', [
129     '$scope', '$injector', function($scope, $injector) {
130       var $builder, $timeout;
131       $builder = $injector.get('$builder');
132       $timeout = $injector.get('$timeout');
133       if ($scope.input == null) {
134         $scope.input = [];
135       }
136       return $scope.$watch('form', function() {
137         if ($scope.input.length > $scope.form.length) {
138           $scope.input.splice($scope.form.length);
139         }
140         return $timeout(function() {
141           return $scope.$broadcast($builder.broadcastChannel.updateInput);
142         });
143       }, true);
144     }
145   ]).controller('fbFormObjectController', [
146     '$scope', '$injector', function($scope, $injector) {
147       var $builder;
148       $builder = $injector.get('$builder');
149       $scope.copyObjectToScope = function(object) {
150         return copyObjectToScope(object, $scope);
151       };
152       return $scope.updateInput = function(value) {
153
154         /*
155         Copy current scope.input[X] to $parent.input.
156         @param value: The input value.
157          */
158         var input;
159         input = {
160           id: $scope.formObject.id,
161           label: $scope.formObject.label,
162           value: value != null ? value : ''
163         };
164         return $scope.$parent.input.splice($scope.$index, 1, input);
165       };
166     }
167   ]);
168
169 }).call(this);
170
171 (function() {
172   angular.module('builder.directive', ['builder.provider', 'builder.controller', 'builder.drag', 'validator']).directive('fbBuilder', [
173     '$injector', function($injector) {
174       var $builder, $drag;
175       $builder = $injector.get('$builder');
176       $drag = $injector.get('$drag');
177       return {
178         restrict: 'A',
179         scope: {
180           fbBuilder: '='
181         },
182         template: "<div class='form-horizontal'>\n    <div class='fb-form-object-editable' ng-repeat=\"object in formObjects\"\n        fb-form-object-editable=\"object\"></div>\n</div>",
183         link: function(scope, element, attrs) {
184           var beginMove, _base, _name;
185           scope.formName = attrs.fbBuilder;
186           if ((_base = $builder.forms)[_name = scope.formName] == null) {
187             _base[_name] = [];
188           }
189           scope.formObjects = $builder.forms[scope.formName];
190           beginMove = true;
191           $(element).addClass('fb-builder');
192           return $drag.droppable($(element), {
193             move: function(e) {
194               var $empty, $formObject, $formObjects, height, index, offset, positions, _i, _j, _ref, _ref1;
195               if (beginMove) {
196                 $("div.fb-form-object-editable").popover('hide');
197                 beginMove = false;
198               }
199               $formObjects = $(element).find('.fb-form-object-editable:not(.empty,.dragging)');
200               if ($formObjects.length === 0) {
201                 if ($(element).find('.fb-form-object-editable.empty').length === 0) {
202                   $(element).find('>div:first').append($("<div class='fb-form-object-editable empty'></div>"));
203                 }
204                 return;
205               }
206               positions = [];
207               positions.push(-1000);
208               for (index = _i = 0, _ref = $formObjects.length; _i < _ref; index = _i += 1) {
209                 $formObject = $($formObjects[index]);
210                 offset = $formObject.offset();
211                 height = $formObject.height();
212                 positions.push(offset.top + height / 2);
213               }
214               positions.push(positions[positions.length - 1] + 1000);
215               for (index = _j = 1, _ref1 = positions.length; _j < _ref1; index = _j += 1) {
216                 if (e.pageY > positions[index - 1] && e.pageY <= positions[index]) {
217                   $(element).find('.empty').remove();
218                   $empty = $("<div class='fb-form-object-editable empty'></div>");
219                   if (index - 1 < $formObjects.length) {
220                     $empty.insertBefore($($formObjects[index - 1]));
221                   } else {
222                     $empty.insertAfter($($formObjects[index - 2]));
223                   }
224                   break;
225                 }
226               }
227             },
228             out: function() {
229               if (beginMove) {
230                 $("div.fb-form-object-editable").popover('hide');
231                 beginMove = false;
232               }
233               return $(element).find('.empty').remove();
234             },
235             up: function(e, isHover, draggable) {
236               var formObject, newIndex, oldIndex;
237               beginMove = true;
238               if (!$drag.isMouseMoved()) {
239                 $(element).find('.empty').remove();
240                 return;
241               }
242               if (!isHover && draggable.mode === 'drag') {
243                 formObject = draggable.object.formObject;
244                 if (formObject.editable) {
245                   $builder.removeFormObject(attrs.fbBuilder, formObject.index);
246                 }
247               } else if (isHover) {
248                 if (draggable.mode === 'mirror') {
249                   $builder.insertFormObject(scope.formName, $(element).find('.empty').index('.fb-form-object-editable'), {
250                     component: draggable.object.componentName
251                   });
252                 }
253                 if (draggable.mode === 'drag') {
254                   oldIndex = draggable.object.formObject.index;
255                   newIndex = $(element).find('.empty').index('.fb-form-object-editable');
256                   if (oldIndex < newIndex) {
257                     newIndex--;
258                   }
259                   $builder.updateFormObjectIndex(scope.formName, oldIndex, newIndex);
260                 }
261               }
262               return $(element).find('.empty').remove();
263             }
264           });
265         }
266       };
267     }
268   ]).directive('fbFormObjectEditable', [
269     '$injector', function($injector) {
270       var $builder, $compile, $drag, $validator;
271       $builder = $injector.get('$builder');
272       $drag = $injector.get('$drag');
273       $compile = $injector.get('$compile');
274       $validator = $injector.get('$validator');
275       return {
276         restrict: 'A',
277         controller: 'fbFormObjectEditableController',
278         scope: {
279           formObject: '=fbFormObjectEditable'
280         },
281         link: function(scope, element) {
282           var popover;
283           scope.inputArray = [];
284           scope.$component = $builder.components[scope.formObject.component];
285           scope.setupScope(scope.formObject);
286           scope.$watch('$component.template', function(template) {
287             var view;
288             if (!template) {
289               return;
290             }
291             view = $compile(template)(scope);
292             return $(element).html(view);
293           });
294           $(element).on('click', function() {
295             return false;
296           });
297           $drag.draggable($(element), {
298             object: {
299               formObject: scope.formObject
300             }
301           });
302           if (!scope.formObject.editable) {
303             return;
304           }
305           popover = {};
306           scope.$watch('$component.popoverTemplate', function(template) {
307             if (!template) {
308               return;
309             }
310             $(element).removeClass(popover.id);
311             popover = {
312               id: "fb-" + (Math.random().toString().substr(2)),
313               isClickedSave: false,
314               view: null,
315               html: template
316             };
317             popover.html = $(popover.html).addClass(popover.id);
318             popover.view = $compile(popover.html)(scope);
319             $(element).addClass(popover.id);
320             return $(element).popover({
321               html: true,
322               title: scope.$component.label,
323               content: popover.view,
324               container: 'body'
325             });
326           });
327           scope.popover = {
328             save: function($event) {
329
330               /*
331               The save event of the popover.
332                */
333               $event.preventDefault();
334               $validator.validate(scope).success(function() {
335                 popover.isClickedSave = true;
336                 return $(element).popover('hide');
337               });
338             },
339             remove: function($event) {
340
341               /*
342               The delete event of the popover.
343                */
344               $event.preventDefault();
345               $builder.removeFormObject(scope.$parent.formName, scope.$parent.$index);
346               $(element).popover('hide');
347             },
348             shown: function() {
349
350               /*
351               The shown event of the popover.
352                */
353               scope.data.backup();
354               return popover.isClickedSave = false;
355             },
356             cancel: function($event) {
357
358               /*
359               The cancel event of the popover.
360                */
361               scope.data.rollback();
362               if ($event) {
363                 $event.preventDefault();
364                 $(element).popover('hide');
365               }
366             }
367           };
368           $(element).on('show.bs.popover', function() {
369             var $popover, elementOrigin, popoverTop;
370             if ($drag.isMouseMoved()) {
371               return false;
372             }
373             $("div.fb-form-object-editable:not(." + popover.id + ")").popover('hide');
374             $popover = $("form." + popover.id).closest('.popover');
375             if ($popover.length > 0) {
376               elementOrigin = $(element).offset().top + $(element).height() / 2;
377               popoverTop = elementOrigin - $popover.height() / 2;
378               $popover.css({
379                 position: 'absolute',
380                 top: popoverTop
381               });
382               $popover.show();
383               setTimeout(function() {
384                 $popover.addClass('in');
385                 return $(element).triggerHandler('shown.bs.popover');
386               }, 0);
387               return false;
388             }
389           });
390           $(element).on('shown.bs.popover', function() {
391             $(".popover ." + popover.id + " input:first").select();
392             scope.$apply(function() {
393               return scope.popover.shown();
394             });
395           });
396           return $(element).on('hide.bs.popover', function() {
397             var $popover;
398             $popover = $("form." + popover.id).closest('.popover');
399             if (!popover.isClickedSave) {
400               if (scope.$$phase || scope.$root.$$phase) {
401                 scope.popover.cancel();
402               } else {
403                 scope.$apply(function() {
404                   return scope.popover.cancel();
405                 });
406               }
407             }
408             $popover.removeClass('in');
409             setTimeout(function() {
410               return $popover.hide();
411             }, 300);
412             return false;
413           });
414         }
415       };
416     }
417   ]).directive('fbComponents', function() {
418     return {
419       restrict: 'A',
420       template: "<ul ng-if=\"groups.length > 1\" class=\"nav nav-tabs nav-justified\">\n    <li ng-repeat=\"group in groups\" ng-class=\"{active:activeGroup==group}\">\n        <a href='#' ng-click=\"selectGroup($event, group)\">{{group}}</a>\n    </li>\n</ul>\n<div class='form-horizontal'>\n    <div class='fb-component' ng-repeat=\"component in components\"\n        fb-component=\"component\"></div>\n</div>",
421       controller: 'fbComponentsController'
422     };
423   }).directive('fbComponent', [
424     '$injector', function($injector) {
425       var $builder, $compile, $drag;
426       $builder = $injector.get('$builder');
427       $drag = $injector.get('$drag');
428       $compile = $injector.get('$compile');
429       return {
430         restrict: 'A',
431         scope: {
432           component: '=fbComponent'
433         },
434         controller: 'fbComponentController',
435         link: function(scope, element) {
436           scope.copyObjectToScope(scope.component);
437           $drag.draggable($(element), {
438             mode: 'mirror',
439             defer: false,
440             object: {
441               componentName: scope.component.name
442             }
443           });
444           return scope.$watch('component.template', function(template) {
445             var view;
446             if (!template) {
447               return;
448             }
449             view = $compile(template)(scope);
450             return $(element).html(view);
451           });
452         }
453       };
454     }
455   ]).directive('fbForm', [
456     '$injector', function($injector) {
457       return {
458         restrict: 'A',
459         require: 'ngModel',
460         scope: {
461           formName: '@fbForm',
462           input: '=ngModel',
463           "default": '=fbDefault'
464         },
465         template: "<div class='fb-form-object' ng-repeat=\"object in form\" fb-form-object=\"object\"></div>",
466         controller: 'fbFormController',
467         link: function(scope, element, attrs) {
468           var $builder, _base, _name;
469           $builder = $injector.get('$builder');
470           if ((_base = $builder.forms)[_name = scope.formName] == null) {
471             _base[_name] = [];
472           }
473           return scope.form = $builder.forms[scope.formName];
474         }
475       };
476     }
477   ]).directive('fbFormObject', [
478     '$injector', function($injector) {
479       var $builder, $compile, $parse;
480       $builder = $injector.get('$builder');
481       $compile = $injector.get('$compile');
482       $parse = $injector.get('$parse');
483       return {
484         restrict: 'A',
485         controller: 'fbFormObjectController',
486         link: function(scope, element, attrs) {
487           scope.formObject = $parse(attrs.fbFormObject)(scope);
488           scope.$component = $builder.components[scope.formObject.component];
489           scope.$on($builder.broadcastChannel.updateInput, function() {
490             return scope.updateInput(scope.inputText);
491           });
492           if (scope.$component.arrayToText) {
493             scope.inputArray = [];
494             scope.$watch('inputArray', function(newValue, oldValue) {
495               var checked, index;
496               if (newValue === oldValue) {
497                 return;
498               }
499               checked = [];
500               for (index in scope.inputArray) {
501                 if (scope.inputArray[index]) {
502                   checked.push(scope.options[index]);
503                 }
504               }
505               return scope.inputText = checked.join(', ');
506             }, true);
507           }
508           scope.$watch('inputText', function() {
509             return scope.updateInput(scope.inputText);
510           });
511           scope.$watch(attrs.fbFormObject, function() {
512             return scope.copyObjectToScope(scope.formObject);
513           }, true);
514           scope.$watch('$component.template', function(template) {
515             var $input, $template, view;
516             if (!template) {
517               return;
518             }
519             $template = $(template);
520             $input = $template.find("[ng-model='inputText']");
521             $input.attr({
522               validator: '{{validation}}'
523             });
524             view = $compile($template)(scope);
525             return $(element).html(view);
526           });
527           if (!scope.$component.arrayToText && scope.formObject.options.length > 0) {
528             scope.inputText = scope.formObject.options[0];
529           }
530           return scope.$watch("default[" + scope.formObject.id + "]", function(value) {
531             if (!value) {
532               return;
533             }
534             if (scope.$component.arrayToText) {
535               return scope.inputArray = value;
536             } else {
537               return scope.inputText = value;
538             }
539           });
540         }
541       };
542     }
543   ]);
544
545 }).call(this);
546
547 (function() {
548   angular.module('builder.drag', []).provider('$drag', function() {
549     var $injector, $rootScope, delay;
550     $injector = null;
551     $rootScope = null;
552     this.data = {
553       draggables: {},
554       droppables: {}
555     };
556     this.mouseMoved = false;
557     this.isMouseMoved = (function(_this) {
558       return function() {
559         return _this.mouseMoved;
560       };
561     })(this);
562     this.hooks = {
563       down: {},
564       move: {},
565       up: {}
566     };
567     this.eventMouseMove = function() {};
568     this.eventMouseUp = function() {};
569     $((function(_this) {
570       return function() {
571         $(document).on('mousedown', function(e) {
572           var func, key, _ref;
573           _this.mouseMoved = false;
574           _ref = _this.hooks.down;
575           for (key in _ref) {
576             func = _ref[key];
577             func(e);
578           }
579         });
580         $(document).on('mousemove', function(e) {
581           var func, key, _ref;
582           _this.mouseMoved = true;
583           _ref = _this.hooks.move;
584           for (key in _ref) {
585             func = _ref[key];
586             func(e);
587           }
588         });
589         return $(document).on('mouseup', function(e) {
590           var func, key, _ref;
591           _ref = _this.hooks.up;
592           for (key in _ref) {
593             func = _ref[key];
594             func(e);
595           }
596         });
597       };
598     })(this));
599     this.currentId = 0;
600     this.getNewId = (function(_this) {
601       return function() {
602         return "" + (_this.currentId++);
603       };
604     })(this);
605     this.setupEasing = function() {
606       return jQuery.extend(jQuery.easing, {
607         easeOutQuad: function(x, t, b, c, d) {
608           return -c * (t /= d) * (t - 2) + b;
609         }
610       });
611     };
612     this.setupProviders = function(injector) {
613
614       /*
615       Setup providers.
616        */
617       $injector = injector;
618       return $rootScope = $injector.get('$rootScope');
619     };
620     this.isHover = (function(_this) {
621       return function($elementA, $elementB) {
622
623         /*
624         Is element A hover on element B?
625         @param $elementA: jQuery object
626         @param $elementB: jQuery object
627          */
628         var isHover, offsetA, offsetB, sizeA, sizeB;
629         offsetA = $elementA.offset();
630         offsetB = $elementB.offset();
631         sizeA = {
632           width: $elementA.width(),
633           height: $elementA.height()
634         };
635         sizeB = {
636           width: $elementB.width(),
637           height: $elementB.height()
638         };
639         isHover = {
640           x: false,
641           y: false
642         };
643         isHover.x = offsetA.left > offsetB.left && offsetA.left < offsetB.left + sizeB.width;
644         isHover.x = isHover.x || offsetA.left + sizeA.width > offsetB.left && offsetA.left + sizeA.width < offsetB.left + sizeB.width;
645         if (!isHover) {
646           return false;
647         }
648         isHover.y = offsetA.top > offsetB.top && offsetA.top < offsetB.top + sizeB.height;
649         isHover.y = isHover.y || offsetA.top + sizeA.height > offsetB.top && offsetA.top + sizeA.height < offsetB.top + sizeB.height;
650         return isHover.x && isHover.y;
651       };
652     })(this);
653     delay = function(ms, func) {
654       return setTimeout(function() {
655         return func();
656       }, ms);
657     };
658     this.autoScroll = {
659       up: false,
660       down: false,
661       scrolling: false,
662       scroll: (function(_this) {
663         return function() {
664           _this.autoScroll.scrolling = true;
665           if (_this.autoScroll.up) {
666             $('html, body').dequeue().animate({
667               scrollTop: $(window).scrollTop() - 50
668             }, 100, 'easeOutQuad');
669             return delay(100, function() {
670               return _this.autoScroll.scroll();
671             });
672           } else if (_this.autoScroll.down) {
673             $('html, body').dequeue().animate({
674               scrollTop: $(window).scrollTop() + 50
675             }, 100, 'easeOutQuad');
676             return delay(100, function() {
677               return _this.autoScroll.scroll();
678             });
679           } else {
680             return _this.autoScroll.scrolling = false;
681           }
682         };
683       })(this),
684       start: (function(_this) {
685         return function(e) {
686           if (e.clientY < 50) {
687             _this.autoScroll.up = true;
688             _this.autoScroll.down = false;
689             if (!_this.autoScroll.scrolling) {
690               return _this.autoScroll.scroll();
691             }
692           } else if (e.clientY > $(window).innerHeight() - 50) {
693             _this.autoScroll.up = false;
694             _this.autoScroll.down = true;
695             if (!_this.autoScroll.scrolling) {
696               return _this.autoScroll.scroll();
697             }
698           } else {
699             _this.autoScroll.up = false;
700             return _this.autoScroll.down = false;
701           }
702         };
703       })(this),
704       stop: (function(_this) {
705         return function() {
706           _this.autoScroll.up = false;
707           return _this.autoScroll.down = false;
708         };
709       })(this)
710     };
711     this.dragMirrorMode = (function(_this) {
712       return function($element, defer, object) {
713         var result;
714         if (defer == null) {
715           defer = true;
716         }
717         result = {
718           id: _this.getNewId(),
719           mode: 'mirror',
720           maternal: $element[0],
721           element: null,
722           object: object
723         };
724         $element.on('mousedown', function(e) {
725           var $clone;
726           e.preventDefault();
727           $clone = $element.clone();
728           result.element = $clone[0];
729           $clone.addClass("fb-draggable form-horizontal prepare-dragging");
730           _this.hooks.move.drag = function(e, defer) {
731             var droppable, id, _ref, _results;
732             if ($clone.hasClass('prepare-dragging')) {
733               $clone.css({
734                 width: $element.width(),
735                 height: $element.height()
736               });
737               $clone.removeClass('prepare-dragging');
738               $clone.addClass('dragging');
739               if (defer) {
740                 return;
741               }
742             }
743             $clone.offset({
744               left: e.pageX - $clone.width() / 2,
745               top: e.pageY - $clone.height() / 2
746             });
747             _this.autoScroll.start(e);
748             _ref = _this.data.droppables;
749             _results = [];
750             for (id in _ref) {
751               droppable = _ref[id];
752               if (_this.isHover($clone, $(droppable.element))) {
753                 _results.push(droppable.move(e, result));
754               } else {
755                 _results.push(droppable.out(e, result));
756               }
757             }
758             return _results;
759           };
760           _this.hooks.up.drag = function(e) {
761             var droppable, id, isHover, _ref;
762             _ref = _this.data.droppables;
763             for (id in _ref) {
764               droppable = _ref[id];
765               isHover = _this.isHover($clone, $(droppable.element));
766               droppable.up(e, isHover, result);
767             }
768             delete _this.hooks.move.drag;
769             delete _this.hooks.up.drag;
770             result.element = null;
771             $clone.remove();
772             return _this.autoScroll.stop();
773           };
774           $('body').append($clone);
775           if (!defer) {
776             return _this.hooks.move.drag(e, defer);
777           }
778         });
779         return result;
780       };
781     })(this);
782     this.dragDragMode = (function(_this) {
783       return function($element, defer, object) {
784         var result;
785         if (defer == null) {
786           defer = true;
787         }
788         result = {
789           id: _this.getNewId(),
790           mode: 'drag',
791           maternal: null,
792           element: $element[0],
793           object: object
794         };
795         $element.addClass('fb-draggable');
796         $element.on('mousedown', function(e) {
797           e.preventDefault();
798           if ($element.hasClass('dragging')) {
799             return;
800           }
801           $element.addClass('prepare-dragging');
802           _this.hooks.move.drag = function(e, defer) {
803             var droppable, id, _ref;
804             if ($element.hasClass('prepare-dragging')) {
805               $element.css({
806                 width: $element.width(),
807                 height: $element.height()
808               });
809               $element.removeClass('prepare-dragging');
810               $element.addClass('dragging');
811               if (defer) {
812                 return;
813               }
814             }
815             $element.offset({
816               left: e.pageX - $element.width() / 2,
817               top: e.pageY - $element.height() / 2
818             });
819             _this.autoScroll.start(e);
820             _ref = _this.data.droppables;
821             for (id in _ref) {
822               droppable = _ref[id];
823               if (_this.isHover($element, $(droppable.element))) {
824                 droppable.move(e, result);
825               } else {
826                 droppable.out(e, result);
827               }
828             }
829           };
830           _this.hooks.up.drag = function(e) {
831             var droppable, id, isHover, _ref;
832             _ref = _this.data.droppables;
833             for (id in _ref) {
834               droppable = _ref[id];
835               isHover = _this.isHover($element, $(droppable.element));
836               droppable.up(e, isHover, result);
837             }
838             delete _this.hooks.move.drag;
839             delete _this.hooks.up.drag;
840             $element.css({
841               width: '',
842               height: '',
843               left: '',
844               top: ''
845             });
846             $element.removeClass('dragging defer-dragging');
847             return _this.autoScroll.stop();
848           };
849           if (!defer) {
850             return _this.hooks.move.drag(e, defer);
851           }
852         });
853         return result;
854       };
855     })(this);
856     this.dropMode = (function(_this) {
857       return function($element, options) {
858         var result;
859         result = {
860           id: _this.getNewId(),
861           element: $element[0],
862           move: function(e, draggable) {
863             return $rootScope.$apply(function() {
864               return typeof options.move === "function" ? options.move(e, draggable) : void 0;
865             });
866           },
867           up: function(e, isHover, draggable) {
868             return $rootScope.$apply(function() {
869               return typeof options.up === "function" ? options.up(e, isHover, draggable) : void 0;
870             });
871           },
872           out: function(e, draggable) {
873             return $rootScope.$apply(function() {
874               return typeof options.out === "function" ? options.out(e, draggable) : void 0;
875             });
876           }
877         };
878         return result;
879       };
880     })(this);
881     this.draggable = (function(_this) {
882       return function($element, options) {
883         var draggable, element, result, _i, _j, _len, _len1;
884         if (options == null) {
885           options = {};
886         }
887
888         /*
889         Make the element could be drag.
890         @param element: The jQuery element.
891         @param options: Options
892             mode: 'drag' [default], 'mirror'
893             defer: yes/no. defer dragging
894             object: custom information
895          */
896         result = [];
897         if (options.mode === 'mirror') {
898           for (_i = 0, _len = $element.length; _i < _len; _i++) {
899             element = $element[_i];
900             draggable = _this.dragMirrorMode($(element), options.defer, options.object);
901             result.push(draggable.id);
902             _this.data.draggables[draggable.id] = draggable;
903           }
904         } else {
905           for (_j = 0, _len1 = $element.length; _j < _len1; _j++) {
906             element = $element[_j];
907             draggable = _this.dragDragMode($(element), options.defer, options.object);
908             result.push(draggable.id);
909             _this.data.draggables[draggable.id] = draggable;
910           }
911         }
912         return result;
913       };
914     })(this);
915     this.droppable = (function(_this) {
916       return function($element, options) {
917         var droppable, element, result, _i, _len;
918         if (options == null) {
919           options = {};
920         }
921
922         /*
923         Make the element coulde be drop.
924         @param $element: The jQuery element.
925         @param options: The droppable options.
926             move: The custom mouse move callback. (e, draggable)->
927             up: The custom mouse up callback. (e, isHover, draggable)->
928             out: The custom mouse out callback. (e, draggable)->
929          */
930         result = [];
931         for (_i = 0, _len = $element.length; _i < _len; _i++) {
932           element = $element[_i];
933           droppable = _this.dropMode($(element), options);
934           result.push(droppable);
935           _this.data.droppables[droppable.id] = droppable;
936         }
937         return result;
938       };
939     })(this);
940     this.get = function($injector) {
941       this.setupEasing();
942       this.setupProviders($injector);
943       return {
944         isMouseMoved: this.isMouseMoved,
945         data: this.data,
946         draggable: this.draggable,
947         droppable: this.droppable
948       };
949     };
950     this.get.$inject = ['$injector'];
951     this.$get = this.get;
952   });
953
954 }).call(this);
955
956 (function() {
957   angular.module('builder', ['builder.directive']);
958
959 }).call(this);
960
961
962 /*
963     component:
964         It is like a class.
965         The base components are textInput, textArea, select, check, radio.
966         User can custom the form with components.
967     formObject:
968         It is like an object (an instance of the component).
969         User can custom the label, description, required and validation of the input.
970     form:
971         This is for end-user. There are form groups int the form.
972         They can input the value to the form.
973  */
974
975 (function() {
976   var __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
977
978   angular.module('builder.provider', []).provider('$builder', function() {
979     var $http, $injector, $templateCache;
980     $injector = null;
981     $http = null;
982     $templateCache = null;
983     this.version = '0.0.2';
984     this.components = {};
985     this.groups = [];
986     this.broadcastChannel = {
987       updateInput: '$updateInput'
988     };
989     this.forms = {
990       "default": []
991     };
992     this.formsId = {
993       "default": 0
994     };
995     this.convertComponent = function(name, component) {
996       var result, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9;
997       result = {
998         name: name,
999         group: (_ref = component.group) != null ? _ref : 'Default',
1000         label: (_ref1 = component.label) != null ? _ref1 : '',
1001         description: (_ref2 = component.description) != null ? _ref2 : '',
1002         placeholder: (_ref3 = component.placeholder) != null ? _ref3 : '',
1003         editable: (_ref4 = component.editable) != null ? _ref4 : true,
1004         required: (_ref5 = component.required) != null ? _ref5 : false,
1005         validation: (_ref6 = component.validation) != null ? _ref6 : '/.*/',
1006         validationOptions: (_ref7 = component.validationOptions) != null ? _ref7 : [],
1007         options: (_ref8 = component.options) != null ? _ref8 : [],
1008         arrayToText: (_ref9 = component.arrayToText) != null ? _ref9 : false,
1009         template: component.template,
1010         templateUrl: component.templateUrl,
1011         popoverTemplate: component.popoverTemplate,
1012         popoverTemplateUrl: component.popoverTemplateUrl
1013       };
1014       if (!result.template && !result.templateUrl) {
1015         console.error("The template is empty.");
1016       }
1017       if (!result.popoverTemplate && !result.popoverTemplateUrl) {
1018         console.error("The popoverTemplate is empty.");
1019       }
1020       return result;
1021     };
1022     this.convertFormObject = function(name, formObject) {
1023       var component, exist, form, result, _i, _len, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9;
1024       if (formObject == null) {
1025         formObject = {};
1026       }
1027       component = this.components[formObject.component];
1028       if (component == null) {
1029         throw "The component " + formObject.component + " was not registered.";
1030       }
1031       if (formObject.id) {
1032         exist = false;
1033         _ref = this.forms[name];
1034         for (_i = 0, _len = _ref.length; _i < _len; _i++) {
1035           form = _ref[_i];
1036           if (!(formObject.id <= form.id)) {
1037             continue;
1038           }
1039           formObject.id = this.formsId[name]++;
1040           exist = true;
1041           break;
1042         }
1043         if (!exist) {
1044           this.formsId[name] = formObject.id + 1;
1045         }
1046       }
1047       result = {
1048         id: (_ref1 = formObject.id) != null ? _ref1 : this.formsId[name]++,
1049         component: formObject.component,
1050         editable: (_ref2 = formObject.editable) != null ? _ref2 : component.editable,
1051         index: (_ref3 = formObject.index) != null ? _ref3 : 0,
1052         label: (_ref4 = formObject.label) != null ? _ref4 : component.label,
1053         description: (_ref5 = formObject.description) != null ? _ref5 : component.description,
1054         placeholder: (_ref6 = formObject.placeholder) != null ? _ref6 : component.placeholder,
1055         options: (_ref7 = formObject.options) != null ? _ref7 : component.options,
1056         required: (_ref8 = formObject.required) != null ? _ref8 : component.required,
1057         validation: (_ref9 = formObject.validation) != null ? _ref9 : component.validation
1058       };
1059       return result;
1060     };
1061     this.reindexFormObject = (function(_this) {
1062       return function(name) {
1063         var formObjects, index, _i, _ref;
1064         formObjects = _this.forms[name];
1065         for (index = _i = 0, _ref = formObjects.length; _i < _ref; index = _i += 1) {
1066           formObjects[index].index = index;
1067         }
1068       };
1069     })(this);
1070     this.setupProviders = (function(_this) {
1071       return function(injector) {
1072         $injector = injector;
1073         $http = $injector.get('$http');
1074         return $templateCache = $injector.get('$templateCache');
1075       };
1076     })(this);
1077     this.loadTemplate = function(component) {
1078
1079       /*
1080       Load template for components.
1081       @param component: {object} The component of $builder.
1082        */
1083       if (component.template == null) {
1084         $http.get(component.templateUrl, {
1085           cache: $templateCache
1086         }).success(function(template) {
1087           return component.template = template;
1088         });
1089       }
1090       if (component.popoverTemplate == null) {
1091         return $http.get(component.popoverTemplateUrl, {
1092           cache: $templateCache
1093         }).success(function(template) {
1094           return component.popoverTemplate = template;
1095         });
1096       }
1097     };
1098     this.registerComponent = (function(_this) {
1099       return function(name, component) {
1100         var newComponent, _ref;
1101         if (component == null) {
1102           component = {};
1103         }
1104
1105         /*
1106         Register the component for form-builder.
1107         @param name: The component name.
1108         @param component: The component object.
1109             group: {string} The component group.
1110             label: {string} The label of the input.
1111             description: {string} The description of the input.
1112             placeholder: {string} The placeholder of the input.
1113             editable: {bool} Is the form object editable?
1114             required: {bool} Is the form object required?
1115             validation: {string} angular-validator. "/regex/" or "[rule1, rule2]". (default is RegExp(.*))
1116             validationOptions: {array} [{rule: angular-validator, label: 'option label'}] the options for the validation. (default is [])
1117             options: {array} The input options.
1118             arrayToText: {bool} checkbox could use this to convert input (default is no)
1119             template: {string} html template
1120             templateUrl: {string} The url of the template.
1121             popoverTemplate: {string} html template
1122             popoverTemplateUrl: {string} The url of the popover template.
1123          */
1124         if (_this.components[name] == null) {
1125           newComponent = _this.convertComponent(name, component);
1126           _this.components[name] = newComponent;
1127           if ($injector != null) {
1128             _this.loadTemplate(newComponent);
1129           }
1130           if (_ref = newComponent.group, __indexOf.call(_this.groups, _ref) < 0) {
1131             _this.groups.push(newComponent.group);
1132           }
1133         } else {
1134           console.error("The component " + name + " was registered.");
1135         }
1136       };
1137     })(this);
1138     this.addFormObject = (function(_this) {
1139       return function(name, formObject) {
1140         var _base;
1141         if (formObject == null) {
1142           formObject = {};
1143         }
1144
1145         /*
1146         Insert the form object into the form at last.
1147          */
1148         if ((_base = _this.forms)[name] == null) {
1149           _base[name] = [];
1150         }
1151         return _this.insertFormObject(name, _this.forms[name].length, formObject);
1152       };
1153     })(this);
1154     this.insertFormObject = (function(_this) {
1155       return function(name, index, formObject) {
1156         var _base, _base1;
1157         if (formObject == null) {
1158           formObject = {};
1159         }
1160
1161         /*
1162         Insert the form object into the form at {index}.
1163         @param name: The form name.
1164         @param index: The form object index.
1165         @param form: The form object.
1166             id: {int} The form object id. It will be generate by $builder if not asigned.
1167             component: {string} The component name
1168             editable: {bool} Is the form object editable? (default is yes)
1169             label: {string} The form object label.
1170             description: {string} The form object description.
1171             placeholder: {string} The form object placeholder.
1172             options: {array} The form object options.
1173             required: {bool} Is the form object required? (default is no)
1174             validation: {string} angular-validator. "/regex/" or "[rule1, rule2]".
1175             [index]: {int} The form object index. It will be updated by $builder.
1176         @return: The form object.
1177          */
1178         if ((_base = _this.forms)[name] == null) {
1179           _base[name] = [];
1180         }
1181         if ((_base1 = _this.formsId)[name] == null) {
1182           _base1[name] = 0;
1183         }
1184         if (index > _this.forms[name].length) {
1185           index = _this.forms[name].length;
1186         } else if (index < 0) {
1187           index = 0;
1188         }
1189         _this.forms[name].splice(index, 0, _this.convertFormObject(name, formObject));
1190         _this.reindexFormObject(name);
1191         return _this.forms[name][index];
1192       };
1193     })(this);
1194     this.removeFormObject = (function(_this) {
1195       return function(name, index) {
1196
1197         /*
1198         Remove the form object by the index.
1199         @param name: The form name.
1200         @param index: The form object index.
1201          */
1202         var formObjects;
1203         formObjects = _this.forms[name];
1204         formObjects.splice(index, 1);
1205         return _this.reindexFormObject(name);
1206       };
1207     })(this);
1208     this.updateFormObjectIndex = (function(_this) {
1209       return function(name, oldIndex, newIndex) {
1210
1211         /*
1212         Update the index of the form object.
1213         @param name: The form name.
1214         @param oldIndex: The old index.
1215         @param newIndex: The new index.
1216          */
1217         var formObject, formObjects;
1218         if (oldIndex === newIndex) {
1219           return;
1220         }
1221         formObjects = _this.forms[name];
1222         formObject = formObjects.splice(oldIndex, 1)[0];
1223         formObjects.splice(newIndex, 0, formObject);
1224         return _this.reindexFormObject(name);
1225       };
1226     })(this);
1227     this.$get = [
1228       '$injector', (function(_this) {
1229         return function($injector) {
1230           var component, name, _ref;
1231           _this.setupProviders($injector);
1232           _ref = _this.components;
1233           for (name in _ref) {
1234             component = _ref[name];
1235             _this.loadTemplate(component);
1236           }
1237           return {
1238             version: _this.version,
1239             components: _this.components,
1240             groups: _this.groups,
1241             forms: _this.forms,
1242             broadcastChannel: _this.broadcastChannel,
1243             registerComponent: _this.registerComponent,
1244             addFormObject: _this.addFormObject,
1245             insertFormObject: _this.insertFormObject,
1246             removeFormObject: _this.removeFormObject,
1247             updateFormObjectIndex: _this.updateFormObjectIndex
1248           };
1249         };
1250       })(this)
1251     ];
1252   });
1253
1254 }).call(this);