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 @@ - - + - + - - - + - - - + - + - + + - +
- + - + - +
@@ -158,8 +163,8 @@

-
- +
@@ -170,7 +175,7 @@

- +
@@ -188,36 +193,36 @@

-
- +
+ - +
-
- +
- + - +
- +
@@ -266,7 +271,7 @@

- + - \ No newline at end of file + diff --git a/src/resources/tpl/builder/nls/nl/template.js b/src/resources/tpl/builder/nls/nl/template.js index 224a22c..142162d 100644 --- a/src/resources/tpl/builder/nls/nl/template.js +++ b/src/resources/tpl/builder/nls/nl/template.js @@ -96,7 +96,7 @@ define({ "content2Div2": "U kunt ook het logo van Esri vervangen door uw eigen logo om uw merk te promoten. U kunt ook de website opgeven die wordt geopend als de lezers op uw logo klikken zodat ze meer informatie kunnen krijgen.", "content3Div1": "In het dialoogvenster Organiseren kunt u uw %TPL_NAME% beheren. In dit dialoogvenster kunt u de volgorde van de serie veranderen door te slepen.", "content3Div2": "U kunt ook content verwijderen of verbergen. Verbergen is nuttig als u nieuwe content voorbereidt die nog niet in uw story map kan worden opgenomen.", - "content4Div1": "Hebt u een fout gevonden of wilt u uw materiaal wijzigen? Geen probleem. Zoek naar het bewerkingspictogram dat overal in de app beschikbaar is om wijzigingen in uw inhoud door te voeren. U zult de bewerkingsfuncties vaak gebruiken wanneer u uw %TPL_NAME% ontwikkelt.", + "content4Div1": "Hebt u een fout gevonden of wilt u uw materiaal wijzigen? Geen probleem. Zoek naar het bewerkingspictogram dat overal in de app beschikbaar is om wijzigingen in uw content door te voeren. U zult de bewerkingsfuncties vaak gebruiken wanneer u uw %TPL_NAME% ontwikkelt.", "content5Div1": "Als u uw %TPL_NAME% opslaat is dit in eerste instantie privé. Gebruik de knop Delen om het met anderen te delen. U kunt uw %TPL_NAME% publiekelijk delen zodat het toegankelijk is.", "content5Div2": "Afhankelijk van uw account heeft u wellicht ook de optie om uw %TPL_NAME% te delen met mensen binnen uw organisatie, zodat anderen er geen toegang tot hebben.", "content6Div1": "Standaard zijn de kaarten in een serie gesynchroniseerd om dezelfde locatie te tonen. Dit betekent dat de locatie getoond in de eerste kaart automatisch wordt toegepast op alle andere kaarten en dat als een lezer naar een andere locatie in de huidige kaart pant of zoomt, dit ook wordt toegepast op andere kaarten.",