demo page - load/save state from/to url fragment ID / hash string
milahu opened this issue · 1 comments
milahu commented
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 commented
gh-pages is already public at https://github.com/felixhao28/JSCPP/tree/gh-pages
. Feel free to send a PR. : )