card-mod-script 0.13.0 → 0.13.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 (40) 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 +40 -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 +54 -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.min.js +13 -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. data/file/mod_script_script_decko_machine_output/file.js +5 -30
  36. data/file/mod_script_script_jquery_machine_output/file.js +11 -9
  37. data/init/early/init_execjs.rb +3 -0
  38. data/set/all/head_javascript.rb +8 -3
  39. data/set/self/script_mods.rb +1 -1
  40. metadata +44 -10
@@ -0,0 +1,166 @@
1
+ $(document).ready ->
2
+ $('body').on 'click', 'button._nest-apply', () ->
3
+ if $(this).data("index")?
4
+ nest.applyNestToNestListEditor($(this).data("index"))
5
+ else
6
+ nest.applyNestToTinymceEditor($(this).data("tinymce-id"), $(this).data("tm-snippet-start"), $(this).data("tm-snippet-size"))
7
+
8
+ $('body').on 'click', 'button._change-create-to-update', () ->
9
+ tm_id = $(this).closest("form").find("#success_tinymce_id").val()
10
+ nest.changeCreateToUpdate(tm_id)
11
+
12
+ $('body').on 'click', 'button._open-nest-editor', () ->
13
+ form = $(this).closest("._nest-form")
14
+ reference = form.find("._reference").val()
15
+ nest_options = form.find("._nest-options").val()
16
+ encoded_nest = encodeURIComponent "{{#{reference}|#{nest_options}}}"
17
+ nest.openNestEditorForSlot(
18
+ $(this).closest(".card-slot"),
19
+ $(this).closest(".slotter"),
20
+ "index=#{form.data('index')}&tm_snippet_raw=#{encoded_nest}"
21
+ )
22
+
23
+
24
+ window.nest ||= {}
25
+
26
+ $.extend nest,
27
+ # called by TinyMCE
28
+ openNestEditor: (tm, params) ->
29
+ params = nest.editParams(tm) unless params?
30
+ this.openEditorForTm(tm, params, "nest_editor", "modal_nest_editor")
31
+
32
+ openNestEditorForSlot: (slot, slotter, params) ->
33
+ card = if slot[0] then $(slot[0]).attr('data-card-name') else ":update"
34
+ nest.request(card, "nest_editor", "modal_nest_editor", slotter, params)
35
+
36
+ openEditorForTm: (tm, params, overlay_view, modal_view) ->
37
+ params += "&tinymce_id=#{tm.id}"
38
+ slot = $("##{tm.id}").closest(".card-slot")
39
+ slotter = $("##{tm.id}")
40
+ card = if slot[0] then $(slot[0]).attr('data-card-name') else ":update"
41
+ nest.request(card, overlay_view, modal_view, slotter, params)
42
+
43
+ # called by TinyMCE
44
+ openImageEditor: (tm) ->
45
+ params = nest.editParams(tm, "{{", "}}", false) unless params?
46
+ this.openEditorForTm(tm, params,"nest_image", "modal_nest_image")
47
+
48
+ changeCreateToUpdate: (tm_id) ->
49
+ form = $("##{tm_id}").closest("form")
50
+ new_action = form.attr("action").replace("card/create", "card/update")
51
+ form.attr("action", new_action)
52
+
53
+ insertNest: (tm, nest_string) ->
54
+ tm.insertContent(nest_string)
55
+ # insertIndex = nest.offsetAfterInsert(tm, nest_string)
56
+ # params = nest.paramsStr(insertIndex, nest_string)
57
+ # nest.openNestEditor(etm, params)
58
+
59
+
60
+ request: (card, overlay_view, modal_view, slotter, params) ->
61
+ slot = $(".bridge-sidebar > ._overlay-container-placeholder > .card-slot")
62
+
63
+ if slot[0]
64
+ view = overlay_view
65
+ mode = "overlay"
66
+ else
67
+ slot = $($(".card-slot")[0])
68
+ view = modal_view
69
+ mode = "modal"
70
+
71
+ nest.sendRequest(slotter, slot, mode, card, view, params)
72
+
73
+ sendRequest: (slotter, slot, mode, card, view, params) ->
74
+ params = "" unless params?
75
+ url = "/#{card}?view=#{view}&#{params}"
76
+ $.ajax
77
+ url: url
78
+ type: 'GET'
79
+ success: (html) ->
80
+ slot.setSlotContent html, mode, slotter
81
+
82
+ editParams: (tm, prefix="{{", postfix="}}", edit=true) ->
83
+ sel = tm.selection.getSel()
84
+ return nest.paramsStr(0) unless sel? and sel.anchorNode?
85
+
86
+ text = sel.anchorNode.data
87
+ return nest.paramsStr(sel.anchorOffset) unless text
88
+
89
+ offset = sel.anchorOffset
90
+ before = text.substr(0, offset)
91
+ after = text.substr(offset)
92
+ index = {
93
+ before: {
94
+ close: before.lastIndexOf(postfix)
95
+ open: before.lastIndexOf(prefix)
96
+ },
97
+ after: {
98
+ close: after.indexOf(postfix)
99
+ open: after.indexOf(prefix)
100
+ }
101
+ }
102
+ if index.before.open > index.before.close &&
103
+ index.after.close != -1 &&
104
+ (index.after.open == -1 || index.after.close < index.after.open)
105
+ nest_start = index.before.open
106
+ unless name?
107
+ nest_size = index.after.close + offset + 2 - nest_start
108
+ name = text.substr(nest_start, nest_size)
109
+ if edit
110
+ nest.paramsStr(nest_start, name)
111
+ else
112
+ nest.paramsStr(nest_start + nest_size)
113
+ else
114
+ nest.paramsStr(offset)
115
+
116
+ paramsStr: (start, name) ->
117
+ params = ""
118
+ if start?
119
+ params += "&tm_snippet_start=#{start}"
120
+ if name? and name.length > 0
121
+ params += "&tm_snippet_raw=#{encodeURIComponent(name)}"
122
+
123
+ params
124
+
125
+ offsetAfterInsert: (editor, content) ->
126
+ offset = editor.selection.getSel().anchorOffset
127
+ offset - content.lengthr
128
+
129
+ applyNestToTinymceEditor: (tinymce_id, nest_start, nest_size) ->
130
+ nest.applySnippet("nest", tinymce_id, nest_start, nest_size)
131
+
132
+ applyNestToNestListEditor: (index) ->
133
+ row = $("._nest-form[data-index='#{index}']")
134
+ row.find("._reference").val(nest.name())
135
+ row.find("._nest-options").val(nest.options())
136
+ decko.updateAddItemButton(row)
137
+
138
+
139
+ applySnippet: (snippet_type, tinymce_id, start, size) ->
140
+ content = $("._#{snippet_type}-preview").val()
141
+ editor = tinymce.get(tinymce_id)
142
+ if start?
143
+ nest.replaceSnippet(editor, start, size, content)
144
+ else
145
+ editor.insertContent content
146
+ offset = nest.offsetAfterInsert(editor, content)
147
+ $("button._#{snippet_type}-apply").attr("data-tm-snippet-start", offset)
148
+
149
+ $("button._#{snippet_type}-apply").attr("data-tm-snippet-size", content.length)
150
+
151
+ replaceSnippet: (editor, start, size, content) ->
152
+ sel = editor.selection.getSel()
153
+ if sel? and sel.anchorNode? and sel.anchorNode.data?
154
+ text = sel.anchorNode.data
155
+ size = 0 unless size?
156
+ text = "#{text.substr(0, start)}#{content}#{text.substr(start + size)}"
157
+ sel.anchorNode.data = text
158
+ else
159
+ editor.insertContent content
160
+
161
+ updatePreview: (new_val) ->
162
+ new_val = "{{#{nest.name()}|#{nest.options()}}}" unless new_val?
163
+ preview = $("._nest-preview")
164
+ preview.val new_val
165
+ preview.data("nest-options", nest.options())
166
+ preview.data("reference", nest.name())
@@ -0,0 +1,102 @@
1
+ nestNameTimeout = null
2
+
3
+ $(document).ready ->
4
+ $('body').on 'click', '._nest-field-toggle', () ->
5
+ if $(this).is(':checked')
6
+ nest.addPlus()
7
+ else
8
+ nest.removePlus()
9
+
10
+ $('body').on 'input', 'input._nest-name', (event) ->
11
+ nest.nameChanged()
12
+
13
+ unless event.which == 13
14
+ clearTimeout(nestNameTimeout) if nestNameTimeout
15
+ nestNameTimeout = setTimeout (-> nest.updateNameRelatedTabs()), 700
16
+
17
+ $('body').on 'keydown', 'input._nest-name', (event) ->
18
+ if event.which == 13
19
+ clearTimeout(nestNameTimeout) if nestNameTimeout
20
+ nest.updateNameRelatedTabs()
21
+
22
+ $.extend nest,
23
+ name: () ->
24
+ nest.evalFieldOption $('input._nest-name').val()
25
+
26
+ nameChanged: () ->
27
+ new_val = $("._nest-preview").val().replace(/^\{\{[^}|]*/, "{{" + nest.name())
28
+ nest.updatePreview new_val
29
+
30
+ evalFieldOption: (name) ->
31
+ if nest.isField() then "+#{name}" else name
32
+
33
+ isField: ->
34
+ $('._nest-field-toggle').is(":checked")
35
+
36
+ addPlus: () ->
37
+ new_val = $("._nest-preview").val().replace(/^\{\{\+?/, "{{+")
38
+ nest.updatePreview new_val
39
+ $(".input-group.hide-prefix").removeClass("hide-prefix").addClass("show-prefix")
40
+
41
+ removePlus: () ->
42
+ new_val = $("._nest-preview").val().replace(/^\{\{\+?/, "{{")
43
+ nest.updatePreview new_val
44
+ $(".input-group.show-prefix").removeClass("show-prefix").addClass("hide-prefix")
45
+
46
+ rulesTabSlot: () ->
47
+ $("._nest-editor .tab-pane-rules > .card-slot")
48
+
49
+ contentTabSlot: () ->
50
+ $("._nest-editor .tab-pane-content > .card-slot")
51
+
52
+ emptyNameAlert: (show) ->
53
+ if show
54
+ $("._empty-nest-name-alert").removeClass("d-none")
55
+ else
56
+ $("._empty-nest-name-alert:not(.d-none)").addClass("d-none")
57
+
58
+ updateNameRelatedTabs: () ->
59
+ nest.updateRulesTab()
60
+ nest.updateContentTab()
61
+
62
+ updateContentTab: () ->
63
+ $contentTab = nest.contentTabSlot()
64
+ if $contentTab.length > 0
65
+ url = decko.path "#{nest.fullName()}?view=nest_content"
66
+ nest.updateNameDependentSlot($contentTab, url)
67
+
68
+ updateRulesTab: () ->
69
+ $rulesTab = nest.rulesTabSlot()
70
+ url = decko.path "#{nest.setNameForRules()}?view=nest_rules"
71
+ nest.updateNameDependentSlot($rulesTab, url)
72
+
73
+ updateNameDependentSlot: ($slot, url) ->
74
+ name = $("input._nest-name").val()
75
+ if name? && name.length > 0
76
+ nest.emptyNameAlert(false)
77
+ $slot.reloadSlot url
78
+ else
79
+ $slot.clearSlot()
80
+ nest.emptyNameAlert(true)
81
+
82
+ fullName: () ->
83
+ input = $('input._nest-name')
84
+ nest_name = input.val()
85
+ if nest.isField() and input.attr("data-left-name")
86
+ "#{input.attr("data-left-name")}+#{nest_name}"
87
+ else
88
+ nest_name
89
+
90
+ # set in the sense of card set
91
+ setNameForRules: () ->
92
+ input = $('input._nest-name')
93
+ nest_name = input.val()
94
+ if nest.isField()
95
+ if input.attr("data-left-type")
96
+ "#{input.attr("data-left-type")}+#{nest_name}+*type plus right"
97
+ else
98
+ "#{nest_name}+*right"
99
+ else
100
+ return "#{nest_name}+*self"
101
+
102
+
@@ -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,54 @@
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
+ if @parent().hasClass("_overlay-container-placeholder")
17
+ @parent().addClass("overlay-container")
18
+ else
19
+ @wrapAll('<div class="overlay-container">')
20
+ @addClass("_bottomlay-slot")
21
+ @before overlay
22
+
23
+ $slotter.registerAsOrigin("overlay", overlay)
24
+ decko.contentLoaded(overlay, $slotter)
25
+
26
+ replaceOverlay: (overlay) ->
27
+ @overlaySlot().trigger "slotDestroy"
28
+ @overlaySlot().replaceWith overlay
29
+ $(".bridge-sidebar .tab-pane:not(.active) .bridge-pills > .nav-item > .nav-link.active").removeClass("active")
30
+
31
+ isInOverlay: ->
32
+ return @closest(".card-slot._overlay").length
33
+
34
+ removeOverlay: () ->
35
+ slot = @overlaySlot()
36
+ if slot
37
+ slot.removeOverlaySlot()
38
+
39
+ removeOverlaySlot: () ->
40
+ @trigger "slotDestroy"
41
+ if @siblings().length == 1
42
+ bottomlay = $(@siblings()[0])
43
+ if bottomlay.hasClass("_bottomlay-slot")
44
+ if bottomlay.parent().hasClass("_overlay-container-placeholder")
45
+ bottomlay.parent().removeClass("overlay-container")
46
+ else
47
+ bottomlay.unwrap()
48
+ bottomlay.removeClass("_bottomlay-slot").updateBridge(true, bottomlay)
49
+
50
+ #bottomlay.find(".tinymce-textarea").each ->
51
+ # tinymce.EditorManager.execCommand('mceAddControl',true, editor_id);
52
+ # decko.initTinyMCE($(this).attr("id"))
53
+
54
+ @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 && 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
+