Add acars map page and show in-progress flights

This commit is contained in:
Nabeel Shahzad
2017-12-27 16:47:22 -06:00
parent a2e2a2a6a7
commit edca0644ff
103 changed files with 12380 additions and 827 deletions

View File

@@ -2,16 +2,15 @@
namespace App\Console\Commands;
use GuzzleHttp\Client;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Collection;
use GuzzleHttp\Client;
use App\Facades\Utils;
class AcarsReplay extends Command
{
protected $signature = 'phpvms:replay {files} {--manual} {--write-all}';
protected $signature = 'phpvms:replay {files} {--manual} {--write-all} {--no-submit}';
protected $description = 'Replay an ACARS file';
/**
@@ -64,11 +63,13 @@ class AcarsReplay extends Command
$pft = Utils::hoursToMinutes($flight->planned_hrsenroute,
$flight->planned_minenroute);
$flight_number = substr($flight->callsign, 3);
$response = $this->httpClient->post('/api/pirep/prefile', [
'json' => [
'airline_id' => 1,
'flight_number' => '6028',
'aircraft_id' => 1, # TODO: Lookup
'flight_number' => $flight_number,
'aircraft_id' => 1,
'dpt_airport_id' => $flight->planned_depairport,
'arr_airport_id' => $flight->planned_destairport,
'altitude' => $flight->planned_altitude,
@@ -84,6 +85,7 @@ class AcarsReplay extends Command
/**
* Mark the PIREP as filed
* @param $pirep_id
* @return mixed
*/
protected function filePirep($pirep_id)
{
@@ -187,8 +189,8 @@ class AcarsReplay extends Command
$this->postUpdate($pirep_id, $update);
# we're done
if($updates->count() === 0) {
# we're done and don't put the "no-submit" option
if($updates->count() === 0 && !$this->option('no-submit')) {
$this->filePirep($pirep_id);
}
})->filter(function ($updates, $idx) {

View File

@@ -56,13 +56,6 @@ class CreatePirepTables extends Migration
$table->timestamps();
});
Schema::create('pirep_events', function(Blueprint $table) {
$table->bigIncrements('id');
$table->string('pirep_id', 12);
$table->string('event', 64);
$table->dateTime('dt');
});
/*
* Financial tables/fields
*/

View File

@@ -3,41 +3,40 @@
namespace App\Http\Controllers\Api;
use Log;
use App\Models\Acars;
use Illuminate\Http\Request;
use App\Http\Controllers\AppBaseController;
use App\Models\Acars;
use App\Services\GeoService;
use App\Repositories\AcarsRepository;
use App\Repositories\PirepRepository;
use App\Http\Resources\Acars as AcarsResource;
class AcarsController extends AppBaseController
{
protected $acarsRepo, $pirepRepo;
protected $acarsRepo, $geoSvc, $pirepRepo;
public function __construct(
GeoService $geoSvc,
AcarsRepository $acarsRepo,
PirepRepository $pirepRepo
) {
$this->geoSvc = $geoSvc;
$this->acarsRepo = $acarsRepo;
$this->pirepRepo = $pirepRepo;
}
/**
* Return all of the flights (as points) in GeoJSON format
*/
public function index(Request $request)
{
/*PirepResource::withoutWrapping();
return new PirepResource($this->pirepRepo->find($id));*/
}
/**
* Return the current ACARS map data in GeoJSON format
* @param Request $request
*/
public function geojson(Request $request)
{
$pireps = $this->acarsRepo->getPositions();
$positions = $this->geoSvc->getFeatureForLiveFlights($pireps);
return response(json_encode($positions), 200, [
'Content-type' => 'application/json'
]);
}
}

View File

@@ -181,4 +181,13 @@ class PirepController extends AppBaseController
AcarsResource::withoutWrapping();
return new AcarsResource($update);
}
/**
* @param $id
* @param Request $request
*/
public function geojson($id, Request $request)
{
$pirep = $this->pirepRepo->find($id);
}
}

View File

@@ -0,0 +1,37 @@
<?php
namespace App\Http\Controllers\Frontend;
use App\Models\Pirep;
use App\Repositories\AcarsRepository;
use App\Services\GeoService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class AcarsController extends Controller
{
private $acarsRepo, $geoSvc;
public function __construct(
AcarsRepository $acarsRepo,
GeoService $geoSvc
) {
$this->acarsRepo = $acarsRepo;
$this->geoSvc = $geoSvc;
}
/**
*
*/
public function index(Request $request)
{
$pireps = $this->acarsRepo->getPositions();
$positions = $this->geoSvc->getFeatureForLiveFlights($pireps);
return $this->view('acars.index',[
'pireps' => $pireps,
'positions' => $positions,
]);
}
}

View File

@@ -93,7 +93,8 @@ class Pirep extends BaseModel
public function acars()
{
return $this->hasMany('App\Models\Acars', 'pirep_id');
return $this->hasMany('App\Models\Acars', 'pirep_id')
->orderBy('created_at', 'desc');
}
public function aircraft()
@@ -118,12 +119,8 @@ class Pirep extends BaseModel
public function comments()
{
return $this->hasMany('App\Models\PirepComment', 'pirep_id');
}
public function events()
{
return $this->hasMany('App\Models\PirepEvent', 'pirep_id');
return $this->hasMany('App\Models\PirepComment', 'pirep_id')
->orderBy('created_at', 'desc');
}
public function fields()
@@ -141,14 +138,17 @@ class Pirep extends BaseModel
return $this->user();
}
public function route()
/**
* Relationship that holds the current position, but limits the ACARS
* relationship to only one row (the latest), to prevent an N+! problem
*/
public function position()
{
return [];
return $this->hasOne('App\Models\Acars', 'pirep_id')->latest();
}
public function user()
{
return $this->belongsTo('App\Models\User', 'user_id');
}
}

View File

@@ -1,45 +0,0 @@
<?php
namespace App\Models;
/**
* Class PirepEvent
*
* @package App\Models
*/
class PirepEvent extends BaseModel
{
public $table = 'pirep_fields';
public $fillable
= [
'name',
'value',
];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'name' => 'string',
'required' => 'integer',
];
/**
* Validation rules
*
* @var array
*/
public static $rules
= [
'name' => 'required',
];
public function pirep()
{
return $this->belongsTo('App\Models\Pirep', 'pirep_id');
}
}

View File

@@ -66,10 +66,7 @@ class RouteServiceProvider extends ServiceProvider
protected function mapApiRoutes()
{
Route::group([
'middleware' => [
'api',
'api.auth',
],
'middleware' => ['api'],
'namespace' => $this->namespace."\\Api",
'prefix' => 'api',
'as' => 'api.',

View File

@@ -3,12 +3,16 @@
namespace App\Repositories;
use App\Models\Acars;
use App\Models\Pirep;
use App\Models\Enums\PirepState;
use App\Models\Enums\PirepStatus;
use App\Repositories\Traits\CacheableRepository;
use Prettus\Repository\Contracts\CacheableInterface;
class AcarsRepository extends BaseRepository implements CacheableInterface
class AcarsRepository extends BaseRepository //implements CacheableInterface
{
use CacheableRepository;
//use CacheableRepository;
public function model()
{
@@ -19,4 +23,30 @@ class AcarsRepository extends BaseRepository implements CacheableInterface
{
return $this->findWhere(['pirep_id' => $pirep_id]);
}
/**
* Get all of the PIREPS that are in-progress, and then
* get the latest update for those flights
* @return Pirep
*/
public function getPositions()
{
return Pirep::with(['airline', 'position'])
->where(['state' => PirepState::IN_PROGRESS])
->get();
/*return Pirep::with(['acars' => function($q) {
return $q->limit(1);
}])->where(['state' => PirepState::IN_PROGRESS])->get();*/
}
/**
* @return $this
*/
public function getAllAcarsPoints()
{
return Pirep::with('acars')->where([
'state' => PirepState::IN_PROGRESS
]);
}
}

View File

@@ -1,28 +1,28 @@
<?php
use Illuminate\Http\Request;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::group([], function ()
/**
* public routes
*/
Route::group([], function()
{
Route::match(['get'], 'status', 'BaseController@status');
Route::match(['get'], 'airports/{id}', 'AirportController@get');
Route::match(['get'], 'airports/{id}/lookup', 'AirportController@lookup');
Route::match(['get'], 'acars', 'AcarsController@index');
Route::match(['get'], 'flights/search', 'FlightController@search');
Route::match(['get'], 'flights/{id}', 'FlightController@get');
Route::match(['post'], 'pirep/{id}/geojson', 'PirepController@file');
Route::match(['get'], 'status', 'BaseController@status');
});
/**
* these need to be authenticated with a user's API key
*/
Route::group(['middleware' => ['api.auth']], function ()
{
Route::match(['get'], 'airports/{id}', 'AirportController@get');
Route::match(['get'], 'airports/{id}/lookup', 'AirportController@lookup');
Route::match(['get'], 'pirep/{id}', 'PirepController@get');
Route::match(['post'], 'pirep/prefile', 'PirepController@prefile');
Route::match(['post'], 'pirep/{id}/file', 'PirepController@file');
@@ -30,9 +30,6 @@ Route::group([], function ()
Route::match(['get'], 'pirep/{id}/acars', 'PirepController@acars_get');
Route::match(['post'], 'pirep/{id}/acars', 'PirepController@acars_store');
Route::match(['get'], 'acars', 'AcarsController@index');
Route::match(['get'], 'acars/geojson', 'AcarsController@geojson');
# This is the info of the user whose token is in use
Route::match(['get'], 'user', 'UserController@index');
#Route::match(['get'], 'user/bids', 'UserController@index');

View File

@@ -8,8 +8,10 @@ Route::get('/', 'HomeController@index')->name('home');
Route::group([
'namespace' => 'Frontend', 'prefix' => '', 'as' => 'frontend.'
], function() {
Route::get('/r/{id}', 'PirepController@show')->name('pirep.show.public');
Route::get('/p/{id}', 'ProfileController@show')->name('profile.show.public');
Route::get('r/{id}', 'PirepController@show')->name('pirep.show.public');
Route::get('p/{id}', 'ProfileController@show')->name('profile.show.public');
Route::get('livemap', 'AcarsController@index')->name('livemap.public');
});
/**
@@ -22,7 +24,7 @@ Route::group([
Route::resource('dashboard', 'DashboardController');
Route::get('flights/search', 'FlightController@search')->name('flights.search');
Route::match(['post'], '/flights/save', 'FlightController@save')->name('flights.save');
Route::post('flights/save', 'FlightController@save')->name('flights.save');
Route::resource('flights', 'FlightController');
Route::resource('profile', 'ProfileController');

View File

@@ -139,6 +139,32 @@ class GeoService extends BaseService
return $coords;
}
/**
* Determine the center point between two sets of coordinates
* @param $latA
* @param $lonA
* @param $latB
* @param $lonB
* @return array
* @throws \League\Geotools\Exception\InvalidArgumentException
*/
public function getCenter($latA, $lonA, $latB, $lonB)
{
$geotools = new Geotools();
$coordA = new Coordinate([$latA, $lonA]);
$coordB = new Coordinate([$latB, $lonB]);
$vertex = $geotools->vertex()->setFrom($coordA)->setTo($coordB);
$middlePoint = $vertex->middle();
$center = [
$middlePoint->getLatitude(),
$middlePoint->getLongitude()
];
return $center;
}
/**
* Read an array/relationship of ACARS model points
* @param Pirep $pirep
@@ -171,12 +197,42 @@ class GeoService extends BaseService
# Convert to a feature
$route_line = new Feature(new LineString($route_line), [], 1);
# TODO: Draw the plane icon from the last point
return [
'line' => new FeatureCollection([$route_line]),
'points' => new FeatureCollection($route_points)
];
}
/**
* Return a single feature point for the
*/
public function getFeatureForLiveFlights($pireps)
{
$flight_points = [];
/**
* @var Pirep $pirep
*/
foreach($pireps as $pirep) {
/**
* @var $point \App\Models\Acars
*/
$point = $pirep->position;
$flight_points[] = new Feature(
new Point([$point->lon, $point->lat]), [
'gs' => $point->gs,
'alt' => $point->altitude,
'heading' => $point->heading ?: 0,
'popup' => 'Flight: ' . $pirep->ident,
]);
}
return new FeatureCollection($flight_points);
}
/**
* Return a FeatureCollection GeoJSON object
* @param Flight $flight
@@ -300,30 +356,4 @@ class GeoService extends BaseService
'actual_route_points' => $actual_route['points'],
];
}
/**
* Determine the center point between two sets of coordinates
* @param $latA
* @param $lonA
* @param $latB
* @param $lonB
* @return array
* @throws \League\Geotools\Exception\InvalidArgumentException
*/
public function getCenter($latA, $lonA, $latB, $lonB)
{
$geotools = new Geotools();
$coordA = new Coordinate([$latA, $lonA]);
$coordB = new Coordinate([$latB, $lonB]);
$vertex = $geotools->vertex()->setFrom($coordA)->setTo($coordB);
$middlePoint = $vertex->middle();
$center = [
$middlePoint->getLatitude(),
$middlePoint->getLongitude()
];
return $center;
}
}

View File

@@ -10,7 +10,9 @@
"icheck": "1.0.2",
"popper.js": "^1.12.0",
"rivets": "0.9.6",
"select2": "4.0.3"
"select2": "4.0.3",
"leaflet": "1.2.0",
"leaflet-ajax": "2.1.0"
},
"license": "MIT",
"homepage": "https://github.com/nabeelio/phpvms",

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
public/assets/img/acars/atc.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

View File

@@ -9,6 +9,7 @@ const phpvms = (function() {
set_marker: false,
});
let feature_groups = [];
/*var openaip_airspace_labels = new L.TileLayer.WMS(
"http://{s}.tile.maps.openaip.net/geowebcache/service/wms", {
maxZoom: 14,
@@ -31,7 +32,9 @@ const phpvms = (function() {
transparent: true
});
const openaip_cached_basemap = new L.TileLayer("http://{s}.tile.maps.openaip.net/geowebcache/service/tms/1.0.0/openaip_basemap@EPSG%3A900913@png/{z}/{x}/{y}.png", {
feature_groups.push(opencyclemap_phys_osm);
/*const openaip_cached_basemap = new L.TileLayer("http://{s}.tile.maps.openaip.net/geowebcache/service/tms/1.0.0/openaip_basemap@EPSG%3A900913@png/{z}/{x}/{y}.png", {
maxZoom: 14,
minZoom: 4,
tms: true,
@@ -41,7 +44,10 @@ const phpvms = (function() {
transparent: true
});
const openaip_basemap_phys_osm = L.featureGroup([opencyclemap_phys_osm, openaip_cached_basemap]);
feature_groups.push(openaip_cached_basemap);
*/
const openaip_basemap_phys_osm = L.featureGroup(feature_groups);
let map = L.map('map', {
layers: [openaip_basemap_phys_osm],
@@ -75,7 +81,13 @@ const phpvms = (function() {
layer.bindPopup(popup_html);
};
const pointToLayer = function (feature, latlng) {
/**
* Show each point as a marker
* @param feature
* @param latlng
* @returns {*}
*/
const pointToLayer = (feature, latlng) => {
return L.circleMarker(latlng, {
radius: 12,
fillColor: "#ff7800",
@@ -116,7 +128,6 @@ const phpvms = (function() {
// Draw the route points after
if (opts.route_points !== null) {
console.log(opts.route_points);
let route_points = L.geoJSON(opts.route_points, {
onEachFeature: onFeaturePointClick,
pointToLayer: pointToLayer,
@@ -196,20 +207,66 @@ const phpvms = (function() {
* @private
*/
const _render_live_map = (opts) => {
opts = _.defaults(opts, {
route_points: null,
planned_route_line: null,
actual_route_points: null,
actual_route_line: null,
update_uri: '/api/acars',
positions: null,
render_elem: 'map',
aircraft_icon: '/assets/img/acars/aircraft.png',
});
let map = draw_base_map(opts);
let flightPositions = null;
const map = draw_base_map(opts);
const aircraftIcon = L.icon({
iconUrl: opts.aircraft_icon,
iconSize: [48, 48],
iconAnchor: [0, 0],
popupAnchor: [-3, -76],
});
const updateMap = () => {
console.log('reloading flights from acars...');
/**
* AJAX UPDATE
*/
let flights = $.ajax({
url: opts.update_uri,
dataType: "json",
error: console.log
});
$.when(flights).done(function (flightGeoJson) {
if (flightPositions !== null) {
flightPositions.clearLayers();
}
flightPositions = L.geoJSON(flightGeoJson, {
onEachFeature: onFeaturePointClick,
pointToLayer: function(feature, latlon) {
return L.marker(latlon, {
icon: aircraftIcon,
rotationAngle: feature.properties.heading
});
}
});
flightPositions.addTo(map);
map.fitBounds(flightPositions.getBounds());
});
};
updateMap();
setTimeout(updateMap, 10000);
};
return {
render_route_map: _render_route_map,
render_airspace_map: _render_airspace_map,
render_live_map: _render_live_map,
render_route_map: _render_route_map,
}
})();

View File

@@ -0,0 +1,32 @@
{
"name": "leaflet-ajax",
"version": "2.1.0",
"homepage": "https://github.com/calvinmetcalf/leaflet-ajax",
"authors": [
"Calvin Metcalf <calvin.metcalf@gmail.com>"
],
"description": "AJAX and JSONP in Leaflet",
"main": "dist/leaflet.ajax.js",
"keywords": [
"leaflet",
"ajax",
"jsonp"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"_release": "2.1.0",
"_resolution": {
"type": "version",
"tag": "v2.1.0",
"commit": "26f31a90c684dd54a06feee7d56fadd9b020d4cc"
},
"_source": "https://github.com/calvinmetcalf/leaflet-ajax.git",
"_target": "2.1.0",
"_originalSource": "leaflet-ajax"
}

View File

@@ -0,0 +1,78 @@
leaflet-ajax
===========
[![js-semistandard-style](https://img.shields.io/badge/code%20style-semistandard-brightgreen.svg?style=flat-square)](https://github.com/Flet/semistandard)
Allows you to call JSON via an Ajax call with a jsonp fallback.
```javascript
var geojsonLayer = new L.GeoJSON.AJAX("geojson.json");
```
for jsonp add the option "dataType" and set it to "jsonp"
``` javascript
var geojsonLayer = L.geoJson.ajax("http:webhost.fake/geojson.jsonp",{dataType:"jsonp"});
```
Note that data starts to download when the layer is created NOT when its added to the map in order to get a head start.
You may pass either a url string or an array of url strings if you want to download multiple things (handy
if your downloading data from an ESRI based thing which will have separate line, point, and poly features).
As you see you can also use lower case methods without creating new objects
For weirder jsonp you can set "callbackParam" for if you need to change the name of the callback parameter to something besides "callback", e.g. [Mapquest Nominative Open](http://open.mapquestapi.com/nominatim/) uses "json_callback" instead of "callback".
If you want to be able to load stuff from the file system (with appropriate custom flags set) set local to true.
If you want to set headers to the XMLHttpRequest set the 'headers' option equal to an object.
Gives off three events `data:loading`, `data:progress` and `data:loaded`.
- `data:loading` fires before we start downloading things, note if the constructor is given a url it won't wait to be added to the map
to start downloading the data, but it does do an async wait so you have time to add a listener to it (and so [leaflet.spin](https://github.com/makinacorpus/Leaflet.Spin) will work with it).
- `data:progress` is called each time a file is downloaded and passes the downloaded geojson as event data.
- `data:loaded` is called when all files have downloaded, this is mainly different from `data:progress` when you are downloading multiple things.
You can also add a middleware function which is called after you download the data but before you add it to leaflet:
```javascript
var geojsonLayer = L.geoJson.ajax("route/to/esri.json",{
middleware:function(data){
return esri2geoOrSomething(json);
}
});
```
addUrl does not clear the current layers but adds to the current one, e.g.:
```javascript
var geojsonLayer = L.geoJson.ajax("data.json");
geojsonLayer.addUrl("data2.json");//we now have 2 layers
geojsonLayer.refresh();//redownload the most recent layer
geojsonLayer.refresh("new1.json");//add a new layer replacing whatever is there
```
last but now least we can refilter layers without re adding them
```javascript
var geojsonLayer = L.geoJson.ajax("data.json");
geojsonLayer.refilter(function(feature){
return feature.properties.key === values;
});
```
Behind the scenes are two new classes L.Util.ajax = function (url) for same origin requests and L.Util.jsonp = function (url,options) cross origin ones. Both return promises, which have an additional abort method that will abort the ajax request.
```js
L.Util.ajax("url/same/origin.xml").then(function(data){
doStuff(data);
});
//or
L.Util.jsonp("http://www.dif.ori/gin").then(function(data){
doStuff(data);
});
```
In related news `L.Util.Promise` is now a constructor for a promise, it takes one argument, a resolver function.
Some of the jsonp code inspired by/taken from [this interesting looking plugin](https://github.com/stefanocudini/leaflet-search) that I have failed to make heads nor tails of (the plugin, not the jsonp code)

View File

@@ -0,0 +1,23 @@
{
"name": "leaflet-ajax",
"version": "2.1.0",
"homepage": "https://github.com/calvinmetcalf/leaflet-ajax",
"authors": [
"Calvin Metcalf <calvin.metcalf@gmail.com>"
],
"description": "AJAX and JSONP in Leaflet",
"main": "dist/leaflet.ajax.js",
"keywords": [
"leaflet",
"ajax",
"jsonp"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}

View File

@@ -0,0 +1,575 @@
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
var immediate = require('immediate');
/* istanbul ignore next */
function INTERNAL() {}
var handlers = {};
var REJECTED = ['REJECTED'];
var FULFILLED = ['FULFILLED'];
var PENDING = ['PENDING'];
module.exports = exports = Promise;
function Promise(resolver) {
if (typeof resolver !== 'function') {
throw new TypeError('resolver must be a function');
}
this.state = PENDING;
this.queue = [];
this.outcome = void 0;
if (resolver !== INTERNAL) {
safelyResolveThenable(this, resolver);
}
}
Promise.prototype["catch"] = function (onRejected) {
return this.then(null, onRejected);
};
Promise.prototype.then = function (onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function' && this.state === FULFILLED ||
typeof onRejected !== 'function' && this.state === REJECTED) {
return this;
}
var promise = new this.constructor(INTERNAL);
if (this.state !== PENDING) {
var resolver = this.state === FULFILLED ? onFulfilled : onRejected;
unwrap(promise, resolver, this.outcome);
} else {
this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
}
return promise;
};
function QueueItem(promise, onFulfilled, onRejected) {
this.promise = promise;
if (typeof onFulfilled === 'function') {
this.onFulfilled = onFulfilled;
this.callFulfilled = this.otherCallFulfilled;
}
if (typeof onRejected === 'function') {
this.onRejected = onRejected;
this.callRejected = this.otherCallRejected;
}
}
QueueItem.prototype.callFulfilled = function (value) {
handlers.resolve(this.promise, value);
};
QueueItem.prototype.otherCallFulfilled = function (value) {
unwrap(this.promise, this.onFulfilled, value);
};
QueueItem.prototype.callRejected = function (value) {
handlers.reject(this.promise, value);
};
QueueItem.prototype.otherCallRejected = function (value) {
unwrap(this.promise, this.onRejected, value);
};
function unwrap(promise, func, value) {
immediate(function () {
var returnValue;
try {
returnValue = func(value);
} catch (e) {
return handlers.reject(promise, e);
}
if (returnValue === promise) {
handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));
} else {
handlers.resolve(promise, returnValue);
}
});
}
handlers.resolve = function (self, value) {
var result = tryCatch(getThen, value);
if (result.status === 'error') {
return handlers.reject(self, result.value);
}
var thenable = result.value;
if (thenable) {
safelyResolveThenable(self, thenable);
} else {
self.state = FULFILLED;
self.outcome = value;
var i = -1;
var len = self.queue.length;
while (++i < len) {
self.queue[i].callFulfilled(value);
}
}
return self;
};
handlers.reject = function (self, error) {
self.state = REJECTED;
self.outcome = error;
var i = -1;
var len = self.queue.length;
while (++i < len) {
self.queue[i].callRejected(error);
}
return self;
};
function getThen(obj) {
// Make sure we only access the accessor once as required by the spec
var then = obj && obj.then;
if (obj && typeof obj === 'object' && typeof then === 'function') {
return function appyThen() {
then.apply(obj, arguments);
};
}
}
function safelyResolveThenable(self, thenable) {
// Either fulfill, reject or reject with error
var called = false;
function onError(value) {
if (called) {
return;
}
called = true;
handlers.reject(self, value);
}
function onSuccess(value) {
if (called) {
return;
}
called = true;
handlers.resolve(self, value);
}
function tryToUnwrap() {
thenable(onSuccess, onError);
}
var result = tryCatch(tryToUnwrap);
if (result.status === 'error') {
onError(result.value);
}
}
function tryCatch(func, value) {
var out = {};
try {
out.value = func(value);
out.status = 'success';
} catch (e) {
out.status = 'error';
out.value = e;
}
return out;
}
exports.resolve = resolve;
function resolve(value) {
if (value instanceof this) {
return value;
}
return handlers.resolve(new this(INTERNAL), value);
}
exports.reject = reject;
function reject(reason) {
var promise = new this(INTERNAL);
return handlers.reject(promise, reason);
}
exports.all = all;
function all(iterable) {
var self = this;
if (Object.prototype.toString.call(iterable) !== '[object Array]') {
return this.reject(new TypeError('must be an array'));
}
var len = iterable.length;
var called = false;
if (!len) {
return this.resolve([]);
}
var values = new Array(len);
var resolved = 0;
var i = -1;
var promise = new this(INTERNAL);
while (++i < len) {
allResolver(iterable[i], i);
}
return promise;
function allResolver(value, i) {
self.resolve(value).then(resolveFromAll, function (error) {
if (!called) {
called = true;
handlers.reject(promise, error);
}
});
function resolveFromAll(outValue) {
values[i] = outValue;
if (++resolved === len && !called) {
called = true;
handlers.resolve(promise, values);
}
}
}
}
exports.race = race;
function race(iterable) {
var self = this;
if (Object.prototype.toString.call(iterable) !== '[object Array]') {
return this.reject(new TypeError('must be an array'));
}
var len = iterable.length;
var called = false;
if (!len) {
return this.resolve([]);
}
var i = -1;
var promise = new this(INTERNAL);
while (++i < len) {
resolver(iterable[i]);
}
return promise;
function resolver(value) {
self.resolve(value).then(function (response) {
if (!called) {
called = true;
handlers.resolve(promise, response);
}
}, function (error) {
if (!called) {
called = true;
handlers.reject(promise, error);
}
});
}
}
},{"immediate":2}],2:[function(require,module,exports){
(function (global){
'use strict';
var Mutation = global.MutationObserver || global.WebKitMutationObserver;
var scheduleDrain;
{
if (Mutation) {
var called = 0;
var observer = new Mutation(nextTick);
var element = global.document.createTextNode('');
observer.observe(element, {
characterData: true
});
scheduleDrain = function () {
element.data = (called = ++called % 2);
};
} else if (!global.setImmediate && typeof global.MessageChannel !== 'undefined') {
var channel = new global.MessageChannel();
channel.port1.onmessage = nextTick;
scheduleDrain = function () {
channel.port2.postMessage(0);
};
} else if ('document' in global && 'onreadystatechange' in global.document.createElement('script')) {
scheduleDrain = function () {
// Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
// into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
var scriptEl = global.document.createElement('script');
scriptEl.onreadystatechange = function () {
nextTick();
scriptEl.onreadystatechange = null;
scriptEl.parentNode.removeChild(scriptEl);
scriptEl = null;
};
global.document.documentElement.appendChild(scriptEl);
};
} else {
scheduleDrain = function () {
setTimeout(nextTick, 0);
};
}
}
var draining;
var queue = [];
//named nextTick for less confusing stack traces
function nextTick() {
draining = true;
var i, oldQueue;
var len = queue.length;
while (len) {
oldQueue = queue;
queue = [];
i = -1;
while (++i < len) {
oldQueue[i]();
}
len = queue.length;
}
draining = false;
}
module.exports = immediate;
function immediate(task) {
if (queue.push(task) === 1 && !draining) {
scheduleDrain();
}
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],3:[function(require,module,exports){
(function (global){
'use strict';
var jsonp = require('./jsonp');
var Promise = require('lie');
module.exports = function (url, options) {
options = options || {};
if (options.jsonp) {
return jsonp(url, options);
}
var request;
var cancel;
var out = new Promise(function (resolve, reject) {
cancel = reject;
if (global.XMLHttpRequest === undefined) {
reject('XMLHttpRequest is not supported');
}
var response;
request = new global.XMLHttpRequest();
request.open('GET', url);
if (options.headers) {
Object.keys(options.headers).forEach(function (key) {
request.setRequestHeader(key, options.headers[key]);
});
}
request.onreadystatechange = function () {
if (request.readyState === 4) {
if ((request.status < 400 && options.local) || request.status === 200) {
if (global.JSON) {
response = JSON.parse(request.responseText);
} else {
reject(new Error('JSON is not supported'));
}
resolve(response);
} else {
if (!request.status) {
reject('Attempted cross origin request without CORS enabled');
} else {
reject(request.statusText);
}
}
}
};
request.send();
});
out.catch(function (reason) {
request.abort();
return reason;
});
out.abort = cancel;
return out;
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./jsonp":5,"lie":1}],4:[function(require,module,exports){
(function (global){
'use strict';
var L = global.L || require('leaflet');
var Promise = require('lie');
var ajax = require('./ajax');
L.GeoJSON.AJAX = L.GeoJSON.extend({
defaultAJAXparams: {
dataType: 'json',
callbackParam: 'callback',
local: false,
middleware: function (f) {
return f;
}
},
initialize: function (url, options) {
this.urls = [];
if (url) {
if (typeof url === 'string') {
this.urls.push(url);
} else if (typeof url.pop === 'function') {
this.urls = this.urls.concat(url);
} else {
options = url;
url = undefined;
}
}
var ajaxParams = L.Util.extend({}, this.defaultAJAXparams);
for (var i in options) {
if (this.defaultAJAXparams.hasOwnProperty(i)) {
ajaxParams[i] = options[i];
}
}
this.ajaxParams = ajaxParams;
this._layers = {};
L.Util.setOptions(this, options);
this.on('data:loaded', function () {
if (this.filter) {
this.refilter(this.filter);
}
}, this);
var self = this;
if (this.urls.length > 0) {
new Promise(function (resolve) {
resolve();
}).then(function () {
self.addUrl();
});
}
},
clearLayers: function () {
this.urls = [];
L.GeoJSON.prototype.clearLayers.call(this);
return this;
},
addUrl: function (url) {
var self = this;
if (url) {
if (typeof url === 'string') {
self.urls.push(url);
} else if (typeof url.pop === 'function') {
self.urls = self.urls.concat(url);
}
}
var loading = self.urls.length;
var done = 0;
self.fire('data:loading');
self.urls.forEach(function (url) {
if (self.ajaxParams.dataType.toLowerCase() === 'json') {
ajax(url, self.ajaxParams).then(function (d) {
var data = self.ajaxParams.middleware(d);
self.addData(data);
self.fire('data:progress', data);
}, function (err) {
self.fire('data:progress', {
error: err
});
});
} else if (self.ajaxParams.dataType.toLowerCase() === 'jsonp') {
L.Util.jsonp(url, self.ajaxParams).then(function (d) {
var data = self.ajaxParams.middleware(d);
self.addData(data);
self.fire('data:progress', data);
}, function (err) {
self.fire('data:progress', {
error: err
});
});
}
});
self.on('data:progress', function () {
if (++done === loading) {
self.fire('data:loaded');
}
});
},
refresh: function (url) {
url = url || this.urls;
this.clearLayers();
this.addUrl(url);
},
refilter: function (func) {
if (typeof func !== 'function') {
this.filter = false;
this.eachLayer(function (a) {
a.setStyle({
stroke: true,
clickable: true
});
});
} else {
this.filter = func;
this.eachLayer(function (a) {
if (func(a.feature)) {
a.setStyle({
stroke: true,
clickable: true
});
} else {
a.setStyle({
stroke: false,
clickable: false
});
}
});
}
}
});
L.Util.Promise = Promise;
L.Util.ajax = ajax;
L.Util.jsonp = require('./jsonp');
L.geoJson.ajax = function (geojson, options) {
return new L.GeoJSON.AJAX(geojson, options);
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./ajax":3,"./jsonp":5,"leaflet":undefined,"lie":1}],5:[function(require,module,exports){
(function (global){
'use strict';
var L = global.L || require('leaflet');
var Promise = require('lie');
module.exports = function (url, options) {
options = options || {};
var head = document.getElementsByTagName('head')[0];
var scriptNode = L.DomUtil.create('script', '', head);
var cbName, ourl, cbSuffix, cancel;
var out = new Promise(function (resolve, reject) {
cancel = reject;
var cbParam = options.cbParam || 'callback';
if (options.callbackName) {
cbName = options.callbackName;
} else {
cbSuffix = '_' + ('' + Math.random()).slice(2);
cbName = '_leafletJSONPcallbacks.' + cbSuffix;
}
scriptNode.type = 'text/javascript';
if (cbSuffix) {
if (!global._leafletJSONPcallbacks) {
global._leafletJSONPcallbacks = {
length: 0
};
}
global._leafletJSONPcallbacks.length++;
global._leafletJSONPcallbacks[cbSuffix] = function (data) {
head.removeChild(scriptNode);
delete global._leafletJSONPcallbacks[cbSuffix];
global._leafletJSONPcallbacks.length--;
if (!global._leafletJSONPcallbacks.length) {
delete global._leafletJSONPcallbacks;
}
resolve(data);
};
}
if (url.indexOf('?') === -1) {
ourl = url + '?' + cbParam + '=' + cbName;
} else {
ourl = url + '&' + cbParam + '=' + cbName;
}
scriptNode.src = ourl;
}).then(null, function (reason) {
head.removeChild(scriptNode);
delete L.Util.ajax.cb[cbSuffix];
return reason;
});
out.abort = cancel;
return out;
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"leaflet":undefined,"lie":1}]},{},[4]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

View File

@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=1024, user-scalable=no">
<style>
html { height: 100% }
body { height: 100%; margin: 0; padding: 0;}
#map{ height: 100% }
</style>
<link rel="stylesheet" href="leaflet.css" />
<!--[if lte IE 8]>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.6.4/leaflet.ie.css" />
<![endif]-->
<script src="leaflet-src.js"></script>
<script type="text/javascript" src="../dist/leaflet.ajax.js"></script>
<script src="spin.js"></script>
<script src="leaflet.spin.js"></script>
<title>Leaflet AJAX</title>
</head>
<body>
<div id="map"></div>
<script type="text/javascript">var m= L.map('map').setView([42.2, -71], 8);
var mopt = {
url: 'https://api.mapbox.com/styles/v1/mapbox/streets-v9/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1IjoiY3dtIiwiYSI6InFoYkpvS00ifQ.WHqQ_q865NKjIQB6Wpoi2w',
options: {attribution:'© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'}
};
var mq=L.tileLayer(mopt.url,mopt.options);
mq.addTo(m);
function popUp(f,l){
var out = [];
if (f.properties){
for(key in f.properties){
out.push(key+": "+f.properties[key]);
}
l.bindPopup(out.join("<br />"));
}
}
var jsonTest = new L.GeoJSON.AJAX(["colleges.geojson","counties.geojson"],{onEachFeature:popUp}).addTo(m);
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,511 @@
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-map-pane svg,
.leaflet-map-pane canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
-ms-touch-action: none;
touch-action: none;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg,
.leaflet-container .leaflet-tile-pane img {
max-width: none !important;
}
/* stupid Android 2 doesn't understand "max-width: none" properly */
.leaflet-container img.leaflet-image-layer {
max-width: 15000px !important;
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 8;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 7;
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-tile {
will-change: opacity;
}
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
-o-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
-o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-interactive {
cursor: pointer;
}
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline: 0;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-container a.leaflet-active {
outline: 2px solid orange;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a,
.leaflet-bar a:hover {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-control-zoom-out {
font-size: 20px;
}
.leaflet-touch .leaflet-control-zoom-in {
font-size: 22px;
}
.leaflet-touch .leaflet-control-zoom-out {
font-size: 24px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
padding-right: 5px;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.7);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover {
text-decoration: underline;
}
.leaflet-container .leaflet-control-attribution,
.leaflet-container .leaflet-control-scale {
font-size: 11px;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
font-size: 11px;
white-space: nowrap;
overflow: hidden;
-moz-box-sizing: content-box;
box-sizing: content-box;
background: #fff;
background: rgba(255, 255, 255, 0.5);
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 19px;
line-height: 1.4;
}
.leaflet-popup-content p {
margin: 18px 0;
}
.leaflet-popup-tip-container {
margin: 0 auto;
width: 40px;
height: 20px;
position: relative;
overflow: hidden;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
color: #333;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
padding: 4px 4px 0 0;
border: none;
text-align: center;
width: 18px;
height: 14px;
font: 16px/14px Tahoma, Verdana, sans-serif;
color: #c3c3c3;
text-decoration: none;
font-weight: bold;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover {
color: #999;
}
.leaflet-popup-scrolled {
overflow: auto;
border-bottom: 1px solid #ddd;
border-top: 1px solid #ddd;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-popup-tip-container {
margin-top: -1px;
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}

View File

@@ -0,0 +1,41 @@
L.SpinMapMixin = {
spin: function (state, options) {
if (!!state) {
// start spinning !
if (!this._spinner) {
this._spinner = new Spinner(options).spin(this._container);
this._spinning = 0;
}
this._spinning++;
}
else {
this._spinning--;
if (this._spinning <= 0) {
// end spinning !
if (this._spinner) {
this._spinner.stop();
this._spinner = null;
}
}
}
}
};
L.Map.include(L.SpinMapMixin);
L.Map.addInitHook(function () {
this.on('layeradd', function (e) {
// If added layer is currently loading, spin !
if (e.layer.loading) this.spin(true);
if (typeof e.layer.on != 'function') return;
e.layer.on('data:loading', function () { this.spin(true); }, this);
e.layer.on('data:loaded', function () { this.spin(false); }, this);
}, this);
this.on('layerremove', function (e) {
// Clean-up
if (e.layer.loading) this.spin(false);
if (typeof e.layer.on != 'function') return;
e.layer.off('data:loaded');
e.layer.off('data:loading');
}, this);
});

View File

@@ -0,0 +1,69 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=1024, user-scalable=no">
<style>
html { height: 100% }
body { height: 100%; margin: 0; padding: 0;}
#map{ height: 100% }
</style>
<link rel="stylesheet" href="leaflet.css" />
<script src="leaflet-src.js"></script>
<script type="text/javascript" src="../dist/leaflet.ajax.js"></script>
<script src="spin.js"></script>
<script src="leaflet.spin.js"></script>
<title>Leaflet AJAX</title>
</head>
<body>
<div id="map"></div>
<script type="text/javascript">var m= L.map('map').setView([42.2, -71], 8);
var osmDataAttr = 'Map data &copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors';
var mopt = {
url: 'https://api.mapbox.com/styles/v1/mapbox/streets-v9/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1IjoiY3dtIiwiYSI6InFoYkpvS00ifQ.WHqQ_q865NKjIQB6Wpoi2w',
options: {attribution:'© <a href="https://www.mapbox.com/map-feedback/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'}
};
var osm = L.tileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",{attribution:osmDataAttr});
var mq=L.tileLayer(mopt.url,mopt.options);
mq.addTo(m);
var baseMaps = {
"Mapbox Streets": mq,
"Open Street Map":osm
};
function popUp(f,l){
var out = [];
if (f.properties){
for(key in f.properties){
out.push(key+": "+f.properties[key]);
}
l.bindPopup(out.join("<br />"));
}
}
var jsonTest = new L.GeoJSON.AJAX("colleges.geojson",{onEachFeature:popUp});
var jsonpTest = L.geoJson.ajax("counties.jsonp",{onEachFeature:popUp,dataType:"jsonp"});
jsonTest.addTo(m);
var overlays={
"json":jsonTest,
"jsonp":jsonpTest
}
var lc=L.control.layers(baseMaps,overlays);
lc.addTo(m);
</script>
</body>
</html>

View File

@@ -0,0 +1 @@
(function(t,e){if(typeof exports=="object")module.exports=e();else if(typeof define=="function"&&define.amd)define(e);else t.Spinner=e()})(this,function(){"use strict";var t=["webkit","Moz","ms","O"],e={},i;function o(t,e){var i=document.createElement(t||"div"),o;for(o in e)i[o]=e[o];return i}function n(t){for(var e=1,i=arguments.length;e<i;e++)t.appendChild(arguments[e]);return t}var r=function(){var t=o("style",{type:"text/css"});n(document.getElementsByTagName("head")[0],t);return t.sheet||t.styleSheet}();function s(t,o,n,s){var a=["opacity",o,~~(t*100),n,s].join("-"),f=.01+n/s*100,l=Math.max(1-(1-t)/o*(100-f),t),u=i.substring(0,i.indexOf("Animation")).toLowerCase(),d=u&&"-"+u+"-"||"";if(!e[a]){r.insertRule("@"+d+"keyframes "+a+"{"+"0%{opacity:"+l+"}"+f+"%{opacity:"+t+"}"+(f+.01)+"%{opacity:1}"+(f+o)%100+"%{opacity:"+t+"}"+"100%{opacity:"+l+"}"+"}",r.cssRules.length);e[a]=1}return a}function a(e,i){var o=e.style,n,r;i=i.charAt(0).toUpperCase()+i.slice(1);for(r=0;r<t.length;r++){n=t[r]+i;if(o[n]!==undefined)return n}if(o[i]!==undefined)return i}function f(t,e){for(var i in e)t.style[a(t,i)||i]=e[i];return t}function l(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var o in i)if(t[o]===undefined)t[o]=i[o]}return t}function u(t){var e={x:t.offsetLeft,y:t.offsetTop};while(t=t.offsetParent)e.x+=t.offsetLeft,e.y+=t.offsetTop;return e}function d(t,e){return typeof t=="string"?t:t[e%t.length]}var p={lines:12,length:7,width:5,radius:10,rotate:0,corners:1,color:"#000",direction:1,speed:1,trail:100,opacity:1/4,fps:20,zIndex:2e9,className:"spinner",top:"auto",left:"auto",position:"relative"};function c(t){if(typeof this=="undefined")return new c(t);this.opts=l(t||{},c.defaults,p)}c.defaults={};l(c.prototype,{spin:function(t){this.stop();var e=this,n=e.opts,r=e.el=f(o(0,{className:n.className}),{position:n.position,width:0,zIndex:n.zIndex}),s=n.radius+n.length+n.width,a,l;if(t){t.insertBefore(r,t.firstChild||null);l=u(t);a=u(r);f(r,{left:(n.left=="auto"?l.x-a.x+(t.offsetWidth>>1):parseInt(n.left,10)+s)+"px",top:(n.top=="auto"?l.y-a.y+(t.offsetHeight>>1):parseInt(n.top,10)+s)+"px"})}r.setAttribute("role","progressbar");e.lines(r,e.opts);if(!i){var d=0,p=(n.lines-1)*(1-n.direction)/2,c,h=n.fps,m=h/n.speed,y=(1-n.opacity)/(m*n.trail/100),g=m/n.lines;(function v(){d++;for(var t=0;t<n.lines;t++){c=Math.max(1-(d+(n.lines-t)*g)%m*y,n.opacity);e.opacity(r,t*n.direction+p,c,n)}e.timeout=e.el&&setTimeout(v,~~(1e3/h))})()}return e},stop:function(){var t=this.el;if(t){clearTimeout(this.timeout);if(t.parentNode)t.parentNode.removeChild(t);this.el=undefined}return this},lines:function(t,e){var r=0,a=(e.lines-1)*(1-e.direction)/2,l;function u(t,i){return f(o(),{position:"absolute",width:e.length+e.width+"px",height:e.width+"px",background:t,boxShadow:i,transformOrigin:"left",transform:"rotate("+~~(360/e.lines*r+e.rotate)+"deg) translate("+e.radius+"px"+",0)",borderRadius:(e.corners*e.width>>1)+"px"})}for(;r<e.lines;r++){l=f(o(),{position:"absolute",top:1+~(e.width/2)+"px",transform:e.hwaccel?"translate3d(0,0,0)":"",opacity:e.opacity,animation:i&&s(e.opacity,e.trail,a+r*e.direction,e.lines)+" "+1/e.speed+"s linear infinite"});if(e.shadow)n(l,f(u("#000","0 0 4px "+"#000"),{top:2+"px"}));n(t,n(l,u(d(e.color,r),"0 0 1px rgba(0,0,0,.1)")))}return t},opacity:function(t,e,i){if(e<t.childNodes.length)t.childNodes[e].style.opacity=i}});function h(){function t(t,e){return o("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">',e)}r.addRule(".spin-vml","behavior:url(#default#VML)");c.prototype.lines=function(e,i){var o=i.length+i.width,r=2*o;function s(){return f(t("group",{coordsize:r+" "+r,coordorigin:-o+" "+-o}),{width:r,height:r})}var a=-(i.width+i.length)*2+"px",l=f(s(),{position:"absolute",top:a,left:a}),u;function p(e,r,a){n(l,n(f(s(),{rotation:360/i.lines*e+"deg",left:~~r}),n(f(t("roundrect",{arcsize:i.corners}),{width:o,height:i.width,left:i.radius,top:-i.width>>1,filter:a}),t("fill",{color:d(i.color,e),opacity:i.opacity}),t("stroke",{opacity:0}))))}if(i.shadow)for(u=1;u<=i.lines;u++)p(u,-2,"progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)");for(u=1;u<=i.lines;u++)p(u);return n(e,l)};c.prototype.opacity=function(t,e,i,o){var n=t.firstChild;o=o.shadow&&o.lines||0;if(n&&e+o<n.childNodes.length){n=n.childNodes[e+o];n=n&&n.firstChild;n=n&&n.firstChild;if(n)n.opacity=i}}}var m=f(o("group"),{behavior:"url(#default#VML)"});if(!a(m,"transform")&&m.adj)h();else i=a(m,"animation");return c});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
#Copyright (c) 2012-2015 Calvin Metcalf
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in 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:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
_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 AUTHORS 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 IN THE SOFTWARE._

View File

@@ -0,0 +1,36 @@
{
"name": "leaflet-ajax",
"version": "2.1.0",
"description": "AJAX and JSONP in Leaflet",
"main": "src/index.js",
"directories": {
"example": "example"
},
"scripts": {
"lint": "semistandard src/*.js",
"build": "browserify -u leaflet src/index.js > dist/leaflet.ajax.js && uglifyjs -mc < dist/leaflet.ajax.js > dist/leaflet.ajax.min.js"
},
"devDependencies": {
"browserify": "^11.0.1",
"express": "^4.13.3",
"semistandard": "^9.1.0",
"uglify-js": "^2.4.24"
},
"repository": {
"type": "git",
"url": "git://github.com/calvinmetcalf/leaflet-ajax.git"
},
"keywords": [
"leaflet",
"ajax",
"geojson"
],
"author": "Calvin Metcalf",
"license": "MIT",
"bugs": {
"url": "https://github.com/calvinmetcalf/leaflet-ajax/issues"
},
"dependencies": {
"lie": "^3.0.1"
}
}

View File

@@ -0,0 +1,13 @@
'use strict';
var express = require('express');
var app = express();
var path = require('path');
var fs = require('fs');
var counties = JSON.parse(fs.readFileSync(path.join(__dirname, 'example', 'counties.geojson'), {encoding: 'utf8'}));
app.get('/example/counties.jsonp', function (req, res){
res.jsonp(counties);
});
app.use('/example', express.static(path.join(__dirname, 'example')));
app.use('/dist', express.static(path.join(__dirname, 'dist')));
app.listen(3000);

View File

@@ -0,0 +1,51 @@
'use strict';
var jsonp = require('./jsonp');
var Promise = require('lie');
module.exports = function (url, options) {
options = options || {};
if (options.jsonp) {
return jsonp(url, options);
}
var request;
var cancel;
var out = new Promise(function (resolve, reject) {
cancel = reject;
if (global.XMLHttpRequest === undefined) {
reject('XMLHttpRequest is not supported');
}
var response;
request = new global.XMLHttpRequest();
request.open('GET', url);
if (options.headers) {
Object.keys(options.headers).forEach(function (key) {
request.setRequestHeader(key, options.headers[key]);
});
}
request.onreadystatechange = function () {
if (request.readyState === 4) {
if ((request.status < 400 && options.local) || request.status === 200) {
if (global.JSON) {
response = JSON.parse(request.responseText);
} else {
reject(new Error('JSON is not supported'));
}
resolve(response);
} else {
if (!request.status) {
reject('Attempted cross origin request without CORS enabled');
} else {
reject(request.statusText);
}
}
}
};
request.send();
});
out.catch(function (reason) {
request.abort();
return reason;
});
out.abort = cancel;
return out;
};

View File

@@ -0,0 +1,133 @@
'use strict';
var L = global.L || require('leaflet');
var Promise = require('lie');
var ajax = require('./ajax');
L.GeoJSON.AJAX = L.GeoJSON.extend({
defaultAJAXparams: {
dataType: 'json',
callbackParam: 'callback',
local: false,
middleware: function (f) {
return f;
}
},
initialize: function (url, options) {
this.urls = [];
if (url) {
if (typeof url === 'string') {
this.urls.push(url);
} else if (typeof url.pop === 'function') {
this.urls = this.urls.concat(url);
} else {
options = url;
url = undefined;
}
}
var ajaxParams = L.Util.extend({}, this.defaultAJAXparams);
for (var i in options) {
if (this.defaultAJAXparams.hasOwnProperty(i)) {
ajaxParams[i] = options[i];
}
}
this.ajaxParams = ajaxParams;
this._layers = {};
L.Util.setOptions(this, options);
this.on('data:loaded', function () {
if (this.filter) {
this.refilter(this.filter);
}
}, this);
var self = this;
if (this.urls.length > 0) {
new Promise(function (resolve) {
resolve();
}).then(function () {
self.addUrl();
});
}
},
clearLayers: function () {
this.urls = [];
L.GeoJSON.prototype.clearLayers.call(this);
return this;
},
addUrl: function (url) {
var self = this;
if (url) {
if (typeof url === 'string') {
self.urls.push(url);
} else if (typeof url.pop === 'function') {
self.urls = self.urls.concat(url);
}
}
var loading = self.urls.length;
var done = 0;
self.fire('data:loading');
self.urls.forEach(function (url) {
if (self.ajaxParams.dataType.toLowerCase() === 'json') {
ajax(url, self.ajaxParams).then(function (d) {
var data = self.ajaxParams.middleware(d);
self.addData(data);
self.fire('data:progress', data);
}, function (err) {
self.fire('data:progress', {
error: err
});
});
} else if (self.ajaxParams.dataType.toLowerCase() === 'jsonp') {
L.Util.jsonp(url, self.ajaxParams).then(function (d) {
var data = self.ajaxParams.middleware(d);
self.addData(data);
self.fire('data:progress', data);
}, function (err) {
self.fire('data:progress', {
error: err
});
});
}
});
self.on('data:progress', function () {
if (++done === loading) {
self.fire('data:loaded');
}
});
},
refresh: function (url) {
url = url || this.urls;
this.clearLayers();
this.addUrl(url);
},
refilter: function (func) {
if (typeof func !== 'function') {
this.filter = false;
this.eachLayer(function (a) {
a.setStyle({
stroke: true,
clickable: true
});
});
} else {
this.filter = func;
this.eachLayer(function (a) {
if (func(a.feature)) {
a.setStyle({
stroke: true,
clickable: true
});
} else {
a.setStyle({
stroke: false,
clickable: false
});
}
});
}
}
});
L.Util.Promise = Promise;
L.Util.ajax = ajax;
L.Util.jsonp = require('./jsonp');
L.geoJson.ajax = function (geojson, options) {
return new L.GeoJSON.AJAX(geojson, options);
};

View File

@@ -0,0 +1,50 @@
'use strict';
var L = global.L || require('leaflet');
var Promise = require('lie');
module.exports = function (url, options) {
options = options || {};
var head = document.getElementsByTagName('head')[0];
var scriptNode = L.DomUtil.create('script', '', head);
var cbName, ourl, cbSuffix, cancel;
var out = new Promise(function (resolve, reject) {
cancel = reject;
var cbParam = options.cbParam || 'callback';
if (options.callbackName) {
cbName = options.callbackName;
} else {
cbSuffix = '_' + ('' + Math.random()).slice(2);
cbName = '_leafletJSONPcallbacks.' + cbSuffix;
}
scriptNode.type = 'text/javascript';
if (cbSuffix) {
if (!global._leafletJSONPcallbacks) {
global._leafletJSONPcallbacks = {
length: 0
};
}
global._leafletJSONPcallbacks.length++;
global._leafletJSONPcallbacks[cbSuffix] = function (data) {
head.removeChild(scriptNode);
delete global._leafletJSONPcallbacks[cbSuffix];
global._leafletJSONPcallbacks.length--;
if (!global._leafletJSONPcallbacks.length) {
delete global._leafletJSONPcallbacks;
}
resolve(data);
};
}
if (url.indexOf('?') === -1) {
ourl = url + '?' + cbParam + '=' + cbName;
} else {
ourl = url + '&' + cbParam + '=' + cbName;
}
scriptNode.src = ourl;
}).then(null, function (reason) {
head.removeChild(scriptNode);
delete L.Util.ajax.cb[cbSuffix];
return reason;
});
out.abort = cancel;
return out;
};

View File

@@ -0,0 +1,59 @@
(function () {
// save these original methods before they are overwritten
var proto_initIcon = L.Marker.prototype._initIcon;
var proto_setPos = L.Marker.prototype._setPos;
var oldIE = (L.DomUtil.TRANSFORM === 'msTransform');
L.Marker.addInitHook(function () {
var iconOptions = this.options.icon && this.options.icon.options;
var iconAnchor = iconOptions && this.options.icon.options.iconAnchor;
if (iconAnchor) {
iconAnchor = (iconAnchor[0] + 'px ' + iconAnchor[1] + 'px');
}
this.options.rotationOrigin = this.options.rotationOrigin || iconAnchor || 'center bottom';
this.options.rotationAngle = this.options.rotationAngle || 0;
// Ensure marker keeps rotated during dragging
this.on('drag', function (e) {
e.target._applyRotation();
});
});
L.Marker.include({
_initIcon: function () {
proto_initIcon.call(this);
},
_setPos: function (pos) {
proto_setPos.call(this, pos);
this._applyRotation();
},
_applyRotation: function () {
if (this.options.rotationAngle) {
this._icon.style[L.DomUtil.TRANSFORM + 'Origin'] = this.options.rotationOrigin;
if (oldIE) {
// for IE 9, use the 2D rotation
this._icon.style[L.DomUtil.TRANSFORM] = 'rotate(' + this.options.rotationAngle + 'deg)';
} else {
// for modern browsers, prefer the 3D accelerated version
this._icon.style[L.DomUtil.TRANSFORM] += ' rotateZ(' + this.options.rotationAngle + 'deg)';
}
}
},
setRotationAngle: function (angle) {
this.options.rotationAngle = angle;
this.update();
return this;
},
setRotationOrigin: function (origin) {
this.options.rotationOrigin = origin;
this.update();
return this;
}
});
})();

View File

@@ -22,12 +22,12 @@
"bower_components",
"tests"
],
"version": "1.12.6",
"_release": "1.12.6",
"version": "1.12.9",
"_release": "1.12.9",
"_resolution": {
"type": "version",
"tag": "v1.12.6",
"commit": "ef87c99e389a304fa00e85d6372bf8cb596b9de8"
"tag": "v1.12.9",
"commit": "7621054778867e946dc288632ac059662b3713ec"
},
"_source": "https://github.com/FezVrasta/popper.js.git",
"_target": "^1.12.0",

View File

@@ -11,45 +11,85 @@ Feature requests are welcome!
## Setup
Then run `npm install` or `yarn` to install the needed dependencies.
Run `yarn` to install the needed dependencies.
Note that `npm` is not supported because this projects makes use of the Yarn workspaces.
## Developing
## Adopt an issue
The repository is a monorepo managed by [Lerna](https://github.com/lerna/lerna), this makes it
possible to manage multiple projects on the same repository.
All the issues, if not assigned to someone, can be adopted by anyone. Just make sure to comment on the issue to let know
other users about your intention to work on it.
In our case, the main projects are `popper` and `tooltip`, which are the home of Popper.js and Tooltip.js
All our packages are stored in the `packages/` folder.
### Adopt an issue
All the issues, if not assigned to someone, can be adopted by anyone. Just make sure to comment on
the issue to let know other users about your intention to work on it.
Also, remember to comment again in case you end up abandoning the issue.
Each issue has a `DIFFICULTY` label to help you pick the one with the difficulty level adapt to you.
Additionally, check out the `PRIORITY` label to see which issues should take precedence over the others. If possible, prefer issues with an higher priority, but if you want to adopt an issue with lower priority, it's not a problem!
Each issue has a `DIFFICULTY: *` label to help you pick the one with the difficulty level adapt to you.
Additionally, check out the `PRIORITY: *` label to see which issues should take precedence over the others.
If possible, prefer issues with an higher priority, but if you want to adopt an issue with lower priority,
it's not a problem!
Issues with `NEEDS: CI test` need a PR that integrates a test in the test suite to reproduce the bug, this is very useful because it allows other developers to try to fix the bug having a feedback.
Issues with `NEEDS: CI test` need a PR that integrates a test in the test suite to reproduce the bug,
this is very useful because it allows other developers to try to fix the bug having a feedback.
## Test
We develop following a test driven development approach.
### Style conventions
We have a karma + jasmine environment to unit test Popper.js
Feel free to add tests to the `/tests` folder, any JavaScript file in that folder will be executed as test.
You don't have to worry about code style conventions, [prettier](https://github.com/prettier/prettier)
will automatically format your code once you commit your changes.
### Test
We strive to keep the code coverage as high as possible, but above all, we want to avoid
to introduce or reintroduce bugs in our code base.
For this reason, every time a code change is made, we must make sure that a test is covering
the code we just changed.
If we fix a bug, we add a test to avoid that this bug pops up again in the future.
To help us with this process, we have a karma + jasmine environment to test Popper.js and Tooltip.js
The tests are located in the `tests/` folder of the two projects. (e.g. `packages/popper/tests/`)
To run tests:
```bash
npm run test:dev # watch
npm run test # single run
# You can run all the repositories tests running
yarn test
# or a single project's tests with
yarn test --scope=popper.js # or tooltip.js
```
## Build
If you want to run the tests in watch mode:
```bash
# You can run all the repositories tests running
yarn test:dev
# or a single project's tests with
yarn test:dev --scope=popper.js # or tooltip.js
```
Do you want to test your changes against all the supported browsers? Feel free to send a PR
and your changes will get automatically tested.
### Build
To create a new release run:
```js
npm run build:popper # popper.js
npm run build:tooltip # tooltip.js
npm run build # both
```bash
# to build both projects
yarn build
# or to build a single project
yarn build --scope=popper.js # or tooltip.js
```
The files will be automatically minified and copied in the `build` directory.
**Note:** never commit builds! We take care to compile the source code when we release a new version.
You can also build and watch for changes to automatically refresh the build using the `--watch` option.

View File

@@ -17,7 +17,7 @@ most common frameworks or view libraries thank to the following projects.
### [react-popper](https://github.com/souporserious/react-popper)
React wrapper around Popper.js.
React wrapper around Popper.js. (@FezVrasta approved! 👍)
### [ak-layer](https://www.npmjs.com/package/ak-layer)
@@ -52,6 +52,10 @@ VueJS 2.x popover component based [popper.js](https://popper.js.org/)
Vue.js tooltip directive (based on Popper.js)
### [v-tooltip](https://github.com/Akryum/v-tooltip)
Vue.js 2.x directive
## Ember.js
### [ember-popper](https://github.com/kybishop/ember-popper)

View File

@@ -7,13 +7,14 @@
</p>
<p align="center">
<a href="https://travis-ci.org/FezVrasta/popper.js/branches" target="_blank"><img src="https://travis-ci.org/FezVrasta/popper.js.svg?branch=master" alt="Build Status"/></a>
<img src="http://img.badgesize.io/https://unpkg.com/popper.js/dist/popper.min.js?compression=gzip" alt="Stable Release Size"/>
<img src="http://badge-size.now.sh/https://unpkg.com/popper.js/dist/popper.min.js?compression=brotli" alt="Stable Release Size"/>
<img src="http://badge-size.now.sh/https://unpkg.com/popper.js/dist/popper.min.js?compression=gzip" alt="Stable Release Size"/>
<a href="https://www.bithound.io/github/FezVrasta/popper.js"><img src="https://www.bithound.io/github/FezVrasta/popper.js/badges/score.svg" alt="bitHound Overall Score"></a>
<a href="https://codeclimate.com/github/FezVrasta/popper.js/coverage"><img src="https://codeclimate.com/github/FezVrasta/popper.js/badges/coverage.svg" alt="Istanbul Code Coverage"/></a>
<a href="https://gitter.im/FezVrasta/popper.js" target="_blank"><img src="https://img.shields.io/gitter/room/nwjs/nw.js.svg" alt="Get support or discuss"/></a>
<a href="https://spectrum.chat/popper-js" target="_blank"><img src="https://img.shields.io/badge/chat-on_spectrum-6833F9.svg?logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyBpZD0iTGl2ZWxsb18xIiBkYXRhLW5hbWU9IkxpdmVsbG8gMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMTAgOCI%2BPGRlZnM%2BPHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7fTwvc3R5bGU%2BPC9kZWZzPjx0aXRsZT5zcGVjdHJ1bTwvdGl0bGU%2BPHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNSwwQy40MiwwLDAsLjYzLDAsMy4zNGMwLDEuODQuMTksMi43MiwxLjc0LDMuMWgwVjcuNThhLjQ0LjQ0LDAsMCwwLC42OC4zNUw0LjM1LDYuNjlINWM0LjU4LDAsNS0uNjMsNS0zLjM1UzkuNTgsMCw1LDBaTTIuODMsNC4xOGEuNjMuNjMsMCwxLDEsLjY1LS42M0EuNjQuNjQsMCwwLDEsMi44Myw0LjE4Wk01LDQuMThhLjYzLjYzLDAsMSwxLC42NS0uNjNBLjY0LjY0LDAsMCwxLDUsNC4xOFptMi4xNywwYS42My42MywwLDEsMSwuNjUtLjYzQS42NC42NCwwLDAsMSw3LjE3LDQuMThaIi8%2BPC9zdmc%2B" alt="Get support or discuss"/></a>
<br />
<a href="https://saucelabs.com/u/popperjs" target="_blank"><img src="https://badges.herokuapp.com/browsers?labels=none&googlechrome=latest&firefox=latest&microsoftedge=latest&iexplore=11,10&safari=latest&iphone=latest" alt="SauceLabs Reports"/></a>
<a href="https://travis-ci.org/FezVrasta/popper.js/branches" target="_blank"><img src="https://travis-ci.org/FezVrasta/popper.js.svg?branch=master" alt="Build Status"/></a>
<a href="https://saucelabs.com/u/popperjs" target="_blank"><img src="https://badges.herokuapp.com/browsers?labels=none&googlechrome=latest&firefox=latest&microsoftedge=latest&iexplore=11,10&safari=latest" alt="SauceLabs Reports"/></a>
</p>
<img src="https://raw.githubusercontent.com/FezVrasta/popper.js/master/popperjs.png" align="right" width=250 />
@@ -68,6 +69,11 @@ The tooltips generated by Tooltip.js are accessible thanks to the `aria` tags.
Find [the documentation here](docs/_includes/tooltip-documentation.md).
<a target='_blank' rel='nofollow' href='https://app.codesponsor.io/link/b4EfpdBkBvHcfDMUuTZi8c8e/FezVrasta/popper.js'>
<img alt='Sponsor' width='888' height='68' src='https://app.codesponsor.io/embed/b4EfpdBkBvHcfDMUuTZi8c8e/FezVrasta/popper.js.svg' />
</a>
## Installation
Popper.js is available on the following package managers and CDNs:
@@ -95,7 +101,8 @@ For more info, [read the related issue](https://github.com/FezVrasta/popper.js/i
### Dist targets
Popper.js is currently shipped with 3 targets in mind: UMD, ESM and ESNext.
Popper.js is currently shipped with 3 targets in mind: UMD, ESM and ESNext.
No idea what am I talking about? You are looking for UMD probably.
- UMD - Universal Module Definition: AMD, RequireJS and globals;
- ESM - ES Modules: For webpack/Rollup or browser supporting the spec;
@@ -174,7 +181,7 @@ new Popper(reference, popper, {
applyReactStyle: {
enabled: true,
fn: applyReactStyle,
order: 800,
order: 900,
},
},
});

View File

@@ -1,6 +1,6 @@
/**!
* @fileOverview Kickass library to create and place poppers near their reference elements.
* @version 1.12.6
* @version 1.12.9
* @license
* Copyright (c) 2016 Federico Zivolo and contributors
*
@@ -34,7 +34,7 @@ function getStyleComputedProperty(element, property) {
return [];
}
// NOTE: 1 DOM access here
var css = window.getComputedStyle(element, null);
var css = getComputedStyle(element, null);
return property ? css[property] : css;
}
@@ -62,7 +62,7 @@ function getParentNode(element) {
function getScrollParent(element) {
// Return body, `getScroll` will take care to get the correct `scrollTop` from it
if (!element) {
return window.document.body;
return document.body;
}
switch (element.nodeName) {
@@ -104,7 +104,7 @@ function getOffsetParent(element) {
return element.ownerDocument.documentElement;
}
return window.document.documentElement;
return document.documentElement;
}
// .offsetParent will return the closest TD or TABLE in case
@@ -151,7 +151,7 @@ function getRoot(node) {
function findCommonOffsetParent(element1, element2) {
// This check is needed to avoid errors in case one of the elements isn't defined for any reason
if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
return window.document.documentElement;
return document.documentElement;
}
// Here we make sure to give as "start" the element that comes first in the DOM
@@ -243,7 +243,7 @@ function getBordersSize(styles, axis) {
var sideA = axis === 'x' ? 'Left' : 'Top';
var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
return +styles['border' + sideA + 'Width'].split('px')[0] + +styles['border' + sideB + 'Width'].split('px')[0];
return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
}
/**
@@ -266,9 +266,9 @@ function getSize(axis, body, html, computedStyle) {
}
function getWindowSizes() {
var body = window.document.body;
var html = window.document.documentElement;
var computedStyle = isIE10$1() && window.getComputedStyle(html);
var body = document.body;
var html = document.documentElement;
var computedStyle = isIE10$1() && getComputedStyle(html);
return {
height: getSize('Height', body, html, computedStyle),
@@ -368,8 +368,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
var scrollParent = getScrollParent(children);
var styles = getStyleComputedProperty(parent);
var borderTopWidth = +styles.borderTopWidth.split('px')[0];
var borderLeftWidth = +styles.borderLeftWidth.split('px')[0];
var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
var offsets = getClientRect({
top: childrenRect.top - parentRect.top - borderTopWidth,
@@ -385,8 +385,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
// differently when margins are applied to it. The margins are included in
// the box of the documentElement, in the other cases not.
if (!isIE10 && isHTML) {
var marginTop = +styles.marginTop.split('px')[0];
var marginLeft = +styles.marginLeft.split('px')[0];
var marginTop = parseFloat(styles.marginTop, 10);
var marginLeft = parseFloat(styles.marginLeft, 10);
offsets.top -= borderTopWidth - marginTop;
offsets.bottom -= borderTopWidth - marginTop;
@@ -465,7 +465,7 @@ function getBoundaries(popper, reference, padding, boundariesElement) {
// Handle other cases based on DOM element used as boundaries
var boundariesNode = void 0;
if (boundariesElement === 'scrollParent') {
boundariesNode = getScrollParent(getParentNode(popper));
boundariesNode = getScrollParent(getParentNode(reference));
if (boundariesNode.nodeName === 'BODY') {
boundariesNode = popper.ownerDocument.documentElement;
}
@@ -569,7 +569,7 @@ function computeAutoPlacement(placement, refRect, popper, reference, boundariesE
return computedPlacement + (variation ? '-' + variation : '');
}
var isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
var timeoutDuration = 0;
for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
@@ -586,7 +586,7 @@ function microtaskDebounce(fn) {
return;
}
called = true;
Promise.resolve().then(function () {
window.Promise.resolve().then(function () {
called = false;
fn();
});
@@ -703,7 +703,7 @@ function getOffsetRect(element) {
* @returns {Object} object containing width and height properties
*/
function getOuterSizes(element) {
var styles = window.getComputedStyle(element);
var styles = getComputedStyle(element);
var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
var result = {
@@ -794,7 +794,7 @@ function getSupportedPropertyName(property) {
for (var i = 0; i < prefixes.length - 1; i++) {
var prefix = prefixes[i];
var toCheck = prefix ? '' + prefix + upperProp : property;
if (typeof window.document.body.style[toCheck] !== 'undefined') {
if (typeof document.body.style[toCheck] !== 'undefined') {
return toCheck;
}
}
@@ -1039,5 +1039,6 @@ var index = {
setupEventListeners: setupEventListeners
};
export { computeAutoPlacement, debounce, findIndex, getBordersSize, getBoundaries, getBoundingClientRect, getClientRect, getOffsetParent, getOffsetRect, getOffsetRectRelativeToArbitraryNode, getOuterSizes, getParentNode, getPopperOffsets, getReferenceOffsets, getScroll, getScrollParent, getStyleComputedProperty, getSupportedPropertyName, getWindowSizes, isFixed, isFunction, isModifierEnabled, isModifierRequired, isNumeric, removeEventListeners, runModifiers, setAttributes, setStyles, setupEventListeners };export default index;
export { computeAutoPlacement, debounce, findIndex, getBordersSize, getBoundaries, getBoundingClientRect, getClientRect, getOffsetParent, getOffsetRect, getOffsetRectRelativeToArbitraryNode, getOuterSizes, getParentNode, getPopperOffsets, getReferenceOffsets, getScroll, getScrollParent, getStyleComputedProperty, getSupportedPropertyName, getWindowSizes, isFixed, isFunction, isModifierEnabled, isModifierRequired, isNumeric, removeEventListeners, runModifiers, setAttributes, setStyles, setupEventListeners };
export default index;
//# sourceMappingURL=popper-utils.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
/**!
* @fileOverview Kickass library to create and place poppers near their reference elements.
* @version 1.12.6
* @version 1.12.9
* @license
* Copyright (c) 2016 Federico Zivolo and contributors
*
@@ -22,7 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
var isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
var timeoutDuration = 0;
for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
@@ -39,7 +39,7 @@ function microtaskDebounce(fn) {
return;
}
called = true;
Promise.resolve().then(function () {
window.Promise.resolve().then(function () {
called = false;
fn();
});
@@ -96,7 +96,7 @@ function getStyleComputedProperty(element, property) {
return [];
}
// NOTE: 1 DOM access here
var css = window.getComputedStyle(element, null);
var css = getComputedStyle(element, null);
return property ? css[property] : css;
}
@@ -124,7 +124,7 @@ function getParentNode(element) {
function getScrollParent(element) {
// Return body, `getScroll` will take care to get the correct `scrollTop` from it
if (!element) {
return window.document.body;
return document.body;
}
switch (element.nodeName) {
@@ -166,7 +166,7 @@ function getOffsetParent(element) {
return element.ownerDocument.documentElement;
}
return window.document.documentElement;
return document.documentElement;
}
// .offsetParent will return the closest TD or TABLE in case
@@ -213,7 +213,7 @@ function getRoot(node) {
function findCommonOffsetParent(element1, element2) {
// This check is needed to avoid errors in case one of the elements isn't defined for any reason
if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
return window.document.documentElement;
return document.documentElement;
}
// Here we make sure to give as "start" the element that comes first in the DOM
@@ -305,7 +305,7 @@ function getBordersSize(styles, axis) {
var sideA = axis === 'x' ? 'Left' : 'Top';
var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
return +styles['border' + sideA + 'Width'].split('px')[0] + +styles['border' + sideB + 'Width'].split('px')[0];
return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
}
/**
@@ -328,9 +328,9 @@ function getSize(axis, body, html, computedStyle) {
}
function getWindowSizes() {
var body = window.document.body;
var html = window.document.documentElement;
var computedStyle = isIE10$1() && window.getComputedStyle(html);
var body = document.body;
var html = document.documentElement;
var computedStyle = isIE10$1() && getComputedStyle(html);
return {
height: getSize('Height', body, html, computedStyle),
@@ -473,8 +473,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
var scrollParent = getScrollParent(children);
var styles = getStyleComputedProperty(parent);
var borderTopWidth = +styles.borderTopWidth.split('px')[0];
var borderLeftWidth = +styles.borderLeftWidth.split('px')[0];
var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
var offsets = getClientRect({
top: childrenRect.top - parentRect.top - borderTopWidth,
@@ -490,8 +490,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
// differently when margins are applied to it. The margins are included in
// the box of the documentElement, in the other cases not.
if (!isIE10 && isHTML) {
var marginTop = +styles.marginTop.split('px')[0];
var marginLeft = +styles.marginLeft.split('px')[0];
var marginTop = parseFloat(styles.marginTop, 10);
var marginLeft = parseFloat(styles.marginLeft, 10);
offsets.top -= borderTopWidth - marginTop;
offsets.bottom -= borderTopWidth - marginTop;
@@ -570,7 +570,7 @@ function getBoundaries(popper, reference, padding, boundariesElement) {
// Handle other cases based on DOM element used as boundaries
var boundariesNode = void 0;
if (boundariesElement === 'scrollParent') {
boundariesNode = getScrollParent(getParentNode(popper));
boundariesNode = getScrollParent(getParentNode(reference));
if (boundariesNode.nodeName === 'BODY') {
boundariesNode = popper.ownerDocument.documentElement;
}
@@ -696,7 +696,7 @@ function getReferenceOffsets(state, popper, reference) {
* @returns {Object} object containing width and height properties
*/
function getOuterSizes(element) {
var styles = window.getComputedStyle(element);
var styles = getComputedStyle(element);
var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
var result = {
@@ -913,7 +913,7 @@ function getSupportedPropertyName(property) {
for (var i = 0; i < prefixes.length - 1; i++) {
var prefix = prefixes[i];
var toCheck = prefix ? '' + prefix + upperProp : property;
if (typeof window.document.body.style[toCheck] !== 'undefined') {
if (typeof document.body.style[toCheck] !== 'undefined') {
return toCheck;
}
}
@@ -1032,7 +1032,7 @@ function removeEventListeners(reference, state) {
*/
function disableEventListeners() {
if (this.state.eventsEnabled) {
window.cancelAnimationFrame(this.scheduleUpdate);
cancelAnimationFrame(this.scheduleUpdate);
this.state = removeEventListeners(this.reference, this.state);
}
}
@@ -1272,6 +1272,8 @@ function isModifierRequired(modifiers, requestingName, requestedName) {
* @returns {Object} The data object, properly modified
*/
function arrow(data, options) {
var _data$offsets$arrow;
// arrow depends on keepTogether in order to work
if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
return data;
@@ -1323,22 +1325,23 @@ function arrow(data, options) {
if (reference[side] + arrowElementSize > popper[opSide]) {
data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
}
data.offsets.popper = getClientRect(data.offsets.popper);
// compute center of the popper
var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
// Compute the sideValue using the updated popper offsets
// take popper margin in account because we don't have this info available
var popperMarginSide = getStyleComputedProperty(data.instance.popper, 'margin' + sideCapitalized).replace('px', '');
var sideValue = center - getClientRect(data.offsets.popper)[side] - popperMarginSide;
var css = getStyleComputedProperty(data.instance.popper);
var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);
var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);
var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
// prevent arrowElement from being placed not contiguously to its popper
sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
data.arrowElement = arrowElement;
data.offsets.arrow = {};
data.offsets.arrow[side] = Math.round(sideValue);
data.offsets.arrow[altSide] = ''; // make sure to unset any eventual altSide value from the DOM node
data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
return data;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
/**!
* @fileOverview Kickass library to create and place poppers near their reference elements.
* @version 1.12.6
* @version 1.12.9
* @license
* Copyright (c) 2016 Federico Zivolo and contributors
*
@@ -34,7 +34,7 @@ function getStyleComputedProperty(element, property) {
return [];
}
// NOTE: 1 DOM access here
const css = window.getComputedStyle(element, null);
const css = getComputedStyle(element, null);
return property ? css[property] : css;
}
@@ -62,7 +62,7 @@ function getParentNode(element) {
function getScrollParent(element) {
// Return body, `getScroll` will take care to get the correct `scrollTop` from it
if (!element) {
return window.document.body;
return document.body;
}
switch (element.nodeName) {
@@ -99,7 +99,7 @@ function getOffsetParent(element) {
return element.ownerDocument.documentElement;
}
return window.document.documentElement;
return document.documentElement;
}
// .offsetParent will return the closest TD or TABLE in case
@@ -145,7 +145,7 @@ function getRoot(node) {
function findCommonOffsetParent(element1, element2) {
// This check is needed to avoid errors in case one of the elements isn't defined for any reason
if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
return window.document.documentElement;
return document.documentElement;
}
// Here we make sure to give as "start" the element that comes first in the DOM
@@ -232,7 +232,7 @@ function getBordersSize(styles, axis) {
const sideA = axis === 'x' ? 'Left' : 'Top';
const sideB = sideA === 'Left' ? 'Right' : 'Bottom';
return +styles[`border${sideA}Width`].split('px')[0] + +styles[`border${sideB}Width`].split('px')[0];
return parseFloat(styles[`border${sideA}Width`], 10) + parseFloat(styles[`border${sideB}Width`], 10);
}
/**
@@ -255,9 +255,9 @@ function getSize(axis, body, html, computedStyle) {
}
function getWindowSizes() {
const body = window.document.body;
const html = window.document.documentElement;
const computedStyle = isIE10$1() && window.getComputedStyle(html);
const body = document.body;
const html = document.documentElement;
const computedStyle = isIE10$1() && getComputedStyle(html);
return {
height: getSize('Height', body, html, computedStyle),
@@ -357,8 +357,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
const scrollParent = getScrollParent(children);
const styles = getStyleComputedProperty(parent);
const borderTopWidth = +styles.borderTopWidth.split('px')[0];
const borderLeftWidth = +styles.borderLeftWidth.split('px')[0];
const borderTopWidth = parseFloat(styles.borderTopWidth, 10);
const borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
let offsets = getClientRect({
top: childrenRect.top - parentRect.top - borderTopWidth,
@@ -374,8 +374,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
// differently when margins are applied to it. The margins are included in
// the box of the documentElement, in the other cases not.
if (!isIE10 && isHTML) {
const marginTop = +styles.marginTop.split('px')[0];
const marginLeft = +styles.marginLeft.split('px')[0];
const marginTop = parseFloat(styles.marginTop, 10);
const marginLeft = parseFloat(styles.marginLeft, 10);
offsets.top -= borderTopWidth - marginTop;
offsets.bottom -= borderTopWidth - marginTop;
@@ -454,7 +454,7 @@ function getBoundaries(popper, reference, padding, boundariesElement) {
// Handle other cases based on DOM element used as boundaries
let boundariesNode;
if (boundariesElement === 'scrollParent') {
boundariesNode = getScrollParent(getParentNode(popper));
boundariesNode = getScrollParent(getParentNode(reference));
if (boundariesNode.nodeName === 'BODY') {
boundariesNode = popper.ownerDocument.documentElement;
}
@@ -542,7 +542,7 @@ function computeAutoPlacement(placement, refRect, popper, reference, boundariesE
return computedPlacement + (variation ? `-${variation}` : '');
}
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
const longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
let timeoutDuration = 0;
for (let i = 0; i < longerTimeoutBrowsers.length; i += 1) {
@@ -559,7 +559,7 @@ function microtaskDebounce(fn) {
return;
}
called = true;
Promise.resolve().then(() => {
window.Promise.resolve().then(() => {
called = false;
fn();
});
@@ -669,7 +669,7 @@ function getOffsetRect(element) {
* @returns {Object} object containing width and height properties
*/
function getOuterSizes(element) {
const styles = window.getComputedStyle(element);
const styles = getComputedStyle(element);
const x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
const y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
const result = {
@@ -758,7 +758,7 @@ function getSupportedPropertyName(property) {
for (let i = 0; i < prefixes.length - 1; i++) {
const prefix = prefixes[i];
const toCheck = prefix ? `${prefix}${upperProp}` : property;
if (typeof window.document.body.style[toCheck] !== 'undefined') {
if (typeof document.body.style[toCheck] !== 'undefined') {
return toCheck;
}
}
@@ -996,5 +996,6 @@ var index = {
setupEventListeners
};
export { computeAutoPlacement, debounce, findIndex, getBordersSize, getBoundaries, getBoundingClientRect, getClientRect, getOffsetParent, getOffsetRect, getOffsetRectRelativeToArbitraryNode, getOuterSizes, getParentNode, getPopperOffsets, getReferenceOffsets, getScroll, getScrollParent, getStyleComputedProperty, getSupportedPropertyName, getWindowSizes, isFixed, isFunction, isModifierEnabled, isModifierRequired, isNumeric, removeEventListeners, runModifiers, setAttributes, setStyles, setupEventListeners };export default index;
export { computeAutoPlacement, debounce, findIndex, getBordersSize, getBoundaries, getBoundingClientRect, getClientRect, getOffsetParent, getOffsetRect, getOffsetRectRelativeToArbitraryNode, getOuterSizes, getParentNode, getPopperOffsets, getReferenceOffsets, getScroll, getScrollParent, getStyleComputedProperty, getSupportedPropertyName, getWindowSizes, isFixed, isFunction, isModifierEnabled, isModifierRequired, isNumeric, removeEventListeners, runModifiers, setAttributes, setStyles, setupEventListeners };
export default index;
//# sourceMappingURL=popper-utils.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
/**!
* @fileOverview Kickass library to create and place poppers near their reference elements.
* @version 1.12.6
* @version 1.12.9
* @license
* Copyright (c) 2016 Federico Zivolo and contributors
*
@@ -22,7 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
const longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
let timeoutDuration = 0;
for (let i = 0; i < longerTimeoutBrowsers.length; i += 1) {
@@ -39,7 +39,7 @@ function microtaskDebounce(fn) {
return;
}
called = true;
Promise.resolve().then(() => {
window.Promise.resolve().then(() => {
called = false;
fn();
});
@@ -96,7 +96,7 @@ function getStyleComputedProperty(element, property) {
return [];
}
// NOTE: 1 DOM access here
const css = window.getComputedStyle(element, null);
const css = getComputedStyle(element, null);
return property ? css[property] : css;
}
@@ -124,7 +124,7 @@ function getParentNode(element) {
function getScrollParent(element) {
// Return body, `getScroll` will take care to get the correct `scrollTop` from it
if (!element) {
return window.document.body;
return document.body;
}
switch (element.nodeName) {
@@ -161,7 +161,7 @@ function getOffsetParent(element) {
return element.ownerDocument.documentElement;
}
return window.document.documentElement;
return document.documentElement;
}
// .offsetParent will return the closest TD or TABLE in case
@@ -207,7 +207,7 @@ function getRoot(node) {
function findCommonOffsetParent(element1, element2) {
// This check is needed to avoid errors in case one of the elements isn't defined for any reason
if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
return window.document.documentElement;
return document.documentElement;
}
// Here we make sure to give as "start" the element that comes first in the DOM
@@ -294,7 +294,7 @@ function getBordersSize(styles, axis) {
const sideA = axis === 'x' ? 'Left' : 'Top';
const sideB = sideA === 'Left' ? 'Right' : 'Bottom';
return +styles[`border${sideA}Width`].split('px')[0] + +styles[`border${sideB}Width`].split('px')[0];
return parseFloat(styles[`border${sideA}Width`], 10) + parseFloat(styles[`border${sideB}Width`], 10);
}
/**
@@ -317,9 +317,9 @@ function getSize(axis, body, html, computedStyle) {
}
function getWindowSizes() {
const body = window.document.body;
const html = window.document.documentElement;
const computedStyle = isIE10$1() && window.getComputedStyle(html);
const body = document.body;
const html = document.documentElement;
const computedStyle = isIE10$1() && getComputedStyle(html);
return {
height: getSize('Height', body, html, computedStyle),
@@ -419,8 +419,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
const scrollParent = getScrollParent(children);
const styles = getStyleComputedProperty(parent);
const borderTopWidth = +styles.borderTopWidth.split('px')[0];
const borderLeftWidth = +styles.borderLeftWidth.split('px')[0];
const borderTopWidth = parseFloat(styles.borderTopWidth, 10);
const borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
let offsets = getClientRect({
top: childrenRect.top - parentRect.top - borderTopWidth,
@@ -436,8 +436,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
// differently when margins are applied to it. The margins are included in
// the box of the documentElement, in the other cases not.
if (!isIE10 && isHTML) {
const marginTop = +styles.marginTop.split('px')[0];
const marginLeft = +styles.marginLeft.split('px')[0];
const marginTop = parseFloat(styles.marginTop, 10);
const marginLeft = parseFloat(styles.marginLeft, 10);
offsets.top -= borderTopWidth - marginTop;
offsets.bottom -= borderTopWidth - marginTop;
@@ -516,7 +516,7 @@ function getBoundaries(popper, reference, padding, boundariesElement) {
// Handle other cases based on DOM element used as boundaries
let boundariesNode;
if (boundariesElement === 'scrollParent') {
boundariesNode = getScrollParent(getParentNode(popper));
boundariesNode = getScrollParent(getParentNode(reference));
if (boundariesNode.nodeName === 'BODY') {
boundariesNode = popper.ownerDocument.documentElement;
}
@@ -626,7 +626,7 @@ function getReferenceOffsets(state, popper, reference) {
* @returns {Object} object containing width and height properties
*/
function getOuterSizes(element) {
const styles = window.getComputedStyle(element);
const styles = getComputedStyle(element);
const x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
const y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
const result = {
@@ -833,7 +833,7 @@ function getSupportedPropertyName(property) {
for (let i = 0; i < prefixes.length - 1; i++) {
const prefix = prefixes[i];
const toCheck = prefix ? `${prefix}${upperProp}` : property;
if (typeof window.document.body.style[toCheck] !== 'undefined') {
if (typeof document.body.style[toCheck] !== 'undefined') {
return toCheck;
}
}
@@ -952,7 +952,7 @@ function removeEventListeners(reference, state) {
*/
function disableEventListeners() {
if (this.state.eventsEnabled) {
window.cancelAnimationFrame(this.scheduleUpdate);
cancelAnimationFrame(this.scheduleUpdate);
this.state = removeEventListeners(this.reference, this.state);
}
}
@@ -1232,22 +1232,26 @@ function arrow(data, options) {
if (reference[side] + arrowElementSize > popper[opSide]) {
data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
}
data.offsets.popper = getClientRect(data.offsets.popper);
// compute center of the popper
const center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
// Compute the sideValue using the updated popper offsets
// take popper margin in account because we don't have this info available
const popperMarginSide = getStyleComputedProperty(data.instance.popper, `margin${sideCapitalized}`).replace('px', '');
let sideValue = center - getClientRect(data.offsets.popper)[side] - popperMarginSide;
const css = getStyleComputedProperty(data.instance.popper);
const popperMarginSide = parseFloat(css[`margin${sideCapitalized}`], 10);
const popperBorderSide = parseFloat(css[`border${sideCapitalized}Width`], 10);
let sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
// prevent arrowElement from being placed not contiguously to its popper
sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
data.arrowElement = arrowElement;
data.offsets.arrow = {};
data.offsets.arrow[side] = Math.round(sideValue);
data.offsets.arrow[altSide] = ''; // make sure to unset any eventual altSide value from the DOM node
data.offsets.arrow = {
[side]: Math.round(sideValue),
[altSide]: '' // make sure to unset any eventual altSide value from the DOM node
};
return data;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
/**!
* @fileOverview Kickass library to create and place poppers near their reference elements.
* @version 1.12.6
* @version 1.12.9
* @license
* Copyright (c) 2016 Federico Zivolo and contributors
*
@@ -25,7 +25,7 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.PopperUtils = global.PopperUtils || {})));
(factory((global.PopperUtils = {})));
}(this, (function (exports) { 'use strict';
/**
@@ -40,7 +40,7 @@ function getStyleComputedProperty(element, property) {
return [];
}
// NOTE: 1 DOM access here
var css = window.getComputedStyle(element, null);
var css = getComputedStyle(element, null);
return property ? css[property] : css;
}
@@ -68,7 +68,7 @@ function getParentNode(element) {
function getScrollParent(element) {
// Return body, `getScroll` will take care to get the correct `scrollTop` from it
if (!element) {
return window.document.body;
return document.body;
}
switch (element.nodeName) {
@@ -110,7 +110,7 @@ function getOffsetParent(element) {
return element.ownerDocument.documentElement;
}
return window.document.documentElement;
return document.documentElement;
}
// .offsetParent will return the closest TD or TABLE in case
@@ -157,7 +157,7 @@ function getRoot(node) {
function findCommonOffsetParent(element1, element2) {
// This check is needed to avoid errors in case one of the elements isn't defined for any reason
if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
return window.document.documentElement;
return document.documentElement;
}
// Here we make sure to give as "start" the element that comes first in the DOM
@@ -249,7 +249,7 @@ function getBordersSize(styles, axis) {
var sideA = axis === 'x' ? 'Left' : 'Top';
var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
return +styles['border' + sideA + 'Width'].split('px')[0] + +styles['border' + sideB + 'Width'].split('px')[0];
return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
}
/**
@@ -272,9 +272,9 @@ function getSize(axis, body, html, computedStyle) {
}
function getWindowSizes() {
var body = window.document.body;
var html = window.document.documentElement;
var computedStyle = isIE10$1() && window.getComputedStyle(html);
var body = document.body;
var html = document.documentElement;
var computedStyle = isIE10$1() && getComputedStyle(html);
return {
height: getSize('Height', body, html, computedStyle),
@@ -374,8 +374,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
var scrollParent = getScrollParent(children);
var styles = getStyleComputedProperty(parent);
var borderTopWidth = +styles.borderTopWidth.split('px')[0];
var borderLeftWidth = +styles.borderLeftWidth.split('px')[0];
var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
var offsets = getClientRect({
top: childrenRect.top - parentRect.top - borderTopWidth,
@@ -391,8 +391,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
// differently when margins are applied to it. The margins are included in
// the box of the documentElement, in the other cases not.
if (!isIE10 && isHTML) {
var marginTop = +styles.marginTop.split('px')[0];
var marginLeft = +styles.marginLeft.split('px')[0];
var marginTop = parseFloat(styles.marginTop, 10);
var marginLeft = parseFloat(styles.marginLeft, 10);
offsets.top -= borderTopWidth - marginTop;
offsets.bottom -= borderTopWidth - marginTop;
@@ -471,7 +471,7 @@ function getBoundaries(popper, reference, padding, boundariesElement) {
// Handle other cases based on DOM element used as boundaries
var boundariesNode = void 0;
if (boundariesElement === 'scrollParent') {
boundariesNode = getScrollParent(getParentNode(popper));
boundariesNode = getScrollParent(getParentNode(reference));
if (boundariesNode.nodeName === 'BODY') {
boundariesNode = popper.ownerDocument.documentElement;
}
@@ -575,7 +575,7 @@ function computeAutoPlacement(placement, refRect, popper, reference, boundariesE
return computedPlacement + (variation ? '-' + variation : '');
}
var isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
var timeoutDuration = 0;
for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
@@ -592,7 +592,7 @@ function microtaskDebounce(fn) {
return;
}
called = true;
Promise.resolve().then(function () {
window.Promise.resolve().then(function () {
called = false;
fn();
});
@@ -709,7 +709,7 @@ function getOffsetRect(element) {
* @returns {Object} object containing width and height properties
*/
function getOuterSizes(element) {
var styles = window.getComputedStyle(element);
var styles = getComputedStyle(element);
var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
var result = {
@@ -800,7 +800,7 @@ function getSupportedPropertyName(property) {
for (var i = 0; i < prefixes.length - 1; i++) {
var prefix = prefixes[i];
var toCheck = prefix ? '' + prefix + upperProp : property;
if (typeof window.document.body.style[toCheck] !== 'undefined') {
if (typeof document.body.style[toCheck] !== 'undefined') {
return toCheck;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
/**!
* @fileOverview Kickass library to create and place poppers near their reference elements.
* @version 1.12.6
* @version 1.12.9
* @license
* Copyright (c) 2016 Federico Zivolo and contributors
*
@@ -28,7 +28,7 @@
(global.Popper = factory());
}(this, (function () { 'use strict';
var isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
var timeoutDuration = 0;
for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
@@ -45,7 +45,7 @@ function microtaskDebounce(fn) {
return;
}
called = true;
Promise.resolve().then(function () {
window.Promise.resolve().then(function () {
called = false;
fn();
});
@@ -102,7 +102,7 @@ function getStyleComputedProperty(element, property) {
return [];
}
// NOTE: 1 DOM access here
var css = window.getComputedStyle(element, null);
var css = getComputedStyle(element, null);
return property ? css[property] : css;
}
@@ -130,7 +130,7 @@ function getParentNode(element) {
function getScrollParent(element) {
// Return body, `getScroll` will take care to get the correct `scrollTop` from it
if (!element) {
return window.document.body;
return document.body;
}
switch (element.nodeName) {
@@ -172,7 +172,7 @@ function getOffsetParent(element) {
return element.ownerDocument.documentElement;
}
return window.document.documentElement;
return document.documentElement;
}
// .offsetParent will return the closest TD or TABLE in case
@@ -219,7 +219,7 @@ function getRoot(node) {
function findCommonOffsetParent(element1, element2) {
// This check is needed to avoid errors in case one of the elements isn't defined for any reason
if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
return window.document.documentElement;
return document.documentElement;
}
// Here we make sure to give as "start" the element that comes first in the DOM
@@ -311,7 +311,7 @@ function getBordersSize(styles, axis) {
var sideA = axis === 'x' ? 'Left' : 'Top';
var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
return +styles['border' + sideA + 'Width'].split('px')[0] + +styles['border' + sideB + 'Width'].split('px')[0];
return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
}
/**
@@ -334,9 +334,9 @@ function getSize(axis, body, html, computedStyle) {
}
function getWindowSizes() {
var body = window.document.body;
var html = window.document.documentElement;
var computedStyle = isIE10$1() && window.getComputedStyle(html);
var body = document.body;
var html = document.documentElement;
var computedStyle = isIE10$1() && getComputedStyle(html);
return {
height: getSize('Height', body, html, computedStyle),
@@ -479,8 +479,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
var scrollParent = getScrollParent(children);
var styles = getStyleComputedProperty(parent);
var borderTopWidth = +styles.borderTopWidth.split('px')[0];
var borderLeftWidth = +styles.borderLeftWidth.split('px')[0];
var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
var offsets = getClientRect({
top: childrenRect.top - parentRect.top - borderTopWidth,
@@ -496,8 +496,8 @@ function getOffsetRectRelativeToArbitraryNode(children, parent) {
// differently when margins are applied to it. The margins are included in
// the box of the documentElement, in the other cases not.
if (!isIE10 && isHTML) {
var marginTop = +styles.marginTop.split('px')[0];
var marginLeft = +styles.marginLeft.split('px')[0];
var marginTop = parseFloat(styles.marginTop, 10);
var marginLeft = parseFloat(styles.marginLeft, 10);
offsets.top -= borderTopWidth - marginTop;
offsets.bottom -= borderTopWidth - marginTop;
@@ -576,7 +576,7 @@ function getBoundaries(popper, reference, padding, boundariesElement) {
// Handle other cases based on DOM element used as boundaries
var boundariesNode = void 0;
if (boundariesElement === 'scrollParent') {
boundariesNode = getScrollParent(getParentNode(popper));
boundariesNode = getScrollParent(getParentNode(reference));
if (boundariesNode.nodeName === 'BODY') {
boundariesNode = popper.ownerDocument.documentElement;
}
@@ -702,7 +702,7 @@ function getReferenceOffsets(state, popper, reference) {
* @returns {Object} object containing width and height properties
*/
function getOuterSizes(element) {
var styles = window.getComputedStyle(element);
var styles = getComputedStyle(element);
var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
var result = {
@@ -919,7 +919,7 @@ function getSupportedPropertyName(property) {
for (var i = 0; i < prefixes.length - 1; i++) {
var prefix = prefixes[i];
var toCheck = prefix ? '' + prefix + upperProp : property;
if (typeof window.document.body.style[toCheck] !== 'undefined') {
if (typeof document.body.style[toCheck] !== 'undefined') {
return toCheck;
}
}
@@ -1038,7 +1038,7 @@ function removeEventListeners(reference, state) {
*/
function disableEventListeners() {
if (this.state.eventsEnabled) {
window.cancelAnimationFrame(this.scheduleUpdate);
cancelAnimationFrame(this.scheduleUpdate);
this.state = removeEventListeners(this.reference, this.state);
}
}
@@ -1278,6 +1278,8 @@ function isModifierRequired(modifiers, requestingName, requestedName) {
* @returns {Object} The data object, properly modified
*/
function arrow(data, options) {
var _data$offsets$arrow;
// arrow depends on keepTogether in order to work
if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
return data;
@@ -1329,22 +1331,23 @@ function arrow(data, options) {
if (reference[side] + arrowElementSize > popper[opSide]) {
data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
}
data.offsets.popper = getClientRect(data.offsets.popper);
// compute center of the popper
var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
// Compute the sideValue using the updated popper offsets
// take popper margin in account because we don't have this info available
var popperMarginSide = getStyleComputedProperty(data.instance.popper, 'margin' + sideCapitalized).replace('px', '');
var sideValue = center - getClientRect(data.offsets.popper)[side] - popperMarginSide;
var css = getStyleComputedProperty(data.instance.popper);
var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);
var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);
var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
// prevent arrowElement from being placed not contiguously to its popper
sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
data.arrowElement = arrowElement;
data.offsets.arrow = {};
data.offsets.arrow[side] = Math.round(sideValue);
data.offsets.arrow[altSide] = ''; // make sure to unset any eventual altSide value from the DOM node
data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
return data;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -28,7 +28,7 @@ layout: landing
Popper.js is just <strong>~6KB</strong> minified and gzpipped, zero dependencies.<br />
Its code base is in <strong>ES6</strong> and is <strong>automatically tested</strong> against several browsers.<br />
If this is not enough, it plays super nicely with
<a href="https://github.com/FezVrasta/popper.js/#react-vuejs-angularjs-emberjs-etc-integration" target="_blank"><strong>React</strong>, <strong>AngularJS</strong> and more</a>!
<a href="https://github.com/FezVrasta/popper.js/#react-vuejs-angular-angularjs-emberjs-etc-integration" target="_blank"><strong>React</strong>, <strong>AngularJS</strong> and more</a>!
</p>
<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?zoneid=1673&serve=C6AILKT&placement=fezvrastagithubiopopperjs" id="_carbonads_js"></script>

View File

@@ -4,25 +4,21 @@
"license": "MIT",
"private": true,
"devDependencies": {
"async": "^2.5.0",
"babel-eslint": "^7.2.3",
"bundlesize": "^0.14.4",
"chalk": "^2.1.0",
"eslint-plugin-jasmine": "^2.7.1",
"bundlesize": "^0.15.3",
"jsdoc-to-markdown": "^3.0.0",
"lcov-result-merger": "^1.2.0",
"lerna": "^2.2.0",
"lint-staged": "^4.0.1",
"pre-commit": "^1.2.2",
"prettier-eslint-cli": "^4.1.1",
"wait-on": "^2.0.2"
"wait-on": "^2.0.2",
"which-pm-runs-cli": "^1.0.4"
},
"scripts": {
"postinstall": "which-pm-runs --is yarn",
"precommit": "lint-staged",
"postinstall": "lerna bootstrap",
"bootstrap": "lerna bootstrap",
"pretest": "$BUNDLESIZE && bundlesize-init",
"test": "lerna run --parallel test && yarn build",
"posttest": "$BUNDLESIZE && bundlesize",
"test": "lerna run --parallel test",
"test:dev": "lerna run --parallel test:dev",
"build": "lerna run build",
"docs": "yarn build && for dest in popper tooltip; do jsdoc2md ./packages/$dest/dist/$dest.js > ./docs/_includes/$dest-documentation.md; done",
"docs:serve": "cd docs; { wait-on http://localhost:4000; open http://localhost:4000; } & jekyll serve"

View File

@@ -1,83 +1,137 @@
const { rollup } = require('rollup');
const { rollup, watch } = require('rollup');
const rimraf = require('rimraf');
const { argv } = require('yargs');
// Plugins
const babel = require('rollup-plugin-babel');
const babili = require('rollup-plugin-babel-minify');
const watchEnabled = argv.watch;
// Configs
const babelConfig = require('@popperjs/babel-config');
const sourceMap = true;
const sourcemap = true;
const external = ['popper.js'];
const globals = { 'popper.js': 'Popper' };
function bundle({ entry, dest, moduleName, banner, miniBanner }) {
function bundle({ input, file, name, banner, miniBanner }) {
rimraf.sync('dist');
const minifyOptions = {
comments: false,
banner: miniBanner,
mangle: { topLevel: true },
};
rollup({
entry,
input,
plugins: [babel(babelConfig.es6)],
external,
}).then(bundle => {
bundle.write({
format: 'es',
dest: `dist/${dest}`,
sourceMap,
file: `dist/${file}`,
sourcemap,
globals,
banner,
});
});
rollup({
entry,
plugins: [babili({ comments: false, banner: miniBanner }), babel(babelConfig.es6)],
input,
plugins: [babili(minifyOptions), babel(babelConfig.es6)],
external,
}).then(bundle => {
bundle.write({
format: 'es',
dest: `dist/${dest.replace('.js', '.min.js')}`,
sourceMap,
file: `dist/${file.replace('.js', '.min.js')}`,
sourcemap,
globals,
});
});
rollup({
entry,
input,
plugins: [babel(babelConfig.es5)],
external,
}).then(bundle => {
bundle.write({
format: 'umd',
dest: `dist/umd/${dest}`,
sourceMap,
file: `dist/umd/${file}`,
sourcemap,
globals,
moduleName,
name,
banner,
});
bundle.write({
format: 'es',
dest: `dist/esm/${dest}`,
sourceMap,
file: `dist/esm/${file}`,
sourcemap,
globals,
banner,
});
});
rollup({
entry,
plugins: [babili({ comments: false, banner: miniBanner }), babel(babelConfig.es5)],
input,
plugins: [babili(minifyOptions), babel(babelConfig.es5)],
external,
}).then(bundle => {
bundle.write({
format: 'umd',
dest: `dist/umd/${dest.replace('.js', '.min.js')}`,
sourceMap,
file: `dist/umd/${file.replace('.js', '.min.js')}`,
sourcemap,
globals,
moduleName,
name,
});
bundle.write({
format: 'es',
dest: `dist/esm/${dest.replace('.js', '.min.js')}`,
sourceMap,
file: `dist/esm/${file.replace('.js', '.min.js')}`,
sourcemap,
});
});
}
module.exports = bundle;
function bundleWatch({ input, file, name, banner, miniBanner }) {
const watcher = watch({
input,
plugins: [babel(babelConfig.es5)],
external,
output: {
format: 'umd',
file: `dist/umd/${file}`,
sourcemap,
globals,
name,
banner,
},
});
console.log('\x1Bc'); // reset console
console.log('Rollup is watching for changes...');
watcher.on('event', event => {
switch (event.code) {
case 'START':
console.info('Rebuilding...');
break;
case 'BUNDLE_START':
console.info('Bundling...');
break;
case 'BUNDLE_END':
console.info('Bundled!');
break;
case 'END':
console.info('Done!');
break;
case 'ERROR':
case 'FATAL':
console.error('Error!');
/* eslint-enable no-console */
}
});
process.on('exit', () => {
watcher.close();
});
}
module.exports = watchEnabled ? bundleWatch : bundle;

View File

@@ -6,8 +6,10 @@
"license": "MIT",
"dependencies": {
"@popperjs/babel-config": "^1.0.0",
"rollup": "^0.43.0",
"rimraf": "^2.6.2",
"rollup": "^0.51.5",
"rollup-plugin-babel": "^2.7.1",
"rollup-plugin-babel-minify": "^3.1.2"
"rollup-plugin-babel-minify": "^3.1.2",
"yargs": "^10.0.3"
}
}

View File

@@ -53,7 +53,7 @@ Some of the key points are:
Visit our [project page](https://fezvrasta.github.io/popper.js) to see a lot of examples of what you can do with Popper.js!
Find [the documentation here](docs/_includes/popper-documentation.md).
Find [the documentation here](/docs/_includes/popper-documentation.md).
### Tooltip.js
@@ -65,7 +65,7 @@ Its API is almost identical to the famous tooltip system of Bootstrap, in this w
easy to integrate it in your projects.
The tooltips generated by Tooltip.js are accessible thanks to the `aria` tags.
Find [the documentation here](docs/_includes/tooltip-documentation.md).
Find [the documentation here](/docs/_includes/tooltip-documentation.md).
## Installation
@@ -156,7 +156,7 @@ you can simply disable it and manually apply the popper coordinates using
your library of choice.
For a comprehensive list of libraries that let you use Popper.js into existing
frameworks, visit the [MENTIONS](MENTIONS.md) page.
frameworks, visit the [MENTIONS](/MENTIONS.md) page.
Alternatively, you may even override your own `applyStyles` with your custom one and
integrate Popper.js by yourself!
@@ -202,7 +202,7 @@ This means that it will not cause any [jank](https://www.chromium.org/developers
The aim of Popper.js is to provide a stable and powerful positioning engine ready to
be used in 3rd party libraries.
Visit the [MENTIONS](MENTIONS.md) page for an updated list of projects.
Visit the [MENTIONS](/MENTIONS.md) page for an updated list of projects.
### Credits

View File

@@ -5,7 +5,8 @@ version="$(cat package.json | jq -r '.version')"
# Bower doesn't support Lerna multi-packages, we sacrificy flexibity
# making Bower use the whole repository just for the Popper.js release
cp -R dist ../../dist
rm -rf ../../dist
cp -R dist ../../
cp bower.json ../../bower.json
git add -f ../../dist/*
git add ../../bower.json

View File

@@ -31,17 +31,17 @@ const miniBanner = `/*
*/`
bundle({
moduleName: 'Popper',
entry: 'src/index.js',
dest: 'popper.js',
name: 'Popper',
input: 'src/index.js',
file: 'popper.js',
banner,
miniBanner,
});
bundle({
moduleName: 'PopperUtils',
entry: 'src/utils/index.js',
dest: 'popper-utils.js',
name: 'PopperUtils',
input: 'src/utils/index.js',
file: 'popper-utils.js',
banner,
miniBanner,
});

View File

@@ -1,6 +1,6 @@
{
"name": "popper.js",
"version": "1.12.6",
"version": "1.12.9",
"description": "A kickass library to manage your poppers",
"homepage": "https://popper.js.org",
"repository": {
@@ -28,23 +28,23 @@
"module": "dist/esm/popper.js",
"types": "index.d.ts",
"scripts": {
"prepare": "npm run build",
"prepare": "yarn build",
"postpublish": "nuget-publish && ./bower-publish.sh",
"prebuild": "npm run lint",
"pretest": "npm run lint",
"prebuild": "yarn lint",
"pretest": "yarn lint",
"build": "node bundle.js",
"lint": "eslint .",
"test": "popper-karma",
"test:dev": "BROWSERS=Chrome NODE_ENV=development npm run test",
"coverage": "NODE_ENV=coverage npm run test"
"test:dev": "BROWSERS=Chrome NODE_ENV=development yarn test",
"coverage": "COVERAGE=true yarn test"
},
"devDependencies": {
"@popperjs/bundle": "^1.0.2",
"@popperjs/eslint-config-popper": "^1.0.0",
"nuget-publish": "^1.0.3",
"@popperjs/test": "^1.0.0",
"@popperjs/test-utils": "^1.0.0",
"eslint": "^4.1.1"
"eslint": "^4.1.1",
"nuget-publish": "^1.0.3"
},
"resolutions": {
"micromatch": "^3.0.3"

View File

@@ -9,7 +9,7 @@ import removeEventListeners from '../utils/removeEventListeners';
*/
export default function disableEventListeners() {
if (this.state.eventsEnabled) {
window.cancelAnimationFrame(this.scheduleUpdate);
cancelAnimationFrame(this.scheduleUpdate);
this.state = removeEventListeners(this.reference, this.state);
}
}

View File

@@ -63,26 +63,27 @@ export default function arrow(data, options) {
data.offsets.popper[side] +=
reference[side] + arrowElementSize - popper[opSide];
}
data.offsets.popper = getClientRect(data.offsets.popper);
// compute center of the popper
const center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
// Compute the sideValue using the updated popper offsets
// take popper margin in account because we don't have this info available
const popperMarginSide = getStyleComputedProperty(
data.instance.popper,
`margin${sideCapitalized}`
).replace('px', '');
const css = getStyleComputedProperty(data.instance.popper);
const popperMarginSide = parseFloat(css[`margin${sideCapitalized}`], 10);
const popperBorderSide = parseFloat(css[`border${sideCapitalized}Width`], 10);
let sideValue =
center - getClientRect(data.offsets.popper)[side] - popperMarginSide;
center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
// prevent arrowElement from being placed not contiguously to its popper
sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
data.arrowElement = arrowElement;
data.offsets.arrow = {};
data.offsets.arrow[side] = Math.round(sideValue);
data.offsets.arrow[altSide] = ''; // make sure to unset any eventual altSide value from the DOM node
data.offsets.arrow = {
[side]: Math.round(sideValue),
[altSide]: '', // make sure to unset any eventual altSide value from the DOM node
};
return data;
}

View File

@@ -1,4 +1,4 @@
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
const isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
const longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
let timeoutDuration = 0;
for (let i = 0; i < longerTimeoutBrowsers.length; i += 1) {
@@ -15,7 +15,7 @@ export function microtaskDebounce(fn) {
return
}
called = true
Promise.resolve().then(() => {
window.Promise.resolve().then(() => {
called = false
fn()
})

View File

@@ -13,7 +13,7 @@ import getOffsetParent from './getOffsetParent';
export default function findCommonOffsetParent(element1, element2) {
// This check is needed to avoid errors in case one of the elements isn't defined for any reason
if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
return window.document.documentElement;
return document.documentElement;
}
// Here we make sure to give as "start" the element that comes first in the DOM

View File

@@ -13,7 +13,7 @@ export default function getBordersSize(styles, axis) {
const sideB = sideA === 'Left' ? 'Right' : 'Bottom';
return (
+styles[`border${sideA}Width`].split('px')[0] +
+styles[`border${sideB}Width`].split('px')[0]
parseFloat(styles[`border${sideA}Width`], 10) +
parseFloat(styles[`border${sideB}Width`], 10)
);
}

View File

@@ -33,7 +33,7 @@ export default function getBoundaries(
// Handle other cases based on DOM element used as boundaries
let boundariesNode;
if (boundariesElement === 'scrollParent') {
boundariesNode = getScrollParent(getParentNode(popper));
boundariesNode = getScrollParent(getParentNode(reference));
if (boundariesNode.nodeName === 'BODY') {
boundariesNode = popper.ownerDocument.documentElement;
}

View File

@@ -16,7 +16,7 @@ export default function getOffsetParent(element) {
return element.ownerDocument.documentElement
}
return window.document.documentElement;
return document.documentElement;
}
// .offsetParent will return the closest TD or TABLE in case

View File

@@ -13,8 +13,8 @@ export default function getOffsetRectRelativeToArbitraryNode(children, parent) {
const scrollParent = getScrollParent(children);
const styles = getStyleComputedProperty(parent);
const borderTopWidth = +styles.borderTopWidth.split('px')[0];
const borderLeftWidth = +styles.borderLeftWidth.split('px')[0];
const borderTopWidth = parseFloat(styles.borderTopWidth, 10);
const borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
let offsets = getClientRect({
top: childrenRect.top - parentRect.top - borderTopWidth,
@@ -30,8 +30,8 @@ export default function getOffsetRectRelativeToArbitraryNode(children, parent) {
// differently when margins are applied to it. The margins are included in
// the box of the documentElement, in the other cases not.
if (!isIE10 && isHTML) {
const marginTop = +styles.marginTop.split('px')[0];
const marginLeft = +styles.marginLeft.split('px')[0];
const marginTop = parseFloat(styles.marginTop, 10);
const marginLeft = parseFloat(styles.marginLeft, 10);
offsets.top -= borderTopWidth - marginTop;
offsets.bottom -= borderTopWidth - marginTop;

View File

@@ -6,7 +6,7 @@
* @returns {Object} object containing width and height properties
*/
export default function getOuterSizes(element) {
const styles = window.getComputedStyle(element);
const styles = getComputedStyle(element);
const x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
const y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
const result = {

View File

@@ -11,7 +11,7 @@ import getParentNode from './getParentNode';
export default function getScrollParent(element) {
// Return body, `getScroll` will take care to get the correct `scrollTop` from it
if (!element) {
return window.document.body
return document.body
}
switch (element.nodeName) {

View File

@@ -10,6 +10,6 @@ export default function getStyleComputedProperty(element, property) {
return [];
}
// NOTE: 1 DOM access here
const css = window.getComputedStyle(element, null);
const css = getComputedStyle(element, null);
return property ? css[property] : css;
}

View File

@@ -12,7 +12,7 @@ export default function getSupportedPropertyName(property) {
for (let i = 0; i < prefixes.length - 1; i++) {
const prefix = prefixes[i];
const toCheck = prefix ? `${prefix}${upperProp}` : property;
if (typeof window.document.body.style[toCheck] !== 'undefined') {
if (typeof document.body.style[toCheck] !== 'undefined') {
return toCheck;
}
}

View File

@@ -16,9 +16,9 @@ function getSize(axis, body, html, computedStyle) {
}
export default function getWindowSizes() {
const body = window.document.body;
const html = window.document.documentElement;
const computedStyle = isIE10() && window.getComputedStyle(html);
const body = document.body;
const html = document.documentElement;
const computedStyle = isIE10() && getComputedStyle(html);
return {
height: getSize('Height', body, html, computedStyle),

View File

@@ -8,13 +8,13 @@ const browsers = (argv.browsers ||
'ChromeHeadless'
).split(',');
const singleRun = process.env.NODE_ENV === 'development' ? false : true;
const coverage = process.env.COVERAGE === true;
const coverage = process.env.COVERAGE === 'true';
const basePath = process.cwd();
const babelrc = {
babelrc: false,
presets: [
[require.resolve('babel-preset-es2015'), { modules: false }],
[require.resolve('babel-preset-env'), { modules: false }],
require.resolve('babel-preset-stage-2'),
],
plugins: [
@@ -97,11 +97,16 @@ module.exports = function(config) {
version: '11',
platform: 'Windows 10',
},
SLiOS9: {
// Currently not used because the iOS emulator isn't reliable and
// most of the times it times out
SLiOS11: {
base: 'SauceLabs',
browserName: 'iphone',
version: '9.3',
platform: 'macOS 10.12',
browserName: 'Safari',
deviceName: 'iPhone 8 Plus Simulator',
deviceOrientation: 'portrait',
platformVersion: '11.0',
platformName: 'iOS',
appiumVersion: '1.7.1',
},
SLChromeMobile: {
base: 'SauceLabs',
@@ -139,14 +144,7 @@ module.exports = function(config) {
recordVideo: true,
tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER,
},
coverageReporter: {
dir: './.tmp/coverage',
reporters: [
{ type: 'html', subdir: 'report-html' },
{ type: 'lcov', subdir: 'report-lcov' },
],
},
reporters: ['mocha', 'saucelabs', 'coverage'],
reporters: ['mocha', 'saucelabs'],
plugins: [
require('karma-chai'),
require('karma-chrome-launcher'),
@@ -161,5 +159,16 @@ module.exports = function(config) {
],
};
if (coverage) {
configuration.coverageReporter = {
dir: './.tmp/coverage',
reporters: [
{ type: 'html', subdir: 'report-html' },
{ type: 'lcov', subdir: 'report-lcov' },
],
};
configuration.reporters.push('coverage');
}
config.set(configuration);
};

View File

@@ -16,14 +16,11 @@
"babel-plugin-external-helpers": "^6.22.0",
"babel-plugin-istanbul": "^4.1.4",
"babel-plugin-module-resolver": "^2.7.1",
"babel-preset-es2015": "^6.24.1",
"babel-preset-minify": "^0.2.0",
"babel-preset-stage-2": "^6.24.1",
"chai": "^4.0.1",
"eslint": "^4.0.0",
"eslint-plugin-jasmine": "^2.6.2",
"gitignore-to-glob": "^0.3.0",
"gzipped": "^0.0.5",
"jasmine-core": "^2.6.2",
"karma": "^1.7.0",
"karma-chai": "^0.1.0",

View File

@@ -31,9 +31,9 @@ const miniBanner = `/*
*/`
bundle({
moduleName: 'Tooltip',
entry: 'src/index.js',
dest: 'tooltip.js',
name: 'Tooltip',
input: 'src/index.js',
file: 'tooltip.js',
banner,
miniBanner,
});

View File

@@ -1,16 +1,17 @@
{
"name": "tooltip.js",
"version": "1.1.5",
"version": "1.1.7",
"description": "A kickass library to create tooltips, based on Popper.js",
"main": "./dist/umd/tooltip.js",
"module": "./dist/esm/tooltip.js",
"scripts": {
"build": "node bundle.js",
"prepublish": "npm run build",
"pretest": "npm run lint",
"prepublish": "yarn build",
"pretest": "yarn lint",
"test": "popper-karma",
"test:dev": "BROWSERS=Chrome NODE_ENV=development yarn test",
"lint": "eslint .",
"coverage": "NODE_ENV=coverage npm run test"
"coverage": "COVERAGE=true yarn test"
},
"repository": {
"type": "git",

View File

@@ -58,16 +58,18 @@ export default class Tooltip {
this.options = options;
// get events list
const events = typeof options.trigger === 'string'
? options.trigger
.split(' ')
.filter(
trigger => ['click', 'hover', 'focus'].indexOf(trigger) !== -1
)
: [];
const events =
typeof options.trigger === 'string'
? options.trigger
.split(' ')
.filter(
trigger => ['click', 'hover', 'focus'].indexOf(trigger) !== -1
)
: [];
// set initial state
this._isOpen = false;
this._popperOptions = {};
// set event listeners
this._setEventListeners(reference, events, options);
@@ -141,15 +143,17 @@ export default class Tooltip {
const tooltipNode = tooltipGenerator.childNodes[0];
// add unique ID to our tooltip (needed for accessibility reasons)
tooltipNode.id = `tooltip_${Math.random().toString(36).substr(2, 10)}`;
tooltipNode.id = `tooltip_${Math.random()
.toString(36)
.substr(2, 10)}`;
// set initial `aria-hidden` state to `false` (it's visible!)
tooltipNode.setAttribute('aria-hidden', 'false');
// add title to tooltip
const titleNode = tooltipGenerator.querySelector(this.innerSelector);
if (title.nodeType === 1) {
// if title is a node, append it only if allowHtml is true
if (title.nodeType === 1 || title.nodeType === 11) {
// if title is a element node or document fragment, append it only if allowHtml is true
allowHtml && titleNode.appendChild(title);
} else if (isFunction(title)) {
// if title is a function, call it and set innerText or innerHtml depending by `allowHtml` value
@@ -168,7 +172,8 @@ export default class Tooltip {
_show(reference, options) {
// don't show if it's already visible
if (this._isOpen) {
// or if it's not being showed
if (this._isOpen && !this._isOpening) {
return this;
}
this._isOpen = true;
@@ -205,25 +210,32 @@ export default class Tooltip {
this._append(tooltipNode, container);
const popperOptions = {
this._popperOptions = {
...options.popperOptions,
placement: options.placement,
}
};
popperOptions.modifiers = {
...popperOptions.modifiers,
this._popperOptions.modifiers = {
...this._popperOptions.modifiers,
arrow: {
element: this.arrowSelector,
},
}
offset: {
offset: options.offset,
},
};
if (options.boundariesElement) {
popperOptions.modifiers.preventOverflow = {
this._popperOptions.modifiers.preventOverflow = {
boundariesElement: options.boundariesElement,
};
}
this.popperInstance = new Popper(reference, tooltipNode, popperOptions);
this.popperInstance = new Popper(
reference,
tooltipNode,
this._popperOptions
);
this._tooltipNode = tooltipNode;
@@ -259,9 +271,9 @@ export default class Tooltip {
this.popperInstance.destroy();
// destroy tooltipNode if removeOnDestroy is not set, as popperInstance.destroy() already removes the element
if(!this.popperInstance.options.removeOnDestroy){
this._tooltipNode.parentNode.removeChild(this._tooltipNode);
this._tooltipNode = null;
if (!this.popperInstance.options.removeOnDestroy) {
this._tooltipNode.parentNode.removeChild(this._tooltipNode);
this._tooltipNode = null;
}
}
return this;
@@ -313,7 +325,7 @@ export default class Tooltip {
// schedule show tooltip
directEvents.forEach(event => {
const func = evt => {
if (this._isOpen === true) {
if (this._isOpening === true) {
return;
}
evt.usedByTooltip = true;
@@ -337,15 +349,21 @@ export default class Tooltip {
}
_scheduleShow(reference, delay, options /*, evt */) {
this._isOpening = true;
// defaults to 0
const computedDelay = (delay && delay.show) || delay || 0;
window.setTimeout(() => this._show(reference, options), computedDelay);
this._showTimeout = window.setTimeout(
() => this._show(reference, options),
computedDelay
);
}
_scheduleHide(reference, delay, options, evt) {
this._isOpening = false;
// defaults to 0
const computedDelay = (delay && delay.hide) || delay || 0;
window.setTimeout(() => {
window.clearTimeout(this._showTimeout);
if (this._isOpen === false) {
return;
}
@@ -370,10 +388,12 @@ export default class Tooltip {
}
_setTooltipNodeEvent = (evt, reference, delay, options) => {
const relatedreference = evt.relatedreference || evt.toElement;
const relatedreference =
evt.relatedreference || evt.toElement || evt.relatedTarget;
const callback = evt2 => {
const relatedreference2 = evt2.relatedreference || evt2.toElement;
const relatedreference2 =
evt2.relatedreference || evt2.toElement || evt2.relatedTarget;
// Remove event listener after call
this._tooltipNode.removeEventListener(evt.type, callback);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
@extends('layouts.default.app')
@section('title', 'live map')
@section('content')
@include('layouts.default.acars.map')
<div class="clearfix" style="padding-top: 25px"></div>
@include('layouts.default.acars.table')
@endsection

Some files were not shown because too many files have changed in this diff Show More