오늘은 배열에 특정한 조건을 주어 값을 걸러낼 수 있는 filter() 함수를 소개합니다.

예시 코드 =>

let array = [1, 4, 9, 15];
let str = ['a', 'ab', 'abc', 'abcd' ];
let obj = [{name:"lee", age: 13}, {name:"kim", age: 15}, {name:"park", age: 12}, {name:"choi", age: 14},];

const result = array.filter((a) => a > 5);
const result2 = obj.filter((a) => a.age > 13);
const result3 = str.filter((a) => a.length > 2);

console.log(result);
console.log(result2);
console.log(result3);

 

 

기본적으로 모든 배열에 사용할 수 있고

배열의 모든 원소에 조건을 부여하여 얕은 복사(원본 유지 복사)를 해줍니다.

 

해당 코드를 실행한 콘솔을 보면

 

위 코드 실행 콘솔 사진
위 코드 실행 콘솔 사진

 

각각의 얕은 복사된 결과물이 콘솔에 찍히는 것을 확인할 수 있습니다.

이 외에도 여러가지 기본 메소드를 사용하여 배열 또는 객체(문자)를 필터할 수 있는데 

 

다음 시간에 계속 알아보도록 합시다! 

이전에 iframe 안에 있는 태그들을 선택하는 방법을 포스팅한적이 있는데

그것과는 별개지만 이어서 작업을 하다가 부모창에서 자식창의 복수 선택자에 이벤트를 줘야 하는 경우가 생겼다.

(사실 이거 말이 안되는거 아닌가..?)

 

부모창에서 iframe 컨텐츠에 접근하는 법은 아래에 링크 참조

2023.10.11 - [Javascript] - [Javascript] 부모창에서 iframe 컨텐츠 접근하기

 

[Javascript] 부모창에서 iframe 컨텐츠 접근하기

지난 시간에 이어서 반대로 부모창에서 iframe 컨텐츠에 접근 하는 방법을 알아보자 오늘도 작성하기 전에 확인하면서 나도 다시 검색해봤는데 시키는대로 해도 안잡히거나 제어가 안되는 경우

teddy-code.tistory.com

 

그럼 우선 선택자에 대해 알아보자

예시 코드 사진
예시 코드 사진

 

 

각각 querySelectorAll, getElementsByClassName, getElementById로 콘솔을 찍어보면

 

결과 콘솔 사진
결과 콘솔 창

 

id의 특성상 당연히 하나만 찍힌 id_content와 달리 메소드 이름부터 복수인

ElementsByClassName과 All은 노드리스트와 html 태그 배열이 보인다.

 

자 이제 이러면 자동완성 기능은 어떤 반응을 보이느냐

id_content는 자동완성 기능으로 addEventListener가 보임
id_content는 자동완성 기능으로 addEventListener가 보임
className 또는 selectorAll의 자동완성은 무반응
className 또는 selectorAll의 자동완성은 무반응

 

이렇게 자동완성부터 addEventListener를 거부한다.

그리고 억지로 넣어봐도?

 

복수 선택자에 이벤트 리스너를 억지로 넣어도 안된다.
델리만쥬 바로 에러뜬다

복수 선택자이기 때문에 그렇다..

그렇다면 결국 하나하나씩 해줘야 하는데..

클래스 하나씩 개별로 따로 줘서 변수 또 따로 주고 하나씩할꺼 아니지 않은가?

 

정답은?

배열을  for문을 돌려서 length만큼 각각 이벤트를 바인딩하면 된다.

for문을 이용한 이벤트 바인딩
for문을 이용한 이벤트 바인딩

 

하지만 여기서 ClassName과 SelectorAll의 차이점이 있다. (중요)

 

바로 SelectorAll로 선택된 배열은 forEach가 된다는 점

귀찮게 for문 필요없이 바로 배열 순회가 가능하다.

 

class_content는 에러 selectorAll은 forEach가 적용됐다.
class_content는 에러 selectorAll은 forEach가 적용됐다.

 

개인적으로 이렇다면 복수 선택자에 이벤트 바인딩을 할때에는 SelectorAll에 forEach를 쓰는게 편할꺼 같다.

안 좋은 점이 있는지 혹시나 아신다면 댓글로 알려주시면 감사하겠습니다.

 

현재까지의 결론 =>

똑같은 class의 dom에 동시에 이벤트를 바인딩할때에는 SelectorAll에 forEach! 

이전에 글을 쓰면서 나는 map() 함수를 사랑한다고 한적이 있는데

오늘은 자바스크립트를 하며 많이 사용하고 찾게 되는 배열 순회 함수를 소개한다.

많이들 보았겠지만 map()forEach()가 대표적이다.

 

let array = [1, 4, 9, 15];
let obj = [{name:"lee", age: 13}, {name:"kim", age: 15}, {name:"park", age: 12}, {name:"choi", age: 14},];

let arrayMap = array.map((x) => x + 2);
let arrayFor = array.forEach((x) => x + 2);

let objMap = obj.map((p) => console.log(p.name));
let objFor = obj.forEach((p) => console.log(p.name));

console.log(arrayMap, arrayFor);

예시 코드
예시 코드

샘플로 만든 array 숫자 배열과 객체 배열인 obj를 map()과 forEach()를 통해 콘솔에 찍어보면 비교가 쉽다.

 

결과 콘솔 사진
결과 콘솔 사진

우선 사용하는 방법은 둘다 동일하다.

array.map() 또는 forEach()안에 (배열의 원소) => 실행될 함수 방식으로 써주면 된다. (꼭 arrow function 아니여도 됨)

 

둘의 가장 큰 차이점은 10번줄에 찍힌 로그를 보면 확인할 수 있는데

객체 배열의 name을 콘솔에 찍은 것은 둘다 똑같지만 (단순 실행)

map을 사용한 arrayMap[]은 결과가 배열로 리턴된 것을 볼 수 있고 그것과 달리 forEach를 사용한 arrayFor는 undefined가 나온다..!

 

결론 => map()은 실행과 함께 결과 값도 저장(리턴)

forEach()는 just 실행이에요

 

실제 업무할 때 쓰는 프로그램중에 복사 붙혀넣기를 해야하는 프로그램이 있는데 너무 많이 붙혀넣기를 하려다보니 귀찮아서 자동으로 복사되는 프로그램을 만들어 보다가 js로 복사하는 메소드를 찾게 되었다.

 

이전부터 쓰이던 것들이나 api도 있는거 같지만 환경만 된다면 가장 간단하게 할 수 있는 방법으로 소개한다.

window.navigator.clipboard.writeText();

간단한 예시 사진
간단한 예시

간단하게 설명하면 innerHTML(textarea)이나 textContent(div)로 가져온 문자열을 복사해준다.

 

환경은 https 또는 localhost 에서만 작동하는데 집에서 인터넷으로 할때는

127.0.0.1까지는 문제 없이 작동하는 것을 확인했다.

회사에서 쓸때 와이파이나 테스팅 서버에서 사용할 경우에는 앞에 주소를 localhost로 바꿔주면 문제 없었다.

127.0.0.1은 복사가 된다
127.0.0.1

 

복사가 안될땐 localhost
localhost / https

 i'm 완벽이에요^^

국비지원 교육을 받으면서 처음 코딩 공부를 할때 드롭 다운 메뉴가 첫 과제 같은 느낌이었다.. (어렵진 않지만?)

하지만 html5가 되고 나서 쉽게 드롭다운 메뉴를 만들 수 있는 태그가 생겨서 소개한다.

 

바로 details / summary 태그!

<details>
      <summary>태그로 만드는 드롭 다운 메뉴</summary>
      <ul>
         <li>메뉴1</li>
         <li>메뉴2</li>
         <li>메뉴3</li>
      </ul>
   </details>
   <details>
      <summary>태그로 만드는 드롭 다운 메뉴2</summary>
      <div>
         <div>메뉴1</div>
         <div>메뉴2</div>
         <div>메뉴3</div>
      </div>
   </details>

쉽게 details 태그 안에 summary라는 제목을 넣고 그 외의 다른 메뉴들은 드롭 다운 안으로 들어가게 되는 태그이다.

위 코드의 결과 

ul / li든 div든 뭐든 들어간다!

회사에서나 실제로 쓸때에는 아직 애니메이션이 안된다고 해서 잘 못쓰는 중이긴 하지만 그런거 없는 간단한 드롭다운 메뉴를 만들때에는 쉽게 만들 수 있게 해준다.

 

그리고 summary 앞에 화살표로 나타내는 표시가 있는데 이것 또한 css로 쉽게 커스텀 할 수 있다.

details summary::-webkit-details-marker,
details summary::marker {
 display: none;
 content: "";
}

가끔 검색하다 보면 display: none; list-style-type:none; 으로 된다는 글을 봤었는데.. 안 됐었다

포스팅 하려고 쓰면서 다시 찾아보니 stack-overflow에 content:"";을 찾아서 성공했다.

before / after처럼 content를 가지고 커스텀 하는 방식인 듯!

 

https://stackoverflow.com/questions/48814993/html-details-summary-element-marker-styling

 

HTML Details/Summary Element Marker Styling

I have some CSS that styles the marker next to a summary element within a details element. The CSS itself works fine. However, if I nest another details element within the first one (creating a p...

stackoverflow.com

아직 애니메이션 효과를 줄 수 없어서 아쉽긴 하지만 다음 버전에는 가능해지지 않을까 생각한다.

믿어요^^

슬라이드 메뉴를 만들때 유용한 Swiper.js를 사용하다가 클릭한 요소를 가운데로 옮기는 기능이 필요하게 되었다.

이것 또한 블로그에 여러 글을 보게 되었는데 다 방법은 똑같으나 나는 계속 달라서 왜 그러는지 고민하다가 성공했다..

 

내 슬라이드 옵션

보통 블로그 글에서는 초기화 시키고 깨끗한 상태에서 가운데 정렬 시키는 경우가 많았는데 나는 spaceBetween으로 거리를 벌려 두었다. 그래서 계속 슬라이드의 인덱스 수와 인덱스 사이의 거리만큼 슬라이드 전체 길이가 늘어나서 오른쪽에 있는 슬라이드들이 가운데로 못가고 있었다.

흔히 많이 보는 코드에서 슬라이드 인덱스 수와 마진을 곱한 값을 listWidth에 추가해서 구해줘야 했다.
하단에 넣은 슬라이드 메뉴

슬라이드 부분만 슬쩍 가져오고 색깔도 막 해놓은거라 이쁘진 않지만..

가운데 정렬이동과 선택은 잘 된다. 

 

항상 질문과 같이 고민할만한 내용은 환영입니다. (본인은 뇌가 고통 받는거 좋아함) 

요즘 부동산 플랫폼을 만들어보고 싶어서 api 사용하는 연습도 할겸

공공데이터 api키를 발급받고 데이터를 뿌려보려고 했었는데 

우연히 그런건지 받는 api가 xml 데이터였다

 

하지만 난 Json과 map()을 사랑하는 사람이라

json변환 방법을 찾았는데

 

언제나 그렇듯 흔하게 나오는 json.parse()로는 문법 오류가 났다

(데이터 구조가 이미 json형식일 경우 아님)

 

찾아보니 라이브러리 혹은 직접 해야하는데 검색하다 라이브러리를 사용하지 않고 쉽게 변환할 수 있는

좋은 코드를 받게 되서 공유한다.

function xmlToJson(xml) {
    // Create the return object
    var obj = {};

    if (xml.nodeType == 1) {
        // element
        // do attributes
        if (xml.attributes.length > 0) {
        obj["@attributes"] = {};
        for (var j = 0; j < xml.attributes.length; j++) {
            var attribute = xml.attributes.item(j);
            obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
        }
        }
    } else if (xml.nodeType == 3) {
        // text
        obj = xml.nodeValue;
    }

    // do children
    // If all text nodes inside, get concatenated text from them.
    var textNodes = [].slice.call(xml.childNodes).filter(function(node) {
        return node.nodeType === 3;
    });
    if (xml.hasChildNodes() && xml.childNodes.length === textNodes.length) {
        obj = [].slice.call(xml.childNodes).reduce(function(text, node) {
        return text + node.nodeValue;
        }, "");
    } else if (xml.hasChildNodes()) {
        for (var i = 0; i < xml.childNodes.length; i++) {
        var item = xml.childNodes.item(i);
        var nodeName = item.nodeName;
        if (typeof obj[nodeName] == "undefined") {
            obj[nodeName] = xmlToJson(item);
        } else {
            if (typeof obj[nodeName].push == "undefined") {
            var old = obj[nodeName];
            obj[nodeName] = [];
            obj[nodeName].push(old);
            }
            obj[nodeName].push(xmlToJson(item));
        }
        }
    }
    return obj;
}

https://velog.io/@duboo/javascript-XML-to-JSON-%EB%B3%80%ED%99%98 출처

 

var lo = '구로구';
var xhr = new XMLHttpRequest();
var xmlDoc;
let xmlParser = new DOMParser();
let list = document.getElementById('list');
xhr.open('GET', url);
// xhr.responseType = 'json'
xhr.onreadystatechange = function () {
    if (this.readyState == xhr.DONE) {  // <== 정상적으로 준비되었을때
        if(xhr.status == 200||xhr.status == 201){ // <== 호출 상태가 정상적일때
            xmlDoc = xmlParser.parseFromString(xhr.response, "text/xml");
            var result = xmlToJson(xmlDoc);
            result.tbLnOpendataRtmsV.row.map(h => {
                if(h.HOUSE_TYPE == "아파트"){
                    console.log(h);
                    $(list).append(`
                    <details>
                        <summary>${h.BLDG_NM}</summary>
                        <ul>
                            <li class="h_attr">거래일자 : ${h.DEAL_YMD}</li>
                            <li class="h_attr">소속지역 : ${h.SGG_NM}</li>
                            <li class="h_attr">소속 동 : ${h.BJDONG_NM}</li>
                            <li class="h_attr">주거형태 : ${h.HOUSE_TYPE}</li>
                            <li class="h_attr">실거래금액 : ${h.OBJ_AMT}</li>
                        </ul>
                    </details>`
                    );
                }
            });
        }
    }
};

현재 테스트용으로 쓰고 있는 코드 (발급받은키) 자리에 서울 공공데이터 api키를 발급받아서 넣으면..!

 

깔끔하게 변환되었다.

 

지난 시간에 이어서 반대로 부모창에서 iframe 컨텐츠에 접근 하는 방법을 알아보자

 

오늘도 작성하기 전에 확인하면서 나도 다시 검색해봤는데 시키는대로 해도 안잡히거나 제어가 안되는 경우가 많다

당연하다고 생각해서 안 알려주는건지 모르겠지만 나처럼 1 to 10 봐야하는 분들을 위해 안되는 경우도 공유한다.

 

보통 검색했을때 제일 많이 나오는 부분

  var contents = document.getElementById("vr-frame").contentWindow.document.getElementById("iframe_content");
  var j_contents = $('iframe').contents().find('#iframe_content');

바닐라로 contentWindow를 사용하거나

제이쿼리로 .contents().find면 뚝딱인가 싶더니

 

시키는대로 했는데..

 

아무고토 안나온다

이유는 아이프레임이 로드되기전에 찾아서 그렇다

지난번에도 일할때 잠깐 화났던 기억이..

간단하게 iframe이 로드되고 스크립트를 실행시켜주면 문제가 없다

해결

document.querySelector('iframe').addEventListener("load", function() {
  var contents = document.getElementById("vr-frame").contentWindow.document.getElementById("iframe_content");
  var j_contents = $('iframe').contents().find('#iframe_content');
  j_contents.addClass('controls');
  console.log(contents, j_contents);
});

+ Recent posts