반응형
반응형
export default function Signup() {
  return (
    <form onSubmit={e => {
      e.preventDefault();
      alert('Submitting!');
    }}>
      <input />
      <button>Send</button>
    </form>
  );
}

form 태그에서 onSubmit을 했을 때 화면 전체가 리로딩 되는데 이걸 e.preventDefault()를 이용해 중지시킬 수 있습니다

 

그 외 기본적으로 가지고 있는 동작을 방지하는 것에 대해서 자세히 알아보자면 아래와 같습니다 (그 외 더 많이 존재)

  1. Form 제출
    • 기본적으로 제출하면 폼 데이터가 서버로 전송되지만 폼 제출을 막아서 클라이언트 사이드에서 데이터 검증이나 다른 로직 처리가 가능합니다
  2. a태그 링크이동
    • 링크 이동을 막고 모달창 열거나 등 할 수 있습니다
  3. 마우스 오른쪽 클릭 메뉴 (컨텍스트 메뉴)
    • 오른쪽 버튼 클릭하면 컨텍스트 메뉴가 나오지만 이걸 막고 내가 원하는 컨텍스트 메뉴를 띄우거나 아예 막아버려서 컨텍스트 메뉴를 사용 못하게 할 수 있습니다
  4. 드래그 앤 드롭
    • 요즘 웹브라우저에서 이미지 등을 드래그하면 드래그 앤 드롭이 되는데 이걸 막고 다른 동작을 시킬 수 있습니다
  5. 키보드 입력 (Ctrl+S 등...)
    • 특정 키 조합 (Ctrl + S 등...) 따위를 할 때 기본 동작을 막고 사용자가 정의한 동작을 실행시킬 수 있습니다
  6. 터치 이벤트
    • 터치 기반 디바이스에서 스크롤, 스와이프와 같은 제스처는 특정 UI 요소에서 다르게 동작하도록 설정할 수 있습니다. 예를 들어, 캐러셀 슬라이드에서 스와이프로 슬라이드를 넘기는 동작을 구현할 때 기본 스크롤 동작을 막기 위해 사용할 수 있습니다
반응형
반응형

 

<!DOCTYPE html>
<html lang="en">
<script>
    let number = 123;
    console.log(typeof(number + "")) // string

    let letter = "123";
    console.log(typeof(+ letter));   // number
</script>
<body>

</body>
</html>

 

  • "문자" → "숫자"
    • + 문자 라고 적을시 숫자로 변환된다
  • "숫자" → "문자"
    • 숫자 + "" 라고 적을시 문자로 변환된다

 

반응형
반응형
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<body>
    <input type="file" id="fileInput">
</body>
<script>
    fileInput = document.getElementById('fileInput');

    fileInput.addEventListener('change', function() {
        const file = fileInput.files[0];
        console.log(URL.createObjectURL(file));
        // blob:http://localhost:63342/8a91fb57-0311-4375-b2e4-84bb0c9fc3d6
    });
</script>
</html>

Blob(Binary Large Object)은 말 그대로 큰 객체를 저장하는 타입으로 큰 객체란 일반적으로 이미지, 비디오, 사운드 등과 같은 멀티미디어객체들을 주로 가리킵니다. createObjectURL는 메모리에 있는 객체(일반적으로 Blob이나 File 객체)에 대한 임시 URL을 생성가능합니다

반응형
반응형

 

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>authentication</title>
</head>
<script src="https://code.jquery.com/jquery-3.6.2.js" integrity="sha256-pkn2CUZmheSeyssYw3vMp1+xyub4m+e+QK4sQskvuo4=" crossorigin="anonymous"></script>

<link rel="stylesheet" href="./resource/css/pattern_lock.css">
<script src="./resource/js/pattern_lock.js" charset="utf-8"></script>
<body>


	<!-- 패턴-->
	<svg class="patternlock" id="lock" viewBox="0 0 100 100">
		<g class="lock-actives"></g>
		<g class="lock-lines"></g>
		<g class="lock-dots">
			<circle cx="20" cy="20" r="2"/>
			<circle cx="50" cy="20" r="2"/>
			<circle cx="80" cy="20" r="2"/>
	 
			<circle cx="20" cy="50" r="2"/>
			<circle cx="50" cy="50" r="2"/>
			<circle cx="80" cy="50" r="2"/>
	 
			<circle cx="20" cy="80" r="2"/>
			<circle cx="50" cy="80" r="2"/>
			<circle cx="80" cy="80" r="2"/>
		</g>
    </svg>

	<button onClick="clearPattern()"> Clear </button>

</body>


<script>

	/** 패턴 핸들러 **/
	let lock = new PatternLock("#lock", {
		onPattern: (pattern) => {
			console.log(pattern); // 입력한 패턴 값

			if(pattern === 123){
				lock.success();
			}else{
				lock.error();
			}

		},
		vibrate: false // 진동 on / off
	});

	let clearPattern = () =>{
		lock.clear();
	}

	let getPattern = () =>{
		lock.getPattern();
	}

	
</script>

</html>

index.html

(function (factory) {
  var global = Function('return this')() || (0, eval)('this');
  if (typeof define === 'function' && define.amd) {
      // AMD. Register as an anonymous module.
      define(['jquery'], function($) {
          return factory($, global)
      });
  } else if (typeof exports === 'object') {
      // Node. Does not work with strict CommonJS, but
      // only CommonJS-like environments that support module.exports,
      // like Node.
      module.exports = factory(require('jquery'), global);
  } else {
      // Browser globals (global is window)
      global.PatternLock = factory(global.jQuery, global);
  }
}(function ($, window) {
  var svgns = 'http://www.w3.org/2000/svg'
  var moveEvent = 'touchmove mousemove'

  var scrollKeys = {
      37: true, // left
      38: true, // up
      39: true, // right
      40: true, // down
      32: true, // spacebar
      38: true, // pageup
      34: true, // pagedown
      35: true, // end
      36: true, // home
  };

  function vibrate() {
      navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;
      if (navigator.vibrate) {
          window.navigator.vibrate(25)
      }
  }

  function PatternLock(element, options) {
      let svg = $(element)
      let self = this
      let root = svg[0]
      let dots = svg.find('.lock-dots circle')
      let lines = svg.find('.lock-lines')
      let actives = svg.find('.lock-actives')
      var pt = root.createSVGPoint();
      let code = []
      let currentline
      let currenthandler

      options = Object.assign(PatternLock.defaults, options || {})

      svg.on('touchstart mousedown', (e) => {
          clear()
          e.preventDefault()
          disableScroll()
          svg.on(moveEvent, discoverDot)
          let endEvent = e.type == 'touchstart' ? 'touchend' : 'mouseup';
          $(document).one(endEvent, (e) => {
              end()
          })
      })

      // Exported methods
      Object.assign(this, {
          clear,
          success,
          error,
          getPattern,
      })

      function success() {
          svg.removeClass('error')
          svg.addClass('success')
      }

      function error() {
          svg.removeClass('success')
          svg.addClass('error')
      }

      function getPattern() {
          return parseInt(code.map((i) => dots.index(i)+1).join(''))
      }

      function end() {
          enableScroll()
          stopTrack(currentline)
          currentline && currentline.remove()
          svg.off(moveEvent, discoverDot)
          let val = options.onPattern.call(self, getPattern())
          if (val === true) {
              success()
          } else if (val === false) {
              error()
          }
      }

      function clear() {
          code = []
          currentline = undefined
          currenthandler = undefined
          svg.removeClass('success error')
          lines.empty()
          actives.empty()
      }

      function preventDefault(e) {
          e = e || window.event;
          if (e.preventDefault)
              e.preventDefault();
          e.returnValue = false;
      }

      function preventDefaultForScrollKeys(e) {
          if (scrollKeys[e.keyCode]) {
              preventDefault(e);
              return false;
          }
      }

      function disableScroll() {
          if (window.addEventListener) // older FF
              window.addEventListener('DOMMouseScroll', preventDefault, false);
          window.onwheel = preventDefault; // modern standard
          window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE
          window.ontouchmove = preventDefault; // mobile
          document.onkeydown = preventDefaultForScrollKeys;
      }

      function enableScroll() {
          if (window.removeEventListener)
              window.removeEventListener('DOMMouseScroll', preventDefault, false);
          window.onmousewheel = document.onmousewheel = null;
          window.onwheel = null;
          window.ontouchmove = null;
          document.onkeydown = null;
      }

      function isUsed(target) {
          for (let i = 0; i < code.length; i++) {
              if (code[i] === target) {
                  return true
              }
          }
          return false
      }

      function isAvailable(target) {
          for (let i = 0; i < dots.length; i++) {
              if (dots[i] === target) {
                  return true
              }
          }
          return false
      }

      function updateLine(line) {
          return function(e) {
              e.preventDefault()
              if (currentline !== line) return
              let pos = svgPosition(e.target, e)
              line.setAttribute('x2', pos.x)
              line.setAttribute('y2', pos.y)
              return false
          }
      }

      function discoverDot(e, target) {
          if (!target) {
              let {x, y} = getMousePos(e)
              target = document.elementFromPoint(x, y);
          }
          let cx = target.getAttribute('cx')
          let cy = target.getAttribute('cy')
          if (isAvailable(target) && !isUsed(target)) {
              stopTrack(currentline, target)
              currentline = beginTrack(target)
          }
      }

      function stopTrack(line, target) {
          if (line === undefined) return
          if (currenthandler) {
              svg.off('touchmove mousemove', currenthandler)
          }
          if (target === undefined) return
          let x = target.getAttribute('cx')
          let y = target.getAttribute('cy')
          line.setAttribute('x2', x)
          line.setAttribute('y2', y)
      }

      function beginTrack(target) {
          code.push(target)
          let x = target.getAttribute('cx')
          let y = target.getAttribute('cy')
          var line = createNewLine(x, y)
          var marker = createNewMarker(x, y)
          actives.append(marker)
          currenthandler = updateLine(line)
          svg.on('touchmove mousemove', currenthandler)
          lines.append(line);
          if(options.vibrate) vibrate()
          return line
      }

      function createNewMarker(x, y) {
          var marker = document.createElementNS(svgns, "circle")
          marker.setAttribute('cx', x)
          marker.setAttribute('cy', y)
          marker.setAttribute('r', 6)
          return marker
      }

      function createNewLine(x1, y1, x2, y2) {
          var line = document.createElementNS(svgns, "line")
          line.setAttribute('x1', x1)
          line.setAttribute('y1', y1)
          if (x2 === undefined || y2 == undefined) {
              line.setAttribute('x2', x1)
              line.setAttribute('y2', y1)
          } else {
              line.setAttribute('x2', x2)
              line.setAttribute('y2', y2)
          }
          return line
      }

      function getMousePos(e) {
          return {
              x: e.clientX || e.originalEvent.touches[0].clientX,
              y :e.clientY || e.originalEvent.touches[0].clientY
          }
      }

      function svgPosition(element, e) {
          let {x, y} = getMousePos(e)
          pt.x = x; pt.y = y;
          return pt.matrixTransform(element.getScreenCTM().inverse());
      }
  }


  PatternLock.defaults = {
      onPattern: () => {},
      vibrate: true,
  }


  return PatternLock
}));

pattern_lock.js

 

svg.patternlock g.lock-lines line {
    stroke-width: 1.5;
    stroke: black;
    opacity: 0.5;
}

svg.patternlock g.lock-dots circle {
    stroke: transparent;
    fill: black;
    stroke-width: 13.5;
}

svg.patternlock g.lock-actives circle {
    fill: black;
    opacity: .2;
    animation: lock-activate-dot .15s 0s ease 1;
    transform-origin: center;
}

svg.patternlock g.lock-lines line {
    stroke-width: 1.5;
    stroke-linecap: round;
}

svg.patternlock.success g.lock-actives circle {
    fill: green;
}

svg.patternlock.error g.lock-actives circle {
    fill: red;
}

@keyframes lock-activate-dot {
    0% {
        transform: scale(0);
    }
    75% {
        transform: scale(1.1);
    }
    100% {
        transform: scale(1.0);
    }
}

pattern_lock.css

 

성공
실패

출처 : https://github.com/tympanix/pattern-lock-js

 

GitHub - tympanix/pattern-lock-js: An android inspired pattern lock in scalable vector graphics and pure javascript

An android inspired pattern lock in scalable vector graphics and pure javascript - GitHub - tympanix/pattern-lock-js: An android inspired pattern lock in scalable vector graphics and pure javascript

github.com

 

자세한 문서는 위에 깃허브 참조하시면 됩니다.

반응형
반응형

ajax로 받아온 데이터 jstl에서 사용하고 싶을 시

 

웹페이지 구동 순서는 JAVA(Controller) > JSTL > HTML > JavaScript 순이기 때문에

ajax로 받아온다한들 JSTL부분이 앞에 있어서 화면에 받아온 데이터를 다시 그려주질 못한다.

 

그래서 내가 생각하기에는 SPA를 구현할거면 ajax만 이용하고 MPA의 경우는 JSTL만 사용하는게 올바르다.

 

MPA를 SPA로 다 뜯어고치기 힘든 경우라면 이런 방법을 추천한다.

 

1. ajax로 다시 그려줄 부분을 jsp로 뺀다.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<html>
<head>
	<title>Home</title>
</head>
<body>
<h1>
	Hello world! My Name is ${name}  
</h1>

<P>  The time on the server is ${serverTime}. </P>

<button> 현재 시각을 동적으로 가져옵니다. </button>

</body>
</html>

원본 JSP

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<html>
<head>
	<title>Home</title>
</head>
<body>
<script src="https://code.jquery.com/jquery-3.6.2.js" integrity="sha256-pkn2CUZmheSeyssYw3vMp1+xyub4m+e+QK4sQskvuo4=" crossorigin="anonymous"></script>
<h1>
	Hello world! My Name is ${name}  
</h1>

<div id='ajaxRendering'>
	<P>  The time on the server is ${serverTime}. </P>
</div>

<button onClick=getTime()> 현재 시각을 동적으로 가져옵니다. </button>
	
</body>

<script>

	function getTime() {
		$.ajax({
			url: "/ajax",
			type: 'GET',
			success: function(result){
				$("#ajaxRendering").html(result);
			}	
		
		}); //ajax end	
	} 
</script>
</html>

원본 수정한 페이지 (button으로 ajax 렌더링하는 부분 및 그려줄 부분을 뺐다.)

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<html>

<P>  The time on the server is ${serverTime}. </P>

</body>
</html>

ajax로 그려주는 페이지

 

 

2. Controller에서 다시 그려줄 부분을 뺀 jsp를 호출한다.

package com.lsj.spring_study;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class AjaxController {
	/** ajax로 호출할 페이지 **/
	@RequestMapping(value = "/ajax", method = RequestMethod.GET)
	public String ajaxPage(Model model) {
		
        Date now = new Date();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowTime = sdf1.format(now);
		
		model.addAttribute("serverTime", nowTime);
		
		return "ajax";
		
	}
	
    	/** 원본 페이지 **/
	@RequestMapping(value = "/origin", method = RequestMethod.GET)
	public String originPage(Model model) {
        
		
        Date now = new Date();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowTime = sdf1.format(now);
		
		model.addAttribute("name", "마이클");
		model.addAttribute("serverTime", nowTime);
		
		return "origin";
		
	}

	
}

3. 본 페이지에서 해당 버튼을 클릭시 ajax를 호출한다.

 

origin이라는 URL 호출시 나오는 화면 (JSTL로 현재시각을 받아오려면 해당 URL을 호출해야함 → 새로고침)

 

버튼 클릭 후 네트워크 통신해서 다시 그려준 화면

 

 

 

 

 

 

출처 : https://my-t-space.tistory.com/47

반응형
반응형
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script src="https://code.jquery.com/jquery-3.6.2.js" integrity="sha256-pkn2CUZmheSeyssYw3vMp1+xyub4m+e+QK4sQskvuo4=" crossorigin="anonymous"></script>
<body>

    <div id="Ahistory">
        Ahistory (뒤로가기가 존재합니다.)
    </div>

    <div id="Bhistory">
        Bhistory (뒤로가기가 존재하지 않습니다.)
    </div>
</body>

<script>

$('#Ahistory').click(() =>{
    location.href = 'https://www.naver.com';
});

$('#Bhistory').click(() =>{
    location.replace('https://www.naver.com');
});

</script>
</html>

 

반응형
반응형

앵커(Anchor) A태그를 의미한다.


A태그로 function 사용하는 방법은 3가지가 있습니다.
1. <a href="javascript:callHello();">javascript function</a>
<a href="javascript:function callHello(){alert("hello");} a();">javascript function</a> <!-- 위와 동일 -->

2. <a href="javascript:void(0);" onclick="callHello();">onclick function</a>

3. <a href="#" onclick="callHello();">call function</a>
href="#"을 해 놓으면 클릭시 이벤트 버블링으로 인해 anchor을 타서 브라우저 상단으로 이동합니다.
2번과 같은 방식또는 <a href="#;" onclick="callHello(); return false;">onclick function</a>와 같이 처리로
브라우저 상단으로 안 가게 가능합니다.

반응형
반응형
$.ajax({
    url: "http://127.0.0.1:8080/ocr_search/engine", // Generally use Controller URI
    type: "GET", // GET, POST
    data: {
        status : "200",
        id : "hello",
        shaAdminPw : "hhh",
        type : "f"
    },
    //async : false, // Async 
    success : (result) => console.log(result), //when you success, you can handle it
    fail : (error) => console.log(error), // when you fail, you can handle it
    complete : (finalResult) => console.log(finalResult) // it runs, whenever you fail or success
});

 

@RequestMapping(value = "/engine", method = RequestMethod.GET)
public void engine(EngineDto engineDto) {
	System.out.println(engineDto.getId()); // hello
}
public class EngineDto {

	private String status = "";
	private String id = "";
	private String shaAdminPw = "";
	private String type = "f";

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getShaAdminPw() {
		return shaAdminPw;
	}

	public void setShaAdminPw(String shaAdminPw) {
		this.shaAdminPw = shaAdminPw;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
	
}

해당 객체에 setter만 있으면 알아서 잘 data-binding 됩니다.

 

반응형
반응형
function drawRamPieChartAjax(){

	return new Promise((resolve,reject) =>{
	$.ajax({
		url: "pie-charat",
		type: 'GET',
		success: function(data) {
			initRamPieChart();

			let totalRamSize = data.total_ram;
			let freeRamSize = data.free_ram;
			let usedRamSize = totalRamSize - freeRamSize;

			drawRamPieChart(usedRamSize, freeRamSize);

			resolve("sucess");
		}, //success end
		error : function (error) {
			alert(error.status);       // 에러코드 
			alert(error.responseText); // Error 메시지 
		}, // error end
		complete : function (){
			alert("finally");
		}
	}); //ajax end	
	}); // promise end
}
반응형