From 3b0bdfb6e475b9fb04d4f8db5491fe708e339008 Mon Sep 17 00:00:00 2001 From: Andrew Trice Date: Fri, 20 Apr 2012 13:52:19 -0400 Subject: [PATCH] work in progress & organization --- .DS_Store | Bin 0 -> 6148 bytes LICENSE | 21 + README | 20 + samples/.DS_Store | Bin 0 -> 6148 bytes samples/browser history/.DS_Store | Bin 0 -> 6148 bytes samples/browser history/assets/.DS_Store | Bin 0 -> 6148 bytes .../browser history/assets/header_bg_wood.png | Bin 0 -> 3797 bytes samples/browser history/index.html | 208 + samples/browser history/libs/.DS_Store | Bin 0 -> 6148 bytes .../libs/jquery.address-1.4.js | 655 +++ samples/multi-device form factor/.DS_Store | Bin 0 -> 6148 bytes samples/multi-device form factor/README | 1 + .../RottenTomatoes.xcodeproj/project.pbxproj | 498 ++ .../contents.xcworkspacedata | 7 + .../UserInterfaceState.xcuserstate | Bin 0 -> 19227 bytes .../xcschemes/RottenTomatoes.xcscheme | 84 + .../xcschemes/xcschememanagement.plist | 22 + .../RottenTomatoes/Classes/AppDelegate.h | 52 + .../RottenTomatoes/Classes/AppDelegate.m | 191 + .../Classes/MainViewController.h | 17 + .../Classes/MainViewController.m | 47 + .../Classes/MainViewController.xib | 118 + .../RottenTomatoes/PhoneGap.plist | 56 + .../RottenTomatoes/Plugins/README | 1 + .../Resources/Capture.bundle/controls_bg.png | Bin 0 -> 955 bytes .../Capture.bundle/controls_bg@2x.png | Bin 0 -> 971 bytes .../Capture.bundle/controls_bg~ipad.png | Bin 0 -> 969 bytes .../Resources/Capture.bundle/microphone.png | Bin 0 -> 72226 bytes .../Capture.bundle/microphone@2x.png | Bin 0 -> 282409 bytes .../Capture.bundle/microphone~ipad.png | Bin 0 -> 393975 bytes .../Capture.bundle/record_button.png | Bin 0 -> 5852 bytes .../Capture.bundle/record_button@2x.png | Bin 0 -> 13875 bytes .../Capture.bundle/record_button~ipad.png | Bin 0 -> 7547 bytes .../Resources/Capture.bundle/recording_bg.png | Bin 0 -> 973 bytes .../Capture.bundle/recording_bg@2x.png | Bin 0 -> 990 bytes .../Capture.bundle/recording_bg~ipad.png | Bin 0 -> 996 bytes .../Resources/Capture.bundle/stop_button.png | Bin 0 -> 5514 bytes .../Capture.bundle/stop_button@2x.png | Bin 0 -> 12965 bytes .../Capture.bundle/stop_button~ipad.png | Bin 0 -> 7119 bytes .../Resources/en.lproj/Localizable.strings | 25 + .../Resources/es.lproj/Localizable.strings | 25 + .../Resources/icons/icon-72.png | Bin 0 -> 4944 bytes .../RottenTomatoes/Resources/icons/icon.png | Bin 0 -> 3902 bytes .../Resources/icons/icon@2x.png | Bin 0 -> 7869 bytes .../Resources/splash/Default.png | Bin 0 -> 9537 bytes .../Resources/splash/Default@2x.png | Bin 0 -> 22029 bytes .../RottenTomatoes/RottenTomatoes-Info.plist | 49 + .../RottenTomatoes/RottenTomatoes-Prefix.pch | 7 + .../RottenTomatoes/en.lproj/InfoPlist.strings | 2 + .../RottenTomatoes/main.m | 35 + .../multi-device form factor/www/.DS_Store | Bin 0 -> 6148 bytes .../www/assets/tomato.jpeg | Bin 0 -> 11781 bytes .../multi-device form factor/www/index.html | 233 + .../www/phonegap-1.4.1.js | 4123 +++++++++++++++++ src/libs/css/activityIndicator.css | 5 - src/libs/noClickDelay.js | 10 +- src/slidingview/slidingview.css | 11 + src/slidingview/slidingview.js | 11 + src/splitviewnavigator/splitviewnavigator.css | 11 + src/splitviewnavigator/splitviewnavigator.js | 13 + src/viewnavigator/viewnavigator.css | 12 + src/viewnavigator/viewnavigator.js | 11 + 62 files changed, 6571 insertions(+), 10 deletions(-) create mode 100644 .DS_Store create mode 100644 LICENSE create mode 100644 README create mode 100644 samples/.DS_Store create mode 100644 samples/browser history/.DS_Store create mode 100644 samples/browser history/assets/.DS_Store create mode 100644 samples/browser history/assets/header_bg_wood.png create mode 100644 samples/browser history/index.html create mode 100644 samples/browser history/libs/.DS_Store create mode 100644 samples/browser history/libs/jquery.address-1.4.js create mode 100644 samples/multi-device form factor/.DS_Store create mode 100644 samples/multi-device form factor/README create mode 100644 samples/multi-device form factor/RottenTomatoes.xcodeproj/project.pbxproj create mode 100644 samples/multi-device form factor/RottenTomatoes.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 samples/multi-device form factor/RottenTomatoes.xcodeproj/project.xcworkspace/xcuserdata/triceam.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 samples/multi-device form factor/RottenTomatoes.xcodeproj/xcuserdata/triceam.xcuserdatad/xcschemes/RottenTomatoes.xcscheme create mode 100644 samples/multi-device form factor/RottenTomatoes.xcodeproj/xcuserdata/triceam.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 samples/multi-device form factor/RottenTomatoes/Classes/AppDelegate.h create mode 100644 samples/multi-device form factor/RottenTomatoes/Classes/AppDelegate.m create mode 100644 samples/multi-device form factor/RottenTomatoes/Classes/MainViewController.h create mode 100644 samples/multi-device form factor/RottenTomatoes/Classes/MainViewController.m create mode 100644 samples/multi-device form factor/RottenTomatoes/Classes/MainViewController.xib create mode 100644 samples/multi-device form factor/RottenTomatoes/PhoneGap.plist create mode 100644 samples/multi-device form factor/RottenTomatoes/Plugins/README create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/controls_bg.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/controls_bg@2x.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/controls_bg~ipad.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/microphone.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/microphone@2x.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/microphone~ipad.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/record_button.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/record_button@2x.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/record_button~ipad.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/recording_bg.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/recording_bg@2x.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/recording_bg~ipad.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/stop_button.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/stop_button@2x.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/Capture.bundle/stop_button~ipad.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/en.lproj/Localizable.strings create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/es.lproj/Localizable.strings create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/icons/icon-72.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/icons/icon.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/icons/icon@2x.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/splash/Default.png create mode 100644 samples/multi-device form factor/RottenTomatoes/Resources/splash/Default@2x.png create mode 100644 samples/multi-device form factor/RottenTomatoes/RottenTomatoes-Info.plist create mode 100644 samples/multi-device form factor/RottenTomatoes/RottenTomatoes-Prefix.pch create mode 100644 samples/multi-device form factor/RottenTomatoes/en.lproj/InfoPlist.strings create mode 100644 samples/multi-device form factor/RottenTomatoes/main.m create mode 100644 samples/multi-device form factor/www/.DS_Store create mode 100644 samples/multi-device form factor/www/assets/tomato.jpeg create mode 100644 samples/multi-device form factor/www/index.html create mode 100644 samples/multi-device form factor/www/phonegap-1.4.1.js diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0S5T3PFQ-7crvB$-8l@@<;@eoP{k3tJQSka`ZG!UE8B=%6F@r8T_pTg&H zW_K+F>s8Rs!0z|$&detJL3T3$AX=&41gHXlg^f@USzAHO>{5tlhJK; ze?C8J)a9w&%<6J(+sIFj?JTQQtV;FW+B-NpzwEm6r|kJfi!NwaWV;#`{p*4;VFg$L zR)7^)T?Nc7VQsIj1iW)rfED;b0XiQfHbTc>u2CHw*r^f#v5eEokW(!|IntnGFxQA4 zG@(-wb*eBWhS2FaFHM|dFxRNlL73u0m?wV~FG4*X*Ow|BgrkvrR)7^KDp1nHD&7AV z_{l6S@{1`vVg*=%f2M#aw>#|?Zpz%P-?m40t;BYRjf~=QB5249KLI$PbEKx6+AoP? ZoMSN8NUPAiN=M`$0VN1`tiUfQ@ChwqNK^m- literal 0 HcmV?d00001 diff --git a/samples/browser history/.DS_Store b/samples/browser history/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 zQ&y%_WQCGkYyDcHR;Y#l>AcS6bVL55zYqJ{!8<1GOadj23L>6}385km(c-8HF>w*65q92t zO|iGPIY~euH8jbd=yNiI8t^3UU7yzB>brZ}AC^K*zD?Z`xU76~f2FfBp2El$s8wpa z(&N9_hJMR<8aJ5C93r+>ci!I9+R`BW^-Fx!4-`w*DV_}``+?3b$UK}WFh%Apc$6{C zH)R8#84CHBlsk)$g)5108H1kA6tdr8k-U%&vbAYNtFXO}mMILhJYbOhBjApW66ML| zyWHDd&Fo&Bt6y^xM+pSZ1WEY4fumc98o``!UQ}Tc2U~2&_R6nu(w>*;|1s}-K!?i{ zL8A;!2Tf4*LUN;I=R*(YhYWHy1q_1aZV=%paL1Kyvy9m~P_Vx?b2gt=F~v7!p)$Ob zT}8kR{;g4gK;J>>6ke^XJ?g_NW`$l<(_SW4t0;-H0VE|1gh==yobWSbC7@4|ei@Yr z%LTrt5B6k_;nyTi*Ne6~S}$QRe|BZ3$}uB|-KM84=>6KYU^{PS}(2oSLHxgtkw0I^%?F5yZr#fF5z&9KcgAdKtg z-`zqCL@VF8;0||JAKl*9_ues6aOTu*!#X4!j`ib$V-M^F6F_8IO628lL*R{g!pR%ucE+EvRVAow*xJ<5v%Rr z%pU3qHTz(Rf7EpbTOa`u8G)0_wNbbe2hZgN(s-TkWk3emaYOw64rHd9qpihS&X_&PP2PK zX2ZmO;;Rugj?p7H;YrVzQw?H8IKVrc@MlscdSFV{Eng$C(%d#&W2~I$W2{AoDgH<` zb3S;VSpyc~NZFm-&1=_bI~yFjO>UsfeSHmFz0m{6&yRyQ*mA@k&ZLhf`=kWHaw^mz z1MmxEdc8Bms?k=BiNIcBPpu}y*G zBl++_!M}{eD-qU~a>m4YvTot86m91I;;e~iqqYo;wSLK^x=lAln*t(mu35lX-b7~i zqd83Of($v&5pQ~R6fGr`+X8J=|JZ~CrKX=-Gi!`l#;u4xI$CpP2VAI$$L=I*AO@xD zg)9kQ&b?`GE~Rv#_2ePXYy^0SQRTCYBE{NVr7$0cwPq~HZZ$Y_F4mdAg@9q@migRk zZMn;<%agM|fBF`9mr=)}JDgbZzP{7IxTD5H$bO{cGHT0zbuyuL7hZwO@=&CqW$Qlrqp;QuAcD0urDw91_D`Y!Gj+!5+{X*| z;`drtxgoRAkt9}d$N2O@&w8IgkkxN|jre*$Tn#4FbQJ}|6zez65y_*UWcqZt%Xt?O zlvYu|E2o|l{g=%kYYMSUtQWqp#&*1YF}}0PzTo>PL+?AmQA7S#gR-wLX?HdBdoX!) zx;!W?VRMP>c+Jy1{KGFLb&liq_R|Memp3Mn$^+K5r-c!kPXe^fgYBRFp&IN z7)N|g71>zt;VOCn+ZYOoj*bS9(9qC()BWlczIgFc&Ktukunj`GN7;?Y>kG-#_8Rgh z$F-^c&K0xxzY;**lrz1YYx)oXr?l38NyD=#`R!5k`^Ofi1xklS**9+*yEHpcMzF%<^5d6#0^_#VTXQ~xlXdDD}@QVgeSpQ{tdD&y({r_Z_ zsJejZ>FMbuot^tn`0vQcU%Am*CDu)yw2Rn1XN1l~0O$aCNr4q09XwHCY^68R9sMnk zB#t4(?qrifW=Tm&ehoMh+rL%&Nblvm0V({mq`7D9-b8fHW?$cP-c*54+4dS^ttcf# zSx#X`R3V@1ApY-3CZcrEGkQMjh;Pnhn#`5C%fRVR>(ZUiQr#b9u4E>W&^sR8Q6piH zYb92Z9f80K#HoFEe5W1|LOxf(=K>t|F9R?N(18)=ul>LQVp~y{n3!0qm|u9e8?zatk!z5N&|rk#{XtOogpw*{zkly^%d8P} z*EKX)sQeVDA4s|W=jB2tcbAc>z(aZSyoJT%G)`dx*{HqZJ(K0K|8#P4vagZT6a`kz zK3GNtlAv=!jXZiyVs)~~6Pk1MAAWT2I|exsuuj|B=iAMts7*{PUccn~jXGK^5UKh2 z!tMpSRn<^?(}T|+KPoOv_UOE>_5PU}6nv<+W$|l#=Ppg%-07y~6}hbezwyP*jn8qe zfCfNfctTfimOiqsB|x&SM{>defr3H=c7{SFy%I-2<7tHn6IH{g{gXF&tS(?)DL|fV zawsN`KE^ysCo$>cygX#TG=#P$mfnNEQb&-pfsEN zD(r8}Y!G1B{{EB8-}T4A`@Fwo-RnVsxo?Z>Xz!O?+!lF}zNA|X4UZaH6UHL<0Saqm ziqc~HE>d;bUWsXGWixGP6%L1U{c?!kzj*i@=8EqYhYSp4{d9X!=F@tJ!Kp!&E(V$E zWV>2Cdvw?_D~t*F)WOp!%RVrjpnn4s_q6wm$HbTcpSw$8H&_nH8;Bs*H+cqsh$9Zk z8{4rp6m_A|vPErmix49vxDZcdn=s&R_+rBo>Y28`!3R+g!LET9lnst}_6G#m1FG;s zEWOAZPHYKs7x}1pLKRXb9mm^QMP^6(?BGH<^@s1u^H>&4joUlN-IvVRLI2|7iiWDq zfkNb}O{!MLV(K;kD=qg0(`UuvaN`^H@c{A;2?&U*d{*&wcEd4Cl58U8ICUqyiB^u8u*q$3CWFo zg05xAVDkJM=;{^=*Y~j(mVQ(cQheCMh*3uuN~M+AL>k4IKdWJn(eaMba>^k2&Gp$ z62Ny^k^)BjytcMxnD_e3%`b~zo>(-i77J_PXJCq5U0waWD=T5Sx*)5tuzcewcFxyK z->Ud*C9zXH*$=L!k(OQS5#2|J*VnY)^>#k@@A+GR z{+Go50c8E$=!(i#AqiR_{e|W@o8$l)l>7QwW|5keLRi_SZ}=yOue2tU)}<`o2!IQq zC_!2JPg5)hwja1>tZHOnU+9*XoRE-LV?4yrdm(N`WLiPBE}W=OwITJiI8YvQ#` z(}C|tJbG4_0^i^*h-pKPZ(f)0WTQ5n?bv!eu>R=zB#FZfBpV;l@-0RupmQVj(Y%#l zu(U_QpBX%`p3({VFvMI||MIDzMuVlVreqSrrfK7n*B+z4d9Z`ECc7asF!n@sYTNS~ z=a<2VNV|caI@;8R(z1~qRw9@1f#TvNPHs_l-RX}Hznt`*xWsth19dQHH7Uy=4CZ`V z(nGGh({{`OaDDHH3=3{{wCDL<>+wSV#(J_y1ewGp|c!wvj%unDo~sm zg?UBn-n|G+vgP9Y#;jEpglx}+IWc96$hoKT}!v@+$@3Fdg} + + + TV Listings + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/browser history/libs/.DS_Store b/samples/browser history/libs/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0' + + _d.title.replace('\'', '\\\'') + ' + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/multi-device form factor/www/phonegap-1.4.1.js b/samples/multi-device form factor/www/phonegap-1.4.1.js new file mode 100644 index 0000000..680e180 --- /dev/null +++ b/samples/multi-device form factor/www/phonegap-1.4.1.js @@ -0,0 +1,4123 @@ +/* PhoneGap v1.4.1 */ +/* + 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. +*/ + + +/* + * Some base contributions + * Copyright (c) 2011, Proyectos Equis Ka, S.L. + */ + +if (typeof PhoneGap === "undefined") { + +if (typeof(DeviceInfo) !== 'object'){ + DeviceInfo = {}; +} +/** + * This represents the PhoneGap API itself, and provides a global namespace for accessing + * information about the state of PhoneGap. + * @class + */ +PhoneGap = { + // This queue holds the currently executing command and all pending + // commands executed with PhoneGap.exec(). + commandQueue: [], + // Indicates if we're currently in the middle of flushing the command + // queue on the native side. + commandQueueFlushing: false, + _constructors: [], + documentEventHandler: {}, // Collection of custom document event handlers + windowEventHandler: {} +}; + +/** + * List of resource files loaded by PhoneGap. + * This is used to ensure JS and other files are loaded only once. + */ +PhoneGap.resources = {base: true}; + +/** + * Determine if resource has been loaded by PhoneGap + * + * @param name + * @return + */ +PhoneGap.hasResource = function(name) { + return PhoneGap.resources[name]; +}; + +/** + * Add a resource to list of loaded resources by PhoneGap + * + * @param name + */ +PhoneGap.addResource = function(name) { + PhoneGap.resources[name] = true; +}; + +/** + * Boolean flag indicating if the PhoneGap API is available and initialized. + */ // TODO: Remove this, it is unused here ... -jm +PhoneGap.available = DeviceInfo.uuid != undefined; + +/** + * Add an initialization function to a queue that ensures it will run and initialize + * application constructors only once PhoneGap has been initialized. + * @param {Function} func The function callback you want run once PhoneGap is initialized + */ +PhoneGap.addConstructor = function(func) { + var state = document.readyState; + if ( ( state == 'loaded' || state == 'complete' ) && DeviceInfo.uuid != null ) + { + func(); + } + else + { + PhoneGap._constructors.push(func); + } +}; + +(function() + { + var timer = setInterval(function() + { + + var state = document.readyState; + + if ( ( state == 'loaded' || state == 'complete' ) && DeviceInfo.uuid != null ) + { + clearInterval(timer); // stop looking + // run our constructors list + while (PhoneGap._constructors.length > 0) + { + var constructor = PhoneGap._constructors.shift(); + try + { + constructor(); + } + catch(e) + { + if (typeof(console['log']) == 'function') + { + console.log("Failed to run constructor: " + console.processMessage(e)); + } + else + { + alert("Failed to run constructor: " + e.message); + } + } + } + // all constructors run, now fire the deviceready event + var e = document.createEvent('Events'); + e.initEvent('deviceready'); + document.dispatchEvent(e); + } + }, 1); +})(); + +// session id for calls +PhoneGap.sessionKey = 0; + +// centralized callbacks +PhoneGap.callbackId = 0; +PhoneGap.callbacks = {}; +PhoneGap.callbackStatus = { + NO_RESULT: 0, + OK: 1, + CLASS_NOT_FOUND_EXCEPTION: 2, + ILLEGAL_ACCESS_EXCEPTION: 3, + INSTANTIATION_EXCEPTION: 4, + MALFORMED_URL_EXCEPTION: 5, + IO_EXCEPTION: 6, + INVALID_ACTION: 7, + JSON_EXCEPTION: 8, + ERROR: 9 + }; + +/** + * Creates a gap bridge iframe used to notify the native code about queued + * commands. + * + * @private + */ +PhoneGap.createGapBridge = function() { + gapBridge = document.createElement("iframe"); + gapBridge.setAttribute("style", "display:none;"); + gapBridge.setAttribute("height","0px"); + gapBridge.setAttribute("width","0px"); + gapBridge.setAttribute("frameborder","0"); + document.documentElement.appendChild(gapBridge); + return gapBridge; +} + +/** + * Execute a PhoneGap command by queuing it and letting the native side know + * there are queued commands. The native side will then request all of the + * queued commands and execute them. + * + * Arguments may be in one of two formats: + * + * FORMAT ONE (preferable) + * The native side will call PhoneGap.callbackSuccess or + * PhoneGap.callbackError, depending upon the result of the action. + * + * @param {Function} success The success callback + * @param {Function} fail The fail callback + * @param {String} service The name of the service to use + * @param {String} action The name of the action to use + * @param {String[]} [args] Zero or more arguments to pass to the method + * + * FORMAT TWO + * @param {String} command Command to be run in PhoneGap, e.g. + * "ClassName.method" + * @param {String[]} [args] Zero or more arguments to pass to the method + * object parameters are passed as an array object + * [object1, object2] each object will be passed as + * JSON strings + */ +PhoneGap.exec = function() { + if (!PhoneGap.available) { + alert("ERROR: Attempting to call PhoneGap.exec()" + +" before 'deviceready'. Ignoring."); + return; + } + + var successCallback, failCallback, service, action, actionArgs; + var callbackId = null; + if (typeof arguments[0] !== "string") { + // FORMAT ONE + successCallback = arguments[0]; + failCallback = arguments[1]; + service = arguments[2]; + action = arguments[3]; + actionArgs = arguments[4]; + + // Since we need to maintain backwards compatibility, we have to pass + // an invalid callbackId even if no callback was provided since plugins + // will be expecting it. The PhoneGap.exec() implementation allocates + // an invalid callbackId and passes it even if no callbacks were given. + callbackId = 'INVALID'; + } else { + // FORMAT TWO + splitCommand = arguments[0].split("."); + action = splitCommand.pop(); + service = splitCommand.join("."); + actionArgs = Array.prototype.splice.call(arguments, 1); + } + + // Start building the command object. + var command = { + className: service, + methodName: action, + arguments: [] + }; + + // Register the callbacks and add the callbackId to the positional + // arguments if given. + if (successCallback || failCallback) { + callbackId = service + PhoneGap.callbackId++; + PhoneGap.callbacks[callbackId] = + {success:successCallback, fail:failCallback}; + } + if (callbackId != null) { + command.arguments.push(callbackId); + } + + for (var i = 0; i < actionArgs.length; ++i) { + var arg = actionArgs[i]; + if (arg == undefined || arg == null) { + continue; + } else if (typeof(arg) == 'object') { + command.options = arg; + } else { + command.arguments.push(arg); + } + } + + // Stringify and queue the command. We stringify to command now to + // effectively clone the command arguments in case they are mutated before + // the command is executed. + PhoneGap.commandQueue.push(JSON.stringify(command)); + + // If the queue length is 1, then that means it was empty before we queued + // the given command, so let the native side know that we have some + // commands to execute, unless the queue is currently being flushed, in + // which case the command will be picked up without notification. + if (PhoneGap.commandQueue.length == 1 && !PhoneGap.commandQueueFlushing) { + if (!PhoneGap.gapBridge) { + PhoneGap.gapBridge = PhoneGap.createGapBridge(); + } + + PhoneGap.gapBridge.src = "gap://ready"; + } +} + +/** + * Called by native code to retrieve all queued commands and clear the queue. + */ +PhoneGap.getAndClearQueuedCommands = function() { + json = JSON.stringify(PhoneGap.commandQueue); + PhoneGap.commandQueue = []; + return json; +} + +/** + * Called by native code when returning successful result from an action. + * + * @param callbackId + * @param args + * args.status - PhoneGap.callbackStatus + * args.message - return value + * args.keepCallback - 0 to remove callback, 1 to keep callback in PhoneGap.callbacks[] + */ +PhoneGap.callbackSuccess = function(callbackId, args) { + if (PhoneGap.callbacks[callbackId]) { + + // If result is to be sent to callback + if (args.status == PhoneGap.callbackStatus.OK) { + try { + if (PhoneGap.callbacks[callbackId].success) { + PhoneGap.callbacks[callbackId].success(args.message); + } + } + catch (e) { + console.log("Error in success callback: "+callbackId+" = "+e); + } + } + + // Clear callback if not expecting any more results + if (!args.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } +}; + +/** + * Called by native code when returning error result from an action. + * + * @param callbackId + * @param args + */ +PhoneGap.callbackError = function(callbackId, args) { + if (PhoneGap.callbacks[callbackId]) { + try { + if (PhoneGap.callbacks[callbackId].fail) { + PhoneGap.callbacks[callbackId].fail(args.message); + } + } + catch (e) { + console.log("Error in error callback: "+callbackId+" = "+e); + } + + // Clear callback if not expecting any more results + if (!args.keepCallback) { + delete PhoneGap.callbacks[callbackId]; + } + } +}; + + +/** + * Does a deep clone of the object. + * + * @param obj + * @return + */ +PhoneGap.clone = function(obj) { + if(!obj) { + return obj; + } + + if(obj instanceof Array){ + var retVal = new Array(); + for(var i = 0; i < obj.length; ++i){ + retVal.push(PhoneGap.clone(obj[i])); + } + return retVal; + } + + if (obj instanceof Function) { + return obj; + } + + if(!(obj instanceof Object)){ + return obj; + } + + if (obj instanceof Date) { + return obj; + } + + retVal = new Object(); + for(i in obj){ + if(!(i in retVal) || retVal[i] != obj[i]) { + retVal[i] = PhoneGap.clone(obj[i]); + } + } + return retVal; +}; + +// Intercept calls to document.addEventListener +PhoneGap.m_document_addEventListener = document.addEventListener; + +// Intercept calls to window.addEventListener +PhoneGap.m_window_addEventListener = window.addEventListener; + +/** + * Add a custom window event handler. + * + * @param {String} event The event name that callback handles + * @param {Function} callback The event handler + */ +PhoneGap.addWindowEventHandler = function(event, callback) { + PhoneGap.windowEventHandler[event] = callback; +} + +/** + * Add a custom document event handler. + * + * @param {String} event The event name that callback handles + * @param {Function} callback The event handler + */ +PhoneGap.addDocumentEventHandler = function(event, callback) { + PhoneGap.documentEventHandler[event] = callback; +} + +/** + * Intercept adding document event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +document.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If subscribing to an event that is handled by a plugin + if (typeof PhoneGap.documentEventHandler[e] !== "undefined") { + if (PhoneGap.documentEventHandler[e](e, handler, true)) { + return; // Stop default behavior + } + } + + PhoneGap.m_document_addEventListener.call(document, evt, handler, capture); +}; + +/** + * Intercept adding window event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +window.addEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If subscribing to an event that is handled by a plugin + if (typeof PhoneGap.windowEventHandler[e] !== "undefined") { + if (PhoneGap.windowEventHandler[e](e, handler, true)) { + return; // Stop default behavior + } + } + + PhoneGap.m_window_addEventListener.call(window, evt, handler, capture); +}; + +// Intercept calls to document.removeEventListener and watch for events that +// are generated by PhoneGap native code +PhoneGap.m_document_removeEventListener = document.removeEventListener; + +// Intercept calls to window.removeEventListener +PhoneGap.m_window_removeEventListener = window.removeEventListener; + +/** + * Intercept removing document event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +document.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If unsubcribing from an event that is handled by a plugin + if (typeof PhoneGap.documentEventHandler[e] !== "undefined") { + if (PhoneGap.documentEventHandler[e](e, handler, false)) { + return; // Stop default behavior + } + } + + PhoneGap.m_document_removeEventListener.call(document, evt, handler, capture); +}; + +/** + * Intercept removing window event listeners and handle our own + * + * @param {Object} evt + * @param {Function} handler + * @param capture + */ +window.removeEventListener = function(evt, handler, capture) { + var e = evt.toLowerCase(); + + // If unsubcribing from an event that is handled by a plugin + if (typeof PhoneGap.windowEventHandler[e] !== "undefined") { + if (PhoneGap.windowEventHandler[e](e, handler, false)) { + return; // Stop default behavior + } + } + + PhoneGap.m_window_removeEventListener.call(window, evt, handler, capture); +}; + +/** + * Method to fire document event + * + * @param {String} type The event type to fire + * @param {Object} data Data to send with event + */ +PhoneGap.fireDocumentEvent = function(type, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + document.dispatchEvent(e); +}; + +/** + * Method to fire window event + * + * @param {String} type The event type to fire + * @param {Object} data Data to send with event + */ +PhoneGap.fireWindowEvent = function(type, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + window.dispatchEvent(e); +}; + +/** + * Method to fire event from native code + * Leaving this generic version to handle problems with iOS 3.x. Is currently used by orientation and battery events + * Remove when iOS 3.x no longer supported and call fireWindowEvent or fireDocumentEvent directly + */ +PhoneGap.fireEvent = function(type, target, data) { + var e = document.createEvent('Events'); + e.initEvent(type); + if (data) { + for (var i in data) { + e[i] = data[i]; + } + } + target = target || document; + if (target.dispatchEvent === undefined) { // ie window.dispatchEvent is undefined in iOS 3.x + target = document; + } + + target.dispatchEvent(e); +}; +/** + * Create a UUID + * + * @return + */ +PhoneGap.createUUID = function() { + return PhoneGap.UUIDcreatePart(4) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(2) + '-' + + PhoneGap.UUIDcreatePart(6); +}; + +PhoneGap.UUIDcreatePart = function(length) { + var uuidpart = ""; + for (var i=0; i -1) { + me._batteryListener.splice(pos, 1); + } + } else if (eventType === "batterylow") { + var pos = me._lowListener.indexOf(handler); + if (pos > -1) { + me._lowListener.splice(pos, 1); + } + } else if (eventType === "batterycritical") { + var pos = me._criticalListener.indexOf(handler); + if (pos > -1) { + me._criticalListener.splice(pos, 1); + } + } + + // If there are no more registered event listeners stop the battery listener on native side. + if (me._batteryListener.length === 0 && me._lowListener.length === 0 && me._criticalListener.length === 0) { + PhoneGap.exec(null, null, "com.phonegap.battery", "stop", []); + } + } +}; + +/** + * Callback for battery status + * + * @param {Object} info keys: level, isPlugged + */ +Battery.prototype._status = function(info) { + if (info) { + var me = this; + if (me._level != info.level || me._isPlugged != info.isPlugged) { + // Fire batterystatus event + //PhoneGap.fireWindowEvent("batterystatus", info); + // use this workaround since iOS 3.x does have window.dispatchEvent + PhoneGap.fireEvent("batterystatus", window, info); + + // Fire low battery event + if (info.level == 20 || info.level == 5) { + if (info.level == 20) { + //PhoneGap.fireWindowEvent("batterylow", info); + // use this workaround since iOS 3.x does not have window.dispatchEvent + PhoneGap.fireEvent("batterylow", window, info); + } + else { + //PhoneGap.fireWindowEvent("batterycritical", info); + // use this workaround since iOS 3.x does not have window.dispatchEvent + PhoneGap.fireEvent("batterycritical", window, info); + } + } + } + me._level = info.level; + me._isPlugged = info.isPlugged; + } +}; + +/** + * Error callback for battery start + */ +Battery.prototype._error = function(e) { + console.log("Error initializing Battery: " + e); +}; + +PhoneGap.addConstructor(function() { + if (typeof navigator.battery === "undefined") { + navigator.battery = new Battery(); + PhoneGap.addWindowEventHandler("batterystatus", navigator.battery.eventHandler); + PhoneGap.addWindowEventHandler("batterylow", navigator.battery.eventHandler); + PhoneGap.addWindowEventHandler("batterycritical", navigator.battery.eventHandler); + } +}); +}if (!PhoneGap.hasResource("camera")) { + PhoneGap.addResource("camera"); + + +/** + * This class provides access to the device camera. + * @constructor + */ +Camera = function() { + +} +/** + * Available Camera Options + * {boolean} allowEdit - true to allow editing image, default = false + * {number} quality 0-100 (low to high) default = 100 + * {Camera.DestinationType} destinationType default = DATA_URL + * {Camera.PictureSourceType} sourceType default = CAMERA + * {number} targetWidth - width in pixels to scale image default = 0 (no scaling) + * {number} targetHeight - height in pixels to scale image default = 0 (no scaling) + * {Camera.EncodingType} - encodingType default = JPEG + * {boolean} correctOrientation - Rotate the image to correct for the orientation of the device during capture (iOS only) + * {boolean} saveToPhotoAlbum - Save the image to the photo album on the device after capture (iOS only) + */ +/** + * Format of image that is returned from getPicture. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY}) + */ +Camera.DestinationType = { + DATA_URL: 0, // Return base64 encoded string + FILE_URI: 1 // Return file uri +}; +Camera.prototype.DestinationType = Camera.DestinationType; + +/** + * Source to getPicture from. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY}) + */ +Camera.PictureSourceType = { + PHOTOLIBRARY : 0, // Choose image from picture library + CAMERA : 1, // Take picture from camera + SAVEDPHOTOALBUM : 2 // Choose image from picture library +}; +Camera.prototype.PictureSourceType = Camera.PictureSourceType; + +/** + * Encoding of image returned from getPicture. + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.CAMERA, + * encodingType: Camera.EncodingType.PNG}) + */ +Camera.EncodingType = { + JPEG: 0, // Return JPEG encoded image + PNG: 1 // Return PNG encoded image +}; +Camera.prototype.EncodingType = Camera.EncodingType; + +/** + * Type of pictures to select from. Only applicable when + * PictureSourceType is PHOTOLIBRARY or SAVEDPHOTOALBUM + * + * Example: navigator.camera.getPicture(success, fail, + * { quality: 80, + * destinationType: Camera.DestinationType.DATA_URL, + * sourceType: Camera.PictureSourceType.PHOTOLIBRARY, + * mediaType: Camera.MediaType.PICTURE}) + */ +Camera.MediaType = { + PICTURE: 0, // allow selection of still pictures only. DEFAULT. Will return format specified via DestinationType + VIDEO: 1, // allow selection of video only, ONLY RETURNS URL + ALLMEDIA : 2 // allow selection from all media types +}; +Camera.prototype.MediaType = Camera.MediaType; + +/** + * Gets a picture from source defined by "options.sourceType", and returns the + * image as defined by the "options.destinationType" option. + + * The defaults are sourceType=CAMERA and destinationType=DATA_URL. + * + * @param {Function} successCallback + * @param {Function} errorCallback + * @param {Object} options + */ +Camera.prototype.getPicture = function(successCallback, errorCallback, options) { + // successCallback required + if (typeof successCallback != "function") { + console.log("Camera Error: successCallback is not a function"); + return; + } + + // errorCallback optional + if (errorCallback && (typeof errorCallback != "function")) { + console.log("Camera Error: errorCallback is not a function"); + return; + } + + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.camera","getPicture",[options]); +}; + + + +PhoneGap.addConstructor(function() { + if (typeof navigator.camera == "undefined") navigator.camera = new Camera(); +}); +}; + +if (!PhoneGap.hasResource("device")) { + PhoneGap.addResource("device"); + +/** + * this represents the mobile device, and provides properties for inspecting the model, version, UUID of the + * phone, etc. + * @constructor + */ +Device = function() +{ + this.platform = null; + this.version = null; + this.name = null; + this.phonegap = null; + this.uuid = null; + try + { + this.platform = DeviceInfo.platform; + this.version = DeviceInfo.version; + this.name = DeviceInfo.name; + this.phonegap = DeviceInfo.gap; + this.uuid = DeviceInfo.uuid; + + } + catch(e) + { + // TODO: + } + this.available = PhoneGap.available = this.uuid != null; +} + +PhoneGap.addConstructor(function() { + if (typeof navigator.device === "undefined") { + navigator.device = window.device = new Device(); + } +}); +}; +if (!PhoneGap.hasResource("capture")) { + PhoneGap.addResource("capture"); +/** + * The CaptureError interface encapsulates all errors in the Capture API. + */ +function CaptureError() { + this.code = null; +}; + +// Capture error codes +CaptureError.CAPTURE_INTERNAL_ERR = 0; +CaptureError.CAPTURE_APPLICATION_BUSY = 1; +CaptureError.CAPTURE_INVALID_ARGUMENT = 2; +CaptureError.CAPTURE_NO_MEDIA_FILES = 3; +CaptureError.CAPTURE_NOT_SUPPORTED = 20; + +/** + * The Capture interface exposes an interface to the camera and microphone of the hosting device. + */ +function Capture() { + this.supportedAudioModes = []; + this.supportedImageModes = []; + this.supportedVideoModes = []; +}; + +/** + * Launch audio recorder application for recording audio clip(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureAudioOptions} options + * + * No audio recorder to launch for iOS - return CAPTURE_NOT_SUPPORTED + */ +Capture.prototype.captureAudio = function(successCallback, errorCallback, options) { + /*if (errorCallback && typeof errorCallback === "function") { + errorCallback({ + "code": CaptureError.CAPTURE_NOT_SUPPORTED + }); + }*/ + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.mediacapture", "captureAudio", [options]); +}; + +/** + * Launch camera application for taking image(s). + * + * @param {Function} successCB + * @param {Function} errorCB + * @param {CaptureImageOptions} options + */ +Capture.prototype.captureImage = function(successCallback, errorCallback, options) { + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.mediacapture", "captureImage", [options]); +}; + +/** + * Casts a PluginResult message property (array of objects) to an array of MediaFile objects + * (used in Objective-C) + * + * @param {PluginResult} pluginResult + */ +Capture.prototype._castMediaFile = function(pluginResult) { + var mediaFiles = []; + var i; + for (i=0; i} categories +* @param {ContactField[]} urls contact's web sites +*/ +var Contact = function(id, displayName, name, nickname, phoneNumbers, emails, addresses, + ims, organizations, birthday, note, photos, categories, urls) { + this.id = id || null; + this.displayName = displayName || null; + this.name = name || null; // ContactName + this.nickname = nickname || null; + this.phoneNumbers = phoneNumbers || null; // ContactField[] + this.emails = emails || null; // ContactField[] + this.addresses = addresses || null; // ContactAddress[] + this.ims = ims || null; // ContactField[] + this.organizations = organizations || null; // ContactOrganization[] + this.birthday = birthday || null; // JS Date + this.note = note || null; + this.photos = photos || null; // ContactField[] + this.categories = categories || null; + this.urls = urls || null; // ContactField[] +}; + +/** +* Converts Dates to milliseconds before sending to iOS +*/ +Contact.prototype.convertDatesOut = function() +{ + var dates = new Array("birthday"); + for (var i=0; i][;base64], + * + * @param file {File} File object containing file properties + */ +FileReader.prototype.readAsDataURL = function(file) { + this.fileName = ""; + + if (typeof file.fullPath === "undefined") { + this.fileName = file; + } else { + this.fileName = file.fullPath; + } + + // LOADING state + this.readyState = FileReader.LOADING; + + // If loadstart callback + if (typeof this.onloadstart === "function") { + var evt = File._createEvent("loadstart", this); + this.onloadstart(evt); + } + + var me = this; + + // Read file + navigator.fileMgr.readAsDataURL(this.fileName, + + // Success callback + function(r) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileReader.DONE) { + return; + } + + // Save result + me.result = r; + + // If onload callback + if (typeof me.onload === "function") { + evt = File._createEvent("load", me); + me.onload(evt); + } + + // DONE state + me.readyState = FileReader.DONE; + + // If onloadend callback + if (typeof me.onloadend === "function") { + evt = File._createEvent("loadend", me); + me.onloadend(evt); + } + }, + + // Error callback + function(e) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileReader.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileReader.DONE; + + // If onloadend callback + if (typeof me.onloadend === "function") { + evt = File._createEvent("loadend", me); + me.onloadend(evt); + } + } + ); +}; + +/** + * Read file and return data as a binary data. + * + * @param file The name of the file + */ +FileReader.prototype.readAsBinaryString = function(file) { + // TODO - Can't return binary data to browser. + this.fileName = file; +}; + +/** + * Read file and return data as a binary data. + * + * @param file The name of the file + */ +FileReader.prototype.readAsArrayBuffer = function(file) { + // TODO - Can't return binary data to browser. + this.fileName = file; +}; + +//----------------------------------------------------------------------------- +// File Writer +//----------------------------------------------------------------------------- + +/** + * This class writes to the mobile device file system. + * + @param file {File} a File object representing a file on the file system +*/ +FileWriter = function(file) { + this.fileName = ""; + this.length = 0; + if (file) { + this.fileName = file.fullPath || file; + this.length = file.size || 0; + } + + // default is to write at the beginning of the file + this.position = 0; + + this.readyState = 0; // EMPTY + + this.result = null; + + // Error + this.error = null; + + // Event handlers + this.onwritestart = null; // When writing starts + this.onprogress = null; // While writing the file, and reporting partial file data + this.onwrite = null; // When the write has successfully completed. + this.onwriteend = null; // When the request has completed (either in success or failure). + this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method. + this.onerror = null; // When the write has failed (see errors). +} + +// States +FileWriter.INIT = 0; +FileWriter.WRITING = 1; +FileWriter.DONE = 2; + +/** + * Abort writing file. + */ +FileWriter.prototype.abort = function() { + // check for invalid state + if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) { + throw FileError.INVALID_STATE_ERR; + } + + // set error + var error = new FileError(), evt; + error.code = error.ABORT_ERR; + this.error = error; + + // If error callback + if (typeof this.onerror === "function") { + evt = File._createEvent("error", this); + this.onerror(evt); + } + // If abort callback + if (typeof this.onabort === "function") { + evt = File._createEvent("abort", this); + this.onabort(evt); + } + + this.readyState = FileWriter.DONE; + + // If write end callback + if (typeof this.onwriteend == "function") { + evt = File._createEvent("writeend", this); + this.onwriteend(evt); + } +}; + +/** + * @Deprecated: use write instead + * + * @param file to write the data to + * @param text to be written + * @param bAppend if true write to end of file, otherwise overwrite the file + */ +FileWriter.prototype.writeAsText = function(file, text, bAppend) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + if (bAppend !== true) { + bAppend = false; // for null values + } + + this.fileName = file; + + // WRITING state + this.readyState = FileWriter.WRITING; + + var me = this; + + // If onwritestart callback + if (typeof me.onwritestart === "function") { + var evt = File._createEvent("writestart", me); + me.onwritestart(evt); + } + + + // Write file + navigator.fileMgr.writeAsText(file, text, bAppend, + // Success callback + function(r) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save result + me.result = r; + + // If onwrite callback + if (typeof me.onwrite === "function") { + evt = File._createEvent("write", me); + me.onwrite(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + }, + + // Error callback + function(e) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + } + ); +}; + +/** + * Writes data to the file + * + * @param text to be written + */ +FileWriter.prototype.write = function(text) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + // WRITING state + this.readyState = FileWriter.WRITING; + + var me = this; + + // If onwritestart callback + if (typeof me.onwritestart === "function") { + var evt = File._createEvent("writestart", me); + me.onwritestart(evt); + } + + // Write file + navigator.fileMgr.write(this.fileName, text, this.position, + + // Success callback + function(r) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + + // position always increases by bytes written because file would be extended + me.position += r; + // The length of the file is now where we are done writing. + me.length = me.position; + + // If onwrite callback + if (typeof me.onwrite === "function") { + evt = File._createEvent("write", me); + me.onwrite(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + }, + + // Error callback + function(e) { + var evt; + + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + } + ); + +}; + +/** + * Moves the file pointer to the location specified. + * + * If the offset is a negative number the position of the file + * pointer is rewound. If the offset is greater than the file + * size the position is set to the end of the file. + * + * @param offset is the location to move the file pointer to. + */ +FileWriter.prototype.seek = function(offset) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + + if (!offset) { + return; + } + + // See back from end of file. + if (offset < 0) { + this.position = Math.max(offset + this.length, 0); + } + // Offset is bigger then file size so set position + // to the end of the file. + else if (offset > this.length) { + this.position = this.length; + } + // Offset is between 0 and file size so set the position + // to start writing. + else { + this.position = offset; + } +}; + +/** + * Truncates the file to the size specified. + * + * @param size to chop the file at. + */ +FileWriter.prototype.truncate = function(size) { + // Throw an exception if we are already writing a file + if (this.readyState === FileWriter.WRITING) { + throw FileError.INVALID_STATE_ERR; + } + // what if no size specified? + + // WRITING state + this.readyState = FileWriter.WRITING; + + var me = this; + + // If onwritestart callback + if (typeof me.onwritestart === "function") { + var evt = File._createEvent("writestart", me); + me.onwritestart(evt); + } + + // Write file + navigator.fileMgr.truncate(this.fileName, size, + + // Success callback + function(r) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Update the length of the file + me.length = r; + me.position = Math.min(me.position, r); + + // If onwrite callback + if (typeof me.onwrite === "function") { + evt = File._createEvent("write", me); + me.onwrite(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + }, + + // Error callback + function(e) { + var evt; + // If DONE (cancelled), then don't do anything + if (me.readyState === FileWriter.DONE) { + return; + } + + // Save error + me.error = e; + + // If onerror callback + if (typeof me.onerror === "function") { + evt = File._createEvent("error", me); + me.onerror(evt); + } + + // DONE state + me.readyState = FileWriter.DONE; + + // If onwriteend callback + if (typeof me.onwriteend === "function") { + evt = File._createEvent("writeend", me); + me.onwriteend(evt); + } + } + ); +}; + +LocalFileSystem = function() { +}; + +// File error codes +LocalFileSystem.TEMPORARY = 0; +LocalFileSystem.PERSISTENT = 1; +LocalFileSystem.RESOURCE = 2; +LocalFileSystem.APPLICATION = 3; + +/** + * Requests a filesystem in which to store application data. + * + * @param {int} type of file system being requested + * @param {Function} successCallback is called with the new FileSystem + * @param {Function} errorCallback is called with a FileError + */ +LocalFileSystem.prototype.requestFileSystem = function(type, size, successCallback, errorCallback) { + if (type < 0 || type > 3) { + if (typeof errorCallback == "function") { + errorCallback({ + "code": FileError.SYNTAX_ERR + }); + } + } + else { + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.file", "requestFileSystem", [type, size]); + } +}; + +/** + * + * @param {DOMString} uri referring to a local file in a filesystem + * @param {Function} successCallback is called with the new entry + * @param {Function} errorCallback is called with a FileError + */ +LocalFileSystem.prototype.resolveLocalFileSystemURI = function(uri, successCallback, errorCallback) { + PhoneGap.exec(successCallback, errorCallback, "com.phonegap.file", "resolveLocalFileSystemURI", [uri]); +}; + +/** +* This function is required as we need to convert raw +* JSON objects into concrete File and Directory objects. +* +* @param a JSON Objects that need to be converted to DirectoryEntry or FileEntry objects. +* @returns an entry +*/ +LocalFileSystem.prototype._castFS = function(pluginResult) { + var entry = null; + entry = new DirectoryEntry(); + entry.isDirectory = pluginResult.message.root.isDirectory; + entry.isFile = pluginResult.message.root.isFile; + entry.name = pluginResult.message.root.name; + entry.fullPath = pluginResult.message.root.fullPath; + pluginResult.message.root = entry; + return pluginResult; +} + +LocalFileSystem.prototype._castEntry = function(pluginResult) { + var entry = null; + if (pluginResult.message.isDirectory) { + entry = new DirectoryEntry(); + } + else if (pluginResult.message.isFile) { + entry = new FileEntry(); + } + entry.isDirectory = pluginResult.message.isDirectory; + entry.isFile = pluginResult.message.isFile; + entry.name = pluginResult.message.name; + entry.fullPath = pluginResult.message.fullPath; + pluginResult.message = entry; + return pluginResult; +} + +LocalFileSystem.prototype._castEntries = function(pluginResult) { + var entries = pluginResult.message; + var retVal = []; + for (i=0; i