:: PopupMacro [script] /* See: https://twinery.org/forum/discussion/2613/sugarcube-how-to-using-themadexile-popup-macro And: http://twinery.org/forum/discussion/comment/10126/#Comment_10126 */ Macro.add("popup", { version : { major: 1, minor: 0, revision: 0 }, handler : function () { if (this.args.length < 2) { var errors = []; if (this.args.length < 1) { errors.push("link text"); } if (this.args.length < 2) { errors.push("passage name"); } return this.error("no " + errors.join(" or ") + " specified"); } var el = document.createElement("a"), passage = this.args[1], title; el.innerHTML = this.args[0]; el.className = "link-internal macro-popup"; el.setAttribute("data-passage", passage); title = el.textContent; UI.addClickHandler(el, null, function (evt) { var dialog = UI.setup(title, "popup"); new Wikifier(dialog, tale.get(passage).processText().trim()); }); this.output.appendChild(el); } }); :: ShakeMacro [script] /*! <> macro set for SugarCube 2.x */ ! function() { "use strict"; if ("undefined" == typeof version || "undefined" == typeof version.title || "SugarCube" !== version.title || "undefined" == typeof version.major || version.major < 2 || "undefined" == typeof version.minor || version.minor < 5) throw new Error("<> macro requires SugarCube 2.5.0 or greater, aborting load"); Macro.add("shake", { tags: null, handler: function() { var duration = this.args.length > 0 ? this.args[0] : 1 / 0, shakeClass = "shake"; if (1 / 0 !== duration) try { duration = Math.max(Engine.minDomActionDelay, Util.fromCssTime(duration)) } catch (e) { return this.error(e.message) } Config.debug && this.debugView.modes({ block: !0 }); var $wrapper = jQuery(document.createElement("span")); $wrapper.addClass("macro-" + this.name + " " + shakeClass).wiki(this.payload[0].contents).appendTo(this.output), 1 / 0 !== duration && setTimeout(function() { $wrapper.removeClass(shakeClass) }, Engine.minDomActionDelay + duration) } }), Macro.add(["shakescreen", "shaketarget"], { handler: function() { var $targets, duration, shakeClass; if ("shakescreen" === this.name) $targets = jQuery("#passages"), duration = this.args.length > 0 ? this.args[0] : 1 / 0, shakeClass = "shake-block"; else { if (0 === this.args.length) return this.error("no selector specified"); if ($targets = jQuery(this.args[0]), 0 === $targets.length) return this.error('no elements matched the selector "' + this.args[0] + '"'); duration = this.args.length > 1 ? this.args[1] : 1 / 0, shakeClass = "block" === jQuery($targets[0]).css("display") ? "shake-block" : "shake" } if ("stop" === duration) return void $targets.removeClass(shakeClass); if (1 / 0 !== duration) try { duration = Math.max(Engine.minDomActionDelay, Util.fromCssTime(duration)) } catch (e) { return this.error(e.message) } $targets.addClass(shakeClass), 1 / 0 !== duration && setTimeout(function() { $targets.removeClass(shakeClass) }, Engine.minDomActionDelay + duration) } }) }();