diff --git a/README.md b/README.md index dfcf48e..82d91d1 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ The Story Map Series app lets you present a series of maps via tabs, numbered bu [Download](http://links.esri.com/storymaps/map_series_template_zip) | [Map Series page on Esri Story Maps website](http://links.esri.com/storymaps/map_series_app) -**Latest release is version 1.7.3**, if you want to be informed of new releases, we recommend you to watch this repository ([see GitHub help](https://help.github.com/articles/watching-repositories)). See the [release page](https://github.com/Esri/map-series-storytelling-template-js/releases) for release notes. +**Latest release is version 1.8.0**, if you want to be informed of new releases, we recommend you to watch this repository ([see GitHub help](https://help.github.com/articles/watching-repositories)). See the [release page](https://github.com/Esri/map-series-storytelling-template-js/releases) for release notes. For more infomation about using and customizing Esri's Storytelling Apps follow the [Story Maps Developers' Corner](https://developerscorner.storymaps.arcgis.com). @@ -413,7 +413,7 @@ Find a bug or want to request a new feature? Please let us know by submitting a Esri welcomes contributions from anyone and everyone. Please see our [guidelines for contributing](https://github.com/esri/contributing). ## Licensing -Copyright 2013 Esri +Copyright 2017 Esri Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -438,7 +438,7 @@ Some open-source components of this project are licensed under other License ter | jQuery | MIT | | jQuery Colorbox | MIT | | iDangero.us swiper | MIT | -| ZeroClipboard | MIT | +| Clipboard.js | MIT | | History.js | BSD | | jQuery UI | MIT | | FastClick | MIT | diff --git a/package.json b/package.json index 9715645..dded4b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Storymaps-MapSeries", - "version": "1.7.3", + "version": "1.8.0", "devDependencies": { "grunt": "~0.4.1", "grunt-contrib-clean": "~0.4.0", diff --git a/src/app/storymaps/common/_resources/nls/nl/media.js b/src/app/storymaps/common/_resources/nls/nl/media.js index 3d7a8dd..c7fe9b9 100644 --- a/src/app/storymaps/common/_resources/nls/nl/media.js +++ b/src/app/storymaps/common/_resources/nls/nl/media.js @@ -128,7 +128,7 @@ define({ "preview": "Voorbeeld actie" }, "editorActionMedia": { - "lblTitle": "De inhoud van het hoofdvenster wijzigen" + "lblTitle": "De content van het hoofdvenster wijzigen" }, "editorInlineMedia": { "lblTitle": "Een afbeelding, video of webpagina invoegen" diff --git a/src/app/storymaps/common/_resources/nls/nl/webmap.js b/src/app/storymaps/common/_resources/nls/nl/webmap.js index d9e8657..4c9b192 100644 --- a/src/app/storymaps/common/_resources/nls/nl/webmap.js +++ b/src/app/storymaps/common/_resources/nls/nl/webmap.js @@ -40,10 +40,10 @@ define({ "configure": { "btnReset": "Opnieuw instellen", "btnCancel": "Annuleren", - "tocTitle": "Kaartinhoud", + "tocTitle": "Kaartcontent", "tocExplain": "Selecteer welke kaartlagen zullen worden weergegeven.", "tocNoData": "Er kan geen kaartlaag worden geconfigureerd.", - "tocSave": "Kaartinhoud opslaan", + "tocSave": "Kaartcontent opslaan", "extentTitle": "Kaartlocatie", "extentExplain": "Pan en zoom op de kaart om te definiëren hoe deze eruit zal zien voor uw lezers.", "extentSave": "Kaartlocatie opslaan", diff --git a/src/app/storymaps/common/builder/Builder.js b/src/app/storymaps/common/builder/Builder.js index c5a7fc7..1491ba0 100644 --- a/src/app/storymaps/common/builder/Builder.js +++ b/src/app/storymaps/common/builder/Builder.js @@ -339,9 +339,10 @@ define(["lib-build/css!./Builder", // set app logo to org logo if app.isInitializing if (app.isInitializing && !app.data.getWebAppData().getHeader().logoURL) { var newHeaderConfig = _core.getHeaderUserCfg(); + var clickthroughLink = sharedTheme.logo.link ? sharedTheme.logo.link.trim() : ''; lang.mixin(newHeaderConfig, { logoURL: sharedTheme.logo.small, - logoTarget: '' + logoTarget: clickthroughLink }); app.data.getWebAppData().setHeader(newHeaderConfig); topic.publish('CORE_UPDATE_UI'); diff --git a/src/app/storymaps/common/builder/media/ViewConfigure.js b/src/app/storymaps/common/builder/media/ViewConfigure.js index f3b5b3f..22e95b6 100644 --- a/src/app/storymaps/common/builder/media/ViewConfigure.js +++ b/src/app/storymaps/common/builder/media/ViewConfigure.js @@ -24,35 +24,22 @@ define(["lib-build/css!./ViewConfigure", cfg.mode = app.appCfg.mediaPickerConfigureForceMode; } - container.append(viewTpl({ + var strs = lang.mixin({ mode: cfg.mode, - lblURL: i18n.commonMedia.mediaConfigure.lblURL, - lblURLPH: i18n.commonMedia.mediaConfigure.lblURLPH, - lblURLError: i18n.commonMedia.mediaConfigure.lblURLError, - lblLabel: i18n.commonMedia.mediaConfigure.lblLabel, - lblLabelPH: i18n.commonMedia.mediaConfigure.lblLabelPH, - lblMaximize: i18n.commonMedia.mediaConfigure.lblMaximize, - lblMaximizeHelp: i18n.commonMedia.mediaConfigure.lblMaximizeHelp, - lblPosition: i18n.commonMedia.mediaConfigure.lblPosition, - lblPosition1: i18n.commonMedia.mediaConfigure.lblPosition1, - lblPosition2: i18n.commonMedia.mediaConfigure.lblPosition2, - lblPosition3: i18n.commonMedia.mediaConfigure.lblPosition3, - lblPosition4: i18n.commonMedia.mediaConfigure.lblPosition4, - lblPosition5: i18n.commonMedia.mediaConfigure.lblPosition5, phWidth: i18n.commonCore.common.width, phHeight: i18n.commonCore.common.height, - lblPosition2Explain: i18n.commonMedia.mediaConfigure.lblPosition2Explain, - lblPosition3Explain: i18n.commonMedia.mediaConfigure.lblPosition3Explain, - lblPosition3Explain2: i18n.commonMedia.mediaConfigure.lblPosition3Explain2, - lblPosition4Explain: i18n.commonMedia.mediaConfigure.lblPosition4Explain, - lblURLHelp: app.appCfg.mediaPickerConfigureForceMode != "shortlist" ? i18n.commonMedia.mediaConfigure.lblURLHelp : 'For best results, images should be less than 400 KB. The recommended size & shape is 1000 x 750 pixels (4:3 width:height ratio) or smaller. Larger images can slow performance. For best performance use compressed JPG images at 80% image quality.', - lblThumbURLHelp: 'The recommended thumbnail size & shape is 280 x 210 pixels (4:3 width:height ratio). Larger thumbnails can slow performance. 4:3 aspect ratio thumbnails fit into their tiles without being cropped.', - unloadLbl: i18n.commonMedia.mediaConfigure.unloadLbl, - unloadHelp: i18n.commonMedia.mediaConfigure.unloadHelp, - embedProtocolLabel: i18n.commonMedia.mediaConfigure.embedProtocolLabel, - embedProtocolInfo: location.protocol == 'https:' ? i18n.commonMedia.mediaConfigure.embedProtocolWarning1 : i18n.commonMedia.mediaConfigure.embedProtocolWarning2, - lblThumbURL: "Thumbnail link" - })); + embedProtocolInfo: location.protocol == 'https:' ? i18n.commonMedia.mediaConfigure.embedProtocolWarning1 : i18n.commonMedia.mediaConfigure.embedProtocolWarning2 + }, i18n.commonMedia.mediaConfigure); + + if (app.appCfg.mediaPickerConfigureForceMode === 'shortlist') { + lang.mixin(strs, { + lblURLHelp: i18n.builder.detailPanelBuilder.imageSizeHelperUpdated, + lblThumbURLHelp: i18n.builder.detailPanelBuilder.thumbnailHelp || 'The recommended thumbnail size & shape is 280 x 210 pixels (4:3 width:height ratio). Larger thumbnails can slow performance. 4:3 aspect ratio thumbnails fit into their tiles without being cropped.', + lblThumbURL: i18n.builder.detailPanelBuilder.thumbnailLink + }); + } + + container.append(viewTpl(strs)); initEvents(); @@ -131,6 +118,17 @@ define(["lib-build/css!./ViewConfigure", } container.find('.mediaURLError').fadeOut(); }) + .on('paste', function(){ + if(_params.fromService && media && media.type && (media[media.type].url != container.find('.mediaURL').val())) + _params.fromService = false; + + if (app.appCfg.mediaPickerConfigureForceMode == "shortlist"){ + if(container.find('.mediaThumbURL').val().length){ + container.parent().parent().parent().parent().parent().parent().parent().find('.modal-footer').find('.btnSubmit').attr("disabled",false); + } + } + container.find('.mediaURLError').fadeOut(); + }) .parent().toggle( (params.fromService === false || (app.appCfg.mediaPickerConfigureForceMode == "shortlist" && params.mode == "showURL")) && _mediaType == "image" && _mediaType == "image" ); @@ -149,6 +147,16 @@ define(["lib-build/css!./ViewConfigure", } } container.find('.mediaThumbURLError').fadeOut(); + }) + .on('paste', function(){ + if(_params.fromService && media && media.type && (media[media.type].thumb_url != container.find('.mediaThumbURL').val())) + _params.fromService = false; + if (app.appCfg.mediaPickerConfigureForceMode == "shortlist"){ + if(container.find('.mediaURL').val().length){ + container.parent().parent().parent().parent().parent().parent().parent().find('.modal-footer').find('.btnSubmit').attr("disabled",false); + } + } + container.find('.mediaThumbURLError').fadeOut(); }); // Frame trick diff --git a/src/app/storymaps/common/builder/media/image/FileUploadHelper.js b/src/app/storymaps/common/builder/media/image/FileUploadHelper.js index 4f5a8ca..f5015a3 100644 --- a/src/app/storymaps/common/builder/media/image/FileUploadHelper.js +++ b/src/app/storymaps/common/builder/media/image/FileUploadHelper.js @@ -131,7 +131,7 @@ define([ }, getUploadBaseName: function(file, offset) { - var name = this.getNameWithoutExtension(file.name); + var name = this.getNameWithoutExtension(file.name).replace(/[<>"'()*%!?&]/g, ''); var ext = this.getExt(file.name, file.type); var baseName = name + '__' + (new Date().getTime() + (offset || 0)); return baseName + '.' + ext; @@ -218,7 +218,7 @@ define([ getSizesObj: function(fileName) { return { name: fileName, - url: this.getResourcesUrl() + '/' + encodeURI(fileName), + url: this.getResourcesUrl() + '/' + encodeURIComponent(fileName), width: this.getResourceWidth(fileName) }; }, @@ -422,7 +422,7 @@ define([ lookup[fileId] = { fileId: fileId, sizes: [], - displayName: strippedName + '.' + ext, + displayName: decodeURIComponent(strippedName) + '.' + ext, modified: dateNum ? new Date(dateNum) : '', thumbFile: '', resourcesUrl: resourcesUrl @@ -434,7 +434,7 @@ define([ } else { lookup[fileId].sizes.push({ name: r, - url: resourcesUrl + '/' + r, + url: resourcesUrl + '/' + encodeURIComponent(r), width: self.getResourceWidth(r) || 0 }); } diff --git a/src/app/storymaps/common/builder/settings/ViewHeader.css b/src/app/storymaps/common/builder/settings/ViewHeader.css index 629aaa3..b2038f7 100644 --- a/src/app/storymaps/common/builder/settings/ViewHeader.css +++ b/src/app/storymaps/common/builder/settings/ViewHeader.css @@ -45,7 +45,7 @@ */ .settings-header .settings-table { - width: 310px; + width: 300px; margin-top: 10px; } diff --git a/src/app/storymaps/common/ui/share/ShareURLPanel.js b/src/app/storymaps/common/ui/share/ShareURLPanel.js index ee61b67..6828eed 100644 --- a/src/app/storymaps/common/ui/share/ShareURLPanel.js +++ b/src/app/storymaps/common/ui/share/ShareURLPanel.js @@ -58,7 +58,7 @@ define([ _linkField.val(url); container.find(".btn-bitlylink-open").attr("href", url); - SocialSharing.requestBitly(url).then(function(shortURL){ + SocialSharing.requestShortUrl(url).then(function(shortURL){ _linkField.val(shortURL); if ( selectUrl === undefined || selectUrl === true ) { _linkField.select(); diff --git a/src/app/storymaps/common/utils/CommonHelper.js b/src/app/storymaps/common/utils/CommonHelper.js index e91404b..6319442 100644 --- a/src/app/storymaps/common/utils/CommonHelper.js +++ b/src/app/storymaps/common/utils/CommonHelper.js @@ -810,13 +810,17 @@ define(["dojo/cookie", possiblyAddToken: function(url) { - if (!this.needsToken(url)) { + if (!this.isAppResource(url)) { return url; } // might as well refresh the token...? url = this.removeToken(url); + if (!this.needsTokenAdded(url)) { + return url; + } + var token = ''; if (app.portal && app.portal.getPortalUser()) { @@ -847,7 +851,7 @@ define(["dojo/cookie", && url.match(new RegExp('\/sharing\/rest\/content\/items\/' + appItem.id + '\/resources\/')); }, - needsToken: function(url) { + needsTokenAdded: function(url) { var appItem = app.data && app.data.getWebAppItem && app.data.getWebAppItem(); if (!appItem) { return false; @@ -874,7 +878,7 @@ define(["dojo/cookie", }, possiblyRemoveToken: function(url) { - if (!this.needsToken(url)) { + if (!this.isAppResource(url)) { return url; } return this.removeToken(url); diff --git a/src/app/storymaps/common/utils/SocialSharing.js b/src/app/storymaps/common/utils/SocialSharing.js index a1e3c95..cbf0959 100644 --- a/src/app/storymaps/common/utils/SocialSharing.js +++ b/src/app/storymaps/common/utils/SocialSharing.js @@ -1,4 +1,4 @@ -define(["dojo/Deferred", "esri/urlUtils"], +define(["dojo/Deferred", "esri/urlUtils"], function( Deferred, urlUtils @@ -63,35 +63,31 @@ define(["dojo/Deferred", "esri/urlUtils"], }); }, */ - requestBitly: function (url) - { - var bitlyUrls = [ - "http://api.bitly.com/v3/shorten?callback=?", - "https://api-ssl.bitly.com/v3/shorten?callback=?" - ], - bitlyUrl = location.protocol == 'http:' ? bitlyUrls[0] : bitlyUrls[1], - targetUrl = url || document.location.href, - resultDeferred = new Deferred(); + + requestShortUrl: function(url) { + var esriUrlShortener = 'https://arcg.is/prod/shorten?callback=?', + targetUrl = url || document.location.href, + resultDeferred = new Deferred(); $.getJSON( - bitlyUrl, + esriUrlShortener, { - "format": "json", - "apiKey": app.cfg.HEADER_SOCIAL.bitly.key, - "login": app.cfg.HEADER_SOCIAL.bitly.login, - "longUrl": targetUrl + 'longUrl': targetUrl }, - function(response) - { - if( ! response || ! response || ! response.data.url ) + function(response) { + console.log(response); + if(! response || ! response || ! response.data.url) { resultDeferred.reject(); - else + } + else { resultDeferred.resolve(response.data.url); + } } ); return resultDeferred; }, + cleanURL: function(url, noEncoding) { var urlParams = urlUtils.urlToObject(url); diff --git a/src/app/storymaps/common/utils/WebMapHelper.js b/src/app/storymaps/common/utils/WebMapHelper.js index 5fd0341..86f6e75 100644 --- a/src/app/storymaps/common/utils/WebMapHelper.js +++ b/src/app/storymaps/common/utils/WebMapHelper.js @@ -37,9 +37,9 @@ define(["esri/request", var user = portal.getPortalUser(); var rqUrl = this.getSharingURL(portal) - + "content/users/" + user.credential.userId + + "content/users/" + (app.appCfg.useWebmapOwnerAsSave ? item.owner : user.credential.userId) + (item.ownerFolder ? ("/" + item.ownerFolder) : "") - + "/addItem"; + + (item.id ? "/items/" + item.id + "/update" : "/addItem"); var rqData = { item: item.item, diff --git a/src/app/storymaps/tpl/core/Config.js b/src/app/storymaps/tpl/core/Config.js index ea4cd04..969e6e1 100644 --- a/src/app/storymaps/tpl/core/Config.js +++ b/src/app/storymaps/tpl/core/Config.js @@ -3,7 +3,6 @@ define([], // Header default configuration var HEADER_LOGO_URL = "resources/tpl/viewer/icons/esri-logo.png", HEADER_LOGO_TARGET = "http://www.esri.com", - HEADER_LINK_TEXT = "A story map", HEADER_LINK_URL = "http://storymaps.arcgis.com"; app.appCfg = { @@ -218,7 +217,7 @@ define([], { app.cfg.HEADER_LOGO_URL = HEADER_LOGO_URL; app.cfg.HEADER_LOGO_TARGET = HEADER_LOGO_TARGET; - app.cfg.HEADER_LINK_TEXT = HEADER_LINK_TEXT; + app.cfg.HEADER_LINK_TEXT = i18n.viewer.headerFromCommon.storymapsText; app.cfg.HEADER_LINK_URL = HEADER_LINK_URL; return app.cfg @@ -261,4 +260,4 @@ define([], } }; } -); \ No newline at end of file +); diff --git a/src/app/storymaps/tpl/core/Data.js b/src/app/storymaps/tpl/core/Data.js index 6ef42a1..b246246 100644 --- a/src/app/storymaps/tpl/core/Data.js +++ b/src/app/storymaps/tpl/core/Data.js @@ -320,9 +320,12 @@ define(["./WebApplicationData", // Also add the eventual webmap the application have been published with // when starting from a webmap in AGOL Map Viewer - var sourceWebmap = WebApplicationData.getSourceWebmap(); - if ( sourceWebmap && ! webmapsInfoHash[sourceWebmap] ) { - webmapsInfoHash[sourceWebmap] = {}; + // (but only if we're in builder! otherwise, a private webmap could ruin a public app. -als) + if (app.isInBuilder) { + var sourceWebmap = WebApplicationData.getSourceWebmap(); + if ( sourceWebmap && ! webmapsInfoHash[sourceWebmap] ) { + webmapsInfoHash[sourceWebmap] = {}; + } } $.each(Object.keys(webmapsInfoHash), function(i, webmap){ diff --git a/src/app/storymaps/tpl/ui/MainStage.js b/src/app/storymaps/tpl/ui/MainStage.js index 71650ed..3078111 100644 --- a/src/app/storymaps/tpl/ui/MainStage.js +++ b/src/app/storymaps/tpl/ui/MainStage.js @@ -960,7 +960,7 @@ define(["lib-build/tpl!./MainMediaContainerMap", if (!layer._collection) { query.returnGeometry = true; query.outFields = ["*"]; // popupCfg.fieldName ? - query.outSpatialReference = app.map.spatialReference; + query.outSpatialReference = map.spatialReference; } // TODO: Image Services @@ -986,7 +986,7 @@ define(["lib-build/tpl!./MainMediaContainerMap", query.objectIds = [popupCfg.fieldValue]; query.returnGeometry = true; query.outFields = ["*"]; // popupCfg.fieldName ? - query.outSpatialReference = app.map.spatialReference; + query.outSpatialReference = map.spatialReference; queryTask.execute(query, function(featureSet) { applyPopupConfigurationStep3(map, popupCfg, featureSet.features, index, serviceId, layerIdx); @@ -1017,7 +1017,7 @@ define(["lib-build/tpl!./MainMediaContainerMap", map.infoWindow.show(center); // Center the map is the geometry isn't visible - if ( ! app.map.extent.contains(center) ) { + if ( ! map.extent.contains(center) ) { map.centerAt(center); // Show back btn only if it's a Main Stage action if ( index === null ) { @@ -1040,7 +1040,7 @@ define(["lib-build/tpl!./MainMediaContainerMap", var mapContainer = $(map.container), width = mapContainer.width(), height = mapContainer.height(), - pos = map.toScreen(app.map.infoWindow.location), + pos = map.toScreen(map.infoWindow.location), visibleControls = mapContainer.find('.esriSimpleSlider:visible, .geocoderBtn:visible'), posControls = visibleControls.last().position() || { left: 0 }, posPanel = $(".descLegendPanel:visible").position(), diff --git a/src/index.html b/src/index.html index 97f7c89..d316a18 100644 --- a/src/index.html +++ b/src/index.html @@ -3,35 +3,34 @@