├── .gitignore ├── Dockerfile ├── LICENSE.txt ├── Readme.md ├── data ├── DES0005-0707-gri.jpg └── ps58_16x20.jpg ├── demo └── demo.gif ├── icons ├── fa-eye-slash.png ├── fa-eye.png ├── fa-filter.png ├── fa-random.png ├── fa-refresh.png ├── fa-square-o.png └── fa-star-half-o.png ├── imax-run ├── imax ├── __init__.py ├── client.py ├── config_template.yaml ├── dbfiles │ └── external.db ├── dbutils.py ├── server.py ├── static │ ├── cutouts.css │ ├── functions.js │ ├── help.js │ ├── jquery.min.js │ ├── leaflet │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── dist │ │ │ ├── images │ │ │ │ ├── layers-2x.png │ │ │ │ ├── layers.png │ │ │ │ ├── marker-icon-2x.png │ │ │ │ ├── marker-icon.png │ │ │ │ └── marker-shadow.png │ │ │ ├── leaflet-src.esm.js │ │ │ ├── leaflet-src.esm.js.map │ │ │ ├── leaflet-src.js │ │ │ ├── leaflet-src.js.map │ │ │ ├── leaflet.css │ │ │ ├── leaflet.js │ │ │ └── leaflet.js.map │ │ ├── package.json │ │ └── src │ │ │ ├── Leaflet.js │ │ │ ├── control │ │ │ ├── Control.Attribution.js │ │ │ ├── Control.Layers.js │ │ │ ├── Control.Scale.js │ │ │ ├── Control.Zoom.js │ │ │ ├── Control.js │ │ │ └── index.js │ │ │ ├── core │ │ │ ├── Browser.js │ │ │ ├── Class.js │ │ │ ├── Class.leafdoc │ │ │ ├── Events.js │ │ │ ├── Events.leafdoc │ │ │ ├── Handler.js │ │ │ ├── Util.js │ │ │ └── index.js │ │ │ ├── dom │ │ │ ├── DomEvent.DoubleTap.js │ │ │ ├── DomEvent.Pointer.js │ │ │ ├── DomEvent.js │ │ │ ├── DomUtil.js │ │ │ ├── Draggable.js │ │ │ ├── PosAnimation.js │ │ │ └── index.js │ │ │ ├── geo │ │ │ ├── LatLng.js │ │ │ ├── LatLngBounds.js │ │ │ ├── crs │ │ │ │ ├── CRS.EPSG3395.js │ │ │ │ ├── CRS.EPSG3857.js │ │ │ │ ├── CRS.EPSG4326.js │ │ │ │ ├── CRS.Earth.js │ │ │ │ ├── CRS.Simple.js │ │ │ │ ├── CRS.js │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ └── projection │ │ │ │ ├── Projection.LonLat.js │ │ │ │ ├── Projection.Mercator.js │ │ │ │ ├── Projection.SphericalMercator.js │ │ │ │ └── index.js │ │ │ ├── geometry │ │ │ ├── Bounds.js │ │ │ ├── LineUtil.js │ │ │ ├── Point.js │ │ │ ├── PolyUtil.js │ │ │ ├── Transformation.js │ │ │ └── index.js │ │ │ ├── images │ │ │ ├── layers.svg │ │ │ ├── logo.svg │ │ │ └── marker.svg │ │ │ ├── layer │ │ │ ├── DivOverlay.js │ │ │ ├── FeatureGroup.js │ │ │ ├── GeoJSON.js │ │ │ ├── ImageOverlay.js │ │ │ ├── Layer.Interactive.leafdoc │ │ │ ├── Layer.js │ │ │ ├── LayerGroup.js │ │ │ ├── Popup.js │ │ │ ├── Tooltip.js │ │ │ ├── VideoOverlay.js │ │ │ ├── index.js │ │ │ ├── marker │ │ │ │ ├── DivIcon.js │ │ │ │ ├── Icon.Default.js │ │ │ │ ├── Icon.js │ │ │ │ ├── Marker.Drag.js │ │ │ │ ├── Marker.js │ │ │ │ └── index.js │ │ │ ├── tile │ │ │ │ ├── GridLayer.js │ │ │ │ ├── TileLayer.WMS.js │ │ │ │ ├── TileLayer.js │ │ │ │ └── index.js │ │ │ └── vector │ │ │ │ ├── Canvas.js │ │ │ │ ├── Circle.js │ │ │ │ ├── CircleMarker.js │ │ │ │ ├── Path.js │ │ │ │ ├── Polygon.js │ │ │ │ ├── Polyline.js │ │ │ │ ├── Rectangle.js │ │ │ │ ├── Renderer.getRenderer.js │ │ │ │ ├── Renderer.js │ │ │ │ ├── SVG.Util.js │ │ │ │ ├── SVG.VML.js │ │ │ │ ├── SVG.js │ │ │ │ └── index.js │ │ │ └── map │ │ │ ├── Map.js │ │ │ ├── Map.methodOptions.leafdoc │ │ │ ├── handler │ │ │ ├── Map.BoxZoom.js │ │ │ ├── Map.DoubleClickZoom.js │ │ │ ├── Map.Drag.js │ │ │ ├── Map.Keyboard.js │ │ │ ├── Map.ScrollWheelZoom.js │ │ │ ├── Map.Tap.js │ │ │ └── Map.TouchZoom.js │ │ │ └── index.js │ └── plugins │ │ ├── L.Control.SlideMenu.css │ │ ├── L.Control.SlideMenu.js │ │ ├── Leaflet.Control.Custom.js │ │ ├── Toolbar.js │ │ ├── easy-button.css │ │ ├── easy-button.js │ │ ├── jquery-sidebar.min.js │ │ ├── leaflet-search.css │ │ ├── leaflet-search.js │ │ ├── leaflet-sidebar.css │ │ ├── leaflet-sidebar.js │ │ ├── leaflet-sidebar.min.css │ │ ├── leaflet-sidebar.min.js │ │ ├── leaflet.toolbar.min.css │ │ ├── leaflet.toolbar.min.js │ │ ├── loader.gif │ │ └── search-icon.png ├── templates │ ├── base.html │ └── index.html ├── utils.py └── version.py ├── jupyter ├── .ipynb_checkpoints │ ├── Untitled-checkpoint.ipynb │ ├── Untitled1-checkpoint.ipynb │ └── generate_avatars-checkpoint.ipynb ├── Untitled.ipynb ├── Untitled1.ipynb ├── crop.ipynb ├── generate_avatars.ipynb └── test_cexp.ipynb ├── requirements.txt └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | python_server/config.yaml 2 | python_server/ssl/* 3 | python_server/dbfiles/* 4 | deploy/ 5 | go_test/ 6 | py_test/ 7 | .idea 8 | config.yaml 9 | python_server/__pycache__ 10 | python_server/*.db 11 | # dependencies 12 | /node_modules 13 | /.pnp 14 | .pnp.js 15 | 16 | # testing 17 | /coverage 18 | 19 | # production 20 | /build 21 | 22 | # misc 23 | .DS_Store 24 | .env.local 25 | .env.development.local 26 | .env.test.local 27 | .env.production.local 28 | 29 | npm-debug.log* 30 | yarn-debug.log* 31 | yarn-error.log* 32 | 33 | 34 | .ipynb_checkpoints/* 35 | python_server/.ipynb_checkpoints/* 36 | imax/__pycache__ 37 | imax/.ipynb_checkpoints/* 38 | images/ 39 | dbpath/ 40 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Matias Carrasco Kind 2 | # mcarras2@illinois.edu 3 | # 4 | 5 | FROM python:3-alpine as base 6 | RUN apk add build-base python-dev py-pip jpeg-dev zlib-dev 7 | ENV LIBRARY_PATH=/lib:/usr/lib 8 | FROM base as builder 9 | RUN mkdir /install 10 | WORKDIR /install 11 | ADD requirements.txt /requirements.txt 12 | RUN pip install --install-option="--prefix=/install" -r /requirements.txt 13 | 14 | FROM base 15 | RUN adduser explorer -u 1001 -g 1001 -h /home/explorer -s /bin/sh -D 16 | COPY --from=builder /install /usr/local 17 | ADD python_server /home/explorer/server 18 | RUN chown -R 1001:1001 /home/explorer 19 | WORKDIR /home/explorer/server 20 | RUN rm -rf ssl/ dbfiles/ config.yaml __pycache__ 21 | USER explorer 22 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 National Center for Supercomputing Applications, University of Illinois at Urbana Champaign 2 | All rights reserved. 3 | 4 | Developed by: Matias Carrasco Kind 5 | NCSA/University of Illinois 6 | https://des.ncsa.illinois.edu 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. 10 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. 11 | Neither the names of Matias Carrasco Kind, NCSA, University of Illinois, nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. 13 | -------------------------------------------------------------------------------- /data/DES0005-0707-gri.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/data/DES0005-0707-gri.jpg -------------------------------------------------------------------------------- /data/ps58_16x20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/data/ps58_16x20.jpg -------------------------------------------------------------------------------- /demo/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/demo/demo.gif -------------------------------------------------------------------------------- /icons/fa-eye-slash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/icons/fa-eye-slash.png -------------------------------------------------------------------------------- /icons/fa-eye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/icons/fa-eye.png -------------------------------------------------------------------------------- /icons/fa-filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/icons/fa-filter.png -------------------------------------------------------------------------------- /icons/fa-random.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/icons/fa-random.png -------------------------------------------------------------------------------- /icons/fa-refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/icons/fa-refresh.png -------------------------------------------------------------------------------- /icons/fa-square-o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/icons/fa-square-o.png -------------------------------------------------------------------------------- /icons/fa-star-half-o.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/icons/fa-star-half-o.png -------------------------------------------------------------------------------- /imax-run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import click 3 | from imax.version import __version__ 4 | from imax.server import run_server 5 | from imax.client import run_client 6 | from imax.utils import copy_config_template, copy_folders, create_images, crop_image 7 | import logging as lg 8 | import coloredlogs 9 | 10 | def print_version(ctx, param, value): 11 | if not value or ctx.resilient_parsing: 12 | return 13 | click.echo('Version: {}'.format(__version__)) 14 | ctx.exit() 15 | 16 | logger = lg.getLogger('imax') 17 | 18 | @click.option('--log', default='info', help='log options [info, debug, error, warning]', show_default=True) 19 | @click.option('--version', is_flag=True, callback=print_version,expose_value=False, is_eager=True) 20 | @click.help_option('-h') 21 | @click.group() 22 | def imaxG(**kwargs): 23 | level = kwargs['log'].lower() 24 | if level == 'info': 25 | coloredlogs.install(level=lg.INFO) 26 | elif level == 'debug': 27 | coloredlogs.install(level=lg.DEBUG) 28 | elif level == 'error': 29 | coloredlogs.install(level=lg.ERROR) 30 | elif level == 'warning': 31 | coloredlogs.install(level=lg.WARNING) 32 | else: 33 | coloredlogs.install(level=lg.INFO) 34 | 35 | 36 | @click.option('-c','--config', default='config.yaml', help='path to config file', show_default=True) 37 | @imaxG.command() 38 | def server(**kwargs): 39 | logger.info("======== IMAX Server") 40 | run_server(configfile=kwargs['config']) 41 | 42 | 43 | @click.option('-c','--config', default='config.yaml', help='path to config file',show_default=True ) 44 | @click.option('--local', is_flag=True, help='run client from local static/template files') 45 | @imaxG.command() 46 | def client(**kwargs): 47 | logger.info("======== IMAX Client") 48 | if kwargs['local']: 49 | logger.info('Running locally') 50 | run_client(configfile=kwargs['config'], local=kwargs['local']) 51 | 52 | 53 | @click.option('-c', '--config', default='config.yaml', help='filename for config file', show_default=True) 54 | @imaxG.command() 55 | def create_config(**kwargs): 56 | copy_config_template(kwargs['config']) 57 | 58 | @imaxG.command() 59 | def copy_server_files(**kwargs): 60 | copy_folders() 61 | 62 | @click.option('-f', '--folder', default='images', help='Folder for created images', show_default=True) 63 | @click.option('-n', '--nimages', default=100, help='Number of images', show_default=True) 64 | @click.option('-m', '--cmap', default="summer", help='Background color map', show_default=True) 65 | @imaxG.command() 66 | def create_fake_images(**kwargs): 67 | create_images(N=kwargs['nimages'], folder=kwargs['folder'], mapname=kwargs['cmap']) 68 | 69 | 70 | @click.option('-f', '--folder', default='images', help='Folder for created images', show_default=True) 71 | @click.option('-i', '--input', required=True, help='Input large image') 72 | @click.option('-s', '--size', default=128, help='Default tile size (multiple of 4)', show_default=True, type=int) 73 | @imaxG.command() 74 | def crop_large_image(**kwargs): 75 | crop_image(path=kwargs['folder'], size=kwargs['size'], input=kwargs['input']) 76 | 77 | if __name__ == '__main__': 78 | imaxG() 79 | -------------------------------------------------------------------------------- /imax/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = "Matias Carrasco Kind" 2 | __license__ = "NCSA" 3 | from .version import __version__ 4 | from . import server, client, dbutils, utils 5 | __all__ = ["server", "client", "dbutils", "utils"] 6 | -------------------------------------------------------------------------------- /imax/config_template.yaml: -------------------------------------------------------------------------------- 1 | #### DATABASE 2 | db: 3 | dbpath: '{FILL ME}' # Path to sqlite files 4 | merge: false 5 | #### DISPLAY 6 | display: 7 | path: '{FILL ME}' # Path to images 8 | nimages: 1200 #Number of objects to be displayed even if there are more in the folder 9 | xdim: 40 #X dimension for the display 10 | ydim: 30 #Y dimension for the display 11 | tileSize: 256 #Size of the tile for which images are resized at max zoom level 12 | minXrange: 0 13 | minYrange: 0 14 | deltaZoom: 5 #default == 5 15 | min-width: 500 16 | max-width: 1400 17 | min-height: 500 18 | max-height: 1000 19 | #### SERVER 20 | server: 21 | ssl: false #use ssl, need to have certificates 22 | sslName: test #prefix of .crt and .key files inside ssl/ folder e.g., ssl/{sslName.key} 23 | host: 'http://localhost' #if using ssl, change to https 24 | port: 8888 25 | rootUrl: '/' #root url for server, e.g. request are made to /cexp/, if None use "/" 26 | #workers: None # None will default to the workers in the machine 27 | #### CLIENT 28 | client: 29 | host: 'http://localhost' 30 | port: 8000 31 | #### OPERATIONS options 32 | operation: 33 | updates: false #allows to update and/or remove classes to images, false and classes are fixed. 34 | help: true 35 | fullscreen: true 36 | invert: true 37 | toggle-classes: true 38 | random: true 39 | filter: true 40 | reset: true 41 | search: true 42 | #### CLASSES 43 | #### classes, use any classes from 0 to 9, class 0 is for hidden! class -1 is no class 44 | classes: 45 | - Test: 5 46 | -------------------------------------------------------------------------------- /imax/dbfiles/external.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/imax/dbfiles/external.db -------------------------------------------------------------------------------- /imax/dbutils.py: -------------------------------------------------------------------------------- 1 | import logging as lg 2 | import sqlite3 3 | import os 4 | import os 5 | import numpy as np 6 | import random as rn 7 | from .utils import read_config_single 8 | 9 | logging = lg.getLogger('utils') 10 | 11 | def create_db(filedb): 12 | conn = sqlite3.connect(filedb) 13 | c = conn.cursor() 14 | c.execute( 15 | "create table if not exists IMAGES " 16 | "(id int primary key, display int default 1, name text, class int default -1)" 17 | ) 18 | c.execute( 19 | "create table if not exists COORDS " "(id int primary key, vx int, vy int)" 20 | ) 21 | c.execute( 22 | "create table if not exists CONFIG " "(id int primary key, nimages int , nx int, ny int, updates int default 1)" 23 | ) 24 | conn.commit() 25 | conn.close() 26 | 27 | 28 | def initiate_db(filedb, images): 29 | chunk = [(i, 0, os.path.basename(images[i]), -1) for i in range(len(images))] 30 | conn = sqlite3.connect(filedb) 31 | c = conn.cursor() 32 | c.executemany("INSERT or REPLACE INTO IMAGES VALUES (?,?,?,?)", chunk) 33 | conn.commit() 34 | conn.close() 35 | 36 | def merge_db(dbname): 37 | conn = sqlite3.connect(dbname) 38 | c = conn.cursor() 39 | c.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='{}';".format('META')) 40 | results = c.fetchall() 41 | if len(results) == 0: 42 | logging.info("MERGE: Table META does not exist") 43 | else: 44 | logging.info("MERGE: Merging tables") 45 | c.execute("""UPDATE IMAGES 46 | SET 47 | class = ( select META.class from META where META.name = IMAGES.name) 48 | WHERE 49 | EXISTS ( 50 | SELECT * 51 | FROM META 52 | WHERE META.name = IMAGES.name)""") 53 | conn.commit() 54 | conn.close() 55 | 56 | 57 | 58 | def initialize(images, nimages, NX, NY, NTILES, dbname, configfile): 59 | logging.info('Initializing {}'.format(dbname)) 60 | temp = np.zeros(NX * NY, dtype="int") - 1 61 | image_idx = rn.sample(range(len(images)), nimages) # np.arange(nimages) 62 | conn = sqlite3.connect(dbname) 63 | c = conn.cursor() 64 | c.execute("UPDATE IMAGES SET display = 0") 65 | c.execute("DELETE FROM COORDS") 66 | for i in image_idx: 67 | c.execute("UPDATE IMAGES SET display = 1 where id = {}".format(i)) 68 | c.execute("SELECT id FROM IMAGES where display = 1 order by id") 69 | all_ids = c.fetchall() 70 | all_displayed = [i[0] for i in all_ids] 71 | image_idx = all_displayed 72 | temp[: len(image_idx)] = image_idx 73 | temp = temp.reshape((NY, NX)) 74 | idx = np.pad( 75 | temp, ((0, NTILES - NY), (0, NTILES - NX)), "constant", constant_values=-1 76 | ) 77 | for i in image_idx: 78 | vy, vx = np.where(idx == i) 79 | c.execute("INSERT INTO COORDS VALUES ({},{},{})".format(i, vx[0], vy[0])) 80 | conn.commit() 81 | conn.close() 82 | updates = read_config_single(configfile, 'operation', 'updates') 83 | if updates: 84 | update_config(NX, NY, nimages, dbname, 1) 85 | else: 86 | update_config(NX, NY, nimages, dbname, 0) 87 | return idx 88 | 89 | 90 | def update_config(NX, NY, nimages, userdb, updates=None): 91 | conn = sqlite3.connect(userdb) 92 | c = conn.cursor() 93 | if updates is None: 94 | c.execute('SELECT updates from CONFIG') 95 | updates = c.fetchone()[0] 96 | chunk = [0, nimages, NX, NY, updates] 97 | c.execute("INSERT or REPLACE INTO CONFIG VALUES (?,?,?,?,?)", chunk) 98 | 99 | conn.commit() 100 | conn.close() -------------------------------------------------------------------------------- /imax/static/cutouts.css: -------------------------------------------------------------------------------- 1 | .leaflet-container { 2 | background: #dddddd; 3 | } 4 | .btn-group { 5 | background: #dddddd; 6 | } 7 | #button_0 { 8 | background: rgb(255,192,203); 9 | background: rgba(255,192,203,0.5); 10 | color: black; 11 | } 12 | 13 | #button_9 { 14 | background: rgba(255, 255, 0); 15 | background: rgba(255, 255, 0, 0.5); 16 | color: black; 17 | } 18 | 19 | #button_8 { 20 | background: rgba(255, 0, 255); 21 | background: rgba(255, 0, 255, 0.5); 22 | color: black; 23 | } 24 | 25 | #button_7 { 26 | background: rgba(255, 165, 0); 27 | background: rgba(255, 165, 0, 0.5); 28 | color: black; 29 | } 30 | 31 | #button_6 { 32 | background: rgba(0, 0, 255); 33 | background: rgba(0, 0, 255, 0.5); 34 | color: black; 35 | } 36 | 37 | #button_5 { 38 | background: rgba(255, 0, 0); 39 | background: rgba(255, 0, 0, 0.5); 40 | color: black; 41 | } 42 | 43 | #button_4 { 44 | background: rgba(240, 255, 255); 45 | background: rgba(240, 255, 255, 0.5); 46 | color: black; 47 | } 48 | 49 | #button_3 { 50 | background: rgba(128,128,0); 51 | background: rgba(128,128,0, 0.5); 52 | color: black; 53 | } 54 | 55 | #button_2 { 56 | background: rgba(0,255,255); 57 | background: rgba(0,255,255, 0.5); 58 | color: black; 59 | } 60 | 61 | #button_1 { 62 | background: rgba(160,82,45); 63 | background: rgba(160,82,45, 0.5); 64 | color: black; 65 | } 66 | 67 | .info { 68 | padding: 6px 8px; 69 | font: 14px/16px Arial, Helvetica, sans-serif; 70 | background: white; 71 | background: rgba(255,255,255,0.8); 72 | box-shadow: 0 0 15px rgba(0,0,0,0.2); 73 | border-radius: 5px; 74 | } 75 | .info h4 { 76 | margin: 0 0 5px; 77 | color: #777; 78 | } 79 | 80 | .myhelp { 81 | color: black; 82 | font-size: 15px; 83 | margin-top: 8px; 84 | } 85 | -------------------------------------------------------------------------------- /imax/static/help.js: -------------------------------------------------------------------------------- 1 | var contentHelp = 2 | '

Help


' + 3 | ' -> Fullscreen
' + 4 | ' -> Invert colors
' + 5 | '/ -> Toggle On/Off classified tiles.
First time it reads from DB.

' + 6 | ' -> Random. Show a new random subsample (if available data is larger)
' + 7 | ' -> Apply filter to the displayed data.
Use the checkboxes on the left bottom side. -1 means no classified.
' + 8 | ' -> Reset filters and view. Does not display deleted images.
' + 9 | ' -> Performs a sqlite search on IMAGES.
' + 10 | '

Move around with mouse and keyboard , use the mouse wheel to zoom in/out and double click to focus on one image.' + 11 | '

Keyboard

' + 12 | 'Use "w","a","s","d" to move the selected tile and the keyboard numbers to apply a class as defined in the configuration file
' + 13 | 'Use "+", "-" to zoom in/out
' + 14 | 'Use "c" to clear any class selection
' + 15 | 'Use "t" to toggle on/off the classes
' + 16 | 'Use "h" to toggle on/off the Help
' + 17 | 'Use "f" to toggle on/off Full screen
' + 18 | 'Defined classes will appear at the bottom right side of the map' 19 | ; 20 | -------------------------------------------------------------------------------- /imax/static/leaflet/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2018, Vladimir Agafonkin 2 | Copyright (c) 2010-2011, CloudMade 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are 6 | permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 | of conditions and the following disclaimer in the documentation and/or other materials 13 | provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 16 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 18 | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /imax/static/leaflet/README.md: -------------------------------------------------------------------------------- 1 | Leaflet 2 | 3 | Leaflet is the leading open-source JavaScript library for **mobile-friendly interactive maps**. 4 | Weighing just about 37 KB of gzipped JS code, it has all the mapping [features][] most developers ever need. 5 | 6 | Leaflet is designed with *simplicity*, *performance* and *usability* in mind. 7 | It works efficiently across all major desktop and mobile platforms out of the box, 8 | taking advantage of HTML5 and CSS3 on modern browsers while being accessible on older ones too. 9 | It can be extended with a huge amount of [plugins][], 10 | has a beautiful, easy to use and [well-documented][] API 11 | and a simple, readable [source code][] that is a joy to [contribute][] to. 12 | 13 | For more info, docs and tutorials, check out the [official website][].
14 | For **Leaflet downloads** (including the built master version), check out the [download page][]. 15 | 16 | We're happy to meet new contributors. 17 | If you want to **get involved** with Leaflet development, check out the [contribution guide][contribute]. 18 | Let's make the best mapping library that will ever exist, 19 | and push the limits of what's possible with online maps! 20 | 21 | [![Build Status](https://travis-ci.org/Leaflet/Leaflet.svg?branch=master)](https://travis-ci.org/Leaflet/Leaflet) 22 | 23 | [contributors]: https://github.com/Leaflet/Leaflet/graphs/contributors 24 | [features]: http://leafletjs.com/#features 25 | [plugins]: http://leafletjs.com/plugins.html 26 | [well-documented]: http://leafletjs.com/reference.html "Leaflet API reference" 27 | [source code]: https://github.com/Leaflet/Leaflet "Leaflet GitHub repository" 28 | [hosted on GitHub]: http://github.com/Leaflet/Leaflet 29 | [contribute]: https://github.com/Leaflet/Leaflet/blob/master/CONTRIBUTING.md "A guide to contributing to Leaflet" 30 | [official website]: http://leafletjs.com 31 | [download page]: http://leafletjs.com/download.html 32 | 33 | -------------------------------------------------------------------------------- /imax/static/leaflet/dist/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/imax/static/leaflet/dist/images/layers-2x.png -------------------------------------------------------------------------------- /imax/static/leaflet/dist/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/imax/static/leaflet/dist/images/layers.png -------------------------------------------------------------------------------- /imax/static/leaflet/dist/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/imax/static/leaflet/dist/images/marker-icon-2x.png -------------------------------------------------------------------------------- /imax/static/leaflet/dist/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/imax/static/leaflet/dist/images/marker-icon.png -------------------------------------------------------------------------------- /imax/static/leaflet/dist/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgckind/imax/3223b9c5e0602fed0502a17cb6dd908a97e55629/imax/static/leaflet/dist/images/marker-shadow.png -------------------------------------------------------------------------------- /imax/static/leaflet/src/Leaflet.js: -------------------------------------------------------------------------------- 1 | 2 | import {version} from '../package.json'; 3 | export {version}; 4 | 5 | // control 6 | export * from './control/index'; 7 | 8 | // core 9 | export * from './core/index'; 10 | 11 | // dom 12 | export * from './dom/index'; 13 | 14 | // geometry 15 | export * from './geometry/index'; 16 | 17 | // geo 18 | export * from './geo/index'; 19 | 20 | // layer 21 | export * from './layer/index'; 22 | 23 | // map 24 | export * from './map/index'; 25 | 26 | import {freeze} from './core/Util'; 27 | Object.freeze = freeze; 28 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/control/Control.Attribution.js: -------------------------------------------------------------------------------- 1 | 2 | import {Control} from './Control'; 3 | import {Map} from '../map/Map'; 4 | import * as Util from '../core/Util'; 5 | import * as DomEvent from '../dom/DomEvent'; 6 | import * as DomUtil from '../dom/DomUtil'; 7 | 8 | /* 9 | * @class Control.Attribution 10 | * @aka L.Control.Attribution 11 | * @inherits Control 12 | * 13 | * The attribution control allows you to display attribution data in a small text box on a map. It is put on the map by default unless you set its [`attributionControl` option](#map-attributioncontrol) to `false`, and it fetches attribution texts from layers with the [`getAttribution` method](#layer-getattribution) automatically. Extends Control. 14 | */ 15 | 16 | export var Attribution = Control.extend({ 17 | // @section 18 | // @aka Control.Attribution options 19 | options: { 20 | position: 'bottomright', 21 | 22 | // @option prefix: String = 'Leaflet' 23 | // The HTML text shown before the attributions. Pass `false` to disable. 24 | prefix: 'Leaflet' 25 | }, 26 | 27 | initialize: function (options) { 28 | Util.setOptions(this, options); 29 | 30 | this._attributions = {}; 31 | }, 32 | 33 | onAdd: function (map) { 34 | map.attributionControl = this; 35 | this._container = DomUtil.create('div', 'leaflet-control-attribution'); 36 | DomEvent.disableClickPropagation(this._container); 37 | 38 | // TODO ugly, refactor 39 | for (var i in map._layers) { 40 | if (map._layers[i].getAttribution) { 41 | this.addAttribution(map._layers[i].getAttribution()); 42 | } 43 | } 44 | 45 | this._update(); 46 | 47 | return this._container; 48 | }, 49 | 50 | // @method setPrefix(prefix: String): this 51 | // Sets the text before the attributions. 52 | setPrefix: function (prefix) { 53 | this.options.prefix = prefix; 54 | this._update(); 55 | return this; 56 | }, 57 | 58 | // @method addAttribution(text: String): this 59 | // Adds an attribution text (e.g. `'Vector data © Mapbox'`). 60 | addAttribution: function (text) { 61 | if (!text) { return this; } 62 | 63 | if (!this._attributions[text]) { 64 | this._attributions[text] = 0; 65 | } 66 | this._attributions[text]++; 67 | 68 | this._update(); 69 | 70 | return this; 71 | }, 72 | 73 | // @method removeAttribution(text: String): this 74 | // Removes an attribution text. 75 | removeAttribution: function (text) { 76 | if (!text) { return this; } 77 | 78 | if (this._attributions[text]) { 79 | this._attributions[text]--; 80 | this._update(); 81 | } 82 | 83 | return this; 84 | }, 85 | 86 | _update: function () { 87 | if (!this._map) { return; } 88 | 89 | var attribs = []; 90 | 91 | for (var i in this._attributions) { 92 | if (this._attributions[i]) { 93 | attribs.push(i); 94 | } 95 | } 96 | 97 | var prefixAndAttribs = []; 98 | 99 | if (this.options.prefix) { 100 | prefixAndAttribs.push(this.options.prefix); 101 | } 102 | if (attribs.length) { 103 | prefixAndAttribs.push(attribs.join(', ')); 104 | } 105 | 106 | this._container.innerHTML = prefixAndAttribs.join(' | '); 107 | } 108 | }); 109 | 110 | // @namespace Map 111 | // @section Control options 112 | // @option attributionControl: Boolean = true 113 | // Whether a [attribution control](#control-attribution) is added to the map by default. 114 | Map.mergeOptions({ 115 | attributionControl: true 116 | }); 117 | 118 | Map.addInitHook(function () { 119 | if (this.options.attributionControl) { 120 | new Attribution().addTo(this); 121 | } 122 | }); 123 | 124 | // @namespace Control.Attribution 125 | // @factory L.control.attribution(options: Control.Attribution options) 126 | // Creates an attribution control. 127 | export var attribution = function (options) { 128 | return new Attribution(options); 129 | }; 130 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/control/Control.Scale.js: -------------------------------------------------------------------------------- 1 | 2 | import {Control} from './Control'; 3 | import * as DomUtil from '../dom/DomUtil'; 4 | 5 | /* 6 | * @class Control.Scale 7 | * @aka L.Control.Scale 8 | * @inherits Control 9 | * 10 | * A simple scale control that shows the scale of the current center of screen in metric (m/km) and imperial (mi/ft) systems. Extends `Control`. 11 | * 12 | * @example 13 | * 14 | * ```js 15 | * L.control.scale().addTo(map); 16 | * ``` 17 | */ 18 | 19 | export var Scale = Control.extend({ 20 | // @section 21 | // @aka Control.Scale options 22 | options: { 23 | position: 'bottomleft', 24 | 25 | // @option maxWidth: Number = 100 26 | // Maximum width of the control in pixels. The width is set dynamically to show round values (e.g. 100, 200, 500). 27 | maxWidth: 100, 28 | 29 | // @option metric: Boolean = True 30 | // Whether to show the metric scale line (m/km). 31 | metric: true, 32 | 33 | // @option imperial: Boolean = True 34 | // Whether to show the imperial scale line (mi/ft). 35 | imperial: true 36 | 37 | // @option updateWhenIdle: Boolean = false 38 | // If `true`, the control is updated on [`moveend`](#map-moveend), otherwise it's always up-to-date (updated on [`move`](#map-move)). 39 | }, 40 | 41 | onAdd: function (map) { 42 | var className = 'leaflet-control-scale', 43 | container = DomUtil.create('div', className), 44 | options = this.options; 45 | 46 | this._addScales(options, className + '-line', container); 47 | 48 | map.on(options.updateWhenIdle ? 'moveend' : 'move', this._update, this); 49 | map.whenReady(this._update, this); 50 | 51 | return container; 52 | }, 53 | 54 | onRemove: function (map) { 55 | map.off(this.options.updateWhenIdle ? 'moveend' : 'move', this._update, this); 56 | }, 57 | 58 | _addScales: function (options, className, container) { 59 | if (options.metric) { 60 | this._mScale = DomUtil.create('div', className, container); 61 | } 62 | if (options.imperial) { 63 | this._iScale = DomUtil.create('div', className, container); 64 | } 65 | }, 66 | 67 | _update: function () { 68 | var map = this._map, 69 | y = map.getSize().y / 2; 70 | 71 | var maxMeters = map.distance( 72 | map.containerPointToLatLng([0, y]), 73 | map.containerPointToLatLng([this.options.maxWidth, y])); 74 | 75 | this._updateScales(maxMeters); 76 | }, 77 | 78 | _updateScales: function (maxMeters) { 79 | if (this.options.metric && maxMeters) { 80 | this._updateMetric(maxMeters); 81 | } 82 | if (this.options.imperial && maxMeters) { 83 | this._updateImperial(maxMeters); 84 | } 85 | }, 86 | 87 | _updateMetric: function (maxMeters) { 88 | var meters = this._getRoundNum(maxMeters), 89 | label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km'; 90 | 91 | this._updateScale(this._mScale, label, meters / maxMeters); 92 | }, 93 | 94 | _updateImperial: function (maxMeters) { 95 | var maxFeet = maxMeters * 3.2808399, 96 | maxMiles, miles, feet; 97 | 98 | if (maxFeet > 5280) { 99 | maxMiles = maxFeet / 5280; 100 | miles = this._getRoundNum(maxMiles); 101 | this._updateScale(this._iScale, miles + ' mi', miles / maxMiles); 102 | 103 | } else { 104 | feet = this._getRoundNum(maxFeet); 105 | this._updateScale(this._iScale, feet + ' ft', feet / maxFeet); 106 | } 107 | }, 108 | 109 | _updateScale: function (scale, text, ratio) { 110 | scale.style.width = Math.round(this.options.maxWidth * ratio) + 'px'; 111 | scale.innerHTML = text; 112 | }, 113 | 114 | _getRoundNum: function (num) { 115 | var pow10 = Math.pow(10, (Math.floor(num) + '').length - 1), 116 | d = num / pow10; 117 | 118 | d = d >= 10 ? 10 : 119 | d >= 5 ? 5 : 120 | d >= 3 ? 3 : 121 | d >= 2 ? 2 : 1; 122 | 123 | return pow10 * d; 124 | } 125 | }); 126 | 127 | 128 | // @factory L.control.scale(options?: Control.Scale options) 129 | // Creates an scale control with the given options. 130 | export var scale = function (options) { 131 | return new Scale(options); 132 | }; 133 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/control/Control.Zoom.js: -------------------------------------------------------------------------------- 1 | 2 | import {Control} from './Control'; 3 | import {Map} from '../map/Map'; 4 | import * as DomUtil from '../dom/DomUtil'; 5 | import * as DomEvent from '../dom/DomEvent'; 6 | 7 | /* 8 | * @class Control.Zoom 9 | * @aka L.Control.Zoom 10 | * @inherits Control 11 | * 12 | * A basic zoom control with two buttons (zoom in and zoom out). It is put on the map by default unless you set its [`zoomControl` option](#map-zoomcontrol) to `false`. Extends `Control`. 13 | */ 14 | 15 | export var Zoom = Control.extend({ 16 | // @section 17 | // @aka Control.Zoom options 18 | options: { 19 | position: 'topleft', 20 | 21 | // @option zoomInText: String = '+' 22 | // The text set on the 'zoom in' button. 23 | zoomInText: '+', 24 | 25 | // @option zoomInTitle: String = 'Zoom in' 26 | // The title set on the 'zoom in' button. 27 | zoomInTitle: 'Zoom in', 28 | 29 | // @option zoomOutText: String = '−' 30 | // The text set on the 'zoom out' button. 31 | zoomOutText: '−', 32 | 33 | // @option zoomOutTitle: String = 'Zoom out' 34 | // The title set on the 'zoom out' button. 35 | zoomOutTitle: 'Zoom out' 36 | }, 37 | 38 | onAdd: function (map) { 39 | var zoomName = 'leaflet-control-zoom', 40 | container = DomUtil.create('div', zoomName + ' leaflet-bar'), 41 | options = this.options; 42 | 43 | this._zoomInButton = this._createButton(options.zoomInText, options.zoomInTitle, 44 | zoomName + '-in', container, this._zoomIn); 45 | this._zoomOutButton = this._createButton(options.zoomOutText, options.zoomOutTitle, 46 | zoomName + '-out', container, this._zoomOut); 47 | 48 | this._updateDisabled(); 49 | map.on('zoomend zoomlevelschange', this._updateDisabled, this); 50 | 51 | return container; 52 | }, 53 | 54 | onRemove: function (map) { 55 | map.off('zoomend zoomlevelschange', this._updateDisabled, this); 56 | }, 57 | 58 | disable: function () { 59 | this._disabled = true; 60 | this._updateDisabled(); 61 | return this; 62 | }, 63 | 64 | enable: function () { 65 | this._disabled = false; 66 | this._updateDisabled(); 67 | return this; 68 | }, 69 | 70 | _zoomIn: function (e) { 71 | if (!this._disabled && this._map._zoom < this._map.getMaxZoom()) { 72 | this._map.zoomIn(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1)); 73 | } 74 | }, 75 | 76 | _zoomOut: function (e) { 77 | if (!this._disabled && this._map._zoom > this._map.getMinZoom()) { 78 | this._map.zoomOut(this._map.options.zoomDelta * (e.shiftKey ? 3 : 1)); 79 | } 80 | }, 81 | 82 | _createButton: function (html, title, className, container, fn) { 83 | var link = DomUtil.create('a', className, container); 84 | link.innerHTML = html; 85 | link.href = '#'; 86 | link.title = title; 87 | 88 | /* 89 | * Will force screen readers like VoiceOver to read this as "Zoom in - button" 90 | */ 91 | link.setAttribute('role', 'button'); 92 | link.setAttribute('aria-label', title); 93 | 94 | DomEvent.disableClickPropagation(link); 95 | DomEvent.on(link, 'click', DomEvent.stop); 96 | DomEvent.on(link, 'click', fn, this); 97 | DomEvent.on(link, 'click', this._refocusOnMap, this); 98 | 99 | return link; 100 | }, 101 | 102 | _updateDisabled: function () { 103 | var map = this._map, 104 | className = 'leaflet-disabled'; 105 | 106 | DomUtil.removeClass(this._zoomInButton, className); 107 | DomUtil.removeClass(this._zoomOutButton, className); 108 | 109 | if (this._disabled || map._zoom === map.getMinZoom()) { 110 | DomUtil.addClass(this._zoomOutButton, className); 111 | } 112 | if (this._disabled || map._zoom === map.getMaxZoom()) { 113 | DomUtil.addClass(this._zoomInButton, className); 114 | } 115 | } 116 | }); 117 | 118 | // @namespace Map 119 | // @section Control options 120 | // @option zoomControl: Boolean = true 121 | // Whether a [zoom control](#control-zoom) is added to the map by default. 122 | Map.mergeOptions({ 123 | zoomControl: true 124 | }); 125 | 126 | Map.addInitHook(function () { 127 | if (this.options.zoomControl) { 128 | // @section Controls 129 | // @property zoomControl: Control.Zoom 130 | // The default zoom control (only available if the 131 | // [`zoomControl` option](#map-zoomcontrol) was `true` when creating the map). 132 | this.zoomControl = new Zoom(); 133 | this.addControl(this.zoomControl); 134 | } 135 | }); 136 | 137 | // @namespace Control.Zoom 138 | // @factory L.control.zoom(options: Control.Zoom options) 139 | // Creates a zoom control 140 | export var zoom = function (options) { 141 | return new Zoom(options); 142 | }; 143 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/control/Control.js: -------------------------------------------------------------------------------- 1 | 2 | import {Class} from '../core/Class'; 3 | import {Map} from '../map/Map'; 4 | import * as Util from '../core/Util'; 5 | import * as DomUtil from '../dom/DomUtil'; 6 | 7 | /* 8 | * @class Control 9 | * @aka L.Control 10 | * @inherits Class 11 | * 12 | * L.Control is a base class for implementing map controls. Handles positioning. 13 | * All other controls extend from this class. 14 | */ 15 | 16 | export var Control = Class.extend({ 17 | // @section 18 | // @aka Control options 19 | options: { 20 | // @option position: String = 'topright' 21 | // The position of the control (one of the map corners). Possible values are `'topleft'`, 22 | // `'topright'`, `'bottomleft'` or `'bottomright'` 23 | position: 'topright' 24 | }, 25 | 26 | initialize: function (options) { 27 | Util.setOptions(this, options); 28 | }, 29 | 30 | /* @section 31 | * Classes extending L.Control will inherit the following methods: 32 | * 33 | * @method getPosition: string 34 | * Returns the position of the control. 35 | */ 36 | getPosition: function () { 37 | return this.options.position; 38 | }, 39 | 40 | // @method setPosition(position: string): this 41 | // Sets the position of the control. 42 | setPosition: function (position) { 43 | var map = this._map; 44 | 45 | if (map) { 46 | map.removeControl(this); 47 | } 48 | 49 | this.options.position = position; 50 | 51 | if (map) { 52 | map.addControl(this); 53 | } 54 | 55 | return this; 56 | }, 57 | 58 | // @method getContainer: HTMLElement 59 | // Returns the HTMLElement that contains the control. 60 | getContainer: function () { 61 | return this._container; 62 | }, 63 | 64 | // @method addTo(map: Map): this 65 | // Adds the control to the given map. 66 | addTo: function (map) { 67 | this.remove(); 68 | this._map = map; 69 | 70 | var container = this._container = this.onAdd(map), 71 | pos = this.getPosition(), 72 | corner = map._controlCorners[pos]; 73 | 74 | DomUtil.addClass(container, 'leaflet-control'); 75 | 76 | if (pos.indexOf('bottom') !== -1) { 77 | corner.insertBefore(container, corner.firstChild); 78 | } else { 79 | corner.appendChild(container); 80 | } 81 | 82 | return this; 83 | }, 84 | 85 | // @method remove: this 86 | // Removes the control from the map it is currently active on. 87 | remove: function () { 88 | if (!this._map) { 89 | return this; 90 | } 91 | 92 | DomUtil.remove(this._container); 93 | 94 | if (this.onRemove) { 95 | this.onRemove(this._map); 96 | } 97 | 98 | this._map = null; 99 | 100 | return this; 101 | }, 102 | 103 | _refocusOnMap: function (e) { 104 | // if map exists and event is not a keyboard event 105 | if (this._map && e && e.screenX > 0 && e.screenY > 0) { 106 | this._map.getContainer().focus(); 107 | } 108 | } 109 | }); 110 | 111 | export var control = function (options) { 112 | return new Control(options); 113 | }; 114 | 115 | /* @section Extension methods 116 | * @uninheritable 117 | * 118 | * Every control should extend from `L.Control` and (re-)implement the following methods. 119 | * 120 | * @method onAdd(map: Map): HTMLElement 121 | * Should return the container DOM element for the control and add listeners on relevant map events. Called on [`control.addTo(map)`](#control-addTo). 122 | * 123 | * @method onRemove(map: Map) 124 | * Optional method. Should contain all clean up code that removes the listeners previously added in [`onAdd`](#control-onadd). Called on [`control.remove()`](#control-remove). 125 | */ 126 | 127 | /* @namespace Map 128 | * @section Methods for Layers and Controls 129 | */ 130 | Map.include({ 131 | // @method addControl(control: Control): this 132 | // Adds the given control to the map 133 | addControl: function (control) { 134 | control.addTo(this); 135 | return this; 136 | }, 137 | 138 | // @method removeControl(control: Control): this 139 | // Removes the given control from the map 140 | removeControl: function (control) { 141 | control.remove(); 142 | return this; 143 | }, 144 | 145 | _initControlPos: function () { 146 | var corners = this._controlCorners = {}, 147 | l = 'leaflet-', 148 | container = this._controlContainer = 149 | DomUtil.create('div', l + 'control-container', this._container); 150 | 151 | function createCorner(vSide, hSide) { 152 | var className = l + vSide + ' ' + l + hSide; 153 | 154 | corners[vSide + hSide] = DomUtil.create('div', className, container); 155 | } 156 | 157 | createCorner('top', 'left'); 158 | createCorner('top', 'right'); 159 | createCorner('bottom', 'left'); 160 | createCorner('bottom', 'right'); 161 | }, 162 | 163 | _clearControlPos: function () { 164 | for (var i in this._controlCorners) { 165 | DomUtil.remove(this._controlCorners[i]); 166 | } 167 | DomUtil.remove(this._controlContainer); 168 | delete this._controlCorners; 169 | delete this._controlContainer; 170 | } 171 | }); 172 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/control/index.js: -------------------------------------------------------------------------------- 1 | import {Control, control} from './Control'; 2 | import {Layers, layers} from './Control.Layers'; 3 | import {Zoom, zoom} from './Control.Zoom'; 4 | import {Scale, scale} from './Control.Scale'; 5 | import {Attribution, attribution} from './Control.Attribution'; 6 | 7 | Control.Layers = Layers; 8 | Control.Zoom = Zoom; 9 | Control.Scale = Scale; 10 | Control.Attribution = Attribution; 11 | 12 | control.layers = layers; 13 | control.zoom = zoom; 14 | control.scale = scale; 15 | control.attribution = attribution; 16 | 17 | export {Control, control}; 18 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/core/Class.js: -------------------------------------------------------------------------------- 1 | import * as Util from './Util'; 2 | 3 | // @class Class 4 | // @aka L.Class 5 | 6 | // @section 7 | // @uninheritable 8 | 9 | // Thanks to John Resig and Dean Edwards for inspiration! 10 | 11 | export function Class() {} 12 | 13 | Class.extend = function (props) { 14 | 15 | // @function extend(props: Object): Function 16 | // [Extends the current class](#class-inheritance) given the properties to be included. 17 | // Returns a Javascript function that is a class constructor (to be called with `new`). 18 | var NewClass = function () { 19 | 20 | // call the constructor 21 | if (this.initialize) { 22 | this.initialize.apply(this, arguments); 23 | } 24 | 25 | // call all constructor hooks 26 | this.callInitHooks(); 27 | }; 28 | 29 | var parentProto = NewClass.__super__ = this.prototype; 30 | 31 | var proto = Util.create(parentProto); 32 | proto.constructor = NewClass; 33 | 34 | NewClass.prototype = proto; 35 | 36 | // inherit parent's statics 37 | for (var i in this) { 38 | if (this.hasOwnProperty(i) && i !== 'prototype' && i !== '__super__') { 39 | NewClass[i] = this[i]; 40 | } 41 | } 42 | 43 | // mix static properties into the class 44 | if (props.statics) { 45 | Util.extend(NewClass, props.statics); 46 | delete props.statics; 47 | } 48 | 49 | // mix includes into the prototype 50 | if (props.includes) { 51 | checkDeprecatedMixinEvents(props.includes); 52 | Util.extend.apply(null, [proto].concat(props.includes)); 53 | delete props.includes; 54 | } 55 | 56 | // merge options 57 | if (proto.options) { 58 | props.options = Util.extend(Util.create(proto.options), props.options); 59 | } 60 | 61 | // mix given properties into the prototype 62 | Util.extend(proto, props); 63 | 64 | proto._initHooks = []; 65 | 66 | // add method for calling all hooks 67 | proto.callInitHooks = function () { 68 | 69 | if (this._initHooksCalled) { return; } 70 | 71 | if (parentProto.callInitHooks) { 72 | parentProto.callInitHooks.call(this); 73 | } 74 | 75 | this._initHooksCalled = true; 76 | 77 | for (var i = 0, len = proto._initHooks.length; i < len; i++) { 78 | proto._initHooks[i].call(this); 79 | } 80 | }; 81 | 82 | return NewClass; 83 | }; 84 | 85 | 86 | // @function include(properties: Object): this 87 | // [Includes a mixin](#class-includes) into the current class. 88 | Class.include = function (props) { 89 | Util.extend(this.prototype, props); 90 | return this; 91 | }; 92 | 93 | // @function mergeOptions(options: Object): this 94 | // [Merges `options`](#class-options) into the defaults of the class. 95 | Class.mergeOptions = function (options) { 96 | Util.extend(this.prototype.options, options); 97 | return this; 98 | }; 99 | 100 | // @function addInitHook(fn: Function): this 101 | // Adds a [constructor hook](#class-constructor-hooks) to the class. 102 | Class.addInitHook = function (fn) { // (Function) || (String, args...) 103 | var args = Array.prototype.slice.call(arguments, 1); 104 | 105 | var init = typeof fn === 'function' ? fn : function () { 106 | this[fn].apply(this, args); 107 | }; 108 | 109 | this.prototype._initHooks = this.prototype._initHooks || []; 110 | this.prototype._initHooks.push(init); 111 | return this; 112 | }; 113 | 114 | function checkDeprecatedMixinEvents(includes) { 115 | if (typeof L === 'undefined' || !L || !L.Mixin) { return; } 116 | 117 | includes = Util.isArray(includes) ? includes : [includes]; 118 | 119 | for (var i = 0; i < includes.length; i++) { 120 | if (includes[i] === L.Mixin.Events) { 121 | console.warn('Deprecated include of L.Mixin.Events: ' + 122 | 'this property will be removed in future releases, ' + 123 | 'please inherit from L.Evented instead.', new Error().stack); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/core/Events.leafdoc: -------------------------------------------------------------------------------- 1 | 2 | @namespace Event objects 3 | 4 | 5 | Whenever a class inheriting from `Evented` fires an event, a listener function 6 | will be called with an event argument, which is a plain object containing 7 | information about the event. For example: 8 | 9 | ```js 10 | map.on('click', function(ev) { 11 | alert(ev.latlng); // ev is an event object (MouseEvent in this case) 12 | }); 13 | ``` 14 | 15 | The information available depends on the event type: 16 | 17 | 18 | @miniclass Event (Event objects) 19 | @section 20 | The base event object. All other event objects contain these properties too. 21 | @property type: String 22 | The event type (e.g. `'click'`). 23 | @property target: Object 24 | The object that fired the event. For propagated events, the last object in 25 | the propagation chain that fired the event. 26 | @property sourceTarget: Object 27 | The object that originally fired the event. For non-propagated events, this will 28 | be the same as the `target`. 29 | @property propagatedFrom: Object 30 | For propagated events, the last object that propagated the event to its 31 | event parent. 32 | @property layer: Object 33 | **Deprecated.** The same as `propagatedFrom`. 34 | 35 | 36 | @miniclass KeyboardEvent (Event objects) 37 | @inherits Event 38 | @property originalEvent: DOMEvent 39 | The original [DOM `KeyboardEvent`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent) that triggered this Leaflet event. 40 | 41 | @miniclass MouseEvent (Event objects) 42 | @inherits Event 43 | @property latlng: LatLng 44 | The geographical point where the mouse event occured. 45 | @property layerPoint: Point 46 | Pixel coordinates of the point where the mouse event occured relative to the map layer. 47 | @property containerPoint: Point 48 | Pixel coordinates of the point where the mouse event occured relative to the map сontainer. 49 | @property originalEvent: DOMEvent 50 | The original [DOM `MouseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) or [DOM `TouchEvent`](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent) that triggered this Leaflet event. 51 | 52 | @miniclass LocationEvent (Event objects) 53 | @inherits Event 54 | @property latlng: LatLng 55 | Detected geographical location of the user. 56 | @property bounds: LatLngBounds 57 | Geographical bounds of the area user is located in (with respect to the accuracy of location). 58 | @property accuracy: Number 59 | Accuracy of location in meters. 60 | @property altitude: Number 61 | Height of the position above the WGS84 ellipsoid in meters. 62 | @property altitudeAccuracy: Number 63 | Accuracy of altitude in meters. 64 | @property heading: Number 65 | The direction of travel in degrees counting clockwise from true North. 66 | @property speed: Number 67 | Current velocity in meters per second. 68 | @property timestamp: Number 69 | The time when the position was acquired. 70 | 71 | @miniclass ErrorEvent (Event objects) 72 | @inherits Event 73 | @property message: String 74 | Error message. 75 | @property code: Number 76 | Error code (if applicable). 77 | 78 | @miniclass LayerEvent (Event objects) 79 | @inherits Event 80 | @property layer: Layer 81 | The layer that was added or removed. 82 | 83 | @miniclass LayersControlEvent (Event objects) 84 | @inherits Event 85 | @property layer: Layer 86 | The layer that was added or removed. 87 | @property name: String 88 | The name of the layer that was added or removed. 89 | 90 | @miniclass TileEvent (Event objects) 91 | @inherits Event 92 | @property tile: HTMLElement 93 | The tile element (image). 94 | @property coords: Point 95 | Point object with the tile's `x`, `y`, and `z` (zoom level) coordinates. 96 | 97 | @miniclass TileErrorEvent (Event objects) 98 | @inherits Event 99 | @property tile: HTMLElement 100 | The tile element (image). 101 | @property coords: Point 102 | Point object with the tile's `x`, `y`, and `z` (zoom level) coordinates. 103 | @property error: * 104 | Error passed to the tile's `done()` callback. 105 | 106 | @miniclass ResizeEvent (Event objects) 107 | @inherits Event 108 | @property oldSize: Point 109 | The old size before resize event. 110 | @property newSize: Point 111 | The new size after the resize event. 112 | 113 | @miniclass GeoJSONEvent (Event objects) 114 | @inherits Event 115 | @property layer: Layer 116 | The layer for the GeoJSON feature that is being added to the map. 117 | @property properties: Object 118 | GeoJSON properties of the feature. 119 | @property geometryType: String 120 | GeoJSON geometry type of the feature. 121 | @property id: String 122 | GeoJSON ID of the feature (if present). 123 | 124 | @miniclass PopupEvent (Event objects) 125 | @inherits Event 126 | @property popup: Popup 127 | The popup that was opened or closed. 128 | 129 | @miniclass TooltipEvent (Event objects) 130 | @inherits Event 131 | @property tooltip: Tooltip 132 | The tooltip that was opened or closed. 133 | 134 | @miniclass DragEndEvent (Event objects) 135 | @inherits Event 136 | @property distance: Number 137 | The distance in pixels the draggable element was moved by. 138 | 139 | @miniclass ZoomAnimEvent (Event objects) 140 | @inherits Event 141 | @property center: LatLng; The current center of the map 142 | @property zoom: Number; The current zoom level of the map 143 | @property noUpdate: Boolean; Whether layers should update their contents due to this event 144 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/core/Handler.js: -------------------------------------------------------------------------------- 1 | import {Class} from './Class'; 2 | 3 | /* 4 | L.Handler is a base class for handler classes that are used internally to inject 5 | interaction features like dragging to classes like Map and Marker. 6 | */ 7 | 8 | // @class Handler 9 | // @aka L.Handler 10 | // Abstract class for map interaction handlers 11 | 12 | export var Handler = Class.extend({ 13 | initialize: function (map) { 14 | this._map = map; 15 | }, 16 | 17 | // @method enable(): this 18 | // Enables the handler 19 | enable: function () { 20 | if (this._enabled) { return this; } 21 | 22 | this._enabled = true; 23 | this.addHooks(); 24 | return this; 25 | }, 26 | 27 | // @method disable(): this 28 | // Disables the handler 29 | disable: function () { 30 | if (!this._enabled) { return this; } 31 | 32 | this._enabled = false; 33 | this.removeHooks(); 34 | return this; 35 | }, 36 | 37 | // @method enabled(): Boolean 38 | // Returns `true` if the handler is enabled 39 | enabled: function () { 40 | return !!this._enabled; 41 | } 42 | 43 | // @section Extension methods 44 | // Classes inheriting from `Handler` must implement the two following methods: 45 | // @method addHooks() 46 | // Called when the handler is enabled, should add event hooks. 47 | // @method removeHooks() 48 | // Called when the handler is disabled, should remove the event hooks added previously. 49 | }); 50 | 51 | // @section There is static function which can be called without instantiating L.Handler: 52 | // @function addTo(map: Map, name: String): this 53 | // Adds a new Handler to the given map with the given name. 54 | Handler.addTo = function (map, name) { 55 | map.addHandler(name, this); 56 | return this; 57 | }; 58 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/core/index.js: -------------------------------------------------------------------------------- 1 | import * as Browser from './Browser'; 2 | export {Browser}; 3 | 4 | export {Class} from './Class'; 5 | 6 | import {Evented} from './Events'; 7 | import {Events} from './Events'; 8 | export {Evented}; 9 | export var Mixin = {Events: Events}; 10 | 11 | export {Handler} from './Handler'; 12 | 13 | import * as Util from './Util'; 14 | export {Util}; 15 | export {extend, bind, stamp, setOptions} from './Util'; 16 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/dom/DomEvent.DoubleTap.js: -------------------------------------------------------------------------------- 1 | import * as Browser from '../core/Browser'; 2 | import {_pointersCount} from './DomEvent.Pointer'; 3 | 4 | /* 5 | * Extends the event handling code with double tap support for mobile browsers. 6 | */ 7 | 8 | var _touchstart = Browser.msPointer ? 'MSPointerDown' : Browser.pointer ? 'pointerdown' : 'touchstart'; 9 | var _touchend = Browser.msPointer ? 'MSPointerUp' : Browser.pointer ? 'pointerup' : 'touchend'; 10 | var _pre = '_leaflet_'; 11 | 12 | // inspired by Zepto touch code by Thomas Fuchs 13 | export function addDoubleTapListener(obj, handler, id) { 14 | var last, touch, 15 | doubleTap = false, 16 | delay = 250; 17 | 18 | function onTouchStart(e) { 19 | var count; 20 | 21 | if (Browser.pointer) { 22 | if ((!Browser.edge) || e.pointerType === 'mouse') { return; } 23 | count = _pointersCount; 24 | } else { 25 | count = e.touches.length; 26 | } 27 | 28 | if (count > 1) { return; } 29 | 30 | var now = Date.now(), 31 | delta = now - (last || now); 32 | 33 | touch = e.touches ? e.touches[0] : e; 34 | doubleTap = (delta > 0 && delta <= delay); 35 | last = now; 36 | } 37 | 38 | function onTouchEnd(e) { 39 | if (doubleTap && !touch.cancelBubble) { 40 | if (Browser.pointer) { 41 | if ((!Browser.edge) || e.pointerType === 'mouse') { return; } 42 | // work around .type being readonly with MSPointer* events 43 | var newTouch = {}, 44 | prop, i; 45 | 46 | for (i in touch) { 47 | prop = touch[i]; 48 | newTouch[i] = prop && prop.bind ? prop.bind(touch) : prop; 49 | } 50 | touch = newTouch; 51 | } 52 | touch.type = 'dblclick'; 53 | handler(touch); 54 | last = null; 55 | } 56 | } 57 | 58 | obj[_pre + _touchstart + id] = onTouchStart; 59 | obj[_pre + _touchend + id] = onTouchEnd; 60 | obj[_pre + 'dblclick' + id] = handler; 61 | 62 | obj.addEventListener(_touchstart, onTouchStart, false); 63 | obj.addEventListener(_touchend, onTouchEnd, false); 64 | 65 | // On some platforms (notably, chrome<55 on win10 + touchscreen + mouse), 66 | // the browser doesn't fire touchend/pointerup events but does fire 67 | // native dblclicks. See #4127. 68 | // Edge 14 also fires native dblclicks, but only for pointerType mouse, see #5180. 69 | obj.addEventListener('dblclick', handler, false); 70 | 71 | return this; 72 | } 73 | 74 | export function removeDoubleTapListener(obj, id) { 75 | var touchstart = obj[_pre + _touchstart + id], 76 | touchend = obj[_pre + _touchend + id], 77 | dblclick = obj[_pre + 'dblclick' + id]; 78 | 79 | obj.removeEventListener(_touchstart, touchstart, false); 80 | obj.removeEventListener(_touchend, touchend, false); 81 | if (!Browser.edge) { 82 | obj.removeEventListener('dblclick', dblclick, false); 83 | } 84 | 85 | return this; 86 | } 87 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/dom/DomEvent.Pointer.js: -------------------------------------------------------------------------------- 1 | import * as DomEvent from './DomEvent'; 2 | import * as Util from '../core/Util'; 3 | import * as Browser from '../core/Browser'; 4 | 5 | /* 6 | * Extends L.DomEvent to provide touch support for Internet Explorer and Windows-based devices. 7 | */ 8 | 9 | 10 | var POINTER_DOWN = Browser.msPointer ? 'MSPointerDown' : 'pointerdown'; 11 | var POINTER_MOVE = Browser.msPointer ? 'MSPointerMove' : 'pointermove'; 12 | var POINTER_UP = Browser.msPointer ? 'MSPointerUp' : 'pointerup'; 13 | var POINTER_CANCEL = Browser.msPointer ? 'MSPointerCancel' : 'pointercancel'; 14 | var TAG_WHITE_LIST = ['INPUT', 'SELECT', 'OPTION']; 15 | 16 | var _pointers = {}; 17 | var _pointerDocListener = false; 18 | 19 | // DomEvent.DoubleTap needs to know about this 20 | export var _pointersCount = 0; 21 | 22 | // Provides a touch events wrapper for (ms)pointer events. 23 | // ref http://www.w3.org/TR/pointerevents/ https://www.w3.org/Bugs/Public/show_bug.cgi?id=22890 24 | 25 | export function addPointerListener(obj, type, handler, id) { 26 | if (type === 'touchstart') { 27 | _addPointerStart(obj, handler, id); 28 | 29 | } else if (type === 'touchmove') { 30 | _addPointerMove(obj, handler, id); 31 | 32 | } else if (type === 'touchend') { 33 | _addPointerEnd(obj, handler, id); 34 | } 35 | 36 | return this; 37 | } 38 | 39 | export function removePointerListener(obj, type, id) { 40 | var handler = obj['_leaflet_' + type + id]; 41 | 42 | if (type === 'touchstart') { 43 | obj.removeEventListener(POINTER_DOWN, handler, false); 44 | 45 | } else if (type === 'touchmove') { 46 | obj.removeEventListener(POINTER_MOVE, handler, false); 47 | 48 | } else if (type === 'touchend') { 49 | obj.removeEventListener(POINTER_UP, handler, false); 50 | obj.removeEventListener(POINTER_CANCEL, handler, false); 51 | } 52 | 53 | return this; 54 | } 55 | 56 | function _addPointerStart(obj, handler, id) { 57 | var onDown = Util.bind(function (e) { 58 | if (e.pointerType !== 'mouse' && e.MSPOINTER_TYPE_MOUSE && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) { 59 | // In IE11, some touch events needs to fire for form controls, or 60 | // the controls will stop working. We keep a whitelist of tag names that 61 | // need these events. For other target tags, we prevent default on the event. 62 | if (TAG_WHITE_LIST.indexOf(e.target.tagName) < 0) { 63 | DomEvent.preventDefault(e); 64 | } else { 65 | return; 66 | } 67 | } 68 | 69 | _handlePointer(e, handler); 70 | }); 71 | 72 | obj['_leaflet_touchstart' + id] = onDown; 73 | obj.addEventListener(POINTER_DOWN, onDown, false); 74 | 75 | // need to keep track of what pointers and how many are active to provide e.touches emulation 76 | if (!_pointerDocListener) { 77 | // we listen documentElement as any drags that end by moving the touch off the screen get fired there 78 | document.documentElement.addEventListener(POINTER_DOWN, _globalPointerDown, true); 79 | document.documentElement.addEventListener(POINTER_MOVE, _globalPointerMove, true); 80 | document.documentElement.addEventListener(POINTER_UP, _globalPointerUp, true); 81 | document.documentElement.addEventListener(POINTER_CANCEL, _globalPointerUp, true); 82 | 83 | _pointerDocListener = true; 84 | } 85 | } 86 | 87 | function _globalPointerDown(e) { 88 | _pointers[e.pointerId] = e; 89 | _pointersCount++; 90 | } 91 | 92 | function _globalPointerMove(e) { 93 | if (_pointers[e.pointerId]) { 94 | _pointers[e.pointerId] = e; 95 | } 96 | } 97 | 98 | function _globalPointerUp(e) { 99 | delete _pointers[e.pointerId]; 100 | _pointersCount--; 101 | } 102 | 103 | function _handlePointer(e, handler) { 104 | e.touches = []; 105 | for (var i in _pointers) { 106 | e.touches.push(_pointers[i]); 107 | } 108 | e.changedTouches = [e]; 109 | 110 | handler(e); 111 | } 112 | 113 | function _addPointerMove(obj, handler, id) { 114 | var onMove = function (e) { 115 | // don't fire touch moves when mouse isn't down 116 | if ((e.pointerType === e.MSPOINTER_TYPE_MOUSE || e.pointerType === 'mouse') && e.buttons === 0) { return; } 117 | 118 | _handlePointer(e, handler); 119 | }; 120 | 121 | obj['_leaflet_touchmove' + id] = onMove; 122 | obj.addEventListener(POINTER_MOVE, onMove, false); 123 | } 124 | 125 | function _addPointerEnd(obj, handler, id) { 126 | var onUp = function (e) { 127 | _handlePointer(e, handler); 128 | }; 129 | 130 | obj['_leaflet_touchend' + id] = onUp; 131 | obj.addEventListener(POINTER_UP, onUp, false); 132 | obj.addEventListener(POINTER_CANCEL, onUp, false); 133 | } 134 | 135 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/dom/PosAnimation.js: -------------------------------------------------------------------------------- 1 | import * as Util from '../core/Util'; 2 | import {Evented} from '../core/Events'; 3 | import * as DomUtil from '../dom/DomUtil'; 4 | 5 | 6 | /* 7 | * @class PosAnimation 8 | * @aka L.PosAnimation 9 | * @inherits Evented 10 | * Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9. 11 | * 12 | * @example 13 | * ```js 14 | * var fx = new L.PosAnimation(); 15 | * fx.run(el, [300, 500], 0.5); 16 | * ``` 17 | * 18 | * @constructor L.PosAnimation() 19 | * Creates a `PosAnimation` object. 20 | * 21 | */ 22 | 23 | export var PosAnimation = Evented.extend({ 24 | 25 | // @method run(el: HTMLElement, newPos: Point, duration?: Number, easeLinearity?: Number) 26 | // Run an animation of a given element to a new position, optionally setting 27 | // duration in seconds (`0.25` by default) and easing linearity factor (3rd 28 | // argument of the [cubic bezier curve](http://cubic-bezier.com/#0,0,.5,1), 29 | // `0.5` by default). 30 | run: function (el, newPos, duration, easeLinearity) { 31 | this.stop(); 32 | 33 | this._el = el; 34 | this._inProgress = true; 35 | this._duration = duration || 0.25; 36 | this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2); 37 | 38 | this._startPos = DomUtil.getPosition(el); 39 | this._offset = newPos.subtract(this._startPos); 40 | this._startTime = +new Date(); 41 | 42 | // @event start: Event 43 | // Fired when the animation starts 44 | this.fire('start'); 45 | 46 | this._animate(); 47 | }, 48 | 49 | // @method stop() 50 | // Stops the animation (if currently running). 51 | stop: function () { 52 | if (!this._inProgress) { return; } 53 | 54 | this._step(true); 55 | this._complete(); 56 | }, 57 | 58 | _animate: function () { 59 | // animation loop 60 | this._animId = Util.requestAnimFrame(this._animate, this); 61 | this._step(); 62 | }, 63 | 64 | _step: function (round) { 65 | var elapsed = (+new Date()) - this._startTime, 66 | duration = this._duration * 1000; 67 | 68 | if (elapsed < duration) { 69 | this._runFrame(this._easeOut(elapsed / duration), round); 70 | } else { 71 | this._runFrame(1); 72 | this._complete(); 73 | } 74 | }, 75 | 76 | _runFrame: function (progress, round) { 77 | var pos = this._startPos.add(this._offset.multiplyBy(progress)); 78 | if (round) { 79 | pos._round(); 80 | } 81 | DomUtil.setPosition(this._el, pos); 82 | 83 | // @event step: Event 84 | // Fired continuously during the animation. 85 | this.fire('step'); 86 | }, 87 | 88 | _complete: function () { 89 | Util.cancelAnimFrame(this._animId); 90 | 91 | this._inProgress = false; 92 | // @event end: Event 93 | // Fired when the animation ends. 94 | this.fire('end'); 95 | }, 96 | 97 | _easeOut: function (t) { 98 | return 1 - Math.pow(1 - t, this._easeOutPower); 99 | } 100 | }); 101 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/dom/index.js: -------------------------------------------------------------------------------- 1 | export {PosAnimation} from './PosAnimation'; 2 | 3 | import * as DomEvent from './DomEvent'; 4 | export {DomEvent}; 5 | 6 | import * as DomUtil from './DomUtil'; 7 | export {DomUtil}; 8 | 9 | export {Draggable} from './Draggable'; 10 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/LatLng.js: -------------------------------------------------------------------------------- 1 | import * as Util from '../core/Util'; 2 | import {Earth} from './crs/CRS.Earth'; 3 | import {toLatLngBounds} from './LatLngBounds'; 4 | 5 | /* @class LatLng 6 | * @aka L.LatLng 7 | * 8 | * Represents a geographical point with a certain latitude and longitude. 9 | * 10 | * @example 11 | * 12 | * ``` 13 | * var latlng = L.latLng(50.5, 30.5); 14 | * ``` 15 | * 16 | * All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent: 17 | * 18 | * ``` 19 | * map.panTo([50, 30]); 20 | * map.panTo({lon: 30, lat: 50}); 21 | * map.panTo({lat: 50, lng: 30}); 22 | * map.panTo(L.latLng(50, 30)); 23 | * ``` 24 | * 25 | * Note that `LatLng` does not inherit from Leaflet's `Class` object, 26 | * which means new classes can't inherit from it, and new methods 27 | * can't be added to it with the `include` function. 28 | */ 29 | 30 | export function LatLng(lat, lng, alt) { 31 | if (isNaN(lat) || isNaN(lng)) { 32 | throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')'); 33 | } 34 | 35 | // @property lat: Number 36 | // Latitude in degrees 37 | this.lat = +lat; 38 | 39 | // @property lng: Number 40 | // Longitude in degrees 41 | this.lng = +lng; 42 | 43 | // @property alt: Number 44 | // Altitude in meters (optional) 45 | if (alt !== undefined) { 46 | this.alt = +alt; 47 | } 48 | } 49 | 50 | LatLng.prototype = { 51 | // @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean 52 | // Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number. 53 | equals: function (obj, maxMargin) { 54 | if (!obj) { return false; } 55 | 56 | obj = toLatLng(obj); 57 | 58 | var margin = Math.max( 59 | Math.abs(this.lat - obj.lat), 60 | Math.abs(this.lng - obj.lng)); 61 | 62 | return margin <= (maxMargin === undefined ? 1.0E-9 : maxMargin); 63 | }, 64 | 65 | // @method toString(): String 66 | // Returns a string representation of the point (for debugging purposes). 67 | toString: function (precision) { 68 | return 'LatLng(' + 69 | Util.formatNum(this.lat, precision) + ', ' + 70 | Util.formatNum(this.lng, precision) + ')'; 71 | }, 72 | 73 | // @method distanceTo(otherLatLng: LatLng): Number 74 | // Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines). 75 | distanceTo: function (other) { 76 | return Earth.distance(this, toLatLng(other)); 77 | }, 78 | 79 | // @method wrap(): LatLng 80 | // Returns a new `LatLng` object with the longitude wrapped so it's always between -180 and +180 degrees. 81 | wrap: function () { 82 | return Earth.wrapLatLng(this); 83 | }, 84 | 85 | // @method toBounds(sizeInMeters: Number): LatLngBounds 86 | // Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`. 87 | toBounds: function (sizeInMeters) { 88 | var latAccuracy = 180 * sizeInMeters / 40075017, 89 | lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat); 90 | 91 | return toLatLngBounds( 92 | [this.lat - latAccuracy, this.lng - lngAccuracy], 93 | [this.lat + latAccuracy, this.lng + lngAccuracy]); 94 | }, 95 | 96 | clone: function () { 97 | return new LatLng(this.lat, this.lng, this.alt); 98 | } 99 | }; 100 | 101 | 102 | 103 | // @factory L.latLng(latitude: Number, longitude: Number, altitude?: Number): LatLng 104 | // Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude). 105 | 106 | // @alternative 107 | // @factory L.latLng(coords: Array): LatLng 108 | // Expects an array of the form `[Number, Number]` or `[Number, Number, Number]` instead. 109 | 110 | // @alternative 111 | // @factory L.latLng(coords: Object): LatLng 112 | // Expects an plain object of the form `{lat: Number, lng: Number}` or `{lat: Number, lng: Number, alt: Number}` instead. 113 | 114 | export function toLatLng(a, b, c) { 115 | if (a instanceof LatLng) { 116 | return a; 117 | } 118 | if (Util.isArray(a) && typeof a[0] !== 'object') { 119 | if (a.length === 3) { 120 | return new LatLng(a[0], a[1], a[2]); 121 | } 122 | if (a.length === 2) { 123 | return new LatLng(a[0], a[1]); 124 | } 125 | return null; 126 | } 127 | if (a === undefined || a === null) { 128 | return a; 129 | } 130 | if (typeof a === 'object' && 'lat' in a) { 131 | return new LatLng(a.lat, 'lng' in a ? a.lng : a.lon, a.alt); 132 | } 133 | if (b === undefined) { 134 | return null; 135 | } 136 | return new LatLng(a, b, c); 137 | } 138 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/crs/CRS.EPSG3395.js: -------------------------------------------------------------------------------- 1 | import {Earth} from './CRS.Earth'; 2 | import {Mercator} from '../projection/Projection.Mercator'; 3 | import {toTransformation} from '../../geometry/Transformation'; 4 | import * as Util from '../../core/Util'; 5 | 6 | /* 7 | * @namespace CRS 8 | * @crs L.CRS.EPSG3395 9 | * 10 | * Rarely used by some commercial tile providers. Uses Elliptical Mercator projection. 11 | */ 12 | export var EPSG3395 = Util.extend({}, Earth, { 13 | code: 'EPSG:3395', 14 | projection: Mercator, 15 | 16 | transformation: (function () { 17 | var scale = 0.5 / (Math.PI * Mercator.R); 18 | return toTransformation(scale, 0.5, -scale, 0.5); 19 | }()) 20 | }); 21 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/crs/CRS.EPSG3857.js: -------------------------------------------------------------------------------- 1 | import {Earth} from './CRS.Earth'; 2 | import {SphericalMercator} from '../projection/Projection.SphericalMercator'; 3 | import {toTransformation} from '../../geometry/Transformation'; 4 | import * as Util from '../../core/Util'; 5 | 6 | /* 7 | * @namespace CRS 8 | * @crs L.CRS.EPSG3857 9 | * 10 | * The most common CRS for online maps, used by almost all free and commercial 11 | * tile providers. Uses Spherical Mercator projection. Set in by default in 12 | * Map's `crs` option. 13 | */ 14 | 15 | export var EPSG3857 = Util.extend({}, Earth, { 16 | code: 'EPSG:3857', 17 | projection: SphericalMercator, 18 | 19 | transformation: (function () { 20 | var scale = 0.5 / (Math.PI * SphericalMercator.R); 21 | return toTransformation(scale, 0.5, -scale, 0.5); 22 | }()) 23 | }); 24 | 25 | export var EPSG900913 = Util.extend({}, EPSG3857, { 26 | code: 'EPSG:900913' 27 | }); 28 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/crs/CRS.EPSG4326.js: -------------------------------------------------------------------------------- 1 | import {Earth} from './CRS.Earth'; 2 | import {LonLat} from '../projection/Projection.LonLat'; 3 | import {toTransformation} from '../../geometry/Transformation'; 4 | import * as Util from '../../core/Util'; 5 | 6 | /* 7 | * @namespace CRS 8 | * @crs L.CRS.EPSG4326 9 | * 10 | * A common CRS among GIS enthusiasts. Uses simple Equirectangular projection. 11 | * 12 | * Leaflet 1.0.x complies with the [TMS coordinate scheme for EPSG:4326](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic), 13 | * which is a breaking change from 0.7.x behaviour. If you are using a `TileLayer` 14 | * with this CRS, ensure that there are two 256x256 pixel tiles covering the 15 | * whole earth at zoom level zero, and that the tile coordinate origin is (-180,+90), 16 | * or (-180,-90) for `TileLayer`s with [the `tms` option](#tilelayer-tms) set. 17 | */ 18 | 19 | export var EPSG4326 = Util.extend({}, Earth, { 20 | code: 'EPSG:4326', 21 | projection: LonLat, 22 | transformation: toTransformation(1 / 180, 1, -1 / 180, 0.5) 23 | }); 24 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/crs/CRS.Earth.js: -------------------------------------------------------------------------------- 1 | import {CRS} from './CRS'; 2 | import * as Util from '../../core/Util'; 3 | 4 | /* 5 | * @namespace CRS 6 | * @crs L.CRS.Earth 7 | * 8 | * Serves as the base for CRS that are global such that they cover the earth. 9 | * Can only be used as the base for other CRS and cannot be used directly, 10 | * since it does not have a `code`, `projection` or `transformation`. `distance()` returns 11 | * meters. 12 | */ 13 | 14 | export var Earth = Util.extend({}, CRS, { 15 | wrapLng: [-180, 180], 16 | 17 | // Mean Earth Radius, as recommended for use by 18 | // the International Union of Geodesy and Geophysics, 19 | // see http://rosettacode.org/wiki/Haversine_formula 20 | R: 6371000, 21 | 22 | // distance between two geographical points using spherical law of cosines approximation 23 | distance: function (latlng1, latlng2) { 24 | var rad = Math.PI / 180, 25 | lat1 = latlng1.lat * rad, 26 | lat2 = latlng2.lat * rad, 27 | sinDLat = Math.sin((latlng2.lat - latlng1.lat) * rad / 2), 28 | sinDLon = Math.sin((latlng2.lng - latlng1.lng) * rad / 2), 29 | a = sinDLat * sinDLat + Math.cos(lat1) * Math.cos(lat2) * sinDLon * sinDLon, 30 | c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 31 | return this.R * c; 32 | } 33 | }); 34 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/crs/CRS.Simple.js: -------------------------------------------------------------------------------- 1 | import {CRS} from './CRS'; 2 | import {LonLat} from '../projection/Projection.LonLat'; 3 | import {toTransformation} from '../../geometry/Transformation'; 4 | import * as Util from '../../core/Util'; 5 | 6 | /* 7 | * @namespace CRS 8 | * @crs L.CRS.Simple 9 | * 10 | * A simple CRS that maps longitude and latitude into `x` and `y` directly. 11 | * May be used for maps of flat surfaces (e.g. game maps). Note that the `y` 12 | * axis should still be inverted (going from bottom to top). `distance()` returns 13 | * simple euclidean distance. 14 | */ 15 | 16 | export var Simple = Util.extend({}, CRS, { 17 | projection: LonLat, 18 | transformation: toTransformation(1, 0, -1, 0), 19 | 20 | scale: function (zoom) { 21 | return Math.pow(2, zoom); 22 | }, 23 | 24 | zoom: function (scale) { 25 | return Math.log(scale) / Math.LN2; 26 | }, 27 | 28 | distance: function (latlng1, latlng2) { 29 | var dx = latlng2.lng - latlng1.lng, 30 | dy = latlng2.lat - latlng1.lat; 31 | 32 | return Math.sqrt(dx * dx + dy * dy); 33 | }, 34 | 35 | infinite: true 36 | }); 37 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/crs/index.js: -------------------------------------------------------------------------------- 1 | import {CRS} from './CRS'; 2 | import {Earth} from './CRS.Earth'; 3 | import {EPSG3395} from './CRS.EPSG3395'; 4 | import {EPSG3857, EPSG900913} from './CRS.EPSG3857'; 5 | import {EPSG4326} from './CRS.EPSG4326'; 6 | import {Simple} from './CRS.Simple'; 7 | 8 | CRS.Earth = Earth; 9 | CRS.EPSG3395 = EPSG3395; 10 | CRS.EPSG3857 = EPSG3857; 11 | CRS.EPSG900913 = EPSG900913; 12 | CRS.EPSG4326 = EPSG4326; 13 | CRS.Simple = Simple; 14 | 15 | export {CRS}; 16 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/index.js: -------------------------------------------------------------------------------- 1 | export {LatLng, toLatLng as latLng} from './LatLng'; 2 | export {LatLngBounds, toLatLngBounds as latLngBounds} from './LatLngBounds'; 3 | 4 | import * as Projection from './projection/index'; 5 | export {Projection}; 6 | 7 | export * from './crs/index'; 8 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/projection/Projection.LonLat.js: -------------------------------------------------------------------------------- 1 | import {LatLng} from '../LatLng'; 2 | import {Bounds} from '../../geometry/Bounds'; 3 | import {Point} from '../../geometry/Point'; 4 | 5 | /* 6 | * @namespace Projection 7 | * @section 8 | * Leaflet comes with a set of already defined Projections out of the box: 9 | * 10 | * @projection L.Projection.LonLat 11 | * 12 | * Equirectangular, or Plate Carree projection — the most simple projection, 13 | * mostly used by GIS enthusiasts. Directly maps `x` as longitude, and `y` as 14 | * latitude. Also suitable for flat worlds, e.g. game maps. Used by the 15 | * `EPSG:4326` and `Simple` CRS. 16 | */ 17 | 18 | export var LonLat = { 19 | project: function (latlng) { 20 | return new Point(latlng.lng, latlng.lat); 21 | }, 22 | 23 | unproject: function (point) { 24 | return new LatLng(point.y, point.x); 25 | }, 26 | 27 | bounds: new Bounds([-180, -90], [180, 90]) 28 | }; 29 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/projection/Projection.Mercator.js: -------------------------------------------------------------------------------- 1 | import {LatLng} from '../LatLng'; 2 | import {Bounds} from '../../geometry/Bounds'; 3 | import {Point} from '../../geometry/Point'; 4 | 5 | /* 6 | * @namespace Projection 7 | * @projection L.Projection.Mercator 8 | * 9 | * Elliptical Mercator projection — more complex than Spherical Mercator. Takes into account that Earth is a geoid, not a perfect sphere. Used by the EPSG:3395 CRS. 10 | */ 11 | 12 | export var Mercator = { 13 | R: 6378137, 14 | R_MINOR: 6356752.314245179, 15 | 16 | bounds: new Bounds([-20037508.34279, -15496570.73972], [20037508.34279, 18764656.23138]), 17 | 18 | project: function (latlng) { 19 | var d = Math.PI / 180, 20 | r = this.R, 21 | y = latlng.lat * d, 22 | tmp = this.R_MINOR / r, 23 | e = Math.sqrt(1 - tmp * tmp), 24 | con = e * Math.sin(y); 25 | 26 | var ts = Math.tan(Math.PI / 4 - y / 2) / Math.pow((1 - con) / (1 + con), e / 2); 27 | y = -r * Math.log(Math.max(ts, 1E-10)); 28 | 29 | return new Point(latlng.lng * d * r, y); 30 | }, 31 | 32 | unproject: function (point) { 33 | var d = 180 / Math.PI, 34 | r = this.R, 35 | tmp = this.R_MINOR / r, 36 | e = Math.sqrt(1 - tmp * tmp), 37 | ts = Math.exp(-point.y / r), 38 | phi = Math.PI / 2 - 2 * Math.atan(ts); 39 | 40 | for (var i = 0, dphi = 0.1, con; i < 15 && Math.abs(dphi) > 1e-7; i++) { 41 | con = e * Math.sin(phi); 42 | con = Math.pow((1 - con) / (1 + con), e / 2); 43 | dphi = Math.PI / 2 - 2 * Math.atan(ts * con) - phi; 44 | phi += dphi; 45 | } 46 | 47 | return new LatLng(phi * d, point.x * d / r); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/projection/Projection.SphericalMercator.js: -------------------------------------------------------------------------------- 1 | import {LatLng} from '../LatLng'; 2 | import {Bounds} from '../../geometry/Bounds'; 3 | import {Point} from '../../geometry/Point'; 4 | 5 | /* 6 | * @namespace Projection 7 | * @projection L.Projection.SphericalMercator 8 | * 9 | * Spherical Mercator projection — the most common projection for online maps, 10 | * used by almost all free and commercial tile providers. Assumes that Earth is 11 | * a sphere. Used by the `EPSG:3857` CRS. 12 | */ 13 | 14 | export var SphericalMercator = { 15 | 16 | R: 6378137, 17 | MAX_LATITUDE: 85.0511287798, 18 | 19 | project: function (latlng) { 20 | var d = Math.PI / 180, 21 | max = this.MAX_LATITUDE, 22 | lat = Math.max(Math.min(max, latlng.lat), -max), 23 | sin = Math.sin(lat * d); 24 | 25 | return new Point( 26 | this.R * latlng.lng * d, 27 | this.R * Math.log((1 + sin) / (1 - sin)) / 2); 28 | }, 29 | 30 | unproject: function (point) { 31 | var d = 180 / Math.PI; 32 | 33 | return new LatLng( 34 | (2 * Math.atan(Math.exp(point.y / this.R)) - (Math.PI / 2)) * d, 35 | point.x * d / this.R); 36 | }, 37 | 38 | bounds: (function () { 39 | var d = 6378137 * Math.PI; 40 | return new Bounds([-d, -d], [d, d]); 41 | })() 42 | }; 43 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geo/projection/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @class Projection 3 | 4 | * An object with methods for projecting geographical coordinates of the world onto 5 | * a flat surface (and back). See [Map projection](http://en.wikipedia.org/wiki/Map_projection). 6 | 7 | * @property bounds: Bounds 8 | * The bounds (specified in CRS units) where the projection is valid 9 | 10 | * @method project(latlng: LatLng): Point 11 | * Projects geographical coordinates into a 2D point. 12 | * Only accepts actual `L.LatLng` instances, not arrays. 13 | 14 | * @method unproject(point: Point): LatLng 15 | * The inverse of `project`. Projects a 2D point into a geographical location. 16 | * Only accepts actual `L.Point` instances, not arrays. 17 | 18 | * Note that the projection instances do not inherit from Leafet's `Class` object, 19 | * and can't be instantiated. Also, new classes can't inherit from them, 20 | * and methods can't be added to them with the `include` function. 21 | 22 | */ 23 | 24 | export {LonLat} from './Projection.LonLat'; 25 | export {Mercator} from './Projection.Mercator'; 26 | export {SphericalMercator} from './Projection.SphericalMercator'; 27 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geometry/PolyUtil.js: -------------------------------------------------------------------------------- 1 | import * as LineUtil from './LineUtil'; 2 | 3 | /* 4 | * @namespace PolyUtil 5 | * Various utility functions for polygon geometries. 6 | */ 7 | 8 | /* @function clipPolygon(points: Point[], bounds: Bounds, round?: Boolean): Point[] 9 | * Clips the polygon geometry defined by the given `points` by the given bounds (using the [Sutherland-Hodgman algorithm](https://en.wikipedia.org/wiki/Sutherland%E2%80%93Hodgman_algorithm)). 10 | * Used by Leaflet to only show polygon points that are on the screen or near, increasing 11 | * performance. Note that polygon points needs different algorithm for clipping 12 | * than polyline, so there's a separate method for it. 13 | */ 14 | export function clipPolygon(points, bounds, round) { 15 | var clippedPoints, 16 | edges = [1, 4, 2, 8], 17 | i, j, k, 18 | a, b, 19 | len, edge, p; 20 | 21 | for (i = 0, len = points.length; i < len; i++) { 22 | points[i]._code = LineUtil._getBitCode(points[i], bounds); 23 | } 24 | 25 | // for each edge (left, bottom, right, top) 26 | for (k = 0; k < 4; k++) { 27 | edge = edges[k]; 28 | clippedPoints = []; 29 | 30 | for (i = 0, len = points.length, j = len - 1; i < len; j = i++) { 31 | a = points[i]; 32 | b = points[j]; 33 | 34 | // if a is inside the clip window 35 | if (!(a._code & edge)) { 36 | // if b is outside the clip window (a->b goes out of screen) 37 | if (b._code & edge) { 38 | p = LineUtil._getEdgeIntersection(b, a, edge, bounds, round); 39 | p._code = LineUtil._getBitCode(p, bounds); 40 | clippedPoints.push(p); 41 | } 42 | clippedPoints.push(a); 43 | 44 | // else if b is inside the clip window (a->b enters the screen) 45 | } else if (!(b._code & edge)) { 46 | p = LineUtil._getEdgeIntersection(b, a, edge, bounds, round); 47 | p._code = LineUtil._getBitCode(p, bounds); 48 | clippedPoints.push(p); 49 | } 50 | } 51 | points = clippedPoints; 52 | } 53 | 54 | return points; 55 | } 56 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geometry/Transformation.js: -------------------------------------------------------------------------------- 1 | import {Point} from './Point'; 2 | import * as Util from '../core/Util'; 3 | 4 | /* 5 | * @class Transformation 6 | * @aka L.Transformation 7 | * 8 | * Represents an affine transformation: a set of coefficients `a`, `b`, `c`, `d` 9 | * for transforming a point of a form `(x, y)` into `(a*x + b, c*y + d)` and doing 10 | * the reverse. Used by Leaflet in its projections code. 11 | * 12 | * @example 13 | * 14 | * ```js 15 | * var transformation = L.transformation(2, 5, -1, 10), 16 | * p = L.point(1, 2), 17 | * p2 = transformation.transform(p), // L.point(7, 8) 18 | * p3 = transformation.untransform(p2); // L.point(1, 2) 19 | * ``` 20 | */ 21 | 22 | 23 | // factory new L.Transformation(a: Number, b: Number, c: Number, d: Number) 24 | // Creates a `Transformation` object with the given coefficients. 25 | export function Transformation(a, b, c, d) { 26 | if (Util.isArray(a)) { 27 | // use array properties 28 | this._a = a[0]; 29 | this._b = a[1]; 30 | this._c = a[2]; 31 | this._d = a[3]; 32 | return; 33 | } 34 | this._a = a; 35 | this._b = b; 36 | this._c = c; 37 | this._d = d; 38 | } 39 | 40 | Transformation.prototype = { 41 | // @method transform(point: Point, scale?: Number): Point 42 | // Returns a transformed point, optionally multiplied by the given scale. 43 | // Only accepts actual `L.Point` instances, not arrays. 44 | transform: function (point, scale) { // (Point, Number) -> Point 45 | return this._transform(point.clone(), scale); 46 | }, 47 | 48 | // destructive transform (faster) 49 | _transform: function (point, scale) { 50 | scale = scale || 1; 51 | point.x = scale * (this._a * point.x + this._b); 52 | point.y = scale * (this._c * point.y + this._d); 53 | return point; 54 | }, 55 | 56 | // @method untransform(point: Point, scale?: Number): Point 57 | // Returns the reverse transformation of the given point, optionally divided 58 | // by the given scale. Only accepts actual `L.Point` instances, not arrays. 59 | untransform: function (point, scale) { 60 | scale = scale || 1; 61 | return new Point( 62 | (point.x / scale - this._b) / this._a, 63 | (point.y / scale - this._d) / this._c); 64 | } 65 | }; 66 | 67 | // factory L.transformation(a: Number, b: Number, c: Number, d: Number) 68 | 69 | // @factory L.transformation(a: Number, b: Number, c: Number, d: Number) 70 | // Instantiates a Transformation object with the given coefficients. 71 | 72 | // @alternative 73 | // @factory L.transformation(coefficients: Array): Transformation 74 | // Expects an coefficients array of the form 75 | // `[a: Number, b: Number, c: Number, d: Number]`. 76 | 77 | export function toTransformation(a, b, c, d) { 78 | return new Transformation(a, b, c, d); 79 | } 80 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/geometry/index.js: -------------------------------------------------------------------------------- 1 | export {Point, toPoint as point} from './Point'; 2 | export {Bounds, toBounds as bounds} from './Bounds'; 3 | export {Transformation, toTransformation as transformation} from './Transformation'; 4 | 5 | import * as LineUtil from './LineUtil'; 6 | export {LineUtil}; 7 | import * as PolyUtil from './PolyUtil'; 8 | export {PolyUtil}; 9 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/images/layers.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/layer/FeatureGroup.js: -------------------------------------------------------------------------------- 1 | import {LayerGroup} from './LayerGroup'; 2 | import {LatLngBounds} from '../geo/LatLngBounds'; 3 | 4 | /* 5 | * @class FeatureGroup 6 | * @aka L.FeatureGroup 7 | * @inherits LayerGroup 8 | * 9 | * Extended `LayerGroup` that makes it easier to do the same thing to all its member layers: 10 | * * [`bindPopup`](#layer-bindpopup) binds a popup to all of the layers at once (likewise with [`bindTooltip`](#layer-bindtooltip)) 11 | * * Events are propagated to the `FeatureGroup`, so if the group has an event 12 | * handler, it will handle events from any of the layers. This includes mouse events 13 | * and custom events. 14 | * * Has `layeradd` and `layerremove` events 15 | * 16 | * @example 17 | * 18 | * ```js 19 | * L.featureGroup([marker1, marker2, polyline]) 20 | * .bindPopup('Hello world!') 21 | * .on('click', function() { alert('Clicked on a member of the group!'); }) 22 | * .addTo(map); 23 | * ``` 24 | */ 25 | 26 | export var FeatureGroup = LayerGroup.extend({ 27 | 28 | addLayer: function (layer) { 29 | if (this.hasLayer(layer)) { 30 | return this; 31 | } 32 | 33 | layer.addEventParent(this); 34 | 35 | LayerGroup.prototype.addLayer.call(this, layer); 36 | 37 | // @event layeradd: LayerEvent 38 | // Fired when a layer is added to this `FeatureGroup` 39 | return this.fire('layeradd', {layer: layer}); 40 | }, 41 | 42 | removeLayer: function (layer) { 43 | if (!this.hasLayer(layer)) { 44 | return this; 45 | } 46 | if (layer in this._layers) { 47 | layer = this._layers[layer]; 48 | } 49 | 50 | layer.removeEventParent(this); 51 | 52 | LayerGroup.prototype.removeLayer.call(this, layer); 53 | 54 | // @event layerremove: LayerEvent 55 | // Fired when a layer is removed from this `FeatureGroup` 56 | return this.fire('layerremove', {layer: layer}); 57 | }, 58 | 59 | // @method setStyle(style: Path options): this 60 | // Sets the given path options to each layer of the group that has a `setStyle` method. 61 | setStyle: function (style) { 62 | return this.invoke('setStyle', style); 63 | }, 64 | 65 | // @method bringToFront(): this 66 | // Brings the layer group to the top of all other layers 67 | bringToFront: function () { 68 | return this.invoke('bringToFront'); 69 | }, 70 | 71 | // @method bringToBack(): this 72 | // Brings the layer group to the back of all other layers 73 | bringToBack: function () { 74 | return this.invoke('bringToBack'); 75 | }, 76 | 77 | // @method getBounds(): LatLngBounds 78 | // Returns the LatLngBounds of the Feature Group (created from bounds and coordinates of its children). 79 | getBounds: function () { 80 | var bounds = new LatLngBounds(); 81 | 82 | for (var id in this._layers) { 83 | var layer = this._layers[id]; 84 | bounds.extend(layer.getBounds ? layer.getBounds() : layer.getLatLng()); 85 | } 86 | return bounds; 87 | } 88 | }); 89 | 90 | // @factory L.featureGroup(layers: Layer[]) 91 | // Create a feature group, optionally given an initial set of layers. 92 | export var featureGroup = function (layers) { 93 | return new FeatureGroup(layers); 94 | }; 95 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/layer/Layer.Interactive.leafdoc: -------------------------------------------------------------------------------- 1 | @class Interactive layer 2 | @inherits Layer 3 | 4 | Some `Layer`s can be made interactive - when the user interacts 5 | with such a layer, mouse events like `click` and `mouseover` can be handled. 6 | Use the [event handling methods](#evented-method) to handle these events. 7 | 8 | @option interactive: Boolean = true 9 | If `false`, the layer will not emit mouse events and will act as a part of the underlying map. 10 | 11 | @option bubblingMouseEvents: Boolean = true 12 | When `true`, a mouse event on this layer will trigger the same event on the map 13 | (unless [`L.DomEvent.stopPropagation`](#domevent-stoppropagation) is used). 14 | 15 | @section Mouse events 16 | 17 | @event click: MouseEvent 18 | Fired when the user clicks (or taps) the layer. 19 | 20 | @event dblclick: MouseEvent 21 | Fired when the user double-clicks (or double-taps) the layer. 22 | 23 | @event mousedown: MouseEvent 24 | Fired when the user pushes the mouse button on the layer. 25 | 26 | @event mouseup: MouseEvent 27 | Fired when the user releases the mouse button pushed on the layer. 28 | 29 | @event mouseover: MouseEvent 30 | Fired when the mouse enters the layer. 31 | 32 | @event mouseout: MouseEvent 33 | Fired when the mouse leaves the layer. 34 | 35 | @event contextmenu: MouseEvent 36 | Fired when the user right-clicks on the layer, prevents 37 | default browser context menu from showing if there are listeners on 38 | this event. Also fired on mobile when the user holds a single touch 39 | for a second (also called long press). 40 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/layer/LayerGroup.js: -------------------------------------------------------------------------------- 1 | 2 | import {Layer} from './Layer'; 3 | import * as Util from '../core/Util'; 4 | 5 | /* 6 | * @class LayerGroup 7 | * @aka L.LayerGroup 8 | * @inherits Layer 9 | * 10 | * Used to group several layers and handle them as one. If you add it to the map, 11 | * any layers added or removed from the group will be added/removed on the map as 12 | * well. Extends `Layer`. 13 | * 14 | * @example 15 | * 16 | * ```js 17 | * L.layerGroup([marker1, marker2]) 18 | * .addLayer(polyline) 19 | * .addTo(map); 20 | * ``` 21 | */ 22 | 23 | export var LayerGroup = Layer.extend({ 24 | 25 | initialize: function (layers, options) { 26 | Util.setOptions(this, options); 27 | 28 | this._layers = {}; 29 | 30 | var i, len; 31 | 32 | if (layers) { 33 | for (i = 0, len = layers.length; i < len; i++) { 34 | this.addLayer(layers[i]); 35 | } 36 | } 37 | }, 38 | 39 | // @method addLayer(layer: Layer): this 40 | // Adds the given layer to the group. 41 | addLayer: function (layer) { 42 | var id = this.getLayerId(layer); 43 | 44 | this._layers[id] = layer; 45 | 46 | if (this._map) { 47 | this._map.addLayer(layer); 48 | } 49 | 50 | return this; 51 | }, 52 | 53 | // @method removeLayer(layer: Layer): this 54 | // Removes the given layer from the group. 55 | // @alternative 56 | // @method removeLayer(id: Number): this 57 | // Removes the layer with the given internal ID from the group. 58 | removeLayer: function (layer) { 59 | var id = layer in this._layers ? layer : this.getLayerId(layer); 60 | 61 | if (this._map && this._layers[id]) { 62 | this._map.removeLayer(this._layers[id]); 63 | } 64 | 65 | delete this._layers[id]; 66 | 67 | return this; 68 | }, 69 | 70 | // @method hasLayer(layer: Layer): Boolean 71 | // Returns `true` if the given layer is currently added to the group. 72 | // @alternative 73 | // @method hasLayer(id: Number): Boolean 74 | // Returns `true` if the given internal ID is currently added to the group. 75 | hasLayer: function (layer) { 76 | return !!layer && (layer in this._layers || this.getLayerId(layer) in this._layers); 77 | }, 78 | 79 | // @method clearLayers(): this 80 | // Removes all the layers from the group. 81 | clearLayers: function () { 82 | return this.eachLayer(this.removeLayer, this); 83 | }, 84 | 85 | // @method invoke(methodName: String, …): this 86 | // Calls `methodName` on every layer contained in this group, passing any 87 | // additional parameters. Has no effect if the layers contained do not 88 | // implement `methodName`. 89 | invoke: function (methodName) { 90 | var args = Array.prototype.slice.call(arguments, 1), 91 | i, layer; 92 | 93 | for (i in this._layers) { 94 | layer = this._layers[i]; 95 | 96 | if (layer[methodName]) { 97 | layer[methodName].apply(layer, args); 98 | } 99 | } 100 | 101 | return this; 102 | }, 103 | 104 | onAdd: function (map) { 105 | this.eachLayer(map.addLayer, map); 106 | }, 107 | 108 | onRemove: function (map) { 109 | this.eachLayer(map.removeLayer, map); 110 | }, 111 | 112 | // @method eachLayer(fn: Function, context?: Object): this 113 | // Iterates over the layers of the group, optionally specifying context of the iterator function. 114 | // ```js 115 | // group.eachLayer(function (layer) { 116 | // layer.bindPopup('Hello'); 117 | // }); 118 | // ``` 119 | eachLayer: function (method, context) { 120 | for (var i in this._layers) { 121 | method.call(context, this._layers[i]); 122 | } 123 | return this; 124 | }, 125 | 126 | // @method getLayer(id: Number): Layer 127 | // Returns the layer with the given internal ID. 128 | getLayer: function (id) { 129 | return this._layers[id]; 130 | }, 131 | 132 | // @method getLayers(): Layer[] 133 | // Returns an array of all the layers added to the group. 134 | getLayers: function () { 135 | var layers = []; 136 | this.eachLayer(layers.push, layers); 137 | return layers; 138 | }, 139 | 140 | // @method setZIndex(zIndex: Number): this 141 | // Calls `setZIndex` on every layer contained in this group, passing the z-index. 142 | setZIndex: function (zIndex) { 143 | return this.invoke('setZIndex', zIndex); 144 | }, 145 | 146 | // @method getLayerId(layer: Layer): Number 147 | // Returns the internal ID for a layer 148 | getLayerId: function (layer) { 149 | return Util.stamp(layer); 150 | } 151 | }); 152 | 153 | 154 | // @factory L.layerGroup(layers?: Layer[], options?: Object) 155 | // Create a layer group, optionally given an initial set of layers and an `options` object. 156 | export var layerGroup = function (layers, options) { 157 | return new LayerGroup(layers, options); 158 | }; 159 | -------------------------------------------------------------------------------- /imax/static/leaflet/src/layer/VideoOverlay.js: -------------------------------------------------------------------------------- 1 | import {ImageOverlay} from './ImageOverlay'; 2 | import * as DomUtil from '../dom/DomUtil'; 3 | import * as Util from '../core/Util'; 4 | 5 | /* 6 | * @class VideoOverlay 7 | * @aka L.VideoOverlay 8 | * @inherits ImageOverlay 9 | * 10 | * Used to load and display a video player over specific bounds of the map. Extends `ImageOverlay`. 11 | * 12 | * A video overlay uses the [`