123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 |
- import AssociativeArray from '../Core/AssociativeArray.js';
- import buildModuleUrl from '../Core/buildModuleUrl.js';
- import Check from '../Core/Check.js';
- import Credit from '../Core/Credit.js';
- import defaultValue from '../Core/defaultValue.js';
- import defined from '../Core/defined.js';
- import defineProperties from '../Core/defineProperties.js';
- import destroyObject from '../Core/destroyObject.js';
- var mobileWidth = 576;
- var lightboxHeight = 100;
- var textColor = '#ffffff';
- var highlightColor = '#48b';
- function contains(credits, credit) {
- var len = credits.length;
- for (var i = 0; i < len; i++) {
- var existingCredit = credits[i];
- if (Credit.equals(existingCredit, credit)) {
- return true;
- }
- }
- return false;
- }
- function swapCesiumCredit(creditDisplay) {
- // We don't want to clutter the screen with the Cesium logo and the Cesium ion
- // logo at the same time. Since the ion logo is required, we just replace the
- // Cesium logo or add the logo if the Cesium one was removed.
- var previousCredit = creditDisplay._previousCesiumCredit;
- var currentCredit = creditDisplay._currentCesiumCredit;
- if (Credit.equals(currentCredit, previousCredit)) {
- return;
- }
- if (defined(previousCredit)) {
- creditDisplay._cesiumCreditContainer.removeChild(previousCredit.element);
- }
- if (defined(currentCredit)) {
- creditDisplay._cesiumCreditContainer.appendChild(currentCredit.element);
- }
- creditDisplay._previousCesiumCredit = currentCredit;
- }
- var delimiterClassName = 'cesium-credit-delimiter';
- function createDelimiterElement(delimiter) {
- var delimiterElement = document.createElement('span');
- delimiterElement.textContent = delimiter;
- delimiterElement.className = delimiterClassName;
- return delimiterElement;
- }
- function createCreditElement(element, elementWrapperTagName) {
- // may need to wrap the credit in another element
- if (defined(elementWrapperTagName)) {
- var wrapper = document.createElement(elementWrapperTagName);
- wrapper._creditId = element._creditId;
- wrapper.appendChild(element);
- element = wrapper;
- }
- return element;
- }
- function displayCredits(container, credits, delimiter, elementWrapperTagName) {
- var childNodes = container.childNodes;
- var domIndex = -1;
- for (var creditIndex = 0; creditIndex < credits.length; ++creditIndex) {
- var credit = credits[creditIndex];
- if (defined(credit)) {
- domIndex = creditIndex;
- if (defined(delimiter)) {
- // credits may be separated by delimiters
- domIndex *= 2;
- if (creditIndex > 0) {
- var delimiterDomIndex = domIndex - 1;
- if (childNodes.length <= delimiterDomIndex) {
- container.appendChild(createDelimiterElement(delimiter));
- } else {
- var existingDelimiter = childNodes[delimiterDomIndex];
- if (existingDelimiter.className !== delimiterClassName) {
- container.replaceChild(createDelimiterElement(delimiter), existingDelimiter);
- }
- }
- }
- }
- var element = credit.element;
- // check to see if the correct credit is in the right place
- if (childNodes.length <= domIndex) {
- container.appendChild(createCreditElement(element, elementWrapperTagName));
- } else {
- var existingElement = childNodes[domIndex];
- if (existingElement._creditId !== credit._id) {
- // not the right credit, swap it in
- container.replaceChild(createCreditElement(element, elementWrapperTagName), existingElement);
- }
- }
- }
- }
- // any remaining nodes in the container are unnecessary
- ++domIndex;
- while (domIndex < childNodes.length) {
- container.removeChild(childNodes[domIndex]);
- }
- }
- function styleLightboxContainer(that) {
- var lightboxCredits = that._lightboxCredits;
- var width = that.viewport.clientWidth;
- var height = that.viewport.clientHeight;
- if (width !== that._lastViewportWidth) {
- if (width < mobileWidth) {
- lightboxCredits.className = 'cesium-credit-lightbox cesium-credit-lightbox-mobile';
- lightboxCredits.style.marginTop = '0';
- } else {
- lightboxCredits.className = 'cesium-credit-lightbox cesium-credit-lightbox-expanded';
- lightboxCredits.style.marginTop = Math.floor((height - lightboxCredits.clientHeight) * 0.5) + 'px';
- }
- that._lastViewportWidth = width;
- }
- if (width >= mobileWidth && height !== that._lastViewportHeight) {
- lightboxCredits.style.marginTop = Math.floor((height - lightboxCredits.clientHeight) * 0.5) + 'px';
- that._lastViewportHeight = height;
- }
- }
- function addStyle(selector, styles) {
- var style = selector + ' {';
- for (var attribute in styles) {
- if (styles.hasOwnProperty(attribute)) {
- style += attribute + ': ' + styles[attribute] + '; ';
- }
- }
- style += ' }\n';
- return style;
- }
- function appendCss() {
- var style = '';
- style += addStyle('.cesium-credit-lightbox-overlay', {
- display : 'none',
- 'z-index' : '1', //must be at least 1 to draw over top other Cesium widgets
- position : 'absolute',
- top : '0',
- left : '0',
- width : '100%',
- height : '100%',
- 'background-color' : 'rgba(80, 80, 80, 0.8)'
- });
- style += addStyle('.cesium-credit-lightbox', {
- 'background-color' : '#303336',
- color : textColor,
- position : 'relative',
- 'min-height' : lightboxHeight + 'px',
- margin : 'auto'
- });
- style += addStyle('.cesium-credit-lightbox > ul > li a, .cesium-credit-lightbox > ul > li a:visited', {
- color : textColor
- });
- style += addStyle('.cesium-credit-lightbox > ul > li a:hover', {
- color : highlightColor
- });
- style += addStyle('.cesium-credit-lightbox.cesium-credit-lightbox-expanded', {
- border : '1px solid #444',
- 'border-radius' : '5px',
- 'max-width' : '370px'
- });
- style += addStyle('.cesium-credit-lightbox.cesium-credit-lightbox-mobile', {
- height : '100%',
- width : '100%'
- });
- style += addStyle('.cesium-credit-lightbox-title', {
- padding : '20px 20px 0 20px'
- });
- style += addStyle('.cesium-credit-lightbox-close', {
- 'font-size' : '18pt',
- cursor : 'pointer',
- position : 'absolute',
- top : '0',
- right : '6px',
- color : textColor
- });
- style += addStyle('.cesium-credit-lightbox-close:hover', {
- color : highlightColor
- });
- style += addStyle('.cesium-credit-lightbox > ul', {
- margin : '0',
- padding : '12px 20px 12px 40px',
- 'font-size' : '13px'
- });
- style += addStyle('.cesium-credit-lightbox > ul > li', {
- 'padding-bottom' : '6px'
- });
- style += addStyle('.cesium-credit-lightbox > ul > li *', {
- padding : '0',
- margin : '0'
- });
- style += addStyle('.cesium-credit-expand-link', {
- 'padding-left' : '5px',
- cursor : 'pointer',
- 'text-decoration' : 'underline',
- color : textColor
- });
- style += addStyle('.cesium-credit-expand-link:hover', {
- 'color' : highlightColor
- });
- style += addStyle('.cesium-credit-text', {
- color : textColor
- });
- style += addStyle('.cesium-credit-textContainer *, .cesium-credit-logoContainer *', {
- display : 'inline'
- });
- var head = document.head;
- var css = document.createElement('style');
- css.innerHTML = style;
- head.insertBefore(css, head.firstChild);
- }
- /**
- * The credit display is responsible for displaying credits on screen.
- *
- * @param {HTMLElement} container The HTML element where credits will be displayed
- * @param {String} [delimiter= ' • '] The string to separate text credits
- * @param {HTMLElement} [viewport=document.body] The HTML element that will contain the credits popup
- *
- * @alias CreditDisplay
- * @constructor
- *
- * @example
- * var creditDisplay = new Cesium.CreditDisplay(creditContainer);
- */
- function CreditDisplay(container, delimiter, viewport) {
- //>>includeStart('debug', pragmas.debug);
- Check.defined('container', container);
- //>>includeEnd('debug');
- var that = this;
- viewport = defaultValue(viewport, document.body);
- var lightbox = document.createElement('div');
- lightbox.className = 'cesium-credit-lightbox-overlay';
- viewport.appendChild(lightbox);
- var lightboxCredits = document.createElement('div');
- lightboxCredits.className = 'cesium-credit-lightbox';
- lightbox.appendChild(lightboxCredits);
- function hideLightbox(event) {
- if (lightboxCredits.contains(event.target)) {
- return;
- }
- that.hideLightbox();
- }
- lightbox.addEventListener('click', hideLightbox, false);
- var title = document.createElement('div');
- title.className = 'cesium-credit-lightbox-title';
- title.textContent = 'Data provided by:';
- lightboxCredits.appendChild(title);
- var closeButton = document.createElement('a');
- closeButton.onclick = this.hideLightbox.bind(this);
- closeButton.innerHTML = '×';
- closeButton.className = 'cesium-credit-lightbox-close';
- lightboxCredits.appendChild(closeButton);
- var creditList = document.createElement('ul');
- lightboxCredits.appendChild(creditList);
- var cesiumCreditContainer = document.createElement('div');
- cesiumCreditContainer.className = 'cesium-credit-logoContainer';
- cesiumCreditContainer.style.display = 'inline';
- container.appendChild(cesiumCreditContainer);
- var screenContainer = document.createElement('div');
- screenContainer.className = 'cesium-credit-textContainer';
- screenContainer.style.display = 'inline';
- container.appendChild(screenContainer);
- var expandLink = document.createElement('a');
- expandLink.className = 'cesium-credit-expand-link';
- expandLink.onclick = this.showLightbox.bind(this);
- expandLink.textContent = 'Data attribution';
- container.appendChild(expandLink);
- appendCss();
- var cesiumCredit = Credit.clone(CreditDisplay.cesiumCredit);
- this._delimiter = defaultValue(delimiter, ' • ');
- this._screenContainer = screenContainer;
- this._cesiumCreditContainer = cesiumCreditContainer;
- this._lastViewportHeight = undefined;
- this._lastViewportWidth = undefined;
- this._lightboxCredits = lightboxCredits;
- this._creditList = creditList;
- this._lightbox = lightbox;
- this._hideLightbox = hideLightbox;
- this._expandLink = expandLink;
- this._expanded = false;
- this._defaultCredits = [];
- this._cesiumCredit = cesiumCredit;
- this._previousCesiumCredit = undefined;
- this._currentCesiumCredit = cesiumCredit;
- this._currentFrameCredits = {
- screenCredits : new AssociativeArray(),
- lightboxCredits : new AssociativeArray()
- };
- this._defaultCredit = undefined;
- this.viewport = viewport;
- /**
- * The HTML element where credits will be displayed.
- * @type {HTMLElement}
- */
- this.container = container;
- }
- /**
- * Adds a credit to the list of current credits to be displayed in the credit container
- *
- * @param {Credit} credit The credit to display
- */
- CreditDisplay.prototype.addCredit = function(credit) {
- //>>includeStart('debug', pragmas.debug);
- Check.defined('credit', credit);
- //>>includeEnd('debug');
- if (credit._isIon) {
- // If this is the an ion logo credit from the ion server
- // Juse use the default credit (which is identical) to avoid blinking
- if (!defined(this._defaultCredit)) {
- this._defaultCredit = Credit.clone(getDefaultCredit());
- }
- this._currentCesiumCredit = this._defaultCredit;
- return;
- }
- if (!credit.showOnScreen) {
- this._currentFrameCredits.lightboxCredits.set(credit.id, credit);
- } else {
- this._currentFrameCredits.screenCredits.set(credit.id, credit);
- }
- };
- /**
- * Adds credits that will persist until they are removed
- *
- * @param {Credit} credit The credit to added to defaults
- */
- CreditDisplay.prototype.addDefaultCredit = function(credit) {
- //>>includeStart('debug', pragmas.debug);
- Check.defined('credit', credit);
- //>>includeEnd('debug');
- var defaultCredits = this._defaultCredits;
- if (!contains(defaultCredits, credit)) {
- defaultCredits.push(credit);
- }
- };
- /**
- * Removes a default credit
- *
- * @param {Credit} credit The credit to be removed from defaults
- */
- CreditDisplay.prototype.removeDefaultCredit = function(credit) {
- //>>includeStart('debug', pragmas.debug);
- Check.defined('credit', credit);
- //>>includeEnd('debug');
- var defaultCredits = this._defaultCredits;
- var index = defaultCredits.indexOf(credit);
- if (index !== -1) {
- defaultCredits.splice(index, 1);
- }
- };
- CreditDisplay.prototype.showLightbox = function() {
- this._lightbox.style.display = 'block';
- this._expanded = true;
- };
- CreditDisplay.prototype.hideLightbox = function() {
- this._lightbox.style.display = 'none';
- this._expanded = false;
- };
- /**
- * Updates the credit display before a new frame is rendered.
- */
- CreditDisplay.prototype.update = function() {
- if (this._expanded) {
- styleLightboxContainer(this);
- }
- };
- /**
- * Resets the credit display to a beginning of frame state, clearing out current credits.
- */
- CreditDisplay.prototype.beginFrame = function() {
- var currentFrameCredits = this._currentFrameCredits;
- var screenCredits = currentFrameCredits.screenCredits;
- screenCredits.removeAll();
- var defaultCredits = this._defaultCredits;
- for (var i = 0; i < defaultCredits.length; ++i) {
- var defaultCredit = defaultCredits[i];
- screenCredits.set(defaultCredit.id, defaultCredit);
- }
- currentFrameCredits.lightboxCredits.removeAll();
- if (!Credit.equals(CreditDisplay.cesiumCredit, this._cesiumCredit)) {
- this._cesiumCredit = Credit.clone(CreditDisplay.cesiumCredit);
- }
- this._currentCesiumCredit = this._cesiumCredit;
- };
- /**
- * Sets the credit display to the end of frame state, displaying credits from the last frame in the credit container.
- */
- CreditDisplay.prototype.endFrame = function() {
- var screenCredits = this._currentFrameCredits.screenCredits.values;
- displayCredits(this._screenContainer, screenCredits, this._delimiter, undefined);
- var lightboxCredits = this._currentFrameCredits.lightboxCredits.values;
- this._expandLink.style.display = lightboxCredits.length > 0 ? 'inline' : 'none';
- displayCredits(this._creditList, lightboxCredits, undefined, 'li');
- swapCesiumCredit(this);
- };
- /**
- * Destroys the resources held by this object. Destroying an object allows for deterministic
- * release of resources, instead of relying on the garbage collector to destroy this object.
- * <br /><br />
- * Once an object is destroyed, it should not be used; calling any function other than
- * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
- * assign the return value (<code>undefined</code>) to the object as done in the example.
- *
- * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
- */
- CreditDisplay.prototype.destroy = function() {
- this._lightbox.removeEventListener('click', this._hideLightbox, false);
- this.container.removeChild(this._cesiumCreditContainer);
- this.container.removeChild(this._screenContainer);
- this.container.removeChild(this._expandLink);
- this.viewport.removeChild(this._lightbox);
- return destroyObject(this);
- };
- /**
- * Returns true if this object was destroyed; otherwise, false.
- * <br /><br />
- *
- * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
- */
- CreditDisplay.prototype.isDestroyed = function() {
- return false;
- };
- CreditDisplay._cesiumCredit = undefined;
- CreditDisplay._cesiumCreditInitialized = false;
- var defaultCredit;
- function getDefaultCredit() {
- if (!defined(defaultCredit)) {
- var logo = buildModuleUrl('Assets/Images/ion-credit.png');
- defaultCredit = new Credit('<a href="https://cesium.com/" target="_blank"><img src="' + logo + '" title="Cesium ion"/></a>', true);
- }
- if (!CreditDisplay._cesiumCreditInitialized) {
- CreditDisplay._cesiumCredit = defaultCredit;
- CreditDisplay._cesiumCreditInitialized = true;
- }
- return defaultCredit;
- }
- defineProperties(CreditDisplay, {
- /**
- * Gets or sets the Cesium logo credit.
- * @memberof CreditDisplay
- * @type {Credit}
- */
- cesiumCredit : {
- get : function() {
- getDefaultCredit();
- return CreditDisplay._cesiumCredit;
- },
- set : function(value) {
- CreditDisplay._cesiumCredit = value;
- CreditDisplay._cesiumCreditInitialized = true;
- }
- }
- });
- export default CreditDisplay;
|