card-mod-script 0.13.1 → 0.13.2

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/assets/script/decko/autosave.js.coffee +30 -0
  3. data/assets/script/decko/bridge.js.coffee +31 -0
  4. data/assets/script/decko/card_menu.js.coffee +26 -0
  5. data/assets/script/decko/components.js.coffee +46 -0
  6. data/assets/script/decko/decko.js.coffee +97 -0
  7. data/assets/script/decko/doubleclick.js.coffee +30 -0
  8. data/assets/script/decko/editor.js.coffee +55 -0
  9. data/assets/script/decko/filter.js.coffee +176 -0
  10. data/assets/script/decko/filter_items.js.coffee +128 -0
  11. data/assets/script/decko/filter_links.js.coffee +81 -0
  12. data/assets/script/decko/follow.js.coffee +22 -0
  13. data/assets/script/decko/layout.js.coffee +76 -0
  14. data/assets/script/decko/link_editor.js.coffee +61 -0
  15. data/assets/script/decko/mod.js.coffee +85 -0
  16. data/assets/script/decko/modal.js.coffee +113 -0
  17. data/assets/script/decko/name_editor.js.coffee +58 -0
  18. data/assets/script/decko/navbox.js.coffee +74 -0
  19. data/assets/script/decko/nest_editor.js.coffee +166 -0
  20. data/assets/script/decko/nest_editor_name.js.coffee +102 -0
  21. data/assets/script/decko/nest_editor_options.js.coffee +93 -0
  22. data/assets/script/decko/nest_editor_rules.js.coffee +3 -0
  23. data/assets/script/decko/overlay.js.coffee +57 -0
  24. data/assets/script/decko/recaptcha.js.coffee +19 -0
  25. data/assets/script/decko/selectable_filtered_content.js.coffee +12 -0
  26. data/assets/script/decko/slot.js.coffee +182 -0
  27. data/assets/script/decko/slot_ready.js.coffee +11 -0
  28. data/assets/script/decko/slotter.js.coffee +276 -0
  29. data/assets/script/decko/upload.js.coffee +57 -0
  30. data/assets/script/jquery-ui.js +10 -0
  31. data/assets/script/jquery.autosize.js +274 -0
  32. data/assets/script/manifest.yml +44 -0
  33. data/assets/script/script_pointer_config.js.coffee +80 -0
  34. data/assets/script/script_pointer_list_editor.js.coffee +67 -0
  35. metadata +42 -9
@@ -0,0 +1,93 @@
1
+ $(document).ready ->
2
+ $('body').on 'keyup', 'input._nest-option-value', () ->
3
+ nest.updatePreview()
4
+
5
+ $('body').on "select2:select", "._nest-option-name", () ->
6
+ nest.toggleOptionName($(this).closest("._options-select"), $(this).val(), true)
7
+ nest.updatePreview()
8
+
9
+ $('body').on "select2:selecting", "._nest-option-name", () ->
10
+ nest.toggleOptionName($(this).closest("._options-select"), $(this).val(), false)
11
+
12
+ $('body').on "select2:select", "._nest-option-name._new-row", () ->
13
+ $(this).closest(".input-group").find(".input-group-prepend").removeClass("d-none")
14
+ row = $(this).closest("._nest-option-row")
15
+ row.find("._nest-option-value").removeAttr("disabled")
16
+ template = row.parent().find("._nest-option-row._template")
17
+ $(this).removeClass("_new-row")
18
+ nest.addRow(template)
19
+
20
+ $('body').on "click", "._configure-items-button", () ->
21
+ nest.addItemsOptions($(this))
22
+
23
+ $('body').on 'click', 'button._nest-delete-option', () ->
24
+ nest.removeRow $(this).closest("._nest-option-row")
25
+
26
+ $.extend nest,
27
+ showTemplate: (elem) ->
28
+ elem.removeClass("_template") #.removeClass("_#{name}-template").addClass("_#{name}")
29
+
30
+ addRow: (template) ->
31
+ select_tag = template.find("select")
32
+ select_tag.select2("destroy")
33
+ select_tag.removeAttr("data-select2-id")
34
+ double = template.clone()
35
+ #double = template.cloneSelect2(true, true)
36
+ decko.initSelect2(select_tag)
37
+ nest.showTemplate template
38
+ template.after(double)
39
+ decko.initSelect2(double.find("select"))
40
+
41
+ removeRow: (row) ->
42
+ name = row.find("._nest-option-name").val()
43
+ nest.toggleOptionName(row.closest("._options-select"), name,false)
44
+ row.remove()
45
+ nest.updatePreview()
46
+
47
+ addItemsOptions: (button) ->
48
+ container = button.closest("._configure-items")
49
+ next = container.cloneSelect2(true)
50
+ title = button.text()
51
+ button.replaceWith($("<h6>#{title.substr(9)}<h6>"))
52
+ nest.showTemplate container.find("._options-select._template")
53
+ next.find("._configure-items-button").text(title.replace("items", "subitems"))
54
+ container.after(next)
55
+ nest.updatePreview()
56
+
57
+ options: () ->
58
+ options = []
59
+ for ele in $("._options-select:not(._template")
60
+ options.push nest.extractOptions($(ele))
61
+
62
+ level_options = options.map (opts) ->
63
+ nest.toNestSyntax(opts)
64
+ level_options.join "|"
65
+
66
+ # extract options for one item level
67
+ extractOptions: (ele) ->
68
+ options = {}
69
+ nest.addOption(options, $(row)) for row in ele.find("._nest-option-row:not(.template)")
70
+ options
71
+
72
+ addOption: (options, row) ->
73
+ val = row.find("._nest-option-value").val()
74
+ return unless val? && val.length > 0
75
+
76
+ name = row.find("._nest-option-name").val()
77
+ if options[name]?
78
+ options[name].push val
79
+ else
80
+ options[name] = [val]
81
+
82
+ toggleOptionName: (container, name, active) ->
83
+ return true if name == "show" || name == "hide"
84
+ for sel in container.find("._nest-option-name")
85
+ if $(sel).val() != name
86
+ $(sel).find("option[value=#{name}]").attr "disabled", active
87
+ # $(sel).find("option[value=#{val}]").removeAttr "disabled"
88
+ decko.initSelect2($(sel))
89
+
90
+ toNestSyntax: (opts) ->
91
+ str = []
92
+ str.push "#{name}: #{values.join ', '}" for name, values of opts
93
+ str.join "; "
@@ -0,0 +1,57 @@
1
+ jQuery.fn.extend
2
+ overlaySlot: ->
3
+ oslot = @closest(".card-slot._overlay")
4
+ return oslot if oslot[0]?
5
+ oslot = @closest(".overlay-container").find("._overlay")
6
+ oslot[0]? && $(oslot[0])
7
+
8
+ addOverlay: (overlay, $slotter) ->
9
+ if @parent().hasClass("overlay-container")
10
+ if $(overlay).hasClass("_stack-overlay")
11
+ @before overlay
12
+ else
13
+ $("._overlay-origin").removeClass("_overlay-origin")
14
+ @replaceOverlay(overlay)
15
+ else
16
+ #@find(".tinymce-textarea").each ->
17
+ # tinymce.remove("##{$(this).attr("id")}")
18
+ # #tinyMCE.execCommand('mceRemoveControl', false, $(this).attr("id"))
19
+ if @parent().hasClass("_overlay-container-placeholder")
20
+ @parent().addClass("overlay-container")
21
+ else
22
+ @wrapAll('<div class="overlay-container">')
23
+ @addClass("_bottomlay-slot")
24
+ @before overlay
25
+
26
+ $slotter.registerAsOrigin("overlay", overlay)
27
+ decko.contentLoaded(overlay, $slotter)
28
+
29
+ replaceOverlay: (overlay) ->
30
+ @overlaySlot().trigger "slotDestroy"
31
+ @overlaySlot().replaceWith overlay
32
+ $(".bridge-sidebar .tab-pane:not(.active) .bridge-pills > .nav-item > .nav-link.active").removeClass("active")
33
+
34
+ isInOverlay: ->
35
+ return @closest(".card-slot._overlay").length
36
+
37
+ removeOverlay: () ->
38
+ slot = @overlaySlot()
39
+ if slot
40
+ slot.removeOverlaySlot()
41
+
42
+ removeOverlaySlot: () ->
43
+ @trigger "slotDestroy"
44
+ if @siblings().length == 1
45
+ bottomlay = $(@siblings()[0])
46
+ if bottomlay.hasClass("_bottomlay-slot")
47
+ if bottomlay.parent().hasClass("_overlay-container-placeholder")
48
+ bottomlay.parent().removeClass("overlay-container")
49
+ else
50
+ bottomlay.unwrap()
51
+ bottomlay.removeClass("_bottomlay-slot").updateBridge(true, bottomlay)
52
+
53
+ #bottomlay.find(".tinymce-textarea").each ->
54
+ # tinymce.EditorManager.execCommand('mceAddControl',true, editor_id);
55
+ # decko.initTinyMCE($(this).attr("id"))
56
+
57
+ @remove()
@@ -0,0 +1,19 @@
1
+ jQuery.fn.extend {
2
+ updateRecaptchaToken: (event) ->
3
+ recaptcha = @find("input._recaptcha-token")
4
+
5
+ if !recaptcha[0]?
6
+ recaptcha.val "recaptcha-token-field-missing"
7
+ else if !grecaptcha?
8
+ recaptcha.val("grecaptcha-undefined")
9
+ else
10
+ $slotter = $(this)
11
+ event.stopPropagation() if event
12
+ grecaptcha.execute(recaptcha.data("site-key"), action: recaptcha.data("action"))
13
+ .then (token) ->
14
+ recaptcha.val(token)
15
+ recaptcha.addClass("_token-updated")
16
+ if event
17
+ $slotter.submit()
18
+ false
19
+ }
@@ -0,0 +1,12 @@
1
+ $(window).ready ->
2
+
3
+ # TODO: generalize so this works with item views other than bar
4
+ $("body").on "click", "._selectable-filtered-content .bar-body", (e) ->
5
+ item = $(this)
6
+ name = item.slot().data("card-name")
7
+ container = item.closest("._selectable-filtered-content")
8
+ input = $(container.data("input-selector"))
9
+ input.val name
10
+ item.closest('.modal').modal('hide')
11
+ e.preventDefault()
12
+ e.stopPropagation()
@@ -0,0 +1,182 @@
1
+ $.extend decko,
2
+ snakeCase: (str)->
3
+ str.replace /([a-z])([A-Z])/g, (match) -> match[0] + '_' +
4
+ match[1].toLowerCase()
5
+
6
+ # returns full path with slot parameters
7
+ slotPath: (path, slot)->
8
+ params = decko.slotData(slot)
9
+ decko.path(path) + ( (if path.match /\?/ then '&' else '?') + $.param(params) )
10
+
11
+ slotData: (slot) ->
12
+ xtra = {}
13
+ main = $('#main').children('.card-slot').data 'cardName'
14
+ xtra['main'] = main if main?
15
+
16
+ if slot
17
+ xtra['is_main'] = true if slot.isMain()
18
+ slotdata = slot.data 'slot'
19
+ if slotdata?
20
+ decko.slotParams slotdata, xtra, 'slot'
21
+ xtra['type'] = slotdata['type'] if slotdata['type']
22
+ xtra
23
+
24
+ slotEditView: (slot) ->
25
+ data = decko.slotData(slot)
26
+ switch data["slot[edit]"]
27
+ when "inline" then "edit_inline"
28
+ when "full" then "bridge"
29
+ else "edit"
30
+
31
+ slotEditLink: (slot) ->
32
+ edit_links =
33
+ slot.find(".edit-link").filter (i, el) ->
34
+ $(el).slot().data('slotId') == slot.data('slotId')
35
+
36
+ if edit_links[0] then $(edit_links[0]) else false
37
+
38
+ slotParams: (raw, processed, prefix)->
39
+ $.each raw, (key, value)->
40
+ cgiKey = prefix + '[' + decko.snakeCase(key) + ']'
41
+ if key == 'items'
42
+ decko.slotParams value, processed, cgiKey
43
+ else
44
+ processed[cgiKey] = value
45
+
46
+ contentLoaded: (el, slotter)->
47
+ decko.initializeEditors(el)
48
+ notice = slotter.attr('notify-success')
49
+ if notice?
50
+ el.notify notice, "success"
51
+ el.triggerSlotReady(slotter)
52
+
53
+ slotReady: (func)->
54
+ $('document').ready ->
55
+ $('body').on 'slotReady', '.card-slot', (e, slotter) ->
56
+ e.stopPropagation()
57
+ if slotter?
58
+ func.call this, $(this), $(slotter)
59
+ else
60
+ func.call this, $(this)
61
+
62
+ slotDestroy: (func)->
63
+ $('document').ready ->
64
+ $('body').on 'slotDestroy', '.card-slot, ._modal-slot', (e) ->
65
+ e.stopPropagation()
66
+ func.call this, $(this)
67
+
68
+ jQuery.fn.extend
69
+ slot: (status="success", mode="replace") ->
70
+ if mode == "modal"
71
+ @modalSlot()
72
+ else
73
+ @selectSlot("slot-#{status}-selector") ||
74
+ @selectSlot("slot-selector") ||
75
+ @closest(".card-slot")
76
+
77
+ selectSlot: (selectorName) ->
78
+ if selector = @data(selectorName)
79
+ slot = @findSlot selector
80
+ slot && slot[0] && slot
81
+
82
+ isSlot: ->
83
+ $(this).hasClass "card-slot"
84
+
85
+ isMain: ->
86
+ @slot().parent('#main')[0]
87
+
88
+ isMainOrMainModal: ->
89
+ el = $(this)
90
+ el = el.findOriginSlot("modal") if el.closest(".modal")[0]
91
+ el.isMain()
92
+
93
+ findSlot: (selector) ->
94
+ if selector == "modal-origin"
95
+ @findOriginSlot("modal")
96
+ else if selector == "overlay-origin"
97
+ @findOriginSlot("overlay")
98
+ else
99
+ target_slot = @closest(selector)
100
+ parent_slot = @closest '.card-slot'
101
+
102
+ # if slot-selector doesn't apply to a child, search in all parent slots and finally in the body
103
+ while target_slot.length == 0 and parent_slot.length > 0
104
+ target_slot = $(parent_slot).find(selector)
105
+ parent_slot = $(parent_slot).parent().closest '.card-slot'
106
+ if target_slot.length == 0
107
+ $(selector)
108
+ else
109
+ target_slot
110
+
111
+ # type can be "modal" or "overlay"
112
+ findOriginSlot: (type) ->
113
+ overlaySlot = @closest("[data-#{type}-origin-slot-id]")
114
+ origin_slot_id = overlaySlot.data("#{type}-origin-slot-id")
115
+ origin_slot = $("[data-slot-id=#{origin_slot_id}]")
116
+ if origin_slot[0]?
117
+ origin_slot
118
+ else
119
+ console.log "couldn't find origin with slot id #{origin_slot_id}"
120
+
121
+ reloadSlot: (url) ->
122
+ $slot = $(this)
123
+ if $slot.length > 1
124
+ $slot.each ->
125
+ $(this).reloadSlot url
126
+ return
127
+
128
+ $slot = $slot.slot() unless $slot.isSlot
129
+ return unless $slot[0]
130
+
131
+ unless url?
132
+ url = $slot.slotUrl()
133
+ $slot.addClass 'slotter'
134
+ $slot.attr 'href', url
135
+ $slot.data "url", url
136
+ this[0].href = url # that's where handleRemote gets the url from
137
+ # .attr(href, url) only works for anchors
138
+ $slot.data "remote", true
139
+ $.rails.handleRemote($slot)
140
+
141
+ clearSlot: () ->
142
+ @triggerSlotDestroy()
143
+ @empty()
144
+
145
+ slotUrl: ->
146
+ decko.slotPath "#{this.slotMark()}?view=#{@data("slot")["view"]}"
147
+
148
+ slotMark: ->
149
+ if @data('cardId') then "~#{@data('cardId')}" else @data("cardName")
150
+
151
+ setSlotContent: (val, mode, $slotter) ->
152
+ v = $(val)[0] && $(val) || val
153
+
154
+ if typeof(v) == "string"
155
+ # Needed to support "TEXT: result" pattern in success (eg deleting nested cards)
156
+ @slot("success", mode).replaceWith v
157
+ else
158
+ if v.hasClass("_overlay")
159
+ mode = "overlay"
160
+ else if v.hasClass("_modal")
161
+ mode = "modal"
162
+ @slot("success", mode).setSlotContentFromElement v, mode, $slotter
163
+ v
164
+
165
+ setSlotContentFromElement: (el, mode, $slotter) ->
166
+ if mode == "overlay"
167
+ @addOverlay(el, $slotter)
168
+ else if el.hasClass("_modal-slot") or mode == "modal"
169
+ el.showAsModal($slotter)
170
+ else
171
+ slot_id = @data("slot-id")
172
+ el.attr("data-slot-id", slot_id) if slot_id
173
+ @triggerSlotDestroy()
174
+ @replaceWith el
175
+ decko.contentLoaded(el, $slotter)
176
+
177
+ triggerSlotReady: (slotter) ->
178
+ @trigger "slotReady", slotter if @isSlot()
179
+ @find(".card-slot").trigger "slotReady", slotter
180
+
181
+ triggerSlotDestroy: () ->
182
+ @trigger "slotDestroy"
@@ -0,0 +1,11 @@
1
+ decko.slotReady (slot) ->
2
+ slot.find('._disappear').delay(5000).animate(
3
+ height: 0, 1000, -> $(this).hide())
4
+
5
+ if slot.hasClass("_refresh-timer")
6
+ setTimeout(
7
+ -> slot.reloadSlot(slot.data("refresh-url")),
8
+ 2000
9
+ )
10
+
11
+
@@ -0,0 +1,276 @@
1
+ # There are three places that can control what happens after an ajax request
2
+ # 1. the element that triggered the request (eg. a link or a button)
3
+ # 2. the closest ".slotter" element
4
+ # (if the trigger itself isn't a slotter,
5
+ # a common example is that a form is a slotter but the form buttons aren't)
6
+ # 3. the slot returned by the request
7
+ #
8
+ # A slot is an element marked with "card-slot" class, a slotter has a "slotter" class.
9
+ # By the default, the closest slot of the slotter is replaced with the new slot that the
10
+ # request returned. The behavior can be changed with css classes and data attributes.
11
+ #
12
+ # To 1. The trigger element has only a few options to override the slotter.
13
+ # classes:
14
+ # "_close-modal-on-success"
15
+ # "_close-overlay-on-success"
16
+ # "_update-origin"
17
+ #
18
+ # To 2. The slotter is the standard way to define what happens with request result
19
+ # data:
20
+ # slot-selector
21
+ # a css selector that defines which slot will be replaced.
22
+ # You can also use "modal-origin" and "overlay-origin" to refer to the origin slots.
23
+ # slot-success-selector/slot-error-selector
24
+ # the same as slot-selector but only used
25
+ # for success case or error case, respectively
26
+ # update-foreign-slot
27
+ # a css selector to specify an additional slot that will be
28
+ # updated after the request.
29
+ # update-foreign-slot-url
30
+ # a url to fetch the new content for the additional slot
31
+ # if not given the slot is updated with the same card and view that was used before
32
+ # update-origin
33
+ # if present then the slot from where the current modal or overlay slot was opened
34
+ # will be updated
35
+ # slotter-mode
36
+ # possible values are
37
+ # replace (default)
38
+ # replace the closest slot with new slot
39
+ # modal
40
+ # show new slot in modal; if there is already a modal then put it on top
41
+ # modal-replace
42
+ # replace existing modal
43
+ # overlay
44
+ # show new slot in overlay
45
+ # update-origin
46
+ # update closest slot of the slotter that opened the modal or overlay
47
+ # (assumes that the request was triggered from a modal or overlay)
48
+ # If you need the update-origin mode together with another mode then use
49
+ # data-update-origin="true".
50
+ # silent-success
51
+ # do nothing
52
+ #
53
+ # classes:
54
+ # _close-overlay
55
+ # _close-modal
56
+ #
57
+ # To 3. Similar as 1, the slot has only overlay and modal options.
58
+ # classes:
59
+ # _modal
60
+ # show slot in modal
61
+ # _overlay
62
+ # show slot in overlay
63
+ #
64
+ #
65
+ $(window).ready ->
66
+ $('body').on 'ajax:success', '.slotter', (event, data, c, d) ->
67
+ $(this).slotterSuccess event, data
68
+
69
+ $('body').on 'ajax:error', '.slotter', (event, xhr) ->
70
+ $(this).showErrorResponse xhr.status, xhr.responseText
71
+
72
+ $('body').on 'click', 'button.slotter', (event)->
73
+ return false if !$.rails.allowAction $(this)
74
+ $.rails.handleRemote $(this)
75
+
76
+ $('body').on 'click', '._clickable.slotter', (event)->
77
+ $(this)[0].href = $(this).attr("href") # that's where rails.handleRemote
78
+ # expects the url
79
+ $.rails.handleRemote $(this)
80
+
81
+ $('body').on 'click', '[data-dismiss="overlay"]', (event) ->
82
+ $(this).findSlot(".card-slot._overlay").removeOverlay()
83
+
84
+ $('body').on 'click', '._close-overlay-on-success', (event) ->
85
+ $(this).closeOnSuccess("overlay")
86
+
87
+ $('body').on 'click', '._close-modal-on-success', (event) ->
88
+ $(this).closeOnSuccess("modal")
89
+
90
+ $('body').on 'click', '._close-on-success', (event) ->
91
+ $(this).closeOnSuccess()
92
+
93
+ $('body').on 'click', '._update-origin', (event) ->
94
+ $(this).closest('.slotter').data("slotter-mode", "update-origin")
95
+
96
+ $('body').on 'submit', 'form.slotter', (event)->
97
+ form = $(this)
98
+ if form.data("main-success") and form.isMainOrMainModal()
99
+ form.mainSuccess()
100
+ if form.data('recaptcha') == 'on'
101
+ return form.handleRecaptchaBeforeSubmit(event)
102
+
103
+ $('body').on 'ajax:beforeSend', '.slotter', (event, xhr, opt)->
104
+ $(this).slotterBeforeSend opt
105
+
106
+ jQuery.fn.extend
107
+ mainSuccess: ()->
108
+ form = $(this)
109
+ $.each form.data("main-success"), (key, value)->
110
+ inputSelector = "[name=success\\[" + key + "\\]]"
111
+ input = form.find inputSelector
112
+ unless input[0]
113
+ input = $('<input type="hidden" name="success[' + key + ']"/>')
114
+ form.append input
115
+ input.val value
116
+
117
+ slotterSuccess: (event, data) ->
118
+ unless @hasClass("slotter")
119
+ console.log "warning: slotterSuccess called on non-slotter element #{this}"
120
+ return
121
+
122
+ return if event.slotSuccessful
123
+
124
+ if @data("reload")
125
+ window.location.reload(true)
126
+
127
+ if @data("update-modal-origin")
128
+ @updateModalOrigin()
129
+
130
+ if @data("update-origin")
131
+ @updateOrigin()
132
+
133
+ if @data('original-slotter-mode')
134
+ @attr 'data-slotter-mode', @data('original-slotter-mode')
135
+
136
+ mode = @data("slotter-mode")
137
+ @showSuccessResponse data, mode
138
+
139
+ if @hasClass "_close-overlay"
140
+ @removeOverlay()
141
+ if @hasClass "_close-modal"
142
+ @closest('.modal').modal('hide')
143
+
144
+ # should scroll to top after clicking on new page
145
+ if @hasClass "card-paging-link"
146
+ slot_top_pos = @slot().offset().top
147
+ $("body").scrollTop slot_top_pos
148
+ if @data("update-foreign-slot")
149
+ $slot = @findSlot @data("update-foreign-slot")
150
+ reload_url = @data("update-foreign-slot-url")
151
+ $slot.reloadSlot reload_url
152
+
153
+ event.slotSuccessful = true
154
+
155
+ showSuccessResponse: (data, mode) ->
156
+ if mode == "silent-success"
157
+ return
158
+ else if mode == "update-modal-origin"
159
+ @updateModalOrigin()
160
+ else if mode == "update-origin"
161
+ @updateOrigin()
162
+ else if data.redirect
163
+ window.location = data.redirect
164
+ else if data.reload
165
+ window.location.reload(true)
166
+ else
167
+ @updateSlot data, mode
168
+
169
+ showErrorResponse: (status, result) ->
170
+ if status == 403 #permission denied
171
+ $(result).showAsModal $(this)
172
+ else if status == 900
173
+ $(result).showAsModal $(this)
174
+ else
175
+ @notify result, "error"
176
+
177
+ if status == 409 #edit conflict
178
+ @slot().find('.current_revision_id').val(
179
+ @slot().find('.new-current-revision-id').text()
180
+ )
181
+
182
+ updateModalOrigin: () ->
183
+ if @overlaySlot()
184
+ overlayOrigin = @findOriginSlot("overlay")
185
+ overlayOrigin.updateOrigin()
186
+ else if @closest("#modal-container")[0]
187
+ @updateOrigin()
188
+
189
+ updateOrigin: () ->
190
+ type = if @overlaySlot()
191
+ "overlay"
192
+ else if @closest("#modal-container")[0]
193
+ "modal"
194
+
195
+ return unless type?
196
+
197
+ origin = @findOriginSlot(type)
198
+ if origin && origin[0]?
199
+ origin.reloadSlot()
200
+
201
+ registerAsOrigin: (type, slot) ->
202
+ if slot.hasClass("_modal-slot")
203
+ slot = slot.find(".modal-body .card-slot")
204
+ slot.attr("data-#{type}-origin-slot-id", @closest(".card-slot").data("slot-id"))
205
+
206
+ updateSlot: (data, mode) ->
207
+ mode ||= "replace"
208
+ @setSlotContent data, mode, $(this)
209
+
210
+ # close modal or overlay
211
+ closeOnSuccess: (type) ->
212
+ slotter = @closest('.slotter')
213
+ if !type?
214
+ type = if @isInOverlay() then "overlay" else "modal"
215
+ slotter.addClass "_close-#{type}"
216
+
217
+ slotterBeforeSend: (opt) ->
218
+ return if opt.skip_before_send
219
+
220
+ # avoiding duplication. could be better test?
221
+ unless (opt.url.match(/home_view/) or @data("slotter-mode") == "modal")
222
+ opt.url = decko.slotPath opt.url, @slot()
223
+
224
+ if @is('form')
225
+ if data = @data 'file-data'
226
+ # NOTE - this entire solution is temporary.
227
+ @uploadWithBlueimp(data, opt)
228
+ false
229
+
230
+ uploadWithBlueimp: (data, opt) ->
231
+ input = @find '.file-upload'
232
+ if input[1]
233
+ @notify(
234
+ "Decko does not yet support multiple files in a single form.",
235
+ "error"
236
+ )
237
+ return false
238
+
239
+ widget = input.data 'blueimpFileupload' #jQuery UI widget
240
+
241
+ # browsers that can't do ajax uploads use iframe
242
+ unless widget._isXHRUpload(widget.options)
243
+ # can't do normal redirects.
244
+ @find('[name=success]').val('_self')
245
+ # iframe response not passed back;
246
+ # all responses treated as success. boo
247
+ opt.url += '&simulate_xhr=true'
248
+ # iframe is not xhr request,
249
+ # so would otherwise get full response with layout
250
+ iframeUploadFilter = (data)-> data.find('body').html()
251
+ opt.dataFilter = iframeUploadFilter
252
+ # gets rid of default html and body tags
253
+
254
+ args = $.extend opt, (widget._getAJAXSettings data), url: opt.url
255
+ # combines settings from decko's slotter and jQuery UI's upload widget
256
+ args.skip_before_send = true #avoid looping through this method again
257
+
258
+ $.ajax( args )
259
+
260
+ handleRecaptchaBeforeSubmit: (event) ->
261
+ recaptcha = @find("input._recaptcha-token")
262
+
263
+ if !recaptcha[0]?
264
+ # monkey error (bad form)
265
+ recaptcha.val "recaptcha-token-field-missing"
266
+ else if recaptcha.hasClass "_token-updated"
267
+ # recaptcha token is fine - continue submitting
268
+ recaptcha.removeClass "_token-updated"
269
+ else if !grecaptcha?
270
+ # shark error (probably recaptcha keys of pre v3 version)
271
+ recaptcha.val "grecaptcha-undefined"
272
+ else
273
+ @updateRecaptchaToken(event)
274
+ # this stops the submit here
275
+ # and submits again when the token is ready
276
+