javascript - 클릭 - jquery 파일찾기




프로그래밍 방식으로 생성/활성화 된 파일 입력이 항상 '입력'이벤트를 발생시키는 것은 아닙니다. (2)

귀하의 질문에 Citate : 때로는 (약 1 8), 파일을 선택한 후 입력 이벤트는 파일을 선택 후 발생하지 않습니다.

나는이 동작을 inputchange 이벤트와 함께 Google 크롬 브라우저 엔진 "Blink"를 사용하는 Opera (버전 55.0.2994.61, 최신 버전)를 사용하여 확인할 수 있습니다 . 약 25 명 중 1 명이 발생합니다.

해결책

이것은 더이상 사용하지 않기 때문에 파일 요소 대화 상자를 닫은 후에 입력 요소 객체가 삭제되기 때문에 발생합니다. 그리고 그것이 발생하면 input 이나 change 이벤트를받을 수있는 대상이 없습니다.

이 문제를 해결하려면 다음과 같이 숨겨진 객체를 만든 후에 입력 요소를 DOM의 어딘가에 추가하십시오.

fileInputEl.style.display = 'none';
document.body.appendChild(fileInputEl);

이벤트가 시작되면 다음과 같이 삭제할 수 있습니다.

document.body.removeChild(fileInputEl);

전체 예제

function selectFile()
{
    var fileInputEl = document.createElement('input');
    fileInputEl.type = 'file';
    fileInputEl.accept = 'image/*';
    //on this way you can see how many files you select (is for test only):
    fileInputEl.multiple = 'multiple';

    fileInputEl.style.display = 'none';
    document.body.appendChild(fileInputEl);

    fileInputEl.addEventListener('input', function(e)
    {
        // Handle files here...
        console.log('You have selected ' + fileInputEl.files.length + ' file(s).');
        document.body.removeChild(fileInputEl);
    });  

    try
    {
        fileInputEl.dispatchEvent(new MouseEvent('click'));
    }
    catch(e)
    {
        console.log('Mouse Event error:\n' + e.message);
        // TODO:
        //Creating and firing synthetic events in IE/MS Edge:
        //https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/dn905219(v=vs.85)
    }
}
<input type="button" onclick="selectFile()" value="Select file">

증여금 설명의 Citate : 적절한 해결 방법을 제시 한 사람에게 Bounty가 수여됩니다.

내 오래된 제안 된 해결 방법 (지금 부적절한)

setInterval 함수를 사용하여 입력 값이 변경되었는지 확인할 수 있습니다. 새로운 fileInputEl 를 속성으로 저장 intervalID . 항상 새로운 파일 입력 요소를 생성하기 때문에 시작시 (각 버튼을 클릭 할 때마다) 값은 항상 비어 있습니다. 이 값이 변경되면 빈 문자열과 비교할 때이 값을 감지 할 수 있습니다. 그런 다음 우리가 fileInputElfileInputChanged() 함수에 전달하고 간격 함수를 지우거나 중지합니다.

function selectFile()
{
    var fileInputEl = document.createElement('input');
    fileInputEl.type = 'file';
    fileInputEl.accept = 'image/*';
    //on this way you can see how many files you select (is for test only):
    fileInputEl.multiple = 'multiple';

    fileInputEl.intervalID = setInterval(function()
    {
        // because we always create a new file input element then
        // its value is always empty, but if not then it was changed:
        if(fileInputEl.value != '')
            fileInputChanged(fileInputEl);
    }, 100);

    try
    {
        fileInputEl.dispatchEvent(new MouseEvent('click'));
    }
    catch(e)
    {
        console.log('Mouse Event error:\n' + e.message);
        // TODO:
        //Creating and firing synthetic events in IE/MS Edge:
        //https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/compatibility/dn905219(v=vs.85)
    }
}

function fileInputChanged(obj)
{
    // Handle files here...
    console.log('You have selected ' + obj.files.length + ' file(s).');
    clearInterval(obj.intervalID);
}
<input type="button" onclick="selectFile()" value="Select file">

클릭 이벤트 처리기에 다음 코드가있는 웹 응용 프로그램에 단추가 있습니다.

const fileInputEl = document.createElement('input');
fileInputEl.type = 'file';
fileInputEl.accept = 'image/*';

fileInputEl.addEventListener('input', (e) => {
  if (!e.target.files.length) {
    return;
  }

  // Handle files here...
});  

fileInputEl.dispatchEvent(new MouseEvent('click'));

경우에 따라 (약 8 개 중 1 개) 파일을 선택한 후 파일을 선택하면 input 이벤트가 시작되지 않습니다. 나는 이것이 요소의 생명주기를 둘러싼 브라우저 버그라고 생각한다.

이 요소를 페이지에 추가하고 나중에 제거하는 것만 큼 어떨까요? 요즘 현대의 브라우저에서 이것을 처리하는 적절한 방법은 무엇입니까?

Windows 용 Google 크롬으로 테스트 중입니다.

JSFiddle : http://jsfiddle.net/pja1d5om/2/


그건 당신이 거기에있어 매우 흥미로운 버그, 나는 그것을 재현하지 못했습니다.

자신이하는 방식대로 파일 입력에 접근하는 이유가 있습니까? 그것을 시도하고 스타일을 지정하기를 원하기 때문입니까?

나는 이 기사를 읽었으며, 내가하고있는 일을 적용했다. 나는 이것이 잘 작동 함을 발견했다. 이 기사가 시도하는 것은 label 태그의 for 속성을 사용하여 입력에 레이블을 연결하는 것이다. 그런 다음 CSS와 JavaScript에서 파일 입력 태그가 숨겨지고 레이블이 본질적으로 "버튼"역할을합니다.

예를 들면 ...

내가 코드를 약간 변경했지만, 위에서 언급 한 CoDrops의 저자 인 Osvaldas Valutis에 대한 모든 크레딧은 변경되었습니다.

var inputs = document.querySelectorAll('.inputfile');

inputs.forEach(input => {

  var label = input.nextElementSibling,
    labelVal = label.innerHTML;

  input.addEventListener('change', function(e) {

    var fileName = '';

    if (this.files && this.files.length > 1)
      fileName = (this.getAttribute('data-multiple-caption') || '').replace('{count}', this.files.length);
    else
      fileName = e.target.value.split('\\').pop();

    if (fileName)
      label.querySelector('span').innerHTML = fileName;
    else
      label.innerHTML = labelVal;

  });

});
* {
  font-family: sans-serif;
  font-weight: 300;
}

.inputfile {
  display: none;
}

.inputfile+label {
  font-size: 1.25em;
  font-weight: 700;
  color: white;
  background-color: darkred;
  display: inline-block;
  padding: 10px;
  border-radius: 10px;
  border: 1px darkred solid;
  cursor: pointer;
}

.inputfile+label:hover {
  background-color: darkred;
}
<input type="file" name="file" id="file" class="inputfile" data-multiple-caption="{count} files selected" multiple />
<label for="file">Choose a file <span></span></label>

이제 이것이 이것이 당신이 찾고있는 것과 정확히 일치하지 않을 수도 있다는 것을 알고 있습니다. 그러나 이것은 당신이 시도 할 수있는 대안적인 해결책이 될 수 있습니다.





blink