-

- -

Wednesday, February 25, 2015

JQUERY MOBILE JSON LOCAL STORAGE 2

jQuery Mobile JSON Local Storage 2

1) Create LocalStorage Object

1.1) Find the code below.
If you uncomment the codes highlighted in green colour, you will get an error during emulation..
To fix this error, we have to define LocalStorageDB.
1.2) Create another JavaScript file local-storage.js
Enter the following codes
var LocalStorageDB = function(successCallback, errorCallback) {
}
1.3) Add the reference to the HEAD section of index.html
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>jQuery Mobile To Do</title>
    <link rel="stylesheet"  href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css">
    <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
<script src="./js/local-storage.js"></script>
<script src="./js/app.js"></script>
</head>
Info:
“<script src="./js/local-storage.js"></script>” must be entered before “<script src="./js/app.js"></script>” so that LocalStorageDB would be recognised by the codes in app.js

2) Insert Call Delay error capture code

Call Delay error capture sets the time-out limit during which operation must be completed or else terminated.
var LocalStorageDB = function(successCallback, errorCallback) {
        // Used to simulate async calls. This is done to provide a consistent interface with storage methods like WebSQL and serverside ajax calls
    var callDelay = function(callback, data) {
        if (callback) {
            setTimeout(function() {
                callback(data);
            }, 100);
        }
    }
/* other codes will be placed here */
    callDelay(successCallback);
}

3) Insert tasks codes to app.js and uncomment call to tasks

(add these codes on top of the function initialize in app.js file)
findAll: function() {...} ,
findById: function () {...} ,
markCompleted: function(id) {...} ,
markOutstanding: function(id) {...} ,
insert: function(json) {...} ,
update: function(json) {...} ,
delete: function(json) {...} ,
Don’t forget to put a comma between the function definitions
    findAll: function() {
        console.log('DEBUG - 2. findAll() triggered');
        this.store.findAll(function(todos) {
            var l = todos.length;
            var td;
            // Create new arrays so we can order them with outstanding first
            outstanding = [];
            completed = [];
            allTodos = [];
            // Loop through todos, build up lis and push to arrays
            for (var i=0; i<l; i++) {
                td = todos[i];
                // If not completed
                if (td.status == 0) {
                    outstanding.push('<li data-row-id="' + td.id + '" class="outstanding"><a href="#view" data-transition="slide" class="view" data-view-id="' + td.id +'"><h2>' + td.title+ '</h2><p>' + td.description + '</p></a><a href="#" data-icon="check" data-iconpos="notext" class="mark-completed" data-mark-id="' + td.id +'">Mark as completed</a></li>');
                }
                // If is completed
                else {
                    completed.push('<li data-row-id="' + td.id + '" class="completed"><a href="#view" data-transition="slide" class="view" data-view-id="' + td.id +'"><h2>' + td.title+ '</h2><p>' + td.description + '</p></a><a href="#" data-icon="delete" data-iconpos="notext" class="mark-outstanding" data-mark-id="' + td.id +'">Mark as outstanding</a></li>');
                }
            }
            // Join both arrays
            allTodos = outstanding.concat(completed);
            // Remove any previously appended
            $('.todo-listview li').remove();
            // Append built up arrays to ULs here.
            $('.todo-listview').append(allTodos);            
            // Refresh JQM listview
            $('.todo-listview').listview('refresh');
        });
    },
    findById: function(id) {
       
        this.store.findById(id, function(result) {
           
            $('#title').val(result.title);
            $('#title').attr('data-id', id);
            $('#description').val(result.description);
            $('#id').val(id);
       
        });
    },
    markCompleted: function(id) {
        // Passing json as any store will be able to handle it (even if we change to localStorage etc)
        this.store.markCompleted(id, function(result) {
            // DB updates successful
            if(result) {
                console.log("DEBUG - Success, db updated and marked as completed");
                // Find original row and grab details
                var originalRow =  $('#home *[data-row-id="'+id+'"]'),
                    title = originalRow.find("h2").text(),
                    desc = originalRow.find("p").text();
                // Remove from pending row
                originalRow.remove();
                // Re-build the li rather than clone as jqm generates a lot of fluff
                var newRow = '<li data-row-id="' + id + '" class="completed"><a href="#view" data-transition="slide" class="view" data-view-id="' + id +'"><h2>' + title + '</h2><p>' + desc + '</p></a><a href="#" data-icon="delete" data-iconpos="notext" class="mark-outstanding" data-mark-id="' + id +'">Mark as outstanding</a></li>';
                // Add to completed
                $('.todo-listview').append(newRow);
                // Refresh dom
                $('.todo-listview').listview('refresh');
                // Kept for debugging use
                //console.log("id length = " + $('[data-row-id='+id+']').length);
            } else {
                alert("Error - db did not update and NOT marked as completed");
            }
        });
    },
    markOutstanding: function(id) {
        // Passing json as any store will be able to handle it (even if we change to localStorage, indexedDB etc)
        this.store.markOutstanding(id, function(result) {
            // DB updates successful
            if(result) {
                console.log("DEBUG - Success, db updated and marked as outstanding");
                // Find original row and grab details
                var originalRow =  $('*[data-row-id="'+id+'"]'),
                    title = originalRow.find("h2").text(),
                    desc = originalRow.find("p").text();
                // Remove from pending row
                originalRow.remove();
                // Re-build the li rather than clone as jqm generates a lot of fluff
                var newRow = '<li data-row-id="' + id + '" class="outstanding"><a href="#view" data-transition="slide" class="view" data-view-id="' + id +'"><h2>' + title + '</h2><p>' + desc + '</p></a><a href="#" data-icon="check" data-iconpos="notext" class="mark-completed" data-mark-id="' + id +'">Mark as completed</a></li>';
                // Add to completed
                $('.todo-listview').prepend(newRow);
                // Refresh dom
                $('.todo-listview').listview('refresh');
                // Kept for debugging use
                //console.log("id length = " + $('[data-row-id='+id+']').length);
            } else {
                alert("Error - db did not update and NOT marked as outstanding");
            }
        });
    },
    insert: function(json) {
        // Passing json as any store will be able to handle it (even if we change to localStorage etc)
        this.store.insert(json, function(result) {
            // On successful db insert
            if(result) {
                console.log("DEBUG - Success,  add returned true");
                // Redirect back to #home page, add a transition andchange the hash
                $.mobile.changePage( $("#home"), {
                    transition: "slide",
                    reverse: true,
                    changeHash: true,
                });
            } else {
                alert("Error on insert!");
            }
        });
    },
    update: function(json) {
        // Passing json as any store will be able to handle it (even if we change to localStorage etc)
        this.store.update(json, function(result) {
            // On succuessful db update
            if(result) {
                console.log("DEBUG - Success, updated returned true");
            } else {
                alert("Error on update!");
            }
        });
    },
    delete: function(json) {
        // Passing json as any store will be able to handle it (even if we change to localStorage etc)
        this.store.delete(json, function(result) {
            // On successful db delete
            if(result) {
                console.log("DEBUG - Success, delete returned true");
                // Redirect back to #home page
                $.mobile.changePage( $("#home"), {
                    transition: "slide",
                    reverse: true,
                    changeHash: true
                });
            } else {
                alert("Error on delete!");
            }
        });
    },

4) Emulate

You will get error because your store object has yet to contain the required methods

5) Edit Local-Storage.js

5.1) Find the comment codes “/* other codes will be placed here */
5.2) Replace with the following codes
The green highlighted codes show the method binding for the store object
this.findAll
this.findById
this.markCompleted
this.markOutstanding
this.insert
this.update
this.delete
    // Allows us to sort an array of object - Use array.sort(sortByProperty('firstName'));
    var sortByProperty = function(property) {
        'use strict';
        return function (a, b) {
            var sortStatus = 0;
            if (a[property] < b[property]) {
                sortStatus = -1;
            } else if (a[property] > b[property]) {
                sortStatus = 1;
            }
     
            return sortStatus;
        };
    }

        // Sample Data (An array of objects)
    var todos = [
        {"id": 1, "title": "Go to the shop", "description": "Get milk and bread", "status": 0},
        {"id": 2, "title": "Post office", "description": "Collect mail", "status": 0},
        {"id": 3, "title": "Email Dad", "description": "About birthday", "status": 0},
        {"id": 4, "title": "Haircut", "description": "Well overdue", "status": 1}
    ];
    // Add the sample data to localStorage
    window.localStorage.setItem("todos", JSON.stringify(todos));
    this.findAll = function(callback) {
            // Parse a string as json
            var todos = JSON.parse(window.localStorage.getItem("todos"));
        callDelay(callback, todos);
    }
    this.findById = function(id, callback) {
        var todos = JSON.parse(window.localStorage.getItem("todos")),
                todo = null,
                len = todos.length,
            i = 0;
       
        for (; i < len; i++) {
            if (todos[i].id === id) {
                todo = todos[i];
                break;
            }
        }
        callDelay(callback, todo);
    }
    this.markCompleted = function(id, callback) {
        // Get all todos
        var todos = JSON.parse(window.localStorage.getItem("todos")),
            todo = null,
            len = todos.length,
            i = 0;
       
        // Loop through them and update the value
        $.each(todos, function(i, v) {
            if ( v.id === id ) {
                v.status = 1;
                return false;
            }
        });
        // Save the JSON back to localStorage
        if (window.localStorage.setItem("todos", JSON.stringify(todos))) {
            callDelay(callback, "true");
        } else {
            callDelay(callback, "false");
        }
    }
    this.markOutstanding = function(id, callback) {
        // Get all todos
        var todos = JSON.parse(window.localStorage.getItem("todos")),
            todo = null,
            len = todos.length,
            i = 0;
       
        // Loop through them and update the value
        $.each(todos, function(i, v) {
            if ( v.id === id ) {
                v.status = 0;
                return false;
            }
        });
        // Save the JSON back to localStorage
        if (window.localStorage.setItem("todos", JSON.stringify(todos))) {
            callDelay(callback, "true");
        } else {
            callDelay(callback, "false");
        }
    }
    this.insert = function(json, callback) {
        // Converts a JavaScript Object Notation (JSON) string into an object.
        var passedJson = JSON.parse(json),
            status = 0;
       
        // Get all todos
        var todos = JSON.parse(window.localStorage.getItem("todos")),
            todo = null,
            len = todos.length,
            i = 0;
       
        // Sort the json by ID (default is ASC)
        todos.sort(sortByProperty('id'));
        // Generate a new ID, pop the last obj in the array and grab the ID
        var lastTodo = todos.pop(),
            newID = lastTodo.id + 1;
        // Create the new Todo
        var newTodo = {"id": newID, "title": passedJson.title, "description": passedJson.description, "status": 0}
        // Add it to the existing todos        
        todos.push(lastTodo); // Add the popped one back in
        todos.push(newTodo);
        // Save the JSON back to localStorage
        if (window.localStorage.setItem("todos", JSON.stringify(todos))) {
            callDelay(callback, "true");
        } else {
            callDelay(callback, "false");
        }
    }
    this.update = function(json, callback) {
        // Converts a JavaScript Object Notation (JSON) string into an object.
        var passedJson = JSON.parse(json);
        // Get all todos
        var todos = JSON.parse(window.localStorage.getItem("todos")),
            todo = null,
            len = todos.length,
            i = 0;
       
        // Loop through them and update the value
        $.each(todos, function(i, v) {
            if ( v.id == passedJson.id ) {                
                v.title = passedJson.title;
                v.description = passedJson.description;
                return false;
            }
        });
        // Save the JSON back to localStorage
        if (window.localStorage.setItem("todos", JSON.stringify(todos))) {
            callDelay(callback, "true");
        } else {
            callDelay(callback, "false");
        }
    }
    this.delete = function(json, callback) {
        // Converts a JavaScript Object Notation (JSON) string into an object.
        var passedJson = JSON.parse(json);
        // Get all todos
        var todos = JSON.parse(window.localStorage.getItem("todos")),
            todo = null,
            len = todos.length,
            i = 0;
        // Loop through existing todos and remove one to be deleted
        for(var i=0; i<todos.length; i++){
            if(todos[i].id == passedJson.id){
                todos.splice(i, 1);  //removes 1 element at position i
                break;
            }
        }
        // Save the JSON back to localStorage
        if (window.localStorage.setItem("todos", JSON.stringify(todos))) {
            callDelay(callback, "true");
        } else {
            callDelay(callback, "false");
        }
    }
5.3) Emulate again.

6) Form Action Processing

6.1) There are two Form Actions; Add and Delete.
6.2) At the moment, if you click on the buttons, you will get error message. The method to convert form data into JSON object is missing.
6.3) Add a method “serializeObject” into app.js as shown below
// jQuery plugin - Encode a set of form elements as a JSON object for manipulation/submission.
$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};
6.4) Test in emulator.
Click the test item shown above.
Click the Delete button.
The item will be deleted from the list.

7) Final Codes

7.1) index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>jQuery Mobile To Do</title>
    <link rel="stylesheet"  href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css">
    <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
    <script src="./js/local-storage.js"></script>
    <script src="./js/apps.js"></script>
</head>
<body>
    <!-- Home -->
    <div data-role="page" id="home">
            <div data-role="header" data-position="fixed">
            <h1>JQM To Do</h1>
            <a href="#add" data-icon="plus" data-iconpos="notext" class="ui-btn-right" data-transition="slide" >New</a>
        </div>
        <div data-role="content">
            <ul data-role="listview" class="todo-listview">
            <li data-row-id="1" class="completed"><a href="#view" data-transition="slide" class="view" data-view-id="1"><h2>title</h2><p>desc</p></a><a href="#" data-icon="delete" data-iconpos="notext" class="mark-outstanding" data-mark-id="1">Mark as outstanding</a></li>
        </div>
    </div>
    <!-- /Home -->
  <!-- View -->        
    <div data-role="page" id="view" data-add-back-btn="true">
            <div data-role="header" data-position="fixed">
            <h1>View</h1>
        </div>
        <div data-role="content">
            <form id="edit">
                <input type="hidden" id="id" value="" name="id"/>
                <input type="text" id="title" value="" data-id="" class="target" name="title"/>
                <textarea id="description" data-id="" class="target" name="description"></textarea>
            </form>
            <a href="" data-role="button" class="delete">Delete</a>
        </div>
    </div>
    <!-- /View -->
    <!-- Add -->
    <div data-role="page" id="add" data-add-back-btn="true">
        <div data-role="header" data-position="fixed">
            <h1>Add</h1>
        </div>
        <div data-role="content">
            <form method="" action="" id="insert">
                <label for="title">Title:</label>
                <input type="text" name="title" id="text-basic" value="">
                <label for="description">Description:</label>
                <textarea cols="40" rows="8" name="description" id="text-basic"></textarea>
            </form>
            <a href="" data-role="button" class="add">Add</a>
        </div>
    </div>
    <!-- /Add -->          
</body>
</html>
7.2) app.js
/*
Main App file
*/
// jQuery plugin - Encode a set of form elements as a JSON object for manipulation/submission.
$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};
// Define the app as an object to take out of global scope
var app = {
    findAll: function() {
        console.log('DEBUG - 2. findAll() triggered');
        this.store.findAll(function(todos) {
            var l = todos.length;
            var td;
            // Create new arrays so we can order them with outstanding first
            outstanding = [];
            completed = [];
            allTodos = [];
            // Loop through todos, build up lis and push to arrays
            for (var i=0; i<l; i++) {
                td = todos[i];
                // If not completed
                if (td.status == 0) {
                    outstanding.push('<li data-row-id="' + td.id + '" class="outstanding"><a href="#view" data-transition="slide" class="view" data-view-id="' + td.id +'"><h2>' + td.title+ '</h2><p>' + td.description + '</p></a><a href="#" data-icon="check" data-iconpos="notext" class="mark-completed" data-mark-id="' + td.id +'">Mark as completed</a></li>');
                }
                // If is completed
                else {
                    completed.push('<li data-row-id="' + td.id + '" class="completed"><a href="#view" data-transition="slide" class="view" data-view-id="' + td.id +'"><h2>' + td.title+ '</h2><p>' + td.description + '</p></a><a href="#" data-icon="delete" data-iconpos="notext" class="mark-outstanding" data-mark-id="' + td.id +'">Mark as outstanding</a></li>');
                }
            }
            // Join both arrays
            allTodos = outstanding.concat(completed);
            // Remove any previously appended
            $('.todo-listview li').remove();
            // Append built up arrays to ULs here.
            $('.todo-listview').append(allTodos);            
            // Refresh JQM listview
            $('.todo-listview').listview('refresh');
        });
    },
    findById: function(id) {
       
        this.store.findById(id, function(result) {
           
            $('#title').val(result.title);
            $('#title').attr('data-id', id);
            $('#description').val(result.description);
            $('#id').val(id);
       
        });
    },
    markCompleted: function(id) {
        // Passing json as any store will be able to handle it (even if we change to localStorage etc)
        this.store.markCompleted(id, function(result) {
            // DB updates successful
            if(result) {
                console.log("DEBUG - Success, db updated and marked as completed");
                // Find original row and grab details
                var originalRow =  $('#home *[data-row-id="'+id+'"]'),
                    title = originalRow.find("h2").text(),
                    desc = originalRow.find("p").text();
                // Remove from pending row
                originalRow.remove();
                // Re-build the li rather than clone as jqm generates a lot of fluff
                var newRow = '<li data-row-id="' + id + '" class="completed"><a href="#view" data-transition="slide" class="view" data-view-id="' + id +'"><h2>' + title + '</h2><p>' + desc + '</p></a><a href="#" data-icon="delete" data-iconpos="notext" class="mark-outstanding" data-mark-id="' + id +'">Mark as outstanding</a></li>';
                // Add to completed
                $('.todo-listview').append(newRow);
                // Refresh dom
                $('.todo-listview').listview('refresh');
                // Kept for debugging use
                //console.log("id length = " + $('[data-row-id='+id+']').length);
            } else {
                alert("Error - db did not update and NOT marked as completed");
            }
        });
    },
    markOutstanding: function(id) {
        // Passing json as any store will be able to handle it (even if we change to localStorage, indexedDB etc)
        this.store.markOutstanding(id, function(result) {
            // DB updates successful
            if(result) {
                console.log("DEBUG - Success, db updated and marked as outstanding");
                // Find original row and grab details
                var originalRow =  $('*[data-row-id="'+id+'"]'),
                    title = originalRow.find("h2").text(),
                    desc = originalRow.find("p").text();
                // Remove from pending row
                originalRow.remove();
                // Re-build the li rather than clone as jqm generates a lot of fluff
                var newRow = '<li data-row-id="' + id + '" class="outstanding"><a href="#view" data-transition="slide" class="view" data-view-id="' + id +'"><h2>' + title + '</h2><p>' + desc + '</p></a><a href="#" data-icon="check" data-iconpos="notext" class="mark-completed" data-mark-id="' + id +'">Mark as completed</a></li>';
                // Add to completed
                $('.todo-listview').prepend(newRow);
                // Refresh dom
                $('.todo-listview').listview('refresh');
                // Kept for debugging use
                //console.log("id length = " + $('[data-row-id='+id+']').length);
            } else {
                alert("Error - db did not update and NOT marked as outstanding");
            }
        });
    },
    insert: function(json) {
        // Passing json as any store will be able to handle it (even if we change to localStorage etc)
        this.store.insert(json, function(result) {
            // On successful db insert
            if(result) {
                console.log("DEBUG - Success,  add returned true");
                // Redirect back to #home page, add a transition andchange the hash
                $.mobile.changePage( $("#home"), {
                    transition: "slide",
                    reverse: true,
                    changeHash: true,
                });
            } else {
                alert("Error on insert!");
            }
        });
    },
    update: function(json) {
        // Passing json as any store will be able to handle it (even if we change to localStorage etc)
        this.store.update(json, function(result) {
            // On succuessful db update
            if(result) {
                console.log("DEBUG - Success, updated returned true");
            } else {
                alert("Error on update!");
            }
        });
    },
    delete: function(json) {
        // Passing json as any store will be able to handle it (even if we change to localStorage etc)
        this.store.delete(json, function(result) {
            // On successful db delete
            if(result) {
                console.log("DEBUG - Success, delete returned true");
                // Redirect back to #home page
                $.mobile.changePage( $("#home"), {
                    transition: "slide",
                    reverse: true,
                    changeHash: true
                });
            } else {
                alert("Error on delete!");
            }
        });
    },
    initialize: function() {
        // Create a new store
         this.store = new LocalStorageDB();
        // Bind all events here when the app initializes
        $(document).on('pagebeforeshow', '#home', function(event) {
            console.log("DEBUG - 1. Home pageinit bind");
         app.findAll();
        });
        $(document).on('click', '.view', function(event) {
            console.log("DEBUG - Trying to access view");
         app.findById($(this).data('view-id'))
        });
        $(document).on('click', '.add', function(event) {
            console.log("DEBUG - Trying to insert via the add method");
         var data = JSON.stringify($('#insert').serializeObject());
         app.insert(data);
        });
        $(document).on('change', '.target', function(event) {
            console.log("DEBUG - Trying to update on change");
         var data = JSON.stringify($('#edit').serializeObject());
         app.update(data);
        });
        $(document).on('click', '.delete', function(event) {
            console.log("DEBUG - Trying to delete after delete btn press");
         var data = JSON.stringify($('#edit').serializeObject());
         app.delete(data);
        });
        $(document).on('click', '.mark-completed', function(event) {
            console.log("DEBUG - Mark completed pressed");
         app.markCompleted($(this).data('mark-id'));
        });
        $(document).on('click', '.mark-outstanding', function(event) {
            console.log("DEBUG - Mark outstanding pressed");
         app.markOutstanding($(this).data('mark-id'));
        });
    }
};
app.initialize();
7.3) local-storage.js
var LocalStorageDB = function(successCallback, errorCallback) {
        // Used to simulate async calls. This is done to provide a consistent interface with storage methods like WebSQL and serverside ajax calls
    var callDelay = function(callback, data) {
        if (callback) {
            setTimeout(function() {
                callback(data);
            }, 100);
        }
    }
 // Allows us to sort an array of object - Use array.sort(sortByProperty('firstName'));
    var sortByProperty = function(property) {
        'use strict';
        return function (a, b) {
            var sortStatus = 0;
            if (a[property] < b[property]) {
                sortStatus = -1;
            } else if (a[property] > b[property]) {
                sortStatus = 1;
            }
     
            return sortStatus;
        };
    }

        // Sample Data (An array of objects)
    var todos = [
        {"id": 1, "title": "Go to the shop", "description": "Get milk and bread", "status": 0},
        {"id": 2, "title": "Post office", "description": "Collect mail", "status": 0},
        {"id": 3, "title": "Email Dad", "description": "About birthday", "status": 0},
        {"id": 4, "title": "Haircut", "description": "Well overdue", "status": 1}
    ];
    // Add the sample data to localStorage
    window.localStorage.setItem("todos", JSON.stringify(todos));
    this.findAll = function(callback) {
            // Parse a string as json
            var todos = JSON.parse(window.localStorage.getItem("todos"));
        callDelay(callback, todos);
    }
    this.findById = function(id, callback) {
        var todos = JSON.parse(window.localStorage.getItem("todos")),
                todo = null,
                len = todos.length,
            i = 0;
       
        for (; i < len; i++) {
            if (todos[i].id === id) {
                todo = todos[i];
                break;
            }
        }
        callDelay(callback, todo);
    }
    this.markCompleted = function(id, callback) {
        // Get all todos
        var todos = JSON.parse(window.localStorage.getItem("todos")),
            todo = null,
            len = todos.length,
            i = 0;
       
        // Loop through them and update the value
        $.each(todos, function(i, v) {
            if ( v.id === id ) {
                v.status = 1;
                return false;
            }
        });
        // Save the JSON back to localStorage
        if (window.localStorage.setItem("todos", JSON.stringify(todos))) {
            callDelay(callback, "true");
        } else {
            callDelay(callback, "false");
        }
    }
    this.markOutstanding = function(id, callback) {
        // Get all todos
        var todos = JSON.parse(window.localStorage.getItem("todos")),
            todo = null,
            len = todos.length,
            i = 0;
       
        // Loop through them and update the value
        $.each(todos, function(i, v) {
            if ( v.id === id ) {
                v.status = 0;
                return false;
            }
        });
        // Save the JSON back to localStorage
        if (window.localStorage.setItem("todos", JSON.stringify(todos))) {
            callDelay(callback, "true");
        } else {
            callDelay(callback, "false");
        }
    }
    this.insert = function(json, callback) {
        // Converts a JavaScript Object Notation (JSON) string into an object.
        var passedJson = JSON.parse(json),
            status = 0;
       
        // Get all todos
        var todos = JSON.parse(window.localStorage.getItem("todos")),
            todo = null,
            len = todos.length,
            i = 0;
       
        // Sort the json by ID (default is ASC)
        todos.sort(sortByProperty('id'));
        // Generate a new ID, pop the last obj in the array and grab the ID
        var lastTodo = todos.pop(),
            newID = lastTodo.id + 1;
        // Create the new Todo
        var newTodo = {"id": newID, "title": passedJson.title, "description": passedJson.description, "status": 0}
        // Add it to the existing todos        
        todos.push(lastTodo); // Add the popped one back in
        todos.push(newTodo);
        // Save the JSON back to localStorage
        if (window.localStorage.setItem("todos", JSON.stringify(todos))) {
            callDelay(callback, "true");
        } else {
            callDelay(callback, "false");
        }
    }
    this.update = function(json, callback) {
        // Converts a JavaScript Object Notation (JSON) string into an object.
        var passedJson = JSON.parse(json);
        // Get all todos
        var todos = JSON.parse(window.localStorage.getItem("todos")),
            todo = null,
            len = todos.length,
            i = 0;
       
        // Loop through them and update the value
        $.each(todos, function(i, v) {
            if ( v.id == passedJson.id ) {                
                v.title = passedJson.title;
                v.description = passedJson.description;
                return false;
            }
        });
        // Save the JSON back to localStorage
        if (window.localStorage.setItem("todos", JSON.stringify(todos))) {
            callDelay(callback, "true");
        } else {
            callDelay(callback, "false");
        }
    }
    this.delete = function(json, callback) {
        // Converts a JavaScript Object Notation (JSON) string into an object.
        var passedJson = JSON.parse(json);
        // Get all todos
        var todos = JSON.parse(window.localStorage.getItem("todos")),
            todo = null,
            len = todos.length,
            i = 0;
        // Loop through existing todos and remove one to be deleted
        for(var i=0; i<todos.length; i++){
            if(todos[i].id == passedJson.id){
                todos.splice(i, 1);  //removes 1 element at position i
                break;
            }
        }
        // Save the JSON back to localStorage
        if (window.localStorage.setItem("todos", JSON.stringify(todos))) {
            callDelay(callback, "true");
        } else {
            callDelay(callback, "false");
        }
    }    
    callDelay(successCallback);
}

8) Download

Download Source Files for this part:

No comments:

Post a Comment