foliage 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +9 -0
- data/app/assets/images/.keep +0 -0
- data/app/assets/images/map/marker/icon-2x.png +0 -0
- data/app/assets/images/map/marker/icon.png +0 -0
- data/app/assets/images/map/marker/icon.svg +67 -0
- data/app/assets/images/map/marker/shadow.png +0 -0
- data/app/assets/javascripts/core_ext.js.coffee +61 -0
- data/app/assets/javascripts/foliage.js.coffee +23 -0
- data/app/assets/javascripts/foliage/band.js.coffee +99 -0
- data/app/assets/javascripts/foliage/bubbles.js.coffee +77 -0
- data/app/assets/javascripts/foliage/categories.js.coffee +70 -0
- data/app/assets/javascripts/foliage/choropleth.js.coffee +51 -0
- data/app/assets/javascripts/foliage/color.js.coffee +39 -0
- data/app/assets/javascripts/foliage/gradient.js.coffee +72 -0
- data/app/assets/javascripts/foliage/heatmap.js.coffee +49 -0
- data/app/assets/javascripts/foliage/leaf.js.coffee +422 -0
- data/app/assets/javascripts/foliage/path.js.coffee +76 -0
- data/app/assets/javascripts/foliage/paths.js.coffee +131 -0
- data/app/assets/javascripts/foliage/point_group.js.coffee +83 -0
- data/app/assets/javascripts/foliage/points.js.coffee +79 -0
- data/app/assets/javascripts/foliage/simple.js.coffee +35 -0
- data/app/assets/javascripts/leaflet/geographic_util.js.coffee +23 -0
- data/app/assets/javascripts/leaflet/ghost_label.js.coffee +100 -0
- data/app/assets/javascripts/leaflet/ghost_label_cluster.js.coffee +192 -0
- data/app/assets/javascripts/leaflet/layers_scheduler.js.coffee +57 -0
- data/app/assets/javascripts/leaflet/reactive_measure.js.coffee +414 -0
- data/app/assets/stylesheets/all.scss +16 -0
- data/app/assets/stylesheets/application.css +15 -0
- data/app/assets/stylesheets/compass/reset.scss +3 -0
- data/app/assets/stylesheets/compass/reset/utilities.scss +142 -0
- data/app/assets/stylesheets/leaflet.scss +1093 -0
- data/app/assets/stylesheets/leaflet/label.scss +40 -0
- data/app/assets/stylesheets/leaflet/tooltip.scss +42 -0
- data/app/assets/stylesheets/mixins.scss +131 -0
- data/app/assets/stylesheets/reset.scss +89 -0
- data/app/assets/stylesheets/variables.scss +47 -0
- data/app/helpers/foliage_helper.rb +23 -0
- data/lib/foliage.rb +9 -0
- data/lib/foliage/leaf.rb +235 -0
- data/lib/foliage/rails.rb +2 -0
- data/lib/foliage/rails/engine.rb +7 -0
- data/lib/foliage/rails/integration.rb +8 -0
- data/lib/foliage/version.rb +3 -0
- data/vendor/assets/javascripts/.keep +0 -0
- data/vendor/assets/javascripts/autosize.js +211 -0
- data/vendor/assets/javascripts/geographiclib.js +3074 -0
- data/vendor/assets/javascripts/leaflet.js.erb +9175 -0
- data/vendor/assets/javascripts/leaflet/draw.js +3573 -0
- data/vendor/assets/javascripts/leaflet/easy-button.js +366 -0
- data/vendor/assets/javascripts/leaflet/fullscreen.js +162 -0
- data/vendor/assets/javascripts/leaflet/heatmap.js +142 -0
- data/vendor/assets/javascripts/leaflet/label.js +545 -0
- data/vendor/assets/javascripts/leaflet/measure.js +6966 -0
- data/vendor/assets/javascripts/leaflet/modal.js +364 -0
- data/vendor/assets/javascripts/leaflet/providers.js +479 -0
- data/vendor/assets/javascripts/rbush.js +621 -0
- data/vendor/assets/stylesheets/.keep +0 -0
- data/vendor/assets/stylesheets/bootstrap/mixins.scss +55 -0
- data/vendor/assets/stylesheets/bootstrap/variables.scss +10 -0
- data/vendor/assets/stylesheets/leaflet.scss +479 -0
- data/vendor/assets/stylesheets/leaflet/draw.scss +282 -0
- data/vendor/assets/stylesheets/leaflet/easy-button.scss +56 -0
- data/vendor/assets/stylesheets/leaflet/fullscreen.scss +2 -0
- data/vendor/assets/stylesheets/leaflet/measure.scss +168 -0
- data/vendor/assets/stylesheets/leaflet/modal.scss +85 -0
- metadata +171 -0
@@ -0,0 +1,366 @@
|
|
1
|
+
(function(){
|
2
|
+
|
3
|
+
// This is for grouping buttons into a bar
|
4
|
+
// takes an array of `L.easyButton`s and
|
5
|
+
// then the usual `.addTo(map)`
|
6
|
+
L.Control.EasyBar = L.Control.extend({
|
7
|
+
|
8
|
+
options: {
|
9
|
+
position: 'topleft', // part of leaflet's defaults
|
10
|
+
id: null, // an id to tag the Bar with
|
11
|
+
leafletClasses: true // use leaflet classes?
|
12
|
+
},
|
13
|
+
|
14
|
+
|
15
|
+
initialize: function(buttons, options){
|
16
|
+
|
17
|
+
if(options){
|
18
|
+
L.Util.setOptions( this, options );
|
19
|
+
}
|
20
|
+
|
21
|
+
this._buildContainer();
|
22
|
+
this._buttons = [];
|
23
|
+
|
24
|
+
for(var i = 0; i < buttons.length; i++){
|
25
|
+
buttons[i]._bar = this;
|
26
|
+
buttons[i]._container = buttons[i].button;
|
27
|
+
this._buttons.push(buttons[i]);
|
28
|
+
this.container.appendChild(buttons[i].button);
|
29
|
+
}
|
30
|
+
|
31
|
+
},
|
32
|
+
|
33
|
+
|
34
|
+
_buildContainer: function(){
|
35
|
+
this._container = this.container = L.DomUtil.create('div', '');
|
36
|
+
this.options.leafletClasses && L.DomUtil.addClass(this.container, 'leaflet-bar easy-button-container leaflet-control');
|
37
|
+
this.options.id && (this.container.id = this.options.id);
|
38
|
+
},
|
39
|
+
|
40
|
+
|
41
|
+
enable: function(){
|
42
|
+
L.DomUtil.addClass(this.container, 'enabled');
|
43
|
+
L.DomUtil.removeClass(this.container, 'disabled');
|
44
|
+
this.container.setAttribute('aria-hidden', 'false');
|
45
|
+
return this;
|
46
|
+
},
|
47
|
+
|
48
|
+
|
49
|
+
disable: function(){
|
50
|
+
L.DomUtil.addClass(this.container, 'disabled');
|
51
|
+
L.DomUtil.removeClass(this.container, 'enabled');
|
52
|
+
this.container.setAttribute('aria-hidden', 'true');
|
53
|
+
return this;
|
54
|
+
},
|
55
|
+
|
56
|
+
|
57
|
+
onAdd: function () {
|
58
|
+
return this.container;
|
59
|
+
},
|
60
|
+
|
61
|
+
addTo: function (map) {
|
62
|
+
this._map = map;
|
63
|
+
|
64
|
+
for(var i = 0; i < this._buttons.length; i++){
|
65
|
+
this._buttons[i]._map = map;
|
66
|
+
}
|
67
|
+
|
68
|
+
var container = this._container = this.onAdd(map),
|
69
|
+
pos = this.getPosition(),
|
70
|
+
corner = map._controlCorners[pos];
|
71
|
+
|
72
|
+
L.DomUtil.addClass(container, 'leaflet-control');
|
73
|
+
|
74
|
+
if (pos.indexOf('bottom') !== -1) {
|
75
|
+
corner.insertBefore(container, corner.firstChild);
|
76
|
+
} else {
|
77
|
+
corner.appendChild(container);
|
78
|
+
}
|
79
|
+
|
80
|
+
return this;
|
81
|
+
}
|
82
|
+
|
83
|
+
});
|
84
|
+
|
85
|
+
L.easyBar = function(){
|
86
|
+
var args = [L.Control.EasyBar];
|
87
|
+
for(var i = 0; i < arguments.length; i++){
|
88
|
+
args.push( arguments[i] );
|
89
|
+
}
|
90
|
+
return new (Function.prototype.bind.apply(L.Control.EasyBar, args));
|
91
|
+
};
|
92
|
+
|
93
|
+
// L.EasyButton is the actual buttons
|
94
|
+
// can be called without being grouped into a bar
|
95
|
+
L.Control.EasyButton = L.Control.extend({
|
96
|
+
|
97
|
+
options: {
|
98
|
+
position: 'topleft', // part of leaflet's defaults
|
99
|
+
|
100
|
+
id: null, // an id to tag the button with
|
101
|
+
|
102
|
+
type: 'replace', // [(replace|animate)]
|
103
|
+
// replace swaps out elements
|
104
|
+
// animate changes classes with all elements inserted
|
105
|
+
|
106
|
+
states: [], // state names look like this
|
107
|
+
// {
|
108
|
+
// stateName: 'untracked',
|
109
|
+
// onClick: function(){ handle_nav_manually(); };
|
110
|
+
// title: 'click to make inactive',
|
111
|
+
// icon: 'fa-circle', // wrapped with <a>
|
112
|
+
// }
|
113
|
+
|
114
|
+
leafletClasses: true // use leaflet styles for the button
|
115
|
+
},
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
initialize: function(icon, onClick, title){
|
120
|
+
|
121
|
+
// clear the states manually
|
122
|
+
this.options.states = [];
|
123
|
+
|
124
|
+
// storage between state functions
|
125
|
+
this.storage = {};
|
126
|
+
|
127
|
+
// is the last item an object?
|
128
|
+
if( typeof arguments[arguments.length-1] === 'object' ){
|
129
|
+
|
130
|
+
// if so, it should be the options
|
131
|
+
L.Util.setOptions( this, arguments[arguments.length-1] );
|
132
|
+
}
|
133
|
+
|
134
|
+
// if there aren't any states in options
|
135
|
+
// use the early params
|
136
|
+
if( this.options.states.length === 0 &&
|
137
|
+
typeof icon === 'string' &&
|
138
|
+
typeof onClick === 'function'){
|
139
|
+
|
140
|
+
// turn the options object into a state
|
141
|
+
this.options.states.push({
|
142
|
+
icon: icon,
|
143
|
+
onClick: onClick,
|
144
|
+
title: typeof title === 'string' ? title : ''
|
145
|
+
});
|
146
|
+
}
|
147
|
+
|
148
|
+
// curate and move user's states into
|
149
|
+
// the _states for internal use
|
150
|
+
this._states = [];
|
151
|
+
|
152
|
+
for(var i = 0; i < this.options.states.length; i++){
|
153
|
+
this._states.push( new State(this.options.states[i], this) );
|
154
|
+
}
|
155
|
+
|
156
|
+
this._buildButton();
|
157
|
+
|
158
|
+
this._activateState(this._states[0]);
|
159
|
+
|
160
|
+
},
|
161
|
+
|
162
|
+
_buildButton: function(){
|
163
|
+
|
164
|
+
this.button = L.DomUtil.create('button', '');
|
165
|
+
|
166
|
+
if (this.options.id ){
|
167
|
+
this.button.id = this.options.id;
|
168
|
+
}
|
169
|
+
|
170
|
+
if (this.options.leafletClasses){
|
171
|
+
L.DomUtil.addClass(this.button, 'easy-button-button leaflet-bar-part');
|
172
|
+
}
|
173
|
+
|
174
|
+
// don't let double clicks get to the map
|
175
|
+
L.DomEvent.addListener(this.button, 'dblclick', L.DomEvent.stop);
|
176
|
+
|
177
|
+
// take care of normal clicks
|
178
|
+
L.DomEvent.addListener(this.button,'click', function(e){
|
179
|
+
L.DomEvent.stop(e);
|
180
|
+
this._currentState.onClick(this, this._map ? this._map : null );
|
181
|
+
this._map.getContainer().focus();
|
182
|
+
}, this);
|
183
|
+
|
184
|
+
// prep the contents of the control
|
185
|
+
if(this.options.type == 'replace'){
|
186
|
+
this.button.appendChild(this._currentState.icon);
|
187
|
+
} else {
|
188
|
+
for(var i=0;i<this._states.length;i++){
|
189
|
+
this.button.appendChild(this._states[i].icon);
|
190
|
+
}
|
191
|
+
}
|
192
|
+
},
|
193
|
+
|
194
|
+
|
195
|
+
_currentState: {
|
196
|
+
// placeholder content
|
197
|
+
stateName: 'unnamed',
|
198
|
+
icon: (function(){ return document.createElement('span'); })()
|
199
|
+
},
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
_states: null, // populated on init
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
state: function(newState){
|
208
|
+
|
209
|
+
// activate by name
|
210
|
+
if(typeof newState == 'string'){
|
211
|
+
|
212
|
+
this._activateStateNamed(newState);
|
213
|
+
|
214
|
+
// activate by index
|
215
|
+
} else if (typeof newState == 'number'){
|
216
|
+
|
217
|
+
this._activateState(this._states[newState]);
|
218
|
+
}
|
219
|
+
|
220
|
+
return this;
|
221
|
+
},
|
222
|
+
|
223
|
+
|
224
|
+
_activateStateNamed: function(stateName){
|
225
|
+
for(var i = 0; i < this._states.length; i++){
|
226
|
+
if( this._states[i].stateName == stateName ){
|
227
|
+
this._activateState( this._states[i] );
|
228
|
+
}
|
229
|
+
}
|
230
|
+
},
|
231
|
+
|
232
|
+
_activateState: function(newState){
|
233
|
+
|
234
|
+
if( newState === this._currentState ){
|
235
|
+
|
236
|
+
// don't touch the dom if it'll just be the same after
|
237
|
+
return;
|
238
|
+
|
239
|
+
} else {
|
240
|
+
|
241
|
+
// swap out elements... if you're into that kind of thing
|
242
|
+
if( this.options.type == 'replace' ){
|
243
|
+
this.button.appendChild(newState.icon);
|
244
|
+
this.button.removeChild(this._currentState.icon);
|
245
|
+
}
|
246
|
+
|
247
|
+
if( newState.title ){
|
248
|
+
this.button.title = newState.title;
|
249
|
+
} else {
|
250
|
+
this.button.removeAttribute('title');
|
251
|
+
}
|
252
|
+
|
253
|
+
// update classes for animations
|
254
|
+
for(var i=0;i<this._states.length;i++){
|
255
|
+
L.DomUtil.removeClass(this._states[i].icon, this._currentState.stateName + '-active');
|
256
|
+
L.DomUtil.addClass(this._states[i].icon, newState.stateName + '-active');
|
257
|
+
}
|
258
|
+
|
259
|
+
// update classes for animations
|
260
|
+
L.DomUtil.removeClass(this.button, this._currentState.stateName + '-active');
|
261
|
+
L.DomUtil.addClass(this.button, newState.stateName + '-active');
|
262
|
+
|
263
|
+
// update the record
|
264
|
+
this._currentState = newState;
|
265
|
+
|
266
|
+
}
|
267
|
+
},
|
268
|
+
|
269
|
+
|
270
|
+
|
271
|
+
enable: function(){
|
272
|
+
L.DomUtil.addClass(this.button, 'enabled');
|
273
|
+
L.DomUtil.removeClass(this.button, 'disabled');
|
274
|
+
this.button.setAttribute('aria-hidden', 'false');
|
275
|
+
return this;
|
276
|
+
},
|
277
|
+
|
278
|
+
|
279
|
+
|
280
|
+
disable: function(){
|
281
|
+
L.DomUtil.addClass(this.button, 'disabled');
|
282
|
+
L.DomUtil.removeClass(this.button, 'enabled');
|
283
|
+
this.button.setAttribute('aria-hidden', 'true');
|
284
|
+
return this;
|
285
|
+
},
|
286
|
+
|
287
|
+
|
288
|
+
removeFrom: function (map) {
|
289
|
+
|
290
|
+
this._container.parentNode.removeChild(this._container);
|
291
|
+
this._map = null;
|
292
|
+
|
293
|
+
return this;
|
294
|
+
},
|
295
|
+
|
296
|
+
onAdd: function(){
|
297
|
+
var containerObj = L.easyBar([this], {
|
298
|
+
position: this.options.position,
|
299
|
+
leafletClasses: this.options.leafletClasses
|
300
|
+
});
|
301
|
+
this._container = containerObj.container;
|
302
|
+
return this._container;
|
303
|
+
}
|
304
|
+
|
305
|
+
|
306
|
+
});
|
307
|
+
|
308
|
+
L.easyButton = function(/* args will pass automatically */){
|
309
|
+
var args = Array.prototype.concat.apply([L.Control.EasyButton],arguments)
|
310
|
+
return new (Function.prototype.bind.apply(L.Control.EasyButton, args));
|
311
|
+
};
|
312
|
+
|
313
|
+
/*************************
|
314
|
+
*
|
315
|
+
* util functions
|
316
|
+
*
|
317
|
+
*************************/
|
318
|
+
|
319
|
+
// constructor for states so only curated
|
320
|
+
// states end up getting called
|
321
|
+
function State(template, easyButton){
|
322
|
+
|
323
|
+
this.title = template.title;
|
324
|
+
this.stateName = template.stateName ? template.stateName : 'unnamed-state';
|
325
|
+
|
326
|
+
// build the wrapper
|
327
|
+
this.icon = L.DomUtil.create('span', '');
|
328
|
+
|
329
|
+
L.DomUtil.addClass(this.icon, 'button-state state-' + this.stateName.trim());
|
330
|
+
this.icon.innerHTML = buildIcon(template.icon);
|
331
|
+
this.onClick = L.Util.bind(template.onClick?template.onClick:function(){}, easyButton);
|
332
|
+
}
|
333
|
+
|
334
|
+
function buildIcon(ambiguousIconString) {
|
335
|
+
|
336
|
+
var tmpIcon;
|
337
|
+
|
338
|
+
// does this look like html? (i.e. not a class)
|
339
|
+
if( ambiguousIconString.match(/[&;=<>"']/) ){
|
340
|
+
|
341
|
+
// if so, the user should have put in html
|
342
|
+
// so move forward as such
|
343
|
+
tmpIcon = ambiguousIconString;
|
344
|
+
|
345
|
+
// then it wasn't html, so
|
346
|
+
// it's a class list, figure out what kind
|
347
|
+
} else {
|
348
|
+
ambiguousIconString = ambiguousIconString.trim();
|
349
|
+
tmpIcon = L.DomUtil.create('span', '');
|
350
|
+
|
351
|
+
if( ambiguousIconString.indexOf('fa-') === 0 ){
|
352
|
+
L.DomUtil.addClass(tmpIcon, 'fa ' + ambiguousIconString)
|
353
|
+
} else if ( ambiguousIconString.indexOf('glyphicon-') === 0 ) {
|
354
|
+
L.DomUtil.addClass(tmpIcon, 'glyphicon ' + ambiguousIconString)
|
355
|
+
} else {
|
356
|
+
L.DomUtil.addClass(tmpIcon, /*rollwithit*/ ambiguousIconString)
|
357
|
+
}
|
358
|
+
|
359
|
+
// make this a string so that it's easy to set innerHTML below
|
360
|
+
tmpIcon = tmpIcon.outerHTML;
|
361
|
+
}
|
362
|
+
|
363
|
+
return tmpIcon;
|
364
|
+
}
|
365
|
+
|
366
|
+
})();
|
@@ -0,0 +1,162 @@
|
|
1
|
+
(function() {
|
2
|
+
|
3
|
+
L.Control.FullScreen = L.Control.extend({
|
4
|
+
options: {
|
5
|
+
position: 'topleft',
|
6
|
+
title: 'Full Screen',
|
7
|
+
forceSeparateButton: false
|
8
|
+
},
|
9
|
+
|
10
|
+
onAdd: function (map) {
|
11
|
+
var className = 'leaflet-control-zoom-fullscreen', container;
|
12
|
+
|
13
|
+
if (map.zoomControl && !this.options.forceSeparateButton) {
|
14
|
+
container = map.zoomControl._container;
|
15
|
+
} else {
|
16
|
+
container = L.DomUtil.create('div', 'leaflet-bar');
|
17
|
+
}
|
18
|
+
|
19
|
+
this._createButton(this.options.title, className, container, this.toogleFullScreen, map);
|
20
|
+
|
21
|
+
return container;
|
22
|
+
},
|
23
|
+
|
24
|
+
_createButton: function (title, className, container, fn, context) {
|
25
|
+
var link = L.DomUtil.create('a', className, container);
|
26
|
+
link.href = '#';
|
27
|
+
link.title = title;
|
28
|
+
|
29
|
+
L.DomEvent
|
30
|
+
.addListener(link, 'click', L.DomEvent.stopPropagation)
|
31
|
+
.addListener(link, 'click', L.DomEvent.preventDefault)
|
32
|
+
.addListener(link, 'click', fn, context);
|
33
|
+
|
34
|
+
L.DomEvent
|
35
|
+
.addListener(container, fullScreenApi.fullScreenEventName, L.DomEvent.stopPropagation)
|
36
|
+
.addListener(container, fullScreenApi.fullScreenEventName, L.DomEvent.preventDefault)
|
37
|
+
.addListener(container, fullScreenApi.fullScreenEventName, this._handleEscKey, context);
|
38
|
+
|
39
|
+
L.DomEvent
|
40
|
+
.addListener(document, fullScreenApi.fullScreenEventName, L.DomEvent.stopPropagation)
|
41
|
+
.addListener(document, fullScreenApi.fullScreenEventName, L.DomEvent.preventDefault)
|
42
|
+
.addListener(document, fullScreenApi.fullScreenEventName, this._handleEscKey, context);
|
43
|
+
|
44
|
+
return link;
|
45
|
+
},
|
46
|
+
|
47
|
+
toogleFullScreen: function () {
|
48
|
+
this._exitFired = false;
|
49
|
+
var container = this._container;
|
50
|
+
if (this._isFullscreen) {
|
51
|
+
if (fullScreenApi.supportsFullScreen) {
|
52
|
+
fullScreenApi.cancelFullScreen(container);
|
53
|
+
} else {
|
54
|
+
L.DomUtil.removeClass(container, 'leaflet-pseudo-fullscreen');
|
55
|
+
}
|
56
|
+
this.invalidateSize();
|
57
|
+
this.fire('exitFullscreen');
|
58
|
+
this._exitFired = true;
|
59
|
+
this._isFullscreen = false;
|
60
|
+
}
|
61
|
+
else {
|
62
|
+
if (fullScreenApi.supportsFullScreen) {
|
63
|
+
fullScreenApi.requestFullScreen(container);
|
64
|
+
} else {
|
65
|
+
L.DomUtil.addClass(container, 'leaflet-pseudo-fullscreen');
|
66
|
+
}
|
67
|
+
this.invalidateSize();
|
68
|
+
this.fire('enterFullscreen');
|
69
|
+
this._isFullscreen = true;
|
70
|
+
}
|
71
|
+
},
|
72
|
+
|
73
|
+
_handleEscKey: function () {
|
74
|
+
if (!fullScreenApi.isFullScreen(this) && !this._exitFired) {
|
75
|
+
this.fire('exitFullscreen');
|
76
|
+
this._exitFired = true;
|
77
|
+
this._isFullscreen = false;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
});
|
81
|
+
|
82
|
+
L.Map.addInitHook(function () {
|
83
|
+
if (this.options.fullscreenControl) {
|
84
|
+
this.fullscreenControl = L.control.fullscreen(this.options.fullscreenControlOptions);
|
85
|
+
this.addControl(this.fullscreenControl);
|
86
|
+
}
|
87
|
+
});
|
88
|
+
|
89
|
+
L.control.fullscreen = function (options) {
|
90
|
+
return new L.Control.FullScreen(options);
|
91
|
+
};
|
92
|
+
|
93
|
+
/*
|
94
|
+
Native FullScreen JavaScript API
|
95
|
+
-------------
|
96
|
+
Assumes Mozilla naming conventions instead of W3C for now
|
97
|
+
|
98
|
+
source : http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/
|
99
|
+
|
100
|
+
*/
|
101
|
+
|
102
|
+
var
|
103
|
+
fullScreenApi = {
|
104
|
+
supportsFullScreen: false,
|
105
|
+
isFullScreen: function() { return false; },
|
106
|
+
requestFullScreen: function() {},
|
107
|
+
cancelFullScreen: function() {},
|
108
|
+
fullScreenEventName: '',
|
109
|
+
prefix: ''
|
110
|
+
},
|
111
|
+
browserPrefixes = 'webkit moz o ms khtml'.split(' ');
|
112
|
+
|
113
|
+
// check for native support
|
114
|
+
if (typeof document.exitFullscreen != 'undefined') {
|
115
|
+
fullScreenApi.supportsFullScreen = true;
|
116
|
+
} else {
|
117
|
+
// check for fullscreen support by vendor prefix
|
118
|
+
for (var i = 0, il = browserPrefixes.length; i < il; i++ ) {
|
119
|
+
fullScreenApi.prefix = browserPrefixes[i];
|
120
|
+
if (typeof document[fullScreenApi.prefix + 'CancelFullScreen' ] != 'undefined' ) {
|
121
|
+
fullScreenApi.supportsFullScreen = true;
|
122
|
+
break;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
// update methods to do something useful
|
128
|
+
if (fullScreenApi.supportsFullScreen) {
|
129
|
+
fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
|
130
|
+
fullScreenApi.isFullScreen = function() {
|
131
|
+
switch (this.prefix) {
|
132
|
+
case '':
|
133
|
+
return document.fullScreen;
|
134
|
+
case 'webkit':
|
135
|
+
return document.webkitIsFullScreen;
|
136
|
+
default:
|
137
|
+
return document[this.prefix + 'FullScreen'];
|
138
|
+
}
|
139
|
+
}
|
140
|
+
fullScreenApi.requestFullScreen = function(el) {
|
141
|
+
return (this.prefix === '') ? el.requestFullscreen() : el[this.prefix + 'RequestFullScreen']();
|
142
|
+
}
|
143
|
+
fullScreenApi.cancelFullScreen = function(el) {
|
144
|
+
return (this.prefix === '') ? document.exitFullscreen() : document[this.prefix + 'CancelFullScreen']();
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
// jQuery plugin
|
149
|
+
if (typeof jQuery != 'undefined') {
|
150
|
+
jQuery.fn.requestFullScreen = function() {
|
151
|
+
return this.each(function() {
|
152
|
+
var el = jQuery(this);
|
153
|
+
if (fullScreenApi.supportsFullScreen) {
|
154
|
+
fullScreenApi.requestFullScreen(el);
|
155
|
+
}
|
156
|
+
});
|
157
|
+
};
|
158
|
+
}
|
159
|
+
|
160
|
+
// export api
|
161
|
+
window.fullScreenApi = fullScreenApi;
|
162
|
+
})();
|