Skip to content

Instantly share code, notes, and snippets.

@ngbrown
Last active November 29, 2016 17:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ngbrown/d1874f93beebc3e6724217f88cc2d295 to your computer and use it in GitHub Desktop.
Save ngbrown/d1874f93beebc3e6724217f88cc2d295 to your computer and use it in GitHub Desktop.
redux-little-router utility functions for onClick and onSubmit
import {PUSH, REPLACE} from "redux-little-router";
import defaultCreateLocation from "redux-little-router/lib/util/create-location.js";
// Adapted from https://github.com/FormidableLabs/redux-little-router
// specifically the Link component (https://github.com/FormidableLabs/redux-little-router/blob/master/src/link.js)
const normalizeHref = ({ basename, pathname, search }) =>
`${basename || ''}${pathname}${search || ''}`;
const normalizeLocation = href => {
if (typeof href === 'string') {
const pathnameAndQuery = href.split('?');
const pathname = pathnameAndQuery[0]; // eslint-disable-line no-magic-numbers
const query = pathnameAndQuery[1]; // eslint-disable-line no-magic-numbers
return query ? { pathname, search: `?${query}` } : { pathname };
}
return href;
};
const resolveQueryForLocation = ({
linkLocation,
persistQuery,
currentLocation
}) => {
const currentQuery = currentLocation &&
currentLocation.query;
// Only use the query from state if it exists
// and the href doesn't provide its own query
if (
persistQuery &&
currentQuery &&
!linkLocation.search &&
!linkLocation.query
) {
return {
pathname: linkLocation.pathname,
query: currentQuery
};
}
return linkLocation;
};
const isNotLeftClick = e => e.button && e.button !== LEFT_MOUSE_BUTTON;
const hasModifier = e => Boolean(e.shiftKey || e.altKey || e.metaKey || e.ctrlKey);
// use like this:
// <NavItem href="/items" onClick={handleClickNav(router, "/items")}>View Items</NavItem>
const handleClickNav = (router, href, replaceState=false, persistQuery=false) => {
const locationDescriptor =
resolveQueryForLocation({
linkLocation: normalizeLocation(href),
currentLocation: router.store.getState().router,
persistQuery
});
const location = defaultCreateLocation(locationDescriptor);
return (e) => {
if (hasModifier(e) || isNotLeftClick(e)) { return; }
if (e.defaultPrevented) { return; }
if (router) {
router.store.dispatch({
type: replaceState ? PUSH : PUSH,
payload: location
});
e.preventDefault();
}
};
};
// from http://stackoverflow.com/a/40705993/25182
function serializeForm(form) {
var result = [];
if (typeof form === 'object' && form.nodeName === 'FORM')
Array.prototype.slice.call(form.elements).forEach(function(control) {
if (
control.name &&
!control.disabled &&
['file', 'reset', 'submit', 'button'].indexOf(control.type) === -1
)
if (control.type === 'select-multiple')
Array.prototype.slice.call(control.options).forEach(function(option) {
if (option.selected)
result.push(encodeURIComponent(control.name) + '=' + encodeURIComponent(option.value));
});
else if (
['checkbox', 'radio'].indexOf(control.type) === -1 ||
control.checked
) result.push(encodeURIComponent(control.name) + '=' + encodeURIComponent(control.value));
});
return result.join('&').replace(/%20/g, '+');
}
// use like this:
// <form action="/search" onSubmit={handleOnSubmitNav(router, "/search")}>
const handleOnSubmitNav = (router, action, replaceState=false) => {
const linkLocation = normalizeLocation(action);
return (e) => {
if (hasModifier(e) || isNotLeftClick(e)) { return; }
if (e.defaultPrevented) { return; }
const formQuery = serializeForm(e.currentTarget);
const locationDescriptor = {
pathname: linkLocation.pathname,
search: (linkLocation.search ? (linkLocation.search + "&") : "?") + formQuery
};
const location = defaultCreateLocation(locationDescriptor);
if (router) {
router.store.dispatch({
type: replaceState ? PUSH : PUSH,
payload: location
});
e.preventDefault();
}
};
};
export {
handleClickNav,
handleOnSubmitNav,
normalizeHref,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment