在Firefox中只在Firefox中运行多次Javascript函数,为什么?

时间:2012-02-13 07:01:12

标签: javascript jquery ruby-on-rails coffeescript

我有一个文件上传字段,我在其中添加了jQuery更改。

在chrome中它工作得很好,loadImage函数用要上传的pic的渲染替换占位符pic。在firefox中,以下代码呈现3次(在控制台中有3个“1”,但是在onchange处理程序中只有一个“2”),并且图像随后在添加后被删除。

为什么在Firefox中会发生这种情况,我该如何预防呢?

Coffeescript(如果有人喜欢更好地阅读js,我可以转换):

$('#project_display_pic').change (e) ->
  console.log "2"
  value = $(this).val()
  value = value.replace("C:\\fakepath\\","")
  $('#display_pic_uploader > p').text(value)
  loadImage(
    e.target.files[0],
    ( (img) -> 
      console.log "1"
      $('#display_pic_preview > img').remove()
      $('#display_pic_preview').append(img)
    ),
    {maxWidth: 212}
  )

Haml如果有帮助(#project_display_pic是文件字段的id):

    #display_pic_preview
      = image_tag( @project.display_pic.medium.url, :class => "default_pic" )
    #display_pic_uploader
      %p Add display image
      = f.file_field :display_pic

2 个答案:

答案 0 :(得分:2)

查看the plugin's code,它似乎会调用图像对象的onloadonerror事件的渲染回调。也许Firefox错误地将图像缩放视为加载事件或什么?或者错误事件可能没有充分理由被触发。

无论如何,快速修复可能是这样的:

# Builds a function to show the loaded image
# The function stores the last img object it received,
# and doesn't try to show the same one twice in a row
createRenderCallback = ->
  lastImg = null

  (img) ->
    return if img is lastImg # don't handle the same img twice
    # Note that if the image failed to load, `img` will be undefined
    # You may want to check for that before trying to append it
    $('#display_pic_preview > img').remove()
    $('#display_pic_preview').append(img)
    lastImg = img # remember the img

# Attach the file input's change handler (pretty much the same as before)
$('#project_display_pic').change (e) ->
  value = $(this).val().replace("C:\\fakepath\\","")
  $('#display_pic_uploader > p').text(value)
  loadImage e.target.files[0], createRenderCallback(), { maxWidth: 212 }

你可以在插件的代码中做类似的事情,以避免它重新调用回调。或者你可以从插件中记录一些东西,看看到底发生了什么。


编辑:由于将图像插入DOM似乎会触发渲染回调,因此您可以尝试以下操作:

createRenderCallback = ->
  lastImg = null

  (img) ->
    return if img is lastImg
    lastImg = img # <-- Move this line to here, i.e. before inserting the image
    $('#display_pic_preview > img').remove()
    $('#display_pic_preview').append(img)

,您只需删除事件侦听器,而不是保留lastImg的记录

renderCallback = ->
  if img? # this function was called from an onload event
    img.onload = img.onerror = null

  else  # called from an onerror event
    @onload = @onerror = null

  $('#display_pic_preview > img').remove()
  $('#display_pic_preview').append(img) if img?

$('#project_display_pic').change (e) ->
  value = $(this).val().replace("C:\\fakepath\\","")
  $('#display_pic_uploader > p').text(value)
  loadImage e.target.files[0], renderCallback, { maxWidth: 212 }

答案 1 :(得分:0)

firefox多次调用此函数并显示错误。此代码也应该有效(通过检查width属性来检查它是否是图像对象:

loadImage(file, function(image) {
        if(typeof(image.width) !== "number") { // make sure its an image and not an error
          return;
        }
}