최지우

add readme, 카테고리별 검색 기능

1 +## Subject
2 +Kakao 지도 API를 이용한 여행 경로 추천 서비스
3 +출발지와 도착지를 설정하면 사이 경로의 유명 관광지/음식점/카페 등을 카테고리 별로 반환
4 +원하는 장소를 경유지로 추가하여 경로를 재검색
5 +
6 +## How to build
7 +### npm
8 +
9 + ~$ npm install
10 +
11 +### Kakao 지도 API
12 +<https://apis.map.kakao.com/web/>
13 +카카오계정을 통해 APP KEY를 발급받은 후 views/main.ejs, views/search.ejs의 아래 부분에 추가
14 +src = "//dapi.kakao.com/v2/maps/sdk.js?appkey=APPKEY&libraries=services"
15 +
16 +## How to use
17 +- 메인 페이지 지도상에서 출발지와 도착지를 선택하고 검색버튼 클릭
18 +- 검색된 페이지에서 이동 경로에 있는 카테고리 별 장소(관광명소, 숙박, 카페, 음식점)를 검색 가능
19 +- 지도 상에 마커와 인포윈도우를 통해 결과를 출력
20 +- 원하는 경유지를 선택하여 경로 재검색 가능
21 +
22 +## License
23 +MIT License
24 +
25 +Copyright (c) 2020 Jiwoo Choi
26 +Permission is hereby granted, free of charge, to any person
27 +obtaining a copy of this software and associated documentation
28 +files (the "Software"), to deal in the Software without
29 +restriction, including without limitation the rights to use,
30 +copy, modify, merge, publish, distribute, sublicense, and/or sell
31 +copies of the Software, and to permit persons to whom the
32 +Software is furnished to do so, subject to the following conditions:
33 +
34 +The above copyright notice and this permission notice shall be
35 +included in all copies or substantial portions of the Software.
36 +
37 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
38 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
39 +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
40 +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
41 +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
42 +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
43 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
44 +OTHER DEALINGS IN THE SOFTWARE.
...\ No newline at end of file ...\ No newline at end of file
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
14 <script> 14 <script>
15 var mapContainer = document.getElementById('map'), // 지도를 표시할 div 15 var mapContainer = document.getElementById('map'), // 지도를 표시할 div
16 mapOption = { 16 mapOption = {
17 - center: new kakao.maps.LatLng(33.450701, 126.570667), 17 + center: new kakao.maps.LatLng(37.564213, 127.001698),
18 - level: 3 // 지도의 확대 레벨 18 + level: 10 // 지도의 확대 레벨
19 }; 19 };
20 20
21 var map = new kakao.maps.Map(mapContainer, mapOption); // 지도를 생성합니다 21 var map = new kakao.maps.Map(mapContainer, mapOption); // 지도를 생성합니다
...@@ -39,7 +39,7 @@ var startDragSrc = 'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/red ...@@ -39,7 +39,7 @@ var startDragSrc = 'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/red
39 var startDragImage = new kakao.maps.MarkerImage(startDragSrc, startDragSize, startDragOption); 39 var startDragImage = new kakao.maps.MarkerImage(startDragSrc, startDragSize, startDragOption);
40 40
41 // 출발 마커가 표시될 위치입니다 41 // 출발 마커가 표시될 위치입니다
42 -var startPosition = new kakao.maps.LatLng(33.450701, 126.570667); 42 +var startPosition = new kakao.maps.LatLng(37.564213, 127.001698);
43 43
44 44
45 // 출발 마커를 생성합니다 45 // 출발 마커를 생성합니다
...@@ -83,7 +83,7 @@ var arriveDragSrc = 'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/bl ...@@ -83,7 +83,7 @@ var arriveDragSrc = 'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/bl
83 var arriveDragImage = new kakao.maps.MarkerImage(arriveDragSrc, arriveDragSize, arriveDragOption); 83 var arriveDragImage = new kakao.maps.MarkerImage(arriveDragSrc, arriveDragSize, arriveDragOption);
84 84
85 // 도착 마커가 표시될 위치입니다 85 // 도착 마커가 표시될 위치입니다
86 -var arrivePosition = new kakao.maps.LatLng(33.450701, 126.572667); 86 +var arrivePosition = new kakao.maps.LatLng(37.564213, 127.011698);
87 87
88 // 도착 마커를 생성합니다 88 // 도착 마커를 생성합니다
89 var arriveMarker = new kakao.maps.Marker({ 89 var arriveMarker = new kakao.maps.Marker({
......
...@@ -2,13 +2,96 @@ ...@@ -2,13 +2,96 @@
2 <html> 2 <html>
3 <head> 3 <head>
4 <meta charset="utf-8"> 4 <meta charset="utf-8">
5 - <title>카테고리로 장소 검색하기</title> 5 + <title>검색 결과</title>
6 + <style>
7 +.map_wrap, .map_wrap * {margin:0; padding:0;font-family:'Malgun Gothic',dotum,'돋움',sans-serif;font-size:12px;}
8 +.map_wrap {position:relative;width:100%;height:800px;}
9 +#category {position:absolute;top:10px;left:10px;border-radius: 5px; border:1px solid #909090;box-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);background: #fff;overflow: hidden;z-index: 2;}
10 +#category li {float:left;list-style: none;width:50px;px;border-right:1px solid #acacac;padding:6px 0;text-align: center; cursor: pointer;}
11 +#category li.on {background: #eee;}
12 +#category li:hover {background: #ffe6e6;border-left:1px solid #acacac;margin-left: -1px;}
13 +#category li:last-child{margin-right:0;border-right:0;}
14 +#category li span {display: block;margin:0 auto 3px;width:27px;height: 28px;}
15 +#category li .category_bg {background:url(https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/places_category.png) no-repeat;}
16 +#category li .bank {background-position: -10px 0;}
17 +#category li .mart {background-position: -10px -36px;}
18 +#category li .pharmacy {background-position: -10px -72px;}
19 +#category li .oil {background-position: -10px -108px;}
20 +#category li .cafe {background-position: -10px -144px;}
21 +#category li .store {background-position: -10px -180px;}
22 +#category li.on .category_bg {background-position-x:-46px;}
23 +.placeinfo_wrap {position:absolute;bottom:28px;left:-150px;width:300px;}
24 +.placeinfo {position:relative;width:100%;border-radius:6px;border: 1px solid #ccc;border-bottom:2px solid #ddd;padding-bottom: 10px;background: #fff;}
25 +.placeinfo:nth-of-type(n) {border:0; box-shadow:0px 1px 2px #888;}
26 +.placeinfo_wrap .after {content:'';position:relative;margin-left:-12px;left:50%;width:22px;height:12px;background:url('https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/vertex_white.png')}
27 +.placeinfo a, .placeinfo a:hover, .placeinfo a:active{color:#fff;text-decoration: none;}
28 +.placeinfo a, .placeinfo span {display: block;text-overflow: ellipsis;overflow: hidden;white-space: nowrap;}
29 +.placeinfo span {margin:5px 5px 0 5px;cursor: default;font-size:13px;}
30 +.placeinfo .title {font-weight: bold; font-size:14px;border-radius: 6px 6px 0 0;margin: -1px -1px 0 -1px;padding:10px; color: #fff;background: #d95050;background: #d95050 url(https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/arrow_white.png) no-repeat right 14px center;}
31 +.placeinfo .tel {color:#0f7833;}
32 +.placeinfo .jibun {color:#999;font-size:11px;margin-top:0;}
6 33
34 +
35 +.map_wrap a, .map_wrap a:hover, .map_wrap a:active{color:#000;text-decoration: none;}
36 +#menu_wrap {position:absolute;top:0;left:1600px;bottom:0;width:250px;margin:10px 0 30px 10px;padding:5px;overflow-y:auto;background:rgba(255, 255, 255, 0.7);z-index: 1;font-size:12px;border-radius: 10px;}
37 +.bg_white {background:#fff;}
38 +#placesList li {list-style: none;}
39 +#placesList .item {position:relative;border-bottom:1px solid #888;overflow: hidden;cursor: pointer;min-height: 65px;}
40 +#placesList .item span {display: block;margin-top:4px;}
41 +#placesList .item h5, #placesList .item .info {text-overflow: ellipsis;overflow: hidden;white-space: nowrap;}
42 +#placesList .item .info{padding:10px 0 10px 55px;}
43 +#placesList .info .gray {color:#8a8a8a;}
44 +#placesList .info .jibun {padding-left:26px;background:url(https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/places_jibun.png) no-repeat;}
45 +#placesList .info .tel {color:#009900;}
46 +#placesList .item .markerbg {float:left;position:absolute;width:36px; height:37px;margin:10px 0 0 10px;background:url(https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/marker_number_blue.png) no-repeat;}
47 +#placesList .item .marker_1 {background-position: 0 -10px;}
48 +#placesList .item .marker_2 {background-position: 0 -56px;}
49 +#placesList .item .marker_3 {background-position: 0 -102px}
50 +#placesList .item .marker_4 {background-position: 0 -148px;}
51 +#placesList .item .marker_5 {background-position: 0 -194px;}
52 +#placesList .item .marker_6 {background-position: 0 -240px;}
53 +#placesList .item .marker_7 {background-position: 0 -286px;}
54 +#placesList .item .marker_8 {background-position: 0 -332px;}
55 +#placesList .item .marker_9 {background-position: 0 -378px;}
56 +#placesList .item .marker_10 {background-position: 0 -423px;}
57 +#placesList .item .marker_11 {background-position: 0 -470px;}
58 +#placesList .item .marker_12 {background-position: 0 -516px;}
59 +#placesList .item .marker_13 {background-position: 0 -562px;}
60 +#placesList .item .marker_14 {background-position: 0 -608px;}
61 +#placesList .item .marker_15 {background-position: 0 -654px;}
62 +#pagination {margin:10px auto;text-align: center;}
63 +#pagination a {display:inline-block;margin-right:10px;}
64 +#pagination .on {font-weight: bold; cursor: default;color:#777;}
65 +</style>
7 </head> 66 </head>
8 <body> 67 <body>
9 68
10 -<div id="map" style="width:100%;height:800px;"></div> 69 +<div class="map_wrap">
11 - 70 + <div id="map" style="width:100%;height:800px;position:relative;overflow:hidden;"></div>
71 + <ul id="category">
72 + <li id="AT4" data-order="0">
73 + <span class="category_bg oil"></span>
74 + 관광지
75 + </li>
76 + <li id="AD5" data-order="1">
77 + <span class="category_bg mart"></span>
78 + 숙박
79 + </li>
80 + <li id="CE7" data-order="2">
81 + <span class="category_bg cafe"></span>
82 + 카페
83 + </li>
84 + <li id="FD6" data-order="3">
85 + <span class="category_bg store"></span>
86 + 음식점
87 + </li>
88 + </ul>
89 + <div id="menu_wrap" class="bg_white">
90 + <hr>
91 + <ul id="placesList"></ul>
92 + <div id="pagination"></div>
93 + </div>
94 +</div>
12 <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=비밀&libraries=services"></script> 95 <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=비밀&libraries=services"></script>
13 <script> 96 <script>
14 var Request = function() { 97 var Request = function() {
...@@ -31,47 +114,283 @@ var startx = request.getParameter('startx'); ...@@ -31,47 +114,283 @@ var startx = request.getParameter('startx');
31 var starty = request.getParameter('starty'); 114 var starty = request.getParameter('starty');
32 var endx = request.getParameter('endx'); 115 var endx = request.getParameter('endx');
33 var endy = request.getParameter('endy'); 116 var endy = request.getParameter('endy');
34 -// 마커를 클릭하면 장소명을 표출할 인포윈도우 입니다 117 +
35 -var infowindow = new kakao.maps.InfoWindow({zIndex:1}); 118 +var sw = new kakao.maps.LatLng(startx, endy),
119 + ne = new kakao.maps.LatLng(endx, starty);
120 +
121 +var bs = new kakao.maps.LatLngBounds(sw, ne);
122 +
123 +var placeOverlay = new kakao.maps.CustomOverlay({zIndex:1}),
124 + contentNode = document.createElement('div'), // 커스텀 오버레이의 컨텐츠 엘리먼트 입니다
125 + markers = [], // 마커를 담을 배열입니다
126 + currCategory = ''; // 현재 선택된 카테고리를 가지고 있을 변수입니다
36 127
37 var mapContainer = document.getElementById('map'), // 지도를 표시할 div 128 var mapContainer = document.getElementById('map'), // 지도를 표시할 div
38 mapOption = { 129 mapOption = {
39 center: new kakao.maps.LatLng(endx, endy), // 지도의 중심좌표 130 center: new kakao.maps.LatLng(endx, endy), // 지도의 중심좌표
40 - level: 5 // 지도의 확대 레벨 131 + level: 8 // 지도의 확대 레벨
41 }; 132 };
42 133
43 // 지도를 생성합니다 134 // 지도를 생성합니다
44 var map = new kakao.maps.Map(mapContainer, mapOption); 135 var map = new kakao.maps.Map(mapContainer, mapOption);
45 136
46 // 장소 검색 객체를 생성합니다 137 // 장소 검색 객체를 생성합니다
47 -var ps = new kakao.maps.services.Places(map); 138 +var ps = new kakao.maps.services.Places();
48 139
49 -// 카테고리로 유명관광지를 검색합니다 140 +// 지도에 idle 이벤트를 등록합니다
50 -ps.categorySearch('AT4', placesSearchCB, {useMapBounds:true}); 141 +kakao.maps.event.addListener(map, 'idle', searchPlaces);
51 142
52 -// 키워드 검색 완료 시 호출되는 콜백함수 입니다 143 +// 커스텀 오버레이의 컨텐츠 노드에 css class를 추가합니다
53 -function placesSearchCB (data, status, pagination) { 144 +contentNode.className = 'placeinfo_wrap';
54 - if (status === kakao.maps.services.Status.OK) { 145 +
55 - for (var i=0; i<data.length; i++) { 146 +// 커스텀 오버레이의 컨텐츠 노드에 mousedown, touchstart 이벤트가 발생했을때
56 - displayMarker(data[i]); 147 +// 지도 객체에 이벤트가 전달되지 않도록 이벤트 핸들러로 kakao.maps.event.preventMap 메소드를 등록합니다
148 +addEventHandle(contentNode, 'mousedown', kakao.maps.event.preventMap);
149 +addEventHandle(contentNode, 'touchstart', kakao.maps.event.preventMap);
150 +
151 +// 커스텀 오버레이 컨텐츠를 설정합니다
152 +placeOverlay.setContent(contentNode);
153 +
154 +// 각 카테고리에 클릭 이벤트를 등록합니다
155 +addCategoryClickEvent();
156 +
157 +// 엘리먼트에 이벤트 핸들러를 등록하는 함수입니다
158 +function addEventHandle(target, type, callback) {
159 + if (target.addEventListener) {
160 + target.addEventListener(type, callback);
161 + } else {
162 + target.attachEvent('on' + type, callback);
57 } 163 }
164 +}
165 +
166 +// 카테고리 검색을 요청하는 함수입니다
167 +function searchPlaces() {
168 + if (!currCategory) {
169 + return;
170 + }
171 +
172 + // 커스텀 오버레이를 숨깁니다
173 + placeOverlay.setMap(null);
174 +
175 + removeMarker();
176 + // 지도에 표시되고 있는 마커를 제거합니다
177 +
178 + ps.categorySearch(currCategory, placesSearchCB, {bounds : bs});
179 +}
180 +
181 +// 장소검색이 완료됐을 때 호출되는 콜백함수 입니다
182 +function placesSearchCB(data, status, pagination) {
183 + if (status === kakao.maps.services.Status.OK) {
184 +
185 + // 정상적으로 검색이 완료됐으면 지도에 마커를 표출합니다
186 + displayPlaces(data);
187 + displayPagination(pagination);
188 + } else if (status === kakao.maps.services.Status.ZERO_RESULT) {
189 + // 검색결과가 없는경우 해야할 처리가 있다면 이곳에 작성해 주세요
190 + alert('검색 결과가 존재하지 않습니다.');
191 + return;
192 +
193 + } else if (status === kakao.maps.services.Status.ERROR) {
194 + // 에러로 인해 검색결과가 나오지 않은 경우 해야할 처리가 있다면 이곳에 작성해 주세요
195 + alert('검색 결과 중 오류가 발생했습니다.');
196 + return;
58 } 197 }
59 } 198 }
60 199
61 -// 지도에 마커를 표시하는 함수입니다 200 +// 지도에 마커를 표출하는 함수입니다
62 -function displayMarker(place) { 201 +function displayPlaces(places) {
202 +
203 + var listEl = document.getElementById('placesList'),
204 + menuEl = document.getElementById('menu_wrap'),
205 + fragment = document.createDocumentFragment(),
206 + listStr = '';
207 + removeAllChildNods(listEl);
208 + removeMarker();
209 + // 몇번째 카테고리가 선택되어 있는지 얻어옵니다
210 + // 이 순서는 스프라이트 이미지에서의 위치를 계산하는데 사용됩니다
211 + var order = document.getElementById(currCategory).getAttribute('data-order');
212 +
213 + for ( var i=0; i<places.length; i++ ) {
214 + var placePosition = new kakao.maps.LatLng(places[i].y, places[i].x);
215 +
63 // 마커를 생성하고 지도에 표시합니다 216 // 마커를 생성하고 지도에 표시합니다
64 - var marker = new kakao.maps.Marker({ 217 + var marker = addMarker(placePosition, order);
65 - map: map, 218 + var itemEl = getListItem(i, places[i]);
66 - position: new kakao.maps.LatLng(place.y, place.x) 219 + // 마커와 검색결과 항목을 클릭 했을 때
220 + // 장소정보를 표출하도록 클릭 이벤트를 등록합니다
221 + (function(marker, place) {
222 + kakao.maps.event.addListener(marker, 'click', function() {
223 + displayPlaceInfo(place);
67 }); 224 });
225 + })(marker, places[i]);
226 + fragment.appendChild(itemEl);
227 + }
228 + listEl.appendChild(fragment);
229 + menuEl.scrollTop = 0;
230 +}
68 231
69 - // 마커에 클릭이벤트를 등록합니다 232 +function getListItem(index, places) {
70 - kakao.maps.event.addListener(marker, 'click', function() { 233 +
71 - // 마커를 클릭하면 장소명이 인포윈도우에 표출됩니다 234 + var el = document.createElement('li'),
72 - infowindow.setContent('<div style="padding:5px;font-size:12px;">' + place.place_name + '</div>'); 235 + itemStr = '<span class="markerbg marker_' + (index+1) + '"></span>' +
73 - infowindow.open(map, marker); 236 + '<div class="info">' +
237 + ' <h5>' + places.place_name + '</h5>';
238 +
239 + if (places.road_address_name) {
240 + itemStr += ' <span>' + places.road_address_name + '</span>' +
241 + ' <span class="jibun gray">' + places.address_name + '</span>';
242 + }
243 + else {
244 + itemStr += ' <span>' + places.address_name + '</span>';
245 + }
246 +
247 + itemStr += ' <span class="tel">' + places.phone + '</span>' +
248 + '</div>';
249 +
250 + el.innerHTML = itemStr;
251 + el.className = 'item';
252 +
253 + return el;
254 +}
255 +
256 +// 마커를 생성하고 지도 위에 마커를 표시하는 함수입니다
257 +function addMarker(position, order) {
258 + var imageSrc = 'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/places_category.png', // 마커 이미지 url, 스프라이트 이미지를 씁니다
259 + imageSize = new kakao.maps.Size(27, 28), // 마커 이미지의 크기
260 + imgOptions = {
261 + spriteSize : new kakao.maps.Size(72, 208), // 스프라이트 이미지의 크기
262 + spriteOrigin : new kakao.maps.Point(46, (order*36)), // 스프라이트 이미지 중 사용할 영역의 좌상단 좌표
263 + offset: new kakao.maps.Point(11, 28) // 마커 좌표에 일치시킬 이미지 내에서의 좌표
264 + },
265 + markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imgOptions),
266 + marker = new kakao.maps.Marker({
267 + position: position, // 마커의 위치
268 + image: markerImage
74 }); 269 });
270 +
271 + marker.setMap(map); // 지도 위에 마커를 표출합니다
272 + markers.push(marker); // 배열에 생성된 마커를 추가합니다
273 +
274 + return marker;
275 +}
276 +
277 +// 지도 위에 표시되고 있는 마커를 모두 제거합니다
278 +function removeMarker() {
279 + for ( var i = 0; i < markers.length; i++ ) {
280 + markers[i].setMap(null);
281 + }
282 + markers = [];
283 +}
284 +
285 +// 클릭한 마커에 대한 장소 상세정보를 커스텀 오버레이로 표시하는 함수입니다
286 +function displayPlaceInfo (place) {
287 + var content = '<div class="placeinfo">' +
288 + ' <a class="title" href="' + place.place_url + '" target="_blank" title="' + place.place_name + '">' + place.place_name + '</a>';
289 +
290 + if (place.road_address_name) {
291 + content += ' <span title="' + place.road_address_name + '">' + place.road_address_name + '</span>' +
292 + ' <span class="jibun" title="' + place.address_name + '">(지번 : ' + place.address_name + ')</span>';
293 + } else {
294 + content += ' <span title="' + place.address_name + '">' + place.address_name + '</span>';
295 + }
296 +
297 + content += ' <span class="tel">' + place.phone + '</span>' +
298 + '</div>' +
299 + '<div class="after"></div>';
300 +
301 + contentNode.innerHTML = content;
302 + placeOverlay.setPosition(new kakao.maps.LatLng(place.y, place.x));
303 + placeOverlay.setMap(map);
304 +}
305 +
306 +// 검색결과 목록 하단에 페이지번호를 표시는 함수입니다
307 +function displayPagination(pagination) {
308 + var paginationEl = document.getElementById('pagination'),
309 + fragment = document.createDocumentFragment(),
310 + i;
311 +
312 + // 기존에 추가된 페이지번호를 삭제합니다
313 + while (paginationEl.hasChildNodes()) {
314 + paginationEl.removeChild (paginationEl.lastChild);
315 + }
316 +
317 + for (i=1; i<=pagination.last; i++) {
318 + var el = document.createElement('a');
319 + el.href = "#";
320 + el.innerHTML = i;
321 +
322 + if (i===pagination.current) {
323 + el.className = 'on';
324 + } else {
325 + el.onclick = (function(i) {
326 + return function() {
327 + pagination.gotoPage(i);
328 + }
329 + })(i);
330 + }
331 +
332 + fragment.appendChild(el);
333 + }
334 + paginationEl.appendChild(fragment);
335 +}
336 +
337 +// 검색결과 목록 또는 마커를 클릭했을 때 호출되는 함수입니다
338 +// 인포윈도우에 장소명을 표시합니다
339 +function displayInfowindow(marker, title) {
340 + var content = '<div style="padding:5px;z-index:1;">' + title + '</div>';
341 +
342 + infowindow.setContent(content);
343 + infowindow.open(map, marker);
344 +}
345 +
346 + // 검색결과 목록의 자식 Element를 제거하는 함수입니다
347 + function removeAllChildNods(el) {
348 + while (el.hasChildNodes()) {
349 + el.removeChild (el.lastChild);
350 + }
351 +}
352 +
353 +// 각 카테고리에 클릭 이벤트를 등록합니다
354 +function addCategoryClickEvent() {
355 + var category = document.getElementById('category'),
356 + children = category.children;
357 +
358 + for (var i=0; i<children.length; i++) {
359 + children[i].onclick = onClickCategory;
360 + }
361 +}
362 +
363 +// 카테고리를 클릭했을 때 호출되는 함수입니다
364 +function onClickCategory() {
365 + var id = this.id,
366 + className = this.className;
367 +
368 + placeOverlay.setMap(null);
369 +
370 + if (className === 'on') {
371 + currCategory = '';
372 + changeCategoryClass();
373 + removeMarker();
374 + } else {
375 + currCategory = id;
376 + changeCategoryClass(this);
377 + searchPlaces();
378 + }
379 +}
380 +
381 +// 클릭된 카테고리에만 클릭된 스타일을 적용하는 함수입니다
382 +function changeCategoryClass(el) {
383 + var category = document.getElementById('category'),
384 + children = category.children,
385 + i;
386 +
387 + for ( i=0; i<children.length; i++ ) {
388 + children[i].className = '';
389 + }
390 +
391 + if (el) {
392 + el.className = 'on';
393 + }
75 } 394 }
76 </script> 395 </script>
77 </body> 396 </body>
......