PageSourceSearch

https://firesmoke.ca/static/js/fwf-easy-button.js

js firesmoke.ca collected 2026-10-03 21:22:16 UTC 11,231 bytes, 376 lines download raw bytes

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        tagName:          'button',
116      },
117
118
119
120      initialize: function(icon, onClick, title, id){
121
122        // clear the states manually
123        this.options.states = [];
124
125        // add id to options
126        if(id != null){
127          this.options.id = id;
128        }
129
130        // storage between state functions
131        this.storage = {};
132
133        // is the last item an object?
134        if( typeof arguments[arguments.length-1] === 'object' ){
135
136          // if so, it should be the options
137          L.Util.setOptions( this, arguments[arguments.length-1] );
138        }
139
140        // if there aren't any states in options
141        // use the early params
142        if( this.options.states.length === 0 &&
143            typeof icon  === 'string' &&
144            typeof onClick === 'function'){
145
146          // turn the options object into a state
147          this.options.states.push({
148            icon: icon,
149            onClick: onClick,
150            title: typeof title === 'string' ? title : ''
151          });
152        }
153
154        // curate and move user's states into
155        // the _states for internal use
156        this._states = [];
157
158        for(var i = 0; i < this.options.states.length; i++){
159          this._states.push( new State(this.options.states[i], this) );
160        }
161
162        this._buildButton();
163
164        this._activateState(this._states[0]);
165
166      },
167
168      _buildButton: function(){
169
170        this.button = L.DomUtil.create(this.options.tagName, '');
171
172        if (this.options.tagName === 'button') {
173            this.button.setAttribute('type', 'button');
174        }
175
176        if (this.options.id ){
177          this.button.id = this.options.id;
178        }
179
180        if (this.options.leafletClasses){
181          L.DomUtil.addClass(this.button, 'easy-button-button leaflet-bar-part leaflet-interactive');
182        }
183
184        // don't let double clicks and mousedown get to the map
185        L.DomEvent.addListener(this.button, 'dblclick', L.DomEvent.stop);
186        L.DomEvent.addListener(this.button, 'mousedown', L.DomEvent.stop);
187        L.DomEvent.addListener(this.button, 'mouseup', L.DomEvent.stop);
188
189        // take care of normal clicks
190        L.DomEvent.addListener(this.button,'click', function(e){
191          L.DomEvent.stop(e);
192          this._currentState.onClick(this, this._map ? this._map : null );
193          this._map && this._map.getContainer().focus();
194        }, this);
195
196        // prep the contents of the control
197        if(this.options.type == 'replace'){
198          this.button.appendChild(this._currentState.icon);
199        } else {
200          for(var i=0;i<this._states.length;i++){
201            this.button.appendChild(this._states[i].icon);
202          }
203        }
204      },
205
206
207      _currentState: {
208        // placeholder content
209        stateName: 'unnamed',
210        icon: (function(){ return document.createElement('span'); })()
211      },
212
213
214
215      _states: null, // populated on init
216
217
218
219      state: function(newState){
220
221        // when called with no args, it's a getter
222        if (arguments.length === 0) {
223          return this._currentState.stateName;
224        }
225
226        // activate by name
227        if(typeof newState == 'string'){
228
229          this._activateStateNamed(newState);
230
231        // activate by index
232        } else if (typeof newState == 'number'){
233
234          this._activateState(this._states[newState]);
235        }
236
237        return this;
238      },
239
240
241      _activateStateNamed: function(stateName){
242        for(var i = 0; i < this._states.length; i++){
243          if( this._states[i].stateName == stateName ){
244            this._activateState( this._states[i] );
245          }
246        }
247      },
248
249      _activateState: function(newState){
250
251        if( newState === this._currentState ){
252
253          // don't touch the dom if it'll just be the same after
254          return;
255
256        } else {
257
258          // swap out elements... if you're into that kind of thing
259          if( this.options.type == 'replace' ){
260            this.button.appendChild(newState.icon);
261            this.button.removeChild(this._currentState.icon);
262          }
263
264          if( newState.title ){
265            this.button.title = newState.title;
266          } else {
267            this.button.removeAttribute('title');
268          }
269
270          // update classes for animations
271          for(var i=0;i<this._states.length;i++){
272            L.DomUtil.removeClass(this._states[i].icon, this._currentState.stateName + '-active');
273            L.DomUtil.addClass(this._states[i].icon, newState.stateName + '-active');
274          }
275
276          // update classes for animations
277          L.DomUtil.removeClass(this.button, this._currentState.stateName + '-active');
278          L.DomUtil.addClass(this.button, newState.stateName + '-active');
279
280          // update the record
281          this._currentState = newState;
282
283        }
284      },
285
286      enable: function(){
287        L.DomUtil.addClass(this.button, 'enabled');
288        L.DomUtil.removeClass(this.button, 'disabled');
289        this.button.setAttribute('aria-hidden', 'false');
290        return this;
291      },
292
293      disable: function(){
294        L.DomUtil.addClass(this.button, 'disabled');
295        L.DomUtil.removeClass(this.button, 'enabled');
296        this.button.setAttribute('aria-hidden', 'true');
297        return this;
298      },
299
300      onAdd: function(map){
301        var bar = L.easyBar([this], {
302          position: this.options.position,
303          leafletClasses: this.options.leafletClasses
304        });
305        this._anonymousBar = bar;
306        this._container = bar.container;
307        return this._anonymousBar.container;
308      },
309
310      removeFrom: function (map) {
311        if (this._map === map)
312          this.remove();
313        return this;
314      },
315
316    });
317
318    L.easyButton = function(/* args will pass automatically */){
319      var args = Array.prototype.concat.apply([L.Control.EasyButton],arguments);
320      return new (Function.prototype.bind.apply(L.Control.EasyButton, args));
321    };
322
323    /*************************
324     *
325     * util functions
326     *
327     *************************/
328
329    // constructor for states so only curated
330    // states end up getting called
331    function State(template, easyButton){
332
333      this.title = template.title;
334      this.stateName = template.stateName ? template.stateName : 'unnamed-state';
335
336      // build the wrapper
337      this.icon = L.DomUtil.create('span', '');
338
339      L.DomUtil.addClass(this.icon, 'button-state state-' + this.stateName.replace(/(^\s*|\s*$)/g,''));
340      this.icon.innerHTML = buildIcon(template.icon);
341      this.onClick = L.Util.bind(template.onClick?template.onClick:function(){}, easyButton);
342    }
343
344    function buildIcon(ambiguousIconString) {
345
346      var tmpIcon;
347
348      // does this look like html? (i.e. not a class)
349      if( ambiguousIconString.match(/[&;=<>"']/) ){
350
351        // if so, the user should have put in html
352        // so move forward as such
353        tmpIcon = ambiguousIconString;
354
355      // then it wasn't html, so
356      // it's a class list, figure out what kind
357      } else {
358          ambiguousIconString = ambiguousIconString.replace(/(^\s*|\s*$)/g,'');
359          tmpIcon = L.DomUtil.create('span', '');
360
361          if( ambiguousIconString.indexOf('fa-') === 0 ){
362            L.DomUtil.addClass(tmpIcon, 'fa '  + ambiguousIconString)
363          } else if ( ambiguousIconString.indexOf('glyphicon-') === 0 ) {
364            L.DomUtil.addClass(tmpIcon, 'glyphicon ' + ambiguousIconString)
365          } else {
366            L.DomUtil.addClass(tmpIcon, /*rollwithit*/ ambiguousIconString)
367          }
368
369          // make this a string so that it's easy to set innerHTML below
370          tmpIcon = tmpIcon.outerHTML;
371      }
372
373      return tmpIcon;
374    }
375
376    })();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.