Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Socket
Sign inDemoInstall

labelgun

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

labelgun - npm Package Compare versions

Comparing version 0.1.1 to 2.0.0

.eslintrc.js

200

lib/labelgun.js

@@ -10,14 +10,14 @@ (function webpackUniversalModuleDefinition(root, factory) {

root["labelgun"] = factory(root["rbush"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_0__) {
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)

@@ -29,23 +29,20 @@ /******/ var module = installedModules[moduleId] = {

/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports

@@ -61,3 +58,3 @@ /******/ __webpack_require__.d = function(exports, name, getter) {

/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules

@@ -71,11 +68,11 @@ /******/ __webpack_require__.n = function(module) {

/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 1);
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })

@@ -85,13 +82,7 @@ /************************************************************************/

/* 0 */
/***/ function(module, exports) {
/***/ (function(module, exports, __webpack_require__) {
module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
"use strict";
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
"use strict";
"use strict";
Object.defineProperty(exports, "__esModule", {

@@ -103,3 +94,3 @@ value: true

var _rbush = __webpack_require__(0);
var _rbush = __webpack_require__(1);

@@ -114,3 +105,10 @@ var _rbush2 = _interopRequireDefault(_rbush);

/** Class representing a labelgun instance */
var labelgun = function () {
/**
* @summary create a label gun instance with a hide and show label callback
* @param {function} hideLabel the function responsible for hiding the label on hide event
* @param {function} showLabel the function responsible for showing the label on show event
*/
function labelgun(hideLabel, showLabel) {

@@ -127,12 +125,11 @@ _classCallCheck(this, labelgun);

this.showLabel = showLabel;
var self = this;
}
/**
* @name _total
* @summary get the total hidden or shown labels in the tree
* @param {string} state whether to return 'hide' or 'show' state label totals
* @returns {number} total number of labels of taht state
*/
* @name _total
* @summary get the total hidden or shown labels in the tree
* @param {string} state whether to return 'hide' or 'show' state label totals
* @returns {number} total number of labels of that state
* @private
*/

@@ -177,7 +174,7 @@

/**
* @name getLabelsByState
* @summary provided a state get all labels of that state
* @returns {array}
* @private
*/
* @name getLabelsByState
* @summary provided a state get all labels of that state
* @returns {array}
* @private
*/

@@ -197,6 +194,6 @@ }, {

/**
* @name getHidden
* @summary Return
* @returns {array}
*/
* @name getHidden
* @summary Return
* @returns {array}
*/

@@ -234,2 +231,4 @@ }, {

var self = collisions.indexOf(label);
// Remove the label if it's colliding with itself
if (self !== undefined) collisions.splice(self, 1);

@@ -241,3 +240,3 @@ return collisions;

* @name getLabel
* @summary Convience function to return a label by ID
* @summary Convenience function to return a label by ID
* @param {string} id the ID of the label to get

@@ -265,5 +264,5 @@ * @returns {object}

/**
* @name forceLabelStates
* @name updateLabelStates
* @summary Allows you to set a state for all current labels
* @param {string} forceState the class of which to change the label to
* @param {string} [forceState] the class of which to change the label to
* @returns {undefined}

@@ -273,4 +272,4 @@ */

}, {
key: "forceLabelStates",
value: function forceLabelStates(forceState) {
key: "updateLabelStates",
value: function updateLabelStates(forceState) {
var _this = this;

@@ -301,4 +300,4 @@

/**
* @name _setupLabelStates
* @summary Clears current tree and readds all stations
* @name setupLabelStates
* @summary Setups the labels depending on whether all have changed or some have changed
* @returns {undefined}

@@ -336,3 +335,3 @@ */

topRight: [label.maxX, label.maxY]
}, label._id, label.weight, label.labelObject, label.name, label.isDragged);
}, label.id, label.weight, label.labelObject, label.name, label.isDragged);
});

@@ -343,4 +342,4 @@ }

/**
* @name _resetTree
* @summary Clears current tree and redraws projection overlay
* @name update
* @summary Sets all labels to change and reruns the whole show/hide procedure
* @returns {undefined}

@@ -356,5 +355,12 @@ */

this.handleExCollisions();
this._hideShownCollisions(); // HACK ALERT: why is this necessary ? :(
this.forceLabelStates();
this._hideShownCollisions(); // TODO: why is this necessary ? :(
this.updateLabelStates();
}
/**
* @name handleExCollisions
* @summary Checks to see if a previously hidden/collided label is now able to be shown and then changes there state
* @returns {undefined}
*/
}, {

@@ -366,3 +372,18 @@ key: "handleExCollisions",

this.getHidden().forEach(function (hidden) {
_this3._handleExCollisions(hidden);
if (hidden.state === "hide") {
var stillCollides = false;
var hiddenLabels = _this3.tree.search(hidden);
for (var i = 0; i < hiddenLabels.length; i++) {
if (hiddenLabels[i].state !== "hide") {
stillCollides = true;
break;
}
}
if (!stillCollides) {
hidden.state = "show";
}
}
});

@@ -373,3 +394,3 @@ }

* @name _resetTree
* @summary Clears current tree and redraws projection overlay
* @summary Clears current tree containing all inputted labels
* @returns {undefined}

@@ -409,3 +430,3 @@ * @private

labelObject: labelObject,
labelName: labelName,
name: labelName,
isDragged: isDragged

@@ -431,3 +452,3 @@ };

delete this.allLabels[id];
if (forceUpdate) this.forceLabelStates(true);
if (forceUpdate) this.updateLabelStates(true);
}

@@ -476,3 +497,3 @@

key: "_handleCollisions",
value: function _handleCollisions(collisions, label, isDragged) {
value: function _handleCollisions(collisions, label) {
var originalWeight = void 0;

@@ -486,2 +507,5 @@ if (label.isDragged) label.weight = Infinity;

originalWeight = collision.weight;
// We set the dragged marker to the highest weight
// and make its weight unbeatable (infinity)
highest = collision;

@@ -504,30 +528,3 @@ highest.weight = Infinity;

/**
* @name _handleExCollisions
* @param {object} hidden hidden label
* @summary Checks to see if a previously hidden/collided label is now able to be shown and then shows
* @returns {undefined}
* @private
*/
}, {
key: "_handleExCollisions",
value: function _handleExCollisions(hidden) {
if (hidden.state === "hide") {
var stillCollides = false;
var hiddenLabels = this.tree.search(hidden);
for (var i = 0; i < hiddenLabels.length; i++) {
if (hiddenLabels[i].state !== "hide") {
stillCollides = true;
break;
}
}
if (!stillCollides) {
hidden.state = "show";
}
}
}
/**
* @name _ingestLabel
* @name ingestLabel
* @param {object} boundingBox

@@ -539,3 +536,3 @@ * @param {string} id

* @param {boolean} isDragged
* @summary Creates a label if it does not already exsist, then adds it to the tree, and renders it based on whether it can be shown
* @summary Creates a label if it does not already exist, then adds it to the tree, and renders it based on whether it can be shown
* @returns {object}

@@ -547,8 +544,16 @@ */

value: function ingestLabel(boundingBox, id, weight, labelObject, labelName, isDragged) {
var label = this._makeLabel(boundingBox, id, weight, labelObject, labelName, isDragged);
// If there is already a label in the tree, remove it
var oldLabel = this.allLabels[id];
if (oldLabel) this.removeFromTree(oldLabel);
// Add the new label to the tree
var label = this._makeLabel(boundingBox, id, weight, labelObject, labelName, isDragged);
this._addToTree(label);
// Get all of its collisions
var collisions = this.getCollisions(id);
if (!collisions.length || isDragged) {
// If the collisions are non existance we can show it
if (!collisions.length) {
label.state = "show";

@@ -558,2 +563,3 @@ return;

// Else we need to handle the collisions and decide which one to show
this._handleCollisions(collisions, label, isDragged);

@@ -580,4 +586,10 @@ }

/***/ }
/***/ }),
/* 1 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
/***/ })
/******/ ]);
});

@@ -1,1 +0,1 @@

!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("rbush")):"function"==typeof define&&define.amd?define(["rbush"],t):"object"==typeof exports?exports.labelgun=t(require("rbush")):e.labelgun=t(e.rbush)}(this,function(e){return function(e){function t(i){if(a[i])return a[i].exports;var n=a[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,t),n.l=!0,n.exports}var a={};return t.m=e,t.c=a,t.i=function(e){return e},t.d=function(e,a,i){t.o(e,a)||Object.defineProperty(e,a,{configurable:!1,enumerable:!0,get:i})},t.n=function(e){var a=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(a,"a",a),a},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=1)}([function(t,a){t.exports=e},function(e,t,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function n(e){if(Array.isArray(e)){for(var t=0,a=Array(e.length);t<e.length;t++)a[t]=e[t];return a}return Array.from(e)}function l(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var s=function(){function e(e,t){for(var a=0;a<t.length;a++){var i=t[a];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,a,i){return a&&e(t.prototype,a),i&&e(t,i),t}}(),r=a(0),o=i(r),h=function(){function e(t,a){l(this,e),this.tree=(0,o.default)(6),this.allLabels={},this._point=void 0,this.hasChanged=new Set,this.loaded=!1,this.allChanged=!1,this.hideLabel=t,this.showLabel=a}return s(e,[{key:"_total",value:function(e){var t=0;for(var a in this.allLabels)this.allLabels[a].state==e&&(t+=1);return t}},{key:"totalShown",value:function(){return this._total("show")}},{key:"totalHidden",value:function(){return this._total("hide")}},{key:"_getLabelsByState",value:function(e){var t=[];for(var a in this.allLabels)this.allLabels[a].state==e&&t.push(this.allLabels[a]);return t}},{key:"getHidden",value:function(){return this._getLabelsByState("hide")}},{key:"getShown",value:function(){return this._getLabelsByState("show")}},{key:"getCollisions",value:function(e){var t=this.allLabels[e],a=this.tree.search(t),i=a.indexOf(t);return void 0!==i&&a.splice(i,1),a}},{key:"getLabel",value:function(e){return this.allLabels[e]}},{key:"destroy",value:function(){this._resetTree(),this.allLabels={}}},{key:"forceLabelStates",value:function(e){var t=this;this.tree.all().forEach(function(a){t._labelHasChangedState(a,e)})}},{key:"_labelHasChangedState",value:function(e,t){var a=t||e.state;"show"===a&&this.showLabel(e),"hide"===a&&this.hideLabel(e)}},{key:"setupLabelStates",value:function(){var e=this;if(this.allChanged){this.allChanged=!1,this.hasChanged.clear(),this._resetTree();for(var t in this.allLabels){var a=this.allLabels[t];this.ingestLabel({bottomLeft:[a.minX,a.minY],topRight:[a.maxX,a.maxY]},a.id,a.weight,a.labelObject,a.name,a.isDragged)}}else if(this.hasChanged.size){var i=[].concat(n(this.hasChanged));this.hasChanged.clear(),i.forEach(function(t){var a=e.allLabels[t];e.ingestLabel({bottomLeft:[a.minX,a.minY],topRight:[a.maxX,a.maxY]},a._id,a.weight,a.labelObject,a.name,a.isDragged)})}}},{key:"update",value:function(){this.allChanged=!0,this.setupLabelStates(),this.handleExCollisions(),this._hideShownCollisions(),this.forceLabelStates()}},{key:"handleExCollisions",value:function(){var e=this;this.getHidden().forEach(function(t){e._handleExCollisions(t)})}},{key:"_resetTree",value:function(){this.tree.clear()}},{key:"_makeLabel",value:function(e,t,a,i,n,l){return{minX:e.bottomLeft[0],minY:e.bottomLeft[1],maxX:e.topRight[0],maxY:e.topRight[1],state:"hide",id:t,weight:a||1,labelObject:i,labelName:n,isDragged:l}}},{key:"removeFromTree",value:function(e,t){var a=e.id||e,i=this.allLabels[a];this.tree.remove(i),delete this.allLabels[a],t&&this.forceLabelStates(!0)}},{key:"_addToTree",value:function(e){this.allLabels[e.id]=e,this.tree.insert(e)}},{key:"_hideShownCollisions",value:function(){var e=this;this.getShown().forEach(function(t){e.getCollisions(t.id).forEach(function(e){"show"==e.state&&(e.state="hide")})})}},{key:"_handleCollisions",value:function(e,t,a){var i=void 0;t.isDragged&&(t.weight=1/0);var n=t;e.forEach(function(e){e.isDragged&&(i=e.weight,n=e,n.weight=1/0),e.weight>n.weight?(n.state="hide",n=e):e.state="hide"}),n.state="show",i&&(n.weight=i)}},{key:"_handleExCollisions",value:function(e){if("hide"===e.state){for(var t=!1,a=this.tree.search(e),i=0;i<a.length;i++)if("hide"!==a[i].state){t=!0;break}t||(e.state="show")}}},{key:"ingestLabel",value:function(e,t,a,i,n,l){var s=this._makeLabel(e,t,a,i,n,l),r=this.allLabels[t];r&&this.removeFromTree(r),this._addToTree(s);var o=this.getCollisions(t);return!o.length||l?void(s.state="show"):void this._handleCollisions(o,s,l)}},{key:"labelHasChanged",value:function(e){this.hasChanged.add(e)}}]),e}();t.default=h}])});
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("rbush")):"function"==typeof define&&define.amd?define(["rbush"],t):"object"==typeof exports?exports.labelgun=t(require("rbush")):e.labelgun=t(e.rbush);}(this,function(e){return function(e){function t(i){if(a[i])return a[i].exports;var n=a[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,t),n.l=!0,n.exports;}var a={};return t.m=e,t.c=a,t.i=function(e){return e;},t.d=function(e,a,i){t.o(e,a)||Object.defineProperty(e,a,{configurable:!1,enumerable:!0,get:i});},t.n=function(e){var a=e&&e.__esModule?function(){return e.default;}:function(){return e;};return t.d(a,"a",a),a;},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t);},t.p="",t(t.s=1);}([function(t,a){t.exports=e;},function(e,t,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e};}function n(e){if(Array.isArray(e)){for(var t=0,a=Array(e.length);t<e.length;t++)a[t]=e[t];return a;}return Array.from(e);}function l(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function");}Object.defineProperty(t,"__esModule",{value:!0});var s=function(){function e(e,t){for(var a=0;a<t.length;a++){var i=t[a];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i);}}return function(t,a,i){return a&&e(t.prototype,a),i&&e(t,i),t;};}(),r=a(0),o=i(r),h=function(){function e(t,a){l(this,e),this.tree=(0,o.default)(6),this.allLabels={},this._point=void 0,this.hasChanged=new Set,this.loaded=!1,this.allChanged=!1,this.hideLabel=t,this.showLabel=a;}return s(e,[{key:"_total",value:function(e){var t=0;for(var a in this.allLabels)this.allLabels[a].state==e&&(t+=1);return t;}},{key:"totalShown",value:function(){return this._total("show");}},{key:"totalHidden",value:function(){return this._total("hide");}},{key:"_getLabelsByState",value:function(e){var t=[];for(var a in this.allLabels)this.allLabels[a].state==e&&t.push(this.allLabels[a]);return t;}},{key:"getHidden",value:function(){return this._getLabelsByState("hide");}},{key:"getShown",value:function(){return this._getLabelsByState("show");}},{key:"getCollisions",value:function(e){var t=this.allLabels[e],a=this.tree.search(t),i=a.indexOf(t);return void 0!==i&&a.splice(i,1),a;}},{key:"getLabel",value:function(e){return this.allLabels[e];}},{key:"destroy",value:function(){this._resetTree(),this.allLabels={};}},{key:"forceLabelStates",value:function(e){var t=this;this.tree.all().forEach(function(a){t._labelHasChangedState(a,e);});}},{key:"_labelHasChangedState",value:function(e,t){var a=t||e.state;"show"===a&&this.showLabel(e),"hide"===a&&this.hideLabel(e);}},{key:"setupLabelStates",value:function(){var e=this;if(this.allChanged){this.allChanged=!1,this.hasChanged.clear(),this._resetTree();for(var t in this.allLabels){var a=this.allLabels[t];this.ingestLabel({bottomLeft:[a.minX,a.minY],topRight:[a.maxX,a.maxY]},a.id,a.weight,a.labelObject,a.name,a.isDragged);}}else if(this.hasChanged.size){var i=[].concat(n(this.hasChanged));this.hasChanged.clear(),i.forEach(function(t){var a=e.allLabels[t];e.ingestLabel({bottomLeft:[a.minX,a.minY],topRight:[a.maxX,a.maxY]},a._id,a.weight,a.labelObject,a.name,a.isDragged);});}}},{key:"update",value:function(){this.allChanged=!0,this.setupLabelStates(),this.handleExCollisions(),this._hideShownCollisions(),this.forceLabelStates();}},{key:"handleExCollisions",value:function(){var e=this;this.getHidden().forEach(function(t){e._handleExCollisions(t);});}},{key:"_resetTree",value:function(){this.tree.clear();}},{key:"_makeLabel",value:function(e,t,a,i,n,l){return{minX:e.bottomLeft[0],minY:e.bottomLeft[1],maxX:e.topRight[0],maxY:e.topRight[1],state:"hide",id:t,weight:a||1,labelObject:i,labelName:n,isDragged:l};}},{key:"removeFromTree",value:function(e,t){var a=e.id||e,i=this.allLabels[a];this.tree.remove(i),delete this.allLabels[a],t&&this.forceLabelStates(!0);}},{key:"_addToTree",value:function(e){this.allLabels[e.id]=e,this.tree.insert(e);}},{key:"_hideShownCollisions",value:function(){var e=this;this.getShown().forEach(function(t){e.getCollisions(t.id).forEach(function(e){"show"==e.state&&(e.state="hide");});});}},{key:"_handleCollisions",value:function(e,t,a){var i=void 0;t.isDragged&&(t.weight=1/0);var n=t;e.forEach(function(e){e.isDragged&&(i=e.weight,n=e,n.weight=1/0),e.weight>n.weight?(n.state="hide",n=e):e.state="hide";}),n.state="show",i&&(n.weight=i);}},{key:"_handleExCollisions",value:function(e){if("hide"===e.state){for(var t=!1,a=this.tree.search(e),i=0;i<a.length;i++)if("hide"!==a[i].state){t=!0;break;}t||(e.state="show");}}},{key:"ingestLabel",value:function(e,t,a,i,n,l){var s=this._makeLabel(e,t,a,i,n,l),r=this.allLabels[t];r&&this.removeFromTree(r),this._addToTree(s);var o=this.getCollisions(t);return!o.length||l?void(s.state="show"):void this._handleCollisions(o,s,l);}},{key:"labelHasChanged",value:function(e){this.hasChanged.add(e);}}]),e;}();t.default=h;}]);});
{
"name": "labelgun",
"version": "0.1.1",
"version": "2.0.0",
"description": "A mapping library agnostic labelling engine",
"main": "lib/labelgun.js",
"scripts": {
"test": "jasmine"
"test": "jasmine",
"coverage": "istanbul cover jasmine -x 'spec/**/*.js'",
"coverage-verbose": "istanbul cover jasmine -v -i 'src/labelgun.js'",
"watch": "webpack --watch",
"build": "webpack",
"build-prod": "webpack --env.minified",
"build-both": "webpack && webpack --env.minified",
"doc": "jsdoc src/labelgun.js --destination doc/documentation"
},

@@ -12,13 +19,17 @@ "author": "James Milner <james.milner@geovation.uk> (http://geovation.uk/)",

"repository": {
"type": "git",
"url": "git@github.com:Geovation/labelgun.git"
"type": "git",
"url": "git@github.com:Geovation/labelgun.git"
},
"devDependencies": {
"babel-core": "^6.17.0",
"babel-loader": "^6.2.5",
"babel-preset-es2015": "^6.16.0",
"jasmine": "^2.5.2",
"webpack": "^2.1.0-beta.28",
"systemjs": "^0.19.39",
"whatwg-fetch": "^2.0.1"
"babel-core": "^6.26.0",
"babel-loader": "^7.1.1",
"babel-preset-env": "^1.6.0",
"babel-preset-es2015": "^6.24.1",
"eslint": "^4.4.1",
"istanbul": "^0.4.5",
"jasmine": "^2.7.0",
"jsdoc": "^3.5.4",
"systemjs": "^0.20.17",
"webpack": "^3.5.5",
"whatwg-fetch": "^2.0.3"
},

@@ -25,0 +36,0 @@ "dependencies": {

@@ -12,42 +12,74 @@ ![labelgun](logo.png)

<br><br>
![Labelgun example in leaflet](labelgun.gif)
### Install
You can install all the necessary dependencies with npm
## Using Labelgun
### Use
You can use labelgun in your project via npm such as:
`npm install labelgun --save`
You can also use a auto-generated CDN thanks to unpkg :
`https://unpkg.com/labelgun@0.1.1/lib/labelgun.js`
### Demo
A nice interactive way to play with the demos is to use a hot reloading web server such as live-server:
`npm install -g live-server`
`live-server`
## Develop
### Building
We can install all the required dependencies using node and npm:
`npm install`
### Develop
Labelgun is transpiled from ES6 using babel presets for Webpack 2. You can build the source using:
Labelgun is transpiled from ES6 using babel presets for Webpack 2. You can build the source using
`npm run build`
`webpack`
or:
or
`npm run build-prod`
`webpack --env.minified`
For the minified version. You can also watch the file with:
For the minified version.
`npm run watch`
### Test
### Tests
Labelgun uses Jasmine for testing. You can do an npm install and then use:
`jasmine`
`npm run test`
at the command line. Tests are found in the `spec` folder
at the command line. Tests are found in the `spec` folder. We can also run test coverage as so:
### Demo
`npm run coverage`
A nice interactive way to play with the demos is to use a hot reloading web server such as live-server:
### GitHub Pages & NPM
`npm install -g live-server`
GitHub pages deployment:
`live-server`
`git subtree push --prefix examples origin gh-pages`
### npm
NPM updating:
Labelgun is hosted on npm. You can install via:
`npm publish`
`npm install labelgun --save`
## Users
- [Vroom](http://vroom-project.org/) - Vehicle routing optimisation software
- [OL Mapbox Style](https://github.com/boundlessgeo/ol-mapbox-style) - Use Mapbox Style objects with OpenLayers
Using Labelgun? Open a pull request and let us know!
## Acknowledgements

@@ -54,0 +86,0 @@ Labelgun as an open source project was made possible thanks to [Podaris](http://www.podaris.com).

@@ -1,28 +0,27 @@

var labelgun = require("../lib/labelgun");
describe('labelgun', function() {
describe("labelgun", function() {
it('should import correctly', function(){
it("should import correctly", function(){
expect(labelgun).not.toBeUndefined();
expect(labelgun).not.toBeNull();
expect(labelgun).not.toBeUndefined();
expect(labelgun).not.toBeNull();
});
it('should accept hide and show functions in constructor', function(){
it("should accept hide and show functions in constructor", function(){
var hideLabel = function(){ return false; }
var showLabel = function(){ return true; }
var labelEngine = new labelgun.default(hideLabel, showLabel);
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);
expect(labelEngine.hideLabel()).toBe(false);
expect(labelEngine.showLabel()).toBe(true);
expect(labelEngine.hideLabel()).toBe(false);
expect(labelEngine.showLabel()).toBe(true);
});
it('should ingest a single label', function(){
it("should ingest a single label", function(){
var hideLabel = function(){ return false; }
var showLabel = function(){ return true; }
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);

@@ -42,3 +41,3 @@

false
)
);

@@ -50,6 +49,6 @@ expect(labelEngine.tree.all().length).toBe(1);

it('should ingest many labels (10)', function(){
it("should ingest many labels (10)", function(){
var hideLabel = function(){ return false; }
var showLabel = function(){ return true; }
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);

@@ -72,3 +71,3 @@ var boundingBox;

false
)
);

@@ -82,6 +81,6 @@ }

it('should ingest many labels (10)', function(){
it("should return the total shown and hidden correctly", function(){
var hideLabel = function(){ return false; }
var showLabel = function(){ return true; }
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);

@@ -100,2 +99,92 @@ var boundingBox;

i, //id
1, // Weight
{}, // label object
"Test",
false
);
}
expect(labelEngine.totalShown()).toBe(1);
expect(labelEngine.totalHidden()).toBe(9);
});
it("should return the total shown and hidden correctly", function(){
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);
var boundingBox;
for (var i=0; i < 10; i++) {
boundingBox = {
bottomLeft : [i, i],
topRight : [i + 1.0, i + 1.0]
};
labelEngine.ingestLabel(
boundingBox,
i, //id
1, // Weight
{}, // label object
"Test",
false
);
}
expect(labelEngine.getShown().length).toBe(1);
expect(labelEngine.getHidden().length).toBe(9);
});
it("should return the correct number of collisions", function(){
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);
var boundingBox;
for (var i=0; i < 10; i++) {
boundingBox = {
bottomLeft : [i + 1.0, i + 1.0 ],
topRight : [i + 2.0, i + 2.0]
};
labelEngine.ingestLabel(
boundingBox,
i, //id
1, // Weight
{}, // label object
"Test",
false
);
}
expect(labelEngine.getCollisions(0).length).toBe(1);
});
it("should destroy labelgun data", function(){
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);
var boundingBox;
for (var i=0; i < 10; i++) {
boundingBox = {
bottomLeft : [i, i],
topRight : [i + 1.0, i + 1.0]
};
labelEngine.ingestLabel(
boundingBox,
i, //id
parseInt(Math.random() * (5 - 1) + 1), // Weight

@@ -105,3 +194,3 @@ {}, // label object

false
)
);

@@ -112,9 +201,12 @@ }

expect(Object.keys(labelEngine.allLabels).length).toBe(10);
labelEngine.destroy();
expect(Object.keys(labelEngine.allLabels).length).toBe(0);
expect(labelEngine.tree.all().length).toBe(0);
});
it('should show highest weighted label and hide others', function(){
it("should show highest weighted label and hide others", function(){
var hideLabel = function(){ return false; }
var showLabel = function(){ return true; }
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);

@@ -137,3 +229,3 @@ var boundingBox;

false
)
);

@@ -144,5 +236,5 @@ }

expect(Object.keys(labelEngine.allLabels).length).toBe(10);
for (var i=0; i < 10; i++) {
if (i === 9) expect(labelEngine.allLabels[9].state).toBe("show");
else expect(labelEngine.allLabels[i].state).toBe("hide");
for (var j = 0; j < 10; j++) {
if (j === 9) expect(labelEngine.allLabels[9].state).toBe("show");
else expect(labelEngine.allLabels[j].state).toBe("hide");
}

@@ -152,6 +244,6 @@

it('overlapping labels should be hidden', function(){
it("overlapping labels should be hidden", function(){
var hideLabel = function(){ return false; }
var showLabel = function(){ return true; }
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);

@@ -174,3 +266,3 @@ var boundingBox;

false
)
);

@@ -192,6 +284,6 @@ }

it('no shown labels should collide after their collisions have been dealt with', function(){
it("no shown labels should collide after their collisions have been dealt with", function(){
var hideLabel = function(){ return false; }
var showLabel = function(){ return true; }
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);

@@ -216,3 +308,3 @@ var boundingBox;

false
)
);

@@ -232,10 +324,10 @@ }

});
})
});
});
it('overlapping labels should all be hidden except the one with the highest weight', function(){
it("overlapping labels should all be hidden except the one with the highest weight", function(){
var hideLabel = function(){ return false; }
var showLabel = function(){ return true; }
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);

@@ -259,3 +351,3 @@ var boundingBox;

false
)
);

@@ -270,3 +362,3 @@ }

for (key in labelEngine.allLabels) {
for (var key in labelEngine.allLabels) {
var label = labelEngine.allLabels[key];

@@ -282,3 +374,103 @@ if (label.id === i - 1) {

it("dragged labels should always be shown over none dragged", function(){
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);
var boundingBox;
var n = 1000;
boundingBox = {
bottomLeft : [0, 0],
topRight : [1.0, 1.0]
};
labelEngine.ingestLabel(
boundingBox,
500, //id
0, // Weight
{}, // label object
"Test",
true
);
for (var i = 0; i < n; i++) {
if (i !== 500) {
boundingBox = {
bottomLeft : [0, 0],
topRight : [1.0, 1.0]
};
labelEngine.ingestLabel(
boundingBox,
i, //id
i, // Weight
{}, // label object
"Test",
false
);
}
}
labelEngine.update();
expect(labelEngine.tree.all().length).toBe(n);
expect(Object.keys(labelEngine.allLabels).length).toBe(n);
expect(labelEngine.getShown().length).toBe(1);
for (var key in labelEngine.allLabels) {
var label = labelEngine.allLabels[key];
if (label.id === 500) {
expect(label.state).toBe("show");
} else {
expect(label.state).toBe("hide");
}
}
});
it("should allow for setting one label as changed", function(){
var hideLabel = function(){ return false; };
var showLabel = function(){ return true; };
var labelEngine = new labelgun.default(hideLabel, showLabel);
var boundingBox;
var n = 10;
for (var i = 0; i < n; i++) {
boundingBox = {
bottomLeft : [0, 0],
topRight : [1, 1]
};
labelEngine.ingestLabel(
boundingBox,
i, //id
1, // Weight
{}, // label object
"Test",
false
);
}
labelEngine.allLabels[5].weight = 1000;
labelEngine.labelHasChanged(5);
expect(labelEngine.hasChanged.size).toBe(1);
labelEngine.setupLabelStates();
expect(labelEngine.getShown().length).toBe(1);
expect(typeof(labelEngine.getShown()[0])).toBe("object");
expect(labelEngine.getShown()[0].id).toBe(5);
});
});

@@ -1,4 +0,11 @@

import rbush from 'rbush';
import rbush from "rbush";
export default class labelgun {
/** Class representing a labelgun instance */
class labelgun {
/**
* @summary create a label gun instance with a hide and show label callback
* @param {function} hideLabel the function responsible for hiding the label on hide event
* @param {function} showLabel the function responsible for showing the label on show event
*/
constructor(hideLabel, showLabel) {

@@ -15,11 +22,10 @@

const self = this;
}
/**
/**
* @name _total
* @summary get the total hidden or shown labels in the tree
* @param {string} state whether to return 'hide' or 'show' state label totals
* @returns {number} total number of labels of taht state
* @returns {number} total number of labels of that state
* @private
*/

@@ -56,3 +62,3 @@ _total(state) {

/**
/**
* @name getLabelsByState

@@ -73,3 +79,3 @@ * @summary provided a state get all labels of that state

/**
/**
* @name getHidden

@@ -99,7 +105,9 @@ * @summary Return

getCollisions(id) {
var label = this.allLabels[id];
var collisions = this.tree.search(label);
var self = collisions.indexOf(label);
if (self !== undefined) collisions.splice(self, 1);
return collisions;
var label = this.allLabels[id];
var collisions = this.tree.search(label);
var self = collisions.indexOf(label);
// Remove the label if it's colliding with itself
if (self !== undefined) collisions.splice(self, 1);
return collisions;
}

@@ -109,3 +117,3 @@

* @name getLabel
* @summary Convience function to return a label by ID
* @summary Convenience function to return a label by ID
* @param {string} id the ID of the label to get

@@ -127,9 +135,9 @@ * @returns {object}

/**
* @name forceLabelStates
* @name updateLabelStates
* @summary Allows you to set a state for all current labels
* @param {string} forceState the class of which to change the label to
* @param {string} [forceState] the class of which to change the label to
* @returns {undefined}
*/
forceLabelStates(forceState) {
this.tree.all().forEach(label => {
updateLabelStates(forceState) {
this.tree.all().forEach(label => {
this._labelHasChangedState(label, forceState);

@@ -154,4 +162,4 @@ });

/**
* @name _setupLabelStates
* @summary Clears current tree and readds all stations
* @name setupLabelStates
* @summary Setups the labels depending on whether all have changed or some have changed
* @returns {undefined}

@@ -197,3 +205,3 @@ */

},
label._id,
label.id,
label.weight,

@@ -212,4 +220,4 @@ label.labelObject,

/**
* @name _resetTree
* @summary Clears current tree and redraws projection overlay
* @name update
* @summary Sets all labels to change and reruns the whole show/hide procedure
* @returns {undefined}

@@ -219,13 +227,34 @@ */

this.allChanged = true;
this.setupLabelStates();
this.handleExCollisions();
this._hideShownCollisions(); // HACK ALERT: why is this necessary ? :(
this.forceLabelStates();
this.allChanged = true;
this.setupLabelStates();
this.handleExCollisions();
this._hideShownCollisions(); // TODO: why is this necessary ? :(
this.updateLabelStates();
}
/**
* @name handleExCollisions
* @summary Checks to see if a previously hidden/collided label is now able to be shown and then changes there state
* @returns {undefined}
*/
handleExCollisions() {
this.getHidden().forEach(hidden => {
this._handleExCollisions(hidden);
if (hidden.state === "hide") {
let stillCollides = false;
const hiddenLabels = this.tree.search(hidden);
for (var i=0; i < hiddenLabels.length; i++){
if (hiddenLabels[i].state !== "hide") {
stillCollides = true;
break;
}
}
if (!stillCollides) {
hidden.state = "show";
}
}
});

@@ -236,3 +265,3 @@ }

* @name _resetTree
* @summary Clears current tree and redraws projection overlay
* @summary Clears current tree containing all inputted labels
* @returns {undefined}

@@ -266,3 +295,3 @@ * @private

labelObject : labelObject,
labelName : labelName,
name : labelName,
isDragged : isDragged

@@ -285,3 +314,3 @@ };

delete this.allLabels[id];
if (forceUpdate) this.forceLabelStates(true);
if (forceUpdate) this.updateLabelStates(true);
}

@@ -302,11 +331,10 @@

_hideShownCollisions() {
// This method shouldn't have to exist...
this.getShown().forEach((label) => {
this.getCollisions(label.id).forEach((collision) => {
if (collision.state == "show") {
collision.state = "hide";
}
this.getCollisions(label.id).forEach((collision) => {
if (collision.state == "show") {
collision.state = "hide";
}
});
});
});
}

@@ -323,3 +351,3 @@

*/
_handleCollisions(collisions, label, isDragged) {
_handleCollisions(collisions, label) {
let originalWeight;

@@ -331,15 +359,18 @@ if (label.isDragged) label.weight = Infinity;

if (collision.isDragged) {
originalWeight = collision.weight;
highest = collision;
highest.weight = Infinity;
}
if (collision.isDragged) {
originalWeight = collision.weight;
if (collision.weight > highest.weight) {
highest.state = "hide";
highest = collision;
} else {
collision.state = "hide";
}
// We set the dragged marker to the highest weight
// and make its weight unbeatable (infinity)
highest = collision;
highest.weight = Infinity;
}
if (collision.weight > highest.weight) {
highest.state = "hide";
highest = collision;
} else {
collision.state = "hide";
}
});

@@ -352,27 +383,3 @@

/**
* @name _handleExCollisions
* @param {object} hidden hidden label
* @summary Checks to see if a previously hidden/collided label is now able to be shown and then shows
* @returns {undefined}
* @private
*/
_handleExCollisions(hidden) {
if (hidden.state === "hide") {
let stillCollides = false;
const hiddenLabels = this.tree.search(hidden);
for (var i=0; i < hiddenLabels.length; i++){
if (hiddenLabels[i].state !== "hide") {
stillCollides = true;
break;
}
}
if (!stillCollides) {
hidden.state = "show";
}
}
}
/**
* @name _ingestLabel
* @name ingestLabel
* @param {object} boundingBox

@@ -384,12 +391,20 @@ * @param {string} id

* @param {boolean} isDragged
* @summary Creates a label if it does not already exsist, then adds it to the tree, and renders it based on whether it can be shown
* @summary Creates a label if it does not already exist, then adds it to the tree, and renders it based on whether it can be shown
* @returns {object}
*/
ingestLabel(boundingBox, id, weight, labelObject, labelName, isDragged) {
const label = this._makeLabel(boundingBox, id, weight, labelObject, labelName, isDragged);
// If there is already a label in the tree, remove it
const oldLabel = this.allLabels[id];
if (oldLabel) this.removeFromTree(oldLabel);
// Add the new label to the tree
const label = this._makeLabel(boundingBox, id, weight, labelObject, labelName, isDragged);
this._addToTree(label);
// Get all of its collisions
var collisions = this.getCollisions(id);
if (!collisions.length || isDragged) {
// If the collisions are non existance we can show it
if (!collisions.length) {
label.state = "show";

@@ -399,2 +414,3 @@ return;

// Else we need to handle the collisions and decide which one to show
this._handleCollisions(collisions, label, isDragged);

@@ -414,1 +430,3 @@

}
export default labelgun;

@@ -1,4 +0,4 @@

'use strict';
"use strict";
var webpack = require('webpack');
var webpack = require("webpack");

@@ -37,23 +37,23 @@ module.exports = function(env) {

{
rbush: "rbush"
rbush: "rbush"
}
],
module: {
rules: [{
use : [
{
loader: "babel-loader",
options: {
compact: false, // because I want readable output,
presets: ['es2015']
}
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["env"]
}
]
}]
}
}
]
}
} // End of config
}; // End of config
return config;
}
};

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc