Add tests for geo.gui.widget.
This also adds tests for geo.gui.domWidget and geo.gui.svgWidget.
This removes some unused and untested functions from the widget code,
fixes some typos, and renames some internal functions for clarity and
consistency.
MODIFY
src/d3/d3Renderer.js
src/d3/d3Renderer.js
@@ -223,7 +223,6 @@ var d3Renderer = function (arg) {
/**
* Set the translation, scale, and zoom for the current view.
- * @note rotation not yet supported
* @private
*/
this._setTransform = function () {

MODIFY
src/ui/domWidget.js
src/ui/domWidget.js
@@ -2,6 +2,17 @@ var widget = require('./widget');
var inherit = require('../inherit');
var registerWidget = require('../registry').registerWidget;
+/**
+ * Create a new instance of class domWidget.
+ *
+ * @class
+ * @alias geo.gui.domWidget
+ * @extends geo.gui.widget
+ * @param {object} arg
+ * @param {geo.widget} [parent] A parent widget for this widget.
+ * @param {string} [el='div'] The type of DOM element to create.
+ * @returns {geo.domWidget}
+ */
var domWidget = function (arg) {
'use strict';
if (!(this instanceof domWidget)) {
@@ -17,6 +28,8 @@ var domWidget = function (arg) {
* Initializes DOM Widget.
* Sets the canvas for the widget, does parent/child relationship management,
* appends it to it's parent and handles any positioning logic.
+ *
+ * @returns {this}
*/
this._init = function () {
if (arg.hasOwnProperty('parent')) {
@@ -24,18 +37,18 @@ var domWidget = function (arg) {
}
m_this._createCanvas();
- m_this._appendChild();
+ m_this._appendCanvasToParent();
m_this.canvas().addEventListener('mousedown', function (e) {
e.stopPropagation();
});
m_this.reposition();
+ return m_this;
};
/**
- * Creates the widget canvas.
- * This is just a simple DOM element (based on args.el, or defaults to a div)
+ * Creates the widget canvas. This is a DOM element (`arg.el` or a div).
*/
this._createCanvas = function () {
m_this.canvas(document.createElement(arg.el || m_default_canvas));

MODIFY
src/ui/legendWidget.js
src/ui/legendWidget.js
@@ -26,9 +26,7 @@ var legendWidget = function (arg) {
m_group = null,
m_border = null,
m_spacing = 20, // distance in pixels between lines
- m_padding = 12, // padding in pixels inside the border
- s_createCanvas = this._createCanvas,
- s_appendChild = this._appendChild;
+ m_padding = 12; // padding in pixels inside the border
/**
* Get or set the category array associated with
@@ -212,8 +210,8 @@ var legendWidget = function (arg) {
// adding categories redraws the entire thing by calling _init, see
// the m_top.remove() line below
if (!m_top) {
- s_createCanvas();
- s_appendChild();
+ m_this._createCanvas();
+ m_this._appendCanvasToParent();
}
// total size = interior size + 2 * padding + 2 * width of the border

MODIFY
src/ui/sliderWidget.js
src/ui/sliderWidget.js
@@ -21,8 +21,6 @@ var sliderWidget = function (arg) {
var m_this = this,
s_exit = this._exit,
- s_createCanvas = this._createCanvas,
- s_appendChild = this._appendChild,
m_xscale,
m_yscale,
m_plus,
@@ -91,8 +89,8 @@ var sliderWidget = function (arg) {
* @private
*/
this._init = function () {
- s_createCanvas();
- s_appendChild();
+ m_this._createCanvas();
+ m_this._appendCanvasToParent();
m_this.reposition();

MODIFY
src/ui/svgWidget.js
src/ui/svgWidget.js
-var domWidget = require('./domWidget');
+var widget = require('./widget');
var inherit = require('../inherit');
var registerWidget = require('../registry').registerWidget;
/**
- * Create a new instance of class geo.gui.svgWidget
+ * Create a new instance of class geo.gui.svgWidget.
*
- * Due to the nature of d3 creating DOM elements as it inserts them, calls to appendChild
- * don't appear in this widget.
+ * Due to the nature of d3 creating DOM elements as it inserts them, calls to
+ * appendChild don't appear in this widget.
*
* The canvas of an svgWidget always refers to the actual svg element.
- * The parentCanvas can refer to another widgets svg element, dom element, or the
- * UI layers dom element.
+ * The parentCanvas can refer to another widget's svg element, dom element, or
+ * the UI layer's dom element.
* See {@link geo.gui.widget#parentCanvas}.
*
- * @class geo.gui.svgWidget
- * @extends geo.gui.domWidget
+ * @class
+ * @alias geo.gui.svgWidget
+ * @extends geo.gui.widget
+ * @param {object} arg
+ * @param {geo.widget} [parent] A parent widget for this widget.
* @returns {geo.gui.svgWidget}
- *
*/
var svgWidget = function (arg) {
'use strict';
@@ -24,14 +26,20 @@ var svgWidget = function (arg) {
return new svgWidget(arg);
}
- domWidget.call(this, arg);
+ widget.call(this, arg);
var d3Renderer = require('../d3/d3Renderer');
var m_this = this,
+ s_exit = this._exit,
m_renderer = null;
- this._init = function (arg) {
+ /**
+ * Initializes SVG Widget.
+ *
+ * @returns {this}
+ */
+ this._init = function () {
var d3Parent;
if (arg.hasOwnProperty('parent')) {
arg.parent.addChild(m_this);
@@ -47,12 +55,25 @@ var svgWidget = function (arg) {
});
m_this.reposition();
+ return m_this;
+ };
+
+ /**
+ * Clean up the widget.
+ */
+ this._exit = function () {
+ if (m_renderer) {
+ m_renderer._exit();
+ }
+ s_exit();
};
/**
* Creates the canvas for the svg widget.
- * This directly uses the {@link geo.d3.d3Renderer} as a helper to do all of the heavy
- * lifting.
+ * This directly uses the {@link geo.d3.d3Renderer} as a helper to do all of
+ * the heavy lifting.
+ *
+ * @param {d3Selector} d3Parent The canvas's parent element.
*/
this._createCanvas = function (d3Parent) {
var rendererOpts = {
@@ -75,7 +96,7 @@ var svgWidget = function (arg) {
return this;
};
-inherit(svgWidget, domWidget);
+inherit(svgWidget, widget);
registerWidget('dom', 'svg', svgWidget);
module.exports = svgWidget;

MODIFY
src/ui/widget.js
src/ui/widget.js
@@ -4,15 +4,15 @@ var sceneObject = require('../sceneObject');
/**
* @typedef {object} geo.gui.widget.position
* @property {string|number} [top] The position to the top of the container.
- * A string css position or a number. If a number is used, it will be treated as px value.
- * @property {string|number} [right] The position to the right of the container.
- * Value is used similarly to the top property.
- * @property {string|number} [bottom] The position to the bottom of the container.
- * Value is used similarly to the top property.
+ * A string css position or a number in pixels.
+ * @property {string|number} [right] The position to the right of the
+ * container. A string css position or a number in pixels.
+ * @property {string|number} [bottom] The position to the bottom of the
+ * container. A string css position or a number in pixels.
* @property {string|number} [left] The position to the left of the container.
- * Value is used similarly to the top property.
+ * @property {string|number} [top] The position to the top of the container.
* @property {*} [...] Additional css properties that affect position are
- allowed. See the css specification for details.
+ * allowed. See the css specification for details.
*/
/**
@@ -32,10 +32,10 @@ var widget = function (arg) {
if (!(this instanceof widget)) {
return new widget(arg);
}
+ arg = arg || {};
sceneObject.call(this, arg);
var geo_event = require('../event');
- var createFeature = require('../registry').createFeature;
var m_this = this,
s_exit = this._exit,
@@ -45,6 +45,8 @@ var widget = function (arg) {
if (arg.parent !== undefined && !(arg.parent instanceof widget)) {
throw new Error('Parent must be of type geo.gui.widget');
+ } else if (arg.parent) {
+ m_this.parent(arg.parent);
}
/**
@@ -59,54 +61,31 @@ var widget = function (arg) {
/**
* Clean up the widget.
- *
*/
this._exit = function () {
m_this.children().forEach(function (child) {
- m_this._deleteFeature(child);
+ m_this.removeChild(child);
+ child._exit();
});
m_this.layer().geoOff(geo_event.pan, m_this.repositionEvent);
+ if (m_this.parentCanvas().removeChild && m_this.canvas()) {
+ try {
m_this.parentCanvas().removeChild(m_this.canvas());
+ } catch (err) {
+ // fail gracefully if the canvas is not a child of the parentCanvas
+ }
+ }
s_exit();
};
- /**
- * Create a new feature.
- *
- * @param {string} featureName Name of the feature to create.
- * @param {object} arg Options for the new feature.
- * @returns {geo.feature} The new feature.
- */
- this._createFeature = function (featureName, arg) {
-
- var newFeature = createFeature(
- featureName, m_this, m_this.renderer(), arg);
-
- m_this.addChild(newFeature);
- m_this.modified();
- return newFeature;
- };
-
- /**
- * Delete feature.
- *
- * @param {geo.feature} feature The feature to delete.
- * @returns {this}
- */
- this._deleteFeature = function (feature) {
- m_this.removeChild(feature);
- feature._exit();
- return m_this;
- };
-
/**
* Return the layer associated with this widget.
*
* @returns {geo.layer}
*/
this.layer = function () {
- return m_layer;
+ return m_layer || (m_this.parent() && m_this.parent().layer());
};
/**
@@ -133,11 +112,11 @@ var widget = function (arg) {
};
/**
- * Appends a child to the widget.
+ * Appends the canvas to the parent canvas.
* The widget determines how to append itself to a parent, the parent can
* either be another widget, or the UI Layer.
*/
- this._appendChild = function () {
+ this._appendCanvasToParent = function () {
m_this.parentCanvas().appendChild(m_this.canvas());
};
@@ -148,7 +127,7 @@ var widget = function (arg) {
* @returns {HTMLElement} The canvas of the widget's parent.
*/
this.parentCanvas = function () {
- if (m_this.parent === undefined) {
+ if (!m_this.parent()) {
return m_this.layer().canvas();
}
return m_this.parent().canvas();
@@ -199,6 +178,7 @@ var widget = function (arg) {
*/
this.reposition = function (position) {
position = position || m_this.position();
+ if (m_this.canvas() && m_this.canvas().style) {
m_this.canvas().style.position = 'absolute';
for (var cssAttr in position) {
@@ -207,12 +187,17 @@ var widget = function (arg) {
// specified value. Setting a property to null clears it. Setting to
// undefined doesn't alter it.
if (/^\s*(-|\+)?(\d+(\.\d*)?|\d*\.\d+)([eE](-|\+)?\d+)?\s*$/.test(position[cssAttr])) {
- m_this.canvas().style[cssAttr] = ('' + position[cssAttr]).trim() + 'px';
+ // tris ensures that the number is a float with no more than 3
+ // decimal places (Chrome does this automatically, but doing so
+ // explicitly makes testing more consistent). It will be an
+ // integer when possible.
+ m_this.canvas().style[cssAttr] = parseFloat(parseFloat(position[cssAttr]).toFixed(3)) + 'px';
} else {
m_this.canvas().style[cssAttr] = position[cssAttr];
}
}
}
+ }
return m_this;
};
@@ -227,9 +212,10 @@ var widget = function (arg) {
};
/**
- * Report if the widget is completely within the viewport.
+ * Report if the top left of widget (or its current x, y position) is within
+ * the viewport.
*
- * @returns {boolean} True if the widget is completely within the viewport.
+ * @returns {boolean} True if the widget is within the viewport.
*/
this.isInViewport = function () {
var position = m_this.position();

ADD
tests/cases/domWidget.js
+var $ = require('jquery');
+var geo = require('../test-utils').geo;
+var createMap = require('../test-utils').createMap;
+
+describe('geo.gui.domWidget', function () {
+ 'use strict';
+
+ describe('create', function () {
+ it('direct create', function () {
+ var map, layer, widget, widget2;
+ map = createMap();
+ layer = map.createLayer('ui');
+
+ widget = geo.gui.domWidget({layer: layer});
+ expect(widget instanceof geo.gui.domWidget).toBe(true);
+ expect(widget.parent()).toBe(null);
+ widget2 = geo.gui.domWidget({layer: layer, parent: widget});
+ expect(widget2 instanceof geo.gui.domWidget).toBe(true);
+ expect(widget2.parent()).toBe(widget);
+ });
+ });
+
+ describe('Check private class methods', function () {
+ var map, layer, widget, widget2;
+
+ it('_init and _createCanvas', function () {
+ map = createMap();
+ layer = map.createLayer('ui');
+ widget = geo.gui.domWidget({layer: layer});
+ expect(widget._init()).toBe(widget);
+ expect($(widget.canvas()).is('div')).toBe(true);
+ widget2 = geo.gui.domWidget({layer: layer, parent: widget, el: 'span'});
+ expect(widget2._init()).toBe(widget2);
+ expect($(widget2.canvas()).is('div')).toBe(false);
+ expect($(widget2.canvas()).is('span')).toBe(true);
+ });
+ });
+});

MODIFY
tests/cases/feature.js
tests/cases/feature.js
@@ -47,7 +47,7 @@ describe('geo.feature', function () {
expect(feat.renderer()).toBe(null);
});
});
- describe('Check private class mathods', function () {
+ describe('Check private class methods', function () {
var map, layer, feat, points = {index: [], found: []}, box = [],
events = {};
it('_init', function () {

ADD
tests/cases/svgWidget.js
+var geo = require('../test-utils').geo;
+var createMap = require('../test-utils').createMap;
+
+describe('geo.gui.svgWidget', function () {
+ 'use strict';
+
+ describe('create', function () {
+ it('direct create', function () {
+ var map, layer, widget, widget2;
+ map = createMap();
+ layer = map.createLayer('ui');
+
+ widget = geo.gui.svgWidget({layer: layer});
+ expect(widget instanceof geo.gui.svgWidget).toBe(true);
+ expect(widget.parent()).toBe(null);
+ widget2 = geo.gui.svgWidget({layer: layer, parent: widget});
+ expect(widget2 instanceof geo.gui.svgWidget).toBe(true);
+ expect(widget2.parent()).toBe(widget);
+ });
+ });
+
+ describe('Check private class methods', function () {
+ var map, layer, widget, widget2;
+
+ it('_init and _createCanvas', function () {
+ map = createMap();
+ layer = map.createLayer('ui');
+ widget = geo.gui.svgWidget({layer: layer});
+ expect(widget._init()).toBe(widget);
+ widget2 = geo.gui.svgWidget({layer: layer, parent: widget});
+ expect(widget2._init()).toBe(widget2);
+ });
+
+ it('_exit', function () {
+ var count;
+ map = createMap();
+ layer = map.createLayer('ui');
+ count = layer.node().children().length;
+ widget = geo.gui.svgWidget({layer: layer});
+ widget._init();
+ expect(layer.node().children().length).toBe(count + 1);
+ expect(widget._exit()).toBe(undefined);
+ expect(layer.node().children().length).toBe(count);
+ });
+ });
+});

MODIFY
tests/cases/textFeature.js
tests/cases/textFeature.js
@@ -110,7 +110,7 @@ describe('geo.textFeature', function () {
});
});
- describe('Check private class mathods', function () {
+ describe('Check private class methods', function () {
var map, layer, text;
it('_init', function () {
map = createMap();

ADD
tests/cases/widget.js
+var geo = require('../test-utils').geo;
+var $ = require('jquery');
+var createMap = require('../test-utils').createMap;
+var closeToEqual = require('../test-utils').closeToEqual;
+
+describe('geo.gui.widget', function () {
+ 'use strict';
+
+ describe('create', function () {
+ it('direct create', function () {
+ var map, layer, widget;
+ map = createMap();
+ layer = map.createLayer('ui');
+
+ widget = geo.gui.widget();
+ expect(widget instanceof geo.gui.widget).toBe(true);
+ expect(widget.layer()).toBe(null);
+
+ widget = geo.gui.widget({layer: layer});
+ expect(widget instanceof geo.gui.widget).toBe(true);
+ expect(widget.layer()).toBe(layer);
+ expect(widget.parentCanvas()).toBe(layer.canvas());
+
+ expect(function () {
+ geo.gui.widget({layer: layer, parent: {}});
+ }).toThrow(new Error('Parent must be of type geo.gui.widget'));
+
+ widget = geo.gui.widget({parent: geo.gui.widget({layer: layer})});
+ expect(widget instanceof geo.gui.widget).toBe(true);
+ expect(widget.parentCanvas()).toBe(null);
+ });
+ });
+
+ describe('Check private class methods', function () {
+ var map, layer, widget;
+
+ it('_init', function () {
+ var modTime;
+
+ map = createMap();
+ layer = map.createLayer('ui');
+ widget = geo.gui.widget({layer: layer});
+ modTime = widget.getMTime();
+ expect(widget._init()).toBe(widget);
+ expect(widget.getMTime()).toBeGreaterThan(modTime);
+ });
+ it('_exit', function () {
+ map = createMap();
+ layer = map.createLayer('ui');
+ widget = geo.gui.widget({layer: layer});
+ widget._init();
+ expect(widget._exit()).toBe(undefined);
+
+ widget = geo.gui.widget({layer: layer});
+ widget._init();
+ var canvas = widget.canvas(document.createElement('div'));
+ widget._appendCanvasToParent(canvas);
+ expect(widget._exit()).toBe(undefined);
+ });
+
+ it('_createCanvas', function () {
+ map = createMap();
+ layer = map.createLayer('ui');
+ widget = geo.gui.widget({layer: layer});
+ widget._init();
+ expect(function () {
+ widget._createCanvas();
+ }).toThrow(new Error('Must be defined in derived classes'));
+ });
+ it('_appendCanvasToParent', function () {
+ map = createMap();
+ layer = map.createLayer('ui');
+ widget = geo.gui.widget({layer: layer});
+ widget._init();
+ var canvas = widget.canvas(document.createElement('div'));
+ var children = $(widget.parentCanvas()).children();
+ expect(widget._appendCanvasToParent(canvas)).toBe(undefined);
+ expect($(widget.parentCanvas()).children().length).toBe(children.length + 1);
+ });
+ });
+
+ describe('Check public class methods', function () {
+ var map, layer, widget;
+
+ it('layer', function () {
+ map = createMap();
+ layer = map.createLayer('ui');
+ widget = geo.gui.widget({layer: layer});
+ widget._init();
+ expect(widget.layer()).toBe(layer);
+ });
+ it('canvas', function () {
+ map = createMap();
+ layer = map.createLayer('ui');
+ widget = geo.gui.widget({layer: layer});
+ expect(widget.canvas()).toBe(null);
+ var div = document.createElement('div');
+ expect(widget.canvas(div)).toBe(widget);
+ expect(widget.canvas()).toBe(div);
+ });
+ it('parentCanvas', function () {
+ map = createMap();
+ layer = map.createLayer('ui');
+ widget = geo.gui.widget({layer: layer});
+ expect(widget.parentCanvas()).toBe(layer.canvas());
+ var widget2 = geo.gui.widget({layer: layer, parent: widget});
+ expect(widget2.parentCanvas()).toBe(null);
+ var div = document.createElement('div');
+ widget.canvas(div);
+ expect(widget2.parentCanvas()).toBe(div);
+ });
+ it('position', function () {
+ map = createMap();
+ layer = map.createLayer('ui');
+ widget = geo.gui.widget({layer: layer});
+ expect(widget.position()).toEqual({left: 0, top: 0});
+ expect(widget.position(undefined, true)).toEqual({left: 0, top: 0});
+ expect(widget.position({right: '10px', bottom: '5px'})).toBe(widget);
+ expect(widget.position()).toEqual({right: '10px', bottom: '5px'});
+ expect(widget.position(undefined, true)).toEqual({right: '10px', bottom: '5px'});
+ expect(widget.position({x: -3, y: 3})).toBe(widget);
+ expect(closeToEqual(widget.position(), {left: 285.87, top: 145.85, right: null, bottom: null})).toBe(true);
+ expect(widget.position(undefined, true)).toEqual({x: -3, y: 3});
+ map.pan({x: -5, y: 20});
+ expect(closeToEqual(widget.position(), {left: 280.87, top: 165.85, right: null, bottom: null})).toBe(true);
+ expect(widget.position(undefined, true)).toEqual({x: -3, y: 3});
+ });
+ it('reposition and repositionEvent', function () {
+ map = createMap();
+ layer = map.createLayer('ui');
+ widget = geo.gui.widget({layer: layer});
+ var div = document.createElement('div');
+ widget.canvas(div);
+ widget.position({right: '10px', bottom: '5px'});
+ expect(widget.reposition()).toBe(widget);
+ expect($(div).css('right')).toBe('10px');
+ expect(widget.reposition({right: 20, bottom: 10})).toBe(widget);
+ expect($(div).css('right')).toBe('20px');
+ widget.position({x: -3, y: 3});
+ expect(widget.reposition()).toBe(widget);
+ expect($(div).css('left')).toBe('285.867px');
+ // pan triggers repositionEvent
+ map.pan({x: -5, y: 20});
+ expect($(div).css('left')).toBe('280.867px');
+ });
+ });
+});
+
+describe('widget api', function () {
+ 'use strict';
+
+ function makeMap() {
+ var map;
+
+ map = createMap({
+ center: {
+ x: -98.0,
+ y: 39.5
+ },
+ zoom: 5
+ }, {width: '500px', height: '400px'});
+
+ var uiLayer = map.createLayer('ui');
+ map.draw();
+ return {map: map, uiLayer: uiLayer};
+ }
+
+ it('a widget should have the UI layer as its parent', function () {
+ var widget = makeMap().uiLayer.createWidget('dom');
+
+ expect(widget.parent()).toEqual(jasmine.any(geo.gui.uiLayer));
+ });
+
+ it('a widget stuck to albany shouldn\'t be in the viewport ' +
+ 'if we pan to moscow',
+ function () {
+ var o = makeMap(), widget = o.uiLayer.createWidget(
+ 'dom', {
+ position: {
+ x: -73.7572,
+ y: 42.6525
+ }
+ }
+ );
+
+ o.map.center({x: 37.6167, y: 55.7500});
+ expect(widget.isInViewport()).toBe(false);
+ });
+
+ it('a widget stuck to albany should be in the viewport if albany is', function () {
+ var o = makeMap(),
+ widget = o.uiLayer.createWidget('dom', {
+ position: {
+ x: -73.7572,
+ y: 42.6525
+ }
+ });
+
+ o.map.center({x: -73.7572, y: 42.6525});
+ expect(widget.isInViewport()).toBe(true);
+
+ });
+
+ it('a widget stuck to the top left should always be in the viewport', function () {
+ var o = makeMap(), widget = o.uiLayer.createWidget('dom');
+
+ expect($(widget.canvas()).position()).toEqual({top: 0, left: 0});
+
+ o.map.center({x: 37.6167, y: 55.7500});
+ expect(widget.isInViewport()).toBe(true);
+ expect($(widget.canvas()).position()).toEqual({top: 0, left: 0});
+ });
+
+ it('Widgets positions can be changed', function () {
+ var o = makeMap(), widget = o.uiLayer.createWidget('dom', {
+ position: {left: 15, top: 10}});
+
+ expect($(widget.canvas()).position()).toEqual({top: 10, left: 15});
+ widget.position({top: null, bottom: '20%', left: 10});
+ expect(widget.position()).toEqual({top: null, bottom: '20%', left: 10});
+ expect($(widget.canvas()).position()).toEqual({top: 320, left: 10});
+ });
+
+ it('nested widgets should be properly structured', function () {
+ var o = makeMap();
+ var domWidget = o.uiLayer.createWidget('dom');
+ var svgWidget = o.uiLayer.createWidget('svg', {
+ parent: domWidget
+ });
+ var widgetCount = $(o.uiLayer.canvas()).children().length;
+
+ expect($(svgWidget.canvas()).parent()[0]).toBe($(domWidget.canvas())[0]);
+
+ // Only top level widgets are children of the UI Layer
+ // So removing the domWidget will also remove the svgWidget, but only
+ // reduce the number of widgets the UILayer has as children by 1
+ domWidget._exit();
+ expect($(o.uiLayer.canvas()).children().length).toBe(widgetCount - 1);
+ });
+});

DELETE
tests/cases/widgetApi.js
-var geo = require('../test-utils').geo;
-var createMap = require('../test-utils').createMap;
-var $ = require('jquery');
-
-describe('widget api', function () {
- 'use strict';
-
- function makeMap() {
- var map;
-
- map = createMap({
- center: {
- x: -98.0,
- y: 39.5
- },
- zoom: 5
- }, {width: '500px', height: '400px'});
-
- var uiLayer = map.createLayer('ui');
- map.draw();
- return {map: map, uiLayer: uiLayer};
- }
-
- it('a widget should have the UI layer as its parent', function () {
- var widget = makeMap().uiLayer.createWidget('dom');
-
- expect(widget.parent()).toEqual(jasmine.any(geo.gui.uiLayer));
- });
-
- it('a widget stuck to albany shouldn\'t be in the viewport ' +
- 'if we pan to moscow',
- function () {
- var o = makeMap(), widget = o.uiLayer.createWidget(
- 'dom', {
- position: {
- x: -73.7572,
- y: 42.6525
- }
- }
- );
-
- o.map.center({x: 37.6167, y: 55.7500});
- expect(widget.isInViewport()).toBe(false);
- });
-
- it('a widget stuck to albany should be in the viewport if albany is', function () {
- var o = makeMap(),
- widget = o.uiLayer.createWidget('dom', {
- position: {
- x: -73.7572,
- y: 42.6525
- }
- });
-
- o.map.center({x: -73.7572, y: 42.6525});
- expect(widget.isInViewport()).toBe(true);
-
- });
-
- it('a widget stuck to the top left should always be in the viewport', function () {
- var o = makeMap(), widget = o.uiLayer.createWidget('dom');
-
- expect($(widget.canvas()).position()).toEqual({top: 0, left: 0});
-
- o.map.center({x: 37.6167, y: 55.7500});
- expect(widget.isInViewport()).toBe(true);
- expect($(widget.canvas()).position()).toEqual({top: 0, left: 0});
- });
-
- it('Widgets positions can be changed', function () {
- var o = makeMap(), widget = o.uiLayer.createWidget('dom', {
- position: {left: 15, top: 10}});
-
- expect($(widget.canvas()).position()).toEqual({top: 10, left: 15});
- widget.position({top: null, bottom: '20%', left: 10});
- expect(widget.position()).toEqual({top: null, bottom: '20%', left: 10});
- expect($(widget.canvas()).position()).toEqual({top: 320, left: 10});
- });
-
- it('nested widgets should be properly structured', function () {
- var o = makeMap();
- var domWidget = o.uiLayer.createWidget('dom');
- var svgWidget = o.uiLayer.createWidget('svg', {
- parent: domWidget
- });
- var widgetCount = $(o.uiLayer.canvas()).children().length;
-
- expect($(svgWidget.canvas()).parent()[0]).toBe($(domWidget.canvas())[0]);
-
- // Only top level widgets are children of the UI Layer
- // So removing the domWidget will also remove the svgWidget, but only
- // reduce the number of widgets the UILayer has as children by 1
- domWidget._exit();
- expect($(o.uiLayer.canvas()).children().length).toBe(widgetCount - 1);
- });
-});

Add tests for geo.gui.widget.

This also adds tests for geo.gui.domWidget and geo.gui.svgWidget.

This removes some unused and untested functions from the widget code,
fixes some typos, and renames some internal functions for clarity and
consistency.