JQuery UI ToolTip에서 툴팁에 mouse over시 유지되도록 설정

web/jquery|2018. 7. 6. 19:50

업무를 진행하면서 jquery-ui를 이용해서 툴팁을 만들때 툴팁위에 마우스를 올렸을 때 툴팁이 유지되도록 하는 기능을 만들어야 했다. 

구글링을 통해서 방법을 찾았고 그 방법을 공유해보자.

먼저 기본적인 툴팁이 적용된 input box예제를 살펴보자.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<!doctype html>
<html lang = "en">
   <head>
      <meta charset = "utf-8">
      <title>jQuery UI Tooltip functionality</title>
      <link href = "https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css"
         rel = "stylesheet">
      <script src = "https://code.jquery.com/jquery-1.10.2.js"></script>
      <script src = "https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
 
      <!-- CSS -->
      <style>
         body {
            margin-top: 100px;
         }
         .ui-tooltip-content::after, .ui-tooltip-content::before {
            content: "";
            position: absolute;
            border-style: solid;
            display: block;
            left: 90px;
         }
         .ui-tooltip-content::before {
            bottom: -10px;
            border-color: #AAA transparent;
            border-width: 10px 10px 0;
         }
         .ui-tooltip-content::after {
            bottom: -7px;
            border-color: white transparent;
            border-width: 10px 10px 0;
         }
      </style>
 
      <!-- Javascript -->
      <script>
         $(function() {
            $( "#tooltip-7" ).tooltip({
               position: {
                  my: "center bottom",
                  at: "center top-10",
                  collision: "none"
               }
            });
         });
      </script>
   </head>
 
   <body>
      <!-- HTML -->
      <label for = "name">Enter Date of Birth:</label>
      <input id = "tooltip-7" title = "Please use MM.DD.YY format.">
   </body>
</html>
 
cs

 

단순하게 툴팁이 출력되고 마우스를 가져다 되면 사라져버린다.

툴팁에 마우스를 가져다 되었을 때 툴팁을 유지하기 위해서는 툴팁이 닫히려고 하는 이벤트에 ui hover 이벤트를 달아주면된다. 예제 코드는 다음과 같다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$(function() {
            $( "#tooltip-7" ).tooltip({
               position: {
                  my: "center bottom",
                  at: "center top-10",
                  collision: "none"
               },
                close: function( event, ui ) {
                  ui.tooltip.hover(
                      function () {
                          $(this).stop(true).fadeTo(400, 1);
                          //.fadeIn("slow"); // doesn't work because of stop()
                      },
                      function () {
                          $(this).fadeOut("400", function(){ $(this).remove(); })
                      }
                  );
                }
            });
         });
cs

 

결과를 확인해보면 마우스를 위에 가져다 놓아도 사라지지 않는 것을 확인할 수 있다.

댓글()

html의 화면을 캡쳐해서 이미지로 변경하는 html2canvas와 pdf로 저장하는 jsPDF 라이브러리 소개

web/javaScript|2018. 6. 29. 23:21

회사에서 업무를 진행하면서 현재 화면을 pdf로 만들어야하는 일이 있었다.

기존에 html을 pdf로 스프링에서 만드는 업무는 진행을 했었다. 이때는 이전에 포스팅을 했었으니 참고 하시면 좋을 것 같다. (Spring에서 html2pdf를 사용해서 pdf파일 만들기)

우선 현재 화면을 딱 캡쳐해서 image로 만드는 작업이 필요했다. 그 작업을 제공해주는 라이브러리가 바로 html2canvas이다.

 

html2canvas

우선 html2canvas를 사용하기 위해 파일을 받아보자.

npm install --save html2canvas

캡처를 진행하기 위해서는 캡처하고자 하는 영역을 selector로 위치를 받아서 지정할 수 있다.

우선 캡처를 진행할 화면을 간단하게 만들어보자.

<div id="capture" style="padding: 10px; background: #f5da55">
    <h4 style="color: #000; ">Hello world! Wedul Capture Test!</h4>
</div>

<button id="captureBtn" style="padding:20px;margin-top:15px;">Capture Start!!</button>

<script src="./node_modules/jquery/dist/jquery.min.js"></script>
<script src="./node_modules/html2canvas/dist/html2canvas.min.js"></script>
<script src="./index.js"></script>

하단에 captureBtn 버튼을 누를 경우에 capture영역이 image로 떨어지도록 javascript를 만들어보자.

// 버튼 클릭할 시 캡처한 내용 body에 붙혀보기
$('#captureBtn').click((e) => {
  html2canvas(document.querySelector("#capture")).then(canvas => {
    document.body.appendChild(canvas)
  });
});

캡처 방식이 생각보다 너무 간단하다. querySelector로 영역을 선택하고 html2canvas라이브러리를 호출하면 프로미스를 사용하여 나온 canvas객체를 조작하여 image로 넣을수도 있고 특정 파일로 변경할 수도 있다. 결과는 다음과 같이 버튼을 눌렀을 때 바로 밑에 이미지가 추가되는 것을 확인할 수 있다.

 

jsPDF

그럼 html2canvas로 출력된 image를 pdf 파일로 빼고 싶다면 어떻게 해야할까? 바로 jsPDF 라이브러리를 사용하면 된다.

홈페이지에 들어가면 자세하게 샘플코드가 나와있다. 그럼 간단하게 한번 만들어보자. 

우선 pdf파일로 빼내기 위해서는 jsPDF 라이브러리가 필요하니 설치부터 진행하자.

npm i jspdf --save

// import
<script src="./node_modules/jspdf/dist/jspdf.min.js"></script>

그리고 위에 html2canvas에서 사용한 문장을 그대로 사용하고 출력되서 나온 canvas를 사용하여 pdf로 만들어보자.

// 버튼 클릭할 시 캡처한 내용 body에 붙혀보기
$('#captureBtn').click((e) => {
  html2canvas(document.querySelector("#capture")).then(canvas => {
    // jsPDF 객체 생성 생성자에는 가로, 세로 설정, 페이지 크기 등등 설정할 수 있다. 자세한건 문서 참고.
    // 현재 파라미터는 기본값이다 굳이 쓰지 않아도 되는데 저것이 기본값이라고 보여준다.
    var doc = new jsPDF('p', 'mm', 'a4');

    // html2canvas의 canvas를 png로 바꿔준다.
    var imgData = canvas.toDataURL('image/png'); //Image 코드로 뽑아내기

    // image 추가
    doc.addImage(imgData, 'PNG', 0, 0);

    // pdf로 저장
    doc.save('sample-file.pdf');
  });
});

 

버튼을 클릭해보면 짠하고 pdf가 우선은 다운로드 된 것을 확인할 수 있다. 그럼 pdf 파일을 열어보자!

오호 잘나온다. 참 좋은 시대다 좋은 오픈소스 라이브러리도 많고 공부할 것도 많고 참 본받을 것이 많은 사람들이다.

추가적인 옵션은 문서에 보면 자세히 나와있다.

여기서 참고할만한 내용이 하나 있어서 적어놓았다. 만약에 캡처한 이미지가 출력하는 pdf 페이지보다 클 경우에는 페이지 별로 짤라서 이미지를 붙혀넣으면 자연스럽게 pdf 파일이 만들어진다. 코드는 아래 내용을 참고!

var imgData = canvas.toDataURL('image/png');

var imgWidth = 210; 
var pageHeight = 295;  
var imgHeight = canvas.height * imgWidth / canvas.width;
var heightLeft = imgHeight;

var doc = new jsPDF('p', 'mm');
var position = 0;

doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
heightLeft -= pageHeight;

while (heightLeft >= 0) {
  position = heightLeft - imgHeight;
  doc.addPage();
  doc.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
  heightLeft -= pageHeight;
}
doc.save(filename + '.pdf');

 

 

자세한 문서는 https://rawgit.com/MrRio/jsPDF/master/docs/index.html에서 확인해보자.

댓글()
  1. 2018.08.08 00:53 댓글주소  수정/삭제  댓글쓰기

    안녕하세요! 혹시 소스파일 받아볼 수 가 있을까요?

  2. 김삿갓 2019.01.10 15:49 댓글주소  수정/삭제  댓글쓰기

    body에 이미지를 보여짖말고 바로 다운이 가능한가요?
    pdf처럼요

  3. 호잇 2019.03.27 16:18 댓글주소  수정/삭제  댓글쓰기

    정말 너무너무 감사합니다~
    덕분에 회사업무를 잘 처리할 수 있었습니다 ㅠㅠ!
    유용하게 잘 사용했습니다. 다시한번 감사합니다 ^^

JQuery함수의 append와 appendTo 차이

web/javaScript|2018. 6. 19. 21:31

하나의 dom 객체를 다른 dom에 붙히려고 할때 JQuery에서 제공하는 append나 appendTo를 사용한다.


그런데 append와 appendTo가 헷갈리는 경우가 있는데 이 두개의 차이를 알아보자.


두 개 메서드의 결정적인 차이는 붙는 대상이 무엇이냐에 있다.

아래 예제를 살펴보자

1
2
3
4
5
6
<div id="dbsafer">
 
 
 
$('<div>').appendTo($('#dbsafer'));
$('#dbsafer').append($('<div>'));
cs


코드를 보면 두 개의 결과는 동일하다. 짐작하겠지만 appendTo는 뒤에있는 객체에 앞에있는 내용을 붙히겠다는 의미이고 append는 앞에있는 객체에 뒤라는 객체를 붙히겠다는 뜻이다.


영어 뜻을 잘 해석해서 진행하면 이해하기가 더 쉬울 것 같다.

댓글()

input 태그에 선택한 항목이 label로 출력되게 해주는 choices.js 소개

web/javaScript|2018. 6. 17. 21:06

현재 공부하려고 개인적으로 만들고 있는 프로젝트 위들포스에서 사용자를 검색하고 input 박스위에 레이블처럼 보여주는 기능이 필요했다.

 

아무리 찾아보아도 좋은 라이브러리가 없었는데 choices.js의 이미지를 보니 좀 좋아보여서 적용해 보았다.

우선 내 프로젝트에 적용된 하면은 이렇다.

 

[홈페이지 및 github]

https://joshuajohnson.co.uk/Choices/

https://github.com/jshjohnson/Choices

홈페이지에는 예제가 여러개 나열되어 있고, 필요에 따라 소스보기를 통해 참고할 수 있다. github에는 document가 있어서 사용할 수 있는 속성들이 나열되어 있다.

 

[사용방법]

간단한 사용방법은 github에서 소스를 받거나 npm install choices.js를 통해 소스를  내려받을 수 있다.

필수로 필요한 파일은 assets/script/dist/choices.js와 icon, image, base.css, choices.css가 필요하다.

 

페이지에서 <script>와 <link>를 통해서 로드를 하거나 웹팩에서 import를 사용하여 가져올 수 있다. 그리고 html페이지에 input 태그를 하나 생성하고 다음과 같이 적용하면 된다.

<!-- html -->
<div id="messageTargetSearch">
  <div id="messageTargetLabel">
    <label for="messageTargetInput"><spring:message code="message.title.user"/></label>
 </div>
 <input id="messageTargetInput" class="form-control" type="text" placeholder="Search..">
</div>


<!-- javascript -->
const messageTargetInput = document.getElementById('messageTargetInput');
const choices = new Choices(messageTargetInput, {
  delimiter: ',',
  editItems: true,
  maxItemCount: 1,
  removeItemButton: true,
  addItemText: function(value) {
    return 'Please Enter to add user <b>"' + String(value) + '"</b>';
  },
});


delimiter, editItems등 기타 옵션들은 github 페이지에 가면 자세히 나열되어 있다.

그리고 이벤트를 등록하려면 여러가지 이벤트들이 제공이 되는데 addItem과 removeItem에 대한 소스만 잠깐보자. 이게 적용이 되기전 그러니까 추가 또는 삭제가 되기전에 이벤트를 잡아주면 좋은데 그렇지 못해서 나는 따로 validate검사를 하고 validate가 적합하지 않으면 다시 추가 또는 제거해주는 코드를 별도로 넣었다. 좋은 방법이 있으면 추천 바랍니다~

messageTargetInput.addEventListener('addItem', (event) => {
  // do something creative here...
  console.log(event.detail.id);
  console.log(event.detail.value);
  console.log(event.detail.label);
  console.log(event.detail.groupValue);
  //choices.removeItemsByValue(event.detail.value);
}, false);

messageTargetInput.addEventListener('removeItem', (event) => {

  if (!confirm(Common.getMessage('message.message.close'))) {
    choices.setValue([
      {value: event.detail.value, label: event.detail.label}
    ]);
  }

  // do something creative here...
  console.log(event.detail.id);
  console.log(event.detail.value);
  console.log(event.detail.label);
  console.log(event.detail.groupValue);

}, false);

아쉬운건 아이콘을 svg파일을 사용하는데 webpack에서 svg loader를 적용하여도 정상적으로 로드가 되지 않아서 좀 애를 먹었다. 

다른사람들도 검색해보니 동일한 문제를 겪은 사람이 있는데 해결은 안되었다. 아래 URL 참고

https://github.com/jshjohnson/Choices/issues/223

 

보시는분들중 이런 라이브러리들이 좋은게 있으면 추천 부탁드립니다.

댓글()

div내에 overflow scroll 옵션에 따라 스크롤 생성 시 제일 밑으로 스크롤 내리기

web/javaScript|2018. 6. 17. 20:55

채팅 프로그램을 요새 만들고 있는데 채팅의 경우 스크롤이 새로운 내용이 추가되면 맨 밑으로 이동되어야 한다. 

그래서 jquery를 통해 좀 쉬게 이동하게 할 수 없나 싶어서 찾아보다가 있어서 정리해본다.

const $messageTextBox = $('#messageTextBox');
$messageTextBox.scrollTop($messageTextBox[0].scrollHeight);

div의 태그를 잡아서 해당 스크롤의 높이를 scrollTop 메서드로 잡아주면 자동으로 밑으로 내려가게된다.

 

어려워 어려워.

댓글()

spring에서 List 또는 Array 데이터를 Controller에서 받기

web/Spring|2018. 5. 27. 11:04

컨트롤러에서 List<>데이터를 받아서 매핑하기 위해서 필요한과정을 정리해본다.



1. List<PersonDto> 데이터를 받기


먼저 controller에서 @RequestBody List<PersonDto>를 받도록 설정한다. 

그리고 ajax를 통해서 요청하는 부분에서 다음과 같이 진행한다.


 

1
2
3
4
5
6
7
let data = [{'name':'cjung', 'age':30}, {'name':'wedul', 'age':28}];
 
$.ajax({
    url:....,
    type:...,
    param: JSON.stringify(data);
});
cs






2. DTO객체 안에 LIST 변수에 데이터를 매핍 하고자 하는경우


기존에 습관대로 진행을 다음과 같이 먼저 해보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// javascript
let param = [{ name : 'wedul', age: 1}, {name:'dd', age:2}];
 
// UserDto
private String name;
private int age;
 
// UserDataList
public UserDataList {
 List<UserDto> userDatas;
 
}
 
 
// UserController
public Map<String, Object> getUsers(@ModelAttribute UserDataList users);
cs




Property referenced in indexed property path is neither an array nor a List nor a Map ...

다음과 같은 에러가 발생하고 

formData를 확인하면

param[0]["name"] = wedul
param[0]["age"]=1

과 같이 되어있는것을 확인할 수 있다.

이를 해결하기 위해서는 다음과  json 데이터를 만들어서 전송한다.



1
2
3
var param = {}; 
param['userDatas[' + index +'].name'] = 'yhkim' ;
param['userDatas[' + index +'].age'] = 1; 
cs


댓글()

css 파일 Uncaught SyntaxError: Invalid or unexpected token 에러

web/Web|2018. 5. 27. 10:53

css 파일 로드시 


브라우저에서 다음과 같은 오류가 출력되는 경우가 있다.


Uncaught SyntaxError: Invalid or unexpected token



이 때 가장 의심해 볼 수 있는 부분은 css 파일 로드시


<script src=""> 

다음과 같은 방식으로 로드했는지 의심해 보아야 한다.


css 파일은 자바스크립트 파일이 아니기 때문에 로드시 문법 오류를 유발 할 수 있다. 


그래서 css 파일로드시 다음과 같이 로드하여야 한다.


<link href=""  rel="stylesheet" type="text/css" /> 

댓글()
  1. 2019.08.21 14:23 댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

var와 let 그리고 const 차이점과 사용법 소개

web/javaScript|2018. 5. 27. 10:28

es5까지 Javascript에는 변수 선언할때 var를 사용하였었다.
하지만 var를 선언하여 변수를 선언할때 잘못된 사용으로 인해 문제가 발생하는 경우가 있었다.

하지만

자바스크립트 es6로 올라가게 되면서 let 그리고 const 가 추가되었다.

프로젝트를 진행하면서 es6를 처음 사용하게 되었는데
java8이 나와서 java 사용이 편해진 것 처럼 es6를 사용하면서 더욱 편하게 개발을 진행하였다.

그럼 es6의 특징에 대해 알아보자.

[var와의 차이]
var는 function-scoped이고, let 그리고 const는 block-scoped 이다.

함수 스코프는 모든 변수가 함수에 속하고 한수 전체에 걸쳐서 사용되는 개념이다.
block-scoped는 선언된 변수를 둘러싼 블록의 스코프를 이용하는 개념이다.


변경내용 1)
기존의 var의 경우 두 번이상 선언이 가능하지만 
let, const의 경우 일반 개발언어들과 동일하게 두번이상 선언하게 될 경우 오류를 내보낸다.






변경내용 2)
var에 경우 먼전 선언하지 않아도 밑어딘가에 선언되어 있을 경우 
함수 호이스팅에 의해서 동작되지만 

const와 let의 경우에는 오류가 발생한다. 이는 더 직관적이고 
오류를 더 방지할 수 있다.





다른 예도 살펴 보자






변경내용 3)
var의 경우 전역 변수를 선언할 경우에 global object의 properties로 들어가게 된다.

선언된 global object를 사용하기 위해서 this나 window 키워드를 통해 사용한다.
하지만 let이나 const의 경우에는 global object의 properties를 생설할 수 없다.





[let과 const 차이]
const는 상수를 선언할 때 사용한다.

const는 재 선언이 안된다.
그러므로 array, object, function등을 const로 많이 선언한다.



1
2
3
4
const foo = [0, 1];
const arr = function() {
  console.log('dd');
};
cs





[결론]
var을 사용하지 말고, let 과 const 를 사용하고,
let은 변수 상수는 const를 사용하자.

댓글()