1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954 |
- /**
- * 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,
- 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,
- 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,
- fullPath = this.path + config.path,
- 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,
- fullPath = this.path + config.path,
- 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,
- 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,
- 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;",
- "}"
- ],
- head = document.getElementsByTagName("head")[0],
- 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();
- }
- });
|