6 * LICENSE: This source file is licensed under the terms of the GNU General Public License.
8 * @package Magic3 Framework
9 * @author 平田直毅(Naoki Hirata) <naoki@aplo.co.jp>
10 * @copyright Copyright 2006-2013 Magic3 Project.
11 * @license http://www.gnu.org/copyleft/gpl.html GPL License
12 * @version SVN: $Id: main.js 6030 2013-05-22 00:48:33Z fishbone $
13 * @link http://www.magic3.org
17 CKEDITOR.dialog.add('googlemaps', function(editor){
26 var fieldCenterLatitude;
27 var fieldCenterLongitude;
33 // var path = CKEDITOR.plugins.getPath('googlemaps');
34 // CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(path) + 'dialogs/polyline.js');
35 var pluginUrl = CKEDITOR.getUrl(CKEDITOR.plugins.getPath( 'googlemaps' ));
37 var loadSelectionData = function()
39 if (fakeImage){ // マップ選択からの起動の場合
40 var className = fakeImage.$.className;
42 var regExp = /cke_googlemaps(\d+)/;
43 if (regExp.test(className)) mapNumber = RegExp.$1;
44 mapInfo = GoogleMapsHandler.getMap(mapNumber);
45 if (!mapInfo) mapInfo = GoogleMapsHandler.createNew();
46 } else { // マップが選択されていない場合は新規作成
47 mapInfo = GoogleMapsHandler.createNew();
51 dialog.setValueOf('tab_map', 'txtWidth', mapInfo.width);
52 dialog.setValueOf('tab_map', 'txtHeight', mapInfo.height);
53 dialog.setValueOf('tab_map', 'cmbZoom', mapInfo.zoom);
54 dialog.setValueOf('tab_map', 'txtCenterLat', mapInfo.centerLat);
55 dialog.setValueOf('tab_map', 'txtCenterLon', mapInfo.centerLon);
56 // dialog.setValueOf('tab_line', 'txtEncodedPolyline', mapInfo.linePoints);
57 // dialog.setValueOf('tab_line', 'txtEncodedLevels', mapInfo.lineLevels);
60 setPreviewElement(mapInfo.mapType);
63 var markerPoints = mapInfo.markerPoints;
64 for (var i = 0; i < markerPoints.length; i++)
66 var point = new google.maps.LatLng(parseFloat(markerPoints[i].lat), parseFloat(markerPoints[i].lon));
67 addMarkerAtPoint(point, markerPoints[i].text, false);
71 polyline.setMap(mapObj);
72 polyline.decodePolyline(mapInfo.linePoints);
74 var setPreviewElement = function(mapType)
76 mapDiv = document.getElementById("gmapPreview" + editor.id);
79 var allMapTypes = [ google.maps.MapTypeId.ROADMAP,
80 google.maps.MapTypeId.SATELLITE,
81 google.maps.MapTypeId.HYBRID,
82 google.maps.MapTypeId.TERRAIN ];
83 var opts = { mapTypeId:allMapTypes[mapType],
84 mapTypeControlOptions:{ mapTypeIds:allMapTypes } };
85 mapObj = new google.maps.Map(mapDiv, opts);
90 google.maps.event.addListener(mapObj, 'zoom_changed', function(){
91 fieldZoom.value = mapObj.getZoom();
93 google.maps.event.addListener(mapObj, 'center_changed', function(){ // out of memory on IE8
94 var point = mapObj.getCenter();
95 fieldCenterLatitude.value = point.lat().RoundTo(5);
96 fieldCenterLongitude.value = point.lng().RoundTo(5);
98 google.maps.event.addListener(mapObj, 'click', function(e){
100 var selectedTab = CKEDITOR.dialog.getCurrent().definition.dialog._.currentTabId; // 選択中のタブIDを取得
101 switch (selectedTab){
106 if (mode == 'AddMarker') addMarkerAtPoint(point, editor.lang.googlemaps.markerDefaultText || '', true);
109 polyline.createPoint(point.lat(), point.lng(), 3);
110 polyline.createEncodings(false);
115 google.maps.event.addDomListener(mapDiv, 'keydown', function(e){
116 if (!e) e = window.event;
118 var iCode = (e.keyCode || e.charCode);
119 var selectedTab = CKEDITOR.dialog.getCurrent().definition.dialog._.currentTabId; // 選択中のタブIDを取得
127 polyline.deletePoint();
133 var resizeMap = function()
137 mapDiv.style.width = dialog.getValueOf('tab_map', 'txtWidth') + 'px';
138 mapDiv.style.height = dialog.getValueOf('tab_map', 'txtHeight') + 'px';
142 var updatePreview = function()
146 mapObj.setCenter(new google.maps.LatLng(fieldCenterLatitude.value, fieldCenterLongitude.value));
147 mapObj.setZoom(parseInt(fieldZoom.value, 10));
149 var doSearch = function()
151 var address = dialog.getValueOf('tab_search', 'txtAddress');
152 var geocoder = new google.maps.Geocoder();
154 function processPoint(point)
157 dialog.setValueOf('tab_map', 'txtCenterLat', point.lat().RoundTo(5));
158 dialog.setValueOf('tab_map', 'txtCenterLon', point.lng().RoundTo(5));
161 addMarkerAtPoint(point, address);
165 alert(editor.lang.googlemaps.msgNotFound.replace("%s", address));
169 geocoder.geocode({ 'address':address }, function(results, status){
170 if (status == google.maps.GeocoderStatus.OK){
171 processPoint(results[0].geometry.location);
173 alert(editor.lang.googlemaps.msgNotFound.replace("%s", address));
177 var addMarker = function()
179 if (mode == 'AddMarker'){
183 $('#btnAddNewMarker' + editor.id).attr('src', pluginUrl + 'images/AddMarkerDown.png');
184 $('#msgMarkerInstruction' + editor.id).text(editor.lang.googlemaps.msgMarkerInstruction2);
186 mapObj.setOptions({ draggableCursor:'crosshair' });
188 var addMarkerAtPoint = function(point, text, interactive)
190 var marker = createMarker(point, text);
191 marker.setMap(mapObj);
192 markers.push(marker);
195 if (interactive) editMarker(marker);
197 var createMarker = function(point, html)
199 var marker = new google.maps.Marker({ position:point, title:html, draggable:true });
200 google.maps.event.addListener(marker, "click", function(){
205 var finishAddMarker = function()
209 $('#btnAddNewMarker' + editor.id).attr('src', pluginUrl + 'images/AddMarker.png');
210 $('#msgMarkerInstruction' + editor.id).text(editor.lang.googlemaps.msgMarkerInstruction1);
211 mapObj.setOptions({ draggableCursor:'default' });
213 var editMarker = function(marker)
215 var selectedTab = CKEDITOR.dialog.getCurrent().definition.dialog._.currentTabId; // 選択中のタブIDを取得
216 if (selectedTab == 'tab_marker'){ // マーカーコンテンツを編集
217 activeMarker = marker;
220 if (infoWindow) infoWindow.close();
221 infoWindow = new google.maps.InfoWindow({ content:generateEditPopupString(marker.getTitle()) });
222 google.maps.event.addListener(infoWindow, 'domready', function(){ // 吹き出しの入力画面のイベントを設定
223 $("#btnOk").click(function (){
224 updateCurrentMarker();
226 $("#btnCancel").click(function (){
229 $("#btnDeleteMarker").click(function (){
230 deleteCurrentMarker();
233 infoWindow.open(mapObj, marker);
235 if (infoWindow) infoWindow.close();
236 infoWindow = new google.maps.InfoWindow({ content:marker.getTitle() });
237 infoWindow.open(mapObj, marker);
240 var closeInfoWindow = function()
244 if (infoWindow) infoWindow.close();
248 var updateCurrentMarker = function ()
250 if (activeMarker) activeMarker.setTitle($('#txtMarkerText' + editor.id).val().replace(/\n/g, '<br>'));
253 var deleteCurrentMarker = function()
255 for (var j = 0; j < markers.length; j++){
256 if (markers[j] == activeMarker){
257 markers.splice(j, 1);
261 var tmp = activeMarker;
266 var generateEditPopupString = function(text)
268 return '<div><label for="txtMarkerText' + editor.id + '">' + editor.lang.googlemaps.markerText + '</label></div>' +
269 '<div><textarea id="txtMarkerText' + editor.id + '" class="cke_dialog_ui_input_textarea" style="width:300px; height:120px;">' + text.replace(/<br>/g, '\n') + '</textarea></div>' +
270 '<div class="cke_dialog_footer_buttons"><div style="width:50%;display:inline-block;float:left;"><div class="cke_dialog_ui_hbox_child" style="display:inline-block;"><a id="btnDeleteMarker" class="cke_dialog_ui_button"><span class="cke_dialog_ui_button">' + editor.lang.googlemaps.deleteMarker + '</span></a></div></div>' +
271 '<div style="width:40%;display:inline-block;float:right;"><div class="cke_dialog_ui_hbox_first" style="display:inline-block;"><a id="btnOk" class="cke_dialog_ui_button cke_dialog_ui_button_ok"><span class="cke_dialog_ui_button">' + editor.lang.common.ok + '</span></a></div><div class="cke_dialog_ui_hbox_last" style="display:inline-block;">' +
272 '<a id="btnCancel" class="cke_dialog_ui_button cke_dialog_ui_button_cancel"><span class="cke_dialog_ui_button">' + editor.lang.common.cancel + '</span></a></div></div></div>';
274 var commitValue = function(data){
276 if ( !data.info ) data.info = {};
277 data.info[id] = this.getValue();
280 title: editor.lang.googlemaps.title,
283 onLoad: function(){ // 初期処理
284 dialog = this; // 参照取得
288 // var width = dialog.getSize().width;
289 // var height = dialog.getSize().height;
290 // dialog.resize(width, height);
293 /* var off = $('#placeholder_map').position();
294 $('#placeholder_search').css({position:'absolute', top:off.top + 'px',left:off.left + 'px'});
295 $('#placeholder_marker').css({position:'absolute', top:off.top + 'px',left:off.left + 'px'});
296 $('#placeholder_line').css({position:'absolute', top:off.top + 'px',left:off.left + 'px'});
299 dialog.on('selectPage', function(e){
300 switch (e.data.page){
302 $('#gmapPreview' + editor.id).appendTo('#placeholder_map' + editor.id);
305 $('#gmapPreview' + editor.id).appendTo('#placeholder_search' + editor.id);
308 $('#gmapPreview' + editor.id).appendTo('#placeholder_marker' + editor.id);
311 $('#gmapPreview' + editor.id).appendTo('#placeholder_line' + editor.id);
315 if (e.data.page == 'tab_line'){
316 polyline.showLinePoints();
318 polyline.hideLinePoints();
321 if (e.data.page != 'tab_marker') finishAddMarker();
324 $('#btnAddNewMarker' + editor.id).click(function(){
326 }).attr({ title:editor.lang.googlemaps.addMarker, alt:editor.lang.googlemaps.addMarker });
328 /* onFocus: function() {
334 polyline = new Polyline();
336 // 選択されているマップの情報を取り込む
337 var selectedElement = this.getSelectedElement();
338 if (selectedElement){
339 fakeImage = selectedElement;
340 var realElement = editor.restoreRealElement(selectedElement);
347 // A container for our field data
351 this.commitContent(data);
354 mapInfo.width = data.info['txtWidth'];
355 mapInfo.height = data.info['txtHeight'];
356 mapInfo.zoom = data.info['cmbZoom'];
357 mapInfo.centerLat = data.info['txtCenterLat'];
358 mapInfo.centerLon = data.info['txtCenterLon'];
359 var markerPoints = [];
360 for (var i=0; i < markers.length; i++){
361 var point = markers[i].getPosition();
362 markerPoints.push({ lat:point.lat().RoundTo(5), lon:point.lng().RoundTo(5), text:markers[i].getTitle() });
364 mapInfo.markerPoints = markerPoints;
367 mapInfo.linePoints = polyline.encodedPolyline;
368 mapInfo.lineLevels = polyline.encodedLevels;
369 var script = mapInfo.buildScript();
370 // var scriptElement = CKEDITOR.dom.element.createFromHtml(script, editor.document);
371 // var newMapElement = CKEDITOR.dom.element.createFromHtml('<div></div>', editor.document);
372 // newMapElement.append(scriptElement);
373 var newMapElement = CKEDITOR.dom.element.createFromHtml('<div>' + script + '</div>', editor.document); // IE8 not work.
374 var style = 'width:' + mapInfo.width + 'px;height:' + mapInfo.height + 'px;display:none;';
375 newMapElement.setAttributes({
376 'id': 'gmap' + mapInfo.number,
378 'class': 'm3googlemaps'
382 var extraStyles = { 'background-image': 'url(' + mapInfo.generateStaticMap() + ')',
383 'background-position': 'center center',
384 'background-repeat': 'no-repeat',
386 'width': mapInfo.width + 'px',
387 'height': mapInfo.height + 'px'
389 var newFakeImage = editor.createFakeElement(newMapElement, 'cke_googlemaps' + mapInfo.number, 'div', false);
390 newFakeImage.setStyles( extraStyles );
392 if (fakeImage){ // マップ更新の場合
393 newFakeImage.replace( fakeImage );
394 editor.getSelection().selectElement( newFakeImage );
396 editor.insertElement( newFakeImage );
399 onCancel: function(){
404 label: editor.lang.googlemaps.mapTitle,
409 widths: [ '10%', '20%' ], // 項目間幅を調整
415 label: editor.lang.googlemaps.width,
418 validate : function() {
420 value = this.getValue();
421 pass = pass && CKEDITOR.dialog.validate.integer()( value ) && value > 0;
423 alert( "Invalid Width" );
428 onChange: function(){
435 label: editor.lang.googlemaps.height,
438 validate : function() {
440 value = this.getValue();
441 pass = pass && CKEDITOR.dialog.validate.integer()( value ) && value > 0;
443 alert( "Invalid Height" );
448 onChange: function(){
455 label: editor.lang.googlemaps.zoomLevel,
479 fieldZoom = document.getElementById(this.getInputElement().$.id); // 参照を取得
481 onChange: function() {
482 if (mapObj) mapObj.setZoom(parseInt(this.getValue()), 10);
488 widths: [ '50%', '50%' ],
493 // requiredContent: 'img(cke-xyz)', // Random text like 'xyz' will check if all are allowed.
494 label: editor.lang.googlemaps.latitude,
497 fieldCenterLatitude = document.getElementById(this.getInputElement().$.id); // 参照を取得
499 onChange: function() {
500 if (mapObj) mapObj.setCenter(new google.maps.LatLng(this.getValue(), fieldCenterLongitude.value));
506 //requiredContent: 'img[title]',
507 label: editor.lang.googlemaps.longitude,
510 fieldCenterLongitude = document.getElementById(this.getInputElement().$.id); // 参照を取得
512 onChange: function() {
513 if (mapObj) mapObj.setCenter(new google.maps.LatLng(fieldCenterLatitude.value, this.getValue()));
519 html: '<div id="placeholder_map' + editor.id + '"><div id="gmapPreview' + editor.id + '" style="outline:0;" tabIndex="-1"></div></div>'
523 label: editor.lang.googlemaps.searchTitle,
527 widths: [ '5%', '5%' ],
532 label: editor.lang.googlemaps.searchLabel,
534 labelLayout: 'horizontal'
535 /*onLoad: function(){
536 fieldAddress = $('#' + this.getInputElement().$.id); // 参照を取得
542 //style: 'width:50px',
543 label: editor.lang.googlemaps.search,
550 html: '<div id="placeholder_search' + editor.id + '"></div>'
554 label: editor.lang.googlemaps.markerTitle,
558 html: '<img id="btnAddNewMarker' + editor.id + '" src="' + pluginUrl + 'images/AddMarker.png" style="cursor:pointer;" /><div id="msgMarkerInstruction' + editor.id + '" style="display:inline-block;">' + editor.lang.googlemaps.msgMarkerInstruction1 + '</div>'
561 html: '<div id="placeholder_marker' + editor.id + '"></div>'
565 label: editor.lang.googlemaps.lineTitle,
569 html: '<p>' + editor.lang.googlemaps.msgLineInstruction + '</p>'
572 html: '<div id="placeholder_line' + editor.id + '"></div>'