/** * dedalus-web.js v0.9.5 * 2013, Gustavo Di Pietro * Licensed under the GPL license (http://www.gnu.org/licenses/gpl-2.0.html) **/ /** * DedalusWeb is an implementatio on Dedalus (that DedalusWeb depens on) that * runs a Dedalus story in a browser */ var DedalusWeb; (function () { "use strict"; /*jslint evil: true, white: true, nomen: true */ /*global Dedalus, $, jQuery, doT, localStorage*/ /** * DedalusWeb class inheriting from Dedalus * @param {JSON} options A dictionary of configuration options: * { * domTarget: jQuery element that will contain the output * of the running story * inventoryTarget: jQuery element that will contain the inventory * items * titleTarget: jQuery element that will contain the title * of the story * interactionTarget: jQuery element that will contain the dynamic * action menu. Should have "position: absolute" * undoTarget: jQuery element that, clicked, runs the undo * action * saveTarget: jQuery element that, clicked, runs the save * action * restoreTarget: jQuery element that, clicked, runs the restore * action * resetTarget: jQuery element that, clicked, runs the reset * action * undoStageTarget: jQuery element that will contain a temporary copy * of domTarget. Should have "display: none" * } * @return A DedalusWeb instance */ DedalusWeb = function (options) { var self = this; Dedalus.call(this, options); this.domTarget = options.domTarget; this.domTarget2 = options.domTarget2; this.inventoryTarget = options.inventoryTarget; this.titleTarget = options.titleTarget; this.interactionTarget = options.interactionTarget; this.undoTarget = options.undoTarget; this.saveTarget = options.saveTarget; this.restoreTarget = options.restoreTarget; this.resetTarget = options.resetTarget; this.undoStageTarget = options.undoStageTarget; this.domTargetParent = options.domTargetParent; this.onPrint = options.onPrint ? options.onPrint.bind(this) : this.onPrint; // Set the utility buttons functionality this.undoTarget.on('click', this.undo.bind(this)); this.saveTarget.on('click', this.save.bind(this)); this.restoreTarget.on('click', this.restore.bind(this)); this.resetTarget.on('click', this.reset.bind(this)); // Set the title this.titleTarget.html(this.getTitle()); // Set the story to its initial state this.executeReset(); // Subscribe to inventory changes this.messageCenter.subscribe('inventory', 'dedalusWeb', this.updateInventory.bind(this)); // Make the interaction menu disappear on body click if there is no combination // action awaiting for a parameter $('body, html').on('click', function () { if(!self.isCombinationAction()) { self.interactionTarget.hide(); self.disactivateCombinationAction(); } }); }; DedalusWeb.prototype = new Dedalus(); /** * Convert all the meningful tags (, , ) * withing domTarget into action links */ DedalusWeb.prototype.handleInteractions = function () { var self = this; /** * Convert a target element into a link than, when clicked, runs fn with * argument attrib * @param {String} element Element to convert into * @param {String} attrib Attribute to pass to fn * @param {String} type object|parapgraph|page added as class to the newly * created link * @param {Function} fn Function to be executed when the newly created * link is clicked */ function handle (element, attrib, type, fn) { self.domTarget.find(element).each(function () { var elem = $(this), target = elem.attr(attrib), originalId = elem.attr('id'), elemId = originalId ? 'data-id="' + elem.attr('id') + '"' : '' , targetId = 'data-target-id="' + target + '"', isDisabled = elem.hasClass('disabled'), text = elem.text(), link = $('' + text + ''); link.on('click', function (e) { fn(target, e); e.stopPropagation(); return false; }); link.addClass(type); elem.after(link); elem.remove(); // Actually disable a pre-desabled link (has class="disabled"). Must have an id if (isDisabled) { self.disable(originalId); } }); } // Convert (turn page action) handle('turn', 'to', 'page', function (target) { self.turnTo(target); self.interactionTarget.hide(); $('#popUpWrapper').toggleClass('negativeMargin'); }); // Convert (object or character action) handle('interact', 'with', 'object', function (target, e) { self.interactWith(target, e); }); // Convert (paragraph element) handle('show', 'paragraph', 'paragraph', function (target) { self.showParagraph(target); self.interactionTarget.hide(); }); }; /** * Return the actions available for the interaction with a given object * @param {String} target Id of the object or character to interact with * @param {jQuery Event} e Event generated when clicking on the element * @return {JSON} A dictionary with the available actions */ DedalusWeb.prototype.interactWith = function (target, e) { var action, content, link, self = this, object = this.getObject(target), actions = object.getActiveActions(), clickedElement = $(e.target); this.interactionTarget.html('
    '); /** * Generate a function to be attached to an action menu item that, when * clicked, prints cont * @param {JSON} action Dedalus object action to make "onClick" for * @return {Function} The function to be called on object click */ function makeOnClick (action) { return function () { // If the action is of type "use this in combination with something else" // set the current combination action and populate interactionTarget // with possible candidates (all the objects visible in domTarget and // those in the inventory, exluding the object calling the combination // action), else execute the action if (action.hasWith) { self.activateCombinationAction(); self.interactionTarget.html('
      '); $(self.domTarget).find('a.object').add($(self.inventoryTarget).find('a')).each(function(idx, elem) { var element = $(elem), link = $(element.prop('outerHTML')), targetId = link.attr('data-target-id'), object = self.getObject(targetId), elemText = link.text(), linkText = object.inventoryName || elemText, combinationActionContent = action['with'][targetId] || action.content; // Skip current object, it cannot be associated with itself! if (targetId === target) { return; } // Set the text of the new to inventoryName of the object // or to the current link text link.text(linkText); link.on('click', function () { self.print(combinationActionContent); self.interactionTarget.hide(); self.handleInteractions(); self.disactivateCombinationAction(); }); self.interactionTarget.find('ul').append(link); self.interactionTarget.find('ul>a').wrap('
    • '); }); } else { self.print(action.content); $("#host").animate({ scrollTop: $("#host")[0].scrollHeight}, 200); self.interactionTarget.hide(); self.handleInteractions(); self.disactivateCombinationAction(); } }; } for (action in actions) { if (actions.hasOwnProperty(action)) { content = actions[action].content; link = $('' + action + ''); link.on('click', makeOnClick(actions[action])); // Create the within a
    • within the target