<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Context aware mashups, detecting if running on mobile devices or desktop in App Development</title>
    <link>https://community.qlik.com/t5/App-Development/Context-aware-mashups-detecting-if-running-on-mobile-devices-or/m-p/1268929#M26067</link>
    <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Summary:&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #0f0f0f; background: white;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #0f0f0f; background: white;"&gt;The article explains how to develop context aware mashups, meaning how it is possible for developers to let their mashups detect if they are running within a mobile device or desktop browser instances. Once the context is detected the application will seamlessly refresh the content and displays what is intended per context i.e. different content, resources and layouts will be used for each mode. Mobiles provide a limited real estate while desktops provide more resources, thus it is important to manage the content based on these factors. &lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Description:&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;&lt;BR /&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The default mashups generated in Qlik Sense Dev-Hub provides the minimum skeleton needed for a web application to be built with support for Qlik Sense content. Yet sometimes mashups end up being loaded in different environments and at times it is important to control what to show in what environment given some criteria, such as, are we running on a mobile device with a small screen or are we running on a desktop with a large display. From a user experience perspective, it is important to manage the content given that mobile device resources are not the same as of desktops. Thus we need to know what to show and not when the context changes.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;In addition to the above, this article attempts to shed some light for beginners on how to load different dependencies using require.js. We will see how the syntax looks like especially if the JavaScript files are not placed in the mashup root folder, some people may find it confusing how the path to their resources should look like.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The attached code and snippets touch base on the concept of being modular and how modules communicate with each other when working with mashups. It is meant to be straight forward and works in the same way as in any standard JavaScript application.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;Note that the attached code samples and snippets come with code comments in case something is not clear enough in this article.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The code has been intentionally developed in the form of MVC design pattern “as a snippet” and not as a concrete implementation, so you are most welcome to introduce your own thoughts here. For the sake of learning, code separation was done to serve the following: &lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;OL style="list-style-type: decimal;"&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Demo how to load dependencies using our RequireJS. The one found in the auto-generated JS file in the Dev-Hub.&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Ease of readability for developers how like to keep things tidy.&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Separation of code in a style close to principles found in Object Oriented.&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;This code is subject to more tuning thus &lt;STRONG&gt;&lt;EM&gt;this serves as a proof of concept only&lt;/EM&gt;&lt;/STRONG&gt;.&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;It may also set the foundations for building MVC driven implementations while using other flavors of JavaScript.&lt;/SPAN&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The images below are from our mashup rendered in desktop and mobile modes. As you see, when the context is that of a desktop, an image of a PC is shown while on a mobile, an image of a mobile device is show. In both cases the application auto-detects and &lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;displays the images matching the current context.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;&lt;BR /&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Kindly note that the mashup was developed in Qlik Sense 3.1.2 desktop variant.&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;&lt;BR /&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Desktop use case image&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;IMG __jive_id="157285" alt="OnDesktop.png" class="jive-image image-1" src="https://community.qlik.com/legacyfs/online/157285_OnDesktop.png" style="height: 338px; width: 620px;" /&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Mobile use case image&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;IMG __jive_id="157304" alt="OnMobile.png" class="jive-image image-2" src="https://community.qlik.com/legacyfs/online/157304_OnMobile.png" style="height: auto;" /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Icon in Chrome used to switch between mobile and desktop image&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;IMG __jive_id="157305" alt="ChromeTool.png" class="jive-image image-3" src="https://community.qlik.com/legacyfs/online/157305_ChromeTool.png" style="height: 243px; width: 620px;" /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Solution:&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;SPAN style="color: #000000;"&gt;Got to Qlik Sense Dev-Hub and create a new mashup, in this case I called it MobileVsDesktop.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;In the MobileVsDesktop.js and particularly in the require statement where "js/qlik" is used, in this part of the code we will add three dependencies. They are MobileDetector, ImageFactory and Main. Basically these are three JavaScript files. We could have loaded them in MobileVsDesktop.html by putting them in the &lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;&amp;lt;head&amp;gt;&lt;/SPAN&gt; section but I chose not to do so, simply to demo how dependencies can be loaded from within the auto-generated JS file in Dev-Hub. The code should look something like this:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;require(&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;["js/qlik",&lt;SPAN style="color: red;"&gt;"./js/model/MobileDetector.js","./js/view/ImageFactory.js","./js/controller/Main.js"&lt;/SPAN&gt;],&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;function ( qlik, &lt;SPAN style="color: #70ad47;"&gt;MobileDetector, ImageFactory, Main&lt;/SPAN&gt;) {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;…&lt;BR /&gt;&lt;SPAN style="color: #000000;"&gt; …&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;Our dependencies are highlight above in the red color, and as you see from the path, they are residing inside a subfolder called “js”, this folder is sitting in the root of the mashup folder.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The arguments in the function call highlighted in green are not necessary in this case, they are passed here to the anonymous callback function for the sake of demoing how you can pass on your dependencies into your application context. The obvious example here is the use of “qlik” object, later in the code you can use it for opening a qvf file for example and doing other calls specific to “qlik”object.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;Inside the “js” subfolder there are three subfolders, they are model, view and controller. In each folder there is a JavaScript file that does a specific task and communicate with the other JavaScript code to perform the remoaning task or tasks. In this case we want to detect the context, if mobile then load the corresponding content if not then load something else and then refresh the view. Hence our main files for this implementation are:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;UL style="list-style-type: disc;"&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;MobileDetector.js&lt;/EM&gt;&lt;/STRONG&gt;: Responsible for detecting if the application is running on a mobile device or not. &lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;ImageFactory.js&lt;/EM&gt;&lt;/STRONG&gt;: Creates images for a given context.&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;Main.js&lt;/EM&gt;&lt;/STRONG&gt;: Used for initializing couple objects such as the MobileDetector and ImageFactory, also to create the images.&lt;/SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The context detection task is done in &lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;MobileDetector.js&lt;/EM&gt;&lt;/STRONG&gt; and the code for that is:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;var MobileDetector = {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true if Android mobile, otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;Android: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; return navigator.userAgent.match(/Android/i);&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;},&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true if BlackBerry mobile, otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;BlackBerry: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;return navigator.userAgent.match(/BlackBerry/i);&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;},&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true if iOS mobile, otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;iOS: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; return navigator.userAgent.match(/iPhone|iPad|iPod/i);&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;},&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true if Opera mobile, otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;Opera: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; return navigator.userAgent.match(/Opera Mini/i);&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;},&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true if Windos mobile, otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; Windows: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;return navigator.userAgent.match(/IEMobile/i);&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;},&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; isMobile: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; return (this.Android() || this.BlackBerry() || this.iOS() || this.Opera() || this.Windows());&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; }&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;};&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;In this implementation there are no callback functions invoked when the context changes, it is a very linear approach. Meaning when the application is loaded it then reads the browser mode and decide what resources to grab, after that the view is refreshed. There is nothing special about the code detecting the browser mode we are dealing with. This snippet can be found in the open source space or JavaScript forums.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;Once the above steps are completed then &lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;Main.js&lt;/EM&gt;&lt;/STRONG&gt; in the end will do a JavaScript refresh call of the browser. If you look inside &lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;Main.js&lt;/EM&gt;&lt;/STRONG&gt; the sequence of calls is:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;UL style="list-style-type: disc;"&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Initializing the image factory:&lt;/SPAN&gt;&lt;BR /&gt; &lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;ImageFactory.init(MobileDetector.isMobile());&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Creates the image, will be based on the context, if mobile otherwise desktop / PC etc:&lt;/SPAN&gt;&lt;BR /&gt; &lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;ImageFactory.createImage(null); /* Passing null value as image source just to keep things simple for the time being!*/&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Refresh content when the window size has changed. If this part is removed then the user needs to press "F5" to see the final result:&lt;/SPAN&gt;&lt;BR /&gt; &lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;$(window).resize(function(){window.location.reload();});&lt;/SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The full project and its resources are attached to this article, kindly feel free to amend the content as you see appropriate. Note that the attached code samples and snippets come with code comments in case something is not clear in this article.&lt;/SPAN&gt;&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
    <pubDate>Thu, 23 Mar 2017 14:57:38 GMT</pubDate>
    <dc:creator />
    <dc:date>2017-03-23T14:57:38Z</dc:date>
    <item>
      <title>Context aware mashups, detecting if running on mobile devices or desktop</title>
      <link>https://community.qlik.com/t5/App-Development/Context-aware-mashups-detecting-if-running-on-mobile-devices-or/m-p/1268929#M26067</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Summary:&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #0f0f0f; background: white;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #0f0f0f; background: white;"&gt;The article explains how to develop context aware mashups, meaning how it is possible for developers to let their mashups detect if they are running within a mobile device or desktop browser instances. Once the context is detected the application will seamlessly refresh the content and displays what is intended per context i.e. different content, resources and layouts will be used for each mode. Mobiles provide a limited real estate while desktops provide more resources, thus it is important to manage the content based on these factors. &lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Description:&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;&lt;BR /&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The default mashups generated in Qlik Sense Dev-Hub provides the minimum skeleton needed for a web application to be built with support for Qlik Sense content. Yet sometimes mashups end up being loaded in different environments and at times it is important to control what to show in what environment given some criteria, such as, are we running on a mobile device with a small screen or are we running on a desktop with a large display. From a user experience perspective, it is important to manage the content given that mobile device resources are not the same as of desktops. Thus we need to know what to show and not when the context changes.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;In addition to the above, this article attempts to shed some light for beginners on how to load different dependencies using require.js. We will see how the syntax looks like especially if the JavaScript files are not placed in the mashup root folder, some people may find it confusing how the path to their resources should look like.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The attached code and snippets touch base on the concept of being modular and how modules communicate with each other when working with mashups. It is meant to be straight forward and works in the same way as in any standard JavaScript application.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;Note that the attached code samples and snippets come with code comments in case something is not clear enough in this article.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The code has been intentionally developed in the form of MVC design pattern “as a snippet” and not as a concrete implementation, so you are most welcome to introduce your own thoughts here. For the sake of learning, code separation was done to serve the following: &lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;OL style="list-style-type: decimal;"&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Demo how to load dependencies using our RequireJS. The one found in the auto-generated JS file in the Dev-Hub.&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Ease of readability for developers how like to keep things tidy.&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Separation of code in a style close to principles found in Object Oriented.&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;This code is subject to more tuning thus &lt;STRONG&gt;&lt;EM&gt;this serves as a proof of concept only&lt;/EM&gt;&lt;/STRONG&gt;.&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;It may also set the foundations for building MVC driven implementations while using other flavors of JavaScript.&lt;/SPAN&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The images below are from our mashup rendered in desktop and mobile modes. As you see, when the context is that of a desktop, an image of a PC is shown while on a mobile, an image of a mobile device is show. In both cases the application auto-detects and &lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;displays the images matching the current context.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;&lt;BR /&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Kindly note that the mashup was developed in Qlik Sense 3.1.2 desktop variant.&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;&lt;BR /&gt;&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Desktop use case image&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;IMG __jive_id="157285" alt="OnDesktop.png" class="jive-image image-1" src="https://community.qlik.com/legacyfs/online/157285_OnDesktop.png" style="height: 338px; width: 620px;" /&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Mobile use case image&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;IMG __jive_id="157304" alt="OnMobile.png" class="jive-image image-2" src="https://community.qlik.com/legacyfs/online/157304_OnMobile.png" style="height: auto;" /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Icon in Chrome used to switch between mobile and desktop image&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;IMG __jive_id="157305" alt="ChromeTool.png" class="jive-image image-3" src="https://community.qlik.com/legacyfs/online/157305_ChromeTool.png" style="height: 243px; width: 620px;" /&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG&gt;Solution:&lt;/STRONG&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;SPAN style="color: #000000;"&gt;Got to Qlik Sense Dev-Hub and create a new mashup, in this case I called it MobileVsDesktop.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;In the MobileVsDesktop.js and particularly in the require statement where "js/qlik" is used, in this part of the code we will add three dependencies. They are MobileDetector, ImageFactory and Main. Basically these are three JavaScript files. We could have loaded them in MobileVsDesktop.html by putting them in the &lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;&amp;lt;head&amp;gt;&lt;/SPAN&gt; section but I chose not to do so, simply to demo how dependencies can be loaded from within the auto-generated JS file in Dev-Hub. The code should look something like this:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;require(&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;["js/qlik",&lt;SPAN style="color: red;"&gt;"./js/model/MobileDetector.js","./js/view/ImageFactory.js","./js/controller/Main.js"&lt;/SPAN&gt;],&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;function ( qlik, &lt;SPAN style="color: #70ad47;"&gt;MobileDetector, ImageFactory, Main&lt;/SPAN&gt;) {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;…&lt;BR /&gt;&lt;SPAN style="color: #000000;"&gt; …&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;Our dependencies are highlight above in the red color, and as you see from the path, they are residing inside a subfolder called “js”, this folder is sitting in the root of the mashup folder.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The arguments in the function call highlighted in green are not necessary in this case, they are passed here to the anonymous callback function for the sake of demoing how you can pass on your dependencies into your application context. The obvious example here is the use of “qlik” object, later in the code you can use it for opening a qvf file for example and doing other calls specific to “qlik”object.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;Inside the “js” subfolder there are three subfolders, they are model, view and controller. In each folder there is a JavaScript file that does a specific task and communicate with the other JavaScript code to perform the remoaning task or tasks. In this case we want to detect the context, if mobile then load the corresponding content if not then load something else and then refresh the view. Hence our main files for this implementation are:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;UL style="list-style-type: disc;"&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;MobileDetector.js&lt;/EM&gt;&lt;/STRONG&gt;: Responsible for detecting if the application is running on a mobile device or not. &lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;ImageFactory.js&lt;/EM&gt;&lt;/STRONG&gt;: Creates images for a given context.&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;&lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;Main.js&lt;/EM&gt;&lt;/STRONG&gt;: Used for initializing couple objects such as the MobileDetector and ImageFactory, also to create the images.&lt;/SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The context detection task is done in &lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;MobileDetector.js&lt;/EM&gt;&lt;/STRONG&gt; and the code for that is:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;var MobileDetector = {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true if Android mobile, otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;Android: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; return navigator.userAgent.match(/Android/i);&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;},&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true if BlackBerry mobile, otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;BlackBerry: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;return navigator.userAgent.match(/BlackBerry/i);&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;},&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true if iOS mobile, otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;iOS: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; return navigator.userAgent.match(/iPhone|iPad|iPod/i);&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;},&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true if Opera mobile, otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;Opera: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; return navigator.userAgent.match(/Opera Mini/i);&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;},&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true if Windos mobile, otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; Windows: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;return navigator.userAgent.match(/IEMobile/i);&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;},&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;// Returns true otherwise null&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; isMobile: function() {&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; return (this.Android() || this.BlackBerry() || this.iOS() || this.Opera() || this.Windows());&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt; }&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;};&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;In this implementation there are no callback functions invoked when the context changes, it is a very linear approach. Meaning when the application is loaded it then reads the browser mode and decide what resources to grab, after that the view is refreshed. There is nothing special about the code detecting the browser mode we are dealing with. This snippet can be found in the open source space or JavaScript forums.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;Once the above steps are completed then &lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;Main.js&lt;/EM&gt;&lt;/STRONG&gt; in the end will do a JavaScript refresh call of the browser. If you look inside &lt;STRONG style="font-family: 'Courier New';"&gt;&lt;EM&gt;Main.js&lt;/EM&gt;&lt;/STRONG&gt; the sequence of calls is:&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;&lt;BR /&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;UL style="list-style-type: disc;"&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Initializing the image factory:&lt;/SPAN&gt;&lt;BR /&gt; &lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;ImageFactory.init(MobileDetector.isMobile());&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Creates the image, will be based on the context, if mobile otherwise desktop / PC etc:&lt;/SPAN&gt;&lt;BR /&gt; &lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;ImageFactory.createImage(null); /* Passing null value as image source just to keep things simple for the time being!*/&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;&lt;SPAN style="color: #000000;"&gt;Refresh content when the window size has changed. If this part is removed then the user needs to press "F5" to see the final result:&lt;/SPAN&gt;&lt;BR /&gt; &lt;SPAN style="font-size: 9.0pt; font-family: 'Courier New';"&gt;$(window).resize(function(){window.location.reload();});&lt;/SPAN&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN style="color: #000000;"&gt;The full project and its resources are attached to this article, kindly feel free to amend the content as you see appropriate. Note that the attached code samples and snippets come with code comments in case something is not clear in this article.&lt;/SPAN&gt;&lt;/P&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Thu, 23 Mar 2017 14:57:38 GMT</pubDate>
      <guid>https://community.qlik.com/t5/App-Development/Context-aware-mashups-detecting-if-running-on-mobile-devices-or/m-p/1268929#M26067</guid>
      <dc:creator />
      <dc:date>2017-03-23T14:57:38Z</dc:date>
    </item>
  </channel>
</rss>

