Google play程式: https://play.google.com/store/apps/details?id=com.yslifes.sample.ballot
這裡先簡單的交待程式碼開發的環境及source
程式是由Apache Cordova建立的,如何安裝可以參考Commaond line install的方式,Apahce Cordova其實就是phonegap,phonegap一開始是adobe創建的,不過後來捐給了apache基金會。
此專案有安裝之plugin
org.apache.cordova.devicemotion.AccelListener 用來監控搖動行動裝置的(Android手機或平版)
org.apache.cordova.splashscreen.SplashScreen 一開始的載入畫面SplashScreen
org.apache.cordova.inappbrowser.InAppBrowser 用來另開連接到系統預設的browser的,不過目前沒有使用
com.phonegap.plugins.barcodescanner.BarcodeScanner 條碼QRCode掃描,使用zxing framework
使用的javascript framework
JQuery、JQuery Mobile、htmll10n、jquery.tmp等
其中htmll10n是為了多國語系的支援
原始碼如下:
index.html部份
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, user-scalable=no"> <script type="text/javascript" src="js/l10n.js"></script> <link rel="localizations" href="values/strings.json" type="application/l10n+json"/> <link href="js/jquery.mobile-1.4.4.min.css" rel="stylesheet" type="text/css" /> <!-- Export CSS --> <style> div.ui-field-contain{ font-size:140%; } div.ui-field-contain input{ font-size:140%; } body { font-family: 'Open Sans', sans-serif; } </style> <script src="js/jquery-1.9.1.min.js"></script> <script> $(document).on("mobileinit", function () { $.mobile.autoInitializePage = false; $.mobile.hashListeningEnabled = false; }); function mobileInitPage() { $.mobile.hashListeningEnabled = true; $.mobile.initializePage(); }; </script> <script src="js/jquery.mobile-1.4.4.min.js"></script> <!-- Uncomment the following to include cordova in your android project --> <!--<script src="//jqmdesigner.appspot.com/platforms/android/cordova.js"></script>--> <script type="text/javascript" src="js/jquery.tmpl.min.js"></script> <script type="text/x-jquery-tmpl" id="myTempl"> <tr><th>${time}</th><td>${seq}</td><td> ${val} </td></tr> </script> <script type="text/x-jquery-tmpl" id="NameListTempl"> <tr><th>${seq}</th><td>${name}</td></tr> </script> <script type="text/javascript" src="cordova.js"></script> <script type="text/javascript" src="js/index.js"></script> <script type="text/javascript"> $(document).ready(function() { window.location.hash = 'home'; $.mobile.initializePage(); app.initialize(); handleExternalURLs(); }); </script> <title>yslifes Ballot</title> </head> <body> <!-- Page: home --> <div id="home" data-role="page"> <div data-role="header" data-position="fixed"> <a href="#NameList" data-transition="slidedown" class="ui-btn ui-btn-left ui-shadow ui-icon-arrow-d ui-btn-icon-left" data-l10n-id="str_list">清單</a> <h3 data-l10n-id="str_Setting">設定</h3> <a class="ui-btn ui-btn-right ui-icon-arrow-r ui-btn-icon-right ui-shadow" href="#RandPage" data-transition="slide" ><span data-l10n-id="str_start">開始</span></a> </div> <div role="main" class="ui-content"> <div class="ui-field-contain"> <label for="max_val" data-l10n-id="str_maxValue">最大值:</label> <input type="number" name="max_val" id="max_val" pattern="[0-9.]*" placeholder="{str_maxValue}" value="10" data-clear-btn="false" data-mini="true" data-clear-btn-text="清除" data-prevent-focus-zoom="false"> </div> <div class="ui-field-contain"> <label for="min_val" data-l10n-id="str_minValue">最小值:</label> <input type="number" name="min_val" id="min_val" pattern="[0-9.]*" placeholder="{str_minValue}" value="1" data-clear-btn="false" data-mini="true" data-clear-btn-text="清除" data-prevent-focus-zoom="false" > </div> <div class="ui-field-contain"> <label for="get_val" data-l10n-id="str_getNum">一次取得數:</label> <input type="number" name="get_val" id="get_val" pattern="[0-9.]*" placeholder="{str_getNum}" value="1" data-clear-btn="false" data-mini="true" data-clear-btn-text="清除" data-prevent-focus-zoom="false"> </div> <div class="ui-grid-a" style="height:95px"> <div class="ui-block-a" style="height:100%"> <div class="ui-field-contain"> <label for="append_val" data-l10n-id="str_loop">連續取得</label> <input type="checkbox" data-role="flipswitch" id="append_val" data-mini="true" name="append_val"> </div> </div> <div class="ui-block-b" style="height:100%"> <div class="ui-field-contain"> <label for="loop_same" data-l10n-id="str_append">是否可重覆</label> <input type="checkbox" data-role="flipswitch" id="loop_same" data-mini="true" name="loop_same" checked> </div> </div> </div> </div> </div> <div id="RandPage" data-role="page" is="page"> <div data-role="header" data-position="fixed"> <h3 data-l10n-id="str_result" >結果</h3> <a class="ui-btn ui-btn-left ui-btn-icon-left ui-icon-arrow-l" href="#home" data-transition="slide" data-direction="reverse" data-l10n-id="str_reverse">上層</a> </div> <div role="main" class="ui-content" is="content"> <table data-role="table" data-mode="Reflow" class="ui-responsive ui-shadow gk-decorate table-stripe table-stroke" id="gk-923egj1" is="jqm-table"> <thead> <tr> <th data-priority="1" style="width:30%" data-l10n-id="str_idx" >取號次</th> <th data-priority="1" style="width:30%" data-l10n-id="str_seq" >序號</th> <th data-l10n-id="str_result" >結果</th> </tr> </thead> <tbody> </tbody> </table> </div> <div data-position="fixed" data-role="footer"> <div data-role="navbar"> <ul> <li id="clr_value_bt"> <button type="button" data-icon="delete" data-l10n-id="str_reault_clear" >清除結果</button> </li> <li id="get_value_bt"> <button type="button" data-icon="info" data-l10n-id="str_get" >取號</button> </li> </ul> </div> </div> </div> <div id="NameList" data-role="page" is="page"> <div data-role="header" data-position="fixed"> <h3 data-l10n-id="str_Inventory_list" >清單列表</h3> <a class="ui-btn ui-btn-left ui-btn-icon-left ui-icon-arrow-l" href="#home" data-transition="slide" data-direction="reverse" data-l10n-id="str_reverse">上層</a> </div> <div role="main" class="ui-content" is="content"> <ul><li data-l10n-id="str_qrcode_url">http://ppt.cc/CK~z 建立QRCode</li> <li data-l10n-id="str_row_of_data">一列為一筆資料</li></ul> <table data-role="table" data-mode="Reflow" class="ui-responsive ui-shadow gk-decorate table-stroke table-stripe" id="gk-107ouJq" is="jqm-table"> <thead> <tr> <th data-priority="1" data-l10n-id="str_item_idx">項次</th> <th data-priority="1" data-l10n-id="str_item_name">名稱</th> </tr> </thead> <tbody> </tbody> </table> </div> <div data-position="fixed" data-role="footer"> <div data-role="navbar"> <ul> <li id="qrcode"> <button type="button" data-icon="camera" data-l10n-id="str_scan_qrcode">掃描條碼</button> </li> <li id="clrName_value_bt"> <button type="button" data-icon="delete" data-l10n-id="str_clear_list">清除清單</button> </li> </ul> </div> </div> </div> </body> </html>
index.js
/* * 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. */ var language = document.cookie.match(/language=((\w{2,3})(-\w+)?)/); if(language) language = language[1]; html10n.bind('indexed', function() { html10n.localize([language, navigator.language, navigator.userLanguage, 'en']) //html10n.localize('en'); }) html10n.bind('localized', function() { document.documentElement.lang = html10n.getLanguage() document.documentElement.dir = html10n.getDirection() // Then I display the index page using handlebars to render a template. }); var app = { // Application Constructor initialize: function() { this.bindEvents(); }, // Bind Event Listeners // // Bind any events that are required on startup. Common events are: // 'load', 'deviceready', 'offline', and 'online'. bindEvents: function() { document.addEventListener('deviceready', this.onDeviceReady, false); }, // deviceready Event Handler // // The scope of 'this' is the event. In order to call the 'receivedEvent' // function, we must explicitly call 'app.receivedEvent(...);' onDeviceReady: function() { app.receivedEvent('deviceready'); }, // Update DOM on a Received Event receivedEvent: function(id) { navigator.splashscreen.hide(); } }; //http開頭的url另開bo function handleExternalURLs() { $("a.openbrowser").on("click",function(e){ //console.log($(this).prop('href')); var url = $(this).prop('href'); navigator.app.loadUrl(url, { openExternal: true }); e.preventDefault(); }); /* // Handle click events for all external URLs if (device.platform.toUpperCase() === 'ANDROID') { $(document).on('click', 'a[href^="http"]', function (e) { var url = $(this).attr('href'); navigator.app.loadUrl(url, { openExternal: true }); e.preventDefault(); }); } else if (device.platform.toUpperCase() === 'IOS') { $(document).on('click', 'a[href^="http"]', function (e) { var url = $(this).attr('href'); window.open(url, '_system'); e.preventDefault(); }); } else { // Leave standard behaviour }*/ } function getRandomInt(max,min ) { //console.log(min); //console.log(max); return Math.floor(Math.random() * (max - min + 1) + min); } var time = 0; function clearRandData() { time = 0; $("#gk-923egj1 tbody").empty(); } function onShake() { console.log("shake it"); $("#get_value_bt").click(); }; $(document).on("pageshow", "#home", function () { if(typeof(shake)!="undefined") shake.stopWatch(); }); $(document).on("pageshow", "#RandPage", function () { clearRandData(); if(typeof(shake)!="undefined") shake.startWatch(onShake); }); var NameList = new Array(); //清單列表第一次init $(document).one("pageshow","#NameList",function(){ $("#qrcode").on("click",function(){ cordova.plugins.barcodeScanner.scan( function (result) { // console.log("QRCode Result Data:"); // console.log(result); if(result.cancelled!=true) { //if(result.text.indexOf("\n")>-1){ $("#gk-107ouJq tbody").empty(); NameList = result.text.split("\n"); var val_arr = new Array(NameList.length); for(var i =0;i<NameList.length;i++) { var o = new Object(); o.seq = i+1; o.name = NameList[i]; val_arr[i] = o; } $("#NameListTempl").tmpl(val_arr).prependTo($("#gk-107ouJq tbody")); $("#max_val").val(NameList.length); $("#min_val").val(1); alert(_('clear_first_msg')); //}else //alert("條碼內容錯誤!"); } },function(error){ }); }); $("#clrName_value_bt").on("click", function (e) { $("#gk-107ouJq tbody").empty(); NameList.length = 0; }); }); $(document).one("pageshow", "#RandPage", function () { $("#clr_value_bt").on("click", function (e) { clearRandData(); }); $("#get_value_bt").on("click", function (e) { if ($("#append_val").prop("checked")) { clearRandData(); } var max_val = NameList.length==0?parseInt($("#max_val").val(), 10):NameList.length; var min_val = NameList.length==0?parseInt($("#min_val").val(), 10):1; var get_val = parseInt($("#get_val").val(), 10); var loop_same = $("#loop_same").prop("checked"); var tmp; if(min_val>max_val) { tmp = max_val; max_val = min_val; min_val = tmp; } if(!loop_same && (max_val-min_val)<get_val) { alert(_("less_number_msg")); return; } time++; var val_arr = new Array(get_val); var exist_text = ""; for (var i = 0; i < get_val; i++) { //console.log(val); var val = getRandomInt(max_val, min_val); if(loop_same || (!loop_same && exist_text.indexOf(val+",")==-1)) { var obj = new Object(); obj.val = NameList.length==0?val:(val+","+NameList[val-1]); if(i==0) obj.time = time; else obj.time = ""; obj.seq = i + 1; val_arr[i] = obj; exist_text = val+","; } else//重新取號 i--; } //console.log(val_arr); $("#myTempl").tmpl(val_arr).prependTo($("#gk-923egj1 tbody")); }); });
strings.json
{ "en": { "clear_first_msg": "Unless you clear the list, otherwise the result will take a number so dominated the list!", "less_number_msg": "To obtain the number of not greater than the number of desirable!", "str_list":"List", "str_start":"Go", "str_maxValue":"value of max:", "str_minValue":"value of min:", "str_getNum":"Get the number of:", "str_loop":"Continue loop", "str_append":"Repeat?", "str_result":"Result", "str_reverse":"Return", "str_idx":"Index", "str_seq":"Seq", "str_reault_clear":"Result Clear", "str_get":"Get It!", "str_Inventory_list":"Inventory list", "str_qrcode_url":"http://goo.gl/BqfwZU Create QRCode", "str_row_of_data":"one data at one row", "str_item_idx":"Item", "str_item_name":"Name", "str_scan_qrcode":"Qrcode Scan", "str_clear_list":"Clear List", "str_Setting":"Setting" }, "zh-TW": { "clear_first_msg": "除非您清除清單,否則取號結果會依此清單為主!", "less_number_msg": "要取得數目不可大於可取數目", "str_list":"清單", "str_start":"開始", "str_maxValue":"最大值:", "str_minValue":"最小值:", "str_getNum":"一次取得數:", "str_loop":"連續取得", "str_append":"是否可重覆", "str_result":"結果", "str_reverse":"上層", "str_idx":"取號次", "str_seq":"序號", "str_reault_clear":"清除結果", "str_get":"取號", "str_Inventory_list":"清單列表", "str_qrcode_url":"http://ppt.cc/CK~z 建立QRCode", "str_row_of_data":"一列為一筆資料", "str_item_idx":"項次", "str_item_name":"名稱", "str_scan_qrcode":"掃描條碼", "str_clear_list":"清除清單", "str_Setting":"設定" }, "zh-CN": { "clear_first_msg": "除非您清除清單,否則取號結果會依此清單為主!", "less_number_msg": "要取得數目不可大於可取數目", "str_list":"清單", "str_start":"開始", "str_maxValue":"最大值:", "str_minValue":"最小值:", "str_getNum":"一次取得數:", "str_loop":"連續取得", "str_append":"是否可重覆", "str_result":"結果", "str_reverse":"上層", "str_idx":"取號次", "str_seq":"序號", "str_reault_clear":"清除結果", "str_get":"取號", "str_Inventory_list":"清單列表", "str_qrcode_url":"http://ppt.cc/CK~z 建立QRCode", "str_row_of_data":"一列為一筆資料", "str_item_idx":"項次", "str_item_name":"名稱", "str_scan_qrcode":"掃描條碼", "str_clear_list":"清除清單", "str_Setting":"設定" }, "zh-HK": { "clear_first_msg": "除非您清除清單,否則取號結果會依此清單為主!", "less_number_msg": "要取得數目不可大於可取數目", "str_list":"清單", "str_start":"開始", "str_maxValue":"最大值:", "str_minValue":"最小值:", "str_getNum":"一次取得數:", "str_loop":"連續取得", "str_append":"是否可重覆", "str_result":"結果", "str_reverse":"上層", "str_idx":"取號次", "str_seq":"序號", "str_reault_clear":"清除結果", "str_get":"取號", "str_Inventory_list":"清單列表", "str_qrcode_url":"http://ppt.cc/CK~z 建立QRCode", "str_row_of_data":"一列為一筆資料", "str_item_idx":"項次", "str_item_name":"名稱", "str_scan_qrcode":"掃描條碼", "str_clear_list":"清除清單", "str_Setting":"設定" } }
原始專案再於下一篇附上