Lengthening Game Panes [Solved]

This must have been discussed before but I've not found anything with a quick search. Apologies, if it is 'obvious'.

For one-room puzzles, there may be more items in a room than can be shown without scrolling. Is there a way to lengthen the Inventory and Places and Objects game panes? ...making sure, of course, to stay within the available screen size!


K.V.

Hello, DavyB!

This might be what you're looking for:

http://textadventures.co.uk/forum/quest/topic/oppns_i2cech0laswcyuca/resizing-the-panes


Thanks KV, that addresses my worry about the panes 'overflowing' but is there a way to increase the length of panes before they start scrolling? I'vm just using the Inventory and Places and Objects panes as it is a single room and the scrolling starts earlier than necessaary for most screens.


The updateList javascript function (called every turn to make sure the lists are displayed correctly) sets the logical size of the list to the number of items in it, subject to a minimum of 3 and a maximum of 12. That means that setting the height of the list wrapper will only work to reduce it.

The offending piece of code is:

    var selectSize = count;
    if (selectSize < 3) selectSize = 3;
    if (selectSize > 12) selectSize = 12;
    $(listElement).attr("size", selectSize);

Fairly recently (some time this year?) I posted a piece of code on a thread, changing this so that it just sets the size to the count, and then loops while(sidebar is taller than the screen) { reduce the size of the longest list by 1; }.
I can't find the post right now, and it really needs some more work, but it might be a good starting point to look at.

Off the top of my head, it would be something like:

$(function() {
  var originalUpdateList = updateList;
  updateList = function (n, d) {
    // run the standard function
    originalUpdateList (n, d);

    var inventorySize = $('#lstInventory').children('li').length;
    var placesObjectsSize = $('#lstPlacesObjects').children('li').length;
    $('#lstInventory').attr('size', inventorySize);
    $('#lstPlacesObjects').attr('size', placesObjectsSize);

    // You might need to tweak this to allow for margins etc:
    while ($('#gamePanesRunning').height > window.innerHeight) {
      var maxSize = Math.max(inventorySize, placesObjectsSize);
      if (maxSize == inventorySize) { $('#lstInventory').attr('size', --inventorySize); }
      if (maxSize == placesObjectsSize) { $('#lstPlacesObjects').attr('size', --placesObjectsSize); }

      // if we're playing in a window that's stupidly small, don't shrink the lists any more
      // the sensible behaviour here would probably be to set the sizes back to the actual number of items in the list, and diaplay a scrollbar for the whole sidebar
      if (maxSize < 3) { break; }
    }
  };
});

(all off the top of my head. I vaguely remember there were some other style issues last time, so that might need some tweaking)
(and I just realised that you'd also want to add some code when the verb buttons are displayed to make sure that the list is resized to fit on the screen)


Mrangel...That was me that you were helping with this issue. What you gave me seemed to be working alright...until once again one of my testers piled too much stuff in one area.
http://textadventures.co.uk/forum/quest/topic/1tx_vegry0usmwpv1g8udq/too-many-items-cant-scroll-resolved

I had marked it as resolved...but seems I am still having issues. The only thing I can find to do in order to get to the verb buttons at the bottom when it is too long, is to close up panes above it. Which is a terrible way to play.


Thanks for identifying the original posting Rob. That seems to be addressing the problem of pane overflow but I can't see how to increase the size of a pane up to the overflow point. In a one-room puzzle, the Places and Objects pane is much larger than any other and I'm currently finding that scrolling begins when the number of items is 10 or more. The only other pane is the Inventory and is typically one third the size, so I'd like to carve the screen up to give a quarter to the inventory and three quarters to Places and Objects, calculated on the size of the screen.

I don't know enough about JS to work at that level so something that can be dropped into Quest would be ideal :) Sorry for asking for this on a plate but there are other like me!


Ah, I thought it was mostly working.

So we've got 2 threads where I've posted different javascript attempts at the same idea. I think between the two of them, all the code we need is there. It's just a case of properly integrating them. I'm going to take another look through playercore.css to see if there's anything in there I'm missing with regard to how the panes are laid out.

Can someone link me to a game I can use for testing? I've written chunks of code on my phone, but to test them I'll likely be using my browser's javascript console. So it'd be easier to test if someone can recommend a game where I can quickly get to a point with tons of items in the placesObjects pane.


Mrangel, happy to send you a game. Can you PM an email address to me?


...if you can work from a published game see:
http://textadventures.co.uk/games/view/4vyqhsn-fe_izwyfrtgj5g/escape-this-podcast-episode-1-alexs-bathroom


Thanks, that's perfect.

Ooops.
I was tweaking the size attribute because that's what Quest's built in JS does – but it looks like that might be legacy code that doesn't do anything. (I assumed that because Quest sets a size attribute on it, #lstPlacesObjects would be a <select>. But it isn't, it's an <ol> that acts like a selectable list, so the size attribute does nothing. Maybe it used to be a <select>, and this bit of code is now meaningless?)

One line of javascript:

$('.elementListWrapper').css({maxHeight: 'initial'});

("initial" in this case means the default value for an element of that type, which is to make it as big as all the items in the list)

However, this causes problems if the number of items in the two panes is larger than the window.
What would you like to happen in this case?

  1. Shrink the two panes proportionally. (so if placesObjects contains twice as many items as the inventory, its pane will be twice the size, and both will have scroll bars)
  2. Shrink the larger pane and give it a scroll bar.
  3. Display a single scroll bar for the whole sidebar.

I think all 3 are viable choices, so it's a case of which one you prefer.


Wow mrangel, options! ...I'm not sure what 3. means?...but perhaps a more restricted structure is safer in case the Inventory pane is squeezed too much? In some of these games the Places and Objects pane may need to scroll before there are any items in the Inventory and indeed could in principle scroll when the game starts. To protect against Inventory feeling too small, it could have a fixed size of say 5, and scroll after that, with the remaining space, based on screen size, given over to Places and Objects, which then scrolls when full?

Perhaps what I'm suggesting is covered by option 2 anyway? ...in a better way!


Another option; I didn't think of that one :)

Shouldn't be too hard to do; I'll take another look in the morning, because I should really be working now.

I think the best approach is to create a function which adjusts the pane sizes. It should be called whenever the list of visible items is updated, when an item is selected (to account for the space taken up by newly-displayed verb buttons), and whenever the window is resized.

My initial thoughts for layout are to set:
$('#gamePanes').css({height: 'auto', minHeight: 'initial', bottom: 1});
That prevents the sidebar from being taller than the screen, so that we can then use $('#gamePanes').height() to get the available space for panes, and $('#gamePanesRunning').outerHeight(true) will give the space currently taken up by the panes.

So…

function resizePanes() {
  // enlarge both panes to fit their contents
  $('.elementListWrapper').css({maxHeight: 'initial'});

  // Work out how much we need to shrink the panes by.
  var spaceNeeded = $('#gamePanesRunning').outerHeight(true) - $('#gamePanes').height();
  if (spaceNeeded > 0) {

    // First see if the inventory pane can be shrunk
    if ($('#lstInventory li').length > 5) {
      // Work out how large (in pixels) the inventory can be to limit it to 5 items
      var targetSize = $('#lstInventory li').first().outerHeight(true) * 5;

      // If the window is really small, we don't want to limit the inventory to 5 items and the placesObjects to 2
      // So in this case, make them both half of the available space
      targetSize = Math.min(targetSize, ($('#inventoryWrapper').outerHeight(true) + $('#placesObjectsWrapper').outerHeight(true) - spaceNeeded)/2 - 1);

      // reduce the spaceNeeded by the amount of space we're saving shrinking the inventory
      spaceNeeded += targetSize - $('#inventoryWrapper').height();
      // and if reducing the inventory to 5 items would leave a space at the bottom of the sidebar, reduce it by less
      if (spaceNeeded < -1) {
        targetSize -= spaceNeeded;
      }
      // And finally, shrink the inventory list
      $('#inventoryWrapper').css({maxHeight: targetSize});
    }

    // Do we still need to save space?
    if (spaceNeeded > 0) {
      // This time it's simple: Just shrink the placesObjects list by exactly enough to fit it on the screen
      $('#placesObjectsWrapper').css({maxHeight: $('#placesObjectsWrapper').height() - spaceNeeded -1});
    }
  }
}

All off the top of my head, but fingers crossed it might work :)

If you need the code to modify updateList and updateVerbButtons so that they call that function, I can do that in the morning when I have less work-stuff pending.


Many thanks mrangel, it feels like that is getting close but my lack of JS knowledge and of how inject this function into a Quest game is catching me out. I've tried using JS.eval ("...") around the above (taking out end of lines) and putting it into the user interface initialisation but nothing happens?


K.V.

If you remove the line breaks, that code is one long comment. In JS, anything after ```//1`` on a line is considered a comment.

This function begins with a comment (and has a few other comments throughout).

function resizePanes() {
  // enlarge both panes to fit their contents
  $('.elementListWrapper').css({maxHeight: 'initial'});

  MORE CODE;
}

So, when you remove the line breaks, you get this:

function resizePanes() {  // enlarge both panes to fit their contents  $('.elementListWrapper').css({maxHeight: 'initial'}); MORE CODE; }

That may as well be this: function resizePanes() { // Lots of notes, and that's all. }

The function does nothing. Everything in the script is considered a comment, so nothing runs.

If it makes you feel better, I learned this by doing exactly what you did: I copied one of mrangel's JS functions into a JS.eval() and removed all the line breaks. It took me quite a while to figure out why nothing was happening. It was so frustrating, I'll never forget the lesson. Anyway. . .


One way to fix this is to change each line like // Comment text to /* Comment text */ before removing the line breaks.

Another is to simply remove the lines that are comments before removing the line breaks.

Another is to paste mrangel's unaltered code directly into the game's Javascript in the desktop editor.


Sorry KV, I did remove the comments as well, editing in Notepad++.

I would like to paste the code directly into Javascript in the desktop editor, so now is the time to learn! When I try to add it, Quest looks for a file name. Presumably this is sorting out the initial state. I couldn't see a description of how to set that up when I looked before?

Apologies for the 'hand-holding'!


K.V.

I have no Windows access at the moment, but I'm pretty sure the steps are:

  1. Click on "Advanced" in the object tree (this will show you the Javascript object)

  2. Click on the "Javascript" object (you may have to name and save a JS file, but Quest will automatically initiate this for you - the name does not matter)

  3. Paste mrangel's code directly into the text field


EDIT

To call the function from Quest, use this line of code (probably in the game's UI Init script):

JS.resizePanes()

EDIT 2

To call the function during play in the Quest desktop player, open the HTML tools, go to the Console tab, and enter resizePanes().


As far as I understand it, in the desktop editor javascript is like images. Save the script in a file on its own, change the file extension from .txt to .js, and then add that file to your Quest project.

That function should adjust the sizes of everything each time it is run. (if it works - I haven't debugged it yet).
So once you've got it in the game, you can go to the javascript console (Ctrl+Shift+J on Chrome) and type resizePanes() and it should set your panes to a sensible size. Might be worth trying resizing the window, and trying it with more or fewer items in the placesObjects and the inventory, to make sure it behaves will in different situations.

Once you've got the resizePanes function debugged and you know it works well, you can set up the code to call the function automatically each time it's needed. Something like:

// This little piece of voodoo programming encloses our "var" definitions so that they won't
//   conflict with any of my other libraries that use this structure. As well as delaying this code's
//   execution until all the javascripts have loaded. and the function definition has been executed:
$(function() {

  // Make a copy of the default functions
  // Your game probably doesn't need all of these, but they're included so this code can be used
  //   without modification in other games
  var originalUpdateList = updateList;
  var originalUpdateVerbButtons = updateVerbButtons;
  var originalUpdateStatus = updateStatus;
  var originalSetCustomStatus = setCustomStatus;
  var originalUpdateStatusVisibility = updateStatusVisibility;
  var originalShowStatusVisible = showStatusVisible;

  // Then we replace each of those functions with one that calls the original version,
  //   and then calls resizePanes()
  updateList = function(name, data) {
    originalUpdateList(name, data);
    resizePanes();
  };
  updateVerbButtons = function(item, arr, prefix) {
    originalUpdateVerbButtons(item, arr, prefix);
    resizePanes();
  };
  updateStatus = function(txt) {
    originalUpdateStatus(txt);
    resizePanes();
  };
  setCustomStatus = function(txt) {
    originalSetCustomStatus(txt);
    resizePanes();
  };
  updateStatusVisibility = function() {
    originalUpdateStatusVisibility();
    resizePanes();
  };
  showStatusVisible = function(t) {
    originalShowStatusVisible(t);
    resizePanes();
  };

  // And we might also need to adjust the scroll bars when the window is resized
  $(window).resize( resizePanes );
});

Again, sorry if there's any errors in there.


Excellent! Playing these games no longer feels like keyhole surgery!

I've just played on a desktop so far and the games now play through fully without the need to scroll. Only issue I've noticed so far is in connection with indentation of the names in the panes, which needs a bit more exploration.

I also tried tackling the second stage, of including the above code in the JS file as well. I did that to see what would happen if if I resized the window. The answer is 'nothing' at the moment, with panes simply overrunning the bottom of the page.

I'll experiment further but progress so far is extremely encouraging!


...on a laptop the game I'm trying does build up to exceed the pane size and there is no auto-scrolling when that happens? Ignore the indentation problem for the moment...that may be me!


Hmm… strange.

If you run resizePanes() from the console does it size correctly?

Edit: slightly streamlined the code below

I'm just playing with the game you linked above. The resizePanes function appears to be working, though a few of the sizes are slightly off. I think my calculations might be omitting the width of the borders or something. Pasting the second chunk of code I posted today appears to make it work. The panes are appropriately resized when I resize the window, when more items become visible, when I take or drop items, and when I select a different item which changes the number of rows of verb buttons visible.

The complete JS I'm using is:

$('#gamePanes').css({bottom: 9, minHeight: 'initial', height: 'auto'});
$(function() {
  // The resize function - replace this if you want to change your mind about the size
  //   of each pane.
  // Remove the "var" from this line if you need to call `JS.resizePanes()` from Quest
  var resizePanes = function() {
    // enlarge both panes to fit their contents
    $('.elementListWrapper').css({maxHeight: 'initial'});

    // Work out how much we need to shrink the panes by.
    var spaceNeeded = $('#gamePanesRunning').outerHeight(true) - $('#gamePanes').height();
    if (spaceNeeded > 0) {

      // First see if the inventory pane can be shrunk
      if ($('#lstInventory li').length > 5) {
        // Work out how large (in pixels) the inventory can be to limit it to 5 items
        var targetSize = $('#lstInventory li').first().outerHeight(true) * 5;

        // If the window is really small, we don't want to limit the inventory to 5 items and the placesObjects to 2
        // So in this case, make them both half of the available space
        targetSize = Math.min(targetSize, ($('#inventoryWrapper').outerHeight(true) + $('#placesObjectsWrapper').outerHeight(true) - spaceNeeded)/2 - 1);

        // reduce the spaceNeeded by the amount of space we're saving shrinking the inventory
        spaceNeeded += targetSize - $('#inventoryWrapper').height();
        // and if reducing the inventory to 5 items would leave a space at the bottom of the sidebar, reduce it by less
        if (spaceNeeded < -1) {
          targetSize -= spaceNeeded;
        }
        // And finally, shrink the inventory list
        $('#inventoryWrapper').css({maxHeight: targetSize});
      }

      // Do we still need to save space?
      if (spaceNeeded > 0) {
        // This time it's simple: Just shrink the placesObjects list by exactly enough to fit it on the screen
        $('#placesObjectsWrapper').css({maxHeight: $('#placesObjectsWrapper').height() - spaceNeeded -1});
      }
    }
  };

  // Make a copy of the default functions
  // Your game probably doesn't need all of these, but they're included so this code can be used
  //   without modification in other games
  var originalUpdateList = updateList;
  var originalUpdateVerbButtons = updateVerbButtons;
  var originalUpdateStatus = updateStatus;
  var originalSetCustomStatus = setCustomStatus;
  var originalUpdateStatusVisibility = updateStatusVisibility;
  var originalShowStatusVisible = showStatusVisible;
  var originalShow = uiShow;
  var originalHide = uiHide;

  // Then we replace each of those functions with one that calls the original version,
  //   and then calls resizePanes()
  updateList = function(name, data) {
    originalUpdateList(name, data);
    resizePanes();
  };
  updateVerbButtons = function(item, arr, prefix) {
    originalUpdateVerbButtons(item, arr, prefix);
    resizePanes();
  };
  updateStatus = function(txt) {
    originalUpdateStatus(txt);
    resizePanes();
  };
  setCustomStatus = function(txt) {
    originalSetCustomStatus(txt);
    resizePanes();
  };
  updateStatusVisibility = function() {
    originalUpdateStatusVisibility();
    resizePanes();
  };
  showStatusVisible = function(t) {
    originalShowStatusVisible(t);
    resizePanes();
  };
  uiShow = function(elem) {
    originalShow(elem);
    resizePanes();
  };
  uiHide = function(elem) {
    originalHide(elem);
    resizePanes();
  };

  // And we might also need to adjust the scroll bars when the window is resized
  $(window).resize( resizePanes );
});

Or minified for easier pasting into Quest's UI init:

JS.eval("$('#gamePanes').css({bottom:9,minHeight:'initial',height:'auto'}),$(function(){var n=function(){$('.elementListWrapper').css({maxHeight:'initial'});var t=$('#gamePanesRunning').outerHeight(!0)-$('#gamePanes').height();if(0<t){if(5<$('#lstInventory li').length){var e=5*$('#lstInventory li').first().outerHeight(!0);(t+=(e=Math.min(e,($('#inventoryWrapper').outerHeight(!0)+$('#placesObjectsWrapper').outerHeight(!0)-t)/2-1))-$('#inventoryWrapper').height())<-1&&(e-=t),$('#inventoryWrapper').css({maxHeight:e})}0<t&&$('#placesObjectsWrapper').css({maxHeight:$('#placesObjectsWrapper').height()-t-1})}},i=updateList,s=updateVerbButtons,e=updateStatus,a=setCustomStatus,t=updateStatusVisibility,u=showStatusVisible,o=uiShow,r=uiHide;updateList=function(t,e){i(t,e),n()},updateVerbButtons=function(t,e,i){s(t,e,i),n()},updateStatus=function(t){e(t),n()},setCustomStatus=function(t){a(t),n()},updateStatusVisibility=function(){t(),n()},showStatusVisible=function(t){u(t),n()},uiShow=function(t){o(t),n()},uiHide=function(t){r(t),n()},$(window).resize(n)});")

Not sure what the issue is here mrangel, probably something simple. I used your latest code and still have the same problem. When I try it from the console the response is a very unhelpful < undefined with a dot in the middle of the < symbol. No idea what it means nor how to find out more.


...tried the minimised version and it works!


The console displays the return value from any function you specify there. In the case of resizePanes() that will give undefined because the function doesn't return a value. It should still resize the panes.

If not, I'm not sure of the difference. I tried pasting the whole thing into the JS console on the game you linked, and it seemed to be working as intended.


K.V.

Maybe the function is running before the panes are created? (Just a wild guess. Seems like I recall running into an issue like that before.)


Mea Culpa!! I am working on several games at the same time and said there was a problem based on one that wasn't set up properly. Apologies for wasting everyone's time. I've now gone over everything more carefully, played the games, and both options seem perfect. I'll use the embedded version, even though I can't read it. Thanks mrangel and K.V. for your support...as always!


Maybe the function is running before the panes are created? (Just a wild guess. Seems like I recall running into an issue like that before.)

Shouldn't be. The panes are in playercore.htm, so they exist even if they're not visible. The $(); block ensures that the code inside it runs after the original function definitions are loaded, so that it can override them. So the modified updateList will adjust the panes to the correct size as soon as Quest core sends the initial placesObjects list.

Hmm… it could be that the $(); block is being run after the first browser sync block, so the panes aren't resized immediately.

Also, I think that in the list of overridden functions, I should probably have included uiHide and uiShow. That makes sure that the panes will resize correctly if any other element in the sidebar is shown or hidden.
(When the sidebar is hidden, resizePanes will still be called but both the heights of the elements will be 0, meaning that spaceNeeded is 0 too, so nothing is resized)


Thanks again for the code! The first two games in the EtP series (Escape this Podcast) have been updated to use it, and others will follow:
http://textadventures.co.uk/games/view/4vyqhsn-fe_izwyfrtgj5g/escape-this-podcast-episode-1-alexs-bathroom
http://textadventures.co.uk/games/view/vd0ovejhm0_vykxj4cjhlq/escape-this-podcast-episode-2-the-speakeasy

I also updated a different type of game that had been putting the panes under pressure because of a large Inventory:
http://textadventures.co.uk/games/view/dsi4artkceuko4rslaxzlq/woo-rebooted

This has 4 panes but all worked well when the screen limit was hit. Excellent and a clear improvement to the game.

This code must be a strong candidate for inclusion in standard Quest!


This code must be a strong candidate for inclusion in standard Quest!

If you're doing that, you'd want to give the option of adjusting the sizes of the panes in different ways.

The ones I thought of:

  1. Proportional sizing
function resizePanes() {
  // enlarge both panes to fit their contents
  $('.elementListWrapper').css({maxHeight: 'initial'});

  // Work out how much we need to shrink the panes by.
  var spaceNeeded = $('#gamePanesRunning').outerHeight(true) - $('#gamePanes').height();
  if (spaceNeeded > 0) {
    // determine the total size available for the panes
    var totalHeight = $('#inventoryWrapper').height() + $('placesObjectsWrapper').height();
    var availableSpace = totalHeight - spaceNeeded;

    // and how much space each list should be sized to
    var inventoryHeight = Math.floor($('#inventoryWrapper').height() * availableSpace / totalHeight);
    var placesObjectsHeight = Math.floor($('#placesObjectsWrapper').height() * availableSpace / totalHeight);

    // make sure that there's actually space for both lists
    //   (if the window is really small or there are other panes that are huge, don't shrink the lists)
    var sizeMinimum = $('.elementList').children('li').outerHeight() * 2;
    if (availableSpace > sizeMinimum * 2) {
      if (inventoryHeight < sizeMinimum) {
        inventoryHeight = sizeMinimum;
        placesObjectsHeight = availableSpace - inventoryHeight;
      } elsif (placesObjectsHeight < sizeMinimum) {
        placesObjectsHeight = sizeMinimum;
        inventoryHeight = availableSpace - placesObjectsHeight;
      }
      $('#placesObjectsWrapper').css({maxHeight: placesObjectsHeight});
      $('#inventoryWrapper').css({maxHeight: inventoryHeight});
    }
  }
}
  1. "largest first" sizing
function resizePanes() {
  // enlarge both panes to fit their contents
  $('.elementListWrapper').css({maxHeight: 'initial'});

  // Work out how much we need to shrink the panes by.
  var spaceNeeded = $('#gamePanesRunning').outerHeight(true) - $('#gamePanes').height();
  if (spaceNeeded > 0) {

    // find out if shrinking the larger pane to the size of the smaller one would be sufficient
    var totalHeight = $('#inventoryWrapper').height() + $('placesObjectsWrapper').height();
    var smallerHeight = Math.min($('#inventoryWrapper').height(), $('placesObjectsWrapper').height());

    var targetHeight = (totalHeight - spaceNeeded > smallerHeight * 2) ? (totalHeight - smallerHeight - spaceNeeded) : Math.floor((totalHeight - spaceNeeded) / 2);

    // And make sure there's enough space before shrinking
    if (targetHeight > $('.elementList').children('li').outerHeight() * 3) {
      $('.elementListWrapper').css({maxHeight: targetHeight});
    }
  }
}

I think either of those should work with the script I posted before.
But if you add:

$('#gamePanes').css({width: 250, overflowX: 'hidden', overflowY: 'auto'});
$('#gamePanesRunning #gamePanesFinished').css({width: 216, right: 32});

to the start of the script, I think that should fix the issues with very small windows.
(if resizePanes can't shrink the panes by adding a scroll bar to one or both, for example because a very small window is entirely taken up by the compass and status panes, a single long scroll bar will appear to let you scroll the entire sidebar)

This would allow my option 3 from the ones I suggested above:

  1. No individual scroll bars.
function resizePanes() {
  $('.elementListWrapper').css({maxHeight: 'initial'});
}

I think if this was part of the core, you'd probably want to include a couple of different resize functions, and maybe use a global variable to choose between them.

I'm also trying to think of ways to make this work with an arbitrary number of panes (for example, I believe there's a mod out there that adds a new pane for a spellbook or similar, or gives separate inventory and backpack panes.)


OK, trying to put all that together…

$(function() {
  $('#gamePanes').css({bottom: 9, minHeight: 'initial', height: 'auto', width: 250, overflowX: 'hidden', overflowY: 'auto'});
  $('#gamePanesRunning #gamePanesFinished').css({width: 216, right: 32});

  // Include a set of resize functions to choose from
  var builtInResizeFunctions = {
    proportional: function() {
      // enlarge both panes to fit their contents
      $('.elementListWrapper').css({maxHeight: 'initial'});

      // Work out how much we need to shrink the panes by.
      var spaceNeeded = $('#gamePanesRunning').outerHeight(true) - $('#gamePanes').height();
      if (spaceNeeded > 0) {
        // determine the total size available for the panes
        var totalHeight = $('#inventoryWrapper').height() + $('placesObjectsWrapper').height();
        var availableSpace = totalHeight - spaceNeeded;

        // and how much space each list should be sized to
        var inventoryHeight = Math.floor($('#inventoryWrapper').height() * availableSpace / totalHeight);
        var placesObjectsHeight = Math.floor($('#placesObjectsWrapper').height() * availableSpace / totalHeight);

        // make sure that there's actually space for both lists
        //   (if the window is really small or there are other panes that are huge, don't shrink the lists)
        var sizeMinimum = $('.elementList').children('li').outerHeight() * 2;
        if (availableSpace > sizeMinimum * 2) {
          if (inventoryHeight < sizeMinimum) {
            inventoryHeight = sizeMinimum;
            placesObjectsHeight = availableSpace - inventoryHeight;
          } else if (placesObjectsHeight < sizeMinimum) {
            placesObjectsHeight = sizeMinimum;
            inventoryHeight = availableSpace - placesObjectsHeight;
          }
          $('#placesObjectsWrapper').css({maxHeight: placesObjectsHeight});
          $('#inventoryWrapper').css({maxHeight: inventoryHeight});
        }
      }
    },
    equal: function() {
      // enlarge both panes to fit their contents
      $('.elementListWrapper').css({maxHeight: 'initial'});

      // Work out how much we need to shrink the panes by.
      var spaceNeeded = $('#gamePanesRunning').outerHeight(true) - $('#gamePanes').height();
      if (spaceNeeded > 0) {

        // find out if shrinking the larger pane to the size of the smaller one would be sufficient
        var totalHeight = $('#inventoryWrapper').height() + $('placesObjectsWrapper').height();
        var smallerHeight = Math.min($('#inventoryWrapper').height(), $('placesObjectsWrapper').height());

        var targetHeight = (totalHeight - spaceNeeded > smallerHeight * 2) ?
          (totalHeight - smallerHeight - spaceNeeded) :
          Math.floor((totalHeight - spaceNeeded) / 2);

        // And make sure there's enough space before shrinking
        if (targetHeight > $('.elementList').children('li').outerHeight() * 3) {
          $('.elementListWrapper').css({maxHeight: targetHeight});
        }
      }
    },
    'global': function() {
      $('.elementListWrapper').css({maxHeight: 'initial'});
    }
  };

  // The resize function is in a framed variable to let it be modified.
  // By default it does nothing
  var resizePanes = function() {};

  changePaneResizeMode = function (mode) {
    if (typeof mode == 'function') {
      resizePanes = mode;
    } else if (builtInResizeFunctions[mode]) {
      resizePanes = builtInResizeFunctions[mode];
    } else if (mode) {
      resizePanes = eval(mode);
    } else {
      resizePanes = builtInResizeFunctions['equal'];
    }
    // And resize now, to make sure everything is initially set up right
    resizePanes();
  };

  // Make a copy of the default functions
  // Your game probably doesn't need all of these, but they're included so this code can be used
  //   without modification in other games
  var originalUpdateList = updateList;
  var originalUpdateVerbButtons = updateVerbButtons;
  var originalUpdateStatus = updateStatus;
  var originalSetCustomStatus = setCustomStatus;
  var originalUpdateStatusVisibility = updateStatusVisibility;
  var originalShowStatusVisible = showStatusVisible;
  var originalShow = uiShow;
  var originalHide = uiHide;

  // Then we replace each of those functions with one that calls the original version,
  //   and then calls resizePanes()
  updateList = function(name, data) {
    originalUpdateList(name, data);
    resizePanes();
  };
  updateVerbButtons = function(item, arr, prefix) {
    originalUpdateVerbButtons(item, arr, prefix);
    resizePanes();
  };
  updateStatus = function(txt) {
    originalUpdateStatus(txt);
    resizePanes();
  };
  setCustomStatus = function(txt) {
    originalSetCustomStatus(txt);
    resizePanes();
  };
  updateStatusVisibility = function() {
    originalUpdateStatusVisibility();
    resizePanes();
  };
  showStatusVisible = function(t) {
    originalShowStatusVisible(t);
    resizePanes();
  };
  uiShow = function(elem) {
    originalShow(elem);
    resizePanes();
  };
  uiHide = function(elem) {
    originalHide(elem);
    resizePanes();
  };

  // And we might also need to adjust the scroll bars when the window is resized
  $(window).resize( function() { resizePanes(); } );
});

Haven't tested that yet, but it would minify to:

JS.eval("$(function(){$('#gamePanes').css({bottom:9,minHeight:'initial',height:'auto',width:250,overflowX:'hidden',overflowY:'auto'}),$('#gamePanesRunning #gamePanesFinished').css({width:216,right:32});var t={proportional:function(){$('.elementListWrapper').css({maxHeight:'initial'});var e=$('#gamePanesRunning').outerHeight(!0)-$('#gamePanes').height();if(0<e){var t=$('#inventoryWrapper').height()+$('placesObjectsWrapper').height(),i=t-e,n=Math.floor($('#inventoryWrapper').height()*i/t),a=Math.floor($('#placesObjectsWrapper').height()*i/t),s=2*$('.elementList').children('li').outerHeight();2*s<i&&(n<s?a=i-(n=s):a<s&&(n=i-(a=s)),$('#placesObjectsWrapper').css({maxHeight:a}),$('#inventoryWrapper').css({maxHeight:n}))}},equal:function(){$('.elementListWrapper').css({maxHeight:'initial'});var e=$('#gamePanesRunning').outerHeight(!0)-$('#gamePanes').height();if(0<e){var t=$('#inventoryWrapper').height()+$('placesObjectsWrapper').height(),i=Math.min($('#inventoryWrapper').height(),$('placesObjectsWrapper').height()),n=2*i<t-e?t-i-e:Math.floor((t-e)/2);n>3*$('.elementList').children('li').outerHeight()&&$('.elementListWrapper').css({maxHeight:n})}},global:function(){$('.elementListWrapper').css({maxHeight:'initial'})}},n=function(){};changePaneResizeMode=function(e){(n='function'==typeof e?e:t[e]?t[e]:e?eval(e):t.equal)()};var i=updateList,a=updateVerbButtons,s=updateStatus,r=setCustomStatus,e=updateStatusVisibility,o=showStatusVisible,u=uiShow,h=uiHide;updateList=function(e,t){i(e,t),n()},updateVerbButtons=function(e,t,i){a(e,t,i),n()},updateStatus=function(e){s(e),n()},setCustomStatus=function(e){r(e),n()},updateStatusVisibility=function(){e(),n()},showStatusVisible=function(e){o(e),n()},uiShow=function(e){u(e),n()},uiHide=function(e){h(e),n()},$(window).resize(function(){n()})});")

And you could then adjust the resizing mode of the panes by doing one of:

  • JS.changePaneResizeMode("proportional")
  • JS.changePaneResizeMode("equal")
  • JS.changePaneResizeMode("global")

Have I made any dumb mistakes there?


Tried it out. Just one issue. Should the 250 in $('#gamePanes').css({width: 250, overflowX: 'hidden', overflowY: 'auto'}); be 216?

All three modes feel like a huge step forward from the current restricted sizes! ...and I'd be happy with any of them in the games I've worked on.


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums