<!DOCTYPE html>
<!--

 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.

-->


<html>
  <head>
    <meta name="viewport" content="width=device-width,height=device-height,user-scalable=no,maximum-scale=1.0,initial-scale=1.0" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <!-- ISO-8859-1 -->
    <title>Cordova Mobile Spec</title>
    <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8">
    <script type="text/javascript" charset="utf-8" src="../cordova-incl.js"></script>      

      
<script type="text/javascript" charset="utf-8">

    var deviceReady = false;

    //-------------------------------------------------------------------------
    // Contacts
    //-------------------------------------------------------------------------
    function getContacts() {
        obj = new ContactFindOptions();
        // show all contacts, so don't filter
        obj.multiple = true;
        navigator.contacts.find(
            ["displayName", "name", "phoneNumbers", "emails", "urls", "note"],
            function(contacts) {
                var s = "";
                if (contacts.length == 0) {
                    s = "No contacts found";
                }
                else {
                    s = "Number of contacts: "+contacts.length+"<br><table width='100%'><tr><th>Name</th><td>Phone</td><td>Email</td></tr>";
                    for (var i=0; i<contacts.length; i++) {
                        var contact = contacts[i];
                        s = s + "<tr><td>" + contact.name.formatted + "</td><td>";
                        if (contact.phoneNumbers && contact.phoneNumbers.length > 0) {
                            s = s + contact.phoneNumbers[0].value;
                        }
                        s = s + "</td><td>"
                        if (contact.emails && contact.emails.length > 0) {
                            s = s + contact.emails[0].value;
                        }
                        s = s + "</td></tr>";
                    }
                    s = s + "</table>";
                }
                document.getElementById('contacts_results').innerHTML = s;
            },
            function(e) {
                document.getElementById('contacts_results').innerHTML = "Error: "+e.code;
            },
            obj);
    };

    function addContact(){
        console.log("addContact()");
        try{
            var contact = navigator.contacts.create({"displayName": "Dooney Evans"});
            var contactName = {
                formatted: "Dooney Evans",
                familyName: "Evans",
                givenName: "Dooney",
                middleName: ""
            };

            contact.name = contactName;

            var phoneNumbers = [1];
            phoneNumbers[0] = new ContactField('work', '512-555-1234', true);
            contact.phoneNumbers = phoneNumbers;

            contact.save(
                function() { alert("Contact saved.");},
                function(e) { alert("Contact save failed: " + e.code); }
            );
            console.log("you have saved the contact");
        }
        catch (e){
            alert(e);
        }

    };
    
    /**
     * Function called when page has finished loading.
     */
    function init() {
        document.addEventListener("deviceready", function() {
                deviceReady = true;
                console.log("Device="+device.platform+" "+device.version);
            }, false);
        window.setTimeout(function() {
        	if (!deviceReady) {
        		alert("Error: Apache Cordova did not initialize.  Demo will not run correctly.");
        	}
        },1000);
    }

</script>

  </head>
  <body onload="init();" id="stage" class="theme">
  
    <h1>Contacts</h1>    
    <div id="info">
        <b>Results:</b><br>
        <span id="contacts_results"> </span>
    </div>
    <h2>Action</h2>
    <div class="btn large" onclick="getContacts();">Get phone's contacts</div>
    <div class="btn large" onclick="addContact();">Add a new contact 'Dooney Evans'</div>
    <h2> </h2><div class="backBtn" onclick="backHome();">Back</div>
  </body>
</html>      
