Coffeescript从选择框值更改的列表中动态创建/调用函数

时间:2012-11-02 16:06:01

标签: coffeescript pixastic jquery-select2

我正在使用Pixastic library添加一些图像编辑工具。想法是用户可以从选择框中选择他们想要的图像或工具的一个方面,然后该工具将显示在选择框下方(我正在使用select2),用户可以通过滑块。这是我到目前为止所做的:

# This seeds the select2 options list   
imageToolsList = [
    {id: 'bl', text: 'Blur'}
    {id: 'bc', text: 'Brightness/Contrast'}
    {id: 'ca', text: 'Color Adjust (RGB)'}
    ...
]

#Creates a select box and calls imageTooler function when the value of the box is changed
$(".image_tools_select").each ->
    $(@).select2
        placeholder: "Select an adjustment tool."
        data: imageToolsList
    $(@).on("change", (i) ->
        imageTooler JSON.stringify(
            val: i.val
            clipName: $(@).closest('.clip').attr('id')
        )
    )

# The function called on the value that the select box is changed to
imageTooler = (i) ->
    imageData = jQuery.parseJSON(i)
    iId = imageData.val
    imageClipName = imageData.clipName
    newTool = "<div id=#{iId}><label>#{iId}</label><div class='slider#{iId}'></div></div>"
    $("##{imageClipName}").find(".imagetoolfields").append newTool

当选择工具时,成功添加编辑工具的名称和选择框下方的正确滑块div,但我真正喜欢的是为该特定工具和图像动态创建滑块功能(有页面上有多个图像,每个图像都有自己的编辑工具带。这是一个适用于“模糊”工具的滑块功能:

$('.sliderbl').slider
    min: 0
    max: 5
    value: 0.5
    step: 0.1
    range: "min"
    slide: (event, ui) ->
        $("#img_snapshot_16").pixastic("blurfast", {amount:ui.value})

有没有办法扩展imageToolsList,使其看起来像:

imageToolsList = [
    {id: 'bl', text: 'Blur', tool: $("##{imageClipName}").pixastic("blurfast", {amount:ui.value}), sliderVals: {min: 0, max: 5, value: 0.5, step: 0.1, range: "min"} }
    ...
]

然后为imageTooler中的每个工具动态创建jQuery滑块函数,就像使用div和slider div一样?

1 个答案:

答案 0 :(得分:1)

评论对于任何复杂的事情都会有点乏味,所以我会继续将它全部映射出来。我已经对在何时何地定义的内容做了一些假设,但我认为这些假设并不重要。

我们将从简化的案例开始:只有一个与imageToolsList中的对象类似的对象:

{
    id: 'bl'
    text: 'Blur'
    sliderVals: { min: 0, max: 5, value: 0.5, step: 0.1, range: "min" }
    tool: (imageClipName) ->
        (event, ui) -> $("##{imageClipName}").pixastic("blurfast", {amount:ui.value})
}

我稍微调整了一下顺序,并将tool切换为一个返回函数的函数。当您在pixastic中定义对象文字时,我们不希望imageToolsList调用发生,使tool函数允许我们将pixastic执行推迟到稍后。由于我们(大概)在定义imageClipName时不知道imageToolsList应该是什么,我们需要另一个函数来允许我们再次调用pixastic,直到更晚;因此函数返回一个函数技巧。

鉴于其中一项,我们如何建立slider电话?我们需要做的就是复制sliderVals(以避免更改imageToolsList)并填写slide函数:

sliderDef = { id: 'bl', ... }
doTheSliderThing = (imageClipName) ->
    slide = sliderDef.tool(imageClipName)
    args  = $.extend({ }, sliderDef.sliderVals, slide: slide)
    $(".slider#{sliderDef.id}").slider(args)

# And make it all go and pixastic-ify `#pancakes`.
doTheSliderThing('pancakes')

tool是一个返回回调函数的函数,因此sliderDef.tool(imageClipName)为我们提供了适当的

(event, ui) -> $(...).pixastic(...)

回调函数。

如果我们有id并且我们想要imageToolList的相应条目,那么我们必须去寻找它:

# If the list is short:
[sliderDef] = (o for o in imageToolList when o.id == id)

for loop会返回一个数组,然后是[sliderDef] unwraps that array,并将单个结果保留在sliderDef中。如果imageToolList更长,那么一旦你得到结果,你就想让环路短路并挽救:

# Longer list, bail out as soon as we've found what we're looking for.
for o in imageToolList when o.id == 2
    sliderDef = o
    break

或更好,重新设计imageToolList的结构以允许id直接访问:

# Even longer list: allow direct access by `id`.
imageToolList =
    bl: { text: 'Blur', sliderVals: { ... }, ... }
    ...

然后我们可以做这样的事情:

doTheSliderThing = (id, imageClipName) ->
    sliderDef = imageToolList[id]
    slide     = sliderDef.tool(imageClipName)
    args      = $.extend({ }, sliderDef.sliderVals, slide: slide)
    $(".slider#{id}").slider(args)

# And make it all go and pixastic-ify `#pancakes` using `'bl'`.
doTheSliderThing('bl', 'pancakes')

或者,如果你更喜欢简洁:

doTheSliderThing = (id, imageClipName) ->
    $(".slider#{id}").slider($.extend({ }
        imageToolList[id].sliderVals
        slide: imageToolList[id].tool(imageClipName)
    ))

评论更新:如果您有:

sliderDefs = 
    bl: { text: 'Blur', sliderVals: { ... }, ... }
    ...

然后你可以像这样构建slider2想要的东西:

opts = ({id: k, text: v.text} for k,v of sliderDefs)