Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

demo page - load/save state from/to url fragment ID / hash string #59

Open
milahu opened this issue Aug 15, 2020 · 1 comment
Open

demo page - load/save state from/to url fragment ID / hash string #59

milahu opened this issue Aug 15, 2020 · 1 comment

Comments

@milahu
Copy link
Contributor

milahu commented Aug 15, 2020

please include this feature on the demo page, so we can link to demo code

sample implementation:

Main = React.createClass({
  // ....
  saveToUrl: function(e) {
    if (e != null) {
      e.preventDefault();
    }
    return setFragmentFromState(this.state);
  },
  loadFromUrl: function(e) {
    if (e != null) {
      e.preventDefault();
    }
    return this.setState(
      getStateDiffFromFragment()
    );
  },
var parseQueryString = function(input) {
  // similar to PHP $_GET[key]
  // return array of values if key is repeated in query string
  let queryObject = {};
  const re = /([^?&=]+)(?:=([^&]+))?/g;
  let match;
  while (match = re.exec(input)) {
    const [k, v] = [
      decodeURIComponent(match[1]),
      // empty value = true
      (decodeURIComponent(match[2]) || true)
    ];
    if (k in queryObject) {
      if (Array.isArray(queryObject[k])) {
        queryObject[k].push(v);
      } else {
        queryObject[k] = [queryObject[k], v];
    }} else {
      queryObject[k] = v;
    }
  }
  return queryObject;
};

// keys shared between state and fragment query string
// key "code" is always shared
const fragmentKeys = ["input"];

var getStateDiffFromFragment = function() {
  // fragment string format: key=val&key2=val2/codeString
  // val, val2, ... must be encoded with encodeURIComponent
  // codeString can be encoded with encodeURI
  // which is more compact than encodeURIComponent
  const idxCode = document.location.hash.indexOf("/");
  const query = parseQueryString(
    document.location.hash.substring(1, idxCode));
  let stateDiff = Object.keys(query).reduce((acc, key) => {
    if (fragmentKeys.includes(key)) {
      acc[key] = query[key];
    }
    return acc;
  }, {});
  const code = decodeURI(document.location.hash.substring(idxCode + 1));
  if (code) {
    stateDiff.code = code;
  }
  return stateDiff;
};

var setFragmentFromState = function(state) {
  document.location.hash = fragmentKeys.reduce((acc, key) => {
    if (state[key]) {
      acc.push(`${key}=${encodeURIComponent(state[key])}`)
    }
    return acc;
  }, []).join("&") + "/" + encodeURI(state.code);
};

javascript says document.location.hash, the official name is fragment identifier

limitation: old browsers limit URL length

license is creative-commons-zero, so feel free to steal my code

ps: can you make /gh-pages public? (including jsx files)

@felixhao28
Copy link
Owner

gh-pages is already public at https://github.com/felixhao28/JSCPP/tree/gh-pages. Feel free to send a PR. : )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants