lungo-1.1.2.js 48 KB

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