Skip to content
This repository has been archived by the owner on Dec 19, 2017. It is now read-only.

Commit

Permalink
Vastly improve active-path css binding (#111)
Browse files Browse the repository at this point in the history
* Vastly improve path binding

* Nix parent class
  • Loading branch information
caseyWebb committed Oct 3, 2016
1 parent 325b7e4 commit ba4dcd1
Show file tree
Hide file tree
Showing 9 changed files with 192 additions and 125 deletions.
101 changes: 62 additions & 39 deletions dist/ko-component-router.js
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ return /******/ (function(modules) { // webpackBootstrap
_classCallCheck(this, Context);

bindingCtx.$router = this;
this.bindingCtx = bindingCtx;

var parentRouterBindingCtx = bindingCtx;
var isRoot = true;
Expand Down Expand Up @@ -2334,25 +2335,25 @@ return /******/ (function(modules) { // webpackBootstrap
};
_knockout2.default.bindingHandlers.path.utils = { resolveHref: resolveHref };

function resolveHref(ctx, path, query) {
var _getRoute = getRoute(ctx, path);
function resolveHref(bindingCtx, _path, query) {
var _parsePathBinding = parsePathBinding(bindingCtx, _path);

var _getRoute2 = _slicedToArray(_getRoute, 2);
var _parsePathBinding2 = _slicedToArray(_parsePathBinding, 2);

var router = _getRoute2[0];
var route = _getRoute2[1];
var ctx = _parsePathBinding2[0];
var path = _parsePathBinding2[1];

var querystring = query ? '?' + _qs2.default.stringify(_knockout2.default.toJS(query)) : '';

while (router.$parent) {
route = router.config.base + route;
router = router.$parent;
while (ctx.$parent) {
path = ctx.config.base + path;
ctx = ctx.$parent;
}

return router ? router.config.base + (!router.config.hashbang || router.$parent ? '' : '/#!') + route + querystring : '#';
return ctx ? ctx.config.base + (!ctx.config.hashbang || ctx.$parent ? '' : '/#!') + path + querystring : '#';
}

function applyBinding(el, bindings, ctx) {
function applyBinding(el, bindings, bindingCtx) {
var path = bindings.has('path') ? bindings.get('path') : false;
var query = bindings.has('query') ? bindings.get('query') : false;
var state = bindings.has('state') ? bindings.get('state') : false;
Expand All @@ -2370,12 +2371,12 @@ return /******/ (function(modules) { // webpackBootstrap
return true;
}

var _getRoute3 = getRoute(ctx, path);
var _parsePathBinding3 = parsePathBinding(bindingCtx, path);

var _getRoute4 = _slicedToArray(_getRoute3, 2);
var _parsePathBinding4 = _slicedToArray(_parsePathBinding3, 2);

var router = _getRoute4[0];
var route = _getRoute4[1];
var router = _parsePathBinding4[0];
var route = _parsePathBinding4[1];

var handled = router._update(route, _knockout2.default.toJS(state), true, _knockout2.default.toJS(query), true);

Expand All @@ -2391,21 +2392,14 @@ return /******/ (function(modules) { // webpackBootstrap

bindingsToApply.attr = {
href: _knockout2.default.pureComputed(function () {
return resolveHref(ctx, bindings.get('path'), query);
return resolveHref(bindingCtx, bindings.get('path'), query);
})
};

if (path) {
bindingsToApply.css = {
'active-path': _knockout2.default.pureComputed(function () {
var _getRoute5 = getRoute(ctx, path);

var _getRoute6 = _slicedToArray(_getRoute5, 2);

var router = _getRoute6[0];
var route = _getRoute6[1];

return !router.isNavigating() && router.route() !== '' && route ? router.route().matches(route) : false;
return isActivePath(bindingCtx, path);
})
};
}
Expand All @@ -2416,36 +2410,65 @@ return /******/ (function(modules) { // webpackBootstrap
});
}

function getRoute(ctx, path) {
var router = getRouter(ctx);
var route = path ? _knockout2.default.unwrap(path) : router.canonicalPath();
function isActivePath(bindingCtx, _path) {
var _parsePathBinding5 = parsePathBinding(bindingCtx, _path);

var _parsePathBinding6 = _slicedToArray(_parsePathBinding5, 2);

var ctx = _parsePathBinding6[0];
var path = _parsePathBinding6[1];


if (localPathMatches(ctx, path)) {
while (ctx.$child) {
ctx = ctx.$child;
path = path.replace(ctx.config.base, '');
if (!localPathMatches(ctx, path)) {
return false;
}
}
return true;
} else if (ctx.$parent) {
return isActivePath(ctx.bindingCtx.$parentContext, path);
} else {
return false;
}
}

function parsePathBinding(bindingCtx, _path) {
var ctx = getRouter(bindingCtx);
var path = _path ? _knockout2.default.unwrap(_path) : ctx.canonicalPath();

if (route.indexOf('//') === 0) {
route = route.replace('//', '/');
if (path.indexOf('//') === 0) {
path = path.replace('//', '/');

while (router.$parent) {
router = router.$parent;
while (ctx.$parent) {
ctx = ctx.$parent;
}
} else {
while (route && route.match(/\/?\.\./i) && router.$parent) {
router = router.$parent;
route = route.replace(/\/?\.\./i, '');
while (path && path.match(/\/?\.\./i) && ctx.$parent) {
ctx = ctx.$parent;
path = path.replace(/\/?\.\./i, '');
}
}

return [router, route];
return [ctx, path];
}

function getRouter(ctx) {
while (!(0, _utils.isUndefined)(ctx)) {
if (!(0, _utils.isUndefined)(ctx.$router)) {
return ctx.$router;
function getRouter(bindingCtx) {
while (!(0, _utils.isUndefined)(bindingCtx)) {
if (!(0, _utils.isUndefined)(bindingCtx.$router)) {
return bindingCtx.$router;
}

ctx = ctx.$parentContext;
bindingCtx = bindingCtx.$parentContext;
}
}

function localPathMatches(ctx, path) {
return ctx.pathname() === '/' + path.split('/')[1];
}

function which(e) {
e = e || window.event;
return null === e.which ? e.button : e.which;
Expand Down
4 changes: 2 additions & 2 deletions dist/ko-component-router.min.js

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions example/dist/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion example/dist/bundle.js.map

Large diffs are not rendered by default.

100 changes: 61 additions & 39 deletions lib/binding.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,25 @@ _knockout2.default.bindingHandlers.query = {
};
_knockout2.default.bindingHandlers.path.utils = { resolveHref: resolveHref };

function resolveHref(ctx, path, query) {
var _getRoute = getRoute(ctx, path);
function resolveHref(bindingCtx, _path, query) {
var _parsePathBinding = parsePathBinding(bindingCtx, _path);

var _getRoute2 = _slicedToArray(_getRoute, 2);
var _parsePathBinding2 = _slicedToArray(_parsePathBinding, 2);

var router = _getRoute2[0];
var route = _getRoute2[1];
var ctx = _parsePathBinding2[0];
var path = _parsePathBinding2[1];

var querystring = query ? '?' + _qs2.default.stringify(_knockout2.default.toJS(query)) : '';

while (router.$parent) {
route = router.config.base + route;
router = router.$parent;
while (ctx.$parent) {
path = ctx.config.base + path;
ctx = ctx.$parent;
}

return router ? router.config.base + (!router.config.hashbang || router.$parent ? '' : '/#!') + route + querystring : '#';
return ctx ? ctx.config.base + (!ctx.config.hashbang || ctx.$parent ? '' : '/#!') + path + querystring : '#';
}

function applyBinding(el, bindings, ctx) {
function applyBinding(el, bindings, bindingCtx) {
var path = bindings.has('path') ? bindings.get('path') : false;
var query = bindings.has('query') ? bindings.get('query') : false;
var state = bindings.has('state') ? bindings.get('state') : false;
Expand All @@ -73,12 +73,12 @@ function applyBinding(el, bindings, ctx) {
return true;
}

var _getRoute3 = getRoute(ctx, path);
var _parsePathBinding3 = parsePathBinding(bindingCtx, path);

var _getRoute4 = _slicedToArray(_getRoute3, 2);
var _parsePathBinding4 = _slicedToArray(_parsePathBinding3, 2);

var router = _getRoute4[0];
var route = _getRoute4[1];
var router = _parsePathBinding4[0];
var route = _parsePathBinding4[1];

var handled = router._update(route, _knockout2.default.toJS(state), true, _knockout2.default.toJS(query), true);

Expand All @@ -94,21 +94,14 @@ function applyBinding(el, bindings, ctx) {

bindingsToApply.attr = {
href: _knockout2.default.pureComputed(function () {
return resolveHref(ctx, bindings.get('path'), query);
return resolveHref(bindingCtx, bindings.get('path'), query);
})
};

if (path) {
bindingsToApply.css = {
'active-path': _knockout2.default.pureComputed(function () {
var _getRoute5 = getRoute(ctx, path);

var _getRoute6 = _slicedToArray(_getRoute5, 2);

var router = _getRoute6[0];
var route = _getRoute6[1];

return !router.isNavigating() && router.route() !== '' && route ? router.route().matches(route) : false;
return isActivePath(bindingCtx, path);
})
};
}
Expand All @@ -119,36 +112,65 @@ function applyBinding(el, bindings, ctx) {
});
}

function getRoute(ctx, path) {
var router = getRouter(ctx);
var route = path ? _knockout2.default.unwrap(path) : router.canonicalPath();
function isActivePath(bindingCtx, _path) {
var _parsePathBinding5 = parsePathBinding(bindingCtx, _path);

var _parsePathBinding6 = _slicedToArray(_parsePathBinding5, 2);

var ctx = _parsePathBinding6[0];
var path = _parsePathBinding6[1];


if (localPathMatches(ctx, path)) {
while (ctx.$child) {
ctx = ctx.$child;
path = path.replace(ctx.config.base, '');
if (!localPathMatches(ctx, path)) {
return false;
}
}
return true;
} else if (ctx.$parent) {
return isActivePath(ctx.bindingCtx.$parentContext, path);
} else {
return false;
}
}

function parsePathBinding(bindingCtx, _path) {
var ctx = getRouter(bindingCtx);
var path = _path ? _knockout2.default.unwrap(_path) : ctx.canonicalPath();

if (route.indexOf('//') === 0) {
route = route.replace('//', '/');
if (path.indexOf('//') === 0) {
path = path.replace('//', '/');

while (router.$parent) {
router = router.$parent;
while (ctx.$parent) {
ctx = ctx.$parent;
}
} else {
while (route && route.match(/\/?\.\./i) && router.$parent) {
router = router.$parent;
route = route.replace(/\/?\.\./i, '');
while (path && path.match(/\/?\.\./i) && ctx.$parent) {
ctx = ctx.$parent;
path = path.replace(/\/?\.\./i, '');
}
}

return [router, route];
return [ctx, path];
}

function getRouter(ctx) {
while (!(0, _utils.isUndefined)(ctx)) {
if (!(0, _utils.isUndefined)(ctx.$router)) {
return ctx.$router;
function getRouter(bindingCtx) {
while (!(0, _utils.isUndefined)(bindingCtx)) {
if (!(0, _utils.isUndefined)(bindingCtx.$router)) {
return bindingCtx.$router;
}

ctx = ctx.$parentContext;
bindingCtx = bindingCtx.$parentContext;
}
}

function localPathMatches(ctx, path) {
return ctx.pathname() === '/' + path.split('/')[1];
}

function which(e) {
e = e || window.event;
return null === e.which ? e.button : e.which;
Expand Down
1 change: 1 addition & 0 deletions lib/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var Context = function () {
_classCallCheck(this, Context);

bindingCtx.$router = this;
this.bindingCtx = bindingCtx;

var parentRouterBindingCtx = bindingCtx;
var isRoot = true;
Expand Down
Loading

0 comments on commit ba4dcd1

Please sign in to comment.