-
Notifications
You must be signed in to change notification settings - Fork 15
/
plugin.js
executable file
·176 lines (149 loc) · 7.43 KB
/
plugin.js
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/**
* @fileOverview Leaflet Map Widget.
*/
(function() {
/* Flow of Control for CKEditor and Widget components:
Loading the page:
CKEditor init()
Widget upcast()
Creating new widgets:
Widget init()
Widget data()
Dialog select element's items()
Dialog onShow()
Dialog setup()
Dialog commit()
When editing existing widgets:
Dialog onShow()
Dialog setup()
Dialog commit()
Widget data()
When saving page or clicking the CKEditor's Source button:
Widget downcast()
*/
// Add a new CKEditor plugin. Note that widgets are subclass of plugins.
CKEDITOR.plugins.add('leaflet', {
// Declare dependencies.
requires: 'widget',
// Declare the supported languages.
lang: 'de,en,eu,ru',
init: function(editor) {
var config = editor.config;
// Dummy global method for quick workaround of asynchronous document.write()
// issue of Google APIs with respect to CKEditor.
// See the Google APIs URL below for the query string usage of this dummy().
// Using this hack, the document.write(...) requirement of Google APIs
// will be replaced by the more 'gentle' combination of
// document.createElement(...) and document.body.appendChild(...).
window.dummy = function() {
// Do nothing.
}
// Check if jQuery is already loaded to avoid redundancy and overriding
// existing 3rd-party jQuery plugins' bindings to jQuery prototype.
if (typeof jQuery == 'undefined') {
// This is asynchronous loading.
// See also CKEDITOR.scriptLoader.queue.
CKEDITOR.scriptLoader.load('//code.jquery.com/jquery-1.12.4.min.js');
}
// Access the current translation file.
var pluginTranslation = editor.lang.leaflet;
// Declare a new Dialog for interactive selection of
// map parameters. It's still not bound to any widget at this moment.
CKEDITOR.dialog.add('leaflet', this.path + 'dialogs/leaflet.js');
// For reusability, declare a global variable pointing to the map script path
// that will build and render the map.
// In JavaScript, relative path must include the leading slash.
mapParserPath = CKEDITOR.getUrl(this.path + 'scripts/mapParser.html');
// Declare a new widget.
editor.widgets.add('leaflet', {
// Bind the widget to the Dialog command.
dialog: 'leaflet',
// Declare the elements to be upcasted back.
// Otherwise, the widget's code will be ignored.
// Basically, we will allow all divs with 'leaflet_div' class,
// including their alignment classes, and all iframes with
// 'leaflet_iframe' class, and then include
// all their attributes.
// Read more about the Advanced Content Filter here:
// * http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter
// * http://docs.ckeditor.com/#!/guide/plugin_sdk_integration_with_acf
allowedContent: 'div(!leaflet_div,align-left,align-right,align-center,responsive-map)[*];'
+ 'iframe(!leaflet_iframe,responsive-map-iframe)[*];',
// Declare the widget template/structure, containing the
// important elements/attributes. This is a required property of widget.
template:
'<div id="" class="leaflet_div" data-lat="" data-lon="" data-width="" data-height="" ' +
'data-zoom="" data-popup-text="" data-tile="" data-minimap="" data-alignment="" data-responsive=""></div>',
// This will be executed when going from the View Mode to Source Mode.
// This is usually used as the function to convert the widget to a
// dummy, simpler, or equivalent textual representation.
downcast: function(element) {
// Get the id of the div element.
var divId = element.attributes["id"];
// Get the numeric part of divId: leaflet_div-1399121271748.
// We'll use that number for quick fetching of target iframe.
var iframeId = "leaflet_iframe-" + divId.substring(12);
// The current user might have changed the map's zoom level
// via mouse events/zoom bar. The marker might have been
// dragged also which means its lat/lon had changed.
var mapContainer = editor.document.$.getElementById(iframeId).contentDocument.getElementById("map_container");
// Get the current map states.
var currentZoom = mapContainer.getAttribute("data-zoom");
var currentLat = mapContainer.getAttribute("data-lat");
var currentLon = mapContainer.getAttribute("data-lon");
// Update the saved corresponding values in data attributes.
element.attributes["data-zoom"] = currentZoom;
element.attributes["data-lat"] = currentLat;
element.attributes["data-lon"] = currentLon;
// Fetch the other data attributes needed for
// updating the full path of the map.
var width = element.attributes["data-width"];
var height = element.attributes["data-height"];
var popUpText = element.attributes["data-popup-text"];
var tile = element.attributes["data-tile"];
var minimap = element.attributes["data-minimap"];
var responsive = element.attributes["data-responsive"];
// Build the updated full path to the map renderer.
var mapParserPathFull = mapParserPath + "?lat=" + currentLat + "&lon=" + currentLon + "&width=" + width + "&height=" + height + "&zoom=" + currentZoom + "&text=" + popUpText + "&tile=" + tile + "&minimap=" + minimap + "&responsive=" + responsive;
// Update also the iframe's 'src' attributes.
// Updating 'data-cke-saved-src' is also required for
// internal use of CKEditor.
element.children[0].attributes["src"] = mapParserPathFull;
element.children[0].attributes["data-cke-saved-src"] = mapParserPathFull;
// Return the DOM's textual representation.
return element;
},
// Required property also for widgets, used when switching
// from CKEditor's Source Mode to View Mode.
// The reverse of downcast() method.
upcast: function(element) {
// If we encounter a div with a class of 'leaflet_div',
// it means that it's a widget and we need to convert it properly
// to its original structure.
// Basically, it says to CKEditor which div is a valid widget.
if (element.name == 'div' && element.hasClass('leaflet_div')) {
return element;
}
},
});
// Add the widget button in the toolbar and bind the widget command,
// which is also bound to the Dialog command.
// Apparently, this is required just like their plugin counterpart.
editor.ui.addButton('leaflet', {
label : pluginTranslation.buttonLabel,
command : 'leaflet',
icon : this.path + 'icons/leaflet.png',
toolbar: 'insert,1'
});
// Append the widget's styles when in the CKEditor edit page,
// added for better user experience.
// Assign or append the widget's styles depending on the existing setup.
if (typeof config.contentsCss == 'object') {
config.contentsCss.push(CKEDITOR.getUrl(this.path + 'css/contents.css'));
}
else {
config.contentsCss = [config.contentsCss, CKEDITOR.getUrl(this.path + 'css/contents.css')];
}
},
});
})();