#http://www.kryogenix.org/code/browser/custom-drag-image.html
#http://www.html5rocks.com/en/tutorials/dnd/basics/#toc-examples
class window.Editor extends Backbone.View
el: '#chaskiq-mail-editor'
events: ->
'keyup .note-editable': 'copyToFocusedElement'
'drag .blocks li a' : 'drag'
"click #editor-controls #save" : "saveAndClose"
#propery changer
"changeColor.colorpicker .colorpicker": "changeColor"
"change .text-size-picker": "changeProperty"
"change .font-picker": "changeProperty"
"change .font-weight": "changeProperty"
"change .font-spacing": "changeProperty"
"change .font-align": "changeProperty"
#"submit form" : "submitEditor" #get recursion!
"click input.submit": "submitEditor"
initialize: ->
@textarea = $(@el).find('#campaign_html_content')
@css = $(@el).find('#campaign_css')
window.current_editor = @
@placeholder = null
@files = []
setIframe: (iframe)->
@iframe = iframe
copyToEditor: (ev)->
$this = $(ev.currentTarget);
window.setTimeout ()=>
$(@iframe.el).find('#mail-editor').html($this.val());
, 0
buildOptionsFromStyles: ()->
@renderBlockDesignSettings()
copyToTextArea: ()->
$this = $(@iframe.el).find("#mail-editor")
window.setTimeout ()=>
$(@el).find('#campaign_html_content').val($this.html());
, 0
copyToFocusedElement: (ev)->
@currentFocused().find('.mcnTextContent').html($(ev.currentTarget).html())
@copyToTextArea()
copyCssRulesToTextArea: ()->
rules = _.map @style().cssRules , (rule)->
rule.cssText
$("#campaign_css").val(rules.join(" "))
submitEditor: (ev)->
@removeTplBlockControls()
@copyToTextArea()
@copyCssRulesToTextArea()
setTimeout ->
$(ev.currentTarget).submit()
, 600
template: ->
'
dsfsd
'
render: ->
document.getElementById("editor-frame").onload = ()=>
#iframe loaded
@iframe = $("#editor-frame")[0].contentWindow.iframe
#@buildOptionsFromStyles()
$("#tab-2").html(@baseStylesTemplate("accordeon", @definitionsForEditor()))
$('.colorpicker').colorpicker();
if _.isEmpty(@textarea.val())
$(@iframe.el).find('#mail-editor').html(@baseTemplate())
else
$(@iframe.el).find('#mail-editor').html(@textarea.val()); #init from saved content
#$(@el).find('#mail-editor').html(@baseTemplate()) #init from base js tamplarte
#$("#tab-2").html(@baseStylesTemplate("accordeon", @definitionsForEditor()))
#@removeTplBlockControls() #for legacy already embeded tmp controls
#@addTplBlockControls()
removeTplBlockControls: ->
$(".tpl-block-controls").remove()
addTplBlockControls: ->
_.each $(".chaskiqBlock.tpl-block"), (n)=>
$(n).append(@templateBlockControls())
displaySections: (ev)->
#console.log($(ev.currentTarget))
#console.log($(ev.currentTarget).hasClass("tpl-container"))
container = $(ev.currentTarget).parent(".tpl-container")
#_.each $('.tpl-container'), (n)->
# return if $(n).find(".legend").length > 0
# #debugger
# #$(n).append("#{$(n).attr("mc:container")}
")
container.append("#{$(container).attr("mc:container")}
")
container.addClass("default")
if container.hasClass("tpl-container")
container.addClass("over").removeClass("default")
container.find(".legend").addClass("over").removeClass("default")
ev.preventDefault()
setDraggedEl: (e)->
@crt = $(e.currentTarget).parents(".tpl-block")[0].cloneNode(true) #.clone()
@crt.style.backgroundColor = "white";
@crt.style.position = "absolute";
@crt.style.border = "1px solid #666";
@crt.style.boxShadow = "1px 2px 2px #adadad"
@crt.style.top = "0px";
@crt.style.right = "0px";
@crt.style.opacity = 0.9;
@crt.style.zIndex = -9999;
document.body.appendChild(@crt);
e.dataTransfer = e.originalEvent.dataTransfer;
e.dataTransfer.setDragImage(@crt, 0, 0);
removeDraggedEl: ->
$(@crt).remove()
displayItemOver: (ev)->
@displaySections(ev)
$('.tpl-block').removeClass("chaskiqDndItemBefore")
if $(ev.currentTarget).hasClass("tpl-block")
$(ev.currentTarget).addClass("chaskiqDndItemBefore")
ev.preventDefault()
hideSections: ()->
$('.tpl-container').removeClass("default").removeClass("over")
_.each $('.tpl-container'), (n)->
$(n).find(".legend").remove()
drag: (ev)->
#console.log(ev.currentTarget)
@dragged = $(ev.currentTarget)
allowDrop: (ev)->
#console.log("allos drop")
ev.preventDefault()
displayEmptyBlocks: ->
_.each $('.tpl-container'), (container)->
empty_message = $(container).find('.chaskiqContainerEmptyMessage')
if $(container).find(".tpl-block").length > 0
empty_message.hide()
else
empty_message.show()
dropBlock: (container, tmpl)->
#drop on before item or in tpl-container
if $(".tpl-block.chaskiqDndItemBefore").length > 0
container.find(".tpl-block.chaskiqDndItemBefore").before(tmpl)
container.find('.chaskiqContainerEmptyMessage').hide()
else
container.find(".tpl-container").append(tmpl)
#container.find('.chaskiqContainerEmptyMessage').hide()
releaseBeforeItem: ()->
$(".tpl-block").removeClass("chaskiqDndItemBefore")
displayWysiwyg: ->
$('.block-settings').show()
$('.main-settings').hide()
@initWysiwyg()
false
displayBlockButtons: ->
$('.block-settings').hide()
$('.main-settings').show()
false
saveAndClose: ->
@copyToTextArea()
@displayBlockButtons()
false
currentFocused: ()->
$(@.iframe.el).find(".tpl-block.focus")
initWysiwyg: ->
$('.summernote').destroy()
InitSummernote()
$('.summernote').code(@currentFocused().find('.mcnTextContent').html());
handleBlock: (block_type)->
html = ""
switch block_type
when "boxed"
html = @boxedBlock()
when "text"
html = @textBlock()
when "separator"
html = @separatorBlock()
when "image"
html = @imageBlock()
when "image_group"
html = @imageGroupBlock()
when "image_card"
html = @imageCardBlock()
else
console.log "Nada"
@wrapBlock(html)
deleteBloc: (ev)->
target = $(ev.currentTarget)
container = target.parents(".tpl-container")
target.parents(".tpl-block").remove()
if container.find(".tpl-block").length is 0
container.find(".chaskiqContainerEmptyMessage").show()
false
emptyContainerMessage: ()->
"Drop Content Blocks Here
"
wrapBlock: (content)->
"
#{content}
#{@templateBlockControls()}
"
templateBlockControls: ->
""
baseTemplate: ()->
"
|
|
#{@emptyContainerMessage()}
|
|
|
|
"
boxedBlock: ()->
"
This is a Text Block. Use this to provide text...
|
|
|
"
textBlock: ()->
"
This is a Text Block. Use this to provide text...
|
|
"
separatorBlock: ()->
""
imageBlock: ()->
""
imageGroupBlock: ()->
""
imageCardBlock: ()->
"
|
Your text caption goes here
|
|
"
subscriptionBlock: ()->
"
©
{{campaign_description}}
Our mailing address is:
{{campaign_url}}
unsubscribe from this list
update subscription preferences
|
|
"
listenerForImagesReplace: ()->
$('.image-selector').on "click", ()->
html = current_editor.placeholder.parents(".mcpreview-image-uploader")
url = $(this).data('image-url')
current_editor.replaceImagePreview(html, url )
false
checkExistentImages: (placeholder)->
#@targetForUpload = $(ev.currentTarget)
$.ajax
url: $("#editor-container").data("attachments-path")
dataType: "json"
success: (data)=>
Chaskiq.Helpers.showModal(@templateForAttachments(data), "dsdsda")
@placeholder = placeholder
@listenerForImagesReplace()
$('#myModal input[type=file]').on 'change', @prepareUpload
$('#myModal #upload-form').on 'submit', @uploadFiles
error: (err)->
alert("error retrieving files")
replaceImagePreview: (html_to_replace, url)->
html_to_replace.replaceWith( "" );
Chaskiq.Helpers.hideModal()
@copyToTextArea()
templateforUploader: ->
""
templateForAttachments: (data)->
html = @templateforUploader()
html += ""
_.each data, (num)->
html += "- "
html += "Select"
html += ""
html += "
"
html += "
"
appendImageToAttachmentList: (data)->
$("#myModal .attachments-modal-list").prepend("
Select
")
@listenerForImagesReplace()
fileUploader: ->
# Catch the form submit and upload the files
prepareUpload: (event) ->
window.current_editor.files = event.target.files
return
uploadFiles: (event) ->
console.log("upload upload!")
event.stopPropagation()
# Stop stuff happening
event.preventDefault()
# Totally stop stuff happening
# START A LOADING SPINNER HERE
# Create a formdata object and add the files
data = new FormData
$.each window.current_editor.files, (key, value) ->
#data.append key, value
data.append "attachment[image]", value
return
$.ajax
url: $("#editor-container").data("attachments-path")
type: 'POST'
data: data
cache: false
dataType: 'json'
processData: false
contentType: false
success: (data, textStatus, jqXHR) ->
if typeof data.error == 'undefined'
# Success so call function to process the form
# submitForm event, data
current_editor.appendImageToAttachmentList(data)
else
# Handle errors here
console.log 'ERRORS: ' + data.error
return
error: (jqXHR, textStatus, errorThrown) ->
# Handle errors here
console.log 'ERRORS: ' + textStatus
# STOP LOADING SPINNER
return
return
defaultStyleSheet: ->
@iframe.findStyleSheet()
style: ->
@defaultStyleSheet()
definitionsForEditor: ->
[
{name: "Page", targets:
[ {name: "Background", selector: "#bodyTable", template: "background", namespace: "Content"},
{name: "Text", selector: "#bodyTable", template: "typography", namespace: "Content"}
]
}
{name: "Preheader", targets:
[{name: "background", selector: "#templatePreheader", template: "background", namespace: "Content"},
{name: "Text", selector: "#templatePreHeader", template: "typography", namespace: "Content"},
{name: "h1", selector: "#templatePreHeader h1", template: "typography", namespace: "Content"},
{name: "h2", selector: "#templatePreHeader h2", template: "typography", namespace: "Content"}]}
{name: "Header", targets:
[{name: "Header background", selector: "#templateHeader", template: "background"} ]}
{name: "Body", targets:
[{name: "body background", selector: "#templateBody", template: "background", namespace: "Content"} ,
{name: "font", selector: ".bodyContainer .mcnTextContent", template: "typography", namespace: "Content"}
{name: "links", selector: ".bodyContainer .mcnTextContent a", template: "typography", namespace: "Content"}
]}
{name: "Footer", targets:
[{name: "background",selector: "#templateFooter", template: "background", namespace: "Content"},
{name: "font", selector: ".footerContainer .mcnTextContent, .footerContainer .mcnTextContent p", template: "typography", namespace: "Content"} ]}
{name: "Columns", targets: []}
]
definitionsForBlocks: ->
[
{name: "mcnBaseTemplate", targets: []}
{name: "mcnBoxedText", targets: [
{name: "background", selector: ".mcnTextContentContainer", template: "background", namespace: "Content"},
{name: "font", selector: ".mcnTextContentContainer", template: "typography", namespace: "Content"}
]}
{name: "mcnText", targets: [
{name: "background", selector: "", template: "background", namespace: "Content"},
{name: "font", selector: "", template: "typography", namespace: "Content"},
{name: "heading 1", selector: "h1", template: "typography", namespace: "Content"} ,
{name: "heading 2", selector: "h2", template: "typography", namespace: "Content"} ,
{name: "page links", selector: "a", template: "typography", namespace: "Content"} ]}
{name: "mcnDivider", targets: []}
{name: "mcnImage", targets: []}
{name: "mcnImageGroup", targets: [
{name: "background", selector: "", template: "background", namespace: "BlockInner"},
]}
{name: "mcnImageCard", targets: [
{name: "background", selector: "", template: "background" , namespace: "BottomContent"},
{name: "font", selector: "", template: "typography", namespace: "BottomContent"}
]}
{name: "mcnSubscription", targets: []}
]
renderBlockDesignSettings: ->
try
$('.colorpicker').colorpicker('destroy')
catch e
console.log(e)
focused = @currentFocused().find("table:first").attr("class")
section = _.find editor.definitionsForBlocks(), (n)=>
"#{n.name}Block" == focused
console.log("section #{focused}" )
if section
console.log("display for #{focused}")
@current_section = section
html = @buildDesignToolForTarget(section)
$("#tab-4").html(html)
$('.colorpicker').colorpicker();
#$('.colorpicker').colorpicker('destroy')
#size, align, fonttype, color, weight, line heigh, letter spacing
baseStylesTemplate: (id, definitions)->
"
#{@colapsiblePanelsFor( id, definitions )}
"
colapsiblePanelsFor: (id, style_types)->
tpl = _.map style_types, (n)=>
"
#{@buildDesignToolForTarget(n)}
"
tpl.join(" ")
buildDesignToolForTarget: (section)->
tpl = _.map section.targets, (n)=>
@templateToolsFor(n , section.name)
""
templateToolsFor: (n, parent_name)->
title = "#{n.name}
"
tools = ""
switch n.template
when "background"
tools = @backgroundFieldsFor(n, parent_name)
when "typography"
tools = @typoFieldsFor(n, parent_name)
[title, tools].join(" ")
rgb2hex: (rgb)->
return if _.isUndefined(rgb)
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
return if (rgb && rgb.length is 4)
"#" +
("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[3],10).toString(16)).slice(-2)
else
''
#dry this
changeColor: (ev)->
target = $(ev.currentTarget)
css = target.data('css')
property = target.data('css-property')
value = @rgb2hex(ev.color.toString())
console.log "changing from #{css}, #{property} #{value}"
if css.length > 0
@iframe.modifyRule(css, property, value)
else
@currentFocused()
.find("table:first")
.find(".#{@current_section.name}#{target.data('namespace')}")
.css(property, value)
changeProperty: (ev)->
target = $(ev.currentTarget)
css = target.data('css')
property = target.data('css-property')
value = target.val()
console.log "changing from #{css}, #{property} #{value}"
if css.length > 0
@iframe.modifyRule(css, property, value)
else
editor.currentFocused()
.find("table:first")
.find(".#{@current_section.name}#{target.data('namespace')}")
.css(property, value)
arrayGen: (n)->
Array.apply(null, length: n).map Number.call, Number
styleforSelector: (target, style_selector, parent_name)->
val = if !target.selector then @currentFocused().find(".#{parent_name}#{target.namespace}") else @.iframe.$el.find(target.selector)
o = val.css(style_selector)
#console.log o
o
backgroundFieldsFor: (target, parent_name)->
style_selector = "background-color"
val = @styleforSelector(target, style_selector, parent_name)
val = @rgb2hex(val)
[""].join(" ")
#border style, width, color
typoFieldsFor: (target, parent_name)->
c = @styleforSelector(target, 'color', parent_name)
color = ""
sizeFont = ""
ff = @styleforSelector(target, 'font-family', parent_name)
familyFont = ""
weight = ""
#styleFont
#weightline
#heightletter
spacingtext = ""
align = ""
[color, sizeFont, familyFont, weight, spacingtext, align].join(" ")