* 스크립트 코드 실행 시점문제
- html 파일내에 있는 img 태그의 1.jpg 사진을 스크립트를 실행하여 2.jpg로 바꾸려고 하는데 실행이 안됨.
<script src="test3_study.js"></script>
</head>
<body>
<h1>test3.jsp</h1>
<img src="../images/1.jpg" id="img1" width="150" height="150" >
<body>
/* test3_study.js */
function myFunction(){
document.getElementById("img1").src = "../images/2.jpg";
}
문제점 :
=> 현재 test3.js 파일을 로딩하는 위치가 <head> 태그 내이므로 현재 스트립트가 실행되는 시점에는 <body> 태그 내의 요소들이 로딩되기 전이다. => 따라서, 해당 요소들에 접근하는 코드사용시 요소에 대한 객체가 없으므로 null 값이 리턴되고 이 객체에 접근하기 위한 코드가 실행 될때 null 값을 통한 접근이 불가능하여 오류 발생함. => img1 객체가 존재하지 않으므로(=null) img1.src 속성에 접근이 불가능하다! img1.src = "../images/2.jpg"; // 오류 발생위치 => 해당 오류 메시지 : TypeError: Cannot set properties of null (setting 'src') |
해결책 1번) 해당 요소 태그보다 아래쪽에 스크립트 기술
<script type="text/javascript">
let img1 = document.getElementById("img1");
img1.src = "../images/2.jpg";
</script>
해결책 2번) 스크립트 코드위치와 상관없이 모든 요소 로딩이 완료된 후 스크립트 실행되도록 하기
2-1) 함수를 정의한 후 jsp파일의 <body> 태그에 onload 이벤트를 활용하여 해당함수 호출하기
<body onload="myFunction()">
해결책 2-2번) <body> 태그는 그대로 두고 자바스크립트 window.onload 속성을 이벤트로 활용하여 해당 이벤트가 발생하면 실행할 함수를 속성값으로 전달하기
=> window.onload = 함수명;
=> 주의! 함수명뒤에 소괄호를 기술하지 않는다! (=즉시 호출하는 것이 아니기 때문!)
/* test3_study.js 파일내에 */
window.onload = myFunction;
=> onload 이벤트가 발생하는 시점에 myFunction 함수가 실행됨.
=> 주의 window.onload = myFunction(); // 오류! TypeError: Cannot set properties of null (setting 'src')
=> 현재 코드가 로딩되는 시점에 함수를 실행시킴
=> 즉, onload 이벤트와 관계없이 myFunction 함수가 실행이 되어 버리기 때문에 오류 발생.
해결책 2-3번) window.onload 이벤트 뒤에 별도의 함수를 전달하지 않고 익명함수를 직접구현하는 방법.
=> 익명함수란? 함수 정의 시 함수의 이름이 없는 함수
=> 따라서 ,별도로 정의해 놓고 호출하는 함수가 아닌 특정 속성에 전달하는 등의 실행할 위치에서 정의까지 한꺼번에 수행하는 경우에 사용하는 함수 형태
// 익명함수 형태 : window.onload = function() { .... }
window.onload = function() {
let img1 = document.getElementById("img1");
img1.src = "../images/2.jpg";
}; // 마지막 세미콜론은 생략해도 무관함.(다만 원래 window.onlad = x; 이므로 세미콜론이 포함됨.)
* 익명함수는 보통 언제 쓰는가? 함수가 일회용 일 때
[ form 태그 내의 각 요소에 접근하는 방법 ]
1) 기존의 document.querySelector() 메서드 등을 활용하여 해당 요소를 직접 지정하는 방법 또는
2) form 태그를 통해 폼 내의 요소에 접근하는 방법
- document.form태그의name속성값.접근할태그의name속성값.속성명 또는
document.form태그의name속성값.접근할태그의name속성값.메서드명()
=> 속성명 : name, type, value 등
=> 메서드 : focus() - 대상 요소에 커서(포커스) 요청
blur() - 대상 요소에서 커서(포커스) 해제
select() - 대상 요소에 포커스 요청 및 입력 항목 블럭 지정
● form 태그 내의 각 요소에 접근하는 방법 예제
<h1>test5.jsp - form 태그 이벤트</h1>
<form action="test5_result.jsp" name="fr">
텍스트 <input type="text" name="text1">
<input type="button" value="focus" id="btnFocus">
<input type="button" value="select" id="btnSelect">
<br>
숨김텍스트 <input type="password" name="text2">
<br>
멀티라인텍스트 <textarea rows="5" cols="20" name="ta"></textarea>
<br>
<input type="button" value="입력값 출력" id="btnShowInfo">
<input type="button" value="입력값 체크" id="btnCheck">
<input type="submit" value="입력값 전송" id="btnSubmit">
</form>
<div id="infoArea"></div>
// id 선택자 "btnCheck" 버튼 클릭 이벤트 처리 => 익명함수로 처리
document.querySelector("#btnCheck").onclick = function() {
let text1 = document.fr.text1.value;
let text2 = document.fr.text2.value;
let ta = document.fr.ta.value;
// form 태그 입력 항목 3개중 입력되지 않는 항목 존재 여부 판별
// => 기본적으로 submit 버튼과 입력 항목의 required 속성 조합하여 간단하게 구현 가능하지만
// 추가적인 작업(입력값 규칙 검증 등)을 수행해야 할 경우
// 자바 스크립트를 통해 별도의 코드로 추가작업 구현가능
// => 1) 입력항목(value 속성값)이 널스트링("")인지 판별
// 2) 입력항목(value 속성값)의 문자열 길이 (length 속성값)가 0인지 판별
// => 첫번째 텍스트 입력확인하여
// 미입력 시 "첫번째 텍스트 입력 필수!" 메세지 출력하고 해당 입력창에 커서 요청
// 아니면, 두번째 텍스트 입력 확인하여
// 미입력 시 "두번째 텍스트 입력 필수!" 메세지 출력하고 해당 입력창에 커서 요청
// 아니면, 세번째 텍스트 입력 확인하여
// 미입력 시 "세번째 텍스트 입력 필수!" 메세지 출력하고 해당 입력창에 커서 요청
// 모두 아니면 "모든 텍스트 입력완료"" 메시지 출력
if(document.fr.text1.value == ""){
alert("첫번째 텍스트 입력 필수!");
document.fr.text1.focus();
} else if(document.fr.text2.length == 0){
alert("두번째 텍스트 입력 필수!");
document.fr.text2.focus();
} else if(document.fr.ta.value == ""){
alert("세번째 텍스트 입력 필수!");
document.fr.ta.focus();
} else {
alert("모든 텍스트 입력완료!");
}
/* else 안쓰는 방법 */
// if문과 else if 문 등의 조합을 통해 판별을 수행한 후
// 해당하지 않는 조건에 대한 나머지 모든 작업은 if 문 밖에서 수행하려면
// if 문 블럭마다 작업 완료 후 함수를 종료하도록 rueturn을 기술하면 된다
// => return 문을 만나면 함수 실행이 즉시 종료 되므로 if 문 밖의 문장이 실행되지 않는다.!
if(document.fr.text1.value == ""){
alert("첫번째 텍스트 입력 필수!");
document.fr.text1.focus();
return; // 현재 함수 실행이 즉시 종료됨.
} else if(document.fr.text2.value == ""){
alert("두번째 텍스트 입력 필수!");
document.fr.text2.focus();
return;
} else if(document.fr.ta.value == ""){
alert("세번째 텍스트 입력 필수!");
document.fr.ta.focus();
return;
}
/* 익명함수는 return 이 끝나면 돌아갈 곳이 없다. 근데 onclick 이벤트에 걸려있다.
if문에서 return을 쓰면 아래에 있는 alert 실행하지않고 함수를 끝내버린다.
*/
alert("모든 텍스트 입력완료!"); // 위의 if문 조건이 다 맞지 않으면 return이 실행되지 않으니까 실행이 될것이다.
// return을 넣은 것과 else 의 역할이 똑같다.
// 모든 값이 입력됐을때 submit 버튼과 동일한 동작을 수행하려면
// 해당 form 태그 요소의 submit 메서드를 호출함녀 된다.
document.fr.submit(); /* 체크버튼을 눌러도 submit 동작이되어 넘어간다. 버튼을 button으로 만들어도 submit 버튼으로 만든것과 똑같은 기능을 하는 것이다. */
}
● 라디오박스, 체크박스 값출력하기
<h1>test6.jsp - form 태그 이벤트</h1>
<form action="test6_result.jsp" name="fr">
<!-- 라디오버튼에 requeire 속성 지정시 동일한 그룹내에서 하나만 선택하면 됨. -->
<!-- 이거는 두개 다 걸어도 한개만 선택하면 됨. -->
<input type="radio" name="radio" value="라디오값1">라디오1
<input type="radio" name="radio" value="라디오값2">라디오2
<input type="button" value="라디오버튼 선택완료" id="btnRadio">
<hr>
<!-- 체크박스에 ruquired 속성 지정시 동일한 그룹 상관없이 해당 항목은 무조건 선택해야 한다. -->
<!-- 3개 걸면 3개다 선택해야 함. 하나라도 체크하지 않았을 경우 submit 동작 수행불가.-->
<!-- 다 선택해야하는 것아니면 체크박스는 required 안써야 함. -->
체크박스
<input type="checkbox" name="check" value="체크박스값1">체크박스1
<input type="checkbox" name="check" value="체크박스값2">체크박스2
<input type="checkbox" name="check" value="체크박스값3">체크박스3
<input type="checkbox" name="all_check" id="all_check"><label for="all_check">전체선택</label>
<input type="button" value="체크박스 체크완료" id="btnCheckbox">
<input type="submit" value="전송">
</form>
<div id="infoArea"></div>
window.onload = function() {
// 라디오버튼 선택완료 버튼 클릭 이벤트 핸들링(처리)
document.getElementById("btnRadio").onclick = function(){
// 라디오버튼(name속성명 radio)에 접근하여 value 속성값 출력
// 라디오 버튼의 배열 중 첫번째 요소(인덱스 0)의 value와 checked 속성값 출력
console.log(document.fr.radio[0].value); // 첫번째 라디오버튼의 value속성값
console.log(document.fr.radio[0].checked);// 첫번째 라디오버튼의 checked속성값(선택여부)
// 위의 코드에서 라디오버튼 접근을 위해 선택된 객체(배열)를 변수에 저장하여 중복코드 제거
let arrRadio = document.fr.radio; // radio button 관리하는 배열을 변수에 저장
document.querySelector("#infoArea").innerText =
arrRadio[0].value + " : " + arrRadio[0].checked + "\n"
+ arrRadio[1].value + " : " + arrRadio[1].checked;
// 위의 코드에서 배열 접근 방식을 for문으로 변환(기본 배열 접근 공식 활용)
let radioInfo = "";
for(let i of document.fr.radio){
// console.log(i.value + " : " + i.checked)
radioInfo += i.value + " : " + i.checked;
console.log("radioInfo : " + radioInfo);
}
//-----------------
// 만약, 두개의 라디오버튼 중 하나도 선택하지 않았을 경우
// "라디오버튼항목선택필수" 경고창 출력
if(document.fr.radio[0].checked == "false" && document.fr.radio[1].checked == "false" ) {
alert("라디오버튼항목선택필수");
}
}
// !!!!체크박스버튼 체크완료 버튼 클릭 이벤트 핸들링(처리) : 체크박스 처리 방법은 기본적으로 라디오버튼과 동일함.
// 전체선택 체크박스 클릭 이벤트 핸들링
document.fr.all_check.onclick = function() {
// 전체선택 체크박스가 "체크"상태일 경우
// => 다른 체크박스 3개를 모두 "체크"상태로 변경하고
// 아니면, 모두 "체크해제" 상태로 변경
if(!document.fr.all_check.checked) { // 야임마 boolean 조심해라!!
for(let i of document.fr.check){
i.checked = false;
}
} else {
for(let i of document.fr.check){
i.checked = true;
}
}
//-------------------
// 전체선택 체크박스의 체크상태(true/false)와 각 체크박스의 체크상태가 동일하므로
// if 문을 통한 판벽없이 전체선택 체크박스의 체크상태값을 각 체크박스의 상태값으로 설정해도 된다.
for(let i of document.fr.check) {
i.checked = document.fr.all_check.checked;
}
for(let i = 0; i < document.fr.check.length; i++){
document.fr.check[i].checked = document.fr.all_check.checked; // true이면 true이다.
}
}
}
'자바스프링웹공부(2024) > 자바스크립트' 카테고리의 다른 글
2024.08.27.JS - 카카오우편번호 API 사용하기 (2) | 2024.09.01 |
---|---|
2024.08.27.JS - 셀렉트박스 (2) | 2024.09.01 |
2024.08.14. JS - event (0) | 2024.08.19 |
2024.08.14. JS - document 객체 : querySelector(), innerText, innerHTML (0) | 2024.08.19 |
2024.08.13. JS - history, location, document 객체 - getElementByXX (0) | 2024.08.19 |