haxball / haxball-issues

116 stars 43 forks source link

Sorting options!!! #478

Open RennSoo opened 6 years ago

RennSoo commented 6 years ago

8 years. We still can't sort rooms by countries, ping, etc...

pilaf commented 6 years ago

And for infinite years before that you couldn't play HaxBall at all, so at least show a little humility instead of acting like basro owes you anything (which probably won't make him want to help with your issue, so you're basically killing your chances).

Leo-MapCreator commented 6 years ago

Sorting is indeed a good idea, i dont know if basro want to implement this tough

RennSoo commented 6 years ago

Pilaf, I'm willing to pay for some changes. But i don't think it's hard to do that(sorting). We don't even need other kinds of sorting. Only by countries will be enough. Cause when i trying to join in full room again and again, every time I have to scroll far down. It's very inconvenient.

kamild706 commented 6 years ago

I created a Greasemonkey extension which allows you to filter rooms by country

screenshot_2018-08-02 haxball play

It filters rooms by class name, so you need to know which class name corresponds to which country. The list of valid classes is available at Pastebin (I extracted this from css rules). Not all of them are obvious, but you should easily guess which one corresponds to your country. If not, you can inspect html document and see which class is set for your country.

untitled In this example, the abbreviation for selected flag is rs

You need to install Greasemonkey (or Tampermonkey) in your browser and add following script. Note that the script is a bit buggy when it comes to refresh button.

// ==UserScript==
// @name     Haxball Room Filter
// @author kamild706
// @version  2
// @grant    none
// @include https://www.haxball.com/play*
// ==/UserScript==

((() => {
  "use strict";

  let iframe = document.querySelector(".gameframe");
  let content = iframe.contentDocument || iframe.contentWindow.document;
  let waitTillRoomListAppeareInterval;
  let waitTillRoomListDisappeareInterval;
  let lastClassName;

  let waitTillRoomListAppeare = () => {
    let roomView = content.querySelector(".roomlist-view");
    if (roomView) {
      clearInterval(waitTillRoomListAppeareInterval);
      setTimeout(() => {
        process();
      }, 500)
      waitTillRoomListDisappeareInterval = setInterval(waitTillRoomListDisappeare, 500);
    }
  };

  let waitTillRoomListDisappeare = () => {
    let roomView = content.querySelector(".roomlist-view");
    if (!roomView) {
      clearInterval(waitTillRoomListDisappeareInterval);
      waitTillRoomListAppeareInterval = setInterval(waitTillRoomListAppeare, 500);
    }
  }

  waitTillRoomListAppeareInterval = setInterval(waitTillRoomListAppeare, 500);

  function process() {
    let table = content.querySelector(".content.ps tbody");
    let input;

    setupInputElement();
    setupRefreshButtonListener();

    loadPreviousFilter();

    function setupInputElement() {
      let inputLocation = content.querySelector(".spacer");
      input = document.createElement("input");
      input.style.width = "144px";
      input.style.border = "4px #244967 solid";
      inputLocation.appendChild(input);

      input.addEventListener("keyup", () => {
        let value = input.value;
        let className = `f-${value}`;
        filterRooms(className);
      });
    }

    function setupRefreshButtonListener() {
      let refresh = content.querySelector("[data-hook='refresh']");
      refresh.addEventListener("click", () => {
        setTimeout(() => {
          loadPreviousFilter();
        }, 800)
      });
    }

    function loadPreviousFilter() {
      if (lastClassName) {
        filterRooms(lastClassName);
        input.value = lastClassName.substring(2);
      }
    }

    function filterRooms(className) {
      if (className.length >= 4 || className.length === 2) {
        lastClassName = className;
      }

      for (let row of table.children) {
        let location = row.children[3];
        let flag = location.children[0];
        row.style.display = "";
        if (className.length >= 4 && flag.classList[1] !== className) {
          row.style.display = "none";
        }
      }
    }
  }
}))();
RennSoo commented 6 years ago

kamild706, not bad!! But this is not the solution. When I go back to list mode after a failed attempt, the sort is not saved. I spend about the same amount of time to write it again, as during scrolling. We need options, which will be saved even after refreshing the site. As example - options of sound, or viewport size.

olehmisar commented 6 years ago

You can save current term in variable and then make setupInputButton function to accept first argument as value for that input: setupInputButton(value)

kamild706 commented 6 years ago

@RennSoo I updated the code in previous post. Now it should work as you expect. More over, the script should work correctly with refresh button. You may notice a delay when you click the button, which I arbitrary chose as 800 ms. This is because listening for changes inside iframe tag is not a simple thing and this is a workaround I thought up. You may diminish this value if it is too long for you, but do it with caution. This feature (refresh button support) will work only if list of rooms appears in less than given time after clicking refresh button. From my experience sometimes it takes even more than few seconds, but we have to reach a compromise.

RennSoo commented 6 years ago

@kamild706 Great job, dude, Thank you! But i hope developers will add it officially. Because that extension works only in firefox =(

kamild706 commented 6 years ago

@RennSoo I tested this script on Firefox 61 and Chrome 68 on Linux Debian. I updated the code a bit so you may try to increase the setTimer delay inside waitTillRoomListAppeare. As I said, it is not easy to keep track of changes inside iframe, and my approach is based on fixed-time waiting. This solution works only if changes occur during the time of waiting. Unfortunately, sometimes it takes more than specified time for changes to become fully loaded and then my script could not work correctly.