locked
About dynamically change images in metro style apps using html5

    Question

  • Hi,

    I m developing metro style app using HTML5 and js. I want to add few images which should change dynamivally.

    Can anyone give me idea how to start. 

    Friday, December 28, 2012 7:43 AM

Answers

  • Will the images be part of a ListView or some kind of template? Or will they be just static images on the page? How are you planning to achieve the dynamism?

    In case they are static (positioned IMG tags) images, you can assign them an "Id" attribute on your HTML and through Javascript code change de "src" property to a new image, for example, if your IMG tag has an Id of "img1" and src "/images/image1.png" you can do something like:

    document.getElementById("img1").src = "/images/image2.png";

    You can fire that code on any kind of event that you need, a mouse click, some keyboard event or even a timed event using setTimeout.

    If you clarify a bit what you are trying to accomplish maybe I can provide a more complete answer.


    • Marked as answer by WinNRock Wednesday, January 2, 2013 10:04 AM
    Friday, December 28, 2012 12:27 PM
  • Hi,

    You could use indexeddb to do that. And follow is an example how to add and delete items in listview.

    default.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Task List</title>
     
        <!-- WinJS references -->
        <link href="//Microsoft.WinJS.1.0/css/ui-light.css" rel="stylesheet" />
        <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
        <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
     
        <!-- TaskList references -->
        <link href="/css/default.css" rel="stylesheet">
        <script src="/listview_indexeddb/default.js"></script>
        <script type="text/javascript" src="/listview_indexeddb/tasks.js"></script>
     
        <style type="text/css">
            body {
                font-size: x-large;
            }
     
            form {
                display:  inline;
            }
     
            #appContainer {
                margin:  20px;
                width:  600px;
            }
     
            .win-container {
                padding:  10px;
            }
     
        </style>
     
    </head>
    <body>
        <div>
     
            <!-- Templates -->
            <div id="taskTemplate"
                data-win-control="WinJS.Binding.Template">
                <div>
                    <span data-win-bind="innerText:title"></span>
                </div>
            </div>
     
            <h1>Super Task List</h1>
     
            <div id="appContainer">
                <form id="addTaskForm">
                    <input id="newTaskTitle" title="New Task" required  />
                    <button>Add</button>
                </form>
                <button id="btnDeleteTasks">Delete</button>
     
                <div id="tasksListView"
                    data-win-control="WinJS.UI.ListView"
                    data-win-options="{
                        itemDataSource: TaskList.tasks.dataSource,
                        itemTemplate: select('#taskTemplate'),
                        tapBehavior: 'toggleSelect',
                        selectionMode: 'multi',
                        layout: { type: WinJS.UI.ListLayout }
                    }">
                </div>
            </div>
     
        </div>
    </body>
    </html>

    default.js

    (function () {
        "use strict";
    
        var app = WinJS.Application;
    
        app.onactivated = function (eventObject) {
            if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
    
                WinJS.UI.processAll().then(function () {
    
                    // Get reference to Tasks ListView
                    var tasksListView = document.getElementById("tasksListView");
    
                    // Handle Add Task
                    document.getElementById("addTaskForm").addEventListener("submit", function (evt) {
                        evt.preventDefault();
                        var newTaskTitle = document.getElementById("newTaskTitle");
                        TaskList.addTask({ title: newTaskTitle.value });
                        newTaskTitle.value = "";
                    });
    
                    // Handle Delete Tasks
                    document.getElementById("btnDeleteTasks").addEventListener("click", function (evt) {
                        tasksListView.winControl.selection.getItems().then(function (items) {
                            items.forEach(function (item) {
                                TaskList.deleteTask(item);
                            });
                        });
    
                    });
    
                });
            }
        };
    
        app.start();
    })();

    tasks.js

    (function () {
        "use strict";
    
        // Create the data source
        var tasks = new WinJS.Binding.List();
    
        // Open the database
        var db;
        var req = window.msIndexedDB.open("TasksDB", 1);
        req.onerror = function () {
            console.log("Could not open database");
        };
        req.onupgradeneeded = function (evt) {
            var newDB = evt.target.result;
            newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement: true });
        };
    
        // Load the data source with data from the database
        req.onsuccess = function () {
            db = req.result;
            var tran = db.transaction("tasks");
            tran.objectStore("tasks").openCursor().onsuccess = function (event) {
                var cursor = event.target.result;
                if (cursor) {
                    tasks.dataSource.insertAtEnd(null, cursor.value);
                    cursor.continue();
                };
            };
    
        };
    
        // Add a new task
        function addTask(taskToAdd) {
            var transaction = db.transaction("tasks", "readwrite");
            var addRequest = transaction.objectStore("tasks").add(taskToAdd);
            addRequest.onsuccess = function (evt) {
                taskToAdd.id = evt.target.result;
                tasks.dataSource.insertAtEnd(null, taskToAdd);
            }
        }
    
        // Delete an existing task
        function deleteTask(listViewItem) {
            // Database key != ListView key
            var dbKey = listViewItem.data.id;
            var listViewKey = listViewItem.key;
    
            // Remove item from db and, if success, remove item from ListView
            var transaction = db.transaction("tasks", "readwrite");
            var deleteRequest = transaction.objectStore("tasks").delete(dbKey);
            deleteRequest.onsuccess = function () {
                tasks.dataSource.remove(listViewKey);
            }
        }
    
        // Expose the data source and functions
        WinJS.Namespace.define("TaskList", {
            tasks: tasks,
            addTask: addTask,
            deleteTask: deleteTask
        });
    
    })();


    Roy
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Song Tian Thursday, January 3, 2013 1:29 AM
    Monday, December 31, 2012 2:11 AM

All replies

  • Will the images be part of a ListView or some kind of template? Or will they be just static images on the page? How are you planning to achieve the dynamism?

    In case they are static (positioned IMG tags) images, you can assign them an "Id" attribute on your HTML and through Javascript code change de "src" property to a new image, for example, if your IMG tag has an Id of "img1" and src "/images/image1.png" you can do something like:

    document.getElementById("img1").src = "/images/image2.png";

    You can fire that code on any kind of event that you need, a mouse click, some keyboard event or even a timed event using setTimeout.

    If you clarify a bit what you are trying to accomplish maybe I can provide a more complete answer.


    • Marked as answer by WinNRock Wednesday, January 2, 2013 10:04 AM
    Friday, December 28, 2012 12:27 PM
  • Hi,

    You could use indexeddb to do that. And follow is an example how to add and delete items in listview.

    default.html

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>Task List</title>
     
        <!-- WinJS references -->
        <link href="//Microsoft.WinJS.1.0/css/ui-light.css" rel="stylesheet" />
        <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
        <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>
     
        <!-- TaskList references -->
        <link href="/css/default.css" rel="stylesheet">
        <script src="/listview_indexeddb/default.js"></script>
        <script type="text/javascript" src="/listview_indexeddb/tasks.js"></script>
     
        <style type="text/css">
            body {
                font-size: x-large;
            }
     
            form {
                display:  inline;
            }
     
            #appContainer {
                margin:  20px;
                width:  600px;
            }
     
            .win-container {
                padding:  10px;
            }
     
        </style>
     
    </head>
    <body>
        <div>
     
            <!-- Templates -->
            <div id="taskTemplate"
                data-win-control="WinJS.Binding.Template">
                <div>
                    <span data-win-bind="innerText:title"></span>
                </div>
            </div>
     
            <h1>Super Task List</h1>
     
            <div id="appContainer">
                <form id="addTaskForm">
                    <input id="newTaskTitle" title="New Task" required  />
                    <button>Add</button>
                </form>
                <button id="btnDeleteTasks">Delete</button>
     
                <div id="tasksListView"
                    data-win-control="WinJS.UI.ListView"
                    data-win-options="{
                        itemDataSource: TaskList.tasks.dataSource,
                        itemTemplate: select('#taskTemplate'),
                        tapBehavior: 'toggleSelect',
                        selectionMode: 'multi',
                        layout: { type: WinJS.UI.ListLayout }
                    }">
                </div>
            </div>
     
        </div>
    </body>
    </html>

    default.js

    (function () {
        "use strict";
    
        var app = WinJS.Application;
    
        app.onactivated = function (eventObject) {
            if (eventObject.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
    
                WinJS.UI.processAll().then(function () {
    
                    // Get reference to Tasks ListView
                    var tasksListView = document.getElementById("tasksListView");
    
                    // Handle Add Task
                    document.getElementById("addTaskForm").addEventListener("submit", function (evt) {
                        evt.preventDefault();
                        var newTaskTitle = document.getElementById("newTaskTitle");
                        TaskList.addTask({ title: newTaskTitle.value });
                        newTaskTitle.value = "";
                    });
    
                    // Handle Delete Tasks
                    document.getElementById("btnDeleteTasks").addEventListener("click", function (evt) {
                        tasksListView.winControl.selection.getItems().then(function (items) {
                            items.forEach(function (item) {
                                TaskList.deleteTask(item);
                            });
                        });
    
                    });
    
                });
            }
        };
    
        app.start();
    })();

    tasks.js

    (function () {
        "use strict";
    
        // Create the data source
        var tasks = new WinJS.Binding.List();
    
        // Open the database
        var db;
        var req = window.msIndexedDB.open("TasksDB", 1);
        req.onerror = function () {
            console.log("Could not open database");
        };
        req.onupgradeneeded = function (evt) {
            var newDB = evt.target.result;
            newDB.createObjectStore("tasks", { keyPath: "id", autoIncrement: true });
        };
    
        // Load the data source with data from the database
        req.onsuccess = function () {
            db = req.result;
            var tran = db.transaction("tasks");
            tran.objectStore("tasks").openCursor().onsuccess = function (event) {
                var cursor = event.target.result;
                if (cursor) {
                    tasks.dataSource.insertAtEnd(null, cursor.value);
                    cursor.continue();
                };
            };
    
        };
    
        // Add a new task
        function addTask(taskToAdd) {
            var transaction = db.transaction("tasks", "readwrite");
            var addRequest = transaction.objectStore("tasks").add(taskToAdd);
            addRequest.onsuccess = function (evt) {
                taskToAdd.id = evt.target.result;
                tasks.dataSource.insertAtEnd(null, taskToAdd);
            }
        }
    
        // Delete an existing task
        function deleteTask(listViewItem) {
            // Database key != ListView key
            var dbKey = listViewItem.data.id;
            var listViewKey = listViewItem.key;
    
            // Remove item from db and, if success, remove item from ListView
            var transaction = db.transaction("tasks", "readwrite");
            var deleteRequest = transaction.objectStore("tasks").delete(dbKey);
            deleteRequest.onsuccess = function () {
                tasks.dataSource.remove(listViewKey);
            }
        }
    
        // Expose the data source and functions
        WinJS.Namespace.define("TaskList", {
            tasks: tasks,
            addTask: addTask,
            deleteTask: deleteTask
        });
    
    })();


    Roy
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Song Tian Thursday, January 3, 2013 1:29 AM
    Monday, December 31, 2012 2:11 AM
  • Hi,

    Thank you for your reply. Here i'm creating tile using code as shown below. 

       var dataArray = [
        { title: "Basic banana", text: "$4.5", picture: "URL('/images/images (1).jpg')", type: "smallListIconTextItem" },
        { title: "Banana blast", text: "$4.5", picture: "URL('#')", type: "mediumListIconTextItem" },
        { title: "Brilliant banana", text: "$4.5", picture: "URL('#')", type: "largeListIconTextItem" },
        { title: "Orange surprise", text: "$4.5", picture: "URL('#')", type: "mediumListIconTextItem" },
        { title: "Original orange", text: "$4.5", picture: "URL('#')", type: "smallListIconTextItem" },
        { title: "Vanilla", text: "$4.5", picture:"URL('#')", type: "smallListIconTextItem" },
        { title: "Very vanilla", text: "$4.5", picture:"URL('#')", type: "mediumListIconTextItem" },
        { title: "Marvelous mint", text: "$4.5", picture: "URL('#')", type: "mediumListIconTextItem" },
        { title: "Succulent strawberry", text: "$4.5", picture: "URL('#')", type: "smallListIconTextItem" }
        ]; 

     var groupInfo = WinJS.Utilities.markSupportedForProcessing(function groupInfo() {
            return {
                enableCellSpanning: true,
                cellWidth:10,
                cellHeight: 10
            };
        });


        var dataList = new WinJS.Binding.List(dataArray);
        var publicMembers =
                {
                    groupInfo: groupInfo,
                    itemList: dataList
                };

    In html file

                     

    <div id="mediumListIconTextTemplate" data-win-control="WinJS.Binding.Template" >

            <div id="someTile" data-win-bind="style.backgroundImage: picture" >   
                    <h3 data-win-bind="innerText: title"></h3>

          </div>

    <div id="basicListView" 
          data-win-control="WinJS.UI.ListView"
          data-win-options="{ itemDataSource :a.itemList.dataSource ,
          itemTemplate : select('#mediumListIconTextTemplate'),
          selectionMode: 'multi',                         
          onkeyboardnavigating : handler,

          tapBehavior: 'toggleSelect',

        layout: {             
        type: WinJS.UI.GridLayout 
           }
         }">

    </div>

    Means here i m creating nine tiles with different size.  For the first tile say  "URL('/images/images (1).jpg')" and  title: "Basic banana" i want to change the images for every 3 or 4 seconds. where and how to add images. 


    • Edited by WinNRock Wednesday, January 2, 2013 10:41 AM
    Wednesday, January 2, 2013 10:04 AM
  • In WinJS bindings, if you alter the data Array, it should automatically modify the result, hence, if you modify the object's properties in the array (in your example, the object in position 0, property "picture"), it should change the Grid Layout image.

    You could store the data array globally (on a DB as pointed out by Song Tian) or within the scope of the page with a variable, so you can access it with a setTimeout for example and change the array's object's properties.

    Wednesday, January 2, 2013 12:37 PM
  • Ya but how to do programmatically?

    As you said i m using the code like this. Statically its working.

                   setTimeout(function () { document.getElementById("img1").src = "/images/images (1).jpg"; }, 3000);
                    setTimeout(function () { document.getElementById("img1").src = " /images/images (2).jpg"; }, 6000);
                    setTimeout(function () { document.getElementById("img1").src = "/images/images (3).jpg"; }, 9000);
                    setTimeout(function () { document.getElementById("img1").src = "/images/images (2).jpg"; }, 12000);
                    setTimeout(function () { document.getElementById("img1").src = "/images/images (1).jpg"; }, 15000);

    But how to update for only one tile

        { title: "Basic banana", text: "$4.5", picture: "URL('/images/images (1).jpg')", type: "smallListIconTextItem" }

    Can you tell programmatically please.

    Thursday, January 3, 2013 8:41 AM
  • I'm unable to try it because I don't have my W8 computer at hand, but you should be able to do something like:
    var dataList = new WinJS.Binding.List(dataArray);
    setTimeout(function(){
    //Modify the first item, replace 0 with the index you want to modify
    dataList.getAt(0).picture = "/images/newImage.jpg";
    },3000);
    setTimeout(function(){
    //Modify the first item, replace 0 with the index you want to modify
    dataList.getAt(0).picture = "/images/newImage2.jpg";
    },6000);
    
    

    Thursday, January 3, 2013 2:36 PM
  • Hi,

    One more question.

    I m using settimeout for the tile updates like this.

     setTimeout(function () { document.getElementById("croppingDiv").style.backgroundImage = "URL('/images/images (13).jpg')" }, 2000);
     setTimeout(function () { document.getElementById("croppingDiv").style.backgroundImage = "URL('/images/images (3).jpg')" }, 4000);
     setTimeout(function () { document.getElementById("croppingDiv").style.backgroundImage = "URL('/images/images (13).jpg')" }, 6000);
    setTimeout(function () { document.getElementById("croppingDiv").style.backgroundImage = "URL('/images/images (3).jpg')" }, 8000);    

    But if i click on the button to navigate to next page before 8 second then its generating error. Hot can i disabled this settimeout when the navigation button is pressed. I want help programmatically.

    Thursday, January 10, 2013 8:00 AM
  • When you call setTimeout it returns a pointer to the task, if you want to cancel that given task you can use clearTimeout.

    var firstTO = setTimeout(function () { document.getElementById("croppingDiv").style.backgroundImage = "URL('/images/images (13).jpg')" }, 2000);
    
    //call this when you want to cancel de Timeout, remember that you need the reference to the Timeout return value
    clearTimeout(firstTO);

    Thursday, January 10, 2013 2:23 PM