위의 코드에서 function이 파라미터로 받는 factory는 하위 function 입니다.
(function(factory){}( 이곳에 있는 것을 factory로 넘겨주기 때문에! ));
typeof define 에서 define과 , module은 둘다 콘솔 찍어봤을 때 is not defined가 되므로 else가 실행됩니다.
else는 factory(jQuery)를 넘겨주므로 저 로직은 어떤 상황에서 jquery를 factory 함수에 넘겨주기 위하여 있는 것 같습니다.
}(function($) {
function($) 함수 스코프 내부에서 $를 console.log 찍으면 return new.n.fn.init(a,b)가 찍히는데, 이건 무엇인지 아직 감이 안옵니다. 아래로 내려가겠습니다.
/****
* Allows plugin behavior simulation in modern browsers for easier debugging.
* When setting to true, use attribute "placeholder-x" rather than the usual "placeholder" in your inputs/textareas
* i.e. <input type="text" placeholder-x="my placeholder text" />
*/
var debugMode = false;
// Opera Mini v7 doesn't support placeholder although its DOM seems to indicate so
var isOperaMini = Object.prototype.toString.call(window.operamini) === '[object OperaMini]';
var isInputSupported = 'placeholder' in document.createElement('input') && !isOperaMini && !debugMode;
var isTextareaSupported = 'placeholder' in document.createElement('textarea') && !isOperaMini && !debugMode;
var valHooks = $.valHooks;
var propHooks = $.propHooks;
var hooks;
var placeholder;
var settings = {};
저는 in 연산자를 처음봤습니다.
in 연산자
[속성(속성 이름이나 배열의 인덱스를 넣어야 함) in 객체명] 으로 사용하고 명시된 속성이 객체에 존재하면 true를 반환한다고 합니다.
mdn에서 예제를 가져와봤는데,
var trees = new Array('red', 'blue');
0 in trees // true
1 in trees // true
2 in trees // false = 인덱스는 1까지 있다
'red' in trees // false = 배열의 키 값은 포함안된다
'length' in trees // true = length는 array 객체의 속성이어서 해당된다.
if ($input.data('placeholder-password')) {
$input = $input.hide().nextAll('input[type="password"]:first').show().attr('id', $input.removeAttr('id').data('placeholder-id'));
// If `clearPlaceholder` was called from `$.valHooks.input.set`
if (event === true) {
$input[0].value = value;
return value;
}
$input.focus();
} else {
input == safeActiveElement() && input.select();
}
또 if, else의 기로에 놓이게 되는데, if를 먼저 보면 data로 placeholder-password가 있는지 분기합니다.
이것도 콘솔로 찍어보게 되면, text 타입이랑, password 타입이 다른 data를 가지고 있음을 알게됩니다.
text 타입
password 타입
그렇습니다, 이 if는 password 타입이 있을 때 분기하여 다른 로직을 실행하는데 사용합니다.
$input = $input.hide().nextAll('input[type="password"]:first').show().attr('id', $input.removeAttr('id').data('placeholder-id'));
// If `clearPlaceholder` was called from `$.valHooks.input.set`
if (event === true) {
$input[0].value = value;
return value;
}
$input.focus();
그 다음 $input에 현재 input을 숨기고,,,
nextAll()라는 jQuery API메소드를 사용합니다.
nextAll()은 해당 엘리먼트 이후에 오는 모든 엘리먼트라고 합니다.
예를 들어 아래와 같은 상황일 때, $('.first').nextAll()이면 2,3,4의p가 됩니다.
password타입 input이 특성 상 *****로 표시되기 때문에 text input이 필요했던 것입니다.
그래서 확인해 보면 $input은 새로 생긴 text 타입인 input이고, clearPlaceholder를 하게되면 새로 생긴 text input을 hide합니다.
nextAll()을 사용해서로 내가 html 마크업할 때 넣었던 password input을 show해주면서요.
(이것으로 보아 placeholder 생성 시에 반대로 해줄 것으로 보입니다.)
그 후 attr()로 id에 data로 저장되어 있던 placeholder-id 값을 넣어줍니다.(없으면 빈 값 인듯 싶네요)
if (event === true) {
$input[0].value = value;
return value;
}
$input.focus();
password 타입이 아닐 때의 경우 else를 봐보자
} else {
input == safeActiveElement() && input.select();
}
로직을 내려가보면 if 문을 다시 만나는데, 여기서 event가 true일 때 실행이 됩니다.
event가 를 콘솔에 찍어보면 [object object]가 나옵니다.
boolean 값이 아니군요,, 그러므로 if문은 실행이 안됩니다. (내가 테스트하는 시점)
그럼 넘어가서 input에 focus() 이벤트가 실행됩니다.
콘솔 결과입니다.
input은 해당 input 객체,
safeActiveElement도 해당 input 객체.
input.select()는 undefinde.
input과 safeActiveElement가 같습니다.
safeActiveElement()를 살펴보도록 하겠습니다.
function safeActiveElement() {
// Avoid IE9 `document.activeElement` of death
try {
return document.activeElement;
} catch (exception) {}
}
짧아서 좋습니다.
이건 찾아보니까 ie9에서 bug가 있는데, 이거 해결하려고 만든 소스인 것 같습니다.
<iframe>에서 activeElement하면 에러가 발생한다고 하는데, 테스트해보지 않아서 잘 모르겠습니다.
자 focus의 반대를 알아보도록 하겠습니다.
focusout되었을때,,
'blur.placeholder': setPlaceholder
blue될 때, setPlaceholder()가 실행됩니다.
function setPlaceholder(event) {
var $replacement;
var input = this;
var $input = $(this);
var id = input.id;
event 파라미터를 받는데, 해당하는 input들이며
input.id는 input이 나오게 됩니다.
// If the placeholder is activated, triggering blur event (`$input.trigger('blur')`) should do nothing.
if (event && event.type === 'blur' && $input.hasClass(settings.customClass)) {
return;
}
event가 blur이며 customClass가 있기 때문에 if() 문을 타게되는데, if문은 return 시키는 용도로 사용됩니다.
function args(elem) {
// Return an object of element attributes
var newAttrs = {};
var rinlinejQuery = /^jQuery\d+$/;
$.each(elem.attributes, function(i, attr) {
if (attr.specified && !rinlinejQuery.test(attr.name)) {
newAttrs[attr.name] = attr.value;
}
});
return newAttrs;
}