diff --git a/MapTour/deploy/.gitkeep b/MapTour/deploy/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/MapTour/package.json b/MapTour/package.json index 0b06a7d..e811357 100644 --- a/MapTour/package.json +++ b/MapTour/package.json @@ -1,6 +1,6 @@ { "name": "StorytellingMapTour", - "version": "2.2.6", + "version": "2.2.7", "devDependencies": { "grunt": "~0.4.1", "grunt-contrib-clean": "~0.4.0", diff --git a/MapTour/src/app/maptour-config.js b/MapTour/src/app/maptour-config.js index 78f0870..3087eb8 100644 --- a/MapTour/src/app/maptour-config.js +++ b/MapTour/src/app/maptour-config.js @@ -124,6 +124,9 @@ APPCFG = { // // Builder // + + HELP_URL: "http://links.esri.com/storymaps/map_tour_template", + HELP_URL_PORTAL: "http://links.esri.com/storymaps/map_tour_template", // Control the authorized data source (for initialization and import screen) AUTHORIZED_IMPORT_SOURCE: { @@ -143,6 +146,11 @@ APPCFG = { // To use Facebook import on Portal for ArcGIS, create your own ID at https://developers.facebook.com/ // or set AUTHORIZED_IMPORT_SOURCE.facebook to false FACEBOOK_APP_ID: "471023926309627", + // This Youtube key is valid for application running on arcgis.com and esri.com domains + // If the application is deployed on Portal for ArcGIS or your own server, the Youtube api call + // won't be perfomed until you set the following flag and provide your own key + YOUTUBE_DISABLE_ON_PORTAL: true, + YOUTUBE_API_KEY: "AIzaSyDevTFP16nz6sA-akiOVi6wWXiplJnQ4qw", COLOR_SCHEMES: [ // COLORS is added as the first item at runtime diff --git a/MapTour/src/app/storymaps/core/Core.js b/MapTour/src/app/storymaps/core/Core.js index fc31a91..f70b0b1 100644 --- a/MapTour/src/app/storymaps/core/Core.js +++ b/MapTour/src/app/storymaps/core/Core.js @@ -425,6 +425,14 @@ define(["esri/map", { console.log("maptour.core.Core - loadWebMap - webmapId:", webmapIdOrJSON); + // Fix a Chrome freeze when map have a large initial extent (level 16 and up) + // Set the zoomDuration to 50ms, set back to default in see MainView.displayApp + // Using a value of 0ms create tile loading issue for all app life, it + // looks like the API would not load all zoom level but resample lower level + if( has("chrome") ) { + esriConfig.defaults.map.zoomDuration = 50; + } + arcgisUtils.createMap(webmapIdOrJSON, "mainMap", { mapOptions: { slider: true, @@ -551,9 +559,12 @@ define(["esri/map", function displayApp() { - app.isLoading = false; $("#loadingOverlay").fadeOut(); loadingIndicator.stop(); + + setTimeout(function(){ + app.isLoading = false; + }, 50); } function initError(error, message, noDisplay) @@ -737,7 +748,7 @@ define(["esri/map", function showTemplatePreview() { - window.location.replace('preview.html'); + window.location = app.isPortal && APPCFG.HELP_URL_PORTAL ? APPCFG.HELP_URL_PORTAL : APPCFG.HELP_URL; } function redirectToSignIn() diff --git a/MapTour/src/app/storymaps/maptour/builder/ImportPopupViewHome.js b/MapTour/src/app/storymaps/maptour/builder/ImportPopupViewHome.js index 2720ba9..4d7197b 100644 --- a/MapTour/src/app/storymaps/maptour/builder/ImportPopupViewHome.js +++ b/MapTour/src/app/storymaps/maptour/builder/ImportPopupViewHome.js @@ -20,6 +20,18 @@ define(["storymaps/maptour/core/WebApplicationData", "dojo/has"], this.getView = function() { _footer.find('.btnNext').attr("disabled", "disabled").html(i18n.viewer.onlinePhotoSharingCommon.select); + + if ( app.isPortal && APPCFG.YOUTUBE_DISABLE_ON_PORTAL ) { + _container.find('.btn-select-youtube').addClass("disabled").unbind('click'); + _container.find('.btn-select-youtube').popover('destroy').popover({ + trigger: 'hover', + placement: 'top', + html: true, + content: i18n.viewer.onlinePhotoSharingCommon.disabled, + container: '.popover-import' + }); + } + return _container; }; diff --git a/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHome.js b/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHome.js index 24776cd..4ef4ad5 100644 --- a/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHome.js +++ b/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHome.js @@ -35,6 +35,17 @@ define(["dojo/has"], } _footer.find('.btnNext').attr("disabled", "disabled").html(i18n.viewer.onlinePhotoSharingCommon.select); + if ( app.isPortal && APPCFG.YOUTUBE_DISABLE_ON_PORTAL ) { + _container.find('.btn-select-youtube').addClass("disabled").unbind('click'); + _container.find('.btn-select-youtube').popover('destroy').popover({ + trigger: 'hover', + placement: 'top', + html: true, + content: i18n.viewer.onlinePhotoSharingCommon.disabled, + container: '.popover-init' + }); + } + return _container; }; diff --git a/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHostedFSCreation.js b/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHostedFSCreation.js index 7431d27..b29cb12 100644 --- a/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHostedFSCreation.js +++ b/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHostedFSCreation.js @@ -457,7 +457,9 @@ define([ function getAdminUrl(url) { - return url.replace("rest/services","admin/services").replace("/FeatureServer",".FeatureServer"); + return url.replace("http://", window.location.protocol + "//") + .replace("rest/services","admin/services") + .replace("/FeatureServer",".FeatureServer"); } // diff --git a/MapTour/src/app/storymaps/maptour/core/Config.js b/MapTour/src/app/storymaps/maptour/core/Config.js index 45ddd1b..e028f8c 100644 --- a/MapTour/src/app/storymaps/maptour/core/Config.js +++ b/MapTour/src/app/storymaps/maptour/core/Config.js @@ -35,7 +35,9 @@ define([], && APPCFG.CORS_SERVER && APPCFG.AUTHORIZED_IMPORT_SOURCE && APPCFG.FLICKR_API_KEY - && APPCFG.FACEBOOK_APP_ID; + && APPCFG.FACEBOOK_APP_ID + && APPCFG.YOUTUBE_DISABLE_ON_PORTAL !== undefined + && APPCFG.YOUTUBE_API_KEY; } }; } diff --git a/MapTour/src/app/storymaps/maptour/core/MainView.js b/MapTour/src/app/storymaps/maptour/core/MainView.js index 0fd6583..b51a620 100644 --- a/MapTour/src/app/storymaps/maptour/core/MainView.js +++ b/MapTour/src/app/storymaps/maptour/core/MainView.js @@ -126,13 +126,68 @@ define(["storymaps/maptour/core/WebApplicationData", // Prevent iPad vertical bounce effect // except on few containers that needs that - $(document).bind( - 'touchmove', - function(e) { - if( ! $(e.target).parents('#helpPopup, #placardContainer, #introPanel, #infoPanel, #popupViewGeoTag').length && ! $(e.target).hasClass('subtitle') ) - e.preventDefault(); + if ( has("touch") ) { + $(document).bind( + 'touchmove', + function(e) { + if( ! $(e.target).parents('#helpPopup, #placardContainer, #introPanel, #infoPanel, #popupViewGeoTag').length && ! $(e.target).hasClass('subtitle') ) + e.preventDefault(); + } + ); + } + + // Prevent focus on mousedown but allow it with keyboard + $("body").on("mousedown", "*", function(e) { + if (($(this).is(":focus") || $(this).is(e.target)) && $(this).css("outline-style") == "none") { + $(this).css("outline", "none").on("blur", function() { + $(this).off("blur").css("outline", ""); + }); } - ); + }); + + // Detect focus on the title to avoid losing the current point if + // the app has previously navigated using the mouse + /* + var preventTitleFocusAction = false; + $("#headerDesktop .title").click(function(){ + preventTitleFocusAction = true; + }); + + $("#headerDesktop .title").focusin(function(e){ + setTimeout(function(){ + if ( ! preventTitleFocusAction ) { + if ( app.data.getCurrentIndex() > 0 ) { // && ! e.relatedTarget + if ( app.data.getCurrentIndex() < app.data.getNbPoints() - 1 ) + topic.publish("CAROUSEL_CLICK", app.data.getCurrentIndex() + 1); + } + } + + preventTitleFocusAction = false; + }, 300); + }); + */ + + /* + $(document).on('keydown', function(e){ + if( e.keyCode === 9 ) { + var focusElem = $(":focus"); + + if ( ! focusElem.length ) { + setTimeout(function(){ + if ( ! e.shiftKey ) { + if ( app.data.getCurrentIndex() < app.data.getNbPoints() - 1 ) + topic.publish("CAROUSEL_CLICK", app.data.getCurrentIndex() + 1); + } + else { + if ( app.data.getCurrentIndex() > 0 ) + topic.publish("CAROUSEL_CLICK", app.data.getCurrentIndex() - 1); + } + }, 50); + + } + } + }); + */ if( has("touch") ) $("body").addClass("hasTouch"); @@ -637,6 +692,23 @@ define(["storymaps/maptour/core/WebApplicationData", */ function displayApp() { + // Fix a Chrome freeze when map have a large initial extent (level 16 and up) + // Set back the zoomDuration to 500ms + if( has("chrome") ) { + if ( app.map.getLevel() > 0 ) { + app.map.setZoom(app.map.getLevel() - 1).then(function(){ + // For the map command +/- buttons to behave well + esriConfig.defaults.map.zoomDuration = 50; + app.map.setZoom(app.map.getLevel() + 1).then(function(){ + esriConfig.defaults.map.zoomDuration = 500; + }); + }); + } + else { + esriConfig.defaults.map.zoomDuration = 500; + } + } + // If intro record, display mobile intro view if ( app.data.getIntroData() && app.data.getCurrentIndex() == null && (! has("ie") || has("ie") > 8) ) app.mobileIntroView.init(app.data.getIntroData(), WebApplicationData.getColors()[2]); diff --git a/MapTour/src/app/storymaps/maptour/ui/desktop/Carousel.js b/MapTour/src/app/storymaps/maptour/ui/desktop/Carousel.js index 1b02888..15965ec 100644 --- a/MapTour/src/app/storymaps/maptour/ui/desktop/Carousel.js +++ b/MapTour/src/app/storymaps/maptour/ui/desktop/Carousel.js @@ -33,6 +33,8 @@ define(["dojo/has", onMove: [-1,-1], onScroll: [-1,-1] }; + + var _navigationFromTab = false; this.init = function(slides, bgColor, hoverColor) { @@ -96,7 +98,46 @@ define(["dojo/has", updateArrows(); - $(selector + ' .carouselScroller ul').html(renderItem(slides)); + $(selector + ' .carouselScroller ul').html(renderItem(slides)).removeAttr("aria-hidden"); + + // When navigation with tab also navigate to the point (refresh picture panel and map) + $(selector + ' .carousel-item-div').focus(function(e){ + var selectedIndex = $(selector + ' .carousel-item-div.selected').parents('li').index(), + focusIndex = $(this).parents('li').index(); + + if ( selectedIndex != focusIndex) { + topic.publish("CAROUSEL_CLICK", focusIndex); + _navigationFromTab = true; + } + }); + + // Logic to navigate away after the last point + $(selector + ' .carousel-item-div').on('keydown', function(e){ + var selectedIndex = $(selector + ' .carousel-item-div.selected').parents('li').index(), + focusIndex = $(this).parents('li').index(); + + if( e.keyCode === 9 && ! event.shiftKey ) { + if ( selectedIndex == focusIndex && selectedIndex == $('.carousel-item-div').length - 1) { + // TODO should not be done here + // TODO should also support tab+shift from there + + // Add tabindex to the header righ area + // This need to be done dynamically to only navigate to them after the carousel + $("#headerDesktop .msLink *, #headerDesktop .shareIcon").attr("tabindex", "0"); + + if ( $("#headerDesktop .msLink a").length ) + $("#headerDesktop .msLink a")[0].focus(); + else if ( $("#headerDesktop .msLink span").length ) + $("#headerDesktop .msLink span")[0].focus(); + else if ( $("#headerDesktop .shareIcon:visible").length ) + $("#headerDesktop .shareIcon")[0].focus(); + else + $("#headerDesktop .title")[0].focus(); + + return false; + } + } + }); _picDownloadedIndex = 14; $(selector + ' .carouselScroller ul img').slice(0,_picDownloadedIndex).each(function(i, img){ @@ -120,9 +161,13 @@ define(["dojo/has", // The first div is necessary for vertical centering and the span around the image for the numbering // The color specification though class is not ideal, but to have that more dynamic all the rest is a pain carouselHTML += '
  • '; - carouselHTML += '
  • '; }); @@ -141,6 +186,19 @@ define(["dojo/has", $(selector + ' .carousel-item-div').removeClass("selected"); $(selector + ' .carousel-item-div').eq(index).addClass("selected"); + // Focus new carousel active item + if ( ! app.isLoading ) { + // Does carousel already has focus (through tab navigation) + var carouselHasFocus = !! $(":focus").parents("#footerDesktop").length; + + $(":focus").blur(); + + if ( _navigationFromTab || carouselHasFocus ) + $(selector + ' .carousel-item-div').eq(index).focus(); + + _navigationFromTab = false; + } + scrollToIndex(index); updateArrows(); }; diff --git a/MapTour/src/app/storymaps/maptour/ui/mobile/Carousel.css b/MapTour/src/app/storymaps/maptour/ui/mobile/Carousel.css index 8ae2e9e..a7cfe91 100644 --- a/MapTour/src/app/storymaps/maptour/ui/mobile/Carousel.css +++ b/MapTour/src/app/storymaps/maptour/ui/mobile/Carousel.css @@ -36,4 +36,66 @@ height: 22px; right: 5px; z-index: 499; +} + +/* + * Desktop navigation + */ + +#footerMobile.hasDesktopBtn .carousel { + margin: 0 53px; +} + +#footerMobile .embed-btn-container { + display: none; +} + +#footerMobile.hasDesktopBtn .embed-btn-container { + position: absolute; + top: 14px; + display: block; + width: 51px; + height: 100%; + z-index: 1; + opacity: 0.8; + padding-top: 14px; +} + +#footerMobile .embed-btn-container.disabled { + opacity: 0.2; + cursor: default; +} + +#footerMobile .embed-btn { + width: 42px; + height: 42px; + background: url(../../../../../resources/icons/embed-arrows.png); +} + +#footerMobile .embed-btn-container:not(.disabled):hover { + opacity: 1.0; + cursor: pointer; +} + +/* Left button */ +#footerMobile .embed-btn-left { + left: 0; + padding-left: 9px; +} + +#footerMobile .embed-btn-left.disabled .embed-btn { + background-position: 42px 0; +} + +/* Right button */ +#footerMobile .embed-btn-right { + right: 0; +} + +#footerMobile .embed-btn-right .embed-btn { + background-position: 0 -42px; +} + +#footerMobile .embed-btn-right.disabled .embed-btn { + background-position: 42px -42px; } \ No newline at end of file diff --git a/MapTour/src/app/storymaps/maptour/ui/mobile/Carousel.js b/MapTour/src/app/storymaps/maptour/ui/mobile/Carousel.js index 8257e57..359f28c 100644 --- a/MapTour/src/app/storymaps/maptour/ui/mobile/Carousel.js +++ b/MapTour/src/app/storymaps/maptour/ui/mobile/Carousel.js @@ -23,6 +23,9 @@ define(["storymaps/maptour/core/MapTourHelper", "dojo/topic"], initEvents(slides); topic.subscribe("CORE_SELECTED_TOURPOINT_UPDATE", updateSlide); + + if ( ! $("body").hasClass("hasTouch") ) + $(selector).addClass("hasDesktopBtn"); }; this.update = function(slides, bgColor) @@ -49,6 +52,15 @@ define(["storymaps/maptour/core/MapTourHelper", "dojo/topic"], } else _preventNextRefresh = false; + + $(selector).find(".embed-btn-left").toggleClass( + "disabled", + ! tourPointIndex + ); + $(selector).find(".embed-btn-right").toggleClass( + "disabled", + tourPointIndex === _carousel.options.numberOfPages - 1 + ); }; function render(slides) @@ -56,7 +68,7 @@ define(["storymaps/maptour/core/MapTourHelper", "dojo/topic"], _carousel = new SwipeView(selector + ' .carousel', { numberOfPages: slides.length }); - + // Load initial data var nbSlides = Math.min(3, Math.max(3, slides.length)); for (var i=0; i' + str + ''); + str2.find('a').attr("tabindex", "-1"); + return str2.html(); + } }; } ); \ No newline at end of file diff --git a/MapTour/src/app/storymaps/ui/crossfader/CrossFader.js b/MapTour/src/app/storymaps/ui/crossfader/CrossFader.js index acaff21..ddbfc4c 100644 --- a/MapTour/src/app/storymaps/ui/crossfader/CrossFader.js +++ b/MapTour/src/app/storymaps/ui/crossfader/CrossFader.js @@ -374,9 +374,18 @@ define(["storymaps/ui/inlineFieldEdit/InlineFieldEdit", $(_placardContainer).toggleClass("force-hidden", name === "" && text === ""); } + // Picture panel is not in the tab list except if there is an intro record + var tabOrder = "tabindex='-1' aria-hidden='true'"; + + if ( app.isLoading && app.data.hasIntroRecord() ) + tabOrder = "tabindex='0'"; + $(_placard).empty(); - $(_placard).append("
    "+name+"
    "); - $(_placard).append("
    "+text+"
    "); + $(_placard).append("
    "+name+"
    "); + $(_placard).append("
    "+text+"
    "); + + // Remove user generated content links from the tab navigation + $(_placard).find("a").attr("tabindex", "-1"); if (isInBuilderMode) { new InlineFieldEdit( diff --git a/MapTour/src/app/storymaps/ui/header/Header.css b/MapTour/src/app/storymaps/ui/header/Header.css index 598c944..b6a2546 100644 --- a/MapTour/src/app/storymaps/ui/header/Header.css +++ b/MapTour/src/app/storymaps/ui/header/Header.css @@ -31,7 +31,8 @@ #headerDesktop .title { height:26px; - padding-top: 18px; + margin-top: 14px; + padding-top: 4px; font-size:20px; font-weight:normal; text-align:left; diff --git a/MapTour/src/app/storymaps/ui/header/Header.js b/MapTour/src/app/storymaps/ui/header/Header.js index 7522250..62b40b7 100644 --- a/MapTour/src/app/storymaps/ui/header/Header.js +++ b/MapTour/src/app/storymaps/ui/header/Header.js @@ -53,8 +53,8 @@ define(["storymaps/ui/inlineFieldEdit/InlineFieldEdit", new InlineFieldEdit(selector, editFieldsEnterEvent, editFieldsExitEvent); if( ! isInBuilderMode && ! subtitle ) { - $(selector + ' #headerDesktop .title').css("padding-top", 40); - $(selector + ' #headerDesktop .subtitle').css("height", 32); + $(selector + ' #headerDesktop .title').css("margin-top", 40); + $(selector + ' #headerDesktop .subtitle').css("height", 32).attr("tabindex", "-1"); } // Mobile init @@ -116,8 +116,10 @@ define(["storymaps/ui/inlineFieldEdit/InlineFieldEdit", else { $(selector + ' .logo img').attr("src", url); if (target) { - $(selector + ' .logo img').closest("a").css("cursor", "pointer"); - $(selector + ' .logo img').closest("a").attr("href", target); + $(selector + ' .logo img').closest("a") + .css("cursor", "pointer") + .attr("href", target) + .attr("tabindex", "-1"); } else $(selector + ' .logo img').closest("a").css("cursor", "default"); @@ -129,7 +131,7 @@ define(["storymaps/ui/inlineFieldEdit/InlineFieldEdit", this.setTopRightLink = function(text, link) { if( link ) - $(selector + ' .social .msLink').html(text ? '' + text + '' : ''); + $(selector + ' .social .msLink').html(text ? '' + text + '' : ''); else if ( text ) $(selector + ' .social .msLink').html('' + text + ''); else @@ -175,6 +177,15 @@ define(["storymaps/ui/inlineFieldEdit/InlineFieldEdit", $(selector + " .share_facebook").fastClick(shareFacebook); $(selector + " .share_twitter").fastClick(shareTwitter); $(selector + " .share_bitly").fastClick(shareBitly); + + // Bind keyboard enter to click + $(selector).find(".shareIcon").off('keypress').keypress(function (e) { + if(e.which == 13) { + $(this).click(); + return false; + } + }); + } }; diff --git a/MapTour/src/app/storymaps/ui/multiTips/MultiTips.js b/MapTour/src/app/storymaps/ui/multiTips/MultiTips.js index 2ded2f4..279c85f 100644 --- a/MapTour/src/app/storymaps/ui/multiTips/MultiTips.js +++ b/MapTour/src/app/storymaps/ui/multiTips/MultiTips.js @@ -124,7 +124,7 @@ define(["dojo/dom-style", settings.visible = true; array.forEach(settings.pointArray, function(pt, i) { - domConstruct.place("
    ", mapDiv, "last"); + domConstruct.place("
    ", mapDiv, "last"); query('#multiTip'+i)[0].innerHTML = settings.content; domStyle.set('multiTip' + i, { diff --git a/MapTour/src/app/storymaps/utils/FacebookConnector.js b/MapTour/src/app/storymaps/utils/FacebookConnector.js index 8205e07..520b6c9 100644 --- a/MapTour/src/app/storymaps/utils/FacebookConnector.js +++ b/MapTour/src/app/storymaps/utils/FacebookConnector.js @@ -164,7 +164,8 @@ define(["dojo/Deferred"], appId : appId, // App ID status : true, // check login status cookie : true, // enable cookies to allow the server to access the session - xfbml : true // parse XFBML + xfbml : true, // parse XFBML, + version : 'v2.1' }); FB.Event.subscribe('auth.authResponseChange', function(response) { @@ -183,14 +184,13 @@ define(["dojo/Deferred"], }); }; - // Load the SDK asynchronously - (function(d){ - var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0]; + (function(d, s, id){ + var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) {return;} - js = d.createElement('script'); js.id = id; js.async = true; - js.src = "//connect.facebook.net/en_US/all.js"; - ref.parentNode.insertBefore(js, ref); - }(document)); + js = d.createElement(s); js.id = id; + js.src = "//connect.facebook.net/en_US/sdk.js"; + fjs.parentNode.insertBefore(js, fjs); + }(document, 'script', 'facebook-jssdk')); } }; } diff --git a/MapTour/src/app/storymaps/utils/MovableGraphic.js b/MapTour/src/app/storymaps/utils/MovableGraphic.js index 4e23d8f..7cbb498 100644 --- a/MapTour/src/app/storymaps/utils/MovableGraphic.js +++ b/MapTour/src/app/storymaps/utils/MovableGraphic.js @@ -41,7 +41,7 @@ define(["dojo/has", "dojo/touch", "dojo/on", "dojo/_base/array", "dojo/_base/con var event3 = on(layer._div.rawNode, touch.press, function(event) { // Prevent using another point as a start location on desktop - does not work on touch - if (event.graphic == graphic || has("touch") || has("ie") >= 10 ) { + if (event.graphic == graphic || has("touch") || has("ie") == 10 || has("trident") == 7) { map.disablePan(); _editPointLayer = true; @@ -56,7 +56,7 @@ define(["dojo/has", "dojo/touch", "dojo/on", "dojo/_base/array", "dojo/_base/con onMoveEndCallback(graphic); }); - var event5 = has("touch") || has("ie") >= 10 ? + var event5 = has("touch") || has("ie") >= 10 || has("trident") == 7 ? // Using the layer decrease too much the performance ... touch.move(map.__container, moveGraphic) : connect.connect(map, "onMouseDrag", moveGraphic); diff --git a/MapTour/src/app/storymaps/utils/YoutubeConnector.js b/MapTour/src/app/storymaps/utils/YoutubeConnector.js index 4edf35e..ff94e5c 100644 --- a/MapTour/src/app/storymaps/utils/YoutubeConnector.js +++ b/MapTour/src/app/storymaps/utils/YoutubeConnector.js @@ -12,71 +12,85 @@ define(["dojo/Deferred"], resultDeferred.reject(); return resultDeferred; } - - // Youtube queries are limited to 50 results - // Should be made more robust if nbResultMax could be > 99 - var nbResultRq1 = nbResultMax > 50 ? 50 : nbResultMax; - var rqStr = document.location.protocol - + '//gdata.youtube.com/feeds/api/users/' - + userId.replace(' ','') - + '/uploads?v=2' - + '&alt=jsonc'; + var userRqStr = 'https://www.googleapis.com/youtube/v3/channels' + + '?part=id' + + '&forUsername=' + userId.replace(' ','') + + '&key=' + APPCFG.YOUTUBE_API_KEY; $.ajax({ - url: rqStr + '&max-results=' + nbResultRq1, - dataType: 'jsonp', + url: userRqStr, timeout: 4000 }).then( - function(response){ - videos = videos.concat(parseResults(response)); + function(userRqResponse){ + var channelId = null; + + if ( userRqResponse && userRqResponse.items && userRqResponse.items.length ) { + channelId = userRqResponse.items[0].id; + } + + // Youtube queries are limited to 50 results + // Should be made more robust if nbResultMax could be > 99 + var nbResultRq1 = nbResultMax > 50 ? 50 : nbResultMax; + var rqStr = 'https://www.googleapis.com/youtube/v3/search' + + '?part=snippet' + + '&channelId=' + channelId + + '&key=' + APPCFG.YOUTUBE_API_KEY; + + $.ajax({ + url: rqStr + '&maxResults=' + nbResultRq1, + timeout: 4000 + }).then( + function(response){ + videos = videos.concat(parseResults(response)); - // Do we need to fech more data? - if ( nbResultRq1 != nbResultMax && response.data && response.data.totalItems > nbResultRq1 ) { - rqStr += '&max-results=' + (nbResultMax - nbResultRq1) - + '&start-index=' + (nbResultRq1 + 1); - - $.ajax({ - url: rqStr, - dataType: 'jsonp', - timeout: 4000 - }).then( - function(response){ - videos = videos.concat(parseResults(response)); - resultDeferred.resolve(videos); + // Fetch more data id needed + if ( nbResultRq1 != nbResultMax && response.pageInfo && response.pageInfo.totalResults > nbResultRq1 ) { + rqStr += '&maxResults=' + (nbResultMax - nbResultRq1) + + '&pageToken=' + response.nextPageToken; + + $.ajax({ + url: rqStr, + timeout: 4000 + }).then( + function(response){ + videos = videos.concat(parseResults(response)); + resultDeferred.resolve(videos); + } + ); } - ); - } - else - resultDeferred.resolve(videos); + else + resultDeferred.resolve(videos); + }, + function(){ + resultDeferred.reject(); + } + ); }, function(){ resultDeferred.reject(); } ); - + return resultDeferred; }; function parseResults(response) { var videos = []; - var data = response && response.data && response.data.items ? response.data.items : []; + var data = response && response.items ? response.items : []; $.each(data, function(i, video) { - var videoURL = video.content ? video.content['5'] : ''; + var videoURL = getYoutubeEmbed(video && video.id ? video.id.videoId : ''); - if ( videoURL ) { - // Using /v/ cause issue on Firefox (opaque mode doesn't work - the placard is hidden) - videoURL = videoURL.replace('/v/', '/embed/'); - + if ( videoURL && video.snippet ) { videos.push({ - name: video.title || '', - description: video.description || '', + name: video.snippet.title || '', + description: video.snippet.description || '', pic_url: videoURL, - thumb_url: video.thumbnail ? video.thumbnail.sqDefault : '', - lat: video.geoCoordinates ? video.geoCoordinates.latitude : '', - lng: video.geoCoordinates ? video.geoCoordinates.longitude : '', + thumb_url: video.snippet.thumbnails['default'].url, + lat: '', // Extra request to get those? + lng: '', is_video: true }); } @@ -84,6 +98,11 @@ define(["dojo/Deferred"], return videos; } + + function getYoutubeEmbed(videoId) + { + return "//www.youtube.com/embed/" + videoId + "?wmode=opaque"; + } }; } ); \ No newline at end of file diff --git a/MapTour/src/index.html b/MapTour/src/index.html index d8e0e6c..4f9b17c 100644 --- a/MapTour/src/index.html +++ b/MapTour/src/index.html @@ -19,7 +19,8 @@ - + + @@ -67,7 +68,7 @@