12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955 |
- /**
- * SQL proxy lets you store data in a SQL database.
- * The Sencha Touch SQL proxy outputs model data into an HTML5
- * local database using WebSQL.
- *
- * You can create a Store for the proxy, for example:
- *
- * Ext.require(["Ext.data.proxy.SQL"]);
- *
- * Ext.define("User", {
- * extend: "Ext.data.Model",
- * config: {
- * fields: [ "firstName", "lastName" ]
- * }
- * });
- *
- * Ext.create("Ext.data.Store", {
- * model: "User",
- * storeId: "Users",
- * proxy: {
- * type: "sql"
- * }
- * });
- *
- * Ext.getStore("Users").add({
- * firstName: "Polly",
- * lastName: "Hedra"
- * });
- *
- * Ext.getStore("Users").sync();
- *
- * To destroy a table use:
- *
- * Ext.getStore("Users").getProxy().dropTable();
- *
- * To recreate a table use:
- *
- * Ext.data.Store.sync() or Ext.data.Model.save()
- */
- Ext.define('Ext.data.proxy.Sql', {
- alias: 'proxy.sql',
- extend: 'Ext.data.proxy.Client',
- alternateClassName: 'Ext.data.proxy.SQL',
- isSQLProxy: true,
- config: {
- /**
- * @cfg {Object} reader
- * @hide
- */
- reader: null,
- /**
- * @cfg {Object} writer
- * @hide
- */
- writer: null,
- /**
- * @cfg {String} table
- * Optional Table name to use if not provided ModelName will be used
- */
- table: null,
- /**
- * @cfg {String} database
- * Database name to access tables from
- */
- database: 'Sencha'
- },
- _createOptions: {
- silent: true,
- dirty: false
- },
- updateModel: function(model) {
- var me = this,
- modelName, len, i, columns, quoted;
- if (model) {
- me.uniqueIdStrategy = model.identifier.isUnique;
- if (!me.getTable()) {
- modelName = model.entityName;
- me.setTable(modelName.slice(modelName.lastIndexOf('.') + 1));
- }
- me.columns = columns = me.getPersistedModelColumns(model);
- me.quotedColumns = quoted = [];
- for (i = 0 , len = columns.length; i < len; ++i) {
- quoted.push('"' + columns[i] + '"');
- }
- }
- me.callParent([
- model
- ]);
- },
- setException: function(operation, error) {
- operation.setException(error);
- },
- create: function(operation) {
- var me = this,
- records = operation.getRecords(),
- result, error;
- operation.setStarted();
- me.executeTransaction(function(transaction) {
- me.insertRecords(records, transaction, function(resultSet, statementError) {
- result = resultSet;
- error = statementError;
- });
- }, function(transactionError) {
- operation.setException(transactionError);
- }, function() {
- if (error) {
- operation.setException(statementError);
- } else {
- operation.process(result);
- }
- });
- },
- read: function(operation) {
- var me = this,
- model = me.getModel(),
- records = operation.getRecords(),
- record = records ? records[0] : null,
- result, error, id, params;
- if (record && !record.phantom) {
- id = record.getId();
- } else {
- id = operation.getId();
- }
- if (id !== undefined) {
- params = {
- idOnly: true,
- id: id
- };
- } else {
- params = {
- page: operation.getPage(),
- start: operation.getStart(),
- limit: operation.getLimit(),
- sorters: operation.getSorters(),
- filters: operation.getFilters()
- };
- }
- operation.setStarted();
- me.executeTransaction(function(transaction) {
- me.selectRecords(transaction, params, function(resultSet, statementError) {
- result = resultSet;
- error = statementError;
- });
- }, function(transactionError) {
- operation.setException(transactionError);
- }, function() {
- if (error) {
- operation.setException(statementError);
- } else {
- operation.process(result);
- }
- });
- },
- update: function(operation) {
- var me = this,
- records = operation.getRecords(),
- result, error;
- operation.setStarted();
- me.executeTransaction(function(transaction) {
- me.updateRecords(transaction, records, function(resultSet, statementError) {
- result = resultSet;
- error = statementError;
- });
- }, function(transactionError) {
- operation.setException(transactionError);
- }, function() {
- if (error) {
- operation.setException(statementError);
- } else {
- operation.process(result);
- }
- });
- },
- erase: function(operation) {
- var me = this,
- records = operation.getRecords(),
- result, error;
- operation.setStarted();
- me.executeTransaction(function(transaction) {
- me.destroyRecords(transaction, records, function(resultSet, statementError) {
- result = resultSet;
- error = statementError;
- });
- }, function(transactionError) {
- operation.setException(transactionError);
- }, function() {
- if (error) {
- operation.setException(error);
- } else {
- operation.process(result);
- }
- });
- },
- createTable: function(transaction) {
- var me = this;
- if (!transaction) {
- me.executeTransaction(function(transaction) {
- me.createTable(transaction);
- });
- return;
- }
- me.executeStatement(transaction, 'CREATE TABLE IF NOT EXISTS "' + me.getTable() + '" (' + me.getSchemaString() + ')', function() {
- me.tableExists = true;
- });
- },
- insertRecords: function(records, transaction, callback) {
- var me = this,
- columns = me.columns,
- totalRecords = records.length,
- executed = 0,
- uniqueIdStrategy = me.uniqueIdStrategy,
- setOptions = me._createOptions,
- len = records.length,
- i, record, placeholders, sql, data, values, errors, completeIf;
- completeIf = function(transaction) {
- ++executed;
- if (executed === totalRecords) {
- callback.call(me, new Ext.data.ResultSet({
- success: !errors
- }), errors);
- }
- };
- placeholders = Ext.String.repeat('?', columns.length, ',');
- sql = 'INSERT INTO "' + me.getTable() + '" (' + me.quotedColumns.join(',') + ') VALUES (' + placeholders + ')';
- for (i = 0; i < len; ++i) {
- record = records[i];
- data = me.getRecordData(record);
- values = me.getColumnValues(columns, data);
- // Capture the record in closure scope so we can access it later
- (function(record) {
- me.executeStatement(transaction, sql, values, function(transaction, resultSet) {
- if (!uniqueIdStrategy) {
- record.setId(resultSet.insertId, setOptions);
- }
- completeIf();
- }, function(transaction, error) {
- if (!errors) {
- errors = [];
- }
- errors.push(error);
- completeIf();
- });
- })(record);
- }
- },
- selectRecords: function(transaction, params, callback, scope) {
- var me = this,
- Model = me.getModel(),
- idProperty = Model.idProperty,
- sql = 'SELECT * FROM "' + me.getTable() + '"',
- filterStatement = ' WHERE ',
- sortStatement = ' ORDER BY ',
- values = [],
- sorters, filters, placeholder, i, len, result, filter, sorter, property, operator, value;
- if (params.idOnly) {
- sql += filterStatement + '"' + idProperty + '" = ?';
- values.push(params);
- } else {
- filters = params.filters;
- len = filters && filters.length;
- if (len) {
- for (i = 0; i < len; i++) {
- filter = filters[i];
- property = filter.getProperty();
- value = me.toSqlValue(filter.getValue(), Model.getField(property));
- operator = filter.getOperator();
- if (property !== null) {
- operator = operator || '=';
- placeholder = '?';
- if (operator === 'like' || (operator === '=' && filter.getAnyMatch())) {
- operator = 'LIKE';
- value = '%' + value + '%';
- }
- if (operator === 'in' || operator === 'notin') {
- if (operator === 'notin') {
- operator = 'not in';
- }
- placeholder = '(' + Ext.String.repeat('?', value.length, ',') + ')';
- values = values.concat(value);
- } else {
- values.push(value);
- }
- sql += filterStatement + '"' + property + '" ' + operator + ' ' + placeholder;
- filterStatement = ' AND ';
- }
- }
- }
- sorters = params.sorters;
- len = sorters && sorters.length;
- if (len) {
- for (i = 0; i < len; i++) {
- sorter = sorters[i];
- property = sorter.getProperty();
- if (property !== null) {
- sql += sortStatement + '"' + property + '" ' + sorter.getDirection();
- sortStatement = ', ';
- }
- }
- }
- // handle start, limit, sort, filter and group params
- if (params.page !== undefined) {
- sql += ' LIMIT ' + parseInt(params.start, 10) + ', ' + parseInt(params.limit, 10);
- }
- }
- me.executeStatement(transaction, sql, values, function(transaction, resultSet) {
- var rows = resultSet.rows,
- count = rows.length,
- records = [],
- fields = Model.fields,
- fieldsLen = fields.length,
- raw, data, i, len, j, field, name;
- for (i = 0 , len = count; i < len; ++i) {
- raw = rows.item(i);
- data = {};
- for (j = 0; j < fieldsLen; ++j) {
- field = fields[j];
- name = field.name;
- data[name] = me.fromSqlValue(raw[name], field);
- }
- records.push(new Model(data));
- }
- callback.call(me, new Ext.data.ResultSet({
- records: records,
- success: true,
- total: count,
- count: count
- }));
- }, function(transaction, error) {
- callback.call(me, new Ext.data.ResultSet({
- success: false,
- total: 0,
- count: 0
- }), error);
- });
- },
- updateRecords: function(transaction, records, callback) {
- var me = this,
- columns = me.columns,
- quotedColumns = me.quotedColumns,
- totalRecords = records.length,
- executed = 0,
- updates = [],
- setOptions = me._createOptions,
- len, i, record, placeholders, sql, data, values, errors, completeIf;
- completeIf = function(transaction) {
- ++executed;
- if (executed === totalRecords) {
- callback.call(me, new Ext.data.ResultSet({
- success: !errors
- }), errors);
- }
- };
- for (i = 0 , len = quotedColumns.length; i < len; i++) {
- updates.push(quotedColumns[i] + ' = ?');
- }
- sql = 'UPDATE "' + me.getTable() + '" SET ' + updates.join(', ') + ' WHERE "' + me.getModel().idProperty + '" = ?';
- for (i = 0 , len = records.length; i < len; ++i) {
- record = records[i];
- data = me.getRecordData(record);
- values = me.getColumnValues(columns, data);
- values.push(record.getId());
- // Capture the record in closure scope so we can access it later
- (function(record) {
- me.executeStatement(transaction, sql, values, function(transaction, resultSet) {
- completeIf();
- }, function(transaction, error) {
- if (!errors) {
- errors = [];
- }
- errors.push(error);
- completeIf();
- });
- })(record);
- }
- },
- destroyRecords: function(transaction, records, callback) {
- var me = this,
- table = me.getTable(),
- idProperty = me.getModel().idProperty,
- ids = [],
- values = [],
- destroyedRecords = [],
- len = records.length,
- idStr = '"' + idProperty + '" = ?',
- i, result, record, sql;
- for (i = 0; i < len; i++) {
- ids.push(idStr);
- values.push(records[i].getId());
- }
- sql = 'DELETE FROM "' + me.getTable() + '" WHERE ' + ids.join(' OR ');
- me.executeStatement(transaction, sql, values, function(transaction, resultSet) {
- callback.call(me, new Ext.data.ResultSet({
- success: true
- }));
- }, function(transaction, error) {
- callback.call(me, new Ext.data.ResultSet({
- success: false
- }), error);
- });
- },
- /**
- * Formats the data for each record before sending it to the server. This
- * method should be overridden to format the data in a way that differs from the default.
- * @param {Object} record The record that we are writing to the server.
- * @return {Object} An object literal of name/value keys to be written to the server.
- * By default this method returns the data property on the record.
- */
- getRecordData: function(record) {
- var me = this,
- fields = record.fields,
- idProperty = record.idProperty,
- uniqueIdStrategy = me.uniqueIdStrategy,
- data = {},
- len = fields.length,
- recordData = record.data,
- i, name, value, field;
- for (i = 0; i < len; ++i) {
- field = fields[i];
- if (field.persist !== false) {
- name = field.name;
- if (name === idProperty && !uniqueIdStrategy) {
-
- continue;
- }
- data[name] = me.toSqlValue(recordData[name], field);
- }
- }
- return data;
- },
- getColumnValues: function(columns, data) {
- var len = columns.length,
- values = [],
- i, column, value;
- for (i = 0; i < len; i++) {
- column = columns[i];
- value = data[column];
- if (value !== undefined) {
- values.push(value);
- }
- }
- return values;
- },
- getSchemaString: function() {
- var me = this,
- schema = [],
- model = me.getModel(),
- idProperty = model.idProperty,
- fields = model.fields,
- uniqueIdStrategy = me.uniqueIdStrategy,
- len = fields.length,
- i, field, type, name;
- for (i = 0; i < len; i++) {
- field = fields[i];
- type = field.getType();
- name = field.name;
- if (name === idProperty) {
- if (uniqueIdStrategy) {
- type = me.convertToSqlType(type);
- schema.unshift('"' + idProperty + '" ' + type);
- } else {
- schema.unshift('"' + idProperty + '" INTEGER PRIMARY KEY AUTOINCREMENT');
- }
- } else {
- type = me.convertToSqlType(type);
- schema.push('"' + name + '" ' + type);
- }
- }
- return schema.join(', ');
- },
- convertToSqlType: function(type) {
- switch (type.toLowerCase()) {
- case 'string':
- case 'auto':
- return 'TEXT';
- case 'int':
- case 'date':
- return 'INTEGER';
- case 'float':
- return 'REAL';
- case 'bool':
- return 'NUMERIC';
- }
- },
- dropTable: function() {
- var me = this;
- me.executeTransaction(function(transaction) {
- me.executeStatement(transaction, 'DROP TABLE "' + me.getTable() + '"', function() {
- me.tableExists = false;
- });
- }, null, null, false);
- },
- getDatabaseObject: function() {
- return window.openDatabase(this.getDatabase(), '1.0', 'Sencha Database', 5 * 1024 * 1024);
- },
- privates: {
- executeStatement: function(transaction, sql, values, success, failure) {
- var me = this;
- transaction.executeSql(sql, values, success ? function() {
- success.apply(me, arguments);
- } : null, failure ? function() {
- failure.apply(me, arguments);
- } : null);
- },
- executeTransaction: function(runner, failure, success, autoCreateTable) {
- var me = this;
- autoCreateTable = autoCreateTable !== false;
- me.getDatabaseObject().transaction(runner ? function(transaction) {
- if (autoCreateTable && !me.tableExists) {
- me.createTable(transaction);
- }
- runner.apply(me, arguments);
- } : null, failure ? function() {
- failure.apply(me, arguments);
- } : null, success ? function() {
- success.apply(me, arguments);
- } : null);
- },
- fromSqlValue: function(value, field) {
- if (field.isDateField) {
- value = value ? new Date(value) : null;
- } else if (field.isBooleanField) {
- value = value === 1;
- }
- return value;
- },
- getPersistedModelColumns: function(model) {
- var fields = model.fields,
- uniqueIdStrategy = this.uniqueIdStrategy,
- idProperty = model.idProperty,
- columns = [],
- len = fields.length,
- i, field, name;
- for (i = 0; i < len; ++i) {
- field = fields[i];
- name = field.name;
- if (name === idProperty && !uniqueIdStrategy) {
-
- continue;
- }
- if (field.persist !== false) {
- columns.push(field.name);
- }
- }
- return columns;
- },
- toSqlValue: function(value, field) {
- if (field.isDateField) {
- value = value ? value.getTime() : null;
- } else if (field.isBooleanField) {
- value = value ? 1 : 0;
- }
- return value;
- }
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.accelerometer.Abstract', {
- config: {
- /**
- * @cfg {Number} frequency The default frequency to get the current acceleration when using {@link Ext.device.Accelerometer#watchAcceleration}.
- */
- frequency: 10000
- },
- getCurrentAcceleration: function(config) {
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #getCurrentAcceleration');
- }
- // </debug>
- return config;
- },
- watchAcceleration: function(config) {
- var defaultConfig = Ext.device.accelerometer.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- frequency: defaultConfig.frequency
- });
- // <debug>
- if (!config.callback) {
- Ext.Logger.warn('You need to specify a `callback` function for #watchAcceleration');
- }
- // </debug>
- return config;
- },
- clearWatch: Ext.emptyFn
- });
- /**
- * @private
- */
- Ext.define('Ext.device.accelerometer.Cordova', {
- alternateClassName: 'Ext.device.accelerometer.PhoneGap',
- extend: 'Ext.device.accelerometer.Abstract',
- activeWatchID: null,
- getCurrentAcceleration: function(config) {
- config = this.callParent(arguments);
- navigator.accelerometer.getCurrentAcceleration(config.success, config.failure);
- return config;
- },
- watchAcceleration: function(config) {
- config = this.callParent(arguments);
- if (this.activeWatchID) {
- this.clearWatch();
- }
- this.activeWatchID = navigator.accelerometer.watchAcceleration(config.callback, config.failure, config);
- return config;
- },
- clearWatch: function() {
- if (this.activeWatchID) {
- navigator.accelerometer.clearWatch(this.activeWatchID);
- this.activeWatchID = null;
- }
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.accelerometer.Simulator', {
- extend: 'Ext.device.accelerometer.Abstract'
- });
- /**
- * Provides access to the native Accelerometer API when running on a device. There are three implementations of this API:
- *
- * - [PhoneGap](http://docs.phonegap.com/en/2.6.0/cordova_accelerometer_accelerometer.md.html#Accelerometer)
- *
- * This class will automatically select the correct implementation depending on the device your application is running on.
- *
- * ## Examples
- *
- * Getting the current location:
- *
- * Ext.device.Accelerometer.getCurrentAcceleration({
- * success: function(acceleration) {
- * alert('Acceleration X: ' + acceleration.x + '\n' +
- * 'Acceleration Y: ' + acceleration.y + '\n' +
- * 'Acceleration Z: ' + acceleration.z + '\n' +
- * 'Timestamp: ' + acceleration.timestamp + '\n');
- * },
- * failure: function() {
- * console.log('something went wrong!');
- * }
- * });
- *
- * Watching the current acceleration:
- *
- * Ext.device.Accelerometer.watchAcceleration({
- * frequency: 500, // Update every 1/2 second
- * callback: function(acceleration) {
- * console.log('Acceleration X: ' + acceleration.x + '\n' +
- * 'Acceleration Y: ' + acceleration.y + '\n' +
- * 'Acceleration Z: ' + acceleration.z + '\n' +
- * 'Timestamp: ' + acceleration.timestamp + '\n');
- * },
- * failure: function() {
- * console.log('something went wrong!');
- * }
- * });
- *
- * @mixins Ext.device.accelerometer.Abstract
- */
- Ext.define('Ext.device.Accelerometer', {
- singleton: true,
- requires: [
- 'Ext.device.accelerometer.Cordova',
- 'Ext.device.accelerometer.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView && browserEnv.Cordova) {
- return Ext.create('Ext.device.accelerometer.Cordova');
- }
- return Ext.create('Ext.device.accelerometer.Simulator');
- }
- });
- /**
- * @private
- *
- * This object handles communication between the WebView and Sencha's native shell.
- * Currently it has two primary responsibilities:
- *
- * 1. Maintaining unique string ids for callback functions, together with their scope objects
- * 2. Serializing given object data into HTTP GET request parameters
- *
- * As an example, to capture a photo from the device's camera, we use `Ext.device.Camera.capture()` like:
- *
- * Ext.device.Camera.capture(
- * function(dataUri){
- * // Do something with the base64-encoded `dataUri` string
- * },
- * function(errorMessage) {
- *
- * },
- * callbackScope,
- * {
- * quality: 75,
- * width: 500,
- * height: 500
- * }
- * );
- *
- * Internally, `Ext.device.Communicator.send()` will then be invoked with the following argument:
- *
- * Ext.device.Communicator.send({
- * command: 'Camera#capture',
- * callbacks: {
- * onSuccess: function() {
- * // ...
- * },
- * onError: function() {
- * // ...
- * }
- * },
- * scope: callbackScope,
- * quality: 75,
- * width: 500,
- * height: 500
- * });
- *
- * Which will then be transformed into a HTTP GET request, sent to native shell's local
- * HTTP server with the following parameters:
- *
- * ?quality=75&width=500&height=500&command=Camera%23capture&onSuccess=3&onError=5
- *
- * Notice that `onSuccess` and `onError` have been converted into string ids (`3` and `5`
- * respectively) and maintained by `Ext.device.Communicator`.
- *
- * Whenever the requested operation finishes, `Ext.device.Communicator.invoke()` simply needs
- * to be executed from the native shell with the corresponding ids given before. For example:
- *
- * Ext.device.Communicator.invoke('3', ['DATA_URI_OF_THE_CAPTURED_IMAGE_HERE']);
- *
- * will invoke the original `onSuccess` callback under the given scope. (`callbackScope`), with
- * the first argument of 'DATA_URI_OF_THE_CAPTURED_IMAGE_HERE'
- *
- * Note that `Ext.device.Communicator` maintains the uniqueness of each function callback and
- * its scope object. If subsequent calls to `Ext.device.Communicator.send()` have the same
- * callback references, the same old ids will simply be reused, which guarantee the best possible
- * performance for a large amount of repetitive calls.
- */
- Ext.define('Ext.device.communicator.Default', {
- SERVER_URL: 'http://localhost:3000',
- // Change this to the correct server URL
- callbackDataMap: {},
- callbackIdMap: {},
- idSeed: 0,
- globalScopeId: '0',
- generateId: function() {
- return String(++this.idSeed);
- },
- getId: function(object) {
- var id = object.$callbackId;
- if (!id) {
- object.$callbackId = id = this.generateId();
- }
- return id;
- },
- getCallbackId: function(callback, scope) {
- var idMap = this.callbackIdMap,
- dataMap = this.callbackDataMap,
- id, scopeId, callbackId, data;
- if (!scope) {
- scopeId = this.globalScopeId;
- } else if (scope.isIdentifiable) {
- scopeId = scope.getId();
- } else {
- scopeId = this.getId(scope);
- }
- callbackId = this.getId(callback);
- if (!idMap[scopeId]) {
- idMap[scopeId] = {};
- }
- if (!idMap[scopeId][callbackId]) {
- id = this.generateId();
- data = {
- callback: callback,
- scope: scope
- };
- idMap[scopeId][callbackId] = id;
- dataMap[id] = data;
- }
- return idMap[scopeId][callbackId];
- },
- getCallbackData: function(id) {
- return this.callbackDataMap[id];
- },
- invoke: function(id, args) {
- var data = this.getCallbackData(id);
- data.callback.apply(data.scope, args);
- },
- send: function(args) {
- var callbacks, scope, name, callback;
- if (!args) {
- args = {};
- } else if (args.callbacks) {
- callbacks = args.callbacks;
- scope = args.scope;
- delete args.callbacks;
- delete args.scope;
- for (name in callbacks) {
- if (callbacks.hasOwnProperty(name)) {
- callback = callbacks[name];
- if (typeof callback == 'function') {
- args[name] = this.getCallbackId(callback, scope);
- }
- }
- }
- }
- args.__source = document.location.href;
- var result = this.doSend(args);
- return (result && result.length > 0) ? JSON.parse(result) : null;
- },
- doSend: function(args) {
- var xhr = new XMLHttpRequest();
- xhr.open('GET', this.SERVER_URL + '?' + Ext.Object.toQueryString(args) + '&_dc=' + new Date().getTime(), false);
- // wrap the request in a try/catch block so we can check if any errors are thrown and attempt to call any
- // failure/callback functions if defined
- try {
- xhr.send(null);
- return xhr.responseText;
- } catch (e) {
- if (args.failure) {
- this.invoke(args.failure);
- } else if (args.callback) {
- this.invoke(args.callback);
- }
- }
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.communicator.Android', {
- extend: 'Ext.device.communicator.Default',
- doSend: function(args) {
- return window.Sencha.action(JSON.stringify(args));
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.Communicator', {
- requires: [
- 'Ext.device.communicator.Default',
- 'Ext.device.communicator.Android'
- ],
- singleton: true,
- constructor: function() {
- if (Ext.os.is.Android) {
- return new Ext.device.communicator.Android();
- }
- return new Ext.device.communicator.Default();
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.analytics.Abstract', {
- config: {
- accountID: null
- },
- updateAccountID: function(newID) {
- if (newID) {
- window.plugins.googleAnalyticsPlugin.startTrackerWithAccountID(newID);
- }
- },
- /**
- * Registers yur Google Analytics account.
- *
- * @param {String} accountID Your Google Analytics account ID
- */
- registerAccount: function(accountID) {
- this.setAccountID(accountID);
- },
- /**
- * Track an event in your application.
- *
- * More information here: http://code.google.com/apis/analytics/docs/tracking/eventTrackerGuide.html
- *
- * @param {Object} config
- *
- * @param {String} config.category The name you supply for the group of objects you want to track
- *
- * @param {String} config.action A string that is uniquely paired with each category, and commonly
- * used to define the type of user interaction for the web object.
- *
- * @param {String} config.label An optional string to provide additional dimensions to the event data.
- *
- * @param {String} config.value An integer that you can use to provide numerical data about the user event
- *
- * @param {Boolean} config.nonInteraction A boolean that when set to true, indicates that the event hit will
- * not be used in bounce-rate calculation.
- */
- trackEvent: Ext.emptyFn,
- /**
- * Track an pageview in your application.
- *
- * @param {String} config.page The page you want to track (must start with a slash).
- */
- trackPageview: Ext.emptyFn
- });
- /**
- * @private
- */
- Ext.define('Ext.device.analytics.Cordova', {
- extend: 'Ext.device.analytics.Abstract',
- trackEvent: function(config) {
- if (!this.getAccountID()) {
- return;
- }
- window.plugins.googleAnalyticsPlugin.trackEvent(config.category, config.action, config.label, config.value, config.nonInteraction);
- },
- trackPageview: function(page) {
- if (!this.getAccountID()) {
- return;
- }
- window.plugins.googleAnalyticsPlugin.trackPageview(page);
- }
- });
- /**
- * Allows you to use Google Analytics within your Cordova application.
- *
- * For setup information, please read the [plugin documentation](https://github.com/phonegap/phonegap-facebook-plugin).
- *
- * @mixins Ext.device.analytics.Abstract
- */
- Ext.define('Ext.device.Analytics', {
- alternateClassName: 'Ext.ux.device.Analytics',
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.analytics.*'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView && browserEnv.Cordova) {
- return Ext.create('Ext.device.analytics.Cordova');
- } else {
- return Ext.create('Ext.device.analytics.Abstract');
- }
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.browser.Abstract', {
- /**
- * Used to open a new browser window.
- *
- * When used with Cordova, a new InAppBrowser window opens. With Cordova, you also have the ability
- * to listen when the window starts loading, is finished loading, fails to load, and when it is closed.
- * You can also use the {@link #close} method to close the window, if opened.
- *
- * @param {Object} options
- * The options to use when opening a new browser window.
- *
- * @param {String} options.url
- * The URL to open.
- *
- * @param {Object} options.listeners
- * The listeners you want to add onto the window. Available events are:
- *
- * - `loadstart` - when the window starts loading the URL
- * - `loadstop` - when the window is finished loading the URL
- * - `loaderror` - when the window encounters an error loading the URL
- * - `close` - when the window is closed
- *
- * @param {Boolean} options.showToolbar
- * True to show the toolbar in the browser window.
- *
- * @param {String} options.options
- * A string of options which are used when using Cordova. For a full list of options, visit the
- * [PhoneGap documention](http://docs.phonegap.com/en/2.6.0/cordova_inappbrowser_inappbrowser.md.html#window.open).
- */
- open: Ext.emptyFn,
- /**
- * Used to close the browser, if one is opened.
- */
- close: Ext.emptyFn
- });
- /**
- * @private
- */
- Ext.define('Ext.device.browser.Cordova', {
- extend: 'Ext.device.browser.Abstract',
- open: function(config) {
- if (!this._window) {
- this._window = Ext.create('Ext.device.browser.Window');
- }
- this._window.open(config);
- return this._window;
- },
- close: function() {
- if (!this._window) {
- return;
- }
- this._window.close();
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.browser.Simulator', {
- open: function(config) {
- window.open(config.url, '_blank');
- },
- close: Ext.emptyFn
- });
- /**
- * @mixins Ext.device.browser.Abstract
- */
- Ext.define('Ext.device.Browser', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.browser.Cordova',
- 'Ext.device.browser.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView && browserEnv.Cordova) {
- return Ext.create('Ext.device.browser.Cordova');
- }
- return Ext.create('Ext.device.browser.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.camera.Abstract', {
- source: {
- library: 0,
- camera: 1,
- album: 2
- },
- destination: {
- data: 0,
- // Returns base64-encoded string
- file: 1,
- // Returns file's URI
- 'native': 2
- },
- encoding: {
- jpeg: 0,
- jpg: 0,
- png: 1
- },
- media: {
- picture: 0,
- video: 1,
- all: 2
- },
- direction: {
- back: 0,
- front: 1
- },
- /**
- * Allows you to capture a photo.
- *
- * @param {Object} options
- * The options to use when taking a photo.
- *
- * @param {Function} options.success
- * The success callback which is called when the photo has been taken.
- *
- * @param {String} options.success.image
- * The image which was just taken, either a base64 encoded string or a URI depending on which
- * option you chose (destination).
- *
- * @param {Function} options.failure
- * The function which is called when something goes wrong.
- *
- * @param {Object} scope
- * The scope in which to call the `success` and `failure` functions, if specified.
- *
- * @param {Number} options.quality
- * The quality of the image which is returned in the callback. This should be a percentage.
- *
- * @param {String} options.source
- * The source of where the image should be taken. Available options are:
- *
- * - **album** - prompts the user to choose an image from an album
- * - **camera** - prompts the user to take a new photo
- * - **library** - prompts the user to choose an image from the library
- *
- * @param {String} destination
- * The destination of the image which is returned. Available options are:
- *
- * - **data** - returns a base64 encoded string
- * - **file** - returns the file's URI
- *
- * @param {String} encoding
- * The encoding of the returned image. Available options are:
- *
- * - **jpg**
- * - **png**
- *
- * @param {Number} width
- * The width of the image to return
- *
- * @param {Number} height
- * The height of the image to return
- */
- capture: Ext.emptyFn,
- getPicture: Ext.emptyFn,
- cleanup: Ext.emptyFn
- });
- /**
- * @private
- */
- Ext.define('Ext.device.camera.Cordova', {
- alternateClassName: 'Ext.device.camera.PhoneGap',
- extend: 'Ext.device.camera.Abstract',
- getPicture: function(onSuccess, onError, options) {
- try {
- navigator.camera.getPicture(onSuccess, onError, options);
- } catch (e) {
- alert(e);
- }
- },
- cleanup: function(onSuccess, onError) {
- try {
- navigator.camera.cleanup(onSuccess, onError);
- } catch (e) {
- alert(e);
- }
- },
- capture: function(args) {
- var onSuccess = args.success,
- onError = args.failure,
- scope = args.scope,
- sources = this.source,
- destinations = this.destination,
- encodings = this.encoding,
- source = args.source,
- destination = args.destination,
- encoding = args.encoding,
- options = {};
- if (scope) {
- onSuccess = Ext.Function.bind(onSuccess, scope);
- onError = Ext.Function.bind(onError, scope);
- }
- if (source !== undefined) {
- options.sourceType = sources.hasOwnProperty(source) ? sources[source] : source;
- }
- if (destination !== undefined) {
- options.destinationType = destinations.hasOwnProperty(destination) ? destinations[destination] : destination;
- }
- if (encoding !== undefined) {
- options.encodingType = encodings.hasOwnProperty(encoding) ? encodings[encoding] : encoding;
- }
- if ('quality' in args) {
- options.quality = args.quality;
- }
- if ('width' in args) {
- options.targetWidth = args.width;
- }
- if ('height' in args) {
- options.targetHeight = args.height;
- }
- this.getPicture(onSuccess, onError, options);
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.camera.Simulator', {
- extend: 'Ext.device.camera.Abstract',
- config: {
- samples: [
- {
- success: 'http://www.sencha.com/img/sencha-large.png'
- }
- ]
- },
- constructor: function(config) {
- this.initConfig(config);
- },
- updateSamples: function(samples) {
- this.sampleIndex = 0;
- },
- capture: function(options) {
- var index = this.sampleIndex,
- samples = this.getSamples(),
- samplesCount = samples.length,
- sample = samples[index],
- scope = options.scope,
- success = options.success,
- failure = options.failure;
- if ('success' in sample) {
- if (success) {
- success.call(scope, sample.success);
- }
- } else {
- if (failure) {
- failure.call(scope, sample.failure);
- }
- }
- if (++index > samplesCount - 1) {
- index = 0;
- }
- this.sampleIndex = index;
- }
- });
- /**
- * This class allows you to use native APIs to take photos using the device camera.
- *
- * When this singleton is instantiated, it will automatically select the correct implementation depending on the
- * current device:
- *
- * - Sencha Packager
- * - Cordova
- * - Simulator
- *
- * Both the Sencha Packager and Cordova implementations will use the native camera functionality to take or select
- * a photo. The Simulator implementation will simply return fake images.
- *
- * ## Example
- *
- * You can use the {@link Ext.device.Camera#capture} function to take a photo:
- *
- * Ext.device.Camera.capture({
- * success: function(image) {
- * imageView.setSrc(image);
- * },
- * quality: 75,
- * width: 200,
- * height: 200,
- * destination: 'data'
- * });
- *
- * See the documentation for {@link Ext.device.Camera#capture} all available configurations.
- *
- * @mixins Ext.device.camera.Abstract
- */
- Ext.define('Ext.device.Camera', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.camera.Cordova',
- 'Ext.device.camera.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.Cordova) {
- return Ext.create('Ext.device.camera.Cordova');
- }
- }
- return Ext.create('Ext.device.camera.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.capture.Cordova', {
- captureAudio: function(config) {
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #captureAudio');
- }
- // </debug>
- var options = {
- limit: config.limit,
- duration: config.maximumDuration
- };
- navigator.device.capture.captureAudio(config.success, config.failure, options);
- },
- captureVideo: function(config) {
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #captureVideo');
- }
- // </debug>
- var options = {
- limit: config.limit,
- duration: config.maximumDuration
- };
- navigator.device.capture.captureVideo(config.success, config.failure, options);
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.capture.Abstract', {
- alternateClassName: 'Ext.device.capture.Simulator',
- /**
- * Start the audio recorder application and return information about captured audio clip file(s).
- *
- * @example
- * Ext.device.Capture.captureAudio({
- * limit: 2, // limit to 2 recordings
- * maximumDuration: 10, // limit to 10 seconds per recording
- * success: function(files) {
- * for (var i = 0; i < files.length; i++) {
- * console.log('Captured audio path: ', files[i].fullPath);
- * };
- * },
- * failure: function() {
- * console.log('Something went wrong!');
- * }
- * });
- *
- * @param {Object} config The configuration object to be passed:
- *
- * @param {Number} config.limit The maximum number of recordings allowed (defaults to 1).
- *
- * @param {Number} config.maximumDuration The maximum duration of the capture, in seconds.
- *
- * @param {Number} config.duration The maximum duration of the capture, in seconds.
- *
- * @param {Function} config.success Called if the capture is successful.
- * @param {Array} config.success.files An array of objects containing information about the captured audio.
- *
- * @param {Function} config.failure Called if the capture is unsuccessful.
- */
- captureAudio: Ext.emptyFn,
- /**
- * Start the video recorder application and return information about captured video clip file(s).
- *
- * @example
- * Ext.device.Capture.captureVideo({
- * limit: 2, // limit to 2 recordings
- * maximumDuration: 10, // limit to 10 seconds per recording
- * success: function(files) {
- * for (var i = 0; i < files.length; i++) {
- * console.log('Captured video path: ', files[i].fullPath);
- * };
- * },
- * failure: function() {
- * console.log('Something went wrong!');
- * }
- * });
- *
- * @param {Object} config The configuration object to be passed:
- *
- * @param {Number} config.limit The maximum number of recordings allowed (defaults to 1).
- *
- * @param {Number} config.maximumDuration The maximum duration of the capture, in seconds.
- *
- * @param {Number} config.duration The maximum duration of the capture, in seconds.
- *
- * @param {Function} config.success Called if the capture is successful.
- * @param {Array} config.success.files An array of objects containing information about the captured video.
- *
- * @param {Function} config.failure Called if the capture is unsuccessful.
- */
- captureVideo: Ext.emptyFn
- });
- /**
- * Provides access to the audio and video capture capabilities of the device.
- *
- * @mixins Ext.device.capture.Abstract
- */
- Ext.define('Ext.device.Capture', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.capture.Cordova',
- 'Ext.device.capture.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView && browserEnv.Cordova) {
- return Ext.create('Ext.device.capture.Cordova');
- }
- return Ext.create('Ext.device.capture.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.compass.Abstract', {
- config: {
- /**
- * @cfg {Number} frequency The default frequency to get the current heading when using {@link Ext.device.Compass#watchHeading}.
- */
- frequency: 100
- },
- getHeadingAvailable: function(config) {
- // <debug>
- if (!config.callback) {
- Ext.Logger.warn('You need to specify a `callback` function for #getHeadingAvailable');
- }
- // </debug>
- return config;
- },
- getCurrentHeading: function(config) {
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #getCurrentHeading');
- }
- // </debug>
- return config;
- },
- watchHeading: function(config) {
- var defaultConfig = Ext.device.compass.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- frequency: defaultConfig.frequency
- });
- // <debug>
- if (!config.callback) {
- Ext.Logger.warn('You need to specify a `callback` function for #watchHeading');
- }
- // </debug>
- return config;
- },
- clearWatch: Ext.emptyFn
- });
- /**
- * @private
- */
- Ext.define('Ext.device.compass.Cordova', {
- alternateClassName: 'Ext.device.compass.PhoneGap',
- extend: 'Ext.device.compass.Abstract',
- activeWatchID: null,
- getHeadingAvailable: function(config) {
- var callback = function(result) {
- if (result.hasOwnProperty("code")) {
- config.callback.call(config.scope || this, false);
- } else {
- config.callback.call(config.scope || this, true);
- }
- };
- this.getCurrentHeading({
- success: callback,
- failure: callback
- });
- },
- getCurrentHeading: function(config) {
- config = this.callParent(arguments);
- navigator.compass.getCurrentHeading(config.success, config.failure);
- return config;
- },
- watchHeading: function(config) {
- config = this.callParent(arguments);
- if (this.activeWatchID) {
- this.clearWatch();
- }
- this.activeWatchID = navigator.compass.watchHeading(config.callback, config.failure, config);
- return config;
- },
- clearWatch: function() {
- if (this.activeWatchID) {
- navigator.compass.clearWatch(this.activeWatchID);
- this.activeWatchID = null;
- }
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.compass.Simulator', {
- extend: 'Ext.device.compass.Abstract'
- });
- /**
- * Provides access to the native Compass API when running on a device. There are three implementations of this API:
- *
- * - [PhoneGap](http://docs.phonegap.com/en/2.6.0/cordova_compass_compass.md.html#Compass)
- *
- * This class will automatically select the correct implementation depending on the device your application is running on.
- *
- * ## Examples
- *
- * Getting the current location:
- *
- * Ext.device.Compass.getCurrentHeading({
- * success: function(heading) {
- * alert('Heading: ' + heading.magneticHeading);
- * },
- * failure: function() {
- * console.log('something went wrong!');
- * }
- * });
- *
- * Watching the current compass:
- *
- * Ext.device.Compass.watchHeading({
- * frequency: 500, // Update every 1/2 second
- * callback: function(heading) {
- * console.log('Heading: ' + heading.magneticHeading);
- * },
- * failure: function() {
- * console.log('something went wrong!');
- * }
- * });
- *
- * @mixins Ext.device.compass.Abstract
- */
- Ext.define('Ext.device.Compass', {
- singleton: true,
- requires: [
- 'Ext.device.compass.Cordova',
- 'Ext.device.compass.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView && browserEnv.Cordova) {
- return Ext.create('Ext.device.compass.Cordova');
- }
- return Ext.create('Ext.device.compass.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.connection.Abstract', {
- extend: 'Ext.Evented',
- mixins: [
- 'Ext.mixin.Observable'
- ],
- config: {
- online: false,
- type: null
- },
- /**
- * @event online
- * Fires when the device goes online
- */
- /**
- * @event offline
- * Fires when the device goes offline
- */
- /**
- * @property {String} UNKNOWN
- * Text label for a connection type.
- */
- UNKNOWN: 'Unknown connection',
- /**
- * @property {String} ETHERNET
- * Text label for a connection type.
- */
- ETHERNET: 'Ethernet connection',
- /**
- * @property {String} WIFI
- * Text label for a connection type.
- */
- WIFI: 'WiFi connection',
- /**
- * @property {String} CELL_2G
- * Text label for a connection type.
- */
- CELL_2G: 'Cell 2G connection',
- /**
- * @property {String} CELL_3G
- * Text label for a connection type.
- */
- CELL_3G: 'Cell 3G connection',
- /**
- * @property {String} CELL_4G
- * Text label for a connection type.
- */
- CELL_4G: 'Cell 4G connection',
- /**
- * @property {String} NONE
- * Text label for a connection type.
- */
- NONE: 'No network connection',
- /**
- * True if the device is currently online
- * @return {Boolean} online
- */
- isOnline: function() {
- return this.getOnline();
- }
- });
- /**
- * @method getType
- * Returns the current connection type.
- * @return {String} type
- */
- /**
- * @private
- */
- Ext.define('Ext.device.connection.Cordova', {
- alternateClassName: 'Ext.device.connection.PhoneGap',
- extend: 'Ext.device.connection.Abstract',
- constructor: function() {
- var me = this;
- document.addEventListener('online', function() {
- me.fireEvent('online', me);
- });
- document.addEventListener('offline', function() {
- me.fireEvent('offline', me);
- });
- },
- syncOnline: function() {
- var type = navigator.connection.type;
- this._type = type;
- this._online = type != Connection.NONE;
- },
- getOnline: function() {
- this.syncOnline();
- return this._online;
- },
- getType: function() {
- this.syncOnline();
- return this._type;
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.connection.Simulator', {
- extend: 'Ext.device.connection.Abstract',
- getOnline: function() {
- this._online = navigator.onLine;
- this._type = Ext.device.Connection.UNKNOWN;
- return this._online;
- }
- });
- /**
- * This class is used to check if the current device is currently online or not. It has three different implementations:
- *
- * - Sencha Packager
- * - Cordova
- * - Simulator
- *
- * Both the Sencha Packager and Cordova implementations will use the native functionality to determine if the current
- * device is online. The Simulator version will simply use `navigator.onLine`.
- *
- * When this singleton ({@link Ext.device.Connection}) is instantiated, it will automatically decide which version to
- * use based on the current platform.
- *
- * ## Examples
- *
- * Determining if the current device is online:
- *
- * alert(Ext.device.Connection.isOnline());
- *
- * Checking the type of connection the device has:
- *
- * alert('Your connection type is: ' + Ext.device.Connection.getType());
- *
- * The available connection types are:
- *
- * - {@link Ext.device.Connection#UNKNOWN UNKNOWN} - Unknown connection
- * - {@link Ext.device.Connection#ETHERNET ETHERNET} - Ethernet connection
- * - {@link Ext.device.Connection#WIFI WIFI} - WiFi connection
- * - {@link Ext.device.Connection#CELL_2G CELL_2G} - Cell 2G connection
- * - {@link Ext.device.Connection#CELL_3G CELL_3G} - Cell 3G connection
- * - {@link Ext.device.Connection#CELL_4G CELL_4G} - Cell 4G connection
- * - {@link Ext.device.Connection#NONE NONE} - No network connection
- *
- * @mixins Ext.device.connection.Abstract
- */
- Ext.define('Ext.device.Connection', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.connection.Cordova',
- 'Ext.device.connection.Simulator'
- ],
- /**
- * @event onlinechange
- * @inheritdoc Ext.device.connection.Sencha#onlinechange
- */
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.Cordova) {
- return Ext.create('Ext.device.connection.Cordova');
- }
- }
- return Ext.create('Ext.device.connection.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.contacts.Abstract', {
- mixins: [
- 'Ext.mixin.Observable'
- ],
- config: {
- /**
- * @cfg {Boolean} includeImages
- * True to include images when you get the contacts store. Please beware that this can be very slow.
- */
- includeImages: false
- },
- /**
- * Returns an Array of contact objects.
- * @return {Object[]} An array of contact objects.
- */
- getContacts: function(config) {
- if (!this._store) {
- this._store = [
- {
- first: 'Peter',
- last: 'Venkman',
- emails: {
- work: 'peter.venkman@gb.com'
- }
- },
- {
- first: 'Egon',
- last: 'Spengler',
- emails: {
- work: 'egon.spengler@gb.com'
- }
- }
- ];
- }
- config.success.call(config.scope || this, this._store);
- },
- /**
- * Returns base64 encoded image thumbnail for a contact specified in config.id
- * **This method is for Sencha Native Packager only**
- *
- * @return {String} base64 string
- */
- getThumbnail: function(config) {
- config.callback.call(config.scope || this, "");
- },
- /**
- * Returns localized, user readable label for a contact field (i.e. "Mobile", "Home")
- * **This method is for Sencha Native Packager only**
- *
- * @return {String} user readable string
- */
- getLocalizedLabel: function(config) {
- config.callback.call(config.scope || this, config.label.toUpperCase(), config.label);
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.contacts.Cordova', {
- alternateClassName: 'Ext.device.contacts.PhoneGap',
- extend: 'Ext.device.contacts.Abstract',
- getContacts: function(config) {
- if (!config) {
- Ext.Logger.warn('Ext.device.Contacts#getContacts: You must specify a `config` object.');
- return false;
- }
- if (!config.success) {
- Ext.Logger.warn('Ext.device.Contacts#getContacts: You must specify a `success` method.');
- return false;
- }
- if (!config.fields) {
- config.fields = [
- "*"
- ];
- }
- if (!Ext.isArray(config.fields)) {
- config.fields = [
- config.fields
- ];
- }
- if (Ext.isEmpty(config.multiple)) {
- config.multiple = true;
- }
- navigator.contacts.find(config.fields, config.success, config.failure, config);
- }
- });
- /**
- * This device API allows you to access a users contacts using a {@link Ext.data.Store}. This allows you to search, filter
- * and sort through all the contacts using its methods.
- *
- * To use this API, all you need to do is require this class (`Ext.device.Contacts`) and then use `Ext.device.Contacts.getContacts()`
- * to retrieve an array of contacts.
- *
- * **Please note that getThumbnail and getLocalizedLabel are *only* for the Sencha Native Packager.**
- * **Both Cordova/PhoneGap and Sencha Native Packager can access the find method though properties of returned contacts will differ.**
- *
- * # Example
- *
- * Ext.application({
- * name: 'Sencha',
- * requires: 'Ext.device.Contacts',
- *
- * launch: function() {
- * Ext.Viewport.add({
- * xtype: 'list',
- * itemTpl: '{First} {Last}',
- * store: {
- * fields: ['First', 'Last'],
- * data: Ext.device.Contacts.getContacts()
- * }
- * });
- * }
- * });
- *
- * @mixins Ext.device.contacts.Abstract
- * @mixins Ext.device.contacts.Sencha
- * @mixins Ext.device.contacts.Cordova
- */
- Ext.define('Ext.device.Contacts', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.contacts.Cordova'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.Cordova) {
- return Ext.create('Ext.device.contacts.Cordova');
- }
- }
- return Ext.create('Ext.device.contacts.Abstract');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.device.Abstract', {
- mixins: [
- 'Ext.mixin.Observable'
- ],
- /**
- * @event schemeupdate
- * Event which is fired when your Sencha Native packaged application is opened from another application using a custom URL scheme.
- *
- * This event will only fire if the application was already open (in other words; `onReady` was already fired). This means you should check
- * if {@link Ext.device.Device#scheme} is set in your Application `launch`/`onReady` method, and perform any needed changes for that URL (if defined).
- * Then listen to this event for future changed.
- *
- * ## Example
- *
- * Ext.application({
- * name: 'Sencha',
- * requires: ['Ext.device.Device'],
- * launch: function() {
- * if (Ext.device.Device.scheme) {
- * // the application was opened via another application. Do something:
- * console.log('Applicaton opened via another application: ' + Ext.device.Device.scheme.url);
- * }
- *
- * // Listen for future changes
- * Ext.device.Device.on('schemeupdate', function(device, scheme) {
- * // the application was launched, closed, and then launched another from another application
- * // this means onReady wont be called again ('cause the application is already running in the
- * // background) - but this event will be fired
- * console.log('Applicated reopened via another application: ' + scheme.url);
- * }, this);
- * }
- * });
- *
- * __Note:__ This currently only works with the Sencha Native Packager. If you attempt to listen to this event when packaged with
- * PhoneGap or simply in the browser, it will never fire.**
- *
- * @param {Ext.device.Device} this The instance of Ext.device.Device
- * @param {Object/Boolean} scheme The scheme information, if opened via another application
- * @param {String} scheme.url The URL that was opened, if this application was opened via another application. Example: `sencha:`
- * @param {String} scheme.sourceApplication The source application that opened this application. Example: `com.apple.safari`.
- */
- /**
- * @property {String} name
- * Returns the name of the current device. If the current device does not have a name (for example, in a browser), it will
- * default to `not available`.
- *
- * alert('Device name: ' + Ext.device.Device.name);
- */
- name: 'not available',
- /**
- * @property {String} uuid
- * Returns a unique identifier for the current device. If the current device does not have a unique identifier (for example,
- * in a browser), it will default to `anonymous`.
- *
- * alert('Device UUID: ' + Ext.device.Device.uuid);
- */
- uuid: 'anonymous',
- /**
- * @property {String} platform
- * The current platform the device is running on.
- *
- * alert('Device platform: ' + Ext.device.Device.platform);
- */
- platform: Ext.os.name,
- /**
- * @property {Object/Boolean} scheme
- *
- */
- scheme: false,
- /**
- * Opens a specified URL. The URL can contain a custom URL Scheme for another app or service:
- *
- * // Safari
- * Ext.device.Device.openURL('http://sencha.com');
- *
- * // Telephone
- * Ext.device.Device.openURL('tel:6501231234');
- *
- * // SMS with a default number
- * Ext.device.Device.openURL('sms:+12345678901');
- *
- * // Email client
- * Ext.device.Device.openURL('mailto:rob@sencha.com');
- *
- * You can find a full list of available URL schemes here: [http://wiki.akosma.com/IPhone_URL_Schemes](http://wiki.akosma.com/IPhone_URL_Schemes).
- *
- * __Note:__ This currently only works with the Sencha Native Packager. Attempting to use this on PhoneGap, iOS Simulator
- * or the browser will simply result in the current window location changing.**
- *
- * If successful, this will close the application (as another one opens).
- *
- * @param {String} url The URL to open
- */
- openURL: function(url) {
- window.location = url;
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.device.Cordova', {
- alternateClassName: 'Ext.device.device.PhoneGap',
- extend: 'Ext.device.device.Abstract',
- availableListeners: [
- 'pause',
- 'resume',
- 'backbutton',
- 'batterycritical',
- 'batterylow',
- 'batterystatus',
- 'menubutton',
- 'searchbutton',
- 'startcallbutton',
- 'endcallbutton',
- 'volumeupbutton',
- 'volumedownbutton'
- ],
- constructor: function() {
- // We can't get the device details until the device is ready, so lets wait.
- if (Ext.isReady) {
- this.onReady();
- } else {
- Ext.onReady(this.onReady, this, {
- single: true
- });
- }
- },
- /**
- * @property {String} cordova
- * Returns the version of Cordova running on the device.
- *
- * alert('Device cordova: ' + Ext.device.Device.cordova);
- */
- /**
- * @property {String} version
- * Returns the operating system version.
- *
- * alert('Device Version: ' + Ext.device.Device.version);
- */
- /**
- * @property {String} model
- * Returns the device's model name.
- *
- * alert('Device Model: ' + Ext.device.Device.model);
- */
- /**
- * @event pause
- * Fires when the application goes into the background
- */
- /**
- * @event resume
- * Fires when the application goes into the foreground
- */
- /**
- * @event batterycritical
- * This event that fires when a Cordova application detects the percentage of battery
- * has reached the critical battery threshold.
- */
- /**
- * @event batterylow
- * This event that fires when a Cordova application detects the percentage of battery
- * has reached the low battery threshold.
- */
- /**
- * @event batterystatus
- * This event that fires when a Cordova application detects the percentage of battery
- * has changed by at least 1 percent.
- */
- /**
- * @event backbutton
- * This is an event that fires when the user presses the back button.
- */
- /**
- * @event menubutton
- * This is an event that fires when the user presses the menu button.
- */
- /**
- * @event searchbutton
- * This is an event that fires when the user presses the search button.
- */
- /**
- * @event startcallbutton
- * This is an event that fires when the user presses the start call button.
- */
- /**
- * @event endcallbutton
- * This is an event that fires when the user presses the end call button.
- */
- /**
- * @event volumeupbutton
- * This is an event that fires when the user presses the volume up button.
- */
- /**
- * @event volumedownbutton
- * This is an event that fires when the user presses the volume down button.
- */
- onReady: function() {
- var me = this,
- device = window.device;
- me.name = device.name || device.model;
- me.cordova = device.cordova;
- me.platform = device.platform || Ext.os.name;
- me.uuid = device.uuid;
- me.version = device.version;
- me.model = device.model;
- },
- privates: {
- doAddListener: function(name) {
- var me = this;
- if (!me.addedListeners) {
- me.addedListeners = [];
- }
- if (me.availableListeners.indexOf(name) != -1 && me.addedListeners.indexOf(name) == -1) {
- // Add the listeners
- me.addedListeners.push(name);
- document.addEventListener(name, function() {
- me.fireEvent(name, me);
- });
- }
- Ext.device.Device.mixins.observable.doAddListener.apply(Ext.device.Device.mixins.observable, arguments);
- }
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.device.Simulator', {
- extend: 'Ext.device.device.Abstract'
- });
- /**
- * Provides a cross device way to get information about the device your application is running on. There are 3 different implementations:
- *
- * - Sencha Packager
- * - [Cordova](http://cordova.apache.org/docs/en/2.5.0/cordova_device_device.md.html#Device)
- * - Simulator
- *
- * ## Examples
- *
- * #### Device Information
- *
- * Getting the device information:
- *
- * Ext.application({
- * name: 'Sencha',
- *
- * // Remember that the Ext.device.Device class *must* be required
- * requires: ['Ext.device.Device'],
- *
- * launch: function() {
- * alert([
- * 'Device name: ' + Ext.device.Device.name,
- * 'Device platform: ' + Ext.device.Device.platform,
- * 'Device UUID: ' + Ext.device.Device.uuid
- * ].join('\n'));
- * }
- * });
- *
- * ### Custom Scheme URL
- *
- * Using custom scheme URL to application your application from other applications:
- *
- * Ext.application({
- * name: 'Sencha',
- * requires: ['Ext.device.Device'],
- * launch: function() {
- * if (Ext.device.Device.scheme) {
- * // the application was opened via another application. Do something:
- * alert('Applicaton pened via another application: ' + Ext.device.Device.scheme.url);
- * }
- *
- * // Listen for future changes
- * Ext.device.Device.on('schemeupdate', function(device, scheme) {
- * // the application was launched, closed, and then launched another from another application
- * // this means onReady wont be called again ('cause the application is already running in the
- * // background) - but this event will be fired
- * alert('Applicated reopened via another application: ' + scheme.url);
- * }, this);
- * }
- * });
- *
- * Of course, you must add the custom scheme URL you would like to use when packaging your application.
- * You can do this by setting the `URLScheme` property inside your `package.json` file (Sencha Native Packager configuration file):
- *
- * {
- * ...
- * "URLScheme": "sencha",
- * ...
- * }
- *
- * You can change the available URL scheme.
- *
- * You can then test it by packaging and installing the application onto a device/iOS Simulator, opening Safari and typing: `sencha:testing`.
- * The application will launch and it will `alert` the URL you specified.
- *
- * **PLEASE NOTE: This currently only works with the Sencha Native Packager. If you attempt to listen to this event when packaged with
- * PhoneGap or simply in the browser, it will not function.**
- *
- * @mixins Ext.device.device.Abstract
- */
- Ext.define('Ext.device.Device', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.device.Cordova',
- 'Ext.device.device.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.Cordova) {
- return Ext.create('Ext.device.device.Cordova');
- }
- }
- return Ext.create('Ext.device.device.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.filesystem.Abstract', {
- config: {
- fileSystemType: 1,
- fileSystemSize: 0,
- readerType: "text",
- stringEncoding: "UTF8"
- },
- requestFileSystem: function(config) {
- var defaultConfig = Ext.device.filesystem.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- type: defaultConfig.fileSystemType,
- size: defaultConfig.fileSystemSize,
- success: Ext.emptyFn,
- failure: Ext.emptyFn
- });
- return config;
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.filesystem.HTML5', {
- extend: 'Ext.device.filesystem.Abstract',
- /**
- * Requests a {@link Ext.device.filesystem.FileSystem} instance.
- *
- * var me = this;
- * var fs = Ext.create("Ext.device.FileSystem", {});
- * fs.requestFileSystem({
- * type: window.PERSISTENT,
- * size: 1024 * 1024,
- * success: function(fileSystem) {
- * me.fs = fileSystem;
- * },
- * failure: function(err) {
- * console.log("FileSystem Failure: " + err.code);
- * }
- * });
- *
- * @param {Object} config
- * The object which contains the following config options:
- *
- * @param {Number} config.type
- * window.TEMPORARY (0) or window.PERSISTENT (1)
- *
- * @param {Number} config.size
- * Storage space, in Bytes, needed by the application
- *
- * @param {Function} config.success This is required.
- * The callback to be called when the file system has been successfully created.
- *
- * @param {Ext.device.filesystem.FileSystem} config.success.fileSystem
- * The created file system.
- *
- * @param {Function} config.failure This is optional.
- * The callback to be called when an error occurred.
- *
- * @param {Object} config.failure.error
- * The occurred error.
- *
- * @param {Object} config.scope
- * The scope object
- */
- requestFileSystem: function(config) {
- if (!config.success) {
- Ext.Logger.error('Ext.device.filesystem#requestFileSystem: You must specify a `success` callback.');
- return null;
- }
- var me = this;
- var successCallback = function(fs) {
- var fileSystem = Ext.create('Ext.device.filesystem.FileSystem', fs);
- config.success.call(config.scope || me, fileSystem);
- };
- window.requestFileSystem(config.type, config.size, successCallback, config.failure || Ext.emptyFn);
- }
- }, function() {
- /**
- * The FileSystem class which is used to represent a file system.
- */
- Ext.define('Ext.device.filesystem.FileSystem', {
- fs: null,
- root: null,
- constructor: function(fs) {
- this.fs = fs;
- this.root = Ext.create('Ext.device.filesystem.DirectoryEntry', '/', this);
- },
- /**
- * Returns a {@link Ext.device.filesystem.DirectoryEntry} instance for the root of the file system.
- *
- * @return {Ext.device.filesystem.DirectoryEntry}
- * The file system root directory.
- */
- getRoot: function() {
- return this.root;
- }
- }, function() {
- /**
- * The Entry class which is used to represent entries in a file system,
- * each of which may be a {@link Ext.device.filesystem.FileEntry} or a {@link Ext.device.filesystem.DirectoryEntry}.
- *
- * This is an abstract class.
- * @abstract
- */
- Ext.define('Ext.device.filesystem.Entry', {
- directory: false,
- path: 0,
- fileSystem: null,
- entry: null,
- constructor: function(directory, path, fileSystem) {
- this.directory = directory;
- this.path = path;
- this.fileSystem = fileSystem;
- },
- /**
- * Returns whether the entry is a file.
- *
- * @return {Boolean}
- * The entry is a file.
- */
- isFile: function() {
- return !this.directory;
- },
- /**
- * Returns whether the entry is a directory.
- *
- * @return {Boolean}
- * The entry is a directory.
- */
- isDirectory: function() {
- return this.directory;
- },
- /**
- * Returns the name of the entry, excluding the path leading to it.
- *
- * @return {String}
- * The entry name.
- */
- getName: function() {
- var components = this.path.split('/');
- for (var i = components.length - 1; i >= 0; --i) {
- if (components[i].length > 0) {
- return components[i];
- }
- }
- return '/';
- },
- /**
- * Returns the full absolute path from the root to the entry.
- *
- * @return {String}
- * The entry full path.
- */
- getFullPath: function() {
- return this.path;
- },
- /**
- * Returns the file system on which the entry resides.
- *
- * @return {Ext.device.filesystem.FileSystem}
- * The entry file system.
- */
- getFileSystem: function() {
- return this.fileSystem;
- },
- getEntry: function() {
- return null;
- },
- /**
- * Moves the entry to a different location on the file system.
- *
- * @param {Object} config
- * The object which contains the following config options:
- *
- * @param {Ext.device.filesystem.DirectoryEntry} config.parent This is required.
- * The directory to which to move the entry.
- *
- * @param {String} config.newName This is optional.
- * The new name of the entry to move. Defaults to the entry's current name if unspecified.
- *
- * @param {Function} config.success This is optional.
- * The callback to be called when the entry has been successfully moved.
- *
- * @param {Ext.device.filesystem.Entry} config.success.entry
- * The entry for the new location.
- *
- * @param {Function} config.failure This is optional.
- * The callback to be called when an error occurred.
- *
- * @param {Object} config.failure.error
- * The occurred error.
- *
- * @param {Object} config.scope
- * The scope object
- */
- moveTo: function(config) {
- if (config.parent == null) {
- Ext.Logger.error('Ext.device.filesystem.Entry#moveTo: You must specify a new `parent` of the entry.');
- return null;
- }
- var me = this;
- this.getEntry({
- options: config.options || {},
- success: function(sourceEntry) {
- config.parent.getEntry({
- options: config.options || {},
- success: function(destinationEntry) {
- if (config.copy) {
- sourceEntry.copyTo(destinationEntry, config.newName, function(entry) {
- config.success.call(config.scope || me, entry.isDirectory ? Ext.create('Ext.device.filesystem.DirectoryEntry', entry.fullPath, me.fileSystem) : Ext.create('Ext.device.filesystem.FileEntry', entry.fullPath, me.fileSystem));
- }, config.failure);
- } else {
- sourceEntry.moveTo(destinationEntry, config.newName, function(entry) {
- config.success.call(config.scope || me, entry.isDirectory ? Ext.create('Ext.device.filesystem.DirectoryEntry', entry.fullPath, me.fileSystem) : Ext.create('Ext.device.filesystem.FileEntry', entry.fullPath, me.fileSystem));
- }, config.failure);
- }
- },
- failure: config.failure
- });
- },
- failure: config.failure
- });
- },
- /**
- * Works the same way as {@link Ext.device.filesystem.Entry#moveTo}, but copies the entry.
- */
- copyTo: function(config) {
- this.moveTo(Ext.apply(config, {
- copy: true
- }));
- },
- /**
- * Removes the entry from the file system.
- *
- * @param {Object} config
- * The object which contains the following config options:
- *
- * @param {Boolean} config.recursively This is optional
- * Deletes a directory and all of its contents
- *
- * @param {Function} config.success This is optional.
- * The callback to be called when the entry has been successfully removed.
- *
- * @param {Function} config.failure This is optional.
- * The callback to be called when an error occurred.
- *
- * @param {Object} config.failure.error
- * The occurred error.
- *
- * @param {Object} config.scope
- * The scope object
- */
- remove: function(config) {
- this.getEntry({
- success: function(entry) {
- if (config.recursively && this.directory) {
- entry.removeRecursively(config.success, config.failure);
- } else {
- entry.remove(config.success, config.failure);
- }
- },
- failure: config.failure
- });
- },
- /**
- * Looks up the parent directory containing the entry.
- *
- * @param {Object} config
- * The object which contains the following config options:
- *
- * @param {Function} config.success This is required.
- * The callback to be called when the parent directory has been successfully selected.
- *
- * @param {Ext.device.filesystem.DirectoryEntry} config.success.entry
- * The parent directory of the entry.
- *
- * @param {Function} config.failure This is optional.
- * The callback to be called when an error occurred.
- *
- * @param {Object} config.failure.error
- * The occurred error.
- *
- * @param {Object} config.scope
- * The scope object
- */
- getParent: function(config) {
- if (!config.success) {
- Ext.Logger.error('Ext.device.filesystem.Entry#getParent: You must specify a `success` callback.');
- return null;
- }
- var me = this;
- this.getEntry({
- options: config.options || {},
- success: function(entry) {
- entry.getParent(function(parentEntry) {
- config.success.call(config.scope || me, parentEntry.isDirectory ? Ext.create('Ext.device.filesystem.DirectoryEntry', parentEntry.fullPath, me.fileSystem) : Ext.create('Ext.device.filesystem.FileEntry', parentEntry.fullPath, me.fileSystem));
- }, config.failure);
- },
- failure: config.failure
- });
- }
- });
- /**
- * The DirectoryEntry class which is used to represent a directory on a file system.
- */
- Ext.define('Ext.device.filesystem.DirectoryEntry', {
- extend: 'Ext.device.filesystem.Entry',
- cachedDirectory: null,
- constructor: function(path, fileSystem) {
- this.callParent([
- true,
- path,
- fileSystem
- ]);
- },
- /**
- * Requests a Directory from the Local File System
- *
- * @param {Object} config
- *
- * @param {Object} config.options
- * File creation options {create:true, exclusive:false}
- *
- * @param {Boolean} config.options.create
- * Indicates if the directory should be created if it doesn't exist
- *
- * @param {Boolean} config.options.exclusive
- * Used with the create option only indicates whether a creation causes an error if the directory already exists
- *
- * @param {Function} config.success
- * The function called when the Directory is returned successfully
- *
- * @param {Ext.device.filesystem.DirectoryEntry} config.success.directory
- * DirectoryEntry Object
- *
- * @param {Function} config.failure
- * The function called when the Directory request causes an error
- *
- * @param {FileError} config.failure.error
- */
- getEntry: function(config) {
- var me = this;
- var callback = config.success;
- if ((config.options && config.options.create) && this.path) {
- var folders = this.path.split("/");
- if (folders[0] == '.' || folders[0] == '') {
- folders = folders.slice(1);
- }
- var recursiveCreation = function(dirEntry) {
- if (folders.length) {
- dirEntry.getDirectory(folders.shift(), config.options, recursiveCreation, config.failure);
- } else {
- callback(dirEntry);
- }
- };
- recursiveCreation(this.fileSystem.fs.root);
- } else {
- this.fileSystem.fs.root.getDirectory(this.path, config.options, function(directory) {
- config.success.call(config.scope || me, directory);
- }, config.failure);
- }
- },
- /**
- * Lists all the entries in the directory.
- *
- * @param {Object} config
- * The object which contains the following config options:
- *
- * @param {Function} config.success This is required.
- * The callback to be called when the entries has been successfully read.
- *
- * @param {Ext.device.filesystem.Entry[]} config.success.entries
- * The array of entries of the directory.
- *
- * @param {Function} config.failure This is optional.
- * The callback to be called when an error occurred.
- *
- * @param {Object} config.failure.error
- * The occurred error.
- *
- * @param {Object} config.scope
- * The scope object
- */
- readEntries: function(config) {
- if (!config.success) {
- Ext.Logger.error('Ext.device.filesystem.DirectoryEntry#readEntries: You must specify a `success` callback.');
- return null;
- }
- var me = this;
- this.getEntry({
- success: function(dirEntry) {
- var directoryReader = dirEntry.createReader();
- directoryReader.readEntries(function(entryInfos) {
- var entries = [],
- i = 0,
- len = entryInfos.length;
- for (; i < len; i++) {
- entryInfo = entryInfos[i];
- entries[i] = entryInfo.isDirectory ? Ext.create('Ext.device.filesystem.DirectoryEntry', entryInfo.fullPath, me.fileSystem) : Ext.create('Ext.device.filesystem.FileEntry', entryInfo.fullPath, me.fileSystem);
- }
- config.success.call(config.scope || this, entries);
- }, function(error) {
- if (config.failure) {
- config.failure.call(config.scope || this, error);
- }
- });
- },
- failure: config.failure
- });
- },
- /**
- * Creates or looks up a file.
- *
- * @param {Object} config
- * The object which contains the following config options:
- *
- * @param {String} config.path This is required.
- * The absolute path or relative path from the entry to the file to create or select.
- *
- * @param {Object} config.options This is optional.
- * The object which contains the following options:
- *
- * @param {Boolean} config.options.create This is optional.
- * Indicates whether to create a file, if path does not exist.
- *
- * @param {Boolean} config.options.exclusive This is optional. Used with 'create', by itself has no effect.
- * Indicates that method should fail, if path already exists.
- *
- * @param {Function} config.success This is optional.
- * The callback to be called when the file has been successfully created or selected.
- *
- * @param {Ext.device.filesystem.Entry} config.success.entry
- * The created or selected file.
- *
- * @param {Function} config.failure This is optional.
- * The callback to be called when an error occurred.
- *
- * @param {Object} config.failure.error
- * The occurred error.
- *
- * @param {Object} config.scope
- * The scope object
- */
- getFile: function(config) {
- if (config.path == null) {
- Ext.Logger.error('Ext.device.filesystem.DirectoryEntry#getFile: You must specify a `path` of the file.');
- return null;
- }
- var me = this;
- var fullPath = this.path + config.path;
- var fileEntry = Ext.create('Ext.device.filesystem.FileEntry', fullPath, this.fileSystem);
- fileEntry.getEntry({
- success: function() {
- config.success.call(config.scope || me, fileEntry);
- },
- options: config.options || {},
- failure: config.failure
- });
- },
- /**
- * Works the same way as {@link Ext.device.filesystem.DirectoryEntry#getFile},
- * but creates or looks up a directory.
- */
- getDirectory: function(config) {
- if (config.path == null) {
- Ext.Logger.error('Ext.device.filesystem.DirectoryEntry#getFile: You must specify a `path` of the file.');
- return null;
- }
- var me = this;
- var fullPath = this.path + config.path;
- var directoryEntry = Ext.create('Ext.device.filesystem.DirectoryEntry', fullPath, this.fileSystem);
- directoryEntry.getEntry({
- success: function() {
- config.success.call(config.scope || me, directoryEntry);
- },
- options: config.options || {},
- failure: config.failure
- });
- },
- /**
- * Works the same way as {@link Ext.device.filesystem.Entry#remove},
- * but removes the directory and all of its contents, if any.
- */
- removeRecursively: function(config) {
- this.remove(Ext.apply(config, {
- recursively: true
- }));
- }
- });
- /**
- * The FileEntry class which is used to represent a file on a file system.
- */
- Ext.define('Ext.device.filesystem.FileEntry', {
- extend: 'Ext.device.filesystem.Entry',
- length: 0,
- offset: 0,
- constructor: function(path, fileSystem) {
- this.callParent([
- false,
- path,
- fileSystem
- ]);
- this.offset = 0;
- this.length = 0;
- },
- /**
- * Requests a File Handle from the Local File System
- *
- * @param {Object} config
- *
- * @param {String} config.file
- * Filename optionally including path in string format '/tmp/debug.txt' or a File Object
- *
- * @param {Object} config.options
- * File creation options {create:true, exclusive:false}
- *
- * @param {Boolean} config.options.create
- * Indicates if the file should be created if it doesn't exist
- *
- * @param {Boolean} config.options.exclusive
- * Used with the create option only indicates whether a creation causes an error if the file already exists
- *
- * @param {Function} config.success
- * The function called when the filesystem is returned successfully
- *
- * @param {FileSystem} config.success.entry
- *
- * @param {Function} config.failure
- * The function called when the filesystem request causes and error
- *
- * @param {FileError} config.failure.error
- *
- */
- getEntry: function(config) {
- var me = this;
- var originalConfig = Ext.applyIf({}, config);
- if (this.fileSystem) {
- var failure = function(evt) {
- if ((config.options && config.options.create) && Ext.isString(this.path)) {
- var folders = this.path.split("/");
- if (folders[0] == '.' || folders[0] == '') {
- folders = folders.slice(1);
- }
- if (folders.length > 1 && !config.recursive === true) {
- folders.pop();
- var dirEntry = Ext.create('Ext.device.filesystem.DirectoryEntry', folders.join("/"), me.fileSystem);
- dirEntry.getEntry({
- options: config.options,
- success: function() {
- originalConfig.recursive = true;
- me.getEntry(originalConfig);
- },
- failure: config.failure
- });
- } else {
- if (config.failure) {
- config.failure.call(config.scope || me, evt);
- }
- }
- } else {
- if (config.failure) {
- config.failure.call(config.scope || me, evt);
- }
- }
- };
- this.fileSystem.fs.root.getFile(this.path, config.options || null, function(fileEntry) {
- fileEntry.file(function(file) {
- me.length = file.size;
- originalConfig.success.call(config.scope || me, fileEntry);
- }, function(error) {
- failure.call(config.scope || me, error);
- });
- }, function(error) {
- failure.call(config.scope || me, error);
- });
- } else {
- config.failure({
- code: -1,
- message: "FileSystem not Initialized"
- });
- }
- },
- /**
- * Returns the byte offset into the file at which the next read/write will occur.
- *
- * @return {Number}
- * The file offset.
- */
- getOffset: function() {
- return this.offset;
- },
- /**
- * Sets the byte offset into the file at which the next read/write will occur.
- *
- * @param {Object} config
- * The object which contains the following config options:
- *
- * @param {Number} config.offset This is required.
- * The file offset to set. If negative, the offset back from the end of the file.
- *
- * @param {Function} config.success This is optional.
- * The callback to be called when the file offset has been successfully set.
- *
- * @param {Function} config.failure This is optional.
- * The callback to be called when an error occurred.
- *
- * @param {Object} config.failure.error
- * The occurred error.
- *
- * @param {Object} config.scope
- * The scope object
- */
- seek: function(config) {
- if (config.offset == null) {
- Ext.Logger.error('Ext.device.filesystem.FileEntry#seek: You must specify an `offset` in the file.');
- return null;
- }
- this.offset = config.offset || 0;
- if (config.success) {
- config.success.call(config.scope || this);
- }
- },
- /**
- * Reads the data from the file starting at the file offset.
- *
- * @param {Object} config
- * The object which contains the following config options:
- *
- * @param {Number} config.length This is optional.
- * The length of bytes to read from the file. Defaults to the file's current size if unspecified.
- *
- * @param {String} config.encoding
- * Optional encoding type used only for reading as Text
- *
- * @param {String} config.type
- * Type of reading to use options are "text" (default), "dataURL", "binaryString" and "arrayBuffer"
- *
- * @param {Object} config.reader
- * Optional config params to be applied to a File Reader
- *
- * @param {Function} config.reader.onloadstart
- * @param {Function} config.reader.onloadprogress
- * @param {Function} config.reader.onload
- * @param {Function} config.reader.onabort
- * @param {Function} config.reader.onerror
- * @param {Function} config.reader.onloadend
- *
- * @param {Function} config.success This is optional.
- * The callback to be called when the data has been successfully read.
- *
- * @param {Object} config.success.data
- * The read data.
- *
- * @param {Function} config.failure This is optional.
- * The callback to be called when an error occurred.
- *
- * @param {Object} config.failure.error
- * The occurred error.
- *
- * @param {Object} config.scope
- * The scope object
- */
- read: function(config) {
- var me = this;
- this.getEntry({
- success: function(fileEntry) {
- fileEntry.file(function(file) {
- if (Ext.isNumber(config.length)) {
- if (Ext.isFunction(file.slice)) {
- file = file.slice(me.offset, config.length);
- } else {
- if (config.failure) {
- config.failure.call(config.scope || me, {
- code: -2,
- message: "File missing slice functionality"
- });
- }
- return;
- }
- }
- var reader = new FileReader();
- reader.onloadend = function(evt) {
- config.success.call(config.scope || me, evt.target.result);
- };
- reader.onerror = function(error) {
- config.failure.call(config.scope || me, error);
- };
- if (config.reader) {
- reader = Ext.applyIf(reader, config.reader);
- }
- config.encoding = config.encoding || "UTF8";
- switch (config.type) {
- default:
- case "text":
- reader.readAsText(file, config.encoding);
- break;
- case "dataURL":
- reader.readAsDataURL(file);
- break;
- case "binaryString":
- reader.readAsBinaryString(file);
- break;
- case "arrayBuffer":
- reader.readAsArrayBuffer(file);
- break;
- }
- }, function(error) {
- config.failure.call(config.scope || me, error);
- });
- },
- failure: function(error) {
- config.failure.call(config.scope || me, error);
- }
- });
- },
- /**
- * Writes the data to the file starting at the file offset.
- *
- * @param {Object} config
- * The object which contains the following config options:
- *
- * @param {Object} config.data This is required.
- * The data to write to the file.
- *
- * @param {Boolean} config.append This is optional.
- * Append to the end of the file
- *
- * @param {Object} config.writer
- * Optional config params to be applied to a File Reader
- *
- * @param {Function} config.writer.onwritestart
- * @param {Function} config.writer.onprogress
- * @param {Function} config.writer.onwrite
- * @param {Function} config.writer.onabort
- * @param {Function} config.writer.onerror
- * @param {Function} config.writer.onwriteend
- *
- * @param {Function} config.success This is optional.
- * The callback to be called when the data has been successfully written.
- *
- * @param {Function} config.failure This is optional.
- * The callback to be called when an error occurred.
- *
- * @param {Object} config.failure.error
- * The occurred error.
- *
- * @param {Object} config.scope
- * The scope object
- */
- write: function(config) {
- if (config.data == null) {
- Ext.Logger.error('Ext.device.filesystem.FileEntry#write: You must specify `data` to write into the file.');
- return null;
- }
- var me = this;
- this.getEntry({
- options: config.options || {},
- success: function(fileEntry) {
- fileEntry.createWriter(function(writer) {
- writer.onwriteend = function(evt) {
- me.length = evt.target.length;
- config.success.call(config.scope || me, evt.result);
- };
- writer.onerror = function(error) {
- config.failure.call(config.scope || me, error);
- };
- if (config.writer) {
- writer = Ext.applyIf(writer, config.writer);
- }
- if (me.offset) {
- writer.seek(me.offset);
- } else if (config.append) {
- writer.seek(me.length);
- }
- me.writeData(writer, config.data);
- }, function(error) {
- config.failure.call(config.scope || me, error);
- });
- },
- failure: function(error) {
- config.failure.call(config.scope || me, error);
- }
- });
- },
- writeData: function(writer, data) {
- writer.write(new Blob([
- data
- ]));
- },
- /**
- * Truncates or extends the file to the specified size in bytes.
- * If the file is extended, the added bytes are null bytes.
- *
- * @param {Object} config
- * The object which contains the following config options:
- *
- * @param {Number} config.size This is required.
- * The new file size.
- *
- * @param {Function} config.success This is optional.
- * The callback to be called when the file size has been successfully changed.
- *
- * @param {Function} config.failure This is optional.
- * The callback to be called when an error occurred.
- *
- * @param {Object} config.failure.error
- * The occurred error.
- *
- * @param {Object} config.scope
- * The scope object
- */
- truncate: function(config) {
- if (config.size == null) {
- Ext.Logger.error('Ext.device.filesystem.FileEntry#write: You must specify a `size` of the file.');
- return null;
- }
- var me = this;
- //noinspection JSValidateTypes
- this.getEntry({
- success: function(fileEntry) {
- fileEntry.createWriter(function(writer) {
- writer.truncate(config.size);
- config.success.call(config.scope || me, me);
- }, function(error) {
- config.failure.call(config.scope || me, error);
- });
- },
- failure: function(error) {
- config.failure.call(config.scope || me, error);
- }
- });
- }
- });
- });
- });
- /**
- * Cordova File APi Abstraction
- *
- * For more documentation see
- * http://docs.phonegap.com/en/2.7.0/cordova_file_file.md.html#File
- */
- Ext.define('Ext.device.filesystem.Cordova', {
- alternateClassName: 'Ext.device.filesystem.PhoneGap',
- extend: 'Ext.device.filesystem.HTML5',
- constructor: function() {
- Ext.override(Ext.device.filesystem.Entry, {
- /**
- *
- * @param {Object} config
- *
- * @param {Object} config.metadata
- * Metadata to add to the file or directory
- *
- * @param {Object} config.options
- * File creation options {create:true, exclusive:false}
- *
- * @param {Boolean} config.options.create
- * Indicates if the file should be created if it doesn't exist
- *
- * @param {Boolean} config.options.exclusive
- * Used with the create option only indicates whether a creation causes an error if the file already exists
- *
- * @param {Function} config.success
- * The function called when the File's Metadata is written successfully
- *
- * @param {Function} config.failure
- * The function called when the File request causes an error
- *
- * @param {FileError} config.failure.error
- *
- */
- writeMetadata: function(config) {
- var me = this;
- this.getEntry({
- options: config.options,
- success: function(entry) {
- entry.setMetadata(function() {
- config.success.call(config.scope || me);
- }, function(error) {
- config.failure.call(config.scope || me, error);
- }, config.metadata);
- },
- failure: function(error) {
- config.failure.call(config.scope || me, error);
- }
- });
- },
- /**
- *
- * @param {Object} config
- *
- * @param {Object} config.options
- * File creation options {create:true, exclusive:false}
- *
- * @param {Boolean} config.options.create
- * Indicates if the file should be created if it doesn't exist
- *
- * @param {Boolean} config.options.exclusive
- * Used with the create option only indicates whether a creation causes an error if the file already exists
- *
- * @param {Function} config.success
- * The function called when the File's Metadata is written successfully
- *
- * @param {Function} config.failure
- * The function called when the File request causes an error
- *
- * @param {FileError} config.failure.error
- *
- */
- readMetadata: function(config) {
- var me = this;
- this.getEntry({
- options: config.options,
- success: function(entry) {
- entry.getMetadata(function(metadata) {
- config.success.call(config.scope || me, metadata);
- }, function(error) {
- config.failure.call(config.scope || me, error);
- });
- },
- failure: function(error) {
- config.failure.call(config.scope || me, error);
- }
- });
- }
- });
- Ext.override(Ext.device.filesystem.FileEntry, {
- writeData: function(writer, data) {
- writer.write(data.toString());
- },
- /**
- * Send a file to a server
- *
- * @param {Object} config
- *
- * @param {String} config.url
- * URL of server to receive the file
- *
- * @param {Boolean} config.trustAllHosts
- * (Optional) If true it will accept all security certificates. Defaults to false
- *
- * @param {String} config.fileKey
- * Name of the form element. Defaults to "file"
- *
- * @param {String} config.fileName
- * Name of the file on the server
- *
- * @param {String} config.mimeType
- * mime type of the data being uploaded. defaults to "image/jpeg"
- *
- * @param {Object} config.params
- * (Optional) set of key/value pairs to be passed along with the request
- *
- * @param {Boolean} config.chunkMode
- * Should the data be uploaded in a chunked streaming mode. defaults to true
- *
- * @param {Object} config.headers
- * Map of header name => header values. Multiple values should be specified an array of values
- * var headers={'headerParam':'headerValue'};
- *
- * @param {Function} config.success
- * The function called when the File is uploaded successfully
- *
- * @param {Function} config.success.metadata
- *
- * @param {Function} config.failure
- * The function called when the File upload fails
- *
- * @param {FileError} config.failure.error
- *
- * @return {FileTransfer}
- */
- upload: function(config) {
- var options = new FileUploadOptions();
- options.fileKey = config.fileKey || "file";
- options.fileName = this.path.substr(this.path.lastIndexOf('/') + 1);
- options.mimeType = config.mimeType || "image/jpeg";
- options.params = config.params || {};
- options.headers = config.headers || {};
- options.chunkMode = config.chunkMode || true;
- var fileTransfer = new FileTransfer();
- fileTransfer.upload(this.path, encodeURI(config.url), config.success, config.failure, options, config.trustAllHosts || false);
- return fileTransfer;
- },
- /**
- * Downloads a file from the server saving it into the Local File System
- *
- * @param {Object} config
- *
- * @param {String} config.source
- * URL of file to download
- *
- * @param {Boolean} config.trustAllHosts
- * if true it will accept all security certificates. Defaults to false
- *
- * @param {Object} config.options
- * Header parameters (Auth, etc)
- *
- * {
- * headers: {
- * "Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
- * }
- * }
- *
- * @param {Function} config.success
- * The function called when the File is downloaded successfully
- *
- * @param {Function} config.success.entry
- * File Entry object of the downloaded file
- *
- * @param {Function} config.failure
- * The function called when the File download fails
- *
- * @param {FileError} config.failure.error
- *
- * @return {FileTransfer}
- */
- download: function(config) {
- var fileTransfer = new FileTransfer();
- fileTransfer.download(encodeURI(config.source), this.path, config.success, config.failure, config.trustAllHosts || false, config.options || {});
- return fileTransfer;
- }
- });
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.filesystem.Chrome', {
- extend: 'Ext.device.filesystem.HTML5',
- /**
- * Requests access to the Local File System
- *
- * var me = this;
- * var fs = Ext.create("Ext.device.File", {});
- * fs.requestFileSystem({
- * type: window.PERSISTENT,
- * size: 1024 * 1024,
- * success: function(fileSystem) {
- * me.fs = fileSystem;
- * },
- * failure: function(err) {
- * console.log("FileSystem Failure: " + err.code);
- * }
- * });
- *
- *
- * @param {Object} config An object which contains the follow options
- * @param {Number} config.type
- * window.TEMPORARY (0) or window.PERSISTENT (1)
- *
- * @param {Number} config.size
- * Storage space, in Bytes, needed by the application
- *
- * @param {Function} config.success
- * The function called when the filesystem is returned successfully
- *
- * @param {FileSystem} config.success.fs
- *
- * @param {Function} config.failure
- * The function called when the filesystem request causes and error
- *
- * @param {FileError} config.failure.error
- *
- */
- requestFileSystem: function(config) {
- var me = this;
- config = Ext.device.filesystem.Abstract.prototype.requestFileSystem(config);
- var successCallback = function(fs) {
- var fileSystem = Ext.create('Ext.device.filesystem.FileSystem', fs);
- config.success.call(config.scope || me, fileSystem);
- };
- if (config.type == window.PERSISTENT) {
- if (navigator.webkitPersistentStorage) {
- navigator.webkitPersistentStorage.requestQuota(config.size, function(grantedBytes) {
- window.webkitRequestFileSystem(config.type, grantedBytes, successCallback, config.failure);
- });
- } else {
- window.webkitStorageInfo.requestQuota(window.PERSISTENT, config.size, function(grantedBytes) {
- window.webkitRequestFileSystem(config.type, grantedBytes, successCallback, config.failure);
- });
- }
- } else {
- window.webkitRequestFileSystem(config.type, config.size, successCallback, config.failure);
- }
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.filesystem.Simulator', {
- extend: 'Ext.device.filesystem.HTML5'
- });
- /**
- * Provides an API to navigate file system hierarchies.
- *
- * @mixins Ext.device.filesystem.Sencha
- */
- Ext.define('Ext.device.FileSystem', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.filesystem.Cordova',
- 'Ext.device.filesystem.Chrome',
- 'Ext.device.filesystem.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.Cordova) {
- return Ext.create('Ext.device.filesystem.Cordova');
- }
- } else if (browserEnv.Chrome) {
- return Ext.create('Ext.device.filesystem.Chrome');
- }
- return Ext.create('Ext.device.filesystem.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.geolocation.Abstract', {
- config: {
- /**
- * @cfg {Number} maximumAge
- * This option indicates that the application is willing to accept cached location information whose age
- * is no greater than the specified time in milliseconds. If maximumAge is set to 0, an attempt to retrieve
- * new location information is made immediately.
- */
- maximumAge: 0,
- /**
- * @cfg {Number} frequency The default frequency to get the current position when using {@link Ext.device.Geolocation#watchPosition}.
- */
- frequency: 10000,
- /**
- * @cfg {Boolean} allowHighAccuracy True to allow high accuracy when getting the current position.
- */
- allowHighAccuracy: false,
- /**
- * @cfg {Number} timeout
- * The maximum number of milliseconds allowed to elapse between a location update operation.
- */
- timeout: Infinity
- },
- /**
- * Attempts to get the current position of this device.
- *
- * Ext.device.Geolocation.getCurrentPosition({
- * success: function(position) {
- * console.log(position);
- * },
- * failure: function() {
- * Ext.Msg.alert('Geolocation', 'Something went wrong!');
- * }
- * });
- *
- * *Note:* If you want to watch the current position, you could use {@link Ext.device.Geolocation#watchPosition} instead.
- *
- * @param {Object} config An object which contains the following config options:
- *
- * @param {Function} config.success
- * The function to call when the location of the current device has been received.
- *
- * @param {Object} config.success.position
- *
- * @param {Function} config.failure
- * The function that is called when something goes wrong.
- *
- * @param {Object} config.scope
- * The scope of the `success` and `failure` functions.
- *
- * @param {Number} config.maximumAge
- * The maximum age of a cached location. If you do not enter a value for this, the value of {@link #maximumAge}
- * will be used.
- *
- * @param {Number} config.timeout
- * The timeout for this request. If you do not specify a value, it will default to {@link #timeout}.
- *
- * @param {Boolean} config.allowHighAccuracy
- * True to enable allow accuracy detection of the location of the current device. If you do not specify a value, it will
- * default to {@link #allowHighAccuracy}.
- */
- getCurrentPosition: function(config) {
- var defaultConfig = Ext.device.geolocation.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- maximumAge: defaultConfig.maximumAge,
- frequency: defaultConfig.frequency,
- allowHighAccuracy: defaultConfig.allowHighAccuracy,
- timeout: defaultConfig.timeout
- });
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #getCurrentPosition');
- }
- // </debug>
- return config;
- },
- /**
- * Watches for the current position and calls the callback when successful depending on the specified {@link #frequency}.
- *
- * Ext.device.Geolocation.watchPosition({
- * callback: function(position) {
- * console.log(position);
- * },
- * failure: function() {
- * Ext.Msg.alert('Geolocation', 'Something went wrong!');
- * }
- * });
- *
- * @param {Object} config An object which contains the following config options:
- *
- * @param {Function} config.callback
- * The function to be called when the position has been updated.
- *
- * @param {Function} config.failure
- * The function that is called when something goes wrong.
- *
- * @param {Object} config.scope
- * The scope of the `success` and `failure` functions.
- *
- * @param {Boolean} config.frequency
- * The frequency in which to call the supplied callback. Defaults to {@link #frequency} if you do not specify a value.
- *
- * @param {Boolean} config.allowHighAccuracy
- * True to enable allow accuracy detection of the location of the current device. If you do not specify a value, it will
- * default to {@link #allowHighAccuracy}.
- */
- watchPosition: function(config) {
- var defaultConfig = Ext.device.geolocation.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- maximumAge: defaultConfig.maximumAge,
- frequency: defaultConfig.frequency,
- allowHighAccuracy: defaultConfig.allowHighAccuracy,
- timeout: defaultConfig.timeout
- });
- // <debug>
- if (!config.callback) {
- Ext.Logger.warn('You need to specify a `callback` function for #watchPosition');
- }
- // </debug>
- return config;
- },
- /**
- * If you are currently watching for the current position, this will stop that task.
- */
- clearWatch: function() {}
- });
- /**
- * @private
- */
- Ext.define('Ext.device.geolocation.Cordova', {
- alternateClassName: 'Ext.device.geolocation.PhoneGap',
- extend: 'Ext.device.geolocation.Abstract',
- activeWatchID: null,
- getCurrentPosition: function(config) {
- config = this.callParent(arguments);
- navigator.geolocation.getCurrentPosition(config.success, config.failure, config);
- return config;
- },
- watchPosition: function(config) {
- config = this.callParent(arguments);
- if (this.activeWatchID) {
- this.clearWatch();
- }
- this.activeWatchID = navigator.geolocation.watchPosition(config.callback, config.failure, config);
- return config;
- },
- clearWatch: function() {
- if (this.activeWatchID) {
- navigator.geolocation.clearWatch(this.activeWatchID);
- this.activeWatchID = null;
- }
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.geolocation.Simulator', {
- extend: 'Ext.device.geolocation.Abstract',
- requires: [
- 'Ext.util.Geolocation'
- ],
- getCurrentPosition: function(config) {
- config = this.callParent([
- config
- ]);
- Ext.apply(config, {
- autoUpdate: false,
- listeners: {
- scope: this,
- locationupdate: function(geolocation) {
- if (config.success) {
- config.success.call(config.scope || this, geolocation.position);
- }
- },
- locationerror: function() {
- if (config.failure) {
- config.failure.call(config.scope || this);
- }
- }
- }
- });
- this.geolocation = Ext.create('Ext.util.Geolocation', config);
- this.geolocation.updateLocation();
- return config;
- },
- watchPosition: function(config) {
- config = this.callParent([
- config
- ]);
- Ext.apply(config, {
- listeners: {
- scope: this,
- locationupdate: function(geolocation) {
- if (config.callback) {
- config.callback.call(config.scope || this, geolocation.position);
- }
- },
- locationerror: function() {
- if (config.failure) {
- config.failure.call(config.scope || this);
- }
- }
- }
- });
- this.geolocation = Ext.create('Ext.util.Geolocation', config);
- return config;
- },
- clearWatch: function() {
- if (this.geolocation) {
- this.geolocation.destroy();
- }
- this.geolocation = null;
- }
- });
- /**
- * Provides access to the native Geolocation API when running on a device. There are three implementations of this API:
- *
- * - Sencha Packager
- * - [PhoneGap](http://docs.phonegap.com/en/1.4.1/phonegap_device_device.md.html)
- * - Browser
- *
- * This class will automatically select the correct implementation depending on the device your application is running on.
- *
- * ## Examples
- *
- * Getting the current location:
- *
- * Ext.device.Geolocation.getCurrentPosition({
- * success: function(position) {
- * console.log(position.coords);
- * },
- * failure: function() {
- * console.log('something went wrong!');
- * }
- * });
- *
- * Watching the current location:
- *
- * Ext.device.Geolocation.watchPosition({
- * frequency: 3000, // Update every 3 seconds
- * callback: function(position) {
- * console.log('Position updated!', position.coords);
- * },
- * failure: function() {
- * console.log('something went wrong!');
- * }
- * });
- *
- * @mixins Ext.device.geolocation.Abstract
- */
- Ext.define('Ext.device.Geolocation', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.geolocation.Cordova',
- 'Ext.device.geolocation.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.Cordova) {
- return Ext.create('Ext.device.geolocation.Cordova');
- }
- }
- return Ext.create('Ext.device.geolocation.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.globalization.Abstract', {
- mixins: [
- 'Ext.mixin.Observable'
- ],
- config: {
- formatLength: 'full',
- selector: 'date and time',
- dateType: 'wide',
- items: 'months',
- numberType: 'decimal',
- currencyCode: "USD"
- },
- getPreferredLanguage: function(config) {
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #getPreferredLanguage');
- }
- // </debug>
- return config;
- },
- getLocaleName: function(config) {
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #getLocaleName');
- }
- // </debug>
- return config;
- },
- dateToString: function(config) {
- var defaultConfig = Ext.device.globalization.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- date: new Date(),
- formatLength: defaultConfig.formatLength,
- selector: defaultConfig.selector
- });
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #dateToString');
- }
- // </debug>
- return config;
- },
- stringToDate: function(config) {
- var defaultConfig = Ext.device.globalization.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- dateString: Ext.util.Format.date(new Date(), 'm/d/Y'),
- formatLength: defaultConfig.formatLength,
- selector: defaultConfig.selector
- });
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #stringToDate');
- }
- // </debug>
- return config;
- },
- getDatePattern: function(config) {
- var defaultConfig = Ext.device.globalization.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- formatLength: defaultConfig.formatLength,
- selector: defaultConfig.selector
- });
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #getDatePattern');
- }
- // </debug>
- return config;
- },
- getDateNames: function(config) {
- var defaultConfig = Ext.device.globalization.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- type: defaultConfig.dateType,
- items: defaultConfig.items
- });
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #getDateNames');
- }
- // </debug>
- return config;
- },
- isDayLightSavingsTime: function(config) {
- config = Ext.applyIf(config, {
- date: new Date()
- });
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #isDayLightSavingsTime');
- }
- // </debug>
- return config;
- },
- getFirstDayOfWeek: function(config) {
- // <debug>
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #getFirstDayOfWeek');
- }
- // </debug>
- return config;
- },
- numberToString: function(config) {
- var defaultConfig = Ext.device.globalization.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- number: defaultConfig.number,
- type: defaultConfig.numberType
- });
- // <debug>
- if (!config.number) {
- Ext.Logger.warn('You need to specify a `number` for #numberToString');
- }
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #numberToString');
- }
- // </debug>
- return config;
- },
- stringToNumber: function(config) {
- var defaultConfig = Ext.device.globalization.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- type: defaultConfig.numberType
- });
- // <debug>
- if (!config.number) {
- Ext.Logger.warn('You need to specify a `string` for #stringToNumber');
- }
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #stringToNumber');
- }
- // </debug>
- return config;
- },
- getNumberPattern: function(config) {
- var defaultConfig = Ext.device.globalization.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- type: defaultConfig.numberType
- });
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #getNumberPattern');
- }
- // </debug>
- return config;
- },
- getCurrencyPattern: function(config) {
- var defaultConfig = Ext.device.globalization.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- currencyCode: defaultConfig.currencyCode
- });
- if (!config.success) {
- Ext.Logger.warn('You need to specify a `success` function for #getCurrency');
- }
- // </debug>
- return config;
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.globalization.Cordova', {
- alternateClassName: 'Ext.device.globalization.PhoneGap',
- extend: 'Ext.device.globalization.Abstract',
- getPreferredLanguage: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.getPreferredLanguage(config.success, config.error);
- },
- getLocaleName: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.getLocaleName(config.success, config.error);
- },
- dateToString: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.dateToString(config.date, config.success, config.error, config);
- },
- stringToDate: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.stringToDate(config.dateString, config.success, config.error, config);
- },
- getDatePattern: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.getDatePattern(config.success, config.error, config);
- },
- getDateNames: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.getDateNames(config.success, config.error, config);
- },
- isDayLightSavingsTime: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.isDayLightSavingsTime(config.date, config.success, config.error, config);
- },
- getFirstDayOfWeek: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.getFirstDayOfWeek(config.success, config.error);
- },
- numberToString: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.numberToString(config.number, config.success, config.error, config);
- },
- stringToNumber: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.stringToNumber(config.string, config.success, config.error, config);
- },
- getNumberPattern: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.getNumberPattern(config.success, config.error, config);
- },
- getCurrencyPattern: function(config) {
- config = this.callParent(arguments);
- navigator.globalization.getCurrencyPattern(config.currencyCode, config.success, config.error);
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.globalization.Simulator', {
- extend: 'Ext.device.globalization.Abstract'
- });
- /**
- * Provides access to the native Globalization API
- *
- * - [PhoneGap](http://docs.phonegap.com/en/2.6.0/cordova_globalization_globalization.md.html)
- *
- * Class currently only works with Cordova and does not have a simulated HTML counter part.
- * Please see notes on Cordova Docs for more information.
- *
- * http://docs.phonegap.com/en/2.6.0/cordova_globalization_globalization.md.html
- */
- Ext.define('Ext.device.Globalization', {
- singleton: true,
- requires: [
- 'Ext.device.globalization.Cordova',
- 'Ext.device.globalization.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.Cordova) {
- return Ext.create('Ext.device.globalization.Cordova');
- }
- }
- return Ext.create('Ext.device.globalization.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.media.Abstract', {
- mixins: [
- 'Ext.mixin.Observable'
- ],
- config: {
- src: null
- },
- play: Ext.emptyFn,
- pause: Ext.emptyFn,
- stop: Ext.emptyFn,
- release: Ext.emptyFn,
- seekTo: Ext.emptyFn,
- getCurrentPosition: Ext.emptyFn,
- getDuration: Ext.emptyFn,
- startRecord: Ext.emptyFn,
- stopRecord: Ext.emptyFn
- });
- /**
- * @private
- */
- Ext.define('Ext.device.media.Cordova', {
- alternateClassName: 'Ext.device.media.PhoneGap',
- extend: 'Ext.device.media.Abstract',
- config: {
- /**
- * A URI containing the audio content.
- * @type {String}
- */
- src: null,
- /**
- * @private
- */
- media: null
- },
- updateSrc: function(newSrc, oldSrc) {
- this.setMedia(new Media(newSrc));
- },
- play: function() {
- var media = this.getMedia();
- if (media) {
- media.play();
- }
- },
- pause: function() {
- var media = this.getMedia();
- if (media) {
- media.pause();
- }
- },
- stop: function() {
- var media = this.getMedia();
- if (media) {
- media.stop();
- }
- },
- release: function() {
- var media = this.getMedia();
- if (media) {
- media.release();
- }
- },
- seekTo: function(miliseconds) {
- var media = this.getMedia();
- if (media) {
- media.seekTo(miliseconds);
- }
- },
- getDuration: function() {
- var media = this.getMedia();
- if (media) {
- media.getDuration();
- }
- },
- startRecord: function() {
- var media = this.getMedia();
- if (!media) {
- this.setSrc(null);
- }
- media.startRecord();
- },
- stopRecord: function() {
- var media = this.getMedia();
- if (media) {
- media.stopRecord();
- }
- }
- });
- /**
- * @mixins Ext.device.media.Abstract
- */
- Ext.define('Ext.device.Media', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.media.Cordova'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView && browserEnv.Cordova) {
- return Ext.create('Ext.device.media.Cordova');
- }
- return Ext.create('Ext.device.media.Abstract');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.notification.Abstract', {
- /**
- * A simple way to show a notification.
- *
- * Ext.device.Notification.show({
- * title: 'Verification',
- * message: 'Is your email address is: test@sencha.com',
- * buttons: Ext.MessageBox.OKCANCEL,
- * callback: function(button) {
- * if (button == "ok") {
- * console.log('Verified');
- * } else {
- * console.log('Nope.');
- * }
- * }
- * });
- *
- * @param {Object} config An object which contains the following config options:
- *
- * @param {String} config.title The title of the notification
- *
- * @param {String} config.message The message to be displayed on the notification
- *
- * @param {String/String[]} [config.buttons="OK"]
- * The buttons to be displayed on the notification. It can be a string, which is the title of the button, or an array of multiple strings.
- * Please not that you should not use more than 2 buttons, as they may not be displayed correct on all devices.
- *
- * @param {Function} config.callback
- * A callback function which is called when the notification is dismissed by clicking on the configured buttons.
- * @param {String} config.callback.buttonId The id of the button pressed, one of: 'ok', 'yes', 'no', 'cancel'.
- *
- * @param {Object} config.scope The scope of the callback function
- */
- show: function(config) {
- if (!config.message) {
- throw ('[Ext.device.Notification#show] You passed no message');
- }
- if (!config.buttons) {
- config.buttons = [
- "OK",
- "Cancel"
- ];
- }
- if (!Ext.isArray(config.buttons)) {
- config.buttons = [
- config.buttons
- ];
- }
- if (!config.scope) {
- config.scope = this;
- }
- return config;
- },
- alert: function(config) {
- if (!config.message) {
- throw ('[Ext.device.Notification#alert] You passed no message');
- }
- if (!config.scope) {
- config.scope = this;
- }
- return config;
- },
- confirm: function(config) {
- if (!config.message) {
- throw ('[Ext.device.Notification#confirm] You passed no message');
- }
- if (!config.buttons) {
- config.buttons = [
- "OK",
- "Cancel"
- ];
- }
- if (!Ext.isArray(config.buttons)) {
- config.buttons = [
- config.buttons
- ];
- }
- if (!config.scope) {
- config.scope = this;
- }
- return config;
- },
- prompt: function(config) {
- if (!config.message) {
- throw ('[Ext.device.Notification#prompt] You passed no message');
- }
- if (!config.buttons) {
- config.buttons = [
- "OK",
- "Cancel"
- ];
- }
- if (!Ext.isArray(config.buttons)) {
- config.buttons = [
- config.buttons
- ];
- }
- if (!config.scope) {
- config.scope = this;
- }
- return config;
- },
- /**
- * Vibrates the device.
- */
- vibrate: Ext.emptyFn,
- beep: Ext.emptyFn
- });
- /**
- * @private
- */
- Ext.define('Ext.device.notification.Cordova', {
- alternateClassName: 'Ext.device.notification.PhoneGap',
- extend: 'Ext.device.notification.Abstract',
- requires: [
- 'Ext.device.Communicator'
- ],
- show: function(config) {
- config = this.callParent(arguments);
- this.confirm(config);
- },
- confirm: function(config) {
- config = this.callParent(arguments);
- var buttons = config.buttons,
- ln = config.buttons.length;
- if (ln && typeof buttons[0] != "string") {
- var newButtons = [],
- i;
- for (i = 0; i < ln; i++) {
- newButtons.push(buttons[i].text);
- }
- buttons = newButtons;
- }
- var callback = function(index) {
- if (config.callback) {
- config.callback.apply(config.scope, (buttons) ? [
- buttons[index - 1].toLowerCase()
- ] : []);
- }
- };
- navigator.notification.confirm(config.message, callback, config.title, buttons);
- },
- alert: function(config) {
- navigator.notification.alert(config.message, config.callback, config.title, config.buttonName);
- },
- prompt: function(config) {
- config = this.callParent(arguments);
- var buttons = config.buttons,
- ln = config.buttons.length;
- if (ln && typeof buttons[0] != "string") {
- var newButtons = [],
- i;
- for (i = 0; i < ln; i++) {
- newButtons.push(buttons[i].text);
- }
- buttons = newButtons;
- }
- var callback = function(result) {
- if (config.callback) {
- config.callback.call(config.scope, (buttons) ? buttons[result.buttonIndex - 1].toLowerCase() : null, result.input1);
- }
- };
- navigator.notification.prompt(config.message, callback, config.title, buttons);
- },
- vibrate: function(time) {
- navigator.notification.vibrate(time);
- },
- beep: function(times) {
- navigator.notification.vibrate(times);
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.notification.Simulator', {
- extend: 'Ext.device.notification.Abstract',
- requires: [
- 'Ext.MessageBox',
- 'Ext.util.Audio'
- ],
- /**
- * @private
- */
- msg: null,
- show: function() {
- var config = this.callParent(arguments),
- buttons = [],
- ln = config.buttons.length,
- button, i, callback;
- //buttons
- for (i = 0; i < ln; i++) {
- button = config.buttons[i];
- if (Ext.isString(button)) {
- button = {
- text: config.buttons[i],
- itemId: config.buttons[i].toLowerCase()
- };
- }
- buttons.push(button);
- }
- this.msg = Ext.create('Ext.MessageBox');
- callback = function(itemId) {
- if (config.callback) {
- config.callback.apply(config.scope, [
- itemId
- ]);
- }
- };
- this.msg.show({
- title: config.title,
- message: config.message,
- scope: this.msg,
- buttons: buttons,
- fn: callback
- });
- },
- alert: function() {
- var config = this.callParent(arguments);
- if (config.buttonName) {
- config.buttons = [
- config.buttonName
- ];
- }
- this.show(config);
- },
- confirm: function() {
- var config = this.callParent(arguments);
- this.show(config);
- },
- prompt: function() {
- var config = this.callParent(arguments),
- buttons = [],
- ln = config.buttons.length,
- button, i, callback;
- //buttons
- for (i = 0; i < ln; i++) {
- button = config.buttons[i];
- if (Ext.isString(button)) {
- button = {
- text: config.buttons[i],
- itemId: config.buttons[i].toLowerCase()
- };
- }
- buttons.push(button);
- }
- this.msg = Ext.create('Ext.MessageBox');
- callback = function(buttonText, value) {
- if (config.callback) {
- config.callback.apply(config.scope, [
- buttonText,
- value
- ]);
- }
- };
- this.msg.prompt(config.title, config.message, callback, this.msg, config.multiLine, config.value, config.prompt);
- },
- beep: function(times) {
- if (!Ext.isNumber(times)) {
- times = 1;
- }
-
- var count = 0;
- var callback = function() {
- if (count < times) {
- Ext.defer(function() {
- Ext.util.Audio.beep(callback);
- }, 50);
- }
- count++;
- };
- callback();
- },
- vibrate: function() {
- //nice animation to fake vibration
- var animation = [
- "@-webkit-keyframes vibrate{",
- " from {",
- " -webkit-transform: rotate(-2deg);",
- " }",
- " to{",
- " -webkit-transform: rotate(2deg);",
- " }",
- "}",
- "body {",
- " -webkit-animation: vibrate 50ms linear 10 alternate;",
- "}"
- ];
- var head = document.getElementsByTagName("head")[0];
- var cssNode = document.createElement('style');
- cssNode.innerHTML = animation.join('\n');
- head.appendChild(cssNode);
- Ext.defer(function() {
- head.removeChild(cssNode);
- }, 400);
- }
- });
- /**
- * Provides a cross device way to show notifications. There are three different implementations:
- *
- * - Sencha Packager
- * - Cordova
- * - Simulator
- *
- * When this singleton is instantiated, it will automatically use the correct implementation depending on the current device.
- *
- * Both the Sencha Packager and Cordova versions will use the native implementations to display the notification. The
- * Simulator implementation will use {@link Ext.MessageBox} for {@link #show} and a simply animation when you call {@link #vibrate}.
- *
- * ## Examples
- *
- * To show a simple notification:
- *
- * Ext.device.Notification.show({
- * title: 'Verification',
- * message: 'Is your email address: test@sencha.com',
- * buttons: Ext.MessageBox.OKCANCEL,
- * callback: function(button) {
- * if (button === "ok") {
- * console.log('Verified');
- * } else {
- * console.log('Nope');
- * }
- * }
- * });
- *
- * To make the device vibrate:
- *
- * Ext.device.Notification.vibrate();
- *
- * @mixins Ext.device.notification.Abstract
- */
- Ext.define('Ext.device.Notification', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.notification.Cordova',
- 'Ext.device.notification.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.Cordova) {
- return Ext.create('Ext.device.notification.Cordova');
- }
- }
- return Ext.create('Ext.device.notification.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.orientation.Abstract', {
- mixins: [
- 'Ext.mixin.Observable'
- ],
- /**
- * @event orientationchange
- * Fires when the orientation has been changed on this device.
- *
- * Ext.device.Orientation.on({
- * scope: this,
- * orientationchange: function(e) {
- * console.log('Alpha: ', e.alpha);
- * console.log('Beta: ', e.beta);
- * console.log('Gamma: ', e.gamma);
- * }
- * });
- *
- * @param {Object} event The event object
- * @param {Object} event.alpha The alpha value of the orientation event
- * @param {Object} event.beta The beta value of the orientation event
- * @param {Object} event.gamma The gamma value of the orientation event
- */
- onDeviceOrientation: function(e) {
- this.doFireEvent('orientationchange', [
- e
- ]);
- }
- });
- /**
- * Provides the HTML5 implementation for the orientation API.
- * @private
- */
- Ext.define('Ext.device.orientation.HTML5', {
- extend: 'Ext.device.orientation.Abstract',
- constructor: function() {
- this.callParent(arguments);
- this.onDeviceOrientation = Ext.Function.bind(this.onDeviceOrientation, this);
- window.addEventListener('deviceorientation', this.onDeviceOrientation, true);
- }
- });
- /**
- * This class provides you with a cross platform way of listening to when the the orientation changes on the
- * device your application is running on.
- *
- * The {@link Ext.device.Orientation#orientationchange orientationchange} event gets passes the `alpha`, `beta` and
- * `gamma` values. ** These properties only exist when packaging with the Sencha Native Packager. **
- *
- * You can find more information about these values and how to use them on the [W3C device orientation specification](http://dev.w3.org/geo/api/spec-source-orientation.html#deviceorientation).
- *
- * ## Example
- *
- * To listen to the device orientation, you can do the following:
- *
- * Ext.device.Orientation.on({
- * scope: this,
- * orientationchange: function(e) {
- * console.log('Alpha: ', e.alpha);
- * console.log('Beta: ', e.beta);
- * console.log('Gamma: ', e.gamma);
- * }
- * });
- *
- * @mixins Ext.device.orientation.Abstract
- */
- Ext.define('Ext.device.Orientation', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.orientation.HTML5'
- ],
- constructor: function() {
- return Ext.create('Ext.device.orientation.HTML5');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.push.Abstract', {
- /**
- * @property
- * Notification type: alert.
- */
- ALERT: 1,
- /**
- * @property
- * Notification type: badge.
- */
- BADGE: 2,
- /**
- * @property
- * Notification type: sound.
- */
- SOUND: 4,
- /**
- * @method getInitialConfig
- * @hide
- */
- /**
- * Registers a push notification.
- *
- * Ext.device.Push.register({
- * type: Ext.device.Push.ALERT|Ext.device.Push.BADGE|Ext.device.Push.SOUND,
- * success: function(token) {
- * console.log('# Push notification registration successful:');
- * console.log(' token: ' + token);
- * },
- * failure: function(error) {
- * console.log('# Push notification registration unsuccessful:');
- * console.log(' error: ' + error);
- * },
- * received: function(notifications) {
- * console.log('# Push notification received:');
- * console.log(' ' + JSON.stringify(notifications));
- * }
- * });
- *
- * @param {Object} config
- * The configuration for to pass when registering this push notification service.
- *
- * @param {Number} config.type
- * The type(s) of notifications to enable. Available options are:
- *
- * - {@link Ext.device.Push#ALERT}
- * - {@link Ext.device.Push#BADGE}
- * - {@link Ext.device.Push#SOUND}
- *
- * **Usage**
- *
- * Enable alerts and badges:
- *
- * Ext.device.Push.register({
- * type: Ext.device.Push.ALERT|Ext.device.Push.BADGE
- * // ...
- * });
- *
- * Enable alerts, badges and sounds:
- *
- * Ext.device.Push.register({
- * type: Ext.device.Push.ALERT|Ext.device.Push.BADGE|Ext.device.Push.SOUND
- * // ...
- * });
- *
- * Enable only sounds:
- *
- * Ext.device.Push.register({
- * type: Ext.device.Push.SOUND
- * // ...
- * });
- *
- * @param {Function} config.success
- * The callback to be called when registration is complete.
- *
- * @param {String} config.success.token
- * A unique token for this push notification service.
- *
- * @param {Function} config.failure
- * The callback to be called when registration fails.
- *
- * @param {String} config.failure.error
- * The error message.
- *
- * @param {Function} config.received
- * The callback to be called when a push notification is received on this device.
- *
- * @param {Object} config.received.notifications
- * The notifications that have been received.
- */
- register: function(config) {
- var me = this;
- if (!config.received) {
- Ext.Logger.error('Failed to pass a received callback. This is required.');
- }
- if (config.type == null) {
- Ext.Logger.error('Failed to pass a type. This is required.');
- }
- return {
- success: function(token) {
- me.onSuccess(token, config.success, config.scope || me);
- },
- failure: function(error) {
- me.onFailure(error, config.failure, config.scope || me);
- },
- received: function(notifications) {
- me.onReceived(notifications, config.received, config.scope || me);
- },
- type: config.type
- };
- },
- onSuccess: function(token, callback, scope) {
- if (callback) {
- callback.call(scope, token);
- }
- },
- onFailure: function(error, callback, scope) {
- if (callback) {
- callback.call(scope, error);
- }
- },
- onReceived: function(notifications, callback, scope) {
- if (callback) {
- callback.call(scope, notifications);
- }
- }
- });
- /**
- * @private
- * Interfaces with Cordova PushPlugin: https://github.com/phonegap-build/PushPlugin
- */
- Ext.define('Ext.device.push.Cordova', {
- extend: 'Ext.device.push.Abstract',
- statics: {
- /**
- * @private
- * A collection of callback methods that can be globally called by the Cordova PushPlugin
- */
- callbacks: {}
- },
- setPushConfig: function(config) {
- var methodName = Ext.id(null, 'callback');
- //Cordova's PushPlugin needs a static method to call when notifications are received
- Ext.device.push.Cordova.callbacks[methodName] = config.callbacks.received;
- return {
- "badge": (config.callbacks.type === Ext.device.Push.BADGE) ? "true" : "false",
- "sound": (config.callbacks.type === Ext.device.Push.SOUND) ? "true" : "false",
- "alert": (config.callbacks.type === Ext.device.Push.ALERT) ? "true" : "false",
- "ecb": 'Ext.device.push.Cordova.callbacks.' + methodName,
- "senderID": config.senderID
- };
- },
- register: function() {
- var config = arguments[0];
- config.callbacks = this.callParent(arguments);
- var pushConfig = this.setPushConfig(config),
- plugin = window.plugins.pushNotification;
- plugin.register(config.callbacks.success, config.callbacks.failure, pushConfig);
- }
- });
- /**
- * Provides a way to send push notifications to a device.
- *
- * # Example
- *
- * Ext.device.Push.register({
- * type: Ext.device.Push.ALERT|Ext.device.Push.BADGE|Ext.device.Push.SOUND,
- * success: function(token) {
- * console.log('# Push notification registration successful:');
- * console.log(' token: ' + token);
- * },
- * failure: function(error) {
- * console.log('# Push notification registration unsuccessful:');
- * console.log(' error: ' + error);
- * },
- * received: function(notifications) {
- * console.log('# Push notification received:');
- * console.log(' ' + JSON.stringify(notifications));
- * }
- * });
- *
- *
- * ## Sencha Cmd
- *
- * Currently only available on iOS for apps packaged with Sencha Cmd.
- *
- * ## Cordova / PhoneGap
- *
- * For apps packaged with Cordova or PhoneGap, Ext.device.Push currently supports iOS and
- * Android via the [PushPlugin](https://github.com/phonegap-build/PushPlugin).
- *
- * Be sure to include that plugin in your project; Ext.device.Push simply normalizes the
- * interface for using notifications in your application.
- *
- * @mixins Ext.device.push.Abstract
- */
- Ext.define('Ext.device.Push', {
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.push.Cordova'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.Cordova) {
- return Ext.create('Ext.device.push.Cordova');
- }
- }
- return Ext.create('Ext.device.push.Abstract');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.splashscreen.Abstract', {
- show: Ext.emptyFn,
- hide: Ext.emptyFn
- });
- /**
- * @private
- */
- Ext.define('Ext.device.splashscreen.Cordova', {
- alternateClassName: 'Ext.device.splashscreen.PhoneGap',
- extend: 'Ext.device.splashscreen.Abstract',
- show: function() {
- navigator.splashscreen.show();
- },
- hide: function() {
- navigator.splashscreen.hide();
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.splashscreen.Simulator', {
- extend: 'Ext.device.splashscreen.Abstract'
- });
- /**
- * Provides access to the native Splashscreen API
- *
- * - [PhoneGap](http://docs.phonegap.com/en/2.6.0/cordova_splashscreen_splashscreen.md.html#Splashscreen)
- *
- * Class currently only works with Cordova and does not have a simulated HTML counter part.
- * Please see notes on Cordova Docs for proper Native project code changes that
- * will need to be made to use this plugin.
- *
- * http://docs.phonegap.com/en/2.6.0/cordova_splashscreen_splashscreen.md.html#Splashscreen
- */
- Ext.define('Ext.device.Splashscreen', {
- singleton: true,
- requires: [
- 'Ext.device.splashscreen.Cordova',
- 'Ext.device.splashscreen.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.Cordova) {
- return Ext.create('Ext.device.splashscreen.Cordova');
- }
- }
- return Ext.create('Ext.device.splashscreen.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.storage.Abstract', {
- config: {
- databaseName: "Sencha",
- databaseVersion: '1.0',
- databaseDisplayName: 'Sencha Database',
- databaseSize: 5 * 1024 * 1024
- },
- openDatabase: function(config) {
- var defaultConfig = Ext.device.storage.Abstract.prototype.config;
- config = Ext.applyIf(config, {
- name: defaultConfig.databaseName,
- version: defaultConfig.databaseVersion,
- displayName: defaultConfig.databaseDisplayName,
- size: defaultConfig.databaseSize
- });
- return config;
- },
- numKeys: Ext.emptyFn,
- getKey: Ext.emptyFn,
- getItem: Ext.emptyFn,
- setItem: Ext.emptyFn,
- removeItem: Ext.emptyFn,
- clear: Ext.emptyFn
- });
- /**
- * @private
- */
- Ext.define("Ext.device.storage.HTML5.SQLStatement", {
- extend: 'Ext.Base',
- sql: null,
- "arguments": null,
- success: Ext.emptyFn,
- failure: Ext.emptyFn,
- constructor: function(config) {
- this.sql = config.sql;
- this.arguments = config.arguments;
- this.success = config.success;
- this.failure = config.failure;
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.storage.HTML5.Database', {
- requires: [
- "Ext.device.storage.HTML5.SQLStatement"
- ],
- db: null,
- constructor: function(config) {
- this.db = window.openDatabase(config.name, config.version, config.displayName, config.size);
- },
- getVersion: function() {
- if (this.db) {
- return this.db.version;
- }
- // <debug>
- Ext.Logger.warn('Database has not been opened before calling function #getVersion');
- // </debug>
- return null;
- },
- /**
- * @param {String/String[]/Object/Object[]/SQLStatement/SQLStatement[]} sql SQL Command to run with optional arguments and callbacks
- * @param {Function} success callback for successful transaction
- * @param {Function} failure callback for failed transaction
- */
- transaction: function(sql, success, failure) {
- if (!this.db) {
- // <debug>
- Ext.Logger.warn('Database has not been opened before calling function #transaction');
- // </debug>
- return;
- }
- if (!Ext.isArray(sql)) {
- sql = [
- sql
- ];
- }
- var txFn = function(tx) {
- Ext.each(sql, function(sqlStatement) {
- if (Ext.isString(sqlStatement)) {
- tx.executeSql(sqlStatement);
- } else if (Ext.isObject(sqlStatement)) {
- tx.executeSql(sqlStatement.sql, sqlStatement.arguments, sqlStatement.success, sqlStatement.failure);
- }
- });
- };
- this.db.transaction(txFn, failure, success);
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.storage.HTML5.HTML5', {
- extend: 'Ext.device.storage.Abstract',
- requires: [
- 'Ext.device.storage.HTML5.Database'
- ],
- dbCache: {},
- openDatabase: function(config) {
- config = this.callParent(arguments);
- if (!this.dbCache[config.name] || config.noCache) {
- this.dbCache[config.name] = Ext.create('Ext.device.storage.HTML5.Database', config);
- }
- return this.dbCache[config.name];
- },
- numKeys: function() {
- return window.localStorage.length;
- },
- getKey: function(index) {
- return window.localStorage.key(index);
- },
- getItem: function(key) {
- return window.localStorage.getItem(key);
- },
- setItem: function(key, value) {
- return window.localStorage.setItem(key, value);
- },
- removeItem: function(key) {
- return window.localStorage.removeItem(key);
- },
- clear: function() {
- return window.localStorage.clear();
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.storage.Cordova', {
- alternateClassName: 'Ext.device.storage.PhoneGap',
- extend: 'Ext.device.storage.HTML5.HTML5'
- });
- /**
- * @private
- */
- Ext.define('Ext.device.storage.Simulator', {
- extend: 'Ext.device.storage.HTML5.HTML5'
- });
- /**
- *
- */
- Ext.define('Ext.device.Storage', {
- singleton: true,
- requires: [
- 'Ext.device.storage.Cordova',
- 'Ext.device.storage.Simulator'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView) {
- if (browserEnv.Cordova) {
- return Ext.create('Ext.device.storage.Cordova');
- }
- }
- return Ext.create('Ext.device.storage.Simulator');
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.twitter.Abstract', {
- /**
- * Pops up a Twitter compose sheet view with your specified tweet.
- *
- * @param {Object} config An object which contains the following config options:
- *
- * @param {String} config.tweet The default tweet text to add to the compose window.
- *
- * @param {String} config.url An optional URL to attatch to the Tweet.
- *
- * @param {String} config.image An optional image URL to attatch to the Tweet.
- *
- * @param {Function} config.success The callback when the Tweet is successfully posted.
- *
- * @param {Function} config.failure The callback when the Tweet is unsuccessfully posted.
- */
- compose: Ext.emptyFn,
- /**
- * Gets Tweets from Twitter Timeline
- *
- * @param {Object} config An object which contains the following config options:
- *
- * @param {Function} config.success callback
- * @param {Object[]} config.success.response Tweet objects, see [Twitter Timeline Doc]
- *
- * @param {Function} config.failure callback
- * @param {String} config.failure.error reason for failure
- *
- * [Twitter Timeline Doc]: https://dev.twitter.com/docs/api/1/get/statuses/public_timeline
- */
- getPublicTimeline: Ext.emptyFn,
- /**
- * Gets Tweets from Twitter Mentions
- *
- * @param {Object} config An object which contains the following config options:
- *
- * @param {Function} config.success callback
- * @param {Object[]} config.success.response Tweet objects, see [Twitter Mentions Doc]
- *
- * @param {Function} config.failure callback
- * @param {String} config.failure.error reason for failure
- *
- * [Twitter Timeline Doc]: https://dev.twitter.com/docs/api/1/get/statuses/public_timeline
- */
- getMentions: Ext.emptyFn,
- /**
- * Gets a specific Twitter user info
- *
- * @param {Object} config An object which contains the following config options:
- *
- * @param {Function} config.success callback
- * @param {Object[]} config.success.response The JSON response form twitter
- *
- * @param {Function} config.failure callback
- * @param {String} config.failure.error reason for failure
- */
- getTwitterUsername: Ext.emptyFn,
- /**
- * Gets a specific Twitter user info
- *
- * @param {Object} config An object which contains the following config options:
- *
- * @param {String} config.url of [Twitter API Endpoint]
- *
- * @param {Object} config.params key-value map, matching [Twitter API Endpoint]
- *
- * @param {Object} config.options (optional) other options for the HTTP request
- * @param {String} config.options.requestMethod HTTP Request type, ex: "POST"
- *
- * @param {Function} config.success callback
- * @param {Object[]} config.success.response objects returned from Twitter API (Tweets, Users,...)
- *
- * @param {Function} config.failure callback
- * @param {String} config.failure.error reason for failure
- *
- * [Twitter API Endpoint]: https://dev.twitter.com/docs/api
- */
- getTwitterRequest: Ext.emptyFn
- });
- /**
- * @private
- */
- Ext.define('Ext.device.twitter.Cordova', {
- compose: function(config) {
- window.plugins.twitter.composeTweet(config.success, config.failure, config.tweet, {
- urlAttach: config.url,
- imageAttach: config.image
- });
- },
- getPublicTimeline: function(config) {
- window.plugins.twitter.getPublicTimeline(config.success, config.failure);
- },
- getMentions: function(config) {
- window.plugins.twitter.getMentions(config.success, config.failure);
- },
- getTwitterUsername: function(config) {
- window.plugins.twitter.getTwitterUsername(config.success, config.failure);
- },
- getTwitterRequest: function(config) {
- window.plugins.twitter.getTWRequest(config.url, config.params, config.success, config.failure, config.options);
- }
- });
- /**
- * Allows you to interact with the Twitter API on iOS devices from within your Cordova application.
- *
- * For setup information, please read the [plugin guide](https://github.com/phonegap/phonegap-plugins/tree/master/iOS/Twitter).
- *
- * @mixins Ext.device.twitter.Abstract
- */
- Ext.define('Ext.device.Twitter', {
- alternateClassName: 'Ext.ux.device.Twitter',
- singleton: true,
- requires: [
- 'Ext.device.Communicator',
- 'Ext.device.twitter.*'
- ],
- constructor: function() {
- var browserEnv = Ext.browser.is;
- if (browserEnv.WebView && browserEnv.Cordova) {
- return Ext.create('Ext.device.twitter.Cordova');
- } else {
- return Ext.create('Ext.device.twitter.Abstract');
- }
- }
- });
- /**
- * @private
- */
- Ext.define('Ext.device.browser.Window', {
- extend: 'Ext.Evented',
- open: function(config) {
- var me = this;
- this._window = window.open(config.url, config.showToolbar ? '_blank' : '_self', config.options || null);
- // Add events
- this._window.addEventListener('loadstart', function() {
- me.fireEvent('loadstart', me);
- });
- this._window.addEventListener('loadstop', function() {
- me.fireEvent('loadstop', me);
- });
- this._window.addEventListener('loaderror', function() {
- me.fireEvent('loaderror', me);
- });
- this._window.addEventListener('exit', function() {
- me.fireEvent('close', me);
- });
- },
- close: function() {
- if (!this._window) {
- return;
- }
- this._window.close();
- }
- });
|