ThePix / QuestJS

A major re-write of Quest that is written in JavaScript and will run in the browser.
MIT License
66 stars 13 forks source link

[Add] Function CreateMenu() #39

Closed DakinQuelia closed 3 years ago

DakinQuelia commented 3 years ago

Hello,

It's me again lol

CSS Style :

.menu {
  float: right;
  display: inline-block;
}

.menu a {
  display: inline-flex;
  width: 20px;
  height: 20px;
  border: #ccc 1px solid;
  border-radius: 4px;
  padding: 3px;
  margin-left: 3px;
  background-color: #f9f9f9;
  text-decoration: none;
}

.menu a i {
  vertical-align: middle;
  margin: auto;
}

.menu a:hover {
  color: #FF0000;
}

In "lib/_io.js" :

/**
*   Create a menu with icon
*    menu = [
*        { id: "", title: "", icon: "", onclick: "", href: "" }
*    ];
**/
function createMenu(menu = [])
{
    let html = '<div class="menu">';

    for (let link of menu)
    {
        html += `<a href="${link.href}" onclick="${link.onclick}" id="${link.id}"><i class="fas ${link.icon}" title="${link.title}"></i></a>`;
    }

    html += '</div>';

    $("h2").before(html);
}

Example of settings :

settings.menu = [
    { id: "about", title: "A propos", icon: "fa-info", onclick: "about()", href: "#" },
    { id: "save", title: "Sauvegarder", icon: "fa-save", onclick: "saveGame()", href: "#" }
];

settings.setup = function() 
{
    createMenu(settings.menu);
};

iconmenu

Best regards

ThePix commented 3 years ago

That looks cool. Minor point, I would call it a toolbar, not a menu,

Could it be extended to have a score or other status on the left?

DakinQuelia commented 3 years ago

Yes for Toolbar ; you're right. We can rename the function to createToolbar().

Yes, it's possible to extend.

DakinQuelia commented 3 years ago

You like this ?

Toolbar

ThePix commented 3 years ago

I would prefer to have the score aligned to the left, and buttons to the right. And possibly the current room in the middle

DakinQuelia commented 3 years ago

Okay ! I'll make that.

Exists it a function to get current room to use in function ?

DakinQuelia commented 3 years ago

Like this ?

toolbarv2

DakinQuelia commented 3 years ago

I'm using this : w[w.me.loc].alias to display the location. But I'd like the refresh room name when the player move from location.

ThePix commented 3 years ago

Looking good. How does it look with the side pane turned off? Is it the width of the text or the full page?

Use lang.getName(w[game.player.loc], {article:DEFINITE}) to get the room name (for normal text you can use the text processor directive {hereName}, so I do not think a dedicated function is necessary).

I would suggest adding something to io.updateStatus that checks if there is a toolbar, and calling its update function if there is, to have the room name update. It will do that every turn, but authors might want to display the turn number up there, so this would cover all options.

DakinQuelia commented 3 years ago

Here is my code :

In "*game-/style.css**" :

Add to end file :

/***
* Toolbar 
***/
.toolbar {
  display: inline-flex;
  width: 100%;
  height: 20px;
  margin-top: -3px;
}

.toolbar.button {
  height: 20px;
  border: #ccc 1px solid;
  border-radius: 4px;
  padding: 4px;
  background-color: #f9f9f9;
  text-decoration: none;
  vertical-align: middle;
}

.toolbar .status {
  float: left;
  text-align: left;
  padding-left: 5px;
}

.toolbar .room {
  text-align: center;
  margin: auto;
}

.toolbar .links {
  float: right;
  text-align: right;
}

.toolbar a.link {
  color: #000000;
  vertical-align: middle;
  padding-left: 5px;
  padding-right: 5px;
  text-decoration: none;
}

.toolbar a.link:hover {
  color: blue;
}

In "*game-/settings.js**" :

settings.toolbar = true;
settings.toolbar_options = [
    { id: "about", title: "A propos", icon: "fa-info", onclick: "about()", href: "#" },
    { id: "save", title: "Sauvegarder", icon: "fa-save", onclick: "saveGame()", href: "#" },
    { id: "print", title: "Imprimer", icon: "fa-print", onclick: "#", href: "#" },
];
settings.toolbar_status = { 
    display: true, 
    name: "Test", 
    content: `Hitpoints : 100`,
    roomdisplay: true
};

In "lib/_io.js":

Find :

function createPaneBox(position, title, content) { }

After Add :

// Create Toolbar
function createToolbar(options = [], status = {})
{
  let html = "";

  html += '<div class="toolbar button" id="toolbar">';

  if (status.display == true)
  {
    html += '<div class="status">';
    html += ' <div>' + status.content + '</div>';
    html += '</div>';
  }
  else
  {
    html += '<div class="status"></div>';
  }

  if (status.roomdisplay == true)
  {
    html += '<div class="room">';
    html += ' <div>' + lang.getName(w[game.player.loc], { article:DEFINITE }) + '</div>';
    html += '</div>';
  }
  else
  {
    html += '<div class="room"></div>';
  }

  html += '<div class="links">';
    for (let link of options)
    {
        html += ` <a href="${link.href}" class="link" onclick="${link.onclick}" id="${link.id}"><i class="fas ${link.icon}" title="${link.title}"></i></a>`;
  }
  html += '</div>';

  html += '</div>';

    $("#output").before(html);
}

Update the "io.updateStatus" :

io.updateStatus = function() {
  if (!settings.statusPane) return;

  $("#status-pane").empty();
  for (let st of settings.status) {
    if (typeof st === "string") {
      if (game.player[st] !== undefined) {
        let s = '<tr><td width="' + settings.statusWidthLeft + '">' + sentenceCase(st) + "</td>";
        s += '<td width="' + settings.statusWidthRight + '">' + game.player[st] + "</td></tr>";
        $("#status-pane").append(s);
      }
    }
    else if (typeof st === "function") {
      $("#status-pane").append("<tr>" + st() + "</tr>");
    }
  }

  if (settings.toolbar) 
  { 
    $("#toolbar").remove();
    createToolbar(settings.toolbar_options, settings.toolbar_status);
  }
};

Result :

toolbarv2

ThePix commented 3 years ago

Excellent.

I have uploaded it, but I did change it a bit first. I hope you find the changes acceptable

I think you see this as being sent all the values, and then displaying what it is sent, which varies as the game progresses. I think a better approach (and certainly what other parts of Quest 6 do) is for it to be set up according to the settings, and that never changes. So instead of a content string, have a content function that gets called when the toolbar is redrawn; it can find out the hitpoints, and display that.

I have slightly reworked the settings, so everything is in one toolbar dictionary. I have also made it so the buttons can be given a command, rather than an onclick function (i.e., you can do either). For example:

settings.toolbar = {
  content:function() { return `Hitpoints : 100` },
  roomdisplay: true,
  buttons:[
    { id: "about", title: "About", icon: "fa-info", cmd: "about", href: "#" },
    { id: "save", title: "Save", icon: "fa-save", onclick: "saveGame()", href: "#" },
    { id: "print", title: "Print", icon: "fa-print", onclick: "#", href: "#" },
  ],
};

However, I am wondering if you see this as having dynamic buttons. You way would allow the buttons to change every turn. My way assumes the buttons never change.

I will leave this open, so we can discuss further.

DakinQuelia commented 3 years ago

Excellent. It's better for settings. :)

For buttons, it's better like my method to adapt.

It's good job.

DakinQuelia commented 3 years ago

A little error : it's not status.roomdisplay but settings.toolbar.roomdisplay

However it doesn't display the location.

ThePix commented 3 years ago

Fixed, thanks.

And now with documentation. https://github.com/ThePix/QuestJS/wiki/Adding-a-toolbar

DakinQuelia commented 3 years ago

Good Job 👍

ThePix commented 3 years ago

You too!