Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Twine 1.4.2 SugarCube 2.1.7 JavaScript How To Call It?

I was looking for a way to have the user be able to scroll, using a button and eliminating the scroll bar. I found something that does exactly what I want at dynamicdrive.com/dynamicindex11/scrollc2.htm

What it does:
There is very long text in a 250px div. There are two buttons; an up arrow and a down arrow. When the user hovers over one, the div scrolls up and vice versa.

I downloaded everything and it works fine in an ordinary html page.
In Twine, I get an error that "scrollable" is undefined.

After 2-3 days of searching the forums and net, I cannot seem to get beyond it being about the scope and how the script may need to be changed to something like a
window.myfunction = function(){
type thing. When I tried that on the scrollable function, I got an error that "this" is undefined. I also get errors of "scrollv v" being undefined on mouseover.

The html on the page is:
<div id="scrollable-v" class="scrollable">
<div class="belt">

<!--INSERT CONTENT HERE INSIDE BELT DIV-->

<p>The last few years have bared witness not only to major changes in the technologies that power the net, but also the devices that access it. With the myriad of smart phones and tablets of all sorts riding the internet wave...
</p>

<p>The last few years have bared witness not only to major changes in the technologies that power the net, but also the devices that access it. With the myriad of smart phones and tablets of all sorts riding the internet wave...
</p>

<p>The last few years have bared witness not only to major changes in the technologies that power the net, but also the devices that access it. With the myriad of smart phones and tablets of all sorts riding the internet wave...
</p>

<p>The last few years have bared witness not only to major changes in the technologies that power the net, but also the devices that access it. With the myriad of smart phones and tablets of all sorts riding the internet wave...
</p>

<!--END INSERTION -->

</div>
</div>

<p style="width:250px; text-align:right"><img src="roundup.png" onMouseover="scrollv.scrollContent('up')" onMouseout="scrollv.stopScroll()" />  <img src="rounddown.png"  onMouseover="scrollv.scrollContent('down')" onMouseout="scrollv.stopScroll()" /></p>




There are two .js files and a piece of code that goes in the head.

The first file is call impetus.js
The second is called scrollable.js
The scripts are too long to include in my question. I will try to add them in a comment.

the bit that goes in the head is:
<script>

var scrollv, scrollh // register two global vars for two scrollable instances

jQuery(function(e){ // on DOM load

	scrollv = new scrollable({
		wrapperid: "scrollable-v"
	})

	scrollh = new scrollable({
		wrapperid: "scrollable-h",
		orient: 'horizontal'
	})

})

</script>

The css is
.scrollable{
width: 250px; /* default width of scrollable content in px or percentage */
height: 200px; /* default height of scrollable content */
border: 1px solid black;
overflow: hidden; /* keep this */
position: relative; /* keep this */
}

.scrollable .belt{ /* default style of inner scrollable DIV */
width: 100%;
position:absolute;
left: 0;
top: 0;
padding: 0 5px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}

.scrollable .belt.horizontal{ /* default horizontal specific style of inner scrollable DIV */
width: auto; /* set to auto or an explicit px value large enough to accomodate entire horizontal content */
height: 100%;
/* white-space: nowrap; */   /* prevent wrapping inside DIV. Uncomment if embedding images or regular text content inside horizontal belt diV */
}

article.columns{ /* demo CSS to create columns of content inside horizontal scrollable */
width: 800px; /* See http://www.javascriptkit.com/dhtmltutors/css3columns.shtml */
-moz-column-width: 150px;
-webkit-column-width: 150px;
column-width: 150px;
}

article.columns > p:first-of-type{
margin-top: 0;
}

I tried placing the head code in PassageReady and PassageDone, but still get the undefined error. I am relatively new to JavaScript and have only ever remade other people's scripts. Basically, I don't know what I am doing with it, most of the time. I usually just find a way to make it work. So, if anyone can point me in the direction of being able to use this in Twine OR an even more elegant way to do this, I am all eyes. Thank you, in advance for any help.

Comments

  • This is the first part of the impetus code:
    /* Impetus.js
     * http://chrisbateman.github.com/impetus
     * Copyright (c) 2014 Chris Bateman
     * Licensed under the MIT license */
    
    /*
    	* April 22nd, 15: Modified by DD to add setBounds() method
    */
    
    (function() {
    	var Impetus = function(cfg) {
    		'use strict';
    		
    		var sourceEl, updateCallback, boundXmin, boundXmax, boundYmin, boundYmax, pointerLastX, pointerLastY, pointerCurrentX, pointerCurrentY, pointerId, decVelX, decVelY;
    		var targetX = 0;
    		var targetY = 0;
    		var multiplier = 1;
    		var friction = 0.92;
    		var stopThresholdDefault = 0.4;
    		var stopThreshold = stopThresholdDefault;
    		var ticking = false;
    		var pointerActive = false;
    		var paused = false;
    		var decelerating = false;
    		var trackingPoints = [];
    		
    		
    		/**
    		 * @see http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
    		 */
    		var requestAnimFrame = (function(){
    			return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) {
    				window.setTimeout(callback, 1000 / 60);
    			};
    		})();
    		
    		/**
    		 * Disable movement processing
    		 * @public
    		 */
    		this.pause = function() {
    			pointerActive = false;
    			paused = true;
    		};
    		
    		/**
    		 * Enable movement processing
    		 * @public
    		 */
    		this.resume = function() {
    			paused = false;
    		};
    		
    		/**
    		 * Update the current x and y values
    		 * @public
    		 * @param {Number} x
    		 * @param {Number} y
    		 */
    		this.setValues = function(x, y) {
    			if (typeof x === 'number') {
    				targetX = x;
    			}
    			if (typeof y === 'number') {
    				targetY = y;
    			}
    		};
    		
    		/**
    		 * Update the multiplier value
    		 * @public
    		 * @param {Number} val
    		 */
    		this.setMultiplier = function(val) {
    			multiplier = val;
    			stopThreshold = stopThresholdDefault * multiplier;
    		};
    
    		/**
    		 * Update bounds // DD added method
    		 * @public
    		 * @param {Number} x
    		 * @param {Number} y
    		 * @param {string} type
    		 */
    		this.setBounds = function(min, max, type) {
    			if (type == 'x'){
    				boundXmin	= min
    				boundYmax	= max	
    			}
    			else if (type == 'y'){
    				boundYmin	= min
    				boundYmax	= max	
    			}
    		};
    		
    		/**
    		 * Executes the update function
    		 */
    		var callUpdateCallback = function() {
    			updateCallback.call(sourceEl, targetX, targetY);
    		};
    		
    		/**
    		 * Creates a custom normalized event object from touch and mouse events
    		 * @param  {Event} ev
    		 * @returns {Object} with x, y, and id properties
    		 */
    		var normalizeEvent = function(ev) {
    			if (ev.type === 'touchmove' || ev.type === 'touchstart' || ev.type === 'touchend') {
    				var touch = ev.targetTouches[0] || ev.changedTouches[0];
    				return {
    					x: touch.clientX,
    					y: touch.clientY,
    					id: touch.identifier
    				};
    			} else { // mouse events
    				return {
    					x: ev.clientX,
    					y: ev.clientY,
    					id: null
    				};
    			}
    		};
    		
    		/**
    		 * Initializes movement tracking
    		 * @param  {Object} ev Normalized event
    		 */
    		var onDown = function(ev) {
    			var event = normalizeEvent(ev);
    			if (!pointerActive && !paused) {
    				pointerActive = true;
    				decelerating = false;
    				pointerId = event.id;
    				
    				pointerLastX = pointerCurrentX = event.x;
    				pointerLastY = pointerCurrentY = event.y;
    				trackingPoints = [];
    				addTrackingPoint(pointerLastX, pointerLastY);
    				
    				document.addEventListener('touchmove', onMove);
    				document.addEventListener('touchend', onUp);
    				document.addEventListener('touchcancel', stopTracking);
    				document.addEventListener('mousemove', onMove);
    				document.addEventListener('mouseup', onUp);
    			}
    		};
    		
    		/**
    		 * Handles move events
    		 * @param  {Object} ev Normalized event
    		 */
    		var onMove = function(ev) {
    			ev.preventDefault();
    			var event = normalizeEvent(ev);
    			
    			if (pointerActive && event.id === pointerId) {
    				pointerCurrentX = event.x;
    				pointerCurrentY = event.y;
    				addTrackingPoint(pointerLastX, pointerLastY);
    				requestTick();
    			}
    		};
    		
    		/**
    		 * Handles up/end events
    		 * @param  {Object} ev Normalized event
    		 */
    		var onUp = function(ev) {
    			var event = normalizeEvent(ev);
    			
    			if (pointerActive && event.id === pointerId) {
    				stopTracking();
    			}
    		};
    		
    		/**
    		 * Stops movement tracking, starts animation
    		 */
    		var stopTracking = function() {
    			pointerActive = false;
    			addTrackingPoint(pointerLastX, pointerLastY);
    			startDecelAnim();
    			
    			document.removeEventListener('touchmove', onMove);
    			document.removeEventListener('touchend', onUp);
    			document.removeEventListener('touchcancel', stopTracking);
    			document.removeEventListener('mouseup', onUp);
    			document.removeEventListener('mousemove', onMove);
    		};
    		
    
    
  • This is the second part of impetus.js
    
    		/**
    		 * Records movement for the last 100ms
    		 * @param {number} x
    		 * @param {number} y [description]
    		 */
    		var addTrackingPoint = function(x, y) {
    			var time = Date.now();
    			while (trackingPoints.length > 0) {
    				if (time - trackingPoints[0].time <= 100) {
    					break;
    				}
    				trackingPoints.shift();
    			}
    			
    			trackingPoints.push({
    				x: x,
    				y: y,
    				time: time
    			});
    		};
    		
    		/**
    		 * Calculate new values, call update function
    		 */
    		var update = function() {
    			targetX += (pointerCurrentX - pointerLastX) * multiplier;
    			targetY += (pointerCurrentY - pointerLastY) * multiplier;
    			
    			checkBounds();
    			callUpdateCallback();
    			
    			pointerLastX = pointerCurrentX;
    			pointerLastY = pointerCurrentY;
    			ticking = false;
    		};
    		
    		/**
    		 * prevents animating faster than current framerate
    		 */
    		var requestTick = function() {
    			if (!ticking) {
    				requestAnimFrame(update);
    			}
    			ticking = true;
    		};
    		
    		/**
    		 * Initializes the bound values
    		 */
    		var initBounds = function() {
    			if (cfg.boundX) {
    				boundXmin = cfg.boundX[0];
    				boundXmax = cfg.boundX[1];
    			}
    			if (cfg.boundY) {
    				boundYmin = cfg.boundY[0];
    				boundYmax = cfg.boundY[1];
    			}
    		};
    		
    		/**
    		 * Keep values in bounds, if available
    		 */
    		var checkBounds = function() {
    			if (boundXmin !== undefined && targetX < boundXmin) {
    				targetX = boundXmin;
    			}
    			if (boundXmax !== undefined && targetX > boundXmax) {
    				targetX = boundXmax;
    			}
    			if (boundYmin !== undefined && targetY < boundYmin) {
    				targetY = boundYmin;
    			}
    			if (boundYmax !== undefined && targetY > boundYmax) {
    				targetY = boundYmax;
    			}
    		};
    		
    		/**
    		 * Initialize animation of values coming to a stop
    		 */
    		var startDecelAnim = function() {
    			var firstPoint = trackingPoints[0];
    			var lastPoint = trackingPoints[trackingPoints.length - 1];
    			
    			var xOffset = lastPoint.x - firstPoint.x;
    			var yOffset = lastPoint.y - firstPoint.y;
    			var timeOffset = lastPoint.time - firstPoint.time;
    			
    			var D = (timeOffset / 15) / multiplier;
    			
    			decVelX = xOffset / D;
    			decVelY = yOffset / D;
    			
    			if (Math.abs(decVelX) > 1 || Math.abs(decVelY) > 1) {
    				decelerating = true;
    				requestAnimFrame(stepDecelAnim);
    			}
    		};
    		
    		/**
    		 * Animates values slowing down
    		 */
    		var stepDecelAnim = function() {
    			if (!decelerating) {
    				return;
    			}
    			
    			decVelX *= friction;
    			decVelY *= friction;
    			
    			if (Math.abs(decVelX) > stopThreshold || Math.abs(decVelY) > stopThreshold) {
    				targetX += decVelX;
    				targetY += decVelY;
    				
    				if (checkBounds()) {
    					decelerating = false;
    				}
    				callUpdateCallback();
    				
    				requestAnimFrame(stepDecelAnim);
    			} else {
    				decelerating = false;
    			}
    		};
    		
    		
    		/**
    		 * Initialize instance
    		 */
    		(function init() {
    			if (cfg.source) {
    				sourceEl = (typeof cfg.source === 'string') ? document.querySelector(cfg.source) : cfg.source;
    				if (!sourceEl) {
    					throw new Error('IMPETUS: source not found.');
    				}
    			} else {
    				sourceEl = document;
    			}
    			
    			if (cfg.update) {
    				updateCallback = cfg.update;
    			} else {
    				throw new Error('IMPETUS: update function not defined.');
    			}
    			
    			if (typeof cfg.multiplier !== 'undefined') {
    				multiplier = cfg.multiplier || multiplier;
    				stopThreshold = stopThresholdDefault * multiplier;
    			}
    			if (typeof cfg.friction !== 'undefined') {
    				friction = cfg.friction || friction;
    			}
    			
    			if (cfg.initialValues) {
    				if (cfg.initialValues[0]) {
    					targetX = cfg.initialValues[0];
    				}
    				if (cfg.initialValues[1]) {
    					targetY = cfg.initialValues[1];
    				}
    				callUpdateCallback();
    			}
    			
    			initBounds();
    			
    			sourceEl.addEventListener('touchstart', onDown);
    			sourceEl.addEventListener('mousedown', onDown);
    			
    		})();
    	};
    	
    	// AMD
    	if (typeof define === 'function' && define.amd) {
    		define(function() {
    			return Impetus;
    		});
    	} else {
    		this.Impetus = Impetus;
    	}
    	
    })();
    
  • This is the scrollable.js
    window.requestAnimationFrame = window.requestAnimationFrame
                                   || window.mozRequestAnimationFrame
                                   || window.webkitRequestAnimationFrame
                                   || window.msRequestAnimationFrame
                                   || function(f){return setTimeout(f, 1000/60)}
    
    window.cancelAnimationFrame = window.cancelAnimationFrame
                                  || window.mozCancelAnimationFrame
                                  || function(requestID){clearTimeout(requestID)} //fall back
    
    function scrollable(setting){
    
    	var defaults = {
    		orient: 'vertical',
    		moveby: 5,
    		mousedrag: false
    	}
    
    	var $ = jQuery
    	var s = $.extend({}, defaults, setting)
    	var touchenabled = 'ontouchstart' in window || navigator.msMaxTouchPoints
    	var $outer = $('#' + s.wrapperid)
    	var $belt = $outer.find('div.belt')
    	var curpos, bounds
    	var outerwidth, beltwidth, outerheight, beltheight
    	var moveRequest, updateDimensionsBoundsRequest
    	var thisint = this
    
    	this.getDimensionsAndBounds = function(orient){
    		if (orient == 'vertical'){
    			outerheight = $outer.height()
    			beltheight = $belt.outerHeight()
    			bounds = [outerheight-beltheight, 0]
    		}
    		else{
    			outerwidth = $outer.width()
    			beltwidth = $belt.outerWidth()
    			bounds = [outerwidth-beltwidth, 0]
    		}
    	}
    
    	this.scrollContent = function(dir){
    		this.stopScroll()
    		var moveby = (dir == 'down' || dir =='right')? -s.moveby :s.moveby
    		function movecontent(){
    			curpos = parseInt($belt.css( (s.orient == 'vertical')? 'top' : 'left' ))
    			if (dir == 'down' && curpos > bounds[0]){
    				$belt.css('top', Math.max(curpos + moveby, bounds[0]))
    				moveRequest = requestAnimationFrame(movecontent)
    			}
    			else if (dir == 'up' && curpos < bounds[1]){
    				$belt.css('top', Math.min(curpos + moveby, bounds[1]))
    				moveRequest = requestAnimationFrame(movecontent)
    			}
    			else if (dir == 'right' && curpos > bounds[0]){
    				$belt.css('left', Math.max(curpos + moveby, bounds[0]))
    				moveRequest = requestAnimationFrame(movecontent)
    			}
    			else if (dir == 'left' && curpos < bounds[1]){
    				$belt.css('left', Math.min(curpos + moveby, bounds[1]))
    				moveRequest = requestAnimationFrame(movecontent)
    			}
    		}
    		moveRequest = requestAnimationFrame(movecontent)
    	}
    
    	this.stopScroll = function(){
    		cancelAnimationFrame(moveRequest)
    	}
    
    	var disabletextselect = function(){
    		if ( /(MSIE)|(Trident)/i.test(navigator.userAgent) ){ // test for IE browsers
    			$belt.on('selectstart', function() { return false; })
    		}
    		else{
    			$outer.on('mousedown', function(e){e.preventDefault()})
    			$outer.on('mouseup', function(e){return true})
    		}
    	}
    
    
    	this.getDimensionsAndBounds(s.orient)
    
    	if ($belt.length == 1 && (touchenabled || s.mousedrag)){
    		if (s.orient == 'vertical'){
    			var myImpetus = new Impetus({
    			    source: $belt.get(0),
    					boundY: bounds,
    			    update: function(x, y) {
    						$belt.css('top', y + 'px')
    						curpos = y
    			    }
    			})
    		}
    		else{
    			var myImpetus = new Impetus({
    			    source: $belt.get(0),
    					boundX: bounds,
    			    update: function(x, y) {
    						$belt.css('left', x + 'px')
    						curpos = x
    			    }
    			})
    		}
    	
    		$belt.on('mousedown touchstart', function(e){ // update cur x and y pos inside myImpetus upon touch of scrollable, as x and y may have changed by calling scrollContent()
    			var x = (s.orient == 'vertical')? 0 : curpos
    			var y = (s.orient == 'vertical')? curpos : 0
    			myImpetus.setValues(x, y)
    			thisint.stopScroll()
    		})
    		disabletextselect()
    	}
    
    	$(window).on('load resize', function(){
    		clearTimeout(updateDimensionsBoundsRequest)
    		updateDimensionsBoundsRequest = setTimeout(function(){
    			thisint.getDimensionsAndBounds(s.orient)
    			var boundtype = (s.orient == 'vertical')? 'y': 'x'
    			if (typeof myImpetus !='undefined')
    				myImpetus.setBounds(bounds[0], bounds[1], boundtype)
    		}, 200)
    	})
    
    }
    
  • Change the final line of Impetus to:
    }).call(window);
    

    Then place the following after Impetus:
    window.scrollv = new scrollable({
    	wrapperid: "scrollable-v"
    });
    window.scrollh = new scrollable({
    	wrapperid: "scrollable-h",
    	orient: 'horizontal'
    });
    
  • Thank You, for your help!
    The errors are gone, now, but I have no clue how to code the "onMouseover" and "onMouseout" in Twine. The html code does not work, as is:
    <p>
    <img src="images/roundup.png" onMouseover="scrollv.scrollContent('up')" onMouseout="scrollv.stopScroll()" />  
    <img src="images/rounddown.png"  onMouseover="scrollv.scrollContent('down')" onMouseout="scrollv.stopScroll()" />
    </p>
    
    and the browser complains about the expected ; after the onMouseover. So, I changed it to
    <p>
    <img src="images/roundup.png" onMouseover="scrollv.scrollContent('up')"; onMouseout="scrollv.stopScroll()"; />  
    <img src="images/rounddown.png"  onMouseover="scrollv.scrollContent('down')"; onMouseout="scrollv.stopScroll()"; />
    </p>
    
    which doesn't work, doh. So, I tried a image link with a script tag, like:
    <<link [img[images/roundup.png]]>><<script>>onmouseover="scrollv.scrollContent('up')"; onmouseout="scrollv.stopScroll()";<</script>><</link>>
    <<link [img[images/rounddown.png]]>><<script>>onmouseover="scrollv.scrollContent('down')"; onmouseout="scrollv.stopScroll()";<</script>><</link>>
    
    which doesn't work, either. You must be laughing or shaking your head, but the difference between using JavaScript in html and Twine will eventually dawn on me.
    Nothing happens, when I hover on the images.
  • You posted the scrollable code while I was working on my initial reply, so I didn't see it before I posted.

    Are you placing the Impetus and scrollable scripts within the same script-tagged passage or separate ones? As currently written, they need to go into the same script-tagged passage along with the reworked scrollv/scrollh code I gave previously, which should go after both. Basically, the order should be:
    1. Impetus
    2. scrollable
    3. Reworked scrollv/scrollh code

  • Basically, the order should be:
    1. Impetus
    2. scrollable
    3. Reworked scrollv/scrollh code
    Done. I still don't get any response from onMouseover. I have firebug installed, but am not sure how to check what is being seen by the browser in JavaScript. (I just use it for looking at css most of the time.

    I know this is a holiday for many people. I appreciate you taking time to help me sort this out. Still, it's not urgent, but I want to use this so I don't loose the right side of a popup when it needs to scroll, and this looks so smooth, I would love to be able to use it for that (and some other places).

  • Let me look at the link you provided….


    Okay, the scrollv/scrollh code needs to executed each time passage rendering takes place. Replace the original reworked scrollv/scrollh code I gave you with the following:
    postdisplay['setup-impetus-scrollable'] = function () {
    	if (
    		document.getElementById('scrollable-v') ||
    		document.getElementById('scrollable-h')
    	) {
    		window.scrollv = new scrollable({
    			wrapperid : 'scrollable-v'
    		});
    		window.scrollh = new scrollable({
    			wrapperid : 'scrollable-h',
    			orient    : 'horizontal'
    		});
    	}
    	else {
    		window.scrollv = window.scrollh = null;
    	}
    };
    
  • Yes, Yes, Yes, Yes, Yes, Yes.......
    Thank YOU! I have been looking for a solution for weeks and when I saw the script, even considering the source, I knew this was what would appear best. Thank you, for giving me the help to make it work in Twine! It most definitely works in my test tws. Thank you, so much.
  • @TheMadExile

    Ok, everything works fine, if I am doing the test from a standard passage. When I put the same code on my inventory passage, which is called by a popup macro, I get the error:
    Error: TypeError: scrollv is null.
    when I hover over the image.

    I tried placing all of the scroll code below the popup code in my script passage, but that doesn't do it.

    This is the popup macro code (I believe it was yours)
    /* //*****************************
    //  pop-up macro Just for the inventory
    //  See the popup annotation for how to implement
    //*****************************
    */
    
    /*click pop-i*/
    Macro.add("popi", {
    	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-popi";
    		el.setAttribute("data-passage", passage);
    		title = el.textContent;
    		UI.addClickHandler(el, null, function (evt) {
    			var	dialog = UI.setup(title, "popi");
    			new Wikifier(dialog, tale.get(passage).processText().trim());
    		});
    		this.output.appendChild(el);
    	}
    });
    

    And this was the non-Twine/non-SugarCube way I am doing the mouseover
    <div id="scrollbuttons">
    <p>
    <img src="images/roundup.png" onMouseover="scrollv.scrollContent('up');" onMouseout="scrollv.stopScroll();" />  
    <img src="images/rounddown.png"  onMouseover="scrollv.scrollContent('down');" onMouseout="scrollv.stopScroll();" />
    </p>
    

    I am sure there is a better/easier way.

    The whole point of the scroll script was to remove the scroll bars from the popup, as it is rounded 3d style and the scroll bars just ruin the right side. Thank you, for all the time you have spent helping me with this. I do appreciate it.
  • EarthMagic wrote: »
    The whole point of the scroll script was to remove the scroll bars from the popup, as it is rounded 3d style and the scroll bars just ruin the right side.
    *sigh* This is the kind of information you should have volunteered from the very start.

    If you're only going to use the scrollable within your custom dialogs, then you don't need the scrollv/scrollh code anywhere else and can remove the postdisplay task I gave last time.

    Here's an updated version of the <<popi>> macro, both to bring it up to standards and to add a version of the scrollv/scrollh code: (untested, but should work)
    Macro.add('popi', {
    	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 $link   = jQuery(document.createElement('a'));
    		var passage = this.args[1];
    
    		$link
    			.attr('data-passage', passage)
    			.addClass('link-internal macro-' + this.name)
    			.wiki(this.args[0]);
    
    		var dialogTitle = $link.text();
    		var dialogClass = this.name;
    
    		$link
    			.ariaClick(function () {
    				var dialog = Dialog.setup(dialogTitle, dialogClass);
    
    				Dialog.wiki(Story.get(passage).processText().trim());
    
    				if (dialog.querySelector('#scrollable-v,#scrollable-h')) {
    					window.scrollv = new scrollable({
    						wrapperid : 'scrollable-v'
    					});
    					window.scrollh = new scrollable({
    						wrapperid : 'scrollable-h',
    						orient    : 'horizontal'
    					});
    				}
    				else {
    					window.scrollv = window.scrollh = null;
    				}
    
    				Dialog.open();
    			})
    			.appendTo(this.output);
    	}
    });
    
  • edited April 2017
    EarthMagic wrote: »
    The whole point of the scroll script was to remove the scroll bars from the popup, as it is rounded 3d style and the scroll bars just ruin the right side.

    I do realize that this would have been helpful, from the start. If only we could all think "what first", before we communicate... I did, not at first, mention it:
    Still, it's not urgent, but I want to use this so I don't loose the right side of a popup when it needs to scroll, and this looks so smooth, I would love to be able to use it for that (and some other places).

    I guess, with all the code involved, I just didn't think about the "why", until I got all of the code put down. I do apologize.

    I thank you for the updated
    Macro.add('popi',
    code. It does not show an error on the popup, but the scroll does not function, either. I am attaching a .tws of my test (which I probably should have done at the beginning, as well). The standard passage(scroll_test) does throw an error that "scrollv is not defined.". When you play it to the "begin" link you want to click on inventory on the footer. There is no error, but the text does not scroll.
    Many thanks, for your help and patience. As I said, before, asking for help is relatively new for me.
  • edited April 2017
    Hmm. Apparently, simply having the target elements within the page isn't sufficient for Impetus and/or scrollable, they also need to be displayed when the call to scrollable's constructor is made.

    That's easily fixed by moving the call to Dialog.open() to before the scrollv/scrollh code.

    Here's an updated version of the <<popi>> macro: (tested and working)
    Macro.add('popi', {
    	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 $link   = jQuery(document.createElement('a'));
    		var passage = this.args[1];
    
    		$link
    			.attr('data-passage', passage)
    			.addClass('link-internal macro-' + this.name)
    			.wiki(this.args[0]);
    
    		var dialogTitle = $link.text();
    		var dialogClass = this.name;
    
    		$link
    			.ariaClick(function () {
    				var dialog = Dialog.setup(dialogTitle, dialogClass);
    				Dialog.wiki(Story.get(passage).processText().trim());
    				Dialog.open();
    
    				if (dialog.querySelector('#scrollable-v,#scrollable-h')) {
    					window.scrollv = new scrollable({
    						wrapperid : 'scrollable-v'
    					});
    					window.scrollh = new scrollable({
    						wrapperid : 'scrollable-h',
    						orient    : 'horizontal'
    					});
    				}
    				else {
    					window.scrollv = window.scrollh = null;
    				}
    			})
    			.appendTo(this.output);
    	}
    });
    

    EDIT: By renaming SugarCube's directory within Twine 1's targets directory you've not only broken the support file, unless you renamed it similarly, but also made the TWS unable to be opened on any system where it hasn't been so renamed. You may not care able the latter, though you should the former.
  • That's wonderful. It works very well!
    By renaming SugarCube's directory within Twine 1's targets directory you've not only broken the support file, unless you renamed it similarly, but also made the TWS unable to be opened on any system where it hasn't been so renamed. You may not care able the latter, though you should the former.

    Sorry, for that and I am glad you brought this up. I had no idea that you would not be able to open the file. I guess I was confusing it with the html file, thinking Twine would import it and you would have to choose which story format to use.
    I have about 4-5 versions of SugarCube in my targets folder. I renamed the folders and the .py file inside to version numbers. Somehow, on the latest version, I forgot to rename the .py. Perhaps, this is why my "find" has been acting so strangely...

    Again, many thanks, for your help!
Sign In or Register to comment.