자바스크립트 이벤트 실행 문제 다시 질문합니다.

조회수 1611회
  <div class="container">
 <div class="row p-4">
  <div class="col-xs-12">
   <form name="form" id="form">
    <div class="form-group">
     <label for="selectBox">몇 회차 로또 결과를 볼까요?</label>
     <select id="selectBox" name="selectBox" class="form-control">
       <option value="" selected disabled>선택하세요...</option>
     </select>
    </div>
    <button class="btn btn-primary" type="submit">결과 보기</button>
   </form>
   <script id="a1"  defer="" type="text/javascript" document.write('src=""')></script>
   <pre id="result"></pre>
   <section id="winner" class="shadow">
    <h2 id="lottok">loading...</h2>
    <div class="output" id="output0"></div>
    <div class="output" id="output1"></div>
    <div class="output" id="output2"></div>
    <div class="output" id="output3"></div>
    <div class="output" id="output4"></div>
    <div class="output" id="output5"></div>
    <div class="output" style="box-shadow:none; color:#000;">+</div>
    <div class="output" id="output6"></div>
    </section>
  </div>
 </div>
</div>

전에 질문에 답변 달린것처럼 이런식으로 바꾸어 보았습니다.

결과보기 버튼을 누르면 이벤트가 실행되고 그 이벤트를 통하여

script id="a1" defer="" type="text/javascript" document.write('src=""')

이부분의 src 주소가 바뀌게 됩니다

(ex)http://lotto.kaisyu.com/api?method=get&gno=360;callback=loadlot";

해당 api주소에서 callback을 통하여 loadlot함수로 들어가 데이터가 처리가 되는데

현재 문제는 회차를 변경한후 결과보기 버튼을 눌렀을시 src주소는 회차에 맞게 바뀌지만

단 1번만 회차에 맞게 출력하고 그 이후에는 변동이 없습니다. 버튼을 누를시 저 구문을 다시

실행하게 하는 방법이 없을까요?

-------------------------------------------질문 추가 내용----------------------------

F12 개발자 도구로 보면 첫화면에서는

script id="a1" defer="" type="text/javascript" ')="" document.write('src="">

이런식으로 되어있던 해당 코드가 만약 2회를 클릭했을시

script id="a1" src="http://lotto.kaisyu.com/api?method=get&amp;gno=2;callback=loadlot" defer="" type="text/javascript" ')="" document.write('src="">

이렇게 바뀌고 2회의 당첨번호를 화면에 뿌려줍니다. 그후 3회 4회 5회로 변경시에

저 주소는 바뀌게 되나 당첨번호는 바뀌지가 않네요

$(document).ready(function () {
  var dropdown = $('#selectBox');
  var form = $('#form');
  var result = $('#result');
  var a2=$('#a1');
  for (i = 2; i < 861; i++) {
    var option = $('<option>');
    option.val(i).text(i+'회차');
    dropdown.append(option);
  }
  form.on('submit', function (event) {
    event.preventDefault();
    if (!dropdown.val()) {
      alert('뭔가 선택을 하세요.');
      dropdown.focus();
    } else {
      document.getElementById("a1").src="http://lotto.kaisyu.com/api?method=get&gno="+dropdown.val()+";callback=loadlot";
    }
  });

});

올려주신 코드는 제가 사용하는 api를 ajax로 끌어올수 없어서 이런식으로 변경했습니다

function loadlot(a) {
  $("#lottok").html('제 ' + a.gno + '회차 당첨 결과(' + a.gdate + ')'); // + '<br/>' +
  //a.nums + a.bnum;
  a.nums[6] = a.bnum;
  for (i = 0; i < 7; i++) {
    $('#output' + i).text(a.nums[i]);
  }
  for (i = 0; i < 7; i++) {
    if (a.nums[i] <= 10) {
      $('#output' + i).addClass("c1");
    } else if (a.nums[i] <= 20) {
      $('#output' + i).addClass("c2");
    } else if (a.nums[i] <= 30) {
      $('#output' + i).addClass("c3");
    } else if (a.nums[i] <= 40) {
      $('#output' + i).addClass("c4");
    } else {
      $('#output' + i).addClass("c5");
    }
  }
  data = a;
}

이건 api에서 끌어온 데이터를 변수에 넣어서 화면에 뿌려주는 함수입니다

  • F12 눌러서 개발자도구를 켠 다음에 회차 변경해서 다시 결과보기 해보세요. 콘솔이나 네트워크 쪽에 뭐 빨간 에러 뜨는것 없나요? 엽토군 2019.6.2 18:54
  • 네 따로 뜨는건 없고 본문 수정해서 코드를 다시 올리도록 해볼게요 김이용 2019.6.2 19:02
  • http://59.14.110.208:3000/ 현재 서버도 열어두었습니다 ㅠㅠ 김이용 2019.6.2 19:19
  • 일단 올려주신 프로덕션만 보면 #a19까지만 script 태그가 있기 때문에 20회차나 그 이상의 것을 선택했을 때 Uncaught TypeError: Cannot set property 'src' of null이 찍히네요. 여기서부터가 문제인데... 엽토군 2019.6.2 22:24

1 답변

  • 좋아요

    2

    싫어요
    채택 취소하기

    아시겠지만 여기서 사용되는 기술은 JSONP라고 하는 것인데 문제가 뭐냐면 이 JSONP에 의해 호출될 loadlot() 함수의 정의는 이 JSONP보다 앞에 나와야 한다는 겁니다.

    다음 스크립트를 </body> 직전에 적당히 붙여 보세요. 참고로 제 로컬에서는 대충 이렇게 잘 나옵니다.

    이미지

    이미지

    <script type="text/javascript">
    
    // 일단 이후 나올 함수들이 사용할 DOM을 먼저 정의하자.
    var dropdown = $('#selectBox');
    var form = $('#form');
    var result = $('#result');
    
    // 그 다음 필요한 함수들을 먼저 정의하자.
    // 이 함수는 객체를 하나 받아서 글로벌 스코프에서 콜백될 예정이다.
    // 따라서 그 내용을 정의해 줘야 하고, $(document).ready() 같은 클로저 안에 들어가 있으면 안 된다.
    var loadlot = function (winGameObject) {
      // 그 객체를 활용해서 적당히 만든 html을 적당한 곳에 삽입하게 하자.
      result.html(printWinGame(winGameObject));
    };
    
    // 하나의 함수는 하나의 일만 해야 한다.
    // 적당한 object를 넣으면 그 내용을 기초로 적당한 jQuery 객체를 반환하는 함수를 별도로 작성하자.
    var printWinGame = function (winGameObject) {
      var container = $('<div>');
      var heading = $('<h3>');
      var outputs = $('<div>');
      heading.text("제 " + winGameObject.gno + "회차 당첨 결과 (" + winGameObject.gdate + ")");
      $.each(winGameObject.nums, function (i, number) {
        var output = $('<div>');
        output.addClass(decideClassNameOfOutput(number)).text(number);
        outputs.append(output);
      })
      outputs.append(' + ');
      var bonusNumber = $('<div>');
      bonusNumber.addClass(decideClassNameOfOutput(winGameObject.bnum)).text(winGameObject.bnum);
      outputs.append(bonusNumber);
      container.append(heading).append(outputs);
      return container;
    };
    
    // 반복되는 로직이라면 별도 함수로 분리하자.
    // 이 함수는, 로또 번호를 넣으면, 그 번호를 감쌀 태그에 쓸 수 있는 적당한 클래스명 문자열을 반환한다.
    var decideClassNameOfOutput = function (number) {
      return 'output c' + Math.ceil(number/10); // 10까지는 1, 20까지는 2, ... 라면 버림 계산으로 간단히 잡을 수 있다.
    }
    
    // 어디서든 특정 함수를 실행하면 원하는 API URI를 얻을 수 있도록 하자.
    // 이 함수는 원하는 회차 번호를 넣으면 JSONP 형식으로 호출할 로또 API URI를 반환한다.
    var getAPIOfWinGame = function (gno) {
      return "http://lotto.kaisyu.com/api?method=get&gno=" + gno + "&callback=loadlot";
    };
    
    // 이 함수는 원하는 URL을 넣으면 그걸 JSONP 형식으로 가져오게 해 준다.
    // 지금 다시 보니 `$.ajax()` 메소드에서 jQuery는 이미 JSONP 실행을 지원하고 있긴 한데...
    // 내가 그걸 활용해본 적이 없어 잘 모르겠으므로 여기서는 대충 이렇게 해서 재사용성을 확보함.
    var fetchAsJSONP = function (src) {
    
      // 일단 body 안에서 기존 #jsonp 객체를 없앤다.
      $('body').find('#jsonp').remove();
    
      // 새 #jsonp 객체를 정의한다.
      var jsonp = $('<script>');
      jsonp.attr({
        src: src,
        id: 'jsonp'
      });
    
      // 그걸 body 맨끝에 붙인다.
      $('body').append(jsonp);
    };
    
    // 함수 다음엔 이벤트 바인딩을 정의한다.
    // 원래 form.onsubmit 이었는데 귀찮으니 dropdown.onchange 로 바꿔봄.
    dropdown.on('change', function (event) {
      event.preventDefault();
      if (!dropdown.val()) {
        alert('뭔가 선택을 하세요.');
        dropdown.focus();
      } else {
        var selectedGame = dropdown.val();
        fetchAsJSONP(getAPIOfWinGame(selectedGame));
      }
    });
    
    // 이벤트 바인딩 정의 다음에는 C의 main()에 해당하는 동작들을 작성한다.
    for (i = 1; i < 862; i++) {
      var option = $('<option>');
      option.val(i).text(i+'회차');
      dropdown.append(option);
    }
    
    // 이제 모든 게 다 끝났으니 원하는 것을 한다.
    // 이를테면 기본 결과값인 1회차 결과 받아서 뿌리기 같은 것을 여기서 하자.
    fetchAsJSONP(getAPIOfWinGame('1'));
    </script>
    
    • 답변 감사합니다 많은 도움이 되었습니다 현재 div 안에 태그를 만들어서 이벤트 실행시에 number 라는 아이디를 찾아 remove 시킨후 다시 똑같은 태그를 div안에 append 시키는 식으로 해결을 했습니다만 올려주신 코드를 보니 많은걸 알수 있었습니다 어제부터 계속 도와주셔서 정말 감사합니다 김이용 2019.6.3 00:13
    • 도움이 되었다면 다행입니다 이후에 다시 오셔서 다른 분들의 문제도 해결해 주세요. 엽토군 2019.6.3 11:47

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)