Почему функция Javascript запускается несколько раз в Firefox и только один раз в Chrome, почему? - PullRequest
1 голос
/ 13 февраля 2012

У меня есть поле для загрузки файла, в которое я добавил изменение jQuery.

В chrome все работает отлично, функция loadImage заменяет изображение-заполнитель на рендер для загрузки изображения.В Firefox следующий код визуализируется 3 раза (в консоли 3 «1», но только один «2» из обработчика onchange), и изображение впоследствии удаляется после добавления.

Почему это происходит в 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 ifэто помогает (#project_display_pic - идентификатор поля файла):

    #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 ]

2 голосов
/ 13 февраля 2012

Глядя на код плагина , кажется, что он вызывает ваш обратный вызов рендеринга для событий onload и onerror объекта изображения.Возможно, 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 }
0 голосов
/ 08 мая 2013

firefox вызывает эту функцию несколько раз с ошибкой. этот код также должен работать (проверьте, является ли он объектом изображения, проверив свойство width:

loadImage(file, function(image) {
        if(typeof(image.width) !== "number") { // make sure its an image and not an error
          return;
        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...