lungo-1.0.1.js 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887
  1. /**
  2. *
  3. * /$$
  4. * | $$
  5. * | $$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$
  6. * | $$ | $$ | $$| $$__ $$ /$$__ $$ /$$__ $$
  7. * | $$ | $$ | $$| $$ \ $$| $$ \ $$| $$ \ $$
  8. * | $$ | $$ | $$| $$ | $$| $$ | $$| $$ | $$
  9. * | $$$$$$$$| $$$$$$/| $$ | $$| $$$$$$$| $$$$$$/
  10. * |________/ \______/ |__/ |__/ \____ $$ \______/
  11. * /$$ \ $$
  12. * | $$$$$$/
  13. * \______/
  14. *
  15. * @copyright 2011 TapQuo Inc (c)
  16. * @license http://www.github.com/tapquo/lungo/blob/master/LICENSE.txt
  17. * @version 1.0
  18. * @link https://github.com/TapQuo/Lungo.js
  19. *
  20. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  21. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  22. */
  23. var LUNGO = LUNGO || {};
  24. LUNGO.VERSION = '1.0.1';
  25. LUNGO.Attributes || (LUNGO.Attributes = {});
  26. LUNGO.Data || (LUNGO.Data = {});
  27. LUNGO.Sugar || (LUNGO.Sugar = {});
  28. LUNGO.View || (LUNGO.View = {});/**
  29. * Lungo sandbox APP initialization
  30. *
  31. * @namespace LUNGO
  32. * @class App
  33. *
  34. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  35. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  36. */
  37. LUNGO.App = (function(lng, undefined) {
  38. var default_config = {
  39. id: 1,
  40. name: 'lungo_app',
  41. version: 1.0,
  42. icon: ''
  43. };
  44. /**
  45. * Initializes all LungoJS system: setting properties for the application,
  46. * subscribing to automatic events, initializing sections & articles
  47. * and stating the title.
  48. *
  49. * @method init
  50. *
  51. * @param {object} Application configuration properties
  52. */
  53. var init = function(app_config) {
  54. default_config = lng.Core.mix(default_config, app_config);
  55. lng.Boot();
  56. };
  57. var get = function(property) {
  58. return default_config[property];
  59. };
  60. return {
  61. init: init,
  62. get: get
  63. };
  64. })(LUNGO);/**
  65. * Set environment (Desktop or Mobile) automatically, depending on the
  66. * environment the subscribed events wil be different.
  67. *
  68. * @namespace LUNGO
  69. * @class Environment
  70. *
  71. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  72. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  73. */
  74. LUNGO.Environment = (function(lng, undefined) {
  75. var MOBILE_ENVIRONMENT = 'mobile';
  76. var DESKTOP_ENVIRONMENT = 'desktop';
  77. var _environment = DESKTOP_ENVIRONMENT;
  78. /**
  79. * Analizing if it's run in Mobile Phone and changing the type of event to subscribe.
  80. *
  81. * @method start
  82. */
  83. var start = function() {
  84. if (lng.Core.isMobile()) {
  85. _environment = MOBILE_ENVIRONMENT;
  86. _saveStatsInLungoJS();
  87. }
  88. };
  89. /**
  90. * Gets the current environment for LungoJS
  91. *
  92. * @method init
  93. *
  94. * @return {String} Current environment enumerator
  95. */
  96. var current = function() {
  97. return _environment;
  98. };
  99. /**
  100. * Returns whether the development environment is in desktop mode
  101. *
  102. * @method isDesktop
  103. *
  104. * @return {Boolean} True if is in DESKTOP_ENVIRONMENT
  105. */
  106. var isDesktop = function() {
  107. return (_environment === DESKTOP_ENVIRONMENT) ? true : false;
  108. };
  109. /**
  110. * Save in LungoJS.com the use of the service for further ranking
  111. *
  112. * @method _saveStatsInLungoJS
  113. */
  114. var _saveStatsInLungoJS = function() {
  115. lng.Service.post( 'http://www.lungojs.com/stats/', {
  116. name: lng.App.get('name'),
  117. version: lng.App.get('version'),
  118. icon: lng.App.get('icon')
  119. });
  120. }
  121. return {
  122. start: start,
  123. current: current,
  124. isDesktop: isDesktop
  125. };
  126. })(LUNGO);/**
  127. * Contains all the common functions used in Lungo.
  128. *
  129. * @namespace LUNGO
  130. * @class Core
  131. *
  132. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  133. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  134. */
  135. LUNGO.Core = (function(lng, $, undefined) {
  136. var ARRAY_PROTO = Array.prototype;
  137. var OBJ_PROTO = Object.prototype;
  138. var SUPPORTED_OS = ['ios', 'android', 'blackberry', 'webos'];
  139. /**
  140. * Console system to display messages when you are in debug mode.
  141. *
  142. * @method log
  143. *
  144. * @param {number} Severity based in (1)Log, (2)Warn, (>2)Error
  145. * @param {string} Message to show in console
  146. */
  147. var log = function(severity, message) {
  148. if (lng.Environment.isDesktop()) {
  149. console[(severity === 1) ? 'log' : (severity === 2) ? 'warn' : 'error'](message);
  150. } else {
  151. // @todo : send to the server
  152. }
  153. };
  154. /**
  155. * Executes callbacks based on the parameters received.
  156. *
  157. * @method execute
  158. *
  159. * @param {Function} callback to execute
  160. */
  161. var execute = function() {
  162. var args = toArray(arguments);
  163. var callback = args.shift();
  164. if (toType(callback) === 'function') {
  165. callback.apply(null, args);
  166. }
  167. };
  168. /**
  169. * Creates a new function that, when called, itself calls this function in
  170. * the context of the provided this value, with a given sequence of arguments
  171. * preceding any provided when the new function was called.
  172. *
  173. * @method bind
  174. *
  175. * @param {object} object to which the 'this' can refer in the new function when the new function is called.
  176. * @param {Function} method A function object.
  177. */
  178. var bind = function(object, method) {
  179. return function() {
  180. return method.apply(object, toArray(arguments));
  181. };
  182. };
  183. /**
  184. * Copy from any number of objects and mix them all into a new object.
  185. * The implementation is simple; just loop through arguments and
  186. * copy every property of every object passed to the function.
  187. *
  188. * @method mix
  189. *
  190. * @param {object} arguments to mix them all into a new object.
  191. * @return {object} child a new object with all the objects from the arguments mixed.
  192. */
  193. var mix = function() {
  194. var child = child || {};
  195. for (var arg = 0, len = arguments.length; arg < len; arg++) {
  196. var argument = arguments[arg];
  197. for (var prop in argument) {
  198. if (isOwnProperty(argument, prop)) {
  199. child[prop] = argument[prop];
  200. }
  201. }
  202. }
  203. return child;
  204. };
  205. /**
  206. * Every object descended from Object inherits the hasOwnProperty method.
  207. * This method can be used to determine whether an object has the specified property
  208. * as a direct property of that object.
  209. *
  210. * @param {object} object to test for a property's existence inside itself.
  211. * @param {string} property the name of the property to test.
  212. * @return {boolean} indicating whether the object has the specified property.
  213. */
  214. var isOwnProperty = function(object, property) {
  215. return OBJ_PROTO.hasOwnProperty.call(object, property);
  216. };
  217. /**
  218. * Determine the internal JavaScript [[Class]] of an object.
  219. *
  220. * @param {object} obj to get the real type of itself.
  221. * @return {string} with the internal JavaScript [[Class]] of itself.
  222. */
  223. var toType = function(obj) {
  224. return OBJ_PROTO.toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
  225. };
  226. /**
  227. * Convert an array-like object into a true JavaScript array.
  228. *
  229. * @param {object} obj Any object to turn into a native Array.
  230. * @return {object} The object is now a plain array.
  231. */
  232. var toArray = function(obj) {
  233. return ARRAY_PROTO.slice.call(obj, 0);
  234. };
  235. /**
  236. *
  237. *
  238. */
  239. var isMobile = function() {
  240. var result = false;
  241. for (var i = 0, len = SUPPORTED_OS.length; i < len && !result; i++) {
  242. var mobile_os = SUPPORTED_OS[i];
  243. $.os[mobile_os] && (result = true);
  244. }
  245. return result;
  246. };
  247. return {
  248. log: log,
  249. execute: execute,
  250. bind: bind,
  251. mix: mix,
  252. isOwnProperty: isOwnProperty,
  253. toType: toType,
  254. toArray: toArray,
  255. isMobile: isMobile
  256. };
  257. })(LUNGO, Zepto);/**
  258. * Lungo UI events Manager
  259. *
  260. * @namespace LUNGO
  261. * @class Event
  262. * @requires Zepto
  263. *
  264. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  265. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  266. */
  267. LUNGO.Events = (function(lng, undefined) {
  268. var EVENTS = {
  269. mobile: {
  270. TOUCH_START: 'touchstart',
  271. TOUCH_MOVE: 'touchmove',
  272. TOUCH_END: 'touchend',
  273. TAP: 'tap',
  274. DOUBLE_TAP: 'doubletap',
  275. ORIENTATION_CHANGE: 'orientationchange'
  276. },
  277. desktop: {
  278. TOUCH_START: 'click',
  279. TOUCH_MOVE: 'click',
  280. TOUCH_END: 'click',
  281. TAP: 'click',
  282. DOUBLE_TAP: 'dblclick',
  283. ORIENTATION_CHANGE: 'orientationchange'
  284. }
  285. };
  286. var current_environment = lng.Environment.current();
  287. var current_events = EVENTS[current_environment];
  288. /**
  289. * Returns the touch event based on an enumeration of LungoJS
  290. * and the current environment
  291. *
  292. * @method get
  293. *
  294. * @param {string} Touch enumerator of LungoJS
  295. * @return {string} Touch event based on the current environment
  296. */
  297. var get = function(eventName) {
  298. return current_events[eventName];
  299. };
  300. return {
  301. get: get
  302. };
  303. })(LUNGO);/**
  304. * External Data & Services Manager
  305. *
  306. * @namespace LUNGO
  307. * @class Service
  308. * @requires Zepto
  309. *
  310. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  311. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  312. */
  313. LUNGO.Service = (function(lng, $, undefined) {
  314. /**
  315. * Load data from the server using a HTTP GET request.
  316. *
  317. * @method get
  318. *
  319. * @param {string} Containing the URL to which the request is sent
  320. * @param {object} A map or string that is sent to the server with the request
  321. * @param {Function} [OPTIONAL] Callback function after the request
  322. */
  323. var get = function(url, data, callback) {
  324. var parameters = '?';
  325. for (var parameter in data) {
  326. if (lng.Core.isOwnProperty(data, parameter)) {
  327. if (parameters !== '?') parameters += '&';
  328. parameters += parameter + '=' + data[parameter];
  329. }
  330. }
  331. url = url + parameters;
  332. _ajax('GET', url, null, callback);
  333. };
  334. /**
  335. * Load data from the server using a HTTP POST request.
  336. *
  337. * @method post
  338. *
  339. * @param {string} Containing the URL to which the request is sent
  340. * @param {object} A map or string that is sent to the server with the request
  341. * @param {Function} [OPTIONAL] Callback function after the request
  342. */
  343. var post = function(url, data, callback) {
  344. _ajax('POST', url, data, callback);
  345. };
  346. var _ajax = function(type, url, data, callback, error) {
  347. $.ajax({
  348. type: type,
  349. url: url,
  350. data: data,
  351. dataType: 'json',
  352. success: function(response) {
  353. if (lng.Core.toType(callback) === 'function') {
  354. setTimeout(callback, 100, response);
  355. }
  356. },
  357. error: function(xhr, type) {
  358. if (error) {
  359. setTimeout(error, 100, result);
  360. }
  361. }
  362. });
  363. };
  364. return {
  365. get: get,
  366. post: post
  367. };
  368. })(LUNGO, Zepto);/**
  369. * Handles the <sections> and <articles> to show
  370. *
  371. * @namespace LUNGO
  372. * @class Router
  373. * @requires Zepto
  374. *
  375. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  376. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  377. */
  378. LUNGO.Router = (function(lng, undefined) {
  379. var CSS_CLASSES = {
  380. SHOW: 'show',
  381. HIDE: 'hide'
  382. };
  383. /**
  384. * Navigate to a <section>.
  385. *
  386. * @method section
  387. *
  388. * @param {string} Id of the <section>
  389. */
  390. var section = function(section_id) {
  391. var section_id = (section_id.indexOf('#')) ? '#' + section_id : section_id;
  392. var target = 'section' + section_id;
  393. if (_existsTarget(target)) {
  394. lng.Dom.query(_getHistoryCurrent()).removeClass(CSS_CLASSES.SHOW).addClass(CSS_CLASSES.HIDE);
  395. lng.Dom.query(section_id).addClass(CSS_CLASSES.SHOW);
  396. lng.Router.History.add(section_id);
  397. }
  398. };
  399. /**
  400. * Displays the <article> in a particular <section>.
  401. *
  402. * @method article
  403. *
  404. * @param {string} <section> Id
  405. * @param {string} <article> Id
  406. */
  407. var article = function(section_id, article_id) {
  408. var target = section_id + ' article' + article_id;
  409. if (_existsTarget(target)) {
  410. lng.View.Article.show(section_id, article_id);
  411. }
  412. };
  413. /**
  414. * Return to previous section.
  415. *
  416. * @method back
  417. */
  418. var back = function() {
  419. lng.Dom.query(_getHistoryCurrent()).removeClass(CSS_CLASSES.SHOW);
  420. lng.Router.History.removeLast();
  421. lng.Dom.query(_getHistoryCurrent()).removeClass(CSS_CLASSES.HIDE).addClass(CSS_CLASSES.SHOW);
  422. };
  423. var _existsTarget = function(target) {
  424. var exists = false;
  425. if ($(target).length > 0) {
  426. exists = true;
  427. } else {
  428. lng.Core.log(3, 'Lungo.Router ERROR: The target ' + target + ' does not exists.');
  429. }
  430. return exists;
  431. }
  432. var _getHistoryCurrent = function() {
  433. return lng.Router.History.current();
  434. };
  435. return {
  436. section: section,
  437. article: article,
  438. back: back
  439. };
  440. })(LUNGO);/**
  441. * Stores the displayed <sections> as a historical.
  442. *
  443. * @namespace LUNGO.Router
  444. * @class History
  445. *
  446. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  447. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  448. */
  449. LUNGO.Router.History = (function(undefined) {
  450. var _history = [];
  451. /**
  452. * Create a new element to the browsing history based on the current section id.
  453. *
  454. * @method add
  455. *
  456. * @param {string} Id of the section
  457. */
  458. var add = function(section_id) {
  459. if (section_id !== current()) {
  460. _history.push(section_id);
  461. }
  462. };
  463. /**
  464. * Returns the current browsing history section id.
  465. *
  466. * @method current
  467. *
  468. * @return {string} Current section id
  469. */
  470. var current = function() {
  471. return _history[_history.length - 1];
  472. };
  473. /**
  474. * Removes the current item browsing history.
  475. *
  476. * @method removeLast
  477. */
  478. var removeLast = function() {
  479. _history.length -= 1;
  480. };
  481. return {
  482. add: add,
  483. current: current,
  484. removeLast: removeLast
  485. };
  486. })();/**
  487. * Initialize the <articles> layout of a certain <section>
  488. *
  489. * @namespace LUNGO.View
  490. * @class Article
  491. *
  492. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  493. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  494. */
  495. LUNGO.View.Article = (function(lng, undefined) {
  496. var SELECTORS = {
  497. ARTICLE: 'article',
  498. NAVIGATION_ITEM: 'nav a'
  499. };
  500. var CSS_CLASSES = {
  501. ACTIVE: 'current'
  502. };
  503. var show = function(section_id, article_id) {
  504. var nav_items = section_id + ' ' + SELECTORS.NAVIGATION_ITEM;
  505. _disableNavItems(nav_items);
  506. var current_nav_item = lng.Dom.query(nav_items + '[href="' + article_id + '"]');
  507. current_nav_item.addClass(CSS_CLASSES.ACTIVE);
  508. _setTitle(section_id, current_nav_item);
  509. _showContainer(section_id, article_id);
  510. };
  511. var _disableNavItems = function(items) {
  512. lng.Dom.query(items).removeClass(CSS_CLASSES.ACTIVE);
  513. };
  514. var _showContainer = function(section_id, article_id) {
  515. var section_articles = section_id + ' ' + SELECTORS.ARTICLE;
  516. lng.Dom.query(section_articles).removeClass(CSS_CLASSES.ACTIVE);
  517. lng.Dom.query(article_id).addClass(CSS_CLASSES.ACTIVE);
  518. };
  519. var _setTitle = function(id, item) {
  520. var title = item.data('title');
  521. if (title) {
  522. var section_title = id + ' header .title, ' + id + ' footer .title';
  523. lng.Dom.query(section_title).text(title);
  524. }
  525. };
  526. return {
  527. show: show
  528. };
  529. })(LUNGO);/**
  530. *
  531. *
  532. * @namespace LUNGO.View
  533. * @class Resize
  534. *
  535. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  536. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  537. */
  538. LUNGO.View.Resize = (function(lng, undefined) {
  539. /**
  540. * Rezise a <scroll> element
  541. *
  542. * @method scroll
  543. *
  544. * @param {object} Object reference of a determinated <section>
  545. */
  546. var scroll = function(scroll) {
  547. var container = scroll.children().first();
  548. var child = container.children().first();
  549. if (lng.View.Scroll.isHorizontal(scroll)) {
  550. _resizeScrollContainerWidth(container, child);
  551. } else {
  552. _resizeScrollContainerHeight(scroll, container, child);
  553. }
  554. };
  555. /**
  556. * Resize all <article>s from determinated <section> based on a CSS property.
  557. *
  558. * @method article
  559. *
  560. * @param {object} Object reference of a determinated <section>
  561. * @param {string} Selector that refers to a section element
  562. * @param {string} CSS property
  563. */
  564. var article = function(section, selector, property) {
  565. var element = section.children(selector);
  566. var ARTICLE = 'article'; //@todo >> refactor
  567. if (element) {
  568. section.children(ARTICLE).css(property, element.height() + 'px');
  569. }
  570. };
  571. /**
  572. * Sets toolbars width, using total screen width
  573. *
  574. * @method toolbars
  575. */
  576. var toolbars = function() {
  577. var toolbar = '.toolbar nav';
  578. var all_toolbars = lng.Dom.query(toolbar);
  579. for (var i = 0, len = all_toolbars.length; i < len; i++) {
  580. var toolbar = lng.Dom.query(all_toolbars[i]);
  581. var toolbar_children = toolbar.children();
  582. var toolbar_children_width = (toolbar.width() / toolbar_children.length);
  583. toolbar_children.css('width', toolbar_children_width + 'px');
  584. }
  585. };
  586. var _resizeScrollContainerWidth = function(container, child) {
  587. var scroll_width = (container.children().length * child.width());
  588. container.css('width', scroll_width + 'px');
  589. };
  590. var _resizeScrollContainerHeight = function(scroll, container, child) {
  591. var total_children = container.children().length;
  592. var children_in_scroll_width = Math.floor(scroll.width() / child.width());
  593. var total_rows = Math.ceil(total_children / children_in_scroll_width);
  594. var scroll_height = (total_rows * child.height());
  595. container.css('height', scroll_height + 'px');
  596. };
  597. return {
  598. scroll: scroll,
  599. article: article,
  600. toolbars: toolbars
  601. };
  602. })(LUNGO);/**
  603. * Lungo Template system
  604. *
  605. * @namespace LUNGO.View
  606. * @class Template
  607. * @requires Zepto
  608. *
  609. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  610. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  611. */
  612. LUNGO.View.Template = (function(undefined) {
  613. var _templates = {};
  614. /**
  615. * Create a new databinding template based on a <markup>
  616. *
  617. * @method create
  618. *
  619. * @param {String} Id of the new databinding template
  620. * @param {String} <markup> of the new databinding template
  621. */
  622. var create = function(id, markup) {
  623. _templates[id] = markup;
  624. };
  625. /**
  626. * Returns the existence of a certain Id databinding template
  627. *
  628. * @method exists
  629. *
  630. * @param {String} Id of the databinding template
  631. * @return {Boolean} true if exists, false if not.
  632. */
  633. var exists = function(id) {
  634. return (_templates[id]) ? true : false;
  635. };
  636. /**
  637. * Returns the instance of a certain Id databinding template
  638. *
  639. * @method get
  640. *
  641. * @param {String} Id of the databinding template
  642. * @return {String} Markup of template
  643. */
  644. var get = function(id) {
  645. return _templates[id];
  646. };
  647. /**
  648. * Performs databinding process for a data set and a given template
  649. *
  650. * @method binding
  651. *
  652. * @param {String} Id of the container showing the result of databinding
  653. * @param {Number} Databinding Template Id
  654. * @param {Object} Data for binding
  655. * @param {Function} Callback when the process is complete
  656. */
  657. var binding = function(container_id, id, data, callback) {
  658. lng.View.Template.Binding.create(container_id, id, data, callback);
  659. };
  660. return {
  661. create: create,
  662. exists: exists,
  663. get: get,
  664. binding: binding
  665. };
  666. })();
  667. /**
  668. * Lungo Data-Binding system
  669. *
  670. * @namespace LUNGO.View.Template
  671. * @class Binding
  672. * @requires Zepto
  673. *
  674. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  675. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  676. */
  677. LUNGO.View.Template.Binding = (function(lng, undefined) {
  678. var BINDING_START = '{{';
  679. var BINDING_END = '}}';
  680. var BINDING_PARSER = /\{{.*?\}}/gi;
  681. /**
  682. * Performs databinding process for a data set and a given template
  683. *
  684. * @method create
  685. *
  686. * @param {String} Id of the container showing the result of databinding
  687. * @param {Number} Databinding Template Id
  688. * @param {Object} Data for binding
  689. * @param {Function} Callback when the process is complete
  690. */
  691. var create = function(container_id, id, data, callback) {
  692. if (lng.View.Template.exists(id)) {
  693. var template = lng.View.Template.get(id);
  694. var markup = _processData(data, template);
  695. _render(container_id, markup);
  696. lng.Core.execute(callback);
  697. } else {
  698. lng.Core.log(3, 'lng.View.Template.binding: id ' + id + ' not exists');
  699. }
  700. };
  701. var dataAttribute = function(element, attribute) {
  702. var data = element.data(attribute.tag);
  703. if (data) {
  704. var html_binded = attribute.html.replace(BINDING_START + 'value' + BINDING_END, data);
  705. element.prepend(html_binded);
  706. }
  707. };
  708. var _processData = function(data, template) {
  709. var data_type = lng.Core.toType(data);
  710. if (data_type === 'array') {
  711. return _bindPropertiesInMultiplesElements(data, template);
  712. } else if (data_type === 'object') {
  713. return _bindProperties(data, template);
  714. } else {
  715. lng.Core.log(3, 'View.Template ERROR >> No type defined.');
  716. }
  717. };
  718. var _bindPropertiesInMultiplesElements = function(elements, template) {
  719. var markup = '';
  720. for (var i = 0, len = elements.length; i < len; i++) {
  721. markup += _bindProperties(elements[i], template);
  722. }
  723. return markup;
  724. };
  725. var _bindProperties = function(element, template) {
  726. var regex;
  727. for (var property in element) {
  728. if (lng.Core.isOwnProperty(element, property)) {
  729. regex = new RegExp(BINDING_START + property + BINDING_END, "g");
  730. template = template.replace(regex,element[property]);
  731. }
  732. }
  733. return _removeNoBindedProperties(template);
  734. };
  735. var _removeNoBindedProperties = function(template) {
  736. return template.replace(BINDING_PARSER, '');
  737. };
  738. var _render = function(container_id, markup) {
  739. var container = lng.Dom.query('#' + container_id);
  740. container.html(markup);
  741. };
  742. return {
  743. create: create,
  744. dataAttribute: dataAttribute
  745. };
  746. })(LUNGO);/**
  747. * Auto generate lists based on Template and Data-Binding system
  748. *
  749. * @namespace LUNGO.View.Template
  750. * @class List
  751. * @requires Zepto
  752. *
  753. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  754. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  755. */
  756. LUNGO.View.Template.List = (function(lng, undefined) {
  757. var _config = null;
  758. /**
  759. * Create a list based DataBind with a configuration object for an element <article>
  760. *
  761. * @method create
  762. *
  763. * @param {object} Id of the container showing the result of databinding
  764. */
  765. var create = function(config) {
  766. _config = config;
  767. _config.container_id += '_list';
  768. if (_validateConfig()) {
  769. _order();
  770. // @ToDo >> _group();
  771. _render();
  772. _createScroll();
  773. }
  774. };
  775. var _validateConfig = function() {
  776. var checked = false;
  777. var container_exists = !! lng.Dom.query(_config.container_id);
  778. if (container_exists) {
  779. //@ToDo >> Refactor to other method
  780. lng.Dom.query("#"+_config.container_id).html('');
  781. var template_exists = lng.View.Template.exists(_config.template_id);
  782. if (template_exists && _config.data.length) {
  783. checked = true;
  784. }
  785. }
  786. return checked;
  787. };
  788. var _order = function() {
  789. var order_field = _config.order_field;
  790. var order_type = (_config.order_type === 'desc') ? -1 : 1;
  791. if (order_field && order_type) {
  792. _config.data.sort(function(a, b) {
  793. return (a[order_field] < b[order_field]) ? - order_type :
  794. (a[order_field] > b[order_field]) ? order_type : 0;
  795. });
  796. }
  797. };
  798. // @ToDo >> group list by property
  799. var _group = function() {
  800. };
  801. var _render = function() {
  802. lng.View.Template.Binding.create(_config.container_id, _config.template_id, _config.data);
  803. };
  804. var _createScroll = function() {
  805. var container_id_for_scroll = lng.Dom.query('#' + _config.container_id).parent().attr('id');
  806. var list_config = {snap:'li'};
  807. lng.View.Scroll.create(container_id_for_scroll, list_config);
  808. };
  809. return {
  810. create: create
  811. };
  812. })(LUNGO);/**
  813. * Wrapper of the third library iScroll
  814. *
  815. * @namespace LUNGO.View
  816. * @class Scroll
  817. * @requires Zepto
  818. * @requires iScroll
  819. *
  820. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  821. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  822. */
  823. LUNGO.View.Scroll = (function(lng, undefined) {
  824. var DEFAULT_PROPERTIES = {
  825. hScroll: false,
  826. vScroll: false,
  827. useTransition: true,
  828. momentum: true,
  829. lockDirection: true,
  830. fixedScrollbar: true,
  831. fadeScrollbar: true,
  832. hideScrollbar: true
  833. };
  834. var HORIZONTAL_CLASS = 'horizontal';
  835. var CACHE_KEY = 'scrolls';
  836. /**
  837. * Creates a new iScroll element.
  838. *
  839. * @method create
  840. *
  841. * @param {string} Id of the container scroll.
  842. * @param {object} [OPTIONAL] Properties
  843. */
  844. var create = function(id, properties) {
  845. if (id) {
  846. var scroll = lng.Dom.query('#' + id);
  847. var scroll_children = scroll.children();
  848. var need_scroll = (scroll_children.height() >= scroll.height());
  849. if (scroll_children.length > 0 && need_scroll) {
  850. properties = _mixProperties(scroll, properties);
  851. _saveScrollInCache(id, properties);
  852. }
  853. } else {
  854. lng.Core.log(3, 'ERROR: Impossible to create a <scroll> without ID');
  855. }
  856. };
  857. /**
  858. * Update iScroll element with new <markup> content.
  859. *
  860. * @method update
  861. *
  862. * @param {string} Id of the container scroll.
  863. * @param {string} Markup content
  864. */
  865. var update = function(id, content) {
  866. var scroll = lng.Dom.query('#' + id);
  867. var container = scroll.children().first();
  868. if (container.length === 0) {
  869. scroll.html('<div id="' + id + '_scrl"></div>');
  870. container = scroll.children().first();
  871. }
  872. container.html(content);
  873. lng.View.Resize.scroll(scroll);
  874. _refresh(id);
  875. };
  876. /**
  877. * Removes iScroll instance.
  878. *
  879. * @method remove
  880. *
  881. * @param {string} Id of the <section>
  882. */
  883. var remove = function(id) {
  884. if (lng.Data.Cache.exists(CACHE_KEY)) {
  885. lng.Data.Cache.get(CACHE_KEY, id).destroy();
  886. lng.Data.Cache.remove(CACHE_KEY, id);
  887. }
  888. };
  889. /**
  890. * Removes iScroll instance.
  891. *
  892. * @method scrollIsHorizontal
  893. *
  894. * @param {Object} Id of the <section>
  895. */
  896. var isHorizontal = function(scroll) {
  897. return (scroll.hasClass(HORIZONTAL_CLASS)) ? true : false;
  898. };
  899. var _saveScrollInCache = function(id, properties) {
  900. _createScrollIndexInCache();
  901. var scroll = lng.Data.Cache.get(CACHE_KEY);
  902. scroll[id] = new iScroll(id, properties);
  903. lng.Data.Cache.set(CACHE_KEY, scroll);
  904. };
  905. var _createScrollIndexInCache = function() {
  906. if (!lng.Data.Cache.exists(CACHE_KEY)) {
  907. lng.Data.Cache.set(CACHE_KEY, {});
  908. }
  909. }
  910. var _mixProperties = function(scroll, properties) {
  911. var scroll_type = isHorizontal(scroll) ? 'hScroll' : 'vScroll';
  912. properties || (properties = {});
  913. properties[scroll_type] = true;
  914. properties = lng.Core.mix(DEFAULT_PROPERTIES, properties);
  915. return properties;
  916. };
  917. var _refresh = function(id, properties) {
  918. !lng.Data.Cache.get(CACHE_KEY, id) && _saveScrollInCache(id);
  919. lng.Data.Cache.get(CACHE_KEY, id).refresh();
  920. };
  921. return {
  922. create: create,
  923. update: update,
  924. remove: remove,
  925. isHorizontal: isHorizontal
  926. };
  927. })(LUNGO);/**
  928. * LungoJS Dom Handler
  929. *
  930. * @namespace LUNGO
  931. * @class Dom
  932. *
  933. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  934. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  935. */
  936. LUNGO.Dom = (function(lng, $, undefined) {
  937. /**
  938. * Add an event listener
  939. *
  940. * @method query
  941. *
  942. * @param {string} <Markup> element selector
  943. * @return {Object} Zepto <element> instance
  944. */
  945. var query = function(selector) {
  946. return $(selector);
  947. };
  948. return {
  949. query: query
  950. };
  951. })(LUNGO, Zepto);/**
  952. * Lungo DOM UI events Manager
  953. *
  954. * @namespace LUNGO.Dom
  955. * @class Event
  956. * @requires Zepto
  957. *
  958. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  959. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  960. */
  961. LUNGO.Dom.Event = (function(lng, undefined) {
  962. /**
  963. * Add an event listener
  964. *
  965. * @method bind
  966. *
  967. * @param {string} Selector that dispatches the event
  968. * @param {string} Touch event name
  969. * @param {Function} Callback function after the request
  970. */
  971. var bind = function(selector, event_name, callback) {
  972. if (_isNotSpecialEvent(selector, event_name, callback)) {
  973. lng.Dom.query(selector).bind(lng.Events.get(event_name), callback);
  974. }
  975. };
  976. /**
  977. * Remove bind event listener
  978. *
  979. * @method unbind
  980. *
  981. * @param {string} Selector that dispatches the event
  982. * @param {string} Touch event name
  983. */
  984. var unbind = function(selector, event_name) {
  985. lng.Dom.query(selector).unbind(lng.Events.get(event_name));
  986. };
  987. /**
  988. * Add an event listener that listens to the selector for current and future elements
  989. *
  990. * @method live
  991. *
  992. * @param {string} Selector that dispatches the event
  993. * @param {string} Touch event name
  994. * @param {Function} Callback function after the request
  995. */
  996. var live = function(selector, event_name, callback) {
  997. if (_isNotSpecialEvent(selector, event_name, callback)) {
  998. lng.Dom.query(selector).live(lng.Events.get(event_name), callback);
  999. }
  1000. };
  1001. /**
  1002. * Remove live listener
  1003. *
  1004. * @method die
  1005. *
  1006. * @param {string} Selector that dispatches the event
  1007. * @param {string} Event name
  1008. */
  1009. var die = function(selector, event_name) {
  1010. lng.Dom.query(selector).die(lng.Events.get(event_name));
  1011. };
  1012. /**
  1013. * Add an event listener without event delegation
  1014. *
  1015. * @method delegate
  1016. *
  1017. * @param {string} Selector that dispatches the event
  1018. * @param {string} Children of selector that dispatches the event
  1019. * @param {string} Touch event name
  1020. * @param {Function} Callback function after the request
  1021. */
  1022. var delegate = function(selector, children_selector, event_name, callback) {
  1023. if (_isNotSpecialEvent(selector, event_name, callback)) {
  1024. lng.Dom.query(selector).delegate(children_selector, lng.Events.get(event_name), callback);
  1025. }
  1026. };
  1027. /**
  1028. * Remove delegate event listener
  1029. *
  1030. * @method undelegate
  1031. *
  1032. * @param {string} Selector that dispatches the event
  1033. * @param {string} Children of selector that dispatches the event
  1034. */
  1035. var undelegate = function(selector, children_selector) {
  1036. lng.Dom.query(selector).undelegate(selector);
  1037. };
  1038. /**
  1039. * Listener for DOMelement
  1040. *
  1041. * @method listener
  1042. *
  1043. * @param {object} Selector that dispatches the event
  1044. * @param {string} Touch event name
  1045. * @param {Function} Callback function after the request
  1046. */
  1047. var listener = function(selector, event_name, callback) {
  1048. selector.addEventListener(lng.Events.get(event_name), function(event) {
  1049. setTimeout(callback, 0, event);
  1050. }, false);
  1051. };
  1052. var _isNotSpecialEvent = function(selector, event_name, callback) {
  1053. var is_special_event = false;
  1054. /*
  1055. var SPECIAL_EVENTS = {
  1056. SWIPE: 'swipe',
  1057. SWIPE_LEFT: 'swipeLeft',
  1058. SWIPE_RIGHT: 'swipeRight',
  1059. SWIPE_UP: 'swipeUp',
  1060. SWIPE_DOWN: 'swipeDown',
  1061. DOUBLE_TAP: 'doubleTap'
  1062. };
  1063. var special_event = SPECIAL_EVENTS[event_name];
  1064. lng.Dom.query(selector)[special_event](callback);
  1065. */
  1066. switch(event_name) {
  1067. case 'SWIPE':
  1068. lng.Dom.query(selector).swipe(callback);
  1069. break;
  1070. case 'SWIPE_LEFT':
  1071. lng.Dom.query(selector).swipeLeft(callback);
  1072. break;
  1073. case 'SWIPE_RIGHT':
  1074. lng.Dom.query(selector).swipeRight(callback);
  1075. break;
  1076. case 'SWIPE_UP':
  1077. lng.Dom.query(selector).swipeUp(callback);
  1078. break;
  1079. case 'SWIPE_DOWN':
  1080. lng.Dom.query(selector).swipeDown(callback);
  1081. break;
  1082. case 'DOUBLE_TAP':
  1083. if (lng.Environment.isDesktop()) {
  1084. lng.Dom.query(selector).live(lng.Events.get(event_name), callback);
  1085. } else {
  1086. lng.Dom.query(selector).doubleTap(callback);
  1087. }
  1088. break;
  1089. default:
  1090. is_special_event = true;
  1091. }
  1092. return is_special_event;
  1093. };
  1094. return {
  1095. bind: bind,
  1096. unbind: unbind,
  1097. live: live,
  1098. die: die,
  1099. delegate: delegate,
  1100. undelegate: undelegate,
  1101. listener: listener
  1102. };
  1103. })(LUNGO);/**
  1104. * Object with data-attributes (HTML5) with a special <markup>
  1105. *
  1106. * @namespace LUNGO.Attributes
  1107. * @class Data
  1108. *
  1109. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  1110. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  1111. */
  1112. LUNGO.Attributes.Data = {
  1113. search: {
  1114. tag: 'search',
  1115. selector: '.list',
  1116. html: '<li class="search {{value}}"><input type="search" placeholder="Search..."><a href="#" class="button" data-icon="search"></a></li>'
  1117. },
  1118. icon: {
  1119. tag: 'icon',
  1120. selector: '*',
  1121. html: '<span class="icon {{value}}"></span>'
  1122. },
  1123. title: {
  1124. tag: 'title',
  1125. selector: 'header, footer',
  1126. html: '<h1 class="title">{{value}}</h1>'
  1127. },
  1128. back: {
  1129. tag: 'back',
  1130. selector: 'header, footer',
  1131. html: '<a href="#back" data-target="section" class="back onleft button icon {{value}}"></a>'
  1132. }
  1133. };/**
  1134. * Make an analysis of <elements> in a <section>.
  1135. *
  1136. * @namespace LUNGO.Attributes
  1137. * @class Section
  1138. *
  1139. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  1140. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  1141. */
  1142. LUNGO.Attributes.Section = {
  1143. header: {
  1144. name: 'header',
  1145. bind: 'top'
  1146. },
  1147. footer: {
  1148. name: 'footer',
  1149. bind: 'bottom'
  1150. }
  1151. };/**
  1152. * Temporary cache system
  1153. *
  1154. * @namespace LUNGO.Data
  1155. * @class Cache
  1156. *
  1157. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  1158. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  1159. */
  1160. LUNGO.Data.Cache = (function(lng, undefined) {
  1161. var _cache = {};
  1162. /**
  1163. * Sets in the LungoJS cache system a new key/value
  1164. *
  1165. * @method set
  1166. *
  1167. * @param {string} Key for the new value
  1168. * @param {object} Type of environment: DESKTOP_ENVIRONMENT or MOBILE_ENVIRONMENT
  1169. */
  1170. var set = function(key, value) {
  1171. if (exists(key)) {
  1172. _cache[key] = lng.Core.mix(get(key), value);
  1173. } else {
  1174. _cache[key] = value;
  1175. }
  1176. };
  1177. /**
  1178. * Returns the value of a given key.
  1179. *
  1180. * @method get
  1181. *
  1182. * @param {string} Key in LungoJS Cache System
  1183. * @param {string} [OPTIONAL] Subkey in LungoJS Cache System
  1184. * @return {object} Value
  1185. */
  1186. var get = function(key, value) {
  1187. if (arguments.length === 1) {
  1188. return _cache[key];
  1189. } else {
  1190. return _cache[arguments[0]][arguments[1]];
  1191. }
  1192. };
  1193. /**
  1194. * Removes the instance in LungoJs Cache System of a given key
  1195. *
  1196. * @method remove
  1197. *
  1198. * @param {string} Key in LungoJS Cache System
  1199. * @param {string} [OPTIONAL] Subkey in LungoJS Cache System
  1200. */
  1201. var remove = function(key, value) {
  1202. if (arguments.length === 1) {
  1203. delete _cache[key];
  1204. } else {
  1205. delete _cache[arguments[0]][arguments[1]];
  1206. }
  1207. };
  1208. /**
  1209. * Returns the existence of a key in LungoJs Cache System
  1210. *
  1211. * @method exists
  1212. *
  1213. * @param {String} Key in LungoJS Cache System
  1214. * @return {Boolean} true if exists, false if not
  1215. */
  1216. var exists = function(key) {
  1217. return (_cache[key]) ? true : false;
  1218. };
  1219. return {
  1220. set: set,
  1221. get: get,
  1222. remove: remove,
  1223. exists: exists
  1224. };
  1225. })(LUNGO);/**
  1226. * Wrapper for using WebSql (HTML5 feature)
  1227. *
  1228. * @namespace LUNGO.Data
  1229. * @class Sql
  1230. *
  1231. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  1232. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  1233. */
  1234. LUNGO.Data.Sql = (function(lng, undefined) {
  1235. var CONFIG = {
  1236. name: 'lungo_db',
  1237. version: '1.0',
  1238. size: 65536,
  1239. schema: []
  1240. };
  1241. var db = null;
  1242. /**
  1243. * Initialize the SQLite storage (HTML5 Feature)
  1244. *
  1245. * @method init
  1246. *
  1247. * @param {object} Configuration for the Database
  1248. */
  1249. var init = function(db_config) {
  1250. CONFIG = lng.Core.mix(CONFIG, db_config);
  1251. db = openDatabase(CONFIG.name, CONFIG.version, CONFIG.name, CONFIG.size);
  1252. if (db) {
  1253. _createSchema();
  1254. } else {
  1255. lng.Core.log(3, 'lng.Data.Sql >> Failed to connect to database.');
  1256. }
  1257. };
  1258. /**
  1259. * Select a data set of a given table and based on a selection object
  1260. *
  1261. * @method select
  1262. *
  1263. * @param {string} Name of the table in the database
  1264. * @param {object} [OPTIONAL] Object selection condition
  1265. * @param {Function} Callback when the process is complete
  1266. */
  1267. var select = function(table, where_obj, callback) {
  1268. var where = (where_obj) ? ' WHERE ' + _convertToSql(where_obj, 'AND') : '';
  1269. execute('SELECT * FROM ' + table + where, function(rs) {
  1270. var result = [];
  1271. for (var i = 0, len = rs.rows.length; i < len; i++) {
  1272. result.push(rs.rows.item(i));
  1273. }
  1274. _callbackResponse(callback, result);
  1275. });
  1276. };
  1277. /**
  1278. * Inserts a data set of a given table and based on a data object
  1279. *
  1280. * @method insert
  1281. *
  1282. * @param {string} Name of the table in the database
  1283. * @param {object} Data object to insert in table
  1284. */
  1285. var insert = function(table, data_obj) {
  1286. var fields = '';
  1287. var values = '';
  1288. for (var field in data_obj) {
  1289. if (lng.Core.isOwnProperty(data_obj, field)) {
  1290. var value = data_obj[field];
  1291. fields += (fields) ? ', ' + field : field;
  1292. if (values) values += ', ';
  1293. values += (isNaN(value)) ? '"' + value + '"' : value;
  1294. }
  1295. }
  1296. execute('INSERT INTO ' + table + ' (' + fields + ') VALUES (' + values + ')');
  1297. };
  1298. /**
  1299. * Updates a data set of a given table and based on a data object and
  1300. * an optional selection object
  1301. *
  1302. * @method update
  1303. *
  1304. * @param {string} Name of the table in the database
  1305. * @param {object} Data object to update in table
  1306. * @param {object} [OPTIONAL] Object selection condition
  1307. */
  1308. var update = function(table, data_obj, where_obj) {
  1309. var sql = 'UPDATE ' + table + ' SET ' + _convertToSql(data_obj, ',');
  1310. if (where_obj) sql += ' WHERE ' + _convertToSql(where_obj, 'AND');
  1311. execute(sql);
  1312. };
  1313. /**
  1314. * Delete a data set of a given table and based on a selection object
  1315. *
  1316. * @method drop
  1317. *
  1318. * @param {string} Name of the table in the database
  1319. * @param {object} [OPTIONAL] Object selection condition
  1320. */
  1321. var drop = function(table, where_obj) {
  1322. var where = (where_obj) ? ' WHERE ' + _convertToSql(where_obj, 'AND') : '';
  1323. execute('DELETE FROM ' + table + where + ';');
  1324. };
  1325. /**
  1326. * Executes a SQL statement in the SQLite storage
  1327. *
  1328. * @method execute
  1329. *
  1330. * @param {string} SQL statement
  1331. * @param {Function} Callback when the process is complete
  1332. */
  1333. var execute = function(sql, callback) {
  1334. lng.Core.log(1, 'lng.Data.Sql >> ' + sql);
  1335. db.transaction(function(tx) {
  1336. tx.executeSql(sql, [], function(tx, rs) {
  1337. _callbackResponse(callback, rs);
  1338. }, _throwError);
  1339. });
  1340. };
  1341. var _createSchema = function() {
  1342. var schema = CONFIG.schema;
  1343. var schema_len = schema.length;
  1344. if (!schema_len) return;
  1345. for (var i = 0; i < schema_len; i++) {
  1346. var current = schema[i];
  1347. _regenerateTable(current);
  1348. _createTable(current.name, current.fields);
  1349. }
  1350. };
  1351. var _createTable = function(table, fields) {
  1352. var sql_fields = '';
  1353. for (var field in fields) {
  1354. if (lng.Core.isOwnProperty(fields, field)) {
  1355. if (sql_fields) sql_fields += ', ';
  1356. sql_fields += field + ' ' + fields[field];
  1357. }
  1358. }
  1359. execute('CREATE TABLE IF NOT EXISTS ' + table + ' (' + sql_fields + ');');
  1360. };
  1361. var _regenerateTable = function(table) {
  1362. if (table.drop === true) {
  1363. _dropTable(table.name);
  1364. }
  1365. };
  1366. var _dropTable = function(table) {
  1367. execute('DROP TABLE IF EXISTS ' + table);
  1368. };
  1369. var _convertToSql = function(fields, separator) {
  1370. var sql = '';
  1371. for (var field in fields) {
  1372. if (lng.Core.isOwnProperty(fields, field)) {
  1373. var value = fields[field];
  1374. if (sql) sql += ' ' + separator + ' ';
  1375. sql += field + '=';
  1376. sql += (isNaN(value)) ? '"' + value + '"' : value;
  1377. }
  1378. }
  1379. return sql;
  1380. };
  1381. var _callbackResponse = function(callback, response) {
  1382. if (lng.Core.toType(callback) === 'function') {
  1383. setTimeout(callback, 100, response);
  1384. }
  1385. };
  1386. var _throwError = function(transaction, error) {
  1387. lng.Core.log(3, 'lng.Data.Sql >> ' + error.code + ': ' + error.message);
  1388. };
  1389. return {
  1390. init: init,
  1391. select: select,
  1392. insert: insert,
  1393. update: update,
  1394. drop: drop,
  1395. execute: execute
  1396. };
  1397. })(LUNGO);/**
  1398. * Wrapper for using LocalStorage & SessionStorage (HTML5 Feature)
  1399. *
  1400. * @namespace LUNGO.Data
  1401. * @class Storage
  1402. *
  1403. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  1404. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  1405. */
  1406. LUNGO.Data.Storage = (function(lng, undefined) {
  1407. return {
  1408. };
  1409. })(LUNGO);/**
  1410. * Boot for a new LungoJS Application instance
  1411. *
  1412. * @namespace LUNGO
  1413. * @class App
  1414. *
  1415. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  1416. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  1417. */
  1418. LUNGO.Boot = (function(lng, undefined) {
  1419. return function() {
  1420. lng.Environment.start();
  1421. lng.Boot.Events.start();
  1422. lng.Boot.Data.start();
  1423. lng.Boot.Section.start();
  1424. lng.Boot.Article.start();
  1425. };
  1426. })(LUNGO);/**
  1427. * Initialize the <article> element
  1428. *
  1429. * @namespace LUNGO.Boot
  1430. * @class Article
  1431. * @requires Zepto
  1432. *
  1433. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  1434. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  1435. */
  1436. LUNGO.Boot.Article = (function(lng, undefined) {
  1437. var SELECTORS = {
  1438. LIST_IN_ARTICLE: 'article.list',
  1439. SCROLL_IN_ARTICLE: 'scroll',
  1440. CHECKBOX_IN_ARTICLE: '.checkbox, .radio'
  1441. };
  1442. /**
  1443. * Initializes the markup elements of an article
  1444. *
  1445. * @method init
  1446. */
  1447. var start = function() {
  1448. _initElement(SELECTORS.LIST_IN_ARTICLE, _createListElement);
  1449. _initElement(SELECTORS.SCROLL_IN_ARTICLE, _createScrollElement);
  1450. _initElement(SELECTORS.CHECKBOX_IN_ARTICLE, _b);
  1451. };
  1452. var _initElement = function(selector, callback) {
  1453. var found_elements = lng.Dom.query(selector);
  1454. for (var i = 0, len = found_elements.length; i < len; i++) {
  1455. var element = lng.Dom.query(found_elements[i]);
  1456. lng.Core.execute(callback, element);
  1457. }
  1458. };
  1459. var _createListElement = function(article) {
  1460. if (article.children().length === 0) {
  1461. var article_id = article.attr('id');
  1462. article.append('<ul id="' + article_id + '_list"></ul>');
  1463. }
  1464. };
  1465. var _createScrollElement = function(scroll) {
  1466. var scroll_id = scroll.attr('id');
  1467. lng.View.Scroll.create(scroll_id);
  1468. };
  1469. var _b = function(checkbox) {
  1470. checkbox.append('<span>&nbsp;</span>');
  1471. };
  1472. return {
  1473. start: start
  1474. };
  1475. })(LUNGO);/**
  1476. * Make an analysis of Data attributes in HTML elements and creates a <markup>
  1477. * based on each data type.
  1478. *
  1479. * @namespace LUNGO.Boot
  1480. * @class Data
  1481. * @requires Zepto
  1482. *
  1483. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  1484. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  1485. */
  1486. LUNGO.Boot.Data = (function(lng, undefined) {
  1487. /**
  1488. * Initialize the <markup> data-attributes analisys
  1489. *
  1490. * @method init
  1491. *
  1492. *
  1493. */
  1494. var start = function() {
  1495. var attributes = lng.Attributes.Data;
  1496. for (var attribute in attributes) {
  1497. if (lng.Core.isOwnProperty(attributes, attribute)) {
  1498. _findElements(attributes[attribute]);
  1499. }
  1500. }
  1501. };
  1502. var _findElements = function(attribute) {
  1503. var elements = lng.Dom.query(attribute.selector);
  1504. for (var i = 0, len = elements.length; i < len; i++) {
  1505. var element = lng.Dom.query(elements[i]);
  1506. lng.View.Template.Binding.dataAttribute(element, attribute);
  1507. }
  1508. };
  1509. return {
  1510. start: start
  1511. };
  1512. })(LUNGO);/**
  1513. * Initialize the automatic DOM UI events
  1514. *
  1515. * @namespace LUNGO.Boot
  1516. * @class Events
  1517. *
  1518. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  1519. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  1520. */
  1521. LUNGO.Boot.Events = (function(lng, undefined) {
  1522. /**
  1523. * Initializes the automatic subscription events by markup of the project.
  1524. *
  1525. * @method init
  1526. *
  1527. */
  1528. var start = function() {
  1529. var touch_move_event = 'TOUCH_MOVE';
  1530. var touch_start_event = 'TOUCH_START';
  1531. var orientation_change = 'ORIENTATION_CHANGE';
  1532. var target_selector = 'a[href][data-target]';
  1533. lng.Dom.Event.listener(document, touch_move_event, _iScroll);
  1534. lng.Dom.Event.listener(window, orientation_change, _changeOrientation);
  1535. lng.Dom.Event.live(target_selector, touch_start_event, _loadTarget);
  1536. };
  1537. var _iScroll = function(event_handler) {
  1538. event_handler.preventDefault();
  1539. };
  1540. var _changeOrientation = function(event) {
  1541. lng.View.Resize.toolbars();
  1542. };
  1543. var _loadTarget = function(event) {
  1544. event.preventDefault();
  1545. var link = lng.Dom.query(this);
  1546. var target_id = link.attr('href');
  1547. var target_type = link.data('target');
  1548. (target_type === 'section') ? _goSection(target_id) : _goArticle(link);
  1549. };
  1550. var _goSection = function(id) {
  1551. if (id === '#back') {
  1552. lng.Router.back();
  1553. } else {
  1554. lng.Router.section(id);
  1555. }
  1556. };
  1557. var _goArticle = function(element) {
  1558. var section_id = '#' + element.parents('section').attr('id');
  1559. var article_id = element.attr('href');
  1560. lng.Router.article(section_id, article_id);
  1561. };
  1562. return {
  1563. start: start
  1564. };
  1565. })(LUNGO);/**
  1566. * Initialize the <section> element
  1567. *
  1568. * @namespace LUNGO.Boot
  1569. * @class Section
  1570. * @requires Zepto
  1571. *
  1572. * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
  1573. * @author Guillermo Pascual <pasku@tapquo.com> || @pasku1
  1574. */
  1575. LUNGO.Boot.Section = (function(lng, undefined) {
  1576. var SELECTORS = {
  1577. ARTICLE: 'article',
  1578. SECTION: 'section'
  1579. };
  1580. var ACTIVE_CLASS = 'current';
  1581. /**
  1582. * Initializes all <section>s of the project
  1583. *
  1584. * @method init
  1585. */
  1586. var start = function() {
  1587. var sections = lng.Dom.query(SELECTORS.SECTION);
  1588. var easing_transition = '-webkit-transform 0.3s ease-in-out';
  1589. _initFirstSection(sections);
  1590. _initAllSections(sections);
  1591. lng.View.Resize.toolbars();
  1592. _allocateEasingTransition(sections, easing_transition);
  1593. };
  1594. var _initFirstSection = function(sections) {
  1595. var first_section = sections.first();
  1596. var first_section_id = '#' + first_section.attr('id');
  1597. first_section.addClass(ACTIVE_CLASS);
  1598. lng.Router.History.add(first_section_id);
  1599. };
  1600. var _initAllSections = function(sections) {
  1601. for (var i = 0, len = sections.length; i < len; i++) {
  1602. var section = lng.Dom.query(sections[i]);
  1603. _initSection(section);
  1604. _initFirstArticle(section);
  1605. }
  1606. };
  1607. var _initSection = function(section) {
  1608. var section_attributes = lng.Attributes.Section;
  1609. for (var attribute in section_attributes) {
  1610. if (lng.Core.isOwnProperty(section_attributes, attribute)) {
  1611. var property = section_attributes[attribute];
  1612. lng.View.Resize.article(section, property.name, property.bind);
  1613. }
  1614. }
  1615. };
  1616. var _allocateEasingTransition = function(sections, easing) {
  1617. var transition_property = { '-webkit-transition': easing };
  1618. sections.css(transition_property);
  1619. };
  1620. var _initFirstArticle = function(section) {
  1621. section.children(SELECTORS.ARTICLE).first().addClass(ACTIVE_CLASS);
  1622. };
  1623. return {
  1624. start: start
  1625. };
  1626. })(LUNGO);