(function(Kaki, window) { "use strict"; var path = require('path'); var fs = require('fs'); var Handlebars = require('handlebars'); var cp = require("child_process"); var gui = require('nw.gui'); var minimist = require('minimist'); // Templates var itemsListTpl = Handlebars.compile(select('#items-list-tpl').innerHTML); /** * Start the app * * @param rootEl The application root element selector * @return Kaki */ Kaki.start = function(rootEl) { Kaki._opts = minimist(gui.App.argv); Kaki._rootEl = select(rootEl); Kaki._initListeners(); var profilePath = Kaki._opts.profile || './default-profile.json'; return Kaki.loadProfile(profilePath) .then(function() { return Kaki; }) ; }; /** * Load a profile file and render the application * * @param profilePath The path of the profile file * @return Promise */ Kaki.loadProfile = function(profilePath) { return Kaki._loadJSONFile(profilePath) .then(function(profile) { Kaki._profile = profile; Kaki.render(); return profile; }) ; }; /** * Update the application view * * @return Kaki */ Kaki.render = function() { var rootEl = Kaki._rootEl; var profile = Kaki._profile; rootEl.innerHTML = itemsListTpl(profile); }; /** * Initialize DOM event listeners * @private */ Kaki._initListeners = function() { var rootEl = Kaki._rootEl; rootEl.addEventListener('click', Kaki._onItemClick); }; /** * App item click handler * @private */ Kaki._onItemClick = function(evt) { var appItemEl = evt.srcElement.matches( '.app-item') ? evt.srcElement : getClosestAncestor(evt.srcElement, '.app-item') ; if( !appItemEl ) return; var execPath = appItemEl.dataset.exec; console.info('Launching application "'+execPath+'"...'); if(execPath) { appItemEl.classList.add('loading'); cp.exec(execPath, function(err) { appItemEl.classList.remove('loading'); if(err) return console.error(err.stack || err); console.info('Application closed "'+execPath+'".'); }); } }; /** * Load a JSON file * * @private * @param filePath The path of the json file * @return Promise */ Kaki._loadJSONFile = function(filePath) { return new Promise(function(resolve, reject) { fs.readFile(filePath, 'utf8', function(err, fileContent) { if(err) return reject(err); try { var json = JSON.parse(fileContent); return resolve(json); } catch(err) { return reject(err); } }); }); }; // DOM manipulation helpers /** * Select an element in the DOM by its CSS selector * * @private * @param selector The CSS selector * @return The selected element or null */ function select(selector) { return window.document.querySelector(selector); } /** * Select all elements in the DOM with a CSS selector * * @private * @param selector The CSS selector * @return An array of the selected elements (if any) */ function selectAll(selector) { return window.document.querySelectorAll(selector); } /** * Find the closest ancestor matching the CSS selector * * @private * @param selector The CSS selector * @return An array of the selected elements (if any) */ function getClosestAncestor(el, selector) { var parent = el.parentElement; if(parent) { if(parent.matches(selector)) { return parent; } else { return getClosestAncestor(parent, selector); } } return false; } }(window.Kaki = window.Kaki || {}, window));