chr 0.2.1 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/Gruntfile.coffee +50 -16
  4. data/app/assets/javascripts/chr.coffee +9 -16
  5. data/app/assets/javascripts/chr/core/chr.coffee +38 -20
  6. data/app/assets/javascripts/chr/core/item.coffee +30 -24
  7. data/app/assets/javascripts/chr/core/list.coffee +30 -60
  8. data/app/assets/javascripts/chr/core/list_config.coffee +65 -0
  9. data/app/assets/javascripts/chr/core/list_pagination.coffee +27 -0
  10. data/app/assets/javascripts/chr/core/list_reorder.coffee +75 -0
  11. data/app/assets/javascripts/chr/core/list_search.coffee +41 -0
  12. data/app/assets/javascripts/chr/core/module.coffee +55 -32
  13. data/app/assets/javascripts/chr/core/utils.coffee +34 -13
  14. data/app/assets/javascripts/chr/core/view.coffee +70 -97
  15. data/app/assets/javascripts/chr/form/form.coffee +63 -49
  16. data/app/assets/javascripts/chr/form/input-checkbox.coffee +40 -27
  17. data/app/assets/javascripts/chr/form/input-color.coffee +26 -8
  18. data/app/assets/javascripts/chr/form/input-date.coffee +0 -0
  19. data/app/assets/javascripts/chr/form/input-file.coffee +81 -46
  20. data/app/assets/javascripts/chr/form/input-form.coffee +162 -0
  21. data/app/assets/javascripts/chr/form/input-form_reorder.coffee +67 -0
  22. data/app/assets/javascripts/chr/form/input-hidden.coffee +27 -11
  23. data/app/assets/javascripts/chr/form/input-list.coffee +60 -56
  24. data/app/assets/javascripts/chr/form/input-list_reorder.coffee +37 -0
  25. data/app/assets/javascripts/chr/form/input-password.coffee +31 -0
  26. data/app/assets/javascripts/chr/form/input-select.coffee +61 -35
  27. data/app/assets/javascripts/chr/form/input-string.coffee +55 -25
  28. data/app/assets/javascripts/chr/form/input-text.coffee +22 -5
  29. data/app/assets/javascripts/chr/store/mongosteen-array-store.coffee +1 -1
  30. data/app/assets/javascripts/chr/vendor/ace.js +18280 -0
  31. data/app/assets/javascripts/chr/vendor/marked.js +1272 -0
  32. data/app/assets/javascripts/chr/vendor/mode-html.js +2436 -0
  33. data/app/assets/javascripts/chr/vendor/mode-markdown.js +2820 -0
  34. data/app/assets/javascripts/chr/vendor/redactor.fixedtoolbar.js +110 -0
  35. data/app/assets/javascripts/input-html.coffee +78 -0
  36. data/app/assets/javascripts/input-markdown.coffee +88 -0
  37. data/app/assets/javascripts/input-redactor.coffee +66 -0
  38. data/app/assets/stylesheets/_chr.scss +6 -6
  39. data/app/assets/stylesheets/_input-redactor.scss +34 -0
  40. data/app/assets/stylesheets/core/_mixins.scss +75 -0
  41. data/app/assets/stylesheets/form/_input-checkbox.scss +18 -0
  42. data/app/assets/stylesheets/form/{_input_color.scss → _input-color.scss} +0 -0
  43. data/app/assets/stylesheets/form/{_input_file.scss → _input-file.scss} +1 -0
  44. data/app/assets/stylesheets/form/{_nested_form.scss → _input-form.scss} +0 -0
  45. data/app/assets/stylesheets/form/{_input_list.scss → _input-list.scss} +0 -0
  46. data/app/assets/stylesheets/form/_input-string.scss +8 -0
  47. data/bower.json +3 -2
  48. data/{app/assets/javascripts/chr-dist.js → dist/chr.js} +1472 -1337
  49. data/dist/input-ace.js +24936 -0
  50. data/dist/input-redactor.js +156 -0
  51. data/lib/chr/version.rb +1 -1
  52. data/package.json +2 -2
  53. metadata +29 -13
  54. data/app/assets/javascripts/chr/core/list-pagination.coffee +0 -26
  55. data/app/assets/javascripts/chr/core/list-reorder.coffee +0 -70
  56. data/app/assets/javascripts/chr/core/list-search.coffee +0 -37
  57. data/app/assets/javascripts/chr/form/nested-form.coffee +0 -164
  58. data/app/assets/stylesheets/form/_input_checkbox.scss +0 -91
  59. data/app/assets/stylesheets/form/_input_string.scss +0 -8
@@ -0,0 +1,18 @@
1
+
2
+ // Checkbox -----------------------------------------------
3
+
4
+ .view .input-checkbox { padding: .8em 1em 1em;
5
+ input { display: inline; width: auto; margin-right: .5em; }
6
+ .label { display: inline; cursor: pointer; }
7
+ }
8
+
9
+
10
+ // Switch -------------------------------------------------
11
+
12
+ .view .input-switch { padding-top: .75em;
13
+ .label { cursor: pointer; }
14
+ .switch { @include switchControl(); float: right; }
15
+ }
16
+
17
+
18
+
@@ -11,6 +11,7 @@
11
11
  label { display: inline; font-size: .8em; }
12
12
 
13
13
  &.empty {
14
+ img, a, label, input[type=checkbox] { display: none; }
14
15
  input[type=file] { margin-top: .2em; }
15
16
  }
16
17
  }
@@ -0,0 +1,8 @@
1
+ .view .input-string {
2
+ .twitter-typeahead { width: 100%; }
3
+ .tt-suggestions { padding: .1em .5em; margin: 0 0 0 -.5em; background: rgba(255,255,255, .95); }
4
+ .tt-suggestion { cursor: pointer; opacity: .5;
5
+ p { line-height: 1.5; margin: 0; }
6
+ &.tt-cursor { opacity: 1; }
7
+ }
8
+ }
data/bower.json CHANGED
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "chr",
3
- "version": "0.2.1",
3
+ "version": "0.2.4",
4
4
  "homepage": "https://github.com/slate-studio/chr",
5
5
  "authors": [
6
6
  "Slate Studio (http://www.slatestudio.com)"
7
7
  ],
8
8
  "license": "MIT",
9
9
  "description": "Powerful responsive javascript CMS for apps.",
10
- "main": "app/assets/stylesheets/_chr.scss, app/assets/javascripts/chr-dist.js",
10
+ "main": "app/assets/stylesheets/_chr.scss, app/assets/stylesheets/_input-redactor.scss, dist/chr.js, dist/input-html.js, dist/input-markdown.js, dist/input-redactor.js",
11
11
  "keywords": [
12
12
  "library",
13
13
  "javascript",
14
+ "coffescript",
14
15
  "application",
15
16
  "cms",
16
17
  "rest"
@@ -2654,120 +2654,611 @@ jQuery.fn.scrollParent = function() {
2654
2654
  };
2655
2655
  })();
2656
2656
  })(window.jQuery);
2657
- this.Item = (function() {
2658
- function Item(module, path, object, config) {
2659
- this.module = module;
2660
- this.path = path;
2661
- this.object = object;
2662
- this.config = config;
2663
- this.$el = $("<a class='item' href='" + this.path + "' data-id='" + this.object._id + "' data-title=''></a>");
2664
- this.$el.on('click', (function(_this) {
2665
- return function(e) {
2666
- return _this._on_click(e);
2657
+ this._last = function(array) {
2658
+ return array[array.length - 1];
2659
+ };
2660
+
2661
+ this._first = function(array) {
2662
+ return array[0];
2663
+ };
2664
+
2665
+ this._firstNonEmptyValue = function(o) {
2666
+ var k, v;
2667
+ for (k in o) {
2668
+ v = o[k];
2669
+ if (k[0] !== '_' && v && v !== '') {
2670
+ return v;
2671
+ }
2672
+ }
2673
+ return null;
2674
+ };
2675
+
2676
+ this._entityMap = {
2677
+ "&": "&amp;",
2678
+ "<": "&lt;",
2679
+ ">": "&gt;",
2680
+ '"': '&quot;',
2681
+ "'": '&#39;',
2682
+ "/": '&#x2F;'
2683
+ };
2684
+
2685
+ this._escapeHtml = function(string) {
2686
+ return String(string).replace(/[&<>"'\/]/g, function(s) {
2687
+ return _entityMap[s];
2688
+ });
2689
+ };
2690
+
2691
+ if (typeof String.prototype.titleize !== 'function') {
2692
+ String.prototype.titleize = function() {
2693
+ return this.replace(/_/g, ' ').replace(/\b./g, (function(m) {
2694
+ return m.toUpperCase();
2695
+ }));
2696
+ };
2697
+ }
2698
+
2699
+ if (typeof String.prototype.reverse !== 'function') {
2700
+ String.prototype.reverse = function() {
2701
+ return this.split("").reverse().join("");
2702
+ };
2703
+ }
2704
+
2705
+ if (typeof String.prototype.startsWith !== 'function') {
2706
+ String.prototype.startsWith = function(str) {
2707
+ return this.slice(0, str.length) === str;
2708
+ };
2709
+ }
2710
+
2711
+ if (typeof String.prototype.endsWith !== 'function') {
2712
+ String.prototype.endsWith = function(str) {
2713
+ return this.slice(this.length - str.length, this.length) === str;
2714
+ };
2715
+ }
2716
+
2717
+ if (typeof String.prototype.plainText !== 'function') {
2718
+ String.prototype.plainText = function() {
2719
+ return $("<div>" + this + "</div>").text();
2720
+ };
2721
+ }
2722
+
2723
+ this.extend = function(obj, mixin) {
2724
+ var method, name;
2725
+ for (name in mixin) {
2726
+ method = mixin[name];
2727
+ obj[name] = method;
2728
+ }
2729
+ return obj;
2730
+ };
2731
+
2732
+ this.include = function(klass, mixin) {
2733
+ return extend(klass.prototype, mixin);
2734
+ };
2735
+
2736
+ this.Chr = (function() {
2737
+ function Chr() {
2738
+ this.formInputs = {};
2739
+ this.modules = {};
2740
+ this.itemsPerPageRequest = Math.ceil($(window).height() / 60) * 2;
2741
+ }
2742
+
2743
+ Chr.prototype._unset_active_menu_items = function() {
2744
+ return $('.sidebar .menu a.active').removeClass('active');
2745
+ };
2746
+
2747
+ Chr.prototype._set_active_menu_item = function() {
2748
+ var a, currentModuleName, i, len, moduleName, ref;
2749
+ currentModuleName = window.location.hash.split('/')[1];
2750
+ ref = this.$mainMenu.children();
2751
+ for (i = 0, len = ref.length; i < len; i++) {
2752
+ a = ref[i];
2753
+ moduleName = $(a).attr('href').split('/')[1];
2754
+ if (currentModuleName === moduleName) {
2755
+ return $(a).addClass('active');
2756
+ }
2757
+ }
2758
+ };
2759
+
2760
+ Chr.prototype._navigate = function(path) {
2761
+ var config, crumb, crumbs, i, len, objectId, ref;
2762
+ crumbs = path.split('/');
2763
+ if (this.module !== this.modules[crumbs[1]]) {
2764
+ if ((ref = this.module) != null) {
2765
+ ref.hide(path === '#/');
2766
+ }
2767
+ }
2768
+ this.module = this.modules[crumbs[1]];
2769
+ if (this.module) {
2770
+ this.module.show();
2771
+ config = this.module.config;
2772
+ crumbs = crumbs.splice(2);
2773
+ if (crumbs.length > 0) {
2774
+ for (i = 0, len = crumbs.length; i < len; i++) {
2775
+ crumb = crumbs[i];
2776
+ if (crumb === 'new') {
2777
+ return this.module.showView(null, config, 'New');
2778
+ }
2779
+ if (crumb === 'view') {
2780
+ objectId = _last(crumbs);
2781
+ return this.module.showViewByObjectId(objectId, config);
2782
+ }
2783
+ config = config.items[crumb];
2784
+ if (config.objectStore) {
2785
+ return this.module.showViewByObjectId('', config, crumb.titleize());
2786
+ } else {
2787
+ this.module.showNestedList(crumb);
2788
+ }
2789
+ }
2790
+ } else {
2791
+ return this.module.showRootList();
2792
+ }
2793
+ }
2794
+ };
2795
+
2796
+ Chr.prototype.unsetActiveListItems = function() {
2797
+ return $('.list .items .item.active').removeClass('active');
2798
+ };
2799
+
2800
+ Chr.prototype.isMobile = function() {
2801
+ return $(window).width() < 760;
2802
+ };
2803
+
2804
+ Chr.prototype.updateHash = function(hash, skipHashChange) {
2805
+ if (skipHashChange == null) {
2806
+ skipHashChange = false;
2807
+ }
2808
+ window._skipHashchange = skipHashChange;
2809
+ return location.hash = hash;
2810
+ };
2811
+
2812
+ Chr.prototype.start = function(config1) {
2813
+ var config, name, ref, ref1;
2814
+ this.config = config1;
2815
+ this.$el = $((ref = this.config.selector) != null ? ref : 'body');
2816
+ this.$navBar = $("<nav class='sidebar'>");
2817
+ this.$mainMenu = $("<div class='menu'>");
2818
+ this.$navBar.append(this.$mainMenu);
2819
+ this.$el.append(this.$navBar);
2820
+ ref1 = this.config.modules;
2821
+ for (name in ref1) {
2822
+ config = ref1[name];
2823
+ this.modules[name] = new Module(this, name, config);
2824
+ }
2825
+ $(this).on('hashchange', (function(_this) {
2826
+ return function() {
2827
+ return _this._set_active_menu_item();
2667
2828
  };
2668
2829
  })(this));
2669
- this.render();
2830
+ window.onhashchange = (function(_this) {
2831
+ return function() {
2832
+ _this._unset_active_menu_items();
2833
+ _this.unsetActiveListItems();
2834
+ if (!window._skipHashchange) {
2835
+ _this._navigate(location.hash);
2836
+ }
2837
+ window._skipHashchange = false;
2838
+ return $(_this).trigger('hashchange');
2839
+ };
2840
+ })(this);
2841
+ $(document).on('click', 'a.silent', function(e) {
2842
+ return window._skipHashchange = true;
2843
+ });
2844
+ window._skipHashchange = false;
2845
+ if (location.hash !== '') {
2846
+ this._navigate(location.hash);
2847
+ return $(this).trigger('hashchange');
2848
+ } else if (!this.isMobile()) {
2849
+ return location.hash = '#/' + Object.keys(this.modules)[0];
2850
+ }
2851
+ };
2852
+
2853
+ Chr.prototype.addMenuItem = function(moduleName, title) {
2854
+ return this.$mainMenu.append("<a href='#/" + moduleName + "'>" + title + "</a>");
2855
+ };
2856
+
2857
+ Chr.prototype.showAlert = function(message) {
2858
+ return console.log('Alert: ' + message);
2859
+ };
2860
+
2861
+ Chr.prototype.showError = function(message) {
2862
+ return alert('Error: ' + message);
2863
+ };
2864
+
2865
+ return Chr;
2866
+
2867
+ })();
2868
+
2869
+ window.chr = new Chr();
2870
+
2871
+ this.Module = (function() {
2872
+ function Module(chr1, name, config1) {
2873
+ var base, firstNestedList, menuPath, menuTitle, ref;
2874
+ this.chr = chr1;
2875
+ this.name = name;
2876
+ this.config = config1;
2877
+ this.nestedLists = {};
2878
+ this.$el = $("<section class='module " + this.name + "' style='display: none;'>");
2879
+ this.chr.$el.append(this.$el);
2880
+ this.activeList = this.rootList = new List(this, this.name, this.config);
2881
+ menuTitle = (ref = this.config.menuTitle) != null ? ref : this.config.title;
2882
+ if (menuTitle == null) {
2883
+ menuTitle = this.name.titleize();
2884
+ }
2885
+ menuPath = this.name;
2886
+ if (this.config.showNestedListsAside) {
2887
+ this.$el.addClass('first-list-aside');
2888
+ firstNestedList = _firstNonEmptyValue(this.nestedLists);
2889
+ if (!this.chr.isMobile() && firstNestedList) {
2890
+ menuPath += "/" + firstNestedList.name;
2891
+ }
2892
+ }
2893
+ this.chr.addMenuItem(menuPath, menuTitle);
2894
+ if (typeof (base = this.config).onModuleInit === "function") {
2895
+ base.onModuleInit(this);
2896
+ }
2670
2897
  }
2671
2898
 
2672
- Item.prototype._on_click = function(e) {
2673
- var crumbs, id, title;
2674
- if (this.$el.hasClass('active')) {
2675
- e.preventDefault();
2676
- return;
2899
+ Module.prototype._update_active_list_items = function() {
2900
+ if (!this.activeList.isVisible()) {
2901
+ return this.activeList.updateItems();
2677
2902
  }
2678
- window._skipHashchange = true;
2679
- location.hash = $(e.currentTarget).attr('href');
2680
- title = $(e.currentTarget).attr('data-title');
2681
- id = $(e.currentTarget).attr('data-id');
2682
- crumbs = location.href.split('/');
2683
- if (crumbs[crumbs.length - 2] === 'view') {
2684
- return this.module.showViewByObjectId(id, this.config, title, true);
2903
+ };
2904
+
2905
+ Module.prototype._view_path = function() {
2906
+ var currentList, ref;
2907
+ currentList = (ref = this.visibleNestedListShownWithParent()) != null ? ref : this.activeList;
2908
+ return currentList.path;
2909
+ };
2910
+
2911
+ Module.prototype.addNestedList = function(listName, config, parentList) {
2912
+ return this.nestedLists[listName] = new List(this, listName, config, parentList);
2913
+ };
2914
+
2915
+ Module.prototype.showNestedList = function(listName, animate) {
2916
+ var listToShow;
2917
+ if (animate == null) {
2918
+ animate = false;
2685
2919
  }
2686
- if (this.config.objectStore) {
2687
- return this.module.showViewByObjectId('', this.config, title, true);
2920
+ listToShow = this.nestedLists[listName];
2921
+ if (listToShow.showWithParent) {
2922
+ listToShow.updateItems();
2923
+ listToShow.show(animate, (function(_this) {
2924
+ return function() {
2925
+ var exceptList;
2926
+ return _this.hideNestedLists(exceptList = listName);
2927
+ };
2928
+ })(this));
2929
+ } else {
2930
+ this.activeList = listToShow;
2931
+ this._update_active_list_items();
2932
+ this.activeList.show(animate);
2933
+ }
2934
+ if (animate && this.view) {
2935
+ return this.view.$el.fadeOut($.fx.speeds._default, (function(_this) {
2936
+ return function() {
2937
+ return _this.destroyView();
2938
+ };
2939
+ })(this));
2688
2940
  }
2689
- return this.module.showNestedList(_last(crumbs), true);
2690
2941
  };
2691
2942
 
2692
- Item.prototype._is_folder = function() {
2693
- if (this.object._title) {
2694
- return true;
2943
+ Module.prototype.hideNestedLists = function(exceptList) {
2944
+ var key, list, ref, results;
2945
+ this.activeList = this.rootList;
2946
+ ref = this.nestedLists;
2947
+ results = [];
2948
+ for (key in ref) {
2949
+ list = ref[key];
2950
+ if (key !== exceptList) {
2951
+ results.push(list.hide());
2952
+ }
2953
+ }
2954
+ return results;
2955
+ };
2956
+
2957
+ Module.prototype.visibleNestedListShownWithParent = function() {
2958
+ var key, list, ref;
2959
+ ref = this.nestedLists;
2960
+ for (key in ref) {
2961
+ list = ref[key];
2962
+ if (list.isVisible() && list.showWithParent) {
2963
+ return list;
2964
+ }
2965
+ }
2966
+ };
2967
+
2968
+ Module.prototype.showRootList = function() {
2969
+ var results;
2970
+ this.destroyView();
2971
+ results = [];
2972
+ while (this.activeList !== this.rootList) {
2973
+ results.push(this.hideActiveList(false));
2974
+ }
2975
+ return results;
2976
+ };
2977
+
2978
+ Module.prototype.hideActiveList = function(animate) {
2979
+ if (animate == null) {
2980
+ animate = false;
2981
+ }
2982
+ if (animate) {
2983
+ this.activeList.$el.fadeOut();
2695
2984
  } else {
2696
- return false;
2985
+ this.activeList.$el.hide();
2697
2986
  }
2987
+ return this.activeList = this.activeList.parentList;
2698
2988
  };
2699
2989
 
2700
- Item.prototype._render_title = function() {
2701
- var title;
2702
- title = this.object._title;
2703
- if (title == null) {
2704
- title = this.object[this.config.itemTitleField];
2990
+ Module.prototype.showView = function(object, config, title, animate) {
2991
+ var newView;
2992
+ if (animate == null) {
2993
+ animate = false;
2705
2994
  }
2706
- if (title == null) {
2707
- title = _firstNonEmptyValue(this.object);
2995
+ newView = new View(this, config, this._view_path(), object, title);
2996
+ this.chr.$el.append(newView.$el);
2997
+ return newView.show(animate, (function(_this) {
2998
+ return function() {
2999
+ _this.destroyView();
3000
+ return _this.view = newView;
3001
+ };
3002
+ })(this));
3003
+ };
3004
+
3005
+ Module.prototype.showViewByObjectId = function(objectId, config, title, animate) {
3006
+ var onError, onSuccess;
3007
+ if (animate == null) {
3008
+ animate = false;
2708
3009
  }
2709
- if (title == null) {
2710
- title = "No Title";
3010
+ onSuccess = (function(_this) {
3011
+ return function(object) {
3012
+ return _this.showView(object, config, title, animate);
3013
+ };
3014
+ })(this);
3015
+ onError = function() {
3016
+ return chr.showError("can\'t show view for requested object");
3017
+ };
3018
+ if (objectId === '') {
3019
+ return config.objectStore.loadObject({
3020
+ onSuccess: onSuccess,
3021
+ onError: onError
3022
+ });
3023
+ } else {
3024
+ return config.arrayStore.loadObject(objectId, {
3025
+ onSuccess: onSuccess,
3026
+ onError: onError
3027
+ });
2711
3028
  }
2712
- title = _stripHtml(title);
2713
- this.$title = $("<div class='item-title'>" + title + "</div>");
2714
- this.$el.append(this.$title);
2715
- return this.$el.attr('data-title', title);
2716
3029
  };
2717
3030
 
2718
- Item.prototype._render_subtitle = function() {
2719
- var subtitle;
2720
- if (this.config.itemSubtitleField) {
2721
- subtitle = this.object[this.config.itemSubtitleField];
2722
- if (subtitle !== '') {
2723
- this.$subtitle = $("<div class='item-subtitle'>" + subtitle + "</div>");
2724
- this.$el.append(this.$subtitle);
2725
- return this.$el.addClass('has-subtitle');
3031
+ Module.prototype.destroyView = function() {
3032
+ var ref;
3033
+ return (ref = this.view) != null ? ref.destroy() : void 0;
3034
+ };
3035
+
3036
+ Module.prototype.show = function() {
3037
+ this._update_active_list_items();
3038
+ this.$el.show();
3039
+ return this.activeList.show(false);
3040
+ };
3041
+
3042
+ Module.prototype.hide = function(animate) {
3043
+ if (animate == null) {
3044
+ animate = false;
3045
+ }
3046
+ this.hideNestedLists();
3047
+ if (animate) {
3048
+ if (this.view) {
3049
+ this.view.$el.fadeOut($.fx.speeds._default, (function(_this) {
3050
+ return function() {
3051
+ return _this.destroyView();
3052
+ };
3053
+ })(this));
3054
+ }
3055
+ return this.$el.fadeOut();
3056
+ } else {
3057
+ this.destroyView();
3058
+ return this.$el.hide();
3059
+ }
3060
+ };
3061
+
3062
+ return Module;
3063
+
3064
+ })();
3065
+
3066
+ this.listConfig = {
3067
+ _process_config_items: function() {
3068
+ var config, object, ref, ref1, results, slug;
3069
+ ref = this.config.items;
3070
+ results = [];
3071
+ for (slug in ref) {
3072
+ config = ref[slug];
3073
+ object = {
3074
+ _id: slug,
3075
+ _title: (ref1 = config.title) != null ? ref1 : slug.titleize()
3076
+ };
3077
+ if (config.items || config.arrayStore) {
3078
+ this.module.addNestedList(slug, config, this);
2726
3079
  }
3080
+ this._add_item("#/" + this.path + "/" + slug, object, 0, config);
3081
+ results.push(this.configItemsCount += 1);
3082
+ }
3083
+ return results;
3084
+ },
3085
+ _bind_config_array_store: function() {
3086
+ this.config.arrayStore.on('object_added', (function(_this) {
3087
+ return function(e, data) {
3088
+ return _this._add_item("#/" + _this.path + "/view/" + data.object._id, data.object, data.position, _this.config);
3089
+ };
3090
+ })(this));
3091
+ if (this.config.objects) {
3092
+ this.config.arrayStore.addObjects(this.config.objects);
3093
+ }
3094
+ this.config.arrayStore.on('object_changed', (function(_this) {
3095
+ return function(e, data) {
3096
+ var item;
3097
+ item = _this.items[data.object._id];
3098
+ if (item) {
3099
+ item.render();
3100
+ return _this._update_item_position(item, data.position);
3101
+ }
3102
+ };
3103
+ })(this));
3104
+ this.config.arrayStore.on('object_removed', (function(_this) {
3105
+ return function(e, data) {
3106
+ var item;
3107
+ item = _this.items[data.object_id];
3108
+ if (item) {
3109
+ item.destroy();
3110
+ return delete _this.items[data.object_id];
3111
+ }
3112
+ };
3113
+ })(this));
3114
+ this.config.arrayStore.on('objects_added', (function(_this) {
3115
+ return function(e, data) {
3116
+ _this._hide_spinner();
3117
+ return _this._set_active_item();
3118
+ };
3119
+ })(this));
3120
+ if (this.config.arrayStore.pagination) {
3121
+ this._bind_pagination();
2727
3122
  }
2728
- };
2729
-
2730
- Item.prototype._render_thumbnail = function() {
2731
- var imageUrl;
2732
- if (this.config.itemThumbnail) {
2733
- imageUrl = this.config.itemThumbnail(this.object);
2734
- if (imageUrl !== '' && !imageUrl.endsWith('_old_')) {
2735
- this.$thumbnail = $("<div class='item-thumbnail'><img src='" + imageUrl + "' /></div>");
2736
- this.$el.append(this.$thumbnail);
2737
- return this.$el.addClass('has-thumbnail');
2738
- }
3123
+ if (this.config.arrayStore.searchable) {
3124
+ this._bind_search(this);
2739
3125
  }
2740
- };
2741
-
2742
- Item.prototype.render = function() {
2743
- this.$el.html('').removeClass('item-folder has-subtitle has-thumbnail');
2744
- this._render_title();
2745
- if (this._is_folder()) {
2746
- this.$el.addClass('item-folder');
2747
- return this.$el.append($("<div class='icon-folder'></div>"));
2748
- } else {
2749
- this._render_subtitle();
2750
- this._render_thumbnail();
2751
- if (this.config.arrayStore && this.config.arrayStore.reorderable) {
2752
- this.$el.addClass('reorderable');
2753
- return this.$el.append($("<div class='icon-reorder'></div>"));
2754
- }
3126
+ if (this.config.arrayStore.reorderable) {
3127
+ return this._bind_reorder(this);
2755
3128
  }
2756
- };
2757
-
2758
- Item.prototype.destroy = function() {
2759
- return this.$el.remove();
2760
- };
3129
+ },
3130
+ _bind_config_object_store: function() {}
3131
+ };
2761
3132
 
2762
- Item.prototype.position = function() {
2763
- var positionFieldName;
2764
- positionFieldName = this.config.arrayStore.sortBy;
2765
- return parseFloat(this.object[positionFieldName]);
2766
- };
3133
+ this.listPagination = {
3134
+ _bind_pagination: function() {
3135
+ var arrayStore;
3136
+ arrayStore = this.config.arrayStore;
3137
+ return this.$items.scroll((function(_this) {
3138
+ return function(e) {
3139
+ var $listChildren, listChildrenCount, listFirstChildHeight, listHeight, viewHeight;
3140
+ if (!arrayStore.dataFetchLock) {
3141
+ $listChildren = _this.$items.children();
3142
+ listChildrenCount = $listChildren.length;
3143
+ listFirstChildHeight = $listChildren.first().outerHeight();
3144
+ listHeight = listChildrenCount * listFirstChildHeight;
3145
+ viewHeight = _this.$el.height();
3146
+ if (listHeight < (viewHeight + e.target.scrollTop + 100)) {
3147
+ _this._show_spinner();
3148
+ return arrayStore.load();
3149
+ }
3150
+ }
3151
+ };
3152
+ })(this));
3153
+ }
3154
+ };
2767
3155
 
2768
- return Item;
3156
+ this.listReorder = {
3157
+ _bind_reorder: function(listEl) {
3158
+ var _getObjectNewPosition, arrayStore, config, items, list;
3159
+ items = listEl.items;
3160
+ list = listEl.$items.get(0);
3161
+ arrayStore = listEl.config.arrayStore;
3162
+ config = arrayStore.reorderable;
3163
+ _getObjectNewPosition = function(el) {
3164
+ var $el, newPosition, nextObjectId, nextObjectPosition, prevObjectId, prevObjectPosition;
3165
+ $el = $(el);
3166
+ nextObjectId = $el.next().attr('data-id');
3167
+ prevObjectId = $el.prev().attr('data-id');
3168
+ nextObjectPosition = 0;
3169
+ prevObjectPosition = 0;
3170
+ if (prevObjectId) {
3171
+ prevObjectPosition = items[prevObjectId].position();
3172
+ }
3173
+ if (nextObjectId) {
3174
+ nextObjectPosition = items[nextObjectId].position();
3175
+ }
3176
+ if (arrayStore.sortReverse) {
3177
+ newPosition = nextObjectPosition + Math.abs(nextObjectPosition - prevObjectPosition) / 2.0;
3178
+ } else {
3179
+ newPosition = prevObjectPosition + Math.abs(nextObjectPosition - prevObjectPosition) / 2.0;
3180
+ }
3181
+ return newPosition;
3182
+ };
3183
+ new Slip(list);
3184
+ list.addEventListener('slip:beforeswipe', function(e) {
3185
+ return e.preventDefault();
3186
+ });
3187
+ list.addEventListener('slip:beforewait', (function(e) {
3188
+ if ($(e.target).hasClass("icon-reorder")) {
3189
+ return e.preventDefault();
3190
+ }
3191
+ }), false);
3192
+ list.addEventListener('slip:beforereorder', (function(e) {
3193
+ if (!$(e.target).hasClass("icon-reorder")) {
3194
+ return e.preventDefault();
3195
+ }
3196
+ }), false);
3197
+ list.addEventListener('slip:reorder', ((function(_this) {
3198
+ return function(e) {
3199
+ var objectId, objectPositionValue, value;
3200
+ e.target.parentNode.insertBefore(e.target, e.detail.insertBefore);
3201
+ objectPositionValue = _getObjectNewPosition(e.target);
3202
+ objectId = $(e.target).attr('data-id');
3203
+ value = {};
3204
+ value["[" + arrayStore.sortBy] = "" + objectPositionValue;
3205
+ arrayStore.update(objectId, value, {
3206
+ onSuccess: function(object) {},
3207
+ onError: function(errors) {}
3208
+ });
3209
+ return false;
3210
+ };
3211
+ })(this)), false);
3212
+ return $(list).addClass('reorderable');
3213
+ }
3214
+ };
2769
3215
 
2770
- })();
3216
+ this.listSearch = {
3217
+ _bind_search: function(listEl) {
3218
+ var $input, arrayStore, cancel, search, show;
3219
+ $input = listEl.$search;
3220
+ arrayStore = listEl.config.arrayStore;
3221
+ search = function(input) {
3222
+ var query;
3223
+ query = $(input).val();
3224
+ listEl._show_spinner();
3225
+ return arrayStore.search(query);
3226
+ };
3227
+ show = function() {
3228
+ listEl.$el.addClass('list-search');
3229
+ return $input.find('input').focus();
3230
+ };
3231
+ cancel = function() {
3232
+ listEl.$el.removeClass('list-search');
3233
+ $input.find('input').val('');
3234
+ listEl._show_spinner();
3235
+ return arrayStore.reset();
3236
+ };
3237
+ $input.show();
3238
+ $input.on('keyup', 'input', (function(_this) {
3239
+ return function(e) {
3240
+ if (e.keyCode === 27) {
3241
+ return cancel();
3242
+ }
3243
+ if (e.keyCode === 13) {
3244
+ return search(e.target);
3245
+ }
3246
+ };
3247
+ })(this));
3248
+ $input.on('click', '.icon', (function(_this) {
3249
+ return function(e) {
3250
+ e.preventDefault();
3251
+ return show();
3252
+ };
3253
+ })(this));
3254
+ return $input.on('click', '.cancel', (function(_this) {
3255
+ return function(e) {
3256
+ e.preventDefault();
3257
+ return cancel();
3258
+ };
3259
+ })(this));
3260
+ }
3261
+ };
2771
3262
 
2772
3263
  this.List = (function() {
2773
3264
  function List(module, name, config1, parentList) {
@@ -2803,7 +3294,7 @@ this.List = (function() {
2803
3294
  this.$backBtn = $("<a href='#/" + this.parentList.path + "' class='back silent'></a>");
2804
3295
  this.$backBtn.on('click', (function(_this) {
2805
3296
  return function(e) {
2806
- return _this._on_back(e);
3297
+ return _this._back(e);
2807
3298
  };
2808
3299
  })(this));
2809
3300
  } else {
@@ -2816,7 +3307,7 @@ this.List = (function() {
2816
3307
  this.$newBtn = $("<a href='#/" + this.path + "/new' class='new silent'></a>");
2817
3308
  this.$newBtn.on('click', (function(_this) {
2818
3309
  return function(e) {
2819
- return _this._on_new(e);
3310
+ return _this._new(e);
2820
3311
  };
2821
3312
  })(this));
2822
3313
  this.$header.append(this.$newBtn);
@@ -2872,73 +3363,6 @@ this.List = (function() {
2872
3363
  return this.module.name + (crumbs.length > 0 ? '/' + crumbs.reverse().join('/') : '');
2873
3364
  };
2874
3365
 
2875
- List.prototype._process_config_items = function() {
2876
- var config, object, ref, ref1, results, slug;
2877
- ref = this.config.items;
2878
- results = [];
2879
- for (slug in ref) {
2880
- config = ref[slug];
2881
- object = {
2882
- _id: slug,
2883
- _title: (ref1 = config.title) != null ? ref1 : slug.titleize()
2884
- };
2885
- if (config.items || config.arrayStore) {
2886
- this.module.addNestedList(slug, config, this);
2887
- }
2888
- this._add_item("#/" + this.path + "/" + slug, object, 0, config);
2889
- results.push(this.configItemsCount += 1);
2890
- }
2891
- return results;
2892
- };
2893
-
2894
- List.prototype._bind_config_object_store = function() {};
2895
-
2896
- List.prototype._bind_config_array_store = function() {
2897
- this.config.arrayStore.on('object_added', (function(_this) {
2898
- return function(e, data) {
2899
- return _this._add_item("#/" + _this.path + "/view/" + data.object._id, data.object, data.position, _this.config);
2900
- };
2901
- })(this));
2902
- if (this.config.objects) {
2903
- this.config.arrayStore.addObjects(this.config.objects);
2904
- }
2905
- this.config.arrayStore.on('object_changed', (function(_this) {
2906
- return function(e, data) {
2907
- var item;
2908
- item = _this.items[data.object._id];
2909
- if (item) {
2910
- item.render();
2911
- return _this._update_item_position(item, data.position);
2912
- }
2913
- };
2914
- })(this));
2915
- this.config.arrayStore.on('object_removed', (function(_this) {
2916
- return function(e, data) {
2917
- var item;
2918
- item = _this.items[data.object_id];
2919
- if (item) {
2920
- item.destroy();
2921
- return delete _this.items[data.object_id];
2922
- }
2923
- };
2924
- })(this));
2925
- this.config.arrayStore.on('objects_added', (function(_this) {
2926
- return function(e, data) {
2927
- _this._hide_spinner();
2928
- return _this._set_active_item();
2929
- };
2930
- })(this));
2931
- if (this.config.arrayStore.pagination) {
2932
- _listBindPagination(this);
2933
- }
2934
- if (this.config.arrayStore.searchable) {
2935
- _listBindSearch(this);
2936
- }
2937
- if (this.config.arrayStore.reorderable) {
2938
- return _listBindReorder(this);
2939
- }
2940
- };
2941
-
2942
3366
  List.prototype._add_item = function(path, object, position, config) {
2943
3367
  var item;
2944
3368
  item = new this.itemClass(this.module, path, object, config);
@@ -2964,7 +3388,7 @@ this.List = (function() {
2964
3388
  return this.$el.removeClass('show-spinner');
2965
3389
  };
2966
3390
 
2967
- List.prototype._on_back = function(e) {
3391
+ List.prototype._back = function(e) {
2968
3392
  this.module.chr.unsetActiveListItems();
2969
3393
  this.module.destroyView();
2970
3394
  if (this.showWithParent) {
@@ -2974,9 +3398,8 @@ this.List = (function() {
2974
3398
  }
2975
3399
  };
2976
3400
 
2977
- List.prototype._on_new = function(e) {
2978
- window._skipHashchange = true;
2979
- location.hash = $(e.currentTarget).attr('href');
3401
+ List.prototype._new = function(e) {
3402
+ chr.updateHash($(e.currentTarget).attr('href'), true);
2980
3403
  return this.module.showView(null, this.config, 'New', true);
2981
3404
  };
2982
3405
 
@@ -3023,148 +3446,188 @@ this.List = (function() {
3023
3446
  }
3024
3447
  };
3025
3448
 
3026
- List.prototype.updateItems = function() {
3027
- if (!this.config.disableUpdateItems) {
3028
- if (this.config.arrayStore) {
3029
- this._show_spinner();
3030
- return this.config.arrayStore.reset();
3449
+ List.prototype.updateItems = function() {
3450
+ if (!this.config.disableUpdateItems) {
3451
+ if (this.config.arrayStore) {
3452
+ this._show_spinner();
3453
+ return this.config.arrayStore.reset();
3454
+ }
3455
+ }
3456
+ };
3457
+
3458
+ List.prototype.isVisible = function() {
3459
+ return this.$el.is(':visible');
3460
+ };
3461
+
3462
+ return List;
3463
+
3464
+ })();
3465
+
3466
+ include(List, listConfig);
3467
+
3468
+ include(List, listPagination);
3469
+
3470
+ include(List, listReorder);
3471
+
3472
+ include(List, listSearch);
3473
+
3474
+ this.Item = (function() {
3475
+ function Item(module, path, object, config) {
3476
+ this.module = module;
3477
+ this.path = path;
3478
+ this.object = object;
3479
+ this.config = config;
3480
+ this.$el = $("<a class='item' href='" + this.path + "' data-id='" + this.object._id + "' data-title=''></a>");
3481
+ this.$el.on('click', (function(_this) {
3482
+ return function(e) {
3483
+ return _this._click(e);
3484
+ };
3485
+ })(this));
3486
+ this.render();
3487
+ }
3488
+
3489
+ Item.prototype._is_folder = function() {
3490
+ if (this.object._title) {
3491
+ return true;
3492
+ } else {
3493
+ return false;
3494
+ }
3495
+ };
3496
+
3497
+ Item.prototype._render_title = function() {
3498
+ var title;
3499
+ title = this.object._title;
3500
+ if (title == null) {
3501
+ title = this.object[this.config.itemTitleField];
3502
+ }
3503
+ if (title == null) {
3504
+ title = _firstNonEmptyValue(this.object);
3505
+ }
3506
+ if (title == null) {
3507
+ title = "No Title";
3508
+ }
3509
+ title = title.plainText();
3510
+ this.$title = $("<div class='item-title'>" + title + "</div>");
3511
+ this.$el.append(this.$title);
3512
+ return this.$el.attr('data-title', title);
3513
+ };
3514
+
3515
+ Item.prototype._render_subtitle = function() {
3516
+ var subtitle;
3517
+ if (this.config.itemSubtitleField) {
3518
+ subtitle = this.object[this.config.itemSubtitleField];
3519
+ if (subtitle !== '') {
3520
+ this.$subtitle = $("<div class='item-subtitle'>" + subtitle + "</div>");
3521
+ this.$el.append(this.$subtitle);
3522
+ return this.$el.addClass('has-subtitle');
3523
+ }
3524
+ }
3525
+ };
3526
+
3527
+ Item.prototype._render_thumbnail = function() {
3528
+ var imageUrl;
3529
+ if (this.config.itemThumbnail) {
3530
+ imageUrl = this.config.itemThumbnail(this.object);
3531
+ if (imageUrl !== '' && !imageUrl.endsWith('_old_')) {
3532
+ this.$thumbnail = $("<div class='item-thumbnail'><img src='" + imageUrl + "' /></div>");
3533
+ this.$el.append(this.$thumbnail);
3534
+ return this.$el.addClass('has-thumbnail');
3535
+ }
3536
+ }
3537
+ };
3538
+
3539
+ Item.prototype._click = function(e) {
3540
+ var crumbs, hash, id, title;
3541
+ if (this.$el.hasClass('active')) {
3542
+ e.preventDefault();
3543
+ return;
3544
+ }
3545
+ hash = $(e.currentTarget).attr('href');
3546
+ crumbs = hash.split('/');
3547
+ title = $(e.currentTarget).attr('data-title');
3548
+ id = $(e.currentTarget).attr('data-id');
3549
+ chr.updateHash(hash, true);
3550
+ if (crumbs[crumbs.length - 2] === 'view') {
3551
+ return this.module.showViewByObjectId(id, this.config, title, true);
3552
+ }
3553
+ if (this.config.objectStore) {
3554
+ return this.module.showViewByObjectId('', this.config, title, true);
3555
+ }
3556
+ return this.module.showNestedList(_last(crumbs), true);
3557
+ };
3558
+
3559
+ Item.prototype.render = function() {
3560
+ this.$el.html('').removeClass('item-folder has-subtitle has-thumbnail');
3561
+ this._render_title();
3562
+ if (this._is_folder()) {
3563
+ this.$el.addClass('item-folder');
3564
+ return this.$el.append($("<div class='icon-folder'></div>"));
3565
+ } else {
3566
+ this._render_subtitle();
3567
+ this._render_thumbnail();
3568
+ if (this.config.arrayStore && this.config.arrayStore.reorderable) {
3569
+ this.$el.addClass('reorderable');
3570
+ return this.$el.append($("<div class='icon-reorder'></div>"));
3031
3571
  }
3032
3572
  }
3033
3573
  };
3034
3574
 
3035
- List.prototype.isVisible = function() {
3036
- return this.$el.is(':visible');
3575
+ Item.prototype.destroy = function() {
3576
+ return this.$el.remove();
3037
3577
  };
3038
3578
 
3039
- return List;
3040
-
3041
- })();
3579
+ Item.prototype.position = function() {
3580
+ var positionFieldName;
3581
+ positionFieldName = this.config.arrayStore.sortBy;
3582
+ return parseFloat(this.object[positionFieldName]);
3583
+ };
3042
3584
 
3043
- this._listBindSearch = function(listEl) {
3044
- var $input, arrayStore, cancelSearch, runSearch, showSearch;
3045
- $input = listEl.$search;
3046
- arrayStore = listEl.config.arrayStore;
3047
- runSearch = function(input) {
3048
- var query;
3049
- query = $(input).val();
3050
- listEl._show_spinner();
3051
- return arrayStore.search(query);
3052
- };
3053
- showSearch = function() {
3054
- listEl.$el.addClass('list-search');
3055
- return $input.find('input').focus();
3056
- };
3057
- cancelSearch = function() {
3058
- listEl.$el.removeClass('list-search');
3059
- $input.find('input').val('');
3060
- listEl._show_spinner();
3061
- return arrayStore.reset();
3062
- };
3063
- $input.show();
3064
- $input.on('keyup', 'input', (function(_this) {
3065
- return function(e) {
3066
- if (e.keyCode === 27) {
3067
- return cancelSearch();
3068
- }
3069
- if (e.keyCode === 13) {
3070
- return runSearch(e.target);
3071
- }
3072
- };
3073
- })(this));
3074
- $input.on('click', '.icon', (function(_this) {
3075
- return function(e) {
3076
- e.preventDefault();
3077
- return showSearch();
3078
- };
3079
- })(this));
3080
- return $input.on('click', '.cancel', (function(_this) {
3081
- return function(e) {
3082
- e.preventDefault();
3083
- return cancelSearch();
3084
- };
3085
- })(this));
3086
- };
3585
+ return Item;
3087
3586
 
3088
- this._listBindReorder = function(listEl) {
3089
- var _getObjectNewPosition, arrayStore, config, items, list;
3090
- items = listEl.items;
3091
- list = listEl.$items.get(0);
3092
- arrayStore = listEl.config.arrayStore;
3093
- config = arrayStore.reorderable;
3094
- _getObjectNewPosition = function(el) {
3095
- var $el, newPosition, nextObjectId, nextObjectPosition, prevObjectId, prevObjectPosition;
3096
- $el = $(el);
3097
- nextObjectId = $el.next().attr('data-id');
3098
- prevObjectId = $el.prev().attr('data-id');
3099
- nextObjectPosition = 0;
3100
- prevObjectPosition = 0;
3101
- if (prevObjectId) {
3102
- prevObjectPosition = items[prevObjectId].position();
3103
- }
3104
- if (nextObjectId) {
3105
- nextObjectPosition = items[nextObjectId].position();
3106
- }
3107
- if (arrayStore.sortReverse) {
3108
- newPosition = nextObjectPosition + Math.abs(nextObjectPosition - prevObjectPosition) / 2.0;
3109
- } else {
3110
- newPosition = prevObjectPosition + Math.abs(nextObjectPosition - prevObjectPosition) / 2.0;
3111
- }
3112
- return newPosition;
3113
- };
3114
- new Slip(list);
3115
- list.addEventListener('slip:beforeswipe', function(e) {
3116
- return e.preventDefault();
3117
- });
3118
- list.addEventListener('slip:beforewait', (function(e) {
3119
- if ($(e.target).hasClass("icon-reorder")) {
3120
- return e.preventDefault();
3121
- }
3122
- }), false);
3123
- list.addEventListener('slip:beforereorder', (function(e) {
3124
- if (!$(e.target).hasClass("icon-reorder")) {
3125
- return e.preventDefault();
3126
- }
3127
- }), false);
3128
- list.addEventListener('slip:reorder', ((function(_this) {
3129
- return function(e) {
3130
- var objectId, objectPositionValue, value;
3131
- e.target.parentNode.insertBefore(e.target, e.detail.insertBefore);
3132
- objectPositionValue = _getObjectNewPosition(e.target);
3133
- objectId = $(e.target).attr('data-id');
3134
- value = {};
3135
- value["[" + arrayStore.sortBy] = "" + objectPositionValue;
3136
- arrayStore.update(objectId, value, {
3137
- onSuccess: function(object) {},
3138
- onError: function(errors) {}
3139
- });
3140
- return false;
3141
- };
3142
- })(this)), false);
3143
- return $(list).addClass('reorderable');
3144
- };
3587
+ })();
3145
3588
 
3146
3589
  this.View = (function() {
3147
- function View(module, config, closePath, object1, title1) {
3148
- var ref;
3590
+ function View(module, config, closePath, object, title1) {
3591
+ var ref, ref1;
3149
3592
  this.module = module;
3150
3593
  this.config = config;
3151
3594
  this.closePath = closePath;
3152
- this.object = object1;
3595
+ this.object = object;
3153
3596
  this.title = title1;
3154
3597
  this.store = (ref = this.config.arrayStore) != null ? ref : this.config.objectStore;
3155
- this.$el = $("<section class='view " + this.module.name + "'>");
3156
- this.$el.hide();
3598
+ this.$el = $("<section class='view " + this.module.name + "' style='display:none;'>");
3157
3599
  if (this.config.fullsizeView) {
3158
3600
  this.$el.addClass('fullsize');
3159
3601
  }
3602
+ this.onShowAnimation = this.config.onShowAnimation;
3603
+ this.onCloseAnimation = this.config.onCloseAnimation;
3604
+ if (this.onShowAnimation == null) {
3605
+ this.onShowAnimation = (function(_this) {
3606
+ return function(callback) {
3607
+ return _this.$el.fadeIn($.fx.speeds._default, function() {
3608
+ return callback();
3609
+ });
3610
+ };
3611
+ })(this);
3612
+ }
3613
+ if (this.onCloseAnimation == null) {
3614
+ this.onCloseAnimation = (function(_this) {
3615
+ return function(callback) {
3616
+ return _this.$el.fadeOut($.fx.speeds._default, function() {
3617
+ return callback();
3618
+ });
3619
+ };
3620
+ })(this);
3621
+ }
3160
3622
  this.$header = $("<header></header>");
3161
- this.$el.append(this.$header);
3162
3623
  this.$title = $("<div class='title'></div>");
3163
3624
  this.$header.append(this.$title);
3625
+ this.$el.append(this.$header);
3626
+ this._set_title();
3164
3627
  this.$closeBtn = $("<a href='#/" + this.closePath + "' class='close silent'>Close</a>");
3165
3628
  this.$closeBtn.on('click', (function(_this) {
3166
3629
  return function(e) {
3167
- return _this._on_close(e);
3630
+ return _this._close(e);
3168
3631
  };
3169
3632
  })(this));
3170
3633
  this.$header.append(this.$closeBtn);
@@ -3172,21 +3635,24 @@ this.View = (function() {
3172
3635
  this.$saveBtn = $("<a href='#' class='save'>Save</a>");
3173
3636
  this.$saveBtn.on('click', (function(_this) {
3174
3637
  return function(e) {
3175
- return _this._on_save(e);
3638
+ return _this._save(e);
3176
3639
  };
3177
3640
  })(this));
3178
3641
  this.$header.append(this.$saveBtn);
3179
3642
  }
3180
- this._render();
3643
+ this.form = new ((ref1 = this.config.formClass) != null ? ref1 : Form)(this.object, this.config);
3644
+ this.$el.append(this.form.$el);
3645
+ this._add_form_delete_button();
3181
3646
  }
3182
3647
 
3183
- View.prototype._render = function() {
3184
- this._update_title();
3185
- return this._render_form();
3186
- };
3187
-
3188
- View.prototype._update_title = function() {
3189
- var title, titleText;
3648
+ View.prototype._set_title = function(reset) {
3649
+ var title;
3650
+ if (reset == null) {
3651
+ reset = false;
3652
+ }
3653
+ if (reset && this.config.arrayStore) {
3654
+ this.title = null;
3655
+ }
3190
3656
  title = this.title;
3191
3657
  if (this.config.itemTitleField) {
3192
3658
  if (title == null) {
@@ -3196,353 +3662,134 @@ this.View = (function() {
3196
3662
  if (title == null) {
3197
3663
  title = _firstNonEmptyValue(this.object);
3198
3664
  }
3199
- if (title === "") {
3200
- title = "No Title";
3201
- }
3202
- titleText = $("<div>" + title + "</div>").text();
3203
- return this.$title.html(titleText);
3665
+ return this.$title.html(title.plainText());
3204
3666
  };
3205
3667
 
3206
- View.prototype._render_form = function() {
3207
- var ref;
3208
- if ((ref = this.form) != null) {
3209
- ref.destroy();
3210
- }
3211
- this.form = new Form(this.object, this.config);
3212
- if (!(this.config.disableDelete || this.config.objectStore || this._is_new())) {
3668
+ View.prototype._add_form_delete_button = function() {
3669
+ if (!(this.config.disableDelete || this.config.objectStore || (!this.object))) {
3213
3670
  this.$deleteBtn = $("<a href='#' class='delete'>Delete</a>");
3214
3671
  this.$deleteBtn.on('click', (function(_this) {
3215
3672
  return function(e) {
3216
- return _this._on_delete(e);
3673
+ return _this._delete(e);
3217
3674
  };
3218
3675
  })(this));
3219
- this.form.$el.append(this.$deleteBtn);
3676
+ return this.form.$el.append(this.$deleteBtn);
3220
3677
  }
3221
- return this.$el.append(this.form.$el);
3222
- };
3223
-
3224
- View.prototype._update_object = function(value) {
3225
- this._start_saving();
3226
- return this.store.update(this.object._id, value, {
3227
- onSuccess: (function(_this) {
3228
- return function(object1) {
3229
- var formScrollPosition;
3230
- _this.object = object1;
3231
- if (_this.config.arrayStore) {
3232
- _this.title = null;
3233
- }
3234
- formScrollPosition = _this.form.$el.scrollTop();
3235
- _this._render();
3236
- _this._initialize_form_plugins();
3237
- _this.form.$el.scrollTop(formScrollPosition);
3238
- return _this._stop_saving();
3239
- };
3240
- })(this),
3241
- onError: (function(_this) {
3242
- return function(errors) {
3243
- _this._validation_errors('Changes were not saved.', errors);
3244
- return _this._stop_saving();
3245
- };
3246
- })(this)
3247
- });
3248
- };
3249
-
3250
- View.prototype._create_object = function(value) {
3251
- this._start_saving();
3252
- return this.store.push(value, {
3253
- onSuccess: (function(_this) {
3254
- return function(object) {
3255
- return location.hash = "#/" + _this.closePath + "/view/" + object._id;
3256
- };
3257
- })(this),
3258
- onError: (function(_this) {
3259
- return function(errors) {
3260
- _this._validation_errors('Item were not created.', errors);
3261
- return _this._stop_saving();
3262
- };
3263
- })(this)
3264
- });
3265
- };
3266
-
3267
- View.prototype._start_saving = function() {
3268
- return this.$el.addClass('view-saving');
3269
- };
3270
-
3271
- View.prototype._stop_saving = function() {
3272
- return setTimeout(((function(_this) {
3273
- return function() {
3274
- return _this.$el.removeClass('view-saving');
3275
- };
3276
- })(this)), 250);
3277
3678
  };
3278
3679
 
3279
- View.prototype._initialize_form_plugins = function() {
3280
- var base;
3281
- this.form.initializePlugins();
3282
- return typeof (base = this.config).onViewShow === "function" ? base.onViewShow(this) : void 0;
3680
+ View.prototype._save_success = function() {
3681
+ this.$el.removeClass('view-saving');
3682
+ this._set_title(true);
3683
+ return this.form.updateValues(this.object);
3283
3684
  };
3284
3685
 
3285
- View.prototype._validation_errors = function(message, errors) {
3686
+ View.prototype._save_error = function(message, validationErrors) {
3687
+ this.$el.removeClass('view-saving');
3286
3688
  chr.showError(message);
3287
- return this.form.showValidationErrors(errors);
3288
- };
3289
-
3290
- View.prototype._is_new = function() {
3291
- return !this.object;
3689
+ return this.form.showValidationErrors(validationErrors);
3292
3690
  };
3293
3691
 
3294
- View.prototype._on_close = function(e) {
3295
- return this.$el.fadeOut($.fx.speeds._default, (function(_this) {
3692
+ View.prototype._close = function(e) {
3693
+ return this.onCloseAnimation((function(_this) {
3296
3694
  return function() {
3297
3695
  return _this.destroy();
3298
3696
  };
3299
3697
  })(this));
3300
3698
  };
3301
3699
 
3302
- View.prototype._on_save = function(e) {
3700
+ View.prototype._save = function(e) {
3303
3701
  var serializedFormObj;
3304
3702
  e.preventDefault();
3703
+ this.$el.addClass('view-saving');
3305
3704
  serializedFormObj = this.form.serialize();
3306
3705
  if (this.object) {
3307
- return this._update_object(serializedFormObj);
3308
- } else {
3309
- return this._create_object(serializedFormObj);
3310
- }
3311
- };
3312
-
3313
- View.prototype._on_delete = function(e) {
3314
- e.preventDefault();
3315
- if (confirm("Are you sure?")) {
3316
- this.store.remove(this.object._id);
3317
- return this.$el.fadeOut($.fx.speeds._default, (function(_this) {
3318
- return function() {
3319
- window._skipHashchange = true;
3320
- location.hash = "#/" + _this.closePath;
3321
- return _this.destroy();
3322
- };
3323
- })(this));
3324
- }
3325
- };
3326
-
3327
- View.prototype.show = function(animate, callback) {
3328
- if (animate) {
3329
- return this.$el.fadeIn($.fx.speeds._default, (function(_this) {
3330
- return function() {
3331
- _this._initialize_form_plugins();
3332
- return typeof callback === "function" ? callback() : void 0;
3333
- };
3334
- })(this));
3335
- } else {
3336
- return this.$el.show(0, (function(_this) {
3337
- return function() {
3338
- _this._initialize_form_plugins();
3339
- return typeof callback === "function" ? callback() : void 0;
3340
- };
3341
- })(this));
3342
- }
3343
- };
3344
-
3345
- View.prototype.destroy = function() {
3346
- var ref;
3347
- if ((ref = this.form) != null) {
3348
- ref.destroy();
3349
- }
3350
- return this.$el.remove();
3351
- };
3352
-
3353
- return View;
3354
-
3355
- })();
3356
-
3357
- this.Module = (function() {
3358
- function Module(chr1, name, config1) {
3359
- var base, firstNestedList, menuPath, menuTitle, ref;
3360
- this.chr = chr1;
3361
- this.name = name;
3362
- this.config = config1;
3363
- this.nestedLists = {};
3364
- this.$el = $("<section class='module " + this.name + "' style='display: none;'>");
3365
- this.chr.$el.append(this.$el);
3366
- this.activeList = this.rootList = new List(this, this.name, this.config);
3367
- menuTitle = (ref = this.config.menuTitle) != null ? ref : this.config.title;
3368
- if (menuTitle == null) {
3369
- menuTitle = this.name.titleize();
3370
- }
3371
- menuPath = this.name;
3372
- if (this.config.showNestedListsAside) {
3373
- this.$el.addClass('first-list-aside');
3374
- firstNestedList = _firstNonEmptyValue(this.nestedLists);
3375
- if (!_isMobile() && firstNestedList) {
3376
- menuPath += "/" + firstNestedList.name;
3377
- }
3378
- }
3379
- this.chr.addMenuItem(menuPath, menuTitle);
3380
- if (typeof (base = this.config).onModuleInit === "function") {
3381
- base.onModuleInit(this);
3382
- }
3383
- }
3384
-
3385
- Module.prototype._update_active_list_items = function() {
3386
- if (!this.activeList.isVisible()) {
3387
- return this.activeList.updateItems();
3388
- }
3389
- };
3390
-
3391
- Module.prototype._view_path = function() {
3392
- var currentList, ref;
3393
- currentList = (ref = this.visibleNestedListShownWithParent()) != null ? ref : this.activeList;
3394
- return currentList.path;
3395
- };
3396
-
3397
- Module.prototype.addNestedList = function(listName, config, parentList) {
3398
- return this.nestedLists[listName] = new List(this, listName, config, parentList);
3399
- };
3400
-
3401
- Module.prototype.hideActiveList = function(animate) {
3402
- if (animate == null) {
3403
- animate = false;
3404
- }
3405
- if (animate) {
3406
- this.activeList.$el.fadeOut();
3407
- } else {
3408
- this.activeList.$el.hide();
3409
- }
3410
- return this.activeList = this.activeList.parentList;
3411
- };
3412
-
3413
- Module.prototype.showView = function(object, config, title, animate) {
3414
- var newView;
3415
- if (animate == null) {
3416
- animate = false;
3417
- }
3418
- newView = new View(this, config, this._view_path(), object, title);
3419
- this.chr.$el.append(newView.$el);
3420
- return newView.show(animate, (function(_this) {
3421
- return function() {
3422
- _this.destroyView();
3423
- return _this.view = newView;
3424
- };
3425
- })(this));
3426
- };
3427
-
3428
- Module.prototype.showViewByObjectId = function(objectId, config, title, animate) {
3429
- var onError, onSuccess;
3430
- if (animate == null) {
3431
- animate = false;
3432
- }
3433
- onSuccess = (function(_this) {
3434
- return function(object) {
3435
- return _this.showView(object, config, title, animate);
3436
- };
3437
- })(this);
3438
- onError = function() {
3439
- return chr.showError("can\'t show view for requested object");
3440
- };
3441
- if (objectId === '') {
3442
- return config.objectStore.loadObject({
3443
- onSuccess: onSuccess,
3444
- onError: onError
3445
- });
3446
- } else {
3447
- return config.arrayStore.loadObject(objectId, {
3448
- onSuccess: onSuccess,
3449
- onError: onError
3450
- });
3451
- }
3452
- };
3453
-
3454
- Module.prototype.destroyView = function() {
3455
- var ref;
3456
- return (ref = this.view) != null ? ref.destroy() : void 0;
3457
- };
3458
-
3459
- Module.prototype.show = function() {
3460
- this._update_active_list_items();
3461
- this.$el.show();
3462
- return this.activeList.show(false);
3463
- };
3464
-
3465
- Module.prototype.hide = function(animate) {
3466
- if (animate == null) {
3467
- animate = false;
3468
- }
3469
- this.hideNestedLists();
3470
- if (animate) {
3471
- if (this.view) {
3472
- this.view.$el.fadeOut($.fx.speeds._default, (function(_this) {
3473
- return function() {
3474
- return _this.destroyView();
3475
- };
3476
- })(this));
3477
- }
3478
- return this.$el.fadeOut();
3706
+ return this.store.update(this.object._id, serializedFormObj, {
3707
+ onSuccess: (function(_this) {
3708
+ return function(object) {
3709
+ _this.object = object;
3710
+ return _this._save_success();
3711
+ };
3712
+ })(this),
3713
+ onError: (function(_this) {
3714
+ return function(errors) {
3715
+ return _this._save_error('Changes were not saved.', errors);
3716
+ };
3717
+ })(this)
3718
+ });
3479
3719
  } else {
3480
- this.destroyView();
3481
- return this.$el.hide();
3720
+ return this.store.push(serializedFormObj, {
3721
+ onSuccess: (function(_this) {
3722
+ return function(object) {
3723
+ _this.object = object;
3724
+ _this._save_success();
3725
+ _this._add_form_delete_button();
3726
+ return chr.updateHash("#/" + _this.closePath + "/view/" + _this.object._id, true);
3727
+ };
3728
+ })(this),
3729
+ onError: (function(_this) {
3730
+ return function(errors) {
3731
+ return _this._save_error('Item were not created.', errors);
3732
+ };
3733
+ })(this)
3734
+ });
3482
3735
  }
3483
3736
  };
3484
3737
 
3485
- Module.prototype.showNestedList = function(listName, animate) {
3486
- var listToShow;
3487
- if (animate == null) {
3488
- animate = false;
3738
+ View.prototype._delete = function(e) {
3739
+ e.preventDefault();
3740
+ if (confirm("Are you sure?")) {
3741
+ return this.store.remove(this.object._id, {
3742
+ onSuccess: (function(_this) {
3743
+ return function() {
3744
+ return _this.onCloseAnimation(function() {
3745
+ chr.updateHash("#/" + _this.closePath, true);
3746
+ return _this.destroy();
3747
+ });
3748
+ };
3749
+ })(this),
3750
+ onError: function() {
3751
+ return chr.showError('Can\'t delete object.');
3752
+ }
3753
+ });
3489
3754
  }
3490
- listToShow = this.nestedLists[listName];
3491
- if (listToShow.showWithParent) {
3492
- listToShow.updateItems();
3493
- listToShow.show(animate, (function(_this) {
3755
+ };
3756
+
3757
+ View.prototype.show = function(animate, callback) {
3758
+ var after_show;
3759
+ after_show = (function(_this) {
3760
+ return function() {
3761
+ var base;
3762
+ if (typeof callback === "function") {
3763
+ callback();
3764
+ }
3765
+ _this.form.initializePlugins();
3766
+ return typeof (base = _this.config).onViewShow === "function" ? base.onViewShow(_this) : void 0;
3767
+ };
3768
+ })(this);
3769
+ if (animate) {
3770
+ return this.onShowAnimation((function(_this) {
3494
3771
  return function() {
3495
- var exceptList;
3496
- return _this.hideNestedLists(exceptList = listName);
3772
+ return after_show();
3497
3773
  };
3498
3774
  })(this));
3499
3775
  } else {
3500
- this.activeList = listToShow;
3501
- this._update_active_list_items();
3502
- this.activeList.show(animate);
3503
- }
3504
- if (animate && this.view) {
3505
- return this.view.$el.fadeOut($.fx.speeds._default, (function(_this) {
3776
+ return this.$el.show(0, (function(_this) {
3506
3777
  return function() {
3507
- return _this.destroyView();
3778
+ return after_show();
3508
3779
  };
3509
3780
  })(this));
3510
3781
  }
3511
3782
  };
3512
3783
 
3513
- Module.prototype.hideNestedLists = function(exceptList) {
3514
- var key, list, ref, results;
3515
- this.activeList = this.rootList;
3516
- ref = this.nestedLists;
3517
- results = [];
3518
- for (key in ref) {
3519
- list = ref[key];
3520
- if (key !== exceptList) {
3521
- results.push(list.hide());
3522
- }
3523
- }
3524
- return results;
3525
- };
3526
-
3527
- Module.prototype.visibleNestedListShownWithParent = function() {
3528
- var key, list, ref;
3529
- ref = this.nestedLists;
3530
- for (key in ref) {
3531
- list = ref[key];
3532
- if (list.isVisible() && list.showWithParent) {
3533
- return list;
3534
- }
3535
- }
3784
+ View.prototype.destroy = function() {
3785
+ this.form.destroy();
3786
+ return this.$el.remove();
3536
3787
  };
3537
3788
 
3538
- return Module;
3789
+ return View;
3539
3790
 
3540
3791
  })();
3541
3792
 
3542
- if (this._chrFormInputs == null) {
3543
- this._chrFormInputs = {};
3544
- }
3545
-
3546
3793
  this.Form = (function() {
3547
3794
  function Form(object1, config1) {
3548
3795
  this.object = object1;
@@ -3550,35 +3797,35 @@ this.Form = (function() {
3550
3797
  this.groups = [];
3551
3798
  this.inputs = {};
3552
3799
  this.$el = $(this.config.rootEl || '<form>');
3553
- this.schema = this._getSchema();
3800
+ this.schema = this._get_schema();
3554
3801
  this.isRemoved = false;
3555
- this._buildSchema(this.schema, this.$el);
3556
- this._addNestedFormRemoveButton();
3802
+ this._build_schema(this.schema, this.$el);
3803
+ this._add_nested_form_remove_button();
3557
3804
  }
3558
3805
 
3559
- Form.prototype._getSchema = function() {
3806
+ Form.prototype._get_schema = function() {
3560
3807
  var schema;
3561
3808
  schema = this.config.formSchema;
3562
3809
  if (this.object) {
3563
3810
  if (schema == null) {
3564
- schema = this._generateDefaultSchema();
3811
+ schema = this._generate_default_schema();
3565
3812
  }
3566
3813
  }
3567
3814
  return schema;
3568
3815
  };
3569
3816
 
3570
- Form.prototype._generateDefaultSchema = function() {
3817
+ Form.prototype._generate_default_schema = function() {
3571
3818
  var key, ref, schema, value;
3572
3819
  schema = {};
3573
3820
  ref = this.object;
3574
3821
  for (key in ref) {
3575
3822
  value = ref[key];
3576
- schema[key] = this._generateDefaultInputConfig(key, value);
3823
+ schema[key] = this._generate_default_input_config(key, value);
3577
3824
  }
3578
3825
  return schema;
3579
3826
  };
3580
3827
 
3581
- Form.prototype._generateDefaultInputConfig = function(fieldName, value) {
3828
+ Form.prototype._generate_default_input_config = function(fieldName, value) {
3582
3829
  var config;
3583
3830
  config = {};
3584
3831
  if (fieldName[0] === '_') {
@@ -3595,27 +3842,27 @@ this.Form = (function() {
3595
3842
  return config;
3596
3843
  };
3597
3844
 
3598
- Form.prototype._buildSchema = function(schema, $el) {
3845
+ Form.prototype._build_schema = function(schema, $el) {
3599
3846
  var config, fieldName, group, input, results;
3600
3847
  results = [];
3601
3848
  for (fieldName in schema) {
3602
3849
  config = schema[fieldName];
3603
3850
  if (config.type === 'group') {
3604
- group = this._generateInputsGroup(fieldName, config);
3851
+ group = this._generate_inputs_group(fieldName, config);
3605
3852
  results.push($el.append(group.$el));
3606
3853
  } else {
3607
- input = this._generateInput(fieldName, config);
3854
+ input = this._generate_input(fieldName, config);
3608
3855
  results.push($el.append(input.$el));
3609
3856
  }
3610
3857
  }
3611
3858
  return results;
3612
3859
  };
3613
3860
 
3614
- Form.prototype._generateInputsGroup = function(klassName, groupConfig) {
3861
+ Form.prototype._generate_inputs_group = function(klassName, groupConfig) {
3615
3862
  var $group, group;
3616
3863
  $group = $("<div class='group " + klassName + "' />");
3617
3864
  if (groupConfig.inputs) {
3618
- this._buildSchema(groupConfig.inputs, $group);
3865
+ this._build_schema(groupConfig.inputs, $group);
3619
3866
  }
3620
3867
  group = {
3621
3868
  $el: $group,
@@ -3626,7 +3873,7 @@ this.Form = (function() {
3626
3873
  return group;
3627
3874
  };
3628
3875
 
3629
- Form.prototype._generateInput = function(fieldName, inputConfig) {
3876
+ Form.prototype._generate_input = function(fieldName, inputConfig) {
3630
3877
  var input, inputName, value;
3631
3878
  if (this.object) {
3632
3879
  value = this.object[fieldName];
@@ -3637,16 +3884,16 @@ this.Form = (function() {
3637
3884
  value = '';
3638
3885
  }
3639
3886
  inputName = inputConfig.name || fieldName;
3640
- input = this._renderInput(inputName, inputConfig, value);
3887
+ input = this._render_input(inputName, inputConfig, value);
3641
3888
  this.inputs[fieldName] = input;
3642
3889
  return input;
3643
3890
  };
3644
3891
 
3645
- Form.prototype._renderInput = function(name, config, value) {
3892
+ Form.prototype._render_input = function(name, config, value) {
3646
3893
  var inputClass, inputConfig, inputName;
3647
3894
  inputConfig = $.extend({}, config);
3648
3895
  if (inputConfig.label == null) {
3649
- inputConfig.label = this._titleizeLabel(name);
3896
+ inputConfig.label = name.titleize();
3650
3897
  }
3651
3898
  if (inputConfig.type == null) {
3652
3899
  inputConfig.type = 'string';
@@ -3655,9 +3902,9 @@ this.Form = (function() {
3655
3902
  inputConfig.klass = 'stacked';
3656
3903
  }
3657
3904
  inputConfig.klassName = name;
3658
- inputClass = _chrFormInputs[inputConfig.type];
3905
+ inputClass = chr.formInputs[inputConfig.type];
3659
3906
  if (inputClass == null) {
3660
- inputClass = _chrFormInputs['string'];
3907
+ inputClass = chr.formInputs['string'];
3661
3908
  }
3662
3909
  inputName = this.config.namePrefix ? this.config.namePrefix + "[" + name + "]" : "[" + name + "]";
3663
3910
  if (inputConfig.type === 'form') {
@@ -3668,15 +3915,11 @@ this.Form = (function() {
3668
3915
  return new inputClass(inputName, value, inputConfig, this.object);
3669
3916
  };
3670
3917
 
3671
- Form.prototype._titleizeLabel = function(value) {
3672
- return value.titleize().replace('Id', 'ID');
3673
- };
3674
-
3675
- Form.prototype._addNestedFormRemoveButton = function() {
3918
+ Form.prototype._add_nested_form_remove_button = function() {
3676
3919
  var fieldName, input;
3677
3920
  if (this.config.removeButton) {
3678
3921
  fieldName = '_destroy';
3679
- input = this._renderInput(fieldName, {
3922
+ input = this._render_input(fieldName, {
3680
3923
  type: 'hidden'
3681
3924
  }, false);
3682
3925
  this.inputs[fieldName] = input;
@@ -3730,6 +3973,21 @@ this.Form = (function() {
3730
3973
  };
3731
3974
 
3732
3975
  Form.prototype.destroy = function() {
3976
+ var group, i, input, len, name, ref, ref1;
3977
+ ref = this.groups;
3978
+ for (i = 0, len = ref.length; i < len; i++) {
3979
+ group = ref[i];
3980
+ if (typeof group.destroy === "function") {
3981
+ group.destroy();
3982
+ }
3983
+ }
3984
+ ref1 = this.inputs;
3985
+ for (name in ref1) {
3986
+ input = ref1[name];
3987
+ if (typeof input.destroy === "function") {
3988
+ input.destroy();
3989
+ }
3990
+ }
3733
3991
  return this.$el.remove();
3734
3992
  };
3735
3993
 
@@ -3752,7 +4010,7 @@ this.Form = (function() {
3752
4010
  if (input.config.type === 'file' || input.config.type === 'image') {
3753
4011
  file = input.$input.get()[0].files[0];
3754
4012
  obj["__FILE__" + input.name] = file;
3755
- if (!file && !input.filename) {
4013
+ if (input.isEmpty()) {
3756
4014
  obj[input.removeName()] = 'true';
3757
4015
  }
3758
4016
  }
@@ -3820,57 +4078,294 @@ this.Form = (function() {
3820
4078
  input = ref[inputName];
3821
4079
  results.push(input.hideErrorMessage());
3822
4080
  }
3823
- return results;
4081
+ return results;
4082
+ };
4083
+
4084
+ Form.prototype.updateValues = function(object) {
4085
+ var name, results, value;
4086
+ results = [];
4087
+ for (name in object) {
4088
+ value = object[name];
4089
+ if (this.inputs[name]) {
4090
+ results.push(this.inputs[name].updateValue(value, object));
4091
+ } else {
4092
+ results.push(void 0);
4093
+ }
4094
+ }
4095
+ return results;
4096
+ };
4097
+
4098
+ return Form;
4099
+
4100
+ })();
4101
+
4102
+ this.inputFormReorder = {
4103
+ _bind_forms_reorder: function() {
4104
+ var form, i, len, list, ref, results;
4105
+ if (this.config.sortBy) {
4106
+ list = this.$forms.addClass(this.reorderContainerClass).get(0);
4107
+ new Slip(list);
4108
+ list.addEventListener('slip:beforeswipe', function(e) {
4109
+ return e.preventDefault();
4110
+ });
4111
+ list.addEventListener('slip:beforewait', (function(e) {
4112
+ if ($(e.target).hasClass("icon-reorder")) {
4113
+ return e.preventDefault();
4114
+ }
4115
+ }), false);
4116
+ list.addEventListener('slip:beforereorder', (function(e) {
4117
+ if (!$(e.target).hasClass("icon-reorder")) {
4118
+ return e.preventDefault();
4119
+ }
4120
+ }), false);
4121
+ list.addEventListener('slip:reorder', ((function(_this) {
4122
+ return function(e) {
4123
+ var $targetForm, newTargetFormPosition, nextForm, nextFormPosition, prevForm, prevFormPosition, targetForm;
4124
+ targetForm = _this._find_form_by_target(e.target);
4125
+ if (targetForm) {
4126
+ e.target.parentNode.insertBefore(e.target, e.detail.insertBefore);
4127
+ $targetForm = $(e.target);
4128
+ prevForm = _this._find_form_by_target($targetForm.prev().get(0));
4129
+ nextForm = _this._find_form_by_target($targetForm.next().get(0));
4130
+ prevFormPosition = prevForm ? prevForm.inputs[_this.config.sortBy].value : 0;
4131
+ nextFormPosition = nextForm ? nextForm.inputs[_this.config.sortBy].value : 0;
4132
+ newTargetFormPosition = prevFormPosition + Math.abs(nextFormPosition - prevFormPosition) / 2.0;
4133
+ targetForm.inputs[_this.config.sortBy].updateValue(newTargetFormPosition);
4134
+ }
4135
+ return false;
4136
+ };
4137
+ })(this)), false);
4138
+ ref = this.forms;
4139
+ results = [];
4140
+ for (i = 0, len = ref.length; i < len; i++) {
4141
+ form = ref[i];
4142
+ results.push(this._add_form_reorder_button(form));
4143
+ }
4144
+ return results;
4145
+ }
4146
+ },
4147
+ _add_form_reorder_button: function(form) {
4148
+ return form.$el.append("<div class='icon-reorder' data-container-class='" + this.reorderContainerClass + "'></div>").addClass('reorderable');
4149
+ },
4150
+ _find_form_by_target: function(el) {
4151
+ var form, i, len, ref;
4152
+ if (el) {
4153
+ ref = this.forms;
4154
+ for (i = 0, len = ref.length; i < len; i++) {
4155
+ form = ref[i];
4156
+ if (form.$el.get(0) === el) {
4157
+ return form;
4158
+ }
4159
+ }
4160
+ }
4161
+ return null;
4162
+ }
4163
+ };
4164
+
4165
+ this.InputForm = (function() {
4166
+ function InputForm(name1, nestedObjects, config1, object1) {
4167
+ var base;
4168
+ this.name = name1;
4169
+ this.nestedObjects = nestedObjects;
4170
+ this.config = config1;
4171
+ this.object = object1;
4172
+ this.forms = [];
4173
+ (base = this.config).namePrefix || (base.namePrefix = name);
4174
+ this.config.removeButton = true;
4175
+ this.config.formSchema._id = {
4176
+ type: 'hidden',
4177
+ name: 'id'
4178
+ };
4179
+ this.reorderContainerClass = "nested-forms-" + this.config.klassName;
4180
+ this._create_el();
4181
+ this._add_label();
4182
+ this._add_forms();
4183
+ this._add_new_button();
4184
+ return this;
4185
+ }
4186
+
4187
+ InputForm.prototype._create_el = function() {
4188
+ return this.$el = $("<div class='input-stacked nested-forms " + this.config.klassName + "'>");
4189
+ };
4190
+
4191
+ InputForm.prototype._add_label = function() {
4192
+ this.$label = $("<span class='label'>" + this.config.label + "</span>");
4193
+ this.$errorMessage = $("<span class='error-message'></span>");
4194
+ this.$label.append(this.$errorMessage);
4195
+ return this.$el.append(this.$label);
4196
+ };
4197
+
4198
+ InputForm.prototype._add_forms = function() {
4199
+ var i, namePrefix, object, ref;
4200
+ this.$forms = $("<ul>");
4201
+ this.$label.after(this.$forms);
4202
+ if (this.nestedObjects !== '') {
4203
+ this._sort_nested_objects();
4204
+ ref = this.nestedObjects;
4205
+ for (i in ref) {
4206
+ object = ref[i];
4207
+ namePrefix = this.config.namePrefix + "[" + i + "]";
4208
+ this.forms.push(this._render_form(object, namePrefix, this.config));
4209
+ }
4210
+ return this._bind_forms_reorder();
4211
+ }
4212
+ };
4213
+
4214
+ InputForm.prototype._sort_nested_objects = function() {
4215
+ var i, o, ref, results;
4216
+ if (this.config.sortBy) {
4217
+ this.config.formSchema[this.config.sortBy] = {
4218
+ type: 'hidden'
4219
+ };
4220
+ if (this.nestedObjects) {
4221
+ this.nestedObjects.sort((function(_this) {
4222
+ return function(a, b) {
4223
+ return parseFloat(a[_this.config.sortBy]) - parseFloat(b[_this.config.sortBy]);
4224
+ };
4225
+ })(this));
4226
+ ref = this.nestedObjects;
4227
+ results = [];
4228
+ for (i in ref) {
4229
+ o = ref[i];
4230
+ results.push(o[this.config.sortBy] = parseInt(i) + 1);
4231
+ }
4232
+ return results;
4233
+ }
4234
+ }
4235
+ };
4236
+
4237
+ InputForm.prototype._render_form = function(object, namePrefix, config) {
4238
+ var form, formConfig;
4239
+ formConfig = $.extend({}, config, {
4240
+ namePrefix: namePrefix,
4241
+ rootEl: "<li>"
4242
+ });
4243
+ form = new Form(object, formConfig);
4244
+ this.$forms.append(form.$el);
4245
+ return form;
4246
+ };
4247
+
4248
+ InputForm.prototype._add_new_button = function() {
4249
+ var label;
4250
+ label = this.config.newButtonLabel || "Add";
4251
+ this.$newButton = $("<a href='#' class='nested-form-new'>" + label + "</a>");
4252
+ this.$el.append(this.$newButton);
4253
+ return this.$newButton.on('click', (function(_this) {
4254
+ return function(e) {
4255
+ e.preventDefault();
4256
+ return _this.addNewForm();
4257
+ };
4258
+ })(this));
4259
+ };
4260
+
4261
+ InputForm.prototype.initialize = function() {
4262
+ var base, j, len, nestedForm, ref;
4263
+ ref = this.forms;
4264
+ for (j = 0, len = ref.length; j < len; j++) {
4265
+ nestedForm = ref[j];
4266
+ nestedForm.initializePlugins();
4267
+ }
4268
+ return typeof (base = this.config).onInitialize === "function" ? base.onInitialize(this) : void 0;
4269
+ };
4270
+
4271
+ InputForm.prototype.hash = function(hash) {
4272
+ var form, j, len, ref;
4273
+ if (hash == null) {
4274
+ hash = {};
4275
+ }
4276
+ hash[this.config.klassName] = [];
4277
+ ref = this.forms;
4278
+ for (j = 0, len = ref.length; j < len; j++) {
4279
+ form = ref[j];
4280
+ hash[this.config.klassName].push(form.hash());
4281
+ }
4282
+ return hash;
4283
+ };
4284
+
4285
+ InputForm.prototype.showErrorMessage = function(message) {
4286
+ this.$el.addClass('error');
4287
+ return this.$errorMessage.html(message);
4288
+ };
4289
+
4290
+ InputForm.prototype.hideErrorMessage = function() {
4291
+ this.$el.removeClass('error');
4292
+ return this.$errorMessage.html('');
4293
+ };
4294
+
4295
+ InputForm.prototype.addNewForm = function(object) {
4296
+ var base, form, namePrefix, newFormConfig, position, prevForm;
4297
+ if (object == null) {
4298
+ object = null;
4299
+ }
4300
+ namePrefix = this.config.namePrefix + "[" + (Date.now()) + "]";
4301
+ newFormConfig = $.extend({}, this.config);
4302
+ delete newFormConfig.formSchema._id;
4303
+ form = this._render_form(object, namePrefix, newFormConfig);
4304
+ form.initializePlugins();
4305
+ if (this.config.sortBy) {
4306
+ this._add_form_reorder_button(form);
4307
+ prevForm = _last(this.forms);
4308
+ position = prevForm ? prevForm.inputs[this.config.sortBy].value + 1 : 1;
4309
+ form.inputs[this.config.sortBy].updateValue(position);
4310
+ }
4311
+ this.forms.push(form);
4312
+ if (typeof (base = this.config).onNew === "function") {
4313
+ base.onNew(form);
4314
+ }
4315
+ return form;
3824
4316
  };
3825
4317
 
3826
- Form.prototype.updateValues = function(object) {
3827
- var name, results, value;
3828
- results = [];
3829
- for (name in object) {
3830
- value = object[name];
3831
- if (this.inputs[name]) {
3832
- results.push(this.inputs[name].updateValue(value, object));
3833
- } else {
3834
- results.push(void 0);
3835
- }
3836
- }
3837
- return results;
4318
+ InputForm.prototype.updateValue = function(nestedObjects, object1) {
4319
+ this.nestedObjects = nestedObjects;
4320
+ this.object = object1;
4321
+ this.$forms.remove();
4322
+ this.forms = [];
4323
+ return this._add_forms();
3838
4324
  };
3839
4325
 
3840
- return Form;
4326
+ return InputForm;
3841
4327
 
3842
4328
  })();
3843
4329
 
4330
+ include(InputForm, inputFormReorder);
4331
+
4332
+ chr.formInputs['form'] = InputForm;
4333
+
3844
4334
  this.InputString = (function() {
3845
4335
  function InputString(name, value, config, object) {
3846
4336
  this.name = name;
3847
4337
  this.value = value;
3848
4338
  this.config = config;
3849
4339
  this.object = object;
3850
- this._createEl();
3851
- this._addLabel();
3852
- this._addInput();
3853
- this._addPlaceholder();
4340
+ this._create_el();
4341
+ this._add_label();
4342
+ this._add_input();
4343
+ this._add_placeholder();
3854
4344
  return this;
3855
4345
  }
3856
4346
 
3857
- InputString.prototype._createEl = function() {
4347
+ InputString.prototype._safe_value = function() {
4348
+ if (typeof this.value === 'object') {
4349
+ return JSON.stringify(this.value);
4350
+ } else {
4351
+ return _escapeHtml(this.value);
4352
+ }
4353
+ };
4354
+
4355
+ InputString.prototype._create_el = function() {
3858
4356
  return this.$el = $("<label for='" + this.name + "' class='input-" + this.config.type + " input-" + this.config.klass + " " + this.config.klassName + "'>");
3859
4357
  };
3860
4358
 
3861
- InputString.prototype._addLabel = function() {
3862
- var ref;
3863
- if ((ref = this.config.klass) === 'inline' || ref === 'stacked') {
3864
- this.$label = $("<span class='label'>" + this.config.label + "</span>");
3865
- this.$el.append(this.$label);
3866
- this.$errorMessage = $("<span class='error-message'></span>");
3867
- return this.$label.append(this.$errorMessage);
3868
- }
4359
+ InputString.prototype._add_label = function() {
4360
+ this.$label = $("<span class='label'>" + this.config.label + "</span>");
4361
+ this.$errorMessage = $("<span class='error-message'></span>");
4362
+ this.$label.append(this.$errorMessage);
4363
+ return this.$el.append(this.$label);
3869
4364
  };
3870
4365
 
3871
- InputString.prototype._addInput = function() {
4366
+ InputString.prototype._add_input = function() {
3872
4367
  var data;
3873
- this.$input = $("<input type='text' name='" + this.name + "' value='" + (this._valueSafe()) + "' id='" + this.name + "' />");
4368
+ this.$input = $("<input type='text' name='" + this.name + "' value='" + (this._safe_value()) + "' />");
3874
4369
  this.$el.append(this.$input);
3875
4370
  if (this.config.options && $.isArray(this.config.options)) {
3876
4371
  data = new Bloodhound({
@@ -3895,15 +4390,7 @@ this.InputString = (function() {
3895
4390
  }
3896
4391
  };
3897
4392
 
3898
- InputString.prototype._valueSafe = function() {
3899
- if (typeof this.value === 'object') {
3900
- return JSON.stringify(this.value);
3901
- } else {
3902
- return _escapeHtml(this.value);
3903
- }
3904
- };
3905
-
3906
- InputString.prototype._addPlaceholder = function() {
4393
+ InputString.prototype._add_placeholder = function() {
3907
4394
  var ref;
3908
4395
  if ((ref = this.config.klass) === 'placeholder' || ref === 'stacked') {
3909
4396
  this.$input.attr('placeholder', this.config.label);
@@ -3945,7 +4432,57 @@ this.InputString = (function() {
3945
4432
 
3946
4433
  })();
3947
4434
 
3948
- _chrFormInputs['string'] = InputString;
4435
+ chr.formInputs['string'] = InputString;
4436
+
4437
+ this.InputHidden = (function() {
4438
+ function InputHidden(name, value, config, object) {
4439
+ this.name = name;
4440
+ this.value = value;
4441
+ this.config = config;
4442
+ this.object = object;
4443
+ this._create_el();
4444
+ return this;
4445
+ }
4446
+
4447
+ InputHidden.prototype._create_el = function() {
4448
+ return this.$el = $("<input type='hidden' name='" + this.name + "' value='" + (this._safe_value()) + "' />");
4449
+ };
4450
+
4451
+ InputHidden.prototype._safe_value = function() {
4452
+ if (typeof this.value === 'object') {
4453
+ return JSON.stringify(this.value);
4454
+ } else {
4455
+ return _escapeHtml(this.value);
4456
+ }
4457
+ };
4458
+
4459
+ InputHidden.prototype.initialize = function() {
4460
+ var base;
4461
+ return typeof (base = this.config).onInitialize === "function" ? base.onInitialize(this) : void 0;
4462
+ };
4463
+
4464
+ InputHidden.prototype.updateValue = function(value) {
4465
+ this.value = value;
4466
+ return this.$el.val(this._safe_value());
4467
+ };
4468
+
4469
+ InputHidden.prototype.hash = function(hash) {
4470
+ if (hash == null) {
4471
+ hash = {};
4472
+ }
4473
+ hash[this.config.klassName] = this.$el.val();
4474
+ return hash;
4475
+ };
4476
+
4477
+ InputHidden.prototype.showErrorMessage = function(message) {};
4478
+
4479
+ InputHidden.prototype.hideErrorMessage = function() {};
4480
+
4481
+ return InputHidden;
4482
+
4483
+ })();
4484
+
4485
+ chr.formInputs['hidden'] = InputHidden;
3949
4486
 
3950
4487
  var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
3951
4488
  hasProp = {}.hasOwnProperty;
@@ -3953,7 +4490,22 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
3953
4490
  this.InputCheckbox = (function(superClass) {
3954
4491
  extend(InputCheckbox, superClass);
3955
4492
 
3956
- InputCheckbox.prototype._safeValue = function() {
4493
+ function InputCheckbox(name, value, config, object) {
4494
+ this.name = name;
4495
+ this.value = value;
4496
+ this.config = config;
4497
+ this.object = object;
4498
+ this._create_el();
4499
+ this._add_input();
4500
+ this._add_label();
4501
+ return this;
4502
+ }
4503
+
4504
+ InputCheckbox.prototype._create_el = function() {
4505
+ return this.$el = $("<label for='" + this.name + "' class='input-" + this.config.type + " input-" + this.config.klass + " " + this.config.klassName + "'>");
4506
+ };
4507
+
4508
+ InputCheckbox.prototype._safe_value = function() {
3957
4509
  if (!this.value || this.value === 'false' || this.value === 0 || this.value === '0') {
3958
4510
  return false;
3959
4511
  } else {
@@ -3961,27 +4513,16 @@ this.InputCheckbox = (function(superClass) {
3961
4513
  }
3962
4514
  };
3963
4515
 
3964
- InputCheckbox.prototype._addInput = function() {
4516
+ InputCheckbox.prototype._add_input = function() {
3965
4517
  this.$false_hidden_input = $("<input type='hidden' name='" + this.name + "' value='false' />");
3966
4518
  this.$el.append(this.$false_hidden_input);
3967
- this.$input = $("<input type='checkbox' name='" + this.name + "' id='" + this.name + "' value='true' " + (this._safeValue() ? 'checked' : '') + " />");
4519
+ this.$input = $("<input type='checkbox' id='" + this.name + "' name='" + this.name + "' value='true' " + (this._safe_value() ? 'checked' : '') + " />");
3968
4520
  return this.$el.append(this.$input);
3969
4521
  };
3970
4522
 
3971
- function InputCheckbox(name, value, config, object) {
3972
- this.name = name;
3973
- this.value = value;
3974
- this.config = config;
3975
- this.object = object;
3976
- this.$el = $("<label for='" + this.name + "' class='input-" + this.config.type + " input-" + this.config.klass + " " + this.config.klassName + "'>");
3977
- this._addInput();
3978
- this._addLabel();
3979
- return this;
3980
- }
3981
-
3982
4523
  InputCheckbox.prototype.updateValue = function(value) {
3983
4524
  this.value = value;
3984
- return this.$input.prop('checked', this._safeValue());
4525
+ return this.$input.prop('checked', this._safe_value());
3985
4526
  };
3986
4527
 
3987
4528
  InputCheckbox.prototype.hash = function(hash) {
@@ -3996,38 +4537,31 @@ this.InputCheckbox = (function(superClass) {
3996
4537
 
3997
4538
  })(InputString);
3998
4539
 
3999
- _chrFormInputs['checkbox'] = InputCheckbox;
4540
+ chr.formInputs['checkbox'] = InputCheckbox;
4000
4541
 
4001
4542
  this.InputCheckboxSwitch = (function(superClass) {
4002
4543
  extend(InputCheckboxSwitch, superClass);
4003
4544
 
4004
- InputCheckboxSwitch.prototype._addInput = function() {
4545
+ function InputCheckboxSwitch() {
4546
+ return InputCheckboxSwitch.__super__.constructor.apply(this, arguments);
4547
+ }
4548
+
4549
+ InputCheckboxSwitch.prototype._add_input = function() {
4005
4550
  this.$switch = $("<div class='switch'>");
4006
4551
  this.$el.append(this.$switch);
4007
4552
  this.$false_hidden_input = $("<input type='hidden' name='" + this.name + "' value='false' />");
4008
4553
  this.$switch.append(this.$false_hidden_input);
4009
- this.$input = $("<input type='checkbox' name='" + this.name + "' id='" + this.name + "' value='true' " + (this._safeValue() ? 'checked' : '') + " />");
4554
+ this.$input = $("<input type='checkbox' id='" + this.name + "' name='" + this.name + "' value='true' " + (this._safe_value() ? 'checked' : '') + " />");
4010
4555
  this.$switch.append(this.$input);
4011
4556
  this.$checkbox = $("<div class='checkbox'>");
4012
4557
  return this.$switch.append(this.$checkbox);
4013
4558
  };
4014
4559
 
4015
- function InputCheckboxSwitch(name, value, config, object) {
4016
- this.name = name;
4017
- this.value = value;
4018
- this.config = config;
4019
- this.object = object;
4020
- this.$el = $("<label for='" + this.name + "' class='input-" + this.config.type + " input-" + this.config.klass + " " + this.config.klassName + "'>");
4021
- this._addLabel();
4022
- this._addInput();
4023
- return this;
4024
- }
4025
-
4026
4560
  return InputCheckboxSwitch;
4027
4561
 
4028
4562
  })(InputCheckbox);
4029
4563
 
4030
- _chrFormInputs['switch'] = InputCheckboxSwitch;
4564
+ chr.formInputs['switch'] = InputCheckboxSwitch;
4031
4565
 
4032
4566
  var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
4033
4567
  hasProp = {}.hasOwnProperty;
@@ -4039,18 +4573,18 @@ this.InputColor = (function(superClass) {
4039
4573
  return InputColor.__super__.constructor.apply(this, arguments);
4040
4574
  }
4041
4575
 
4042
- InputColor.prototype._addColorPreview = function() {
4576
+ InputColor.prototype._add_color_preview = function() {
4043
4577
  this.$colorPreview = $("<div class='preview'>");
4044
4578
  return this.$el.append(this.$colorPreview);
4045
4579
  };
4046
4580
 
4047
- InputColor.prototype._updateColorPreview = function() {
4581
+ InputColor.prototype._update_color_preview = function() {
4048
4582
  return this.$colorPreview.css({
4049
4583
  'background-color': "#" + (this.$input.val())
4050
4584
  });
4051
4585
  };
4052
4586
 
4053
- InputColor.prototype._validateInputValue = function() {
4587
+ InputColor.prototype._validate_input_value = function() {
4054
4588
  if (/^(?:[0-9a-f]{3}){1,2}$/i.test(this.$input.val())) {
4055
4589
  return this.hideErrorMessage();
4056
4590
  } else {
@@ -4060,13 +4594,14 @@ this.InputColor = (function(superClass) {
4060
4594
 
4061
4595
  InputColor.prototype.initialize = function() {
4062
4596
  var base;
4063
- this._addColorPreview();
4064
- this._updateColorPreview();
4597
+ this.$input.attr('placeholder', this.config.placeholder || 'e.g. #eee');
4598
+ this._add_color_preview();
4599
+ this._update_color_preview();
4065
4600
  this.$input.on('change keyup', (function(_this) {
4066
4601
  return function(e) {
4067
4602
  _this.hideErrorMessage();
4068
- _this._validateInputValue();
4069
- return _this._updateColorPreview();
4603
+ _this._validate_input_value();
4604
+ return _this._update_color_preview();
4070
4605
  };
4071
4606
  })(this));
4072
4607
  return typeof (base = this.config).onInitialize === "function" ? base.onInitialize(this) : void 0;
@@ -4076,7 +4611,9 @@ this.InputColor = (function(superClass) {
4076
4611
 
4077
4612
  })(InputString);
4078
4613
 
4079
- _chrFormInputs['color'] = InputColor;
4614
+ chr.formInputs['color'] = InputColor;
4615
+
4616
+
4080
4617
 
4081
4618
  var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
4082
4619
  hasProp = {}.hasOwnProperty;
@@ -4084,62 +4621,82 @@ var extend = function(child, parent) { for (var key in parent) { if (hasProp.cal
4084
4621
  this.InputFile = (function(superClass) {
4085
4622
  extend(InputFile, superClass);
4086
4623
 
4087
- InputFile.prototype._addInput = function() {
4088
- this.$el.addClass('empty');
4089
- if (this.filename) {
4090
- this.$link = $("<a href='" + this.value.url + "' target='_blank' title='" + this.filename + "'>" + this.filename + "</a>");
4091
- this.$el.append(this.$link);
4092
- this.$el.removeClass('empty');
4093
- }
4094
- this.$input = $("<input type='file' name='" + this.name + "' id='" + this.name + "' />");
4095
- return this.$el.append(this.$input);
4096
- };
4097
-
4098
- InputFile.prototype._addRemoveCheckbox = function() {
4099
- var removeInputName;
4100
- if (this.filename) {
4101
- removeInputName = this.removeName();
4102
- this.$removeLabel = $("<label for='" + removeInputName + "'>Remove</label>");
4103
- this.$link.after(this.$removeLabel);
4104
- this.$hiddenRemoveInput = $("<input type='hidden' name='" + removeInputName + "' value='false'>");
4105
- this.$removeInput = $("<input type='checkbox' name='" + removeInputName + "' id='" + removeInputName + "' value='true'>");
4106
- this.$link.after(this.$removeInput);
4107
- return this.$link.after(this.$hiddenRemoveInput);
4108
- }
4109
- };
4110
-
4111
4624
  function InputFile(name, value, config, object) {
4112
4625
  this.name = name;
4113
4626
  this.value = value;
4114
4627
  this.config = config;
4115
4628
  this.object = object;
4116
- this.$el = $("<div class='input-" + this.config.type + " input-" + this.config.klass + " " + this.config.klassName + "'>");
4117
- this.filename = null;
4629
+ this._create_el();
4630
+ this._add_label();
4631
+ this._add_input();
4632
+ this._update_state();
4633
+ return this;
4634
+ }
4635
+
4636
+ InputFile.prototype._create_el = function() {
4637
+ return this.$el = $("<div class='input-" + this.config.type + " input-" + this.config.klass + " " + this.config.klassName + "'>");
4638
+ };
4639
+
4640
+ InputFile.prototype._add_input = function() {
4641
+ this.$link = $("<a href='#' target='_blank' title=''></a>");
4642
+ this.$el.append(this.$link);
4643
+ this.$input = $("<input type='file' name='" + this.name + "' id='" + this.name + "'>");
4644
+ this.$el.append(this.$input);
4645
+ return this._add_remove_checkbox();
4646
+ };
4647
+
4648
+ InputFile.prototype._add_remove_checkbox = function() {
4649
+ var removeInputName;
4650
+ removeInputName = this.removeName();
4651
+ this.$removeLabel = $("<label for='" + removeInputName + "'>Remove</label>");
4652
+ this.$hiddenRemoveInput = $("<input type='hidden' name='" + removeInputName + "' value='false'>");
4653
+ this.$removeInput = $("<input type='checkbox' name='" + removeInputName + "' id='" + removeInputName + "' value='true'>");
4654
+ this.$link.after(this.$removeLabel);
4655
+ this.$link.after(this.$removeInput);
4656
+ return this.$link.after(this.$hiddenRemoveInput);
4657
+ };
4658
+
4659
+ InputFile.prototype._update_inputs = function() {
4660
+ return this.$link.html(this.filename).attr('title', this.filename).attr('href', this.value.url);
4661
+ };
4662
+
4663
+ InputFile.prototype._update_state = function(filename) {
4664
+ this.filename = filename != null ? filename : null;
4665
+ this.$input.val('');
4666
+ this.$removeInput.prop('checked', false);
4118
4667
  if (this.value.url) {
4119
4668
  this.filename = _last(this.value.url.split('/'));
4120
4669
  if (this.filename === '_old_') {
4121
4670
  this.filename = null;
4122
4671
  }
4123
4672
  }
4124
- this._addLabel();
4125
- this._addInput();
4126
- this._addRemoveCheckbox();
4127
- return this;
4128
- }
4673
+ if (this.filename) {
4674
+ this.$el.removeClass('empty');
4675
+ return this._update_inputs();
4676
+ } else {
4677
+ return this.$el.addClass('empty');
4678
+ }
4679
+ };
4680
+
4681
+ InputFile.prototype.isEmpty = function() {
4682
+ return !this.$input.get()[0].files[0] && !this.filename;
4683
+ };
4129
4684
 
4130
4685
  InputFile.prototype.removeName = function() {
4131
4686
  return this.name.reverse().replace('[', '[remove_'.reverse()).reverse();
4132
4687
  };
4133
4688
 
4134
- InputFile.prototype.updateValue = function(value) {
4689
+ InputFile.prototype.updateValue = function(value, object) {
4135
4690
  this.value = value;
4691
+ this.object = object;
4692
+ return this._update_state();
4136
4693
  };
4137
4694
 
4138
4695
  return InputFile;
4139
4696
 
4140
4697
  })(InputString);
4141
4698
 
4142
- _chrFormInputs['file'] = InputFile;
4699
+ chr.formInputs['file'] = InputFile;
4143
4700
 
4144
4701
  this.InputFileImage = (function(superClass) {
4145
4702
  extend(InputFileImage, superClass);
@@ -4148,76 +4705,56 @@ this.InputFileImage = (function(superClass) {
4148
4705
  return InputFileImage.__super__.constructor.apply(this, arguments);
4149
4706
  }
4150
4707
 
4151
- InputFileImage.prototype._addInput = function() {
4152
- var thumbnailImage, thumbnailImageUrl;
4153
- this.$el.addClass('empty');
4154
- if (this.filename) {
4155
- this.$link = $("<a href='" + this.value.url + "' target='_blank' title='" + this.filename + "'>" + this.filename + "</a>");
4156
- this.$el.append(this.$link);
4157
- thumbnailImageUrl = this.value.url;
4158
- thumbnailImage = this.value[this.config.thumbnailFieldName];
4159
- if (thumbnailImage) {
4160
- thumbnailImageUrl = thumbnailImage.url;
4161
- }
4162
- this.$thumb = $("<img src='" + thumbnailImageUrl + "' />");
4163
- this.$el.append(this.$thumb);
4164
- this.$el.removeClass('empty');
4165
- }
4708
+ InputFileImage.prototype._add_input = function() {
4709
+ this.$link = $("<a href='#' target='_blank' title=''></a>");
4710
+ this.$el.append(this.$link);
4711
+ this.$thumb = $("<img src='' />");
4712
+ this.$el.append(this.$thumb);
4166
4713
  this.$input = $("<input type='file' name='" + this.name + "' id='" + this.name + "' />");
4167
- return this.$el.append(this.$input);
4714
+ this.$el.append(this.$input);
4715
+ return this._add_remove_checkbox();
4716
+ };
4717
+
4718
+ InputFileImage.prototype._update_inputs = function() {
4719
+ var image_thumb_url;
4720
+ this.$link.html(this.filename).attr('title', this.filename).attr('href', this.value.url);
4721
+ image_thumb_url = this.config.thumbnail ? this.config.thumbnail(this.object) : this.value.url;
4722
+ return this.$thumb.attr('src', image_thumb_url).attr('alt', this.filename);
4168
4723
  };
4169
4724
 
4170
4725
  return InputFileImage;
4171
4726
 
4172
4727
  })(InputFile);
4173
4728
 
4174
- _chrFormInputs['image'] = InputFileImage;
4729
+ chr.formInputs['image'] = InputFileImage;
4175
4730
 
4176
- this.InputHidden = (function() {
4177
- function InputHidden(name, value, config, object) {
4178
- this.name = name;
4179
- this.value = value;
4180
- this.config = config;
4181
- this.object = object;
4182
- this.$el = $("<input type='hidden' name='" + this.name + "' value='" + (this._valueSafe()) + "' id='" + this.name + "' />");
4183
- return this;
4731
+ this.inputListReorder = {
4732
+ _bind_reorder: function() {
4733
+ var list;
4734
+ list = this.$items.get(0);
4735
+ new Slip(list);
4736
+ list.addEventListener('slip:beforeswipe', function(e) {
4737
+ return e.preventDefault();
4738
+ });
4739
+ list.addEventListener('slip:beforewait', (function(e) {
4740
+ if ($(e.target).hasClass("icon-reorder")) {
4741
+ return e.preventDefault();
4742
+ }
4743
+ }), false);
4744
+ list.addEventListener('slip:beforereorder', (function(e) {
4745
+ if (!$(e.target).hasClass("icon-reorder")) {
4746
+ return e.preventDefault();
4747
+ }
4748
+ }), false);
4749
+ return list.addEventListener('slip:reorder', ((function(_this) {
4750
+ return function(e) {
4751
+ e.target.parentNode.insertBefore(e.target, e.detail.insertBefore);
4752
+ _this._update_input_value();
4753
+ return false;
4754
+ };
4755
+ })(this)), false);
4184
4756
  }
4185
-
4186
- InputHidden.prototype._valueSafe = function() {
4187
- if (typeof this.value === 'object') {
4188
- return JSON.stringify(this.value);
4189
- } else {
4190
- return _escapeHtml(this.value);
4191
- }
4192
- };
4193
-
4194
- InputHidden.prototype.initialize = function() {
4195
- var base;
4196
- return typeof (base = this.config).onInitialize === "function" ? base.onInitialize(this) : void 0;
4197
- };
4198
-
4199
- InputHidden.prototype.updateValue = function(value) {
4200
- this.value = value;
4201
- return this.$el.val(this._valueSafe());
4202
- };
4203
-
4204
- InputHidden.prototype.hash = function(hash) {
4205
- if (hash == null) {
4206
- hash = {};
4207
- }
4208
- hash[this.config.klassName] = this.$el.val();
4209
- return hash;
4210
- };
4211
-
4212
- InputHidden.prototype.showErrorMessage = function(message) {};
4213
-
4214
- InputHidden.prototype.hideErrorMessage = function() {};
4215
-
4216
- return InputHidden;
4217
-
4218
- })();
4219
-
4220
- _chrFormInputs['hidden'] = InputHidden;
4757
+ };
4221
4758
 
4222
4759
  var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
4223
4760
  hasProp = {}.hasOwnProperty;
@@ -4229,7 +4766,21 @@ this.InputList = (function(superClass) {
4229
4766
  return InputList.__super__.constructor.apply(this, arguments);
4230
4767
  }
4231
4768
 
4232
- InputList.prototype._updateInputValue = function() {
4769
+ InputList.prototype._add_input = function() {
4770
+ var name, placeholder;
4771
+ name = this.config.namePrefix ? this.config.namePrefix + "[__LIST__" + this.config.target + "]" : "[__LIST__" + this.config.target + "]";
4772
+ this.$input = $("<input type='hidden' name='" + name + "' value='' />");
4773
+ this.$el.append(this.$input);
4774
+ if (this.config.typeahead) {
4775
+ placeholder = this.config.typeahead.placeholder;
4776
+ this.typeaheadInput = $("<input type='text' placeholder='" + placeholder + "' />");
4777
+ this.$el.append(this.typeaheadInput);
4778
+ }
4779
+ this._add_items();
4780
+ return this._update_input_value();
4781
+ };
4782
+
4783
+ InputList.prototype._update_input_value = function() {
4233
4784
  var ids, value;
4234
4785
  ids = [];
4235
4786
  this.$items.children('li').each(function(i, el) {
@@ -4239,15 +4790,15 @@ this.InputList = (function(superClass) {
4239
4790
  return this.$input.val(value);
4240
4791
  };
4241
4792
 
4242
- InputList.prototype._removeItem = function($el) {
4793
+ InputList.prototype._remove_item = function($el) {
4243
4794
  var id;
4244
4795
  id = $el.attr('data-id');
4245
4796
  delete this.objects[id];
4246
4797
  $el.parent().remove();
4247
- return this._updateInputValue();
4798
+ return this._update_input_value();
4248
4799
  };
4249
4800
 
4250
- InputList.prototype._addItem = function(o) {
4801
+ InputList.prototype._add_item = function(o) {
4251
4802
  var id, item, listItem;
4252
4803
  id = o['_id'];
4253
4804
  this.objects[id] = o;
@@ -4258,38 +4809,24 @@ this.InputList = (function(superClass) {
4258
4809
  }
4259
4810
  listItem = $("<li data-id='" + id + "'>\n <span class='icon-reorder' data-container-class='" + this.reorderContainerClass + "'></span>\n " + item + "\n <a href='#' class='action_remove'>Remove</a>\n</li>");
4260
4811
  this.$items.append(listItem);
4261
- return this._updateInputValue();
4812
+ return this._update_input_value();
4262
4813
  };
4263
4814
 
4264
- InputList.prototype._addItems = function() {
4815
+ InputList.prototype._add_items = function() {
4265
4816
  var j, len, o, ref;
4266
- this.reorderContainerClass = this.config.klassName;
4267
- this.objects = {};
4268
- this.$items = $("<ul class='" + this.reorderContainerClass + "'></ul>");
4269
- ref = this.value;
4270
- for (j = 0, len = ref.length; j < len; j++) {
4271
- o = ref[j];
4272
- this._addItem(o);
4273
- }
4274
- return this.typeaheadInput.before(this.$items);
4275
- };
4276
-
4277
- InputList.prototype._addInput = function() {
4278
- var name, placeholder;
4279
- name = this.config.namePrefix ? this.config.namePrefix + "[__LIST__" + this.config.target + "]" : "[__LIST__" + this.config.target + "]";
4280
- this.$input = $("<input type='hidden' name='" + name + "' value='' />");
4281
- this.$el.append(this.$input);
4282
- if (this.config.typeahead) {
4283
- placeholder = this.config.typeahead.placeholder;
4284
- this.typeaheadInput = $("<input type='text' placeholder='" + placeholder + "' />");
4285
- this.$el.append(this.typeaheadInput);
4817
+ this.reorderContainerClass = this.config.klassName;
4818
+ this.objects = {};
4819
+ this.$items = $("<ul class='" + this.reorderContainerClass + "'></ul>");
4820
+ ref = this.value;
4821
+ for (j = 0, len = ref.length; j < len; j++) {
4822
+ o = ref[j];
4823
+ this._add_item(o);
4286
4824
  }
4287
- this._addItems();
4288
- return this._updateInputValue();
4825
+ return this.typeaheadInput.before(this.$items);
4289
4826
  };
4290
4827
 
4291
4828
  InputList.prototype.initialize = function() {
4292
- var base, dataSource, limit, list;
4829
+ var base, dataSource, limit;
4293
4830
  if (this.config.typeahead) {
4294
4831
  limit = this.config.typeahead.limit || 5;
4295
4832
  dataSource = new Bloodhound({
@@ -4309,7 +4846,7 @@ this.InputList = (function(superClass) {
4309
4846
  });
4310
4847
  this.typeaheadInput.on('typeahead:selected', (function(_this) {
4311
4848
  return function(e, object, dataset) {
4312
- _this._addItem(object);
4849
+ _this._add_item(object);
4313
4850
  return _this.typeaheadInput.typeahead('val', '');
4314
4851
  };
4315
4852
  })(this));
@@ -4318,39 +4855,14 @@ this.InputList = (function(superClass) {
4318
4855
  return function(e) {
4319
4856
  e.preventDefault();
4320
4857
  if (confirm('Are you sure?')) {
4321
- return _this._removeItem($(e.currentTarget));
4858
+ return _this._remove_item($(e.currentTarget));
4322
4859
  }
4323
4860
  };
4324
4861
  })(this));
4325
- list = this.$items.get(0);
4326
- new Slip(list);
4327
- list.addEventListener('slip:beforeswipe', function(e) {
4328
- return e.preventDefault();
4329
- });
4330
- list.addEventListener('slip:beforewait', (function(e) {
4331
- if ($(e.target).hasClass("icon-reorder")) {
4332
- return e.preventDefault();
4333
- }
4334
- }), false);
4335
- list.addEventListener('slip:beforereorder', (function(e) {
4336
- if (!$(e.target).hasClass("icon-reorder")) {
4337
- return e.preventDefault();
4338
- }
4339
- }), false);
4340
- list.addEventListener('slip:reorder', ((function(_this) {
4341
- return function(e) {
4342
- e.target.parentNode.insertBefore(e.target, e.detail.insertBefore);
4343
- _this._updateInputValue();
4344
- return false;
4345
- };
4346
- })(this)), false);
4862
+ this._bind_reorder();
4347
4863
  return typeof (base = this.config).onInitialize === "function" ? base.onInitialize(this) : void 0;
4348
4864
  };
4349
4865
 
4350
- InputList.prototype.updateValue = function(value1) {
4351
- this.value = value1;
4352
- };
4353
-
4354
4866
  InputList.prototype.hash = function(hash) {
4355
4867
  var id, ids, j, len;
4356
4868
  if (hash == null) {
@@ -4365,347 +4877,172 @@ this.InputList = (function(superClass) {
4365
4877
  return hash;
4366
4878
  };
4367
4879
 
4368
- return InputList;
4369
-
4370
- })(InputString);
4371
-
4372
- _chrFormInputs['list'] = InputList;
4373
-
4374
- var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
4375
- hasProp = {}.hasOwnProperty;
4376
-
4377
- this.InputSelect = (function(superClass) {
4378
- extend(InputSelect, superClass);
4379
-
4380
- function InputSelect() {
4381
- return InputSelect.__super__.constructor.apply(this, arguments);
4382
- }
4383
-
4384
- InputSelect.prototype._createEl = function() {
4385
- return this.$el = $("<div class='input-" + this.config.type + " input-" + this.config.klass + " " + this.config.klassName + "'>");
4386
- };
4387
-
4388
- InputSelect.prototype._addOption = function(title, value) {
4389
- var $option, selected;
4390
- selected = this.value === value ? 'selected' : '';
4391
- $option = $("<option value='" + value + "' " + selected + ">" + title + "</option>");
4392
- return this.$input.append($option);
4393
- };
4394
-
4395
- InputSelect.prototype._addListOptions = function() {
4396
- var data, i, len, o, results;
4397
- data = this.config.optionsList;
4398
- results = [];
4399
- for (i = 0, len = data.length; i < len; i++) {
4400
- o = data[i];
4401
- results.push(this._addOption(o, o));
4402
- }
4403
- return results;
4404
- };
4405
-
4406
- InputSelect.prototype._addHashOptions = function() {
4407
- var data, results, title, value;
4408
- data = this.config.optionsHash;
4409
- results = [];
4410
- for (value in data) {
4411
- title = data[value];
4412
- results.push(this._addOption(title, value));
4413
- }
4414
- return results;
4415
- };
4416
-
4417
- InputSelect.prototype._addCollectionOptions = function() {
4418
- var data, i, len, o, results, title, titleField, value, valueField;
4419
- data = this.config.collection.data;
4420
- valueField = this.config.collection.valueField;
4421
- titleField = this.config.collection.titleField;
4880
+ InputList.prototype.updateValue = function(value1) {
4881
+ var j, len, o, ref, results;
4882
+ this.value = value1;
4883
+ this.$items.html('');
4884
+ ref = this.value;
4422
4885
  results = [];
4423
- for (i = 0, len = data.length; i < len; i++) {
4424
- o = data[i];
4425
- title = o[titleField];
4426
- value = o[valueField];
4427
- results.push(this._addOption(title, value));
4886
+ for (j = 0, len = ref.length; j < len; j++) {
4887
+ o = ref[j];
4888
+ results.push(this._add_item(o));
4428
4889
  }
4429
4890
  return results;
4430
4891
  };
4431
4892
 
4432
- InputSelect.prototype._addOptions = function() {
4433
- if (this.config.collection) {
4434
- return this._addCollectionOptions();
4435
- } else if (this.config.optionsList) {
4436
- return this._addListOptions();
4437
- } else if (this.config.optionsHash) {
4438
- return this._addHashOptions();
4439
- }
4440
- };
4441
-
4442
- InputSelect.prototype._addInput = function() {
4443
- this.$input = $("<select name='" + this.name + "' id='" + this.name + "'></select>");
4444
- this.$el.append(this.$input);
4445
- if (this.config.optionsHashFieldName) {
4446
- this.value = String(this.value);
4447
- if (this.object) {
4448
- this.config.optionsHash = this.object[this.config.optionsHashFieldName];
4449
- } else {
4450
- this.config.optionsHash = {
4451
- '': '--'
4452
- };
4453
- }
4454
- }
4455
- return this._addOptions();
4456
- };
4457
-
4458
- return InputSelect;
4893
+ return InputList;
4459
4894
 
4460
4895
  })(InputString);
4461
4896
 
4462
- _chrFormInputs['select'] = InputSelect;
4897
+ include(InputList, inputListReorder);
4898
+
4899
+ chr.formInputs['list'] = InputList;
4463
4900
 
4464
4901
  var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
4465
4902
  hasProp = {}.hasOwnProperty;
4466
4903
 
4467
- this.InputText = (function(superClass) {
4468
- extend(InputText, superClass);
4904
+ this.InputPassword = (function(superClass) {
4905
+ extend(InputPassword, superClass);
4469
4906
 
4470
- function InputText() {
4471
- return InputText.__super__.constructor.apply(this, arguments);
4907
+ function InputPassword() {
4908
+ return InputPassword.__super__.constructor.apply(this, arguments);
4472
4909
  }
4473
4910
 
4474
- InputText.prototype._addInput = function() {
4475
- this.$input = $("<textarea class='autosize' name='" + this.name + "' id='" + this.name + "' rows=1>" + (this._valueSafe()) + "</textarea>");
4911
+ InputPassword.prototype._add_input = function() {
4912
+ this.$input = $("<input type='password' name='" + this.name + "' value='" + this.value + "' />");
4476
4913
  return this.$el.append(this.$input);
4477
4914
  };
4478
4915
 
4479
- InputText.prototype.initialize = function() {
4480
- var base;
4481
- this.$input.textareaAutoSize();
4482
- return typeof (base = this.config).onInitialize === "function" ? base.onInitialize(this) : void 0;
4916
+ InputPassword.prototype.updateValue = function(value) {
4917
+ this.value = value;
4918
+ return this.$input.val(this.value);
4483
4919
  };
4484
4920
 
4485
- return InputText;
4921
+ return InputPassword;
4486
4922
 
4487
4923
  })(InputString);
4488
4924
 
4489
- _chrFormInputs['text'] = InputText;
4925
+ chr.formInputs['password'] = InputPassword;
4490
4926
 
4491
- this.NestedForm = (function() {
4492
- function NestedForm(name1, nestedObjects, config1, object1) {
4493
- var base, i, o, ref;
4494
- this.name = name1;
4495
- this.nestedObjects = nestedObjects;
4496
- this.config = config1;
4497
- this.object = object1;
4498
- this.forms = [];
4499
- (base = this.config).namePrefix || (base.namePrefix = name);
4500
- this.config.removeButton = true;
4501
- this.config.formSchema.id = {
4502
- type: 'hidden'
4503
- };
4504
- this.reorderContainerClass = "nested-forms-" + this.config.klassName;
4505
- if (this.config.sortBy) {
4506
- this.config.formSchema[this.config.sortBy] = {
4507
- type: 'hidden'
4508
- };
4509
- if (this.nestedObjects) {
4510
- this.nestedObjects.sort((function(_this) {
4511
- return function(a, b) {
4512
- return parseFloat(a[_this.config.sortBy]) - parseFloat(b[_this.config.sortBy]);
4513
- };
4514
- })(this));
4515
- ref = this.nestedObjects;
4516
- for (i in ref) {
4517
- o = ref[i];
4518
- o[this.config.sortBy] = parseInt(i) + 1;
4519
- }
4520
- }
4521
- }
4522
- this.$el = $("<div class='input-stacked nested-forms " + this.config.klassName + "'>");
4523
- this._addLabel();
4524
- this._addForms();
4525
- this._addFormsReorder();
4526
- this._addNewButton();
4527
- return this;
4528
- }
4927
+ var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
4928
+ hasProp = {}.hasOwnProperty;
4529
4929
 
4530
- NestedForm.prototype._addLabel = function() {
4531
- var ref;
4532
- if ((ref = this.config.klass) === 'inline' || ref === 'stacked') {
4533
- this.$label = $("<span class='label'>" + this.config.label + "</span>");
4534
- this.$el.append(this.$label);
4535
- this.$errorMessage = $("<span class='error-message'></span>");
4536
- return this.$label.append(this.$errorMessage);
4537
- }
4538
- };
4930
+ this.InputSelect = (function(superClass) {
4931
+ extend(InputSelect, superClass);
4539
4932
 
4540
- NestedForm.prototype._addForms = function() {
4541
- var i, namePrefix, object, ref, results;
4542
- this.$forms = $("<ul>");
4543
- this.$el.append(this.$forms);
4544
- if (this.nestedObjects !== '') {
4545
- ref = this.nestedObjects;
4546
- results = [];
4547
- for (i in ref) {
4548
- object = ref[i];
4549
- namePrefix = this.config.namePrefix + "[" + i + "]";
4550
- results.push(this.forms.push(this._renderForm(object, namePrefix, this.config)));
4551
- }
4552
- return results;
4553
- }
4554
- };
4933
+ function InputSelect() {
4934
+ return InputSelect.__super__.constructor.apply(this, arguments);
4935
+ }
4555
4936
 
4556
- NestedForm.prototype._renderForm = function(object, namePrefix, config) {
4557
- var form, formConfig;
4558
- formConfig = $.extend({}, config, {
4559
- namePrefix: namePrefix,
4560
- rootEl: "<li>"
4561
- });
4562
- form = new Form(object, formConfig);
4563
- this.$forms.append(form.$el);
4564
- return form;
4937
+ InputSelect.prototype._create_el = function() {
4938
+ return this.$el = $("<div class='input-" + this.config.type + " input-" + this.config.klass + " " + this.config.klassName + "'>");
4565
4939
  };
4566
4940
 
4567
- NestedForm.prototype._addFormsReorder = function() {
4568
- var form, j, len, list, ref, results;
4569
- if (this.config.sortBy) {
4570
- list = this.$forms.addClass(this.reorderContainerClass).get(0);
4571
- new Slip(list);
4572
- list.addEventListener('slip:beforeswipe', function(e) {
4573
- return e.preventDefault();
4574
- });
4575
- list.addEventListener('slip:beforewait', (function(e) {
4576
- if ($(e.target).hasClass("icon-reorder")) {
4577
- return e.preventDefault();
4578
- }
4579
- }), false);
4580
- list.addEventListener('slip:beforereorder', (function(e) {
4581
- if (!$(e.target).hasClass("icon-reorder")) {
4582
- return e.preventDefault();
4583
- }
4584
- }), false);
4585
- list.addEventListener('slip:reorder', ((function(_this) {
4586
- return function(e) {
4587
- var $targetForm, newTargetFormPosition, nextForm, nextFormPosition, prevForm, prevFormPosition, targetForm;
4588
- targetForm = _this._findFormByTarget(e.target);
4589
- if (targetForm) {
4590
- e.target.parentNode.insertBefore(e.target, e.detail.insertBefore);
4591
- $targetForm = $(e.target);
4592
- prevForm = _this._findFormByTarget($targetForm.prev().get(0));
4593
- nextForm = _this._findFormByTarget($targetForm.next().get(0));
4594
- prevFormPosition = prevForm ? prevForm.inputs[_this.config.sortBy].value : 0;
4595
- nextFormPosition = nextForm ? nextForm.inputs[_this.config.sortBy].value : 0;
4596
- newTargetFormPosition = prevFormPosition + Math.abs(nextFormPosition - prevFormPosition) / 2.0;
4597
- targetForm.inputs[_this.config.sortBy].updateValue(newTargetFormPosition);
4598
- }
4599
- return false;
4941
+ InputSelect.prototype._add_input = function() {
4942
+ this.$input = $("<select name='" + this.name + "' id='" + this.name + "'></select>");
4943
+ this.$el.append(this.$input);
4944
+ if (this.config.optionsHashFieldName) {
4945
+ this.value = String(this.value);
4946
+ if (this.object) {
4947
+ this.config.optionsHash = this.object[this.config.optionsHashFieldName];
4948
+ } else {
4949
+ this.config.optionsHash = {
4950
+ '': '--'
4600
4951
  };
4601
- })(this)), false);
4602
- ref = this.forms;
4603
- results = [];
4604
- for (j = 0, len = ref.length; j < len; j++) {
4605
- form = ref[j];
4606
- results.push(this._addFormReorderButton(form));
4607
4952
  }
4608
- return results;
4609
4953
  }
4954
+ return this._add_options();
4610
4955
  };
4611
4956
 
4612
- NestedForm.prototype._addFormReorderButton = function(form) {
4613
- return form.$el.append("<div class='icon-reorder' data-container-class='" + this.reorderContainerClass + "'></div>").addClass('reorderable');
4614
- };
4615
-
4616
- NestedForm.prototype._findFormByTarget = function(el) {
4617
- var form, j, len, ref;
4618
- if (el) {
4619
- ref = this.forms;
4620
- for (j = 0, len = ref.length; j < len; j++) {
4621
- form = ref[j];
4622
- if (form.$el.get(0) === el) {
4623
- return form;
4624
- }
4625
- }
4957
+ InputSelect.prototype._add_options = function() {
4958
+ if (this.config.collection) {
4959
+ return this._add_collection_options();
4960
+ } else if (this.config.optionsList) {
4961
+ return this._add_list_options();
4962
+ } else if (this.config.optionsHash) {
4963
+ return this._add_hash_options();
4626
4964
  }
4627
- return null;
4628
- };
4629
-
4630
- NestedForm.prototype._addNewButton = function() {
4631
- var label;
4632
- label = this.config.newButtonLabel || "Add";
4633
- this.$newButton = $("<a href='#' class='nested-form-new'>" + label + "</a>");
4634
- this.$el.append(this.$newButton);
4635
- return this.$newButton.on('click', (function(_this) {
4636
- return function(e) {
4637
- e.preventDefault();
4638
- return _this.addNewForm();
4639
- };
4640
- })(this));
4641
4965
  };
4642
4966
 
4643
- NestedForm.prototype.addNewForm = function(object) {
4644
- var base, form, namePrefix, newFormConfig, position, prevForm;
4645
- if (object == null) {
4646
- object = null;
4647
- }
4648
- namePrefix = this.config.namePrefix + "[" + (Date.now()) + "]";
4649
- newFormConfig = $.extend({}, this.config);
4650
- delete newFormConfig.formSchema.id;
4651
- form = this._renderForm(object, namePrefix, newFormConfig);
4652
- form.initializePlugins();
4653
- if (this.config.sortBy) {
4654
- this._addFormReorderButton(form);
4655
- prevForm = _last(this.forms);
4656
- position = prevForm ? prevForm.inputs[this.config.sortBy].value + 1 : 1;
4657
- form.inputs[this.config.sortBy].updateValue(position);
4658
- }
4659
- this.forms.push(form);
4660
- if (typeof (base = this.config).onNew === "function") {
4661
- base.onNew(form);
4967
+ InputSelect.prototype._add_collection_options = function() {
4968
+ var i, len, o, ref, results, title, value;
4969
+ ref = this.config.collection.data;
4970
+ results = [];
4971
+ for (i = 0, len = ref.length; i < len; i++) {
4972
+ o = ref[i];
4973
+ title = o[this.config.collection.titleField];
4974
+ value = o[this.config.collection.valueField];
4975
+ results.push(this._add_option(title, value));
4662
4976
  }
4663
- return form;
4977
+ return results;
4664
4978
  };
4665
4979
 
4666
- NestedForm.prototype.initialize = function() {
4667
- var base, j, len, nestedForm, ref;
4668
- ref = this.forms;
4669
- for (j = 0, len = ref.length; j < len; j++) {
4670
- nestedForm = ref[j];
4671
- nestedForm.initializePlugins();
4980
+ InputSelect.prototype._add_list_options = function() {
4981
+ var data, i, len, o, results;
4982
+ data = this.config.optionsList;
4983
+ results = [];
4984
+ for (i = 0, len = data.length; i < len; i++) {
4985
+ o = data[i];
4986
+ results.push(this._add_option(o, o));
4672
4987
  }
4673
- return typeof (base = this.config).onInitialize === "function" ? base.onInitialize(this) : void 0;
4988
+ return results;
4674
4989
  };
4675
4990
 
4676
- NestedForm.prototype.showErrorMessage = function(message) {
4677
- this.$el.addClass('error');
4678
- return this.$errorMessage.html(message);
4991
+ InputSelect.prototype._add_hash_options = function() {
4992
+ var data, results, title, value;
4993
+ data = this.config.optionsHash;
4994
+ results = [];
4995
+ for (value in data) {
4996
+ title = data[value];
4997
+ results.push(this._add_option(title, value));
4998
+ }
4999
+ return results;
4679
5000
  };
4680
5001
 
4681
- NestedForm.prototype.hideErrorMessage = function() {
4682
- this.$el.removeClass('error');
4683
- return this.$errorMessage.html('');
5002
+ InputSelect.prototype._add_option = function(title, value) {
5003
+ var $option, selected;
5004
+ selected = this.value === value ? 'selected' : '';
5005
+ $option = $("<option value='" + value + "' " + selected + ">" + title + "</option>");
5006
+ return this.$input.append($option);
4684
5007
  };
4685
5008
 
4686
- NestedForm.prototype.updateValue = function(value) {
4687
- this.value = value;
5009
+ InputSelect.prototype.updateValue = function(value1) {
5010
+ this.value = value1;
5011
+ return this.$input.val(this.value).prop('selected', true);
4688
5012
  };
4689
5013
 
4690
- NestedForm.prototype.hash = function(hash) {
4691
- var form, j, len, ref;
4692
- if (hash == null) {
4693
- hash = {};
4694
- }
4695
- hash[this.config.klassName] = [];
4696
- ref = this.forms;
4697
- for (j = 0, len = ref.length; j < len; j++) {
4698
- form = ref[j];
4699
- hash[this.config.klassName].push(form.hash());
4700
- }
4701
- return hash;
5014
+ return InputSelect;
5015
+
5016
+ })(InputString);
5017
+
5018
+ chr.formInputs['select'] = InputSelect;
5019
+
5020
+ var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
5021
+ hasProp = {}.hasOwnProperty;
5022
+
5023
+ this.InputText = (function(superClass) {
5024
+ extend(InputText, superClass);
5025
+
5026
+ function InputText() {
5027
+ return InputText.__super__.constructor.apply(this, arguments);
5028
+ }
5029
+
5030
+ InputText.prototype._add_input = function() {
5031
+ this.$input = $("<textarea class='autosize' name='" + this.name + "' rows=1>" + (this._safe_value()) + "</textarea>");
5032
+ return this.$el.append(this.$input);
5033
+ };
5034
+
5035
+ InputText.prototype.initialize = function() {
5036
+ var base;
5037
+ this.$input.textareaAutoSize();
5038
+ return typeof (base = this.config).onInitialize === "function" ? base.onInitialize(this) : void 0;
4702
5039
  };
4703
5040
 
4704
- return NestedForm;
5041
+ return InputText;
4705
5042
 
4706
- })();
5043
+ })(InputString);
4707
5044
 
4708
- _chrFormInputs['form'] = NestedForm;
5045
+ chr.formInputs['text'] = InputText;
4709
5046
 
4710
5047
  this.ArrayStore = (function() {
4711
5048
  function ArrayStore(config) {
@@ -5258,7 +5595,7 @@ this.MongosteenArrayStore = (function(superClass) {
5258
5595
  }
5259
5596
 
5260
5597
  MongosteenArrayStore.prototype._initialize_database = function() {
5261
- var ref, ref1;
5598
+ var ref, ref1, ref2;
5262
5599
  this.dataFetchLock = false;
5263
5600
  this.ajaxConfig = {
5264
5601
  processData: false,
@@ -5268,7 +5605,7 @@ this.MongosteenArrayStore = (function(superClass) {
5268
5605
  this.searchQuery = '';
5269
5606
  this.pagination = (ref1 = this.config.pagination) != null ? ref1 : true;
5270
5607
  this.nextPage = 1;
5271
- this.objectsPerPage = typeof _itemsPerPageRequest !== "undefined" && _itemsPerPageRequest !== null ? _itemsPerPageRequest : 20;
5608
+ this.objectsPerPage = (ref2 = chr.itemsPerPageRequest) != null ? ref2 : 20;
5272
5609
  if (this.pagination) {
5273
5610
  return this._bind_pagination_sync();
5274
5611
  }
@@ -5482,205 +5819,3 @@ this.MongosteenObjectStore = (function(superClass) {
5482
5819
  return MongosteenObjectStore;
5483
5820
 
5484
5821
  })(RestObjectStore);
5485
-
5486
- this._last = function(array) {
5487
- return array[array.length - 1];
5488
- };
5489
-
5490
- this._first = function(array) {
5491
- return array[0];
5492
- };
5493
-
5494
- this._firstNonEmptyValue = function(o) {
5495
- var k, v;
5496
- for (k in o) {
5497
- v = o[k];
5498
- if (k[0] !== '_' && v && v !== '') {
5499
- return v;
5500
- }
5501
- }
5502
- return null;
5503
- };
5504
-
5505
- this._stripHtml = function(string) {
5506
- return String(string).replace(/<\/?[^>]+(>|$)/g, "");
5507
- };
5508
-
5509
- this._entityMap = {
5510
- "&": "&amp;",
5511
- "<": "&lt;",
5512
- ">": "&gt;",
5513
- '"': '&quot;',
5514
- "'": '&#39;',
5515
- "/": '&#x2F;'
5516
- };
5517
-
5518
- this._escapeHtml = function(string) {
5519
- return String(string).replace(/[&<>"'\/]/g, function(s) {
5520
- return _entityMap[s];
5521
- });
5522
- };
5523
-
5524
- if (typeof String.prototype.titleize !== 'function') {
5525
- String.prototype.titleize = function() {
5526
- return this.replace(/_/g, ' ').replace(/\b./g, (function(m) {
5527
- return m.toUpperCase();
5528
- }));
5529
- };
5530
- }
5531
-
5532
- if (typeof String.prototype.reverse !== 'function') {
5533
- String.prototype.reverse = function(str) {
5534
- return this.split("").reverse().join("");
5535
- };
5536
- }
5537
-
5538
- if (typeof String.prototype.startsWith !== 'function') {
5539
- String.prototype.startsWith = function(str) {
5540
- return this.slice(0, str.length) === str;
5541
- };
5542
- }
5543
-
5544
- if (typeof String.prototype.endsWith !== 'function') {
5545
- String.prototype.endsWith = function(str) {
5546
- return this.slice(this.length - str.length, this.length) === str;
5547
- };
5548
- }
5549
-
5550
- this._itemsPerScreen = function() {
5551
- var itemHeight;
5552
- itemHeight = 60;
5553
- return Math.ceil($(window).height() / itemHeight);
5554
- };
5555
-
5556
- this._itemsPerPageRequest = _itemsPerScreen() * 2;
5557
-
5558
- this._isMobile = function() {
5559
- return $(window).width() < 760;
5560
- };
5561
-
5562
- this.Chr = (function() {
5563
- function Chr() {
5564
- this.modules = {};
5565
- }
5566
-
5567
- Chr.prototype._unset_active_menu_items = function() {
5568
- return $('.sidebar .menu a.active').removeClass('active');
5569
- };
5570
-
5571
- Chr.prototype.unsetActiveListItems = function() {
5572
- return $('.list .items .item.active').removeClass('active');
5573
- };
5574
-
5575
- Chr.prototype._set_active_menu_item = function() {
5576
- var a, currentModuleName, i, len, moduleName, ref;
5577
- currentModuleName = window.location.hash.split('/')[1];
5578
- ref = this.$mainMenu.children();
5579
- for (i = 0, len = ref.length; i < len; i++) {
5580
- a = ref[i];
5581
- moduleName = $(a).attr('href').split('/')[1];
5582
- if (currentModuleName === moduleName) {
5583
- return $(a).addClass('active');
5584
- }
5585
- }
5586
- };
5587
-
5588
- Chr.prototype._navigate = function(path) {
5589
- var config, crumb, crumbs, i, len, objectId, ref, results;
5590
- crumbs = path.split('/');
5591
- if (this.module !== this.modules[crumbs[1]]) {
5592
- if ((ref = this.module) != null) {
5593
- ref.hide(path === '#/');
5594
- }
5595
- }
5596
- this.module = this.modules[crumbs[1]];
5597
- if (this.module) {
5598
- this.module.show();
5599
- config = this.module.config;
5600
- crumbs = crumbs.splice(2);
5601
- if (crumbs.length > 0) {
5602
- for (i = 0, len = crumbs.length; i < len; i++) {
5603
- crumb = crumbs[i];
5604
- if (crumb === 'new') {
5605
- return this.module.showView(null, config, 'New');
5606
- }
5607
- if (crumb === 'view') {
5608
- objectId = _last(crumbs);
5609
- return this.module.showViewByObjectId(objectId, config);
5610
- }
5611
- config = config.items[crumb];
5612
- if (config.objectStore) {
5613
- return this.module.showViewByObjectId('', config, crumb.titleize());
5614
- } else {
5615
- this.module.showNestedList(crumb);
5616
- }
5617
- }
5618
- } else {
5619
- this.module.destroyView();
5620
- results = [];
5621
- while (this.module.activeList !== this.module.rootList) {
5622
- results.push(this.module.hideActiveList(false));
5623
- }
5624
- return results;
5625
- }
5626
- }
5627
- };
5628
-
5629
- Chr.prototype.start = function(config1) {
5630
- var config, name, ref, ref1;
5631
- this.config = config1;
5632
- this.$el = $((ref = this.config.selector) != null ? ref : 'body');
5633
- this.$navBar = $("<nav class='sidebar'>");
5634
- this.$mainMenu = $("<div class='menu'>");
5635
- this.$navBar.append(this.$mainMenu);
5636
- this.$el.append(this.$navBar);
5637
- ref1 = this.config.modules;
5638
- for (name in ref1) {
5639
- config = ref1[name];
5640
- this.modules[name] = new Module(this, name, config);
5641
- }
5642
- $(this).on('hashchange', (function(_this) {
5643
- return function() {
5644
- return _this._set_active_menu_item();
5645
- };
5646
- })(this));
5647
- window.onhashchange = (function(_this) {
5648
- return function() {
5649
- _this._unset_active_menu_items();
5650
- _this.unsetActiveListItems();
5651
- if (!window._skipHashchange) {
5652
- _this._navigate(location.hash);
5653
- }
5654
- window._skipHashchange = false;
5655
- return $(_this).trigger('hashchange');
5656
- };
5657
- })(this);
5658
- $(document).on('click', 'a.silent', function(e) {
5659
- return window._skipHashchange = true;
5660
- });
5661
- window._skipHashchange = false;
5662
- if (location.hash !== '') {
5663
- this._navigate(location.hash);
5664
- return $(this).trigger('hashchange');
5665
- } else if (!_isMobile()) {
5666
- return location.hash = '#/' + Object.keys(this.modules)[0];
5667
- }
5668
- };
5669
-
5670
- Chr.prototype.addMenuItem = function(moduleName, title) {
5671
- return this.$mainMenu.append("<a href='#/" + moduleName + "'>" + title + "</a>");
5672
- };
5673
-
5674
- Chr.prototype.showAlert = function(message) {
5675
- return console.log('Alert: ' + message);
5676
- };
5677
-
5678
- Chr.prototype.showError = function(message) {
5679
- return console.log('Error: ' + message);
5680
- };
5681
-
5682
- return Chr;
5683
-
5684
- })();
5685
-
5686
- window.chr = new Chr();