From 7b00eb1ecf081d3af4ae4b8cf152bb7f1b6eaa85 Mon Sep 17 00:00:00 2001
From: Thomas Steur <thomas.steur@googlemail.com>
Date: Mon, 20 Oct 2014 05:02:39 +0200
Subject: [PATCH] refs #6469 update smartbanner lib and make sure it works

---
 libs/jquery/jquery.smartbanner.js             | 176 ++++++++++++++----
 .../jquery/stylesheets/jquery.smartbanner.css |   3 +-
 plugins/Login/templates/login.twig            |   2 +-
 3 files changed, 147 insertions(+), 34 deletions(-)

diff --git a/libs/jquery/jquery.smartbanner.js b/libs/jquery/jquery.smartbanner.js
index 912084cf5c..542242b7eb 100644
--- a/libs/jquery/jquery.smartbanner.js
+++ b/libs/jquery/jquery.smartbanner.js
@@ -10,14 +10,16 @@
 
         var standalone = navigator.standalone // Check if it's already a standalone web app or running within a webui view of an app (not mobile safari)
           , UA = navigator.userAgent
-          
+
         // Detect banner type (iOS or Android)
         if (this.options.force) {
             this.type = this.options.force
-        } else if (UA.match(/iPad|iPhone|iPod/i) != null) {
+        } else if (UA.match(/iPhone|iPod/i) != null || (UA.match(/iPad/) && this.options.iOSUniversalApp)) {
             if (UA.match(/Safari/i) != null &&
                (UA.match(/CriOS/i) != null ||
-               window.Number(navigator.userAgent.substr(navigator.userAgent.indexOf('OS ') + 3, 3).replace('_', '.')) < 6)) this.type = 'ios' // Check webview and native smart banner support (iOS 6+)
+               window.Number(UA.substr(UA.indexOf('OS ') + 3, 3).replace('_', '.')) < 6)) this.type = 'ios' // Check webview and native smart banner support (iOS 6+)
+        } else if (UA.match(/\bSilk\/(.*\bMobile Safari\b)?/) || UA.match(/\bKF\w/) || UA.match('Kindle Fire')) {
+            this.type = 'kindle'
         } else if (UA.match(/Android/i) != null) {
             this.type = 'android'
         } else if (UA.match(/Windows NT 6.2/i) != null && UA.match(/Touch/i) !== null) {
@@ -35,7 +37,8 @@
 
         // Get info from meta data
         var meta = $(this.type == 'android' ? 'meta[name="google-play-app"]' :
-            this.type == 'ios' ? 'meta[name="apple-itunes-app"]' : 'meta[name="msApplication-ID"]');
+            this.type == 'ios' ? 'meta[name="apple-itunes-app"]' :
+            this.type == 'kindle' ? 'meta[name="kindle-fire-app"]' : 'meta[name="msApplication-ID"]');
         if (meta.length == 0) return
 
         // For Windows Store apps, get the PackageFamilyName for protocol launch
@@ -46,8 +49,10 @@
             this.appId = /app-id=([^\s,]+)/.exec(meta.attr('content'))[1]
         }
 
-        this.title = this.options.title ? this.options.title : $('title').text().replace(/\s*[|\-·].*$/, '')
-        this.author = this.options.author ? this.options.author : ($('meta[name="author"]').length ? $('meta[name="author"]').attr('content') : window.location.hostname)
+        this.title = this.options.title ? this.options.title : meta.data('title') || $('title').text().replace(/\s*[|\-·].*$/, '')
+        this.author = this.options.author ? this.options.author : meta.data('author') || ($('meta[name="author"]').length ? $('meta[name="author"]').attr('content') : window.location.hostname)
+        this.iconUrl = meta.data('icon-url');
+        this.price = meta.data('price');
 
         // Create banner
         this.create()
@@ -58,17 +63,32 @@
     SmartBanner.prototype = {
 
         constructor: SmartBanner
-    
+
       , create: function() {
             var iconURL
-              , link=(this.options.url ? this.options.url : (this.type == 'windows' ? 'ms-windows-store:PDP?PFN=' + this.pfn : (this.type == 'android' ? 'market://details?id=' : 'https://itunes.apple.com/' + this.options.appStoreLanguage + '/app/id')) + this.appId)
-              , inStore=this.options.price ? this.options.price + ' - ' + (this.type == 'android' ? this.options.inGooglePlay : this.type == 'ios' ? this.options.inAppStore : this.options.inWindowsStore) : ''
+              , link=(this.options.url ? this.options.url : (this.type == 'windows' ? 'ms-windows-store:PDP?PFN=' + this.pfn : (this.type == 'android' ? 'market://details?id=' : (this.type == 'kindle' ? 'amzn://apps/android?asin=' : 'https://itunes.apple.com/' + this.options.appStoreLanguage + '/app/id'))) + this.appId)
+              , price = this.price || this.options.price
+              , inStore=price ? price + ' - ' + (this.type == 'android' ? this.options.inGooglePlay : this.type == 'kindle' ? this.options.inAmazonAppStore : this.type == 'ios' ? this.options.inAppStore : this.options.inWindowsStore) : ''
               , gloss=this.options.iconGloss === null ? (this.type=='ios') : this.options.iconGloss
+            if(this.options.url)
+              link = this.options.url
+            else {
+              if(this.type=='android') {
+                link = 'market://details?id=' + this.appId
+                if(this.options.GooglePlayParams)
+                  link = link + '&referrer=' + this.options.GooglePlayParams
+              }
+              else
+              link = 'https://itunes.apple.com/' + this.options.appStoreLanguage + '/app/id' + this.appId
+            }
+
+            var banner = '<div id="smartbanner" class="'+this.type+'"><div class="sb-container"><a href="#" class="sb-close">&times;</a><span class="sb-icon"></span><div class="sb-info"><strong>'+this.title+'</strong><span>'+this.author+'</span><span>'+inStore+'</span></div><a href="'+link+'" class="sb-button"><span>'+this.options.button+'</span></a></div></div>';
+            (this.options.layer) ? $(this.options.appendToSelector).append(banner) : $(this.options.appendToSelector).prepend(banner);
 
-            $('body').append('<div id="smartbanner" class="'+this.type+'"><div class="sb-container"><a href="#" class="sb-close">&times;</a><span class="sb-icon"></span><div class="sb-info"><strong>'+this.title+'</strong><span>'+this.author+'</span><span>'+inStore+'</span></div><a href="'+link+'" class="sb-button"><span>'+this.options.button+'</span></a></div></div>')
-            
             if (this.options.icon) {
                 iconURL = this.options.icon
+            } else if(this.iconUrl) {
+                iconURL = this.iconUrl;
             } else if ($('link[rel="apple-touch-icon-precomposed"]').length > 0) {
                 iconURL = $('link[rel="apple-touch-icon-precomposed"]').attr('href')
                 if (this.options.iconGloss === null) gloss = false
@@ -79,7 +99,7 @@
             } else if ($('meta[name="msapplication-TileImage"]').length > 0) { /* redundant because ms docs show two case usages */
               iconURL = $('meta[name="msapplication-TileImage"]').attr('content')
             }
-            
+
             if (iconURL) {
                 $('#smartbanner .sb-icon').css('background-image','url('+iconURL+')')
                 if (gloss) $('#smartbanner .sb-icon').addClass('gloss')
@@ -93,47 +113,87 @@
                 $('#smartbanner')
                     .css('top', parseFloat($('#smartbanner').css('top')) * this.scale)
                     .css('height', parseFloat($('#smartbanner').css('height')) * this.scale)
+                    .hide()
                 $('#smartbanner .sb-container')
                     .css('-webkit-transform', 'scale('+this.scale+')')
                     .css('-msie-transform', 'scale('+this.scale+')')
                     .css('-moz-transform', 'scale('+this.scale+')')
                     .css('width', $(window).width() / this.scale)
             }
+            $('#smartbanner').css('position', (this.options.layer) ? 'absolute' : 'static')
         }
-        
+
       , listen: function () {
             $('#smartbanner .sb-close').on('click',$.proxy(this.close, this))
             $('#smartbanner .sb-button').on('click',$.proxy(this.install, this))
         }
-        
+
       , show: function(callback) {
-            $('#smartbanner').stop().animate({top:0},this.options.speedIn).addClass('shown')
-            $('html').animate({marginTop:this.origHtmlMargin+(this.bannerHeight*this.scale)},this.options.speedIn,'swing',callback)
+            var banner = $('#smartbanner');
+            banner.stop();
+
+            if (this.options.layer) {
+                banner.animate({top: 0, display: 'block'}, this.options.speedIn).addClass('shown').show();
+                $('html').animate({marginTop: this.origHtmlMargin + (this.bannerHeight * this.scale)}, this.options.speedIn, 'swing', callback);
+            } else {
+                if ($.support.transition) {
+                    banner.animate({top:0},this.options.speedIn).addClass('shown');
+                    var transitionCallback = function() {
+                        $('html').removeClass('sb-animation');
+                        if (callback) {
+                            callback();
+                        }
+                    };
+                    $('html').addClass('sb-animation').one($.support.transition.end, transitionCallback).emulateTransitionEnd(this.options.speedIn).css('margin-top', this.origHtmlMargin+(this.bannerHeight*this.scale));
+                } else {
+                    banner.slideDown(this.options.speedIn).addClass('shown');
+                }
+            }
         }
-        
+
       , hide: function(callback) {
-            $('#smartbanner').stop().animate({top:-1*this.bannerHeight*this.scale},this.options.speedOut).removeClass('shown')
-            $('html').animate({marginTop:this.origHtmlMargin},this.options.speedOut,'swing',callback)
+            var banner = $('#smartbanner');
+            banner.stop();
+
+            if (this.options.layer) {
+                banner.animate({top: -1 * this.bannerHeight * this.scale, display: 'block'}, this.options.speedIn).removeClass('shown');
+                $('html').animate({marginTop: this.origHtmlMargin}, this.options.speedIn, 'swing', callback);
+            } else {
+                if ($.support.transition) {
+                    banner.css('top', -1*this.bannerHeight*this.scale).removeClass('shown');
+                    var transitionCallback = function() {
+                        $('html').removeClass('sb-animation');
+                        if (callback) {
+                            callback();
+                        }
+                    };
+                    $('html').addClass('sb-animation').one($.support.transition.end, transitionCallback).emulateTransitionEnd(this.options.speedOut).css('margin-top', this.origHtmlMargin);
+                } else {
+                    banner.slideUp(this.options.speedOut).removeClass('shown');
+                }
+            }
         }
-      
+
       , close: function(e) {
             e.preventDefault()
             this.hide()
-            this.setCookie('sb-closed','true',this.options.daysHidden)
+            this.setCookie('sb-closed','true',this.options.daysHidden);
         }
-       
+
       , install: function(e) {
-            this.hide()
+			if (this.options.hideOnInstall) {
+				this.hide()
+			}
             this.setCookie('sb-installed','true',this.options.daysReminder)
         }
-       
+
       , setCookie: function(name, value, exdays) {
             var exdate = new Date()
             exdate.setDate(exdate.getDate()+exdays)
-            value=escape(value)+((exdays==null)?'':'; expires='+exdate.toUTCString())
+            value=encodeURI(value)+((exdays==null)?'':'; expires='+exdate.toUTCString())
             document.cookie=name+'='+value+'; path=/;'
         }
-        
+
       , getCookie: function(name) {
             var i,x,y,ARRcookies = document.cookie.split(";")
             for(i=0;i<ARRcookies.length;i++) {
@@ -141,12 +201,12 @@
                 y = ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1)
                 x = x.replace(/^\s+|\s+$/g,"")
                 if (x==name) {
-                    return unescape(y)
+                    return decodeURI(y)
                 }
             }
             return null
         }
-      
+
       // Demo only
       , switchType: function() {
           var that = this
@@ -165,9 +225,9 @@
 
     $.smartbanner = function (option) {
         var $window = $(window)
-        , data = $window.data('typeahead')
+        , data = $window.data('smartbanner')
         , options = typeof option == 'object' && option
-        if (!data) $window.data('typeahead', (data = new SmartBanner(options)))
+        if (!data) $window.data('smartbanner', (data = new SmartBanner(options)))
         if (typeof option == 'string') data[option]()
     }
 
@@ -179,7 +239,9 @@
         appStoreLanguage: 'us', // Language code for App Store
         inAppStore: 'On the App Store', // Text of price for iOS
         inGooglePlay: 'In Google Play', // Text of price for Android
+        inAmazonAppStore: 'In the Amazon Appstore',
         inWindowsStore: 'In the Windows Store', //Text of price for Windows
+        GooglePlayParams: null, // Aditional parameters for the market
         icon: null, // The URL of the icon (defaults to <meta name="apple-touch-icon">)
         iconGloss: null, // Force gloss effect for iOS even for precomposed
         button: 'VIEW', // Text for the install button
@@ -189,9 +251,59 @@
         speedOut: 400, // Close animation speed of the banner
         daysHidden: 15, // Duration to hide the banner after being closed (0 = always show banner)
         daysReminder: 90, // Duration to hide the banner after "VIEW" is clicked *separate from when the close button is clicked* (0 = always show banner)
-        force: null // Choose 'ios', 'android' or 'windows'. Don't do a browser check, just always show this banner
+        force: null, // Choose 'ios', 'android' or 'windows'. Don't do a browser check, just always show this banner
+        hideOnInstall: true, // Hide the banner after "VIEW" is clicked.
+        layer: false, // Display as overlay layer or slide down the page
+        iOSUniversalApp: true, // If the iOS App is a universal app for both iPad and iPhone, display Smart Banner to iPad users, too.
+        appendToSelector: 'body' //Append the banner to a specific selector
+    }
+
+    $.smartbanner.Constructor = SmartBanner;
+
+
+    // ============================================================
+    // Bootstrap transition
+    // Copyright 2011-2014 Twitter, Inc.
+    // Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+
+    function transitionEnd() {
+        var el = document.createElement('smartbanner')
+
+        var transEndEventNames = {
+            WebkitTransition: 'webkitTransitionEnd',
+            MozTransition: 'transitionend',
+            OTransition: 'oTransitionEnd otransitionend',
+            transition: 'transitionend'
+        }
+
+        for (var name in transEndEventNames) {
+            if (el.style[name] !== undefined) {
+                return {end: transEndEventNames[name]}
+            }
+        }
+
+        return false // explicit for ie8 (  ._.)
+    }
+
+    if ($.support.transition !== undefined)
+        return  // Prevent conflict with Twitter Bootstrap
+
+    // http://blog.alexmaccaw.com/css-transitions
+    $.fn.emulateTransitionEnd = function(duration) {
+        var called = false, $el = this
+        $(this).one($.support.transition.end, function() {
+            called = true
+        })
+        var callback = function() {
+            if (!called) $($el).trigger($.support.transition.end)
+        }
+        setTimeout(callback, duration)
+        return this
     }
 
-    $.smartbanner.Constructor = SmartBanner
+    $(function() {
+        $.support.transition = transitionEnd()
+    })
+    // ============================================================
 
 }(window.jQuery);
diff --git a/libs/jquery/stylesheets/jquery.smartbanner.css b/libs/jquery/stylesheets/jquery.smartbanner.css
index 7ad1a69394..ae4dd31381 100644
--- a/libs/jquery/stylesheets/jquery.smartbanner.css
+++ b/libs/jquery/stylesheets/jquery.smartbanner.css
@@ -1,4 +1,5 @@
 #smartbanner { position:absolute; left:0; top:-82px; border-bottom:1px solid #e8e8e8; width:100%; height:78px; font-family:'Helvetica Neue',sans-serif; background:-webkit-linear-gradient(top, #f4f4f4 0%,#cdcdcd 100%); background-image: -ms-linear-gradient(top, #F4F4F4 0%, #CDCDCD 100%); background-image: -moz-linear-gradient(top, #F4F4F4 0%, #CDCDCD 100%); box-shadow:0 1px 2px rgba(0,0,0,0.5); z-index:9998; -webkit-font-smoothing:antialiased; overflow:hidden; -webkit-text-size-adjust:none; }
+#smartbanner, html.sb-animation {-webkit-transition: all .3s ease;}
 #smartbanner .sb-container { margin: 0 auto; }
 #smartbanner .sb-close { position:absolute; left:5px; top:5px; display:block; border:2px solid #fff; width:14px; height:14px; font-family:'ArialRoundedMTBold',Arial; font-size:15px; line-height:15px; text-align:center; color:#fff; background:#070707; text-decoration:none; text-shadow:none; border-radius:14px; box-shadow:0 2px 3px rgba(0,0,0,0.4); -webkit-font-smoothing:subpixel-antialiased; }
 #smartbanner .sb-close:active { font-size:13px; color:#aaa; }
@@ -14,7 +15,7 @@
 
 #smartbanner .sb-icon.gloss:after { content:''; position:absolute; left:0; top:-1px; border-top:1px solid rgba(255,255,255,0.8); width:100%; height:50%; background:-webkit-linear-gradient(top, rgba(255,255,255,0.7) 0%,rgba(255,255,255,0.2) 100%); border-radius:10px 10px 12px 12px; }
 
-#smartbanner.android { border-color:#212228; background: #3d3d3d; border-top: 5px solid #88B131; box-shadow: none; }
+#smartbanner.android { border-color:#212228; background: #3d3d3d url('dark_background_stripes.gif'); border-top: 5px solid #88B131; box-shadow: none; }
 #smartbanner.android .sb-close { border:0; width:17px; height:17px; line-height:17px; color:#b1b1b3; background:#1c1e21; text-shadow:0 1px 1px #000; box-shadow:0 1px 2px rgba(0,0,0,0.8) inset,0 1px 1px rgba(255,255,255,0.3); }
 #smartbanner.android .sb-close:active { color:#eee; }
 #smartbanner.android .sb-info { color:#ccc; text-shadow:0 1px 2px #000; }
diff --git a/plugins/Login/templates/login.twig b/plugins/Login/templates/login.twig
index 6bdc139e5b..830b8b0f85 100644
--- a/plugins/Login/templates/login.twig
+++ b/plugins/Login/templates/login.twig
@@ -28,7 +28,7 @@
         $(function () {
             $('#form_login').focus();
             $('input').placeholder();
-            $.smartbanner({title: "Piwik Mobile 2", author: "Piwik team", icon: "plugins/CoreHome/images/googleplay.png"});
+            $.smartbanner({title: "Piwik Mobile 2", author: "Piwik team", hideOnInstall: false, layer: true, icon: "plugins/CoreHome/images/googleplay.png"});
         });
 	</script>
 	</head>
-- 
GitLab