Skip to content
This repository has been archived by the owner on Jul 15, 2019. It is now read-only.

Commit

Permalink
Merge e082e5f into 687b169
Browse files Browse the repository at this point in the history
  • Loading branch information
kaesonho committed Jul 23, 2015
2 parents 687b169 + e082e5f commit 9782dc3
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 140 deletions.
127 changes: 2 additions & 125 deletions lib/NavLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,130 +6,7 @@
'use strict';

var React = require('react');
var navigateAction = require('./navigateAction');
var debug = require('debug')('NavLink');
var createNavLink = require('./createNavLink');
var objectAssign = require('object-assign');
var handleRoute = require('./handleRoute');
var Immutable = require('immutable');

function isLeftClickEvent (e) {
return e.button === 0;
}

function isModifiedEvent (e) {
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
}

var NavLink = React.createClass({
displayName: 'NavLink',
contextTypes: {
executeAction: React.PropTypes.func
},
propTypes: {
currentRoute: React.PropTypes.object,
currentNavigate: React.PropTypes.object,
href: React.PropTypes.string,
isActive: React.PropTypes.func,
makePath: React.PropTypes.func,
stopPropagation: React.PropTypes.bool,
routeName: React.PropTypes.string,
navParams: React.PropTypes.object,
followLink: React.PropTypes.bool,
preserveScrollPosition: React.PropTypes.bool,
replaceState: React.PropTypes.bool
},
_getHrefFromProps: function (props) {
var href = props.href;
var routeName = props.routeName;
if (!href && routeName) {
href = this.props.makePath(routeName, props.navParams);
}
if (!href) {
throw new Error('NavLink created without href or unresolvable routeName \'' + routeName + '\'');
}
return href;
},
dispatchNavAction: function (e) {
var navType = this.props.replaceState ? 'replacestate' : 'click';
debug('dispatchNavAction: action=NAVIGATE', this.props.href, this.props.followLink, this.props.navParams);

if (this.props.followLink) {
return;
}

if (isModifiedEvent(e) || !isLeftClickEvent(e)) {
// this is a click with a modifier or not a left-click
// let browser handle it natively
return;
}

var href = this._getHrefFromProps(this.props);

if (href[0] === '#') {
// this is a hash link url for page's internal links.
// Do not trigger navigate action. Let browser handle it natively.
return;
}

if (href[0] !== '/') {
// this is not a relative url. check for external urls.
var location = window.location;
var origin = location.origin || (location.protocol + '//' + location.host);

if (href.indexOf(origin) !== 0) {
// this is an external url, do not trigger navigate action.
// let browser handle it natively.
return;
}

href = href.substring(origin.length) || '/';
}

e.preventDefault();
if (this.props.stopPropagation) {
e.stopPropagation();
}

var context = this.props.context || this.context;
var onBeforeUnloadText = typeof window.onbeforeunload === 'function' ? window.onbeforeunload() : '';
var confirmResult = onBeforeUnloadText ? window.confirm(onBeforeUnloadText) : true;

if (confirmResult) {
// Removes the window.onbeforeunload method so that the next page will not be affected
window.onbeforeunload = null;

context.executeAction(navigateAction, {
type: navType,
url: href,
preserveScrollPosition: this.props.preserveScrollPosition,
params: this.props.navParams
});
}
},
render: function() {
var href = this._getHrefFromProps(this.props);
var isActive = this.props.isActive(href);

var className = this.props.className;
var style = this.props.style;
if (isActive) {
className = className ? (className + ' ') : '';
className += this.props.activeClass || 'active';
style = objectAssign({}, style, this.props.activeStyle);
}

return React.createElement(
'a',
objectAssign({}, {
onClick: this.dispatchNavAction
}, this.props, {
href: href,
className: className,
style: style
}),
this.props.children
);
}
});

module.exports = handleRoute(NavLink);
module.exports = createNavLink();
138 changes: 138 additions & 0 deletions lib/createNavLink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/**
* Copyright 2015, Yahoo! Inc.
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
/*global window */
'use strict';
var React = require('react');
var RouteStore = require('./RouteStore');
var debug = require('debug')('NavLink');
var navigateAction = require('./navigateAction');
var objectAssign = require('object-assign');

function isLeftClickEvent (e) {
return e.button === 0;
}

function isModifiedEvent (e) {
return !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
}

/**
* create NavLink with custom options
* @param {Object} options to overwrite the default attributes to create NavLink
* @returns {React.Component} NavLink
*/
module.exports = function createNavLink (options) {
var NavLink = React.createClass(objectAssign({}, {
displayName: 'NavLink',
contextTypes: {
executeAction: React.PropTypes.func,
getStore: React.PropTypes.func
},
propTypes: {
currentRoute: React.PropTypes.object,
currentNavigate: React.PropTypes.object,
href: React.PropTypes.string,
stopPropagation: React.PropTypes.bool,
routeName: React.PropTypes.string,
navParams: React.PropTypes.object,
followLink: React.PropTypes.bool,
preserveScrollPosition: React.PropTypes.bool,
replaceState: React.PropTypes.bool
},
dispatchNavAction: function (e) {
var navType = this.props.replaceState ? 'replacestate' : 'click';
debug('dispatchNavAction: action=NAVIGATE', this.props.href, this.props.followLink, this.props.navParams);

if (this.props.followLink) {
return;
}

if (isModifiedEvent(e) || !isLeftClickEvent(e)) {
// this is a click with a modifier or not a left-click
// let browser handle it natively
return;
}

var href = this._getHrefFromProps();

if (href[0] === '#') {
// this is a hash link url for page's internal links.
// Do not trigger navigate action. Let browser handle it natively.
return;
}

if (href[0] !== '/') {
// this is not a relative url. check for external urls.
var location = window.location;
var origin = location.origin || (location.protocol + '//' + location.host);

if (href.indexOf(origin) !== 0) {
// this is an external url, do not trigger navigate action.
// let browser handle it natively.
return;
}

href = href.substring(origin.length) || '/';
}

e.preventDefault();
if (this.props.stopPropagation) {
e.stopPropagation();
}

var context = this.props.context || this.context;
var onBeforeUnloadText = typeof window.onbeforeunload === 'function' ? window.onbeforeunload() : '';
var confirmResult = onBeforeUnloadText ? window.confirm(onBeforeUnloadText) : true;

if (confirmResult) {
// Removes the window.onbeforeunload method so that the next page will not be affected
window.onbeforeunload = null;

context.executeAction(navigateAction, {
type: navType,
url: href,
preserveScrollPosition: this.props.preserveScrollPosition,
params: this.props.navParams
});
}
},
_getHrefFromProps: function () {
var href = this.props.href;
var routeName = this.props.routeName;
var routeStore = this.context.getStore(RouteStore);
if (!href && routeName) {
href = routeStore.makePath(routeName, this.props.navParams);
}
if (!href) {
throw new Error('NavLink created without href or unresolvable routeName \'' + routeName + '\'');
}
return href;
},
render: function () {
var href = this._getHrefFromProps();
var routeStore = this.context.getStore(RouteStore);
var isActive = routeStore.isActive(href);
var className = this.props.className;
var style = this.props.style;
if (isActive) {
className = className ? (className + ' ') : '';
className += this.props.activeClass || 'active';
style = objectAssign({}, style, this.props.activeStyle);
}
return React.createElement(
'a',
objectAssign({}, {
onClick: this.dispatchNavAction
}, this.props, {
href: href,
className: className,
style: style
}),
this.props.children
);
}
}, options));
return NavLink;
};
15 changes: 0 additions & 15 deletions tests/unit/lib/NavLink-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -397,19 +397,4 @@ describe('NavLink', function () {
}, 50);
});
});

describe('componentWillUnmount', function () {
it('should update active state', function () {
var div = document.createElement('div');
React.render(
<MockAppComponent context={mockContext}>
<NavLink href='/foo' />
</MockAppComponent>
, div);
var routeStore = mockContext.getStore('RouteStore');
expect(routeStore.listeners('change').length).to.equal(2);
React.unmountComponentAtNode(div);
expect(routeStore.listeners('change').length).to.equal(0);
});
});
});

0 comments on commit 9782dc3

Please sign in to comment.