2012-08-05 4 views
3

중복 된 JavaScript 코드를 제거하려고합니다. 나는 많은 페이지가 <input type="file">입니다. 각각은 이미지를로드하고 몇 가지 고유 한 처리를 수행합니다. DOM 이벤트 핸들러의 중복 JavaScript 코드를 제거하는 방법은 무엇입니까?

inputFile1.onchange = function (e) { 
     var file = e.target.files[0]; 
     if (typeof file == 'undefined' || file == null) { 
      return; 
     } 
     var imageType = /image.*/; 
     if (!file.type.match(imageType)) { 
      window.alert('Bad file type!'); 
      return; 
     } 
     var reader = new FileReader(); 
     reader.onloadend = function (e) { 
      var imageLoader = new Image(); 
      imageLoader.onload = function() { 
       // process image 
      }; 
      imageLoader.src = e.target.result; 
     }; 
     reader.readAsDataURL(file); 
    }; 

inputFile2.onchange = ... (repeats all but process image) 
inputFile3.onchange = ... (repeats all but process image) 

process image 코멘트에서 코드가 달라집니다 문제는 그 다음 코드의 많은 중복을 가지고있다. 주변 중복 코드를 제거하려면 어떻게해야합니까?

JavaScript 함수가 객체라는 것을 알고 있습니다. 함수 객체를 정의하고 각 객체에 process image 다른 함수를 전달하여 각 이벤트 핸들러에 대해 하나의 별개의 인스턴스를 만드는 방법은 무엇입니까?

인수로 각각의 콜백을 복용 폐쇄와 같은 기능을위한 발전기를 만들 수 있습니다

답변

3

:

function getChangeHandler(loadCallback) { 
    return function (e) { 
     var file = e.target.files[0]; 
     if (typeof file == 'undefined' || file == null) { 
      return; 
     } 
     var imageType = /image.*/; 
     if (!file.type.match(imageType)) { 
      window.alert('Bad file type!'); 
      return; 
     } 
     var reader = new FileReader(); 
     reader.onloadend = function (e) { 
      var imageLoader = new Image(); 
      imageLoader.onload = loadCallback; // <= uses the closure argument 
      imageLoader.src = e.target.result; 
     }; 
     reader.readAsDataURL(file); 
    }; 
} 
inputFile1.onchange = getChangeHandler(function() { /* custom process image */ }); 
inputFile2.onchange = getChangeHandler(function() { /* custom process image */ }); 
inputFile3.onchange = getChangeHandler(function() { /* custom process image */ }); 

는 다른, 결국 우수한 접근 방식에 대해 하나의 change -event 처리기를 사용하는 것

var imageProcessors = { 
    "box1": function() { … }, 
    "anotherbox": function() { … }, 
    … 
}; 
function changeHandler(e) { 
    var input = this; // === e.target 
    … 
    reader.onloadend = function (e) { 
     … 
     imageLoader.onload = imageProcessors[input.id]; 
    }; 
} 
// and bind this one function on all inputs (jQuery-style): 
$("#box1, #anotherbox, …").click(changeHandler); 
1

요 : 동적 name 또는 id 입력하여 사용자 정의 이미지 프로세서를 선택하는 모든 입력,

function processFile(callback) { //callback is the unique file processing routine 
    return function(e) { 
     var file = e.target.files[0]; 
     if (typeof file == 'undefined' || file == null) { 
      return; 
     } 
     var imageType = /image.*/; 
     if (!file.type.match(imageType)) { 
      window.alert('Bad file type!'); 
      return; 
     } 
     var reader = new FileReader(); 
     reader.onloadend = function (e) { 
      var imageLoader = new Image(); 
      imageLoader.onload = callback; //Put it here! 
      imageLoader.src = e.target.result; 
     }; 
     reader.readAsDataURL(file); 
    }; 
} 

는 다음과 같이 전화 :

inputFile1.onchange = processFile(function() { 
     //file processing for number 1 
}); 
inputFile2.onchange = processFile(function() { 
     //file processing for number 2 
}); 
inputFile3.onchange = processFile(function() { 
     //file processing for number 3 
}); 
+0

함수를 반환하는 함수를 사용할 필요가 없습니다. 공통 기능에 onchange 만 지정하면됩니다. – jfriend00

+1

@ jfriend00 비공식 함수를'input [type = "file"]'에 연결하는 방법이 필요합니다. – Dennis

+0

응? 당신은 'e' 매개 변수로부터 이벤트를 일으키는 객체를 얻을 수 있습니다. 그리고 나는 당신이 여분의 기능 수준으로 추가 작업을하는 것을 보지 못합니다. 그것은 나에게 요구하지 않는다. – jfriend00

1

여기 단지 믹스에 던져하기 위해, EMCA5 솔루션입니다 u는 함수를 반환하는 함수를 작성할 수 있습니다. 요소에 따라 동적 이벤트 콜백을 바인딩합니다.

나는 각 필드에 ID (input1 등)가 있다고 가정했으나 코드의 일부 수정 (즉, 다른 수단으로 트리거 요소를 식별)이 필요하지 않았습니다.

Array.prototype.slice.call(document.querySelectorAll('input[type=file]')).forEach(function(element) { 

    /* prepare code specific to the element */ 
    var input_specific_code = (function() { 
     switch (element.id) { 
      case 'input1': return function() { /* #input1 code here */ }; 
      case 'input2': return function() { /* #input2 code here */ }; 
      case 'input3': return function() { /* #input3 code here */ }; 
     } 
    })(); 

    element.addEventListener('change', (function(input_specific_code) { return function(evt) { 
     var id_of_trigger_input = element.id; 

     /* common code here */ 

     /* element-specific code */ 
     input_specific_code(); 

     /* continuation of common code */ 

    }; })(input_specific_code), false); 
}); 
+0

'element.id'를 스위치에 직접 입력하지 않으시겠습니까? 또한이 접근법은 모든 n 입력에 대한 코드를 모두 포함하지만 그 중 하나만 필요로하는 n 개의 함수를 생성합니다. – Bergi

+0

사실 - 나는 ECMA5에서 방금 '스케치'했다. 대신 폐쇄를 사용하도록 수정되었습니다. – Utkanos

관련 문제