pjax-base.js revision 5e276dd3a17da2c3a390c2c42830d08955670636
168N/AYUI.add('pjax-base', function(Y) {
769N/A
769N/Avar win = Y.config.win,
168N/A originalRoot = getRoot(),
168N/A
168N/A CLASS_PJAX = Y.ClassNameManager.getClassName('pjax'),
168N/A EVT_NAVIGATE = 'navigate';
168N/A
168N/Afunction getRoot() {
168N/A var segments = (win && win.location.pathname.split('/')) || [];
168N/A segments.pop();
168N/A return segments.join('/');
168N/A}
168N/A
168N/A// PjaxBase is a mixin for Controller.
292N/Afunction PjaxBase() {}
168N/A
168N/APjaxBase.prototype = {
168N/A // -- Properties -----------------------------------------------------------
168N/A _resolved: {},
168N/A _regexUrl: /^((?:([^:]+):(?:\/\/)?|\/\/)[^\/]*)?([^?#]*)(.*)$/i,
168N/A
168N/A // -- Lifecycle Methods ----------------------------------------------------
168N/A initializer: function () {
168N/A this._pjaxRoot = originalRoot;
168N/A this.publish(EVT_NAVIGATE, {defaultFn: this._defNavigateFn});
168N/A this._pjaxBindUI();
168N/A },
168N/A
168N/A destructor: function () {
168N/A this._pjaxEvents && this._pjaxEvents.detach();
168N/A },
670N/A
769N/A // -- Public Prototype Methods ---------------------------------------------
168N/A navigate: function (url, options) {
670N/A options || (options = {});
526N/A options.url = url;
526N/A
526N/A this.fire(EVT_NAVIGATE, options);
526N/A },
670N/A
670N/A // -- Protected Prototype Methods ------------------------------------------
526N/A _getRoot: getRoot,
670N/A
526N/A _normalizePath: function (path) {
526N/A var dots = '..',
526N/A slash = '/',
168N/A i, len, normalized, parts, part, stack;
168N/A
670N/A if (!path) {
670N/A return path;
670N/A }
670N/A
168N/A parts = path.split(slash);
168N/A stack = [];
168N/A
168N/A for (i = 0, len = parts.length; i < len; ++i) {
613N/A part = parts[i];
613N/A
613N/A if (part === dots) {
168N/A stack.pop();
613N/A } else if (part) {
613N/A stack.push(part);
613N/A }
168N/A }
168N/A
168N/A normalized = stack.join(slash);
168N/A
168N/A // Append a slash if necessary.
168N/A if (path.charAt(path.length - 1) === slash) {
670N/A normalized += slash;
670N/A }
670N/A
670N/A return normalized;
670N/A },
670N/A
670N/A _pjaxBindUI: function () {
670N/A if (this.html5) {
670N/A this._pjaxEvents = Y.one('body').delegate('click',
670N/A this._onLinkClick, this.get('linkSelector'), this);
670N/A }
670N/A },
670N/A
670N/A _resolvePath: function (path) {
670N/A var root = this._pjaxRoot;
670N/A
670N/A if (!path) {
670N/A return root;
670N/A }
670N/A
670N/A // Path is host relative.
670N/A if (path.charAt(0) === '/') {
670N/A return path;
670N/A }
670N/A
670N/A return this._normalizePath(root + '/' + path);
670N/A },
670N/A
670N/A _resolveUrl: function (url) {
670N/A var self = this,
670N/A resolved = self._resolved,
670N/A resolvedUrl = resolved[url];
670N/A
670N/A if (resolvedUrl) {
670N/A return resolvedUrl;
670N/A }
670N/A
670N/A function resolve(match, prefix, scheme, path, suffix) {
670N/A if (scheme && scheme.toLowerCase().indexOf('http') !== 0) {
670N/A return match;
168N/A }
670N/A
670N/A return (prefix || '') + self._resolvePath(path) + (suffix || '');
670N/A }
670N/A
670N/A // Cache resolved URL.
670N/A resolvedUrl = resolved[url] = url.replace(self._regexUrl, resolve);
670N/A
670N/A return resolvedUrl;
670N/A },
670N/A
670N/A // -- Protected Event Handlers ---------------------------------------------
670N/A _defNavigateFn: function (e) {
168N/A this.save(this._resolveUrl(e.url));
168N/A
168N/A if (this.get('scrollToTop') && Y.config.win) {
168N/A // Scroll to the top of the page. The timeout ensures that the
168N/A // scroll happens after navigation begins, so that the current
670N/A // scroll position will be restored if the user clicks the back
670N/A // button.
670N/A setTimeout(function () {
670N/A Y.config.win.scroll(0, 0);
295N/A }, 1);
295N/A }
295N/A },
670N/A
295N/A _onLinkClick: function (e) {
295N/A var url = this._resolveUrl(e.currentTarget.get('href'));
295N/A
295N/A // Allow the native behavior on middle/right-click, or when Ctrl or
295N/A // Command are pressed.
295N/A if (e.button !== 1 || e.ctrlKey || e.metaKey) { return; }
295N/A
295N/A // Do nothing if there's no matching route for this URL.
295N/A if (!this.hasRoute(url)) { return; }
295N/A
670N/A e.preventDefault();
670N/A
670N/A this.navigate(url, {originEvent: e});
295N/A }
295N/A};
295N/A
295N/APjaxBase.ATTRS = {
295N/A
769N/A linkSelector: {
769N/A value : 'a.' + CLASS_PJAX,
295N/A writeOnce: 'initOnly'
769N/A },
670N/A
670N/A scrollToTop: {
670N/A value: true
670N/A }
670N/A};
670N/A
670N/AY.PjaxBase = PjaxBase;
670N/A
670N/A
670N/A}, '@VERSION@' ,{requires:['classnamemanager', 'controller', 'node-event-delegate']});
295N/A