chr 0.2.1 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
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,156 @@
1
+ /*
2
+ * webhook-redactor
3
+ *
4
+ *
5
+ * Copyright (c) 2014 Webhook
6
+ * Licensed under the MIT license.
7
+ */
8
+
9
+ (function ($) {
10
+ "use strict";
11
+
12
+ // namespacing
13
+ var Fixedtoolbar = function (redactor) {
14
+ this.redactor = redactor;
15
+ this.$window = $('.view > form'); //$(window);
16
+ this.viewHeaderHeight = 40;
17
+
18
+ this.$window.on('scroll', $.proxy(this.checkOffset, this));
19
+ redactor.$box.on('scroll', $.proxy(this.checkOffset, this));
20
+
21
+ this.redactor.$editor.on('focus', $.proxy(function () {
22
+ this.isFocused = true;
23
+ }, this));
24
+
25
+ this.redactor.$editor.on('blur', $.proxy(function () {
26
+ this.isFocused = false;
27
+ }, this));
28
+ };
29
+ Fixedtoolbar.prototype = {
30
+ isFixed: false,
31
+ isFocused: false,
32
+
33
+ checkOffset: function () {
34
+ if ( !this.redactor.fullscreen.isOpen )
35
+ {
36
+ var boxOffset = this.redactor.$box.offset();
37
+
38
+ var isBelowBoxTop = boxOffset.top - this.viewHeaderHeight <= 0;
39
+ //var isAboveBoxBottom = boxOffset.top + this.redactor.$box.outerHeight() - this.redactor.$toolbar.outerHeight() - this.$window.scrollTop() >= 0;
40
+ var isAboveBoxBottom = this.redactor.$box.outerHeight() + boxOffset.top - this.viewHeaderHeight - this.redactor.$toolbar.outerHeight() >= 0;
41
+
42
+ if (isBelowBoxTop && isAboveBoxBottom) {
43
+ this.fix();
44
+ } else {
45
+ this.unfix();
46
+ }
47
+ }
48
+ },
49
+
50
+ fix: function () {
51
+
52
+ if (this.isFixed) {
53
+
54
+ // webkit does not recalc top: 0 when focused on contenteditable
55
+ if (this.redactor.utils.isMobile() && this.isFocused) {
56
+ this.redactor.$toolbar.css({
57
+ position: 'absolute',
58
+ top : this.$window.scrollTop() - this.redactor.$box.offset().top,
59
+ left : this.redactor.$box.offset().left
60
+ });
61
+ }
62
+
63
+ return;
64
+ }
65
+
66
+ var border_left = parseInt(this.redactor.$box.css('border-left-width').replace('px', ''), 10);
67
+
68
+ this.redactor.$toolbar.css({
69
+ position: 'fixed',
70
+ top : this.viewHeaderHeight,
71
+ left : this.redactor.$box.offset().left + border_left,
72
+ width : this.redactor.$box.width(),
73
+ zIndex : 300
74
+ });
75
+
76
+ this.redactor.$editor.css('padding-top', this.redactor.$toolbar.height() + 10);
77
+
78
+ this.isFixed = true;
79
+
80
+ },
81
+
82
+ unfix: function () {
83
+ if (!this.isFixed) {
84
+ return;
85
+ }
86
+
87
+ this.redactor.$toolbar.css({
88
+ position: 'relative',
89
+ left : '',
90
+ width : '',
91
+ top : ''
92
+ });
93
+
94
+ this.redactor.$editor.css('padding-top', 10);
95
+
96
+ this.isFixed = false;
97
+ }
98
+ };
99
+
100
+ // Hook up plugin to Redactor.
101
+ window.RedactorPlugins = window.RedactorPlugins || {};
102
+ window.RedactorPlugins.fixedtoolbar = function() {
103
+ return {
104
+ init: function () {
105
+ this.fixedtoolbar = new Fixedtoolbar(this);
106
+ }
107
+ };
108
+ };
109
+
110
+ }(jQuery));
111
+
112
+ 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; },
113
+ hasProp = {}.hasOwnProperty;
114
+
115
+ this.InputRedactor = (function(superClass) {
116
+ extend(InputRedactor, superClass);
117
+
118
+ function InputRedactor() {
119
+ return InputRedactor.__super__.constructor.apply(this, arguments);
120
+ }
121
+
122
+ InputRedactor.prototype._add_input = function() {
123
+ this.$el.css('opacity', 0);
124
+ this.$input = $("<textarea class='redactor' name='" + this.name + "' rows=1>" + (this._safe_value()) + "</textarea>");
125
+ return this.$el.append(this.$input);
126
+ };
127
+
128
+ InputRedactor.prototype.initialize = function() {
129
+ var base, base1, redactor_options;
130
+ redactor_options = {
131
+ focus: false,
132
+ imageFloatMargin: '20px',
133
+ buttonSource: true,
134
+ pastePlainText: true,
135
+ plugins: ['fixedtoolbar', 'loft'],
136
+ buttons: ['html', 'formatting', 'bold', 'italic', 'deleted', 'alignment', 'unorderedlist', 'orderedlist', 'link']
137
+ };
138
+ if ((base = this.config).redactorOptions == null) {
139
+ base.redactorOptions = {};
140
+ }
141
+ $.extend(redactor_options, this.config.redactorOptions);
142
+ this.$input.redactor(redactor_options);
143
+ this.$el.css('opacity', 1);
144
+ return typeof (base1 = this.config).onInitialize === "function" ? base1.onInitialize(this) : void 0;
145
+ };
146
+
147
+ InputRedactor.prototype.updateValue = function(value) {
148
+ this.value = value;
149
+ return this.$input.redactor('insert.set', this._safe_value());
150
+ };
151
+
152
+ return InputRedactor;
153
+
154
+ })(InputString);
155
+
156
+ chr.formInputs['redactor'] = InputRedactor;
data/lib/chr/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Chr
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.4"
3
3
  end
data/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "chr",
3
- "version": "0.2.1",
3
+ "version": "0.2.4",
4
4
  "devDependencies": {
5
5
  "grunt": "^0.4.5",
6
- "grunt-contrib-clean": "^0.6.0",
6
+ "grunt-contrib-clean": "^0.6.0",
7
7
  "grunt-contrib-coffee": "^0.13.0",
8
8
  "grunt-contrib-concat": "^0.5.1"
9
9
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Kravets
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-31 00:00:00.000000000 Z
11
+ date: 2015-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bourbon
@@ -68,38 +68,51 @@ files:
68
68
  - LICENSE.md
69
69
  - README.md
70
70
  - Rakefile
71
- - app/assets/javascripts/chr-dist.js
72
71
  - app/assets/javascripts/chr.coffee
73
72
  - app/assets/javascripts/chr/core/chr.coffee
74
73
  - app/assets/javascripts/chr/core/item.coffee
75
- - app/assets/javascripts/chr/core/list-pagination.coffee
76
- - app/assets/javascripts/chr/core/list-reorder.coffee
77
- - app/assets/javascripts/chr/core/list-search.coffee
78
74
  - app/assets/javascripts/chr/core/list.coffee
75
+ - app/assets/javascripts/chr/core/list_config.coffee
76
+ - app/assets/javascripts/chr/core/list_pagination.coffee
77
+ - app/assets/javascripts/chr/core/list_reorder.coffee
78
+ - app/assets/javascripts/chr/core/list_search.coffee
79
79
  - app/assets/javascripts/chr/core/module.coffee
80
80
  - app/assets/javascripts/chr/core/utils.coffee
81
81
  - app/assets/javascripts/chr/core/view.coffee
82
82
  - app/assets/javascripts/chr/form/form.coffee
83
83
  - app/assets/javascripts/chr/form/input-checkbox.coffee
84
84
  - app/assets/javascripts/chr/form/input-color.coffee
85
+ - app/assets/javascripts/chr/form/input-date.coffee
85
86
  - app/assets/javascripts/chr/form/input-file.coffee
87
+ - app/assets/javascripts/chr/form/input-form.coffee
88
+ - app/assets/javascripts/chr/form/input-form_reorder.coffee
86
89
  - app/assets/javascripts/chr/form/input-hidden.coffee
87
90
  - app/assets/javascripts/chr/form/input-list.coffee
91
+ - app/assets/javascripts/chr/form/input-list_reorder.coffee
92
+ - app/assets/javascripts/chr/form/input-password.coffee
88
93
  - app/assets/javascripts/chr/form/input-select.coffee
89
94
  - app/assets/javascripts/chr/form/input-string.coffee
90
95
  - app/assets/javascripts/chr/form/input-text.coffee
91
- - app/assets/javascripts/chr/form/nested-form.coffee
92
96
  - app/assets/javascripts/chr/store/_array-store.coffee
93
97
  - app/assets/javascripts/chr/store/_object-store.coffee
94
98
  - app/assets/javascripts/chr/store/mongosteen-array-store.coffee
95
99
  - app/assets/javascripts/chr/store/mongosteen-object-store.coffee
96
100
  - app/assets/javascripts/chr/store/rest-array-store.coffee
97
101
  - app/assets/javascripts/chr/store/rest-object-store.coffee
102
+ - app/assets/javascripts/chr/vendor/ace.js
98
103
  - app/assets/javascripts/chr/vendor/jquery.scrollparent.js
99
104
  - app/assets/javascripts/chr/vendor/jquery.textarea_autosize.js
100
105
  - app/assets/javascripts/chr/vendor/jquery.typeahead.js
106
+ - app/assets/javascripts/chr/vendor/marked.js
107
+ - app/assets/javascripts/chr/vendor/mode-html.js
108
+ - app/assets/javascripts/chr/vendor/mode-markdown.js
109
+ - app/assets/javascripts/chr/vendor/redactor.fixedtoolbar.js
101
110
  - app/assets/javascripts/chr/vendor/slip.js
111
+ - app/assets/javascripts/input-html.coffee
112
+ - app/assets/javascripts/input-markdown.coffee
113
+ - app/assets/javascripts/input-redactor.coffee
102
114
  - app/assets/stylesheets/_chr.scss
115
+ - app/assets/stylesheets/_input-redactor.scss
103
116
  - app/assets/stylesheets/core/_icons.scss
104
117
  - app/assets/stylesheets/core/_list.scss
105
118
  - app/assets/stylesheets/core/_main.scss
@@ -107,14 +120,17 @@ files:
107
120
  - app/assets/stylesheets/core/_responsive.scss
108
121
  - app/assets/stylesheets/core/_settings.scss
109
122
  - app/assets/stylesheets/form/_form.scss
110
- - app/assets/stylesheets/form/_input_checkbox.scss
111
- - app/assets/stylesheets/form/_input_color.scss
112
- - app/assets/stylesheets/form/_input_file.scss
113
- - app/assets/stylesheets/form/_input_list.scss
114
- - app/assets/stylesheets/form/_input_string.scss
115
- - app/assets/stylesheets/form/_nested_form.scss
123
+ - app/assets/stylesheets/form/_input-checkbox.scss
124
+ - app/assets/stylesheets/form/_input-color.scss
125
+ - app/assets/stylesheets/form/_input-file.scss
126
+ - app/assets/stylesheets/form/_input-form.scss
127
+ - app/assets/stylesheets/form/_input-list.scss
128
+ - app/assets/stylesheets/form/_input-string.scss
116
129
  - bower.json
117
130
  - chr.gemspec
131
+ - dist/chr.js
132
+ - dist/input-ace.js
133
+ - dist/input-redactor.js
118
134
  - docs/assets.md
119
135
  - docs/basics.md
120
136
  - docs/bootstrap-data.md
@@ -1,26 +0,0 @@
1
- # -----------------------------------------------------------------------------
2
- # LIST SCROLL
3
- # todo:
4
- # - trigger onScroll event only when scrolling down
5
- # -----------------------------------------------------------------------------
6
- @_listBindPagination = (listEl) ->
7
- $container = listEl.$el
8
- $list = listEl.$items
9
- arrayStore = listEl.config.arrayStore
10
-
11
- $list.scroll (e) =>
12
- if ! arrayStore.dataFetchLock
13
- $listChildren = $list.children()
14
- listChildrenCount = $listChildren.length
15
- listFirstChildHeight = $listChildren.first().outerHeight()
16
- listHeight = listChildrenCount * listFirstChildHeight
17
- viewHeight = $container.height()
18
-
19
- if listHeight < (viewHeight + e.target.scrollTop + 100)
20
- listEl._show_spinner()
21
- arrayStore.load()
22
-
23
-
24
-
25
-
26
-
@@ -1,70 +0,0 @@
1
- # -----------------------------------------------------------------------------
2
- # LIST REORDER
3
- # -----------------------------------------------------------------------------
4
- # Dependencies:
5
- # - slip
6
- # -----------------------------------------------------------------------------
7
-
8
- @_listBindReorder = (listEl) ->
9
- items = listEl.items
10
- list = listEl.$items.get(0)
11
- arrayStore = listEl.config.arrayStore
12
-
13
- config = arrayStore.reorderable
14
-
15
- # this is optimistic scenario when assumes that all positions are different
16
- _getObjectNewPosition = (el) ->
17
- $el =$ el
18
-
19
- nextObjectId = $el.next().attr('data-id')
20
- prevObjectId = $el.prev().attr('data-id')
21
- nextObjectPosition = 0
22
- prevObjectPosition = 0
23
-
24
- if prevObjectId
25
- prevObjectPosition = items[prevObjectId].position()
26
-
27
- if nextObjectId
28
- nextObjectPosition = items[nextObjectId].position()
29
-
30
- if arrayStore.sortReverse
31
- newPosition = nextObjectPosition + Math.abs(nextObjectPosition - prevObjectPosition) / 2.0
32
- else
33
- newPosition = prevObjectPosition + Math.abs(nextObjectPosition - prevObjectPosition) / 2.0
34
-
35
- return newPosition
36
-
37
- new Slip(list)
38
-
39
- list.addEventListener 'slip:beforeswipe', (e) -> e.preventDefault()
40
-
41
- list.addEventListener 'slip:beforewait', ((e) ->
42
- if $(e.target).hasClass("icon-reorder") then e.preventDefault()
43
- ), false
44
-
45
- list.addEventListener 'slip:beforereorder', ((e) ->
46
- if not $(e.target).hasClass("icon-reorder") then e.preventDefault()
47
- ), false
48
-
49
- list.addEventListener 'slip:reorder', ((e) =>
50
- # when `e.detail.insertBefore` is null, item put to the end of the list.
51
- e.target.parentNode.insertBefore(e.target, e.detail.insertBefore)
52
-
53
- objectPositionValue = _getObjectNewPosition(e.target)
54
- objectId = $(e.target).attr('data-id')
55
- value = {}
56
- value["[#{arrayStore.sortBy}"] = "#{ objectPositionValue }"
57
-
58
- arrayStore.update objectId, value,
59
- # error handling
60
- onSuccess: (object) => ;
61
- onError: (errors) => ;
62
-
63
- return false
64
- ), false
65
-
66
- $(list).addClass 'reorderable'
67
-
68
-
69
-
70
-
@@ -1,37 +0,0 @@
1
- # -----------------------------------------------------------------------------
2
- # LIST SEARCH
3
- # -----------------------------------------------------------------------------
4
- @_listBindSearch = (listEl) ->
5
- $input = listEl.$search
6
- arrayStore = listEl.config.arrayStore
7
-
8
- runSearch = (input) ->
9
- query = $(input).val()
10
- listEl._show_spinner()
11
- arrayStore.search(query)
12
-
13
- showSearch = ->
14
- listEl.$el.addClass 'list-search'
15
- $input.find('input').focus()
16
-
17
- cancelSearch = ->
18
- listEl.$el.removeClass 'list-search'
19
- $input.find('input').val('')
20
- listEl._show_spinner()
21
- arrayStore.reset()
22
-
23
- $input.show()
24
-
25
- $input.on 'keyup', 'input', (e) =>
26
- if e.keyCode == 27 # esc
27
- return cancelSearch()
28
-
29
- if e.keyCode == 13 # enter
30
- return runSearch(e.target)
31
-
32
- $input.on 'click', '.icon', (e) => e.preventDefault() ; showSearch()
33
- $input.on 'click', '.cancel', (e) => e.preventDefault() ; cancelSearch()
34
-
35
-
36
-
37
-
@@ -1,164 +0,0 @@
1
- # -----------------------------------------------------------------------------
2
- # NESTED FORM
3
- # -----------------------------------------------------------------------------
4
- class @NestedForm
5
- constructor: (@name, @nestedObjects, @config, @object) ->
6
- @forms = []
7
-
8
- @config.namePrefix ||= name
9
- @config.removeButton = true
10
- @config.formSchema.id = { type: 'hidden' }
11
- @reorderContainerClass = "nested-forms-#{@config.klassName}"
12
-
13
- if @config.sortBy
14
- @config.formSchema[@config.sortBy] = { type: 'hidden' }
15
- if @nestedObjects
16
- # NOTE: this is not required but make things a bit easier on the backend
17
- # as object don't have to be in a specific order.
18
- @nestedObjects.sort (a, b) => parseFloat(a[@config.sortBy]) - parseFloat(b[@config.sortBy])
19
- # NOTE: normalizes nested objects positions
20
- (o[@config.sortBy] = parseInt(i) + 1) for i, o of @nestedObjects
21
-
22
- @$el =$ "<div class='input-stacked nested-forms #{ @config.klassName }'>"
23
-
24
- @_addLabel()
25
- @_addForms()
26
- @_addFormsReorder()
27
- @_addNewButton()
28
-
29
- return this
30
-
31
- _addLabel: ->
32
- if @config.klass in [ 'inline', 'stacked' ]
33
- @$label =$ "<span class='label'>#{ @config.label }</span>"
34
- @$el.append @$label
35
-
36
- @$errorMessage =$ "<span class='error-message'></span>"
37
- @$label.append @$errorMessage
38
-
39
- _addForms: ->
40
- @$forms =$ "<ul>"
41
- @$el.append @$forms
42
-
43
- # if not default value which means no objects
44
- if @nestedObjects != ''
45
- for i, object of @nestedObjects
46
- namePrefix = "#{ @config.namePrefix }[#{ i }]"
47
- @forms.push @_renderForm(object, namePrefix, @config)
48
-
49
- _renderForm: (object, namePrefix, config) ->
50
- formConfig = $.extend {}, config,
51
- namePrefix: namePrefix
52
- rootEl: "<li>"
53
-
54
- form = new Form(object, formConfig)
55
- @$forms.append form.$el
56
-
57
- return form
58
-
59
- _addFormsReorder: ->
60
- if @config.sortBy
61
- list = @$forms.addClass(@reorderContainerClass).get(0)
62
-
63
- new Slip(list)
64
-
65
- list.addEventListener 'slip:beforeswipe', (e) -> e.preventDefault()
66
-
67
- list.addEventListener 'slip:beforewait', ((e) ->
68
- if $(e.target).hasClass("icon-reorder") then e.preventDefault()
69
- ), false
70
-
71
- list.addEventListener 'slip:beforereorder', ((e) ->
72
- if not $(e.target).hasClass("icon-reorder") then e.preventDefault()
73
- ), false
74
-
75
- list.addEventListener 'slip:reorder', ((e) =>
76
- # NOTE: this event called for all parent lists, add a check for context:
77
- # process this event only if target form is in the @forms list.
78
- targetForm = @_findFormByTarget(e.target)
79
- if targetForm
80
- # NOTE: when `e.detail.insertBefore` is null, item put to the end of the list.
81
- e.target.parentNode.insertBefore(e.target, e.detail.insertBefore)
82
-
83
- $targetForm =$ e.target
84
- prevForm = @_findFormByTarget($targetForm.prev().get(0))
85
- nextForm = @_findFormByTarget($targetForm.next().get(0))
86
-
87
- prevFormPosition = if prevForm then prevForm.inputs[@config.sortBy].value else 0
88
- nextFormPosition = if nextForm then nextForm.inputs[@config.sortBy].value else 0
89
- newTargetFormPosition = prevFormPosition + Math.abs(nextFormPosition - prevFormPosition) / 2.0
90
-
91
- targetForm.inputs[@config.sortBy].updateValue(newTargetFormPosition)
92
-
93
- return false
94
- ), false
95
-
96
- @_addFormReorderButton(form) for form in @forms
97
-
98
- _addFormReorderButton: (form) ->
99
- form.$el.append("""<div class='icon-reorder' data-container-class='#{@reorderContainerClass}'></div>""").addClass('reorderable')
100
-
101
- _findFormByTarget: (el) ->
102
- if el
103
- for form in @forms
104
- if form.$el.get(0) == el then return form
105
- return null
106
-
107
- _addNewButton: ->
108
- label = @config.newButtonLabel || "Add"
109
- @$newButton =$ """<a href='#' class='nested-form-new'>#{ label }</a>"""
110
- @$el.append @$newButton
111
- @$newButton.on 'click', (e) => e.preventDefault() ; @addNewForm()
112
-
113
- #
114
- # PUBLIC
115
- #
116
-
117
- addNewForm: (object=null) ->
118
- namePrefix = "#{ @config.namePrefix }[#{ Date.now() }]"
119
- newFormConfig = $.extend({}, @config)
120
-
121
- delete newFormConfig.formSchema.id
122
-
123
- form = @_renderForm(object, namePrefix, newFormConfig)
124
- form.initializePlugins()
125
-
126
- if @config.sortBy
127
- @_addFormReorderButton(form)
128
- prevForm = _last(@forms)
129
- position = if prevForm then prevForm.inputs[@config.sortBy].value + 1 else 1
130
- form.inputs[@config.sortBy].updateValue(position)
131
-
132
- @forms.push(form)
133
-
134
- @config.onNew?(form)
135
-
136
- return form
137
-
138
- initialize: ->
139
- for nestedForm in @forms
140
- nestedForm.initializePlugins()
141
- @config.onInitialize?(this)
142
-
143
- showErrorMessage: (message) ->
144
- @$el.addClass 'error'
145
- @$errorMessage.html(message)
146
-
147
- hideErrorMessage: ->
148
- @$el.removeClass 'error'
149
- @$errorMessage.html('')
150
-
151
- updateValue: (@value) ->
152
- # TODO: update
153
-
154
- hash: (hash={})->
155
- hash[@config.klassName] = []
156
- for form in @forms
157
- hash[@config.klassName].push form.hash()
158
- return hash
159
-
160
- _chrFormInputs['form'] = NestedForm
161
-
162
-
163
-
164
-