Hi there, this is my first question!
I was looking for a final fantasy type menu and came upon this fiddle
http://jsfiddle.net/2ZqN6/5/
While it works very well, as is, on a web page, it performs oddly in Twine. At first, I couldn't get it to work at all, then while I was searching the forums for other things I came across a post by CoraBlue
twinery.org/forum/discussion/1051/performing-a-macro-after-page-displays/p1 about the very SAME menu.
I found that it needs to be in the PassageDone passage and put this script there:
<<if passage() is "Start" or "menu_test">>
<<script>>
//SET UP VARIABLES//
var cells = document.getElementsByTagName("li");
var cursorposition = 0;
var maxposition = cells.length-1;
var ScrollKeysToDisable = new Array(35, 36, 37, 38, 39, 40, 8);
//LOAD MEDIA//
var beep = new Audio('http://rpg.hamsterrepublic.com/wiki-images/8/8e/Confirm8-Bit.ogg');
var select = new Audio('http://rpg.hamsterrepublic.com/wiki-images/2/21/Collision8-Bit.ogg');
cells[cursorposition].className = cells[cursorposition].className + " pointer";
//ON KEYPRESS//
$(document).on('keydown', function (e) {
//GET ALL THESE VARIABLES EACH KEYPRESS//
var key = e.which; //THE KEY THAT IS PRESSED IN KEYCODE//
var char = String.fromCharCode(key); //THE KEY THAT IS PRESSED IN STRING FORM//
//DOWN ARROW//
if (e.keyCode == 40 && cursorposition < maxposition) {
cursorposition += 1;
}
//UP ARROW//
if (e.keyCode == 38 && cursorposition > 0) {
cursorposition -= 1;
}
//LEFT ARROW//
if (e.keyCode == 37) {
}
//RIGHT ARROW//
if (e.keyCode == 39) {
}
//PLAY BEEP//
if (e.keyCode == 37 || e.keyCode == 38 || e.keyCode == 39 || e.keyCode == 40) {
beep.currentTime = 0;
beep.play();
}
//ENTER//
if (e.keyCode == 13) {
}
//CATCH ALL ALPHANUMERIC KEYS//
if (e.shiftKey && e.keyCode > 47 && e.keyCode < 91) {
}
//CONVERT TO LOWERCASE IF SHIFT NOT HELD//
if (!e.shiftKey && e.keyCode > 47 && e.keyCode < 91) {
if (e.keyCode > 57) {
var char = String.fromCharCode(key + 32);
}
}
//SPACEBAR//
if (e.keyCode == 32 && macroName == 'cursortable') {
}
//BACKSPACE//
if (e.keyCode == 8 && macroName == 'cursortable') {
}
//PLAY SELECT//
if (e.keyCode == 8 || e.keyCode == 32 || e.keyCode == 13 || e.keyCode > 47 && e.keyCode < 91) {
select.currentTime = 0;
select.play();
}
//PREVENT DISABLED KEYS//
if ($.inArray(key, ScrollKeysToDisable) > -1) {
e.preventDefault();
e.stopPropagation();
}
//REFRESH CURSOR AFTER DONE//
for(var i=0; i<cells.length; i++){ cells[i].className = "" }
cells[cursorposition].className = cells[cursorposition].className + " pointer";
});
<</script>>
<<endif>>
My menu_test passage has:
@.choice;New Game@@.choice;Load Game@@.choice;Quit@@
<div class="big-box">
<ul>
<li>New Game</li>
<li>Continue</li>
<li>Quit</li>
</ul>
</div>
</div>
My css is:
/* finger cursor menu */
.big-box {
background-color:#ddd;
width:300px;
margin:auto;
position:relative;
padding:5px 35px;
}
.big-box ul {
list-style:none inside none;
padding:0;
font-size:40px;
}
.pointer:before {
content:url("http://static2.wikia.nocookie.net/__cb20121113193557/finalfantasy/images/1/1b/FF1_PSP_cursor.png"
;
position:absolute;
left:0px;
}
What displays is the gray box with the words, but NO pointing finger. At first, I thought, I must have mis-typed something. After I tried using my arrow keys, the finger magically appeared, after I clicked the down arrow twice. When moving down through the menu, it works as it should, and stops at the last list item. When moving back up, again, it disappears, when I click the up arrow, when the finger is placed on the "New Game" li.
What I want is for the pointer to be focused on the first menu item after the page loads and if somebody clicks the up arrow too many times the pointer would not move past the top menu item.
I am pretty good with html and css. I can usually get php to do what I want. I have very little experience with JavaScript, but can usually figure out how to change variables to get it to do what I want. Reading the forums has helped a lot.
I played around with the css, thinking it might be the z-index or positioning, or the online cursor image, so I put my own pointing finger in the local folder, but nothing seemed to affect the appearing and disappearing of the finger image. The code I have, above, is exactly what was on the fiddle frame, minus the
<script type='text/javascript'>//<![CDATA[
$(window).on('load', function() {
, as I have found errors on fiddle codes previously.
I tried removing all the comments, but nothing changed. I did notice that some of the script is colored green and the rest is black. I take it that may have something to do with the problem. Sorry to be so long on this. I don't usually ask for help, so this is new for me. I wanted to give as much information as I have available. Please, be kind and constructive when critical.
Thanks!
Comments
I'll take a closer look at the rest when I can.
Thank you, very much!
I had an inkling that was the case. I'll have to go through my other passages and check for more of the same. Thanks, again. Looking forward to finding a solution!
I have a tag on Start and menu_test, called noui.
noui has the css:
Without that tag, the finger is starting at the top of the ui-bar and two links later, it hits the menu test.
Then, I noticed something else. The PassageDone passage is no longer green at the top, but is blue like a normal passage. So, I check out the docs for special names and see:
I know I saw this before, but I thought it meant not to tag a special passage(which I did). I know I must sound dumb, but after looking at the list of special tags on the same page, I am confused. How exactly do you mean "combine"?
note: the one possible exception to the above rule is the nobr tag, which may work correctly when assigned to some of the special passages but not all.
So, does this mean, in general, using a class tag "zz" on a passage is not going to break a PassageDone inclusion?
If so, then it appears my script is seeing the ui-bar list items, even though they have a "display: none" attribute in the css.
warning: Using CSS like display:none; on a parent element (eg. #ui-bar) only causes that element (and its li element children) to not be visualised in the page's output. The elements still exist in the Document Object Model (DOM) so they can still be found when using Javascript like document.getElementsByTagName("li")
Thank you. I did not know that.
"my script" is the same as the script in my PassageDone passage, at the top of this page, with the exception that I have changed the first line.
I tried changing the var that looks for the list item
to
but it breaks the script, something about the I know very little about JavaScript(but I am learning). It can't be that hard to have it look for list items with an existing class name, can it?
Also, I just want to say that I truly appreciate the fact that you(all) take time to help others learn how to do things with Twine and JavaScript. I would have quit the first week, if it hadn't been for these forums and all the knowledge that is shared here.
The problem is quite simple, at the end of the code that handles each key-press you empty the current class property values of your li elements. This means that after the first key-press none of those elements has a class of mymenu, this in turn means the cells variable will contain an empty array which will result in an error when you try to access the cursorposition element of the array.
I'd suggest using something like the following as a starting point. As-is, pressing enter/return or spacebar will activate the menu links—in addition to clicking on them, naturally.
JavaScript (Twine 1: goes in script-tagged passage; Twine 2: goes in Story JavaScript)
Stylesheet (Twine 1: goes in stylesheet-tagged passage; Twine 2: goes in Story Stylesheet) NOTE: You'll need to remove the spurious semi-color inside the closing parenthesis of the url() that the forums added.
Menu markup
PS: I hope you have permission to use the assets you are or they're only temporary. Unauthorized hot linking to others' resources, public or not, is frowned upon.
Yes!
So, I changed
to
and it works. Awesome!
Is this correct, or just luck?
I do want to be able to have a class on the menus, as there may be more than one on the page, especially at character generation.
Thank you, so much!
Wow, you know exactly what I want to do. Thank you, for taking the time to work this out. Only I must have done something off, because it is not working for me. At first, I thought it might be the cursor, so I loaded my local cursor, but it made no change. The script does not appear to be read, as the arrow keys still scroll the page.
I am attaching the test tws. I am sure I just did something dumb or missed a ; or }, but I cannot see it.
PassageDone
I could have added a postdisplay task to the module, which would do the same without the need for PassageDone, however, I don't know where you eventually plan to place to the menu and I didn't want to make that bit difficult for you to find.
Awesome Possum. It works well. Many thanks to you and greyelf.
Oh, and no, I will not be hotlinking. It was just because the fiddle had that and it made it simpler to explain.:)