From disqus.com, 2 Months ago, written in JavaScript.
This paste is a reply to main.js from disqus.com
- go back
Embed
Viewing differences between main.js and Router.js
define('home/main',[  define('Router',[  // eslint-disable-line requirejs/amd-function-arity
    'home/config',
    'home/utils/layoutUtils',
    'Router',
'underscore',
    'jquery',
    'modernizr',
    'backbone',
    'backbone-marionette',

    'home/templates/preload',

    'home/views/MainLayout',
    'home/views/HomepageView',
    'home/views/ActivityFeedView',
    'home/views/NotificationsView',
    'home/views/NotificationsLoggedOutView',
    'home/views/ForumProfileView',
    'home/views/ProfileView',
    'home/views/DiscussionCreateView',
    'home/views/DiscussionPageView',
    'home/views/WelcomeView',
    'home/views/ChannelProfileView',
    'home/views/SettingsLayout',
    'home/views/ChannelsView',
    'home/views/ExploreView',
    'home/views/OnboardingView',
    'home/viewmodels/DiscussionCreateViewModel',
    'home/viewmodels/ChannelsViewModel',
    'home/viewmodels/DiscussionViewModel',

    'home/collections/common/ExtensibleCollection',
    'home/collections/ChannelCollection',

    'home/models/Session',
    'core/UniqueModel',
    'home/models/UserProfile',
    'home/models/Thread',
    'home/models/Forum',
    'home/models/Channel',
    'home/models/ChannelProfile',
    'home/models/ForumProfile',
    'home/models/HomepageProfile',
    'home/models/ExploreViewModel',

    'home/utils/navigationUtils',
    'home/utils/trackingUtils',
    'core/utils/auth',
    'core/utils/url/parseQueryString',
    'core/api',
    'core/engagement/page',
    'core/strings',
    'core/switches',
    'remote/config',
    'core/config/urls',

    'jquery',\r\n    'backbone',\r\n\r\n    'home/mixins/asEmbedApp',\r\n    'home/utils/sidebarUtils',\r\n    'home/utils/navigationUtils',\r\n\r\n    // imported for side effects
    'bootstrap/dropdown',
    'bootstrap/tooltip',
    'bootstrap/modal',
    'bootstrap/collapse',
    'jquery.trunk8',
'home/backbone.overrides',
    'home/overrides/marionette.overrides',

    'disqus.sdk',  // needed to load the embed on Discussion pages
], function (
    config,
    layoutUtils,

    Router,
_,
    $,
    Modernizr,
    Backbone,
    Marionette,

    preloadTemplate,

    MainLayout,
    HomepageView,
    AnonHomepageView,
    NotificationsView,
    NotificationsLoggedOutView,
    ForumProfileView,
    ProfileView,
    DiscussionCreateView,
    DiscussionPageView,
    WelcomeView,
    ChannelProfileView,
    SettingsLayout,
    ChannelsView,
    ExploreView,
    OnboardingView,
    DiscussionCreateViewModel,
    ChannelsViewModel,
    DiscussionViewModel,

    ExtensibleCollection,
    ChannelCollection,

    Session,
    urls,

    $,
    Backbone,

    asEmbedApp,
    sidebarUtils,
    navigationUtils
UniqueModel,
    UserProfile,
    Thread,
    Forum,
    Channel,
    ChannelProfile,
    ForumProfile,
    HomepageProfile,
    ExploreViewModel,

    NavigationUtils,
    TrackingUtils,
    auth,
    parseQueryString,
    api,
    pageEngagement,
    strings,
    switches,
    remoteConfig,
    urls
) {
    'use strict';

    var initFixtures localStorageSupported = Modernizr.localstorage;

    /* eslint-disable no-unused-expressions */
    // This line causes the grunt task to add the Modernizr Touch test
    // which in turn causes Modernizr to add a css class touch/no-touch
    // to the <html> tag
    Modernizr.touch;

    // Add flexbox/no-flexbox detection for IE9
    Modernizr.flexbox;
    /* eslint-disable no-unused-expressions */

    // TODO: move this to jesterUtils
    var logStatsD 
= function (callback) (eventName) {
        if (window.IS_DEV)
            require(['fixtures/fixtures'], callback);
        else
            callback();
new window.Image().src = urls.jester + '/stat.gif?event=' + eventName;
    };

    /**
     * Backwards compatibility layer 
var gettext = strings.get;

    var Router = Backbone.Router.extend({

        name: 'home',

        routes: {
            'home/discuss/:forum(/)': 'startDiscussion',
            'home/edit/:forum/:thread(/)': 'editDiscussion',
            'home/search(/)': 'search',
            'home/user(s)(/:username)(/:feed)(/)': 'profile',
            'home/user(s)/(:username)(/:feed)(/:subfeed)(/)': 'profile',
            'by/:username(/:feed)(/)': 'profile',
            'by/:username(/:feed)(/:subfeed)(/)': 'profile',
            'home/inbox(/:feed)(/)': 'inbox',
            'home/preload(/)': 'preload',
            'home/account(/)': 'account',
            'home/notifications(/)': 'notifications',
            'home/topic(s)/:topicId(/)': 'topics',
            'home/forum(s)/:forumId(/:feed)(/)': 'forums',
            'home/discussion(s)/:forum/:thread(/:activeTab)(/:permalink)(/)': 'discussion',
            'home/ndiscussion(s)/:forum/:thread(/:activeTab)(/:permalink)(/)': 'nativeDiscussion',
            'home/follow/channel(s)/:channelId(/)': 'followChannel',

            'home/channel(s)(/)': 'channelsPage',
            'home/channel(s)/:channelId(/:feed)(/)': 'channels',
            'home/channel(s)/:channelId/topics/:topic(/)': 'channelTopics',
            'home/channel(s)/:channelId/discussion(s)/:forumId/:thread(/:activeTab)(/:permalink)(/)': 'channelDiscussion',
            'home/channel(s)/:channelId/ndiscussion(s)/:forumId/:thread(/:activeTab)(/:permalink)(/)': 'nativeChannelDiscussion',
            'home/settings(/:section)/': 'settings',

            // TODO: remove this once nowhere in disqus-web is directing users 
to support old #-based routes
     
/home/discover
            // (specifically after email verification, possibly other places)
            // Note: also remove 'discover' route handler in trackingUtils zone names
            'home/discover(/)': 'channelsPage',

            'home/explore(/)': 'explore',
            'home/explore/:activeTab(/)': 'explore',
            'home/explore/channels/:channelId(/:activeTab)(/)': 'exploreChannel',
            'home/explore/discussions/:channelId(/)': 'exploreDiscussions',

            // This must remain as the last item so that it doesn't match this router when
            // it should match something more specific (ex: home/inbox/)
            'home(/:feed)(/)': 'home',
        },

        initialize: function (options) {
            this.CDN_ROOT = options.CDN_ROOT;
            this.feeds = {};
            this.listenTo(this, 'route', this.handleRouteChange);

            this.listenTo(this, 'route', this.logRouteChange);

            this.messages = [];

            this.onboardingWithoutChannels = switches.isFeatureActive('onboarding_without_channels');
        },

        /*
         
e.Start the application by running through a
         * sequence of initialization steps.
         */
        bootstrap: function () {
            this.initSession();
            this.initTracking();
            this.initPageEngagementTracking();
            this.initLinkHandling();
            this.initMainLayout();
        },

        initTracking: function () {
            TrackingUtils.init();
            TrackingUtils.trackVisit();
        },

        initLinkHandling: function () {
            $('body').on('click', 'a[href]', _.bind(NavigationUtils.handleLinkClicks, NavigationUtils));
        },

        initSession: function () {
            var session = this.session = Session.get();
            session.load();
            session.loadPromise().then(_.bind(function () {
                if (window.Raven) {
                    window.Raven.setUser({
                        id: session.user.get('id'),
                        username: session.user.get('username'),
                    });
                }

                this.loadModeratedForums();
            }, this));

            session.loadPromise().fail(function () {
                var provider = session.provider();
                // If we know the session provider and we are rejecting the
                // session authentication anyway, then there was something wrong
                // with our disqusauth cookie (or the user is an "SSO" publisher account).
                if (provider)  // don't log all the random provider domains, just do 'remote' instead
                    logStatsD('home.session.rejected.' + (provider === 'disqus' ? 'disqus' : 'remote'));
            });

            this.initUserProfile();

            return session;
        },

        initMainLayout: function () {
            this.layout = new MainLayout({
                container: 'body',
                session: this.session,
                app: this,
            });
            // We do not render here because rendering kicks off the creation of
            // certain subviews (e.
g., /home/#account
     */
    function transitionUrl() {
        var location = window.location;

        // If we are at the /home/ prefix and we happen to also have a
        // hash 
NavView) that matches one of our routes, then we should try to
        // direct the user to that route instead of just going to /home/.
        // NOTE: this hash routing feature is only to support a few legacy
        //       urls like disqus.com/home/#account.
        if (location.hash.length > 1 && (location.pathname === '/home' || location.pathname === '/home/')) {
            // Construct a new location object that contains the hash's route
            // as well as search params, etc.
            var loc = {
                pathname: '/home/' + location.hash.slice(1).replace(/^\//, ''),
                search: location.search,
                hash: '',
                host: location.host,
            };

            if (navigationUtils.matchesRoute(loc))
                return navigationUtils.navigate(loc, true);
        }

        return 
rely on Backbone.history.loadUrl();
    }

    
start
            // having been called, which does not occur until after app.bootstrap.
            // And we cannot init the MainLayout AFTER History.start because History.start
            // will trigger a route that relies on MainLayout existing. And we cannot
            // hook into the route event because that is fired after the route handler
            // has been executed.
        },

        /*
         * Returns the view currently showing in the main content area of the page.
         * Useful for anything external to the content view (ex: NavView) to get
         * the current view/model being shown.
         */
        getCurrentView: function () {
            
return {
        _init: 
this.layout.content.currentView;
        },

        initPageEngagementTracking: function () {
            pageEngagement.start();
        },

        /*
         * When the asEmbedApp mixin is applied, loadModeratedForums is only called
         * when the 'showPath' message is received via the FrameBus.
         */
        loadModeratedForums: function () {
            this.session.loadModeratedForums();
        },

        logRouteChange: function (route) {
            // Log the page view to 'events.*.route.<page path>'
            logStatsD(this.name + '.route.' + route);
        },

        /*
         * When the asEmbedApp mixin is applied, initUserProfile is only called when
         * the 'showPath' message is received via the FrameBus.
         */
        initUserProfile: function () {
            var username = Session.fromCookie().username;

            if (username) {
                // It appears the user is logged in. Fetch all the necessary user details
                // asynchronously using the username from the auth cookie.
                // (If the user turns out to be not logged in, or session expired, it'll be
                // handled on api response)
                this.session.initUserProfile(username);
            } else {
                // If we can't get the username from the cookie, wait until users/details
                // returns and then fetch the rest of the user details using the fetched username
                this.session.once('change:id', function (user) {
                    this.session.initUserProfile(user.get('username'));
                }, this);
            }
        },

        /*
         * Inherits + overrides parent .execute method
         * Handle pre-view setup and post-view cleanup before executing a route handler.
         */
        execute: function () {
            // Before showing a new view remove the logged-in requirement handling that may have been
            // added for the previous view.
            api.off('error', NavigationUtils.navigateToLoginOnAuthFail);

            TrackingUtils.pageChanged();

            Backbone.Router.prototype.execute.apply(this, arguments);
        },

        ensureAuthenticated: function (callback) {

            // Reset the api 'error' handler so we don't bind this
            // more than necessary.
            api.off('error', NavigationUtils.navigateToLoginOnAuthFail);

            if (Session.isKnownToBeLoggedOut())
                return NavigationUtils.navigateToLogin();

            // If we expect the user to be logged in, but we make
            // an API call that returns an error, we should direct the
            // user to the login page.
            api.on('error', NavigationUtils.navigateToLoginOnAuthFail);

            // Ensure the session is fetched. Once it is, call the
            // callback. If fetch fails, prompt user to login
            this.session.loadPromise().then(
                _.bind(callback, this, _.tail(arguments)),
                NavigationUtils.navigateToLogin
            );
        },

        navigateToLandingPage: 
function (options) {
            var app = new Router(options);

            // Start
            app.bootstrap();

            // overwrite tooltip support so 
return NavigationUtils.navigate('/home/', options);
        },

        /*
         * Ensures that logged in users are redirected to onboarding step 1 if
         * 
they don't show
            
have not completed it yet. Logged out users are not affected.
         */
        ensureOnboardingComplete: function (callback) {
            // TODO: @taylangocmen once channels is removed kill this onboarding flow
            
if (layoutUtils.isNarrowLayout())
                $.fn.tooltip = $.noop;

            window.DISQUS = window.DISQUS 
(this.onboardingWithoutChannels || {};
            window.DISQUS.home = {
                app: app,
            };

            // Wait for fixtures to initialize (for dev) before beginning navigation
            initFixtures(function 
Session.isKnownToBeLoggedOut())
                return callback.apply(this);

            this.session.loadPromise().always(_.bind(function 
() {
                Backbone.history.start({
                    pushState: true,
                    hashChange: false,
                    root: config.appRoot,
                    
if (this.session.isLoggedIn() && this.session.user.shouldHomeOnboard())
                    // Defer this so that the current route event is triggered before navigating to the 1st step of
                    // onboarding. Not deferring it will result in route events being triggered in the wrong order.
                    _.defer(this.navigateToOnboarding);
                else
                    callback.apply(this);
            }, this));
        },

        navigateToOnboarding: function () {
            var welcomeRoute = 'home/explore/';
            var params = parseQueryString();
            var toKeep = {};

            // Retain certain params for use later.
            // Only retain them if given truthy values, so that checks later
            // for these params can skip value check and only check existence.
            if (params.email_verified)
                toKeep.email_verified = params.email_verified;

            if (params.forum_id)
                toKeep.forum_id = params.forum_id;

            if (_.size(toKeep))
                welcomeRoute += '?' + $.param(toKeep);

            NavigationUtils.navigate(welcomeRoute, { trigger: true, replace: true });
        },

        /*
         * Verifies the forum with the given id has a channel and that
         * this user can create on that channel.
         */
        ensureCanCreateOnChannel: function (callback, forumId) {
            var forum = new UniqueModel(Forum, {
                id: forumId,
            });

            // If forum hasn't been fetched yet, wait until fetching is complete
            // and then re-call this function
            if (forum.shouldFetch()) {
                forum.fetch();
                this.listenToOnce(forum, 'sync', _.bind.apply(_, [this.ensureCanCreateOnChannel, this].concat(_.toArray(arguments))));
                return;
            }

            // If the forum is not the primary forum for a channel, or if the
            // current user does not have create permissions for the channel,
            // redirect to an error page.
            if ((!forum.channel && forumId !== 'gabalafou-test') ||
                !forum.channel.userCanCreate(this.session.user))

                // TODO: this should redirect to a page with a message like:
                // "You do not have permission to view this page"
                return this.notFound();

            // The forum has a channel. Call the callback.
            callback.apply(this, _.tail(arguments));
        },

        /**
         * Listens for a tabbed view in case it throws a badTab event. If that occurs,
         * rewrites the url to the given route silently. It's expected that the tabbed
         * view will handle the event gracefully.
         *
         * @param  {tabbedView} tabbedView - A view instance that triggers a badTab event
         *                                   in the case that an invalid tab is navigated
         *                                   to, as TabbedView does.
         * @param  {string} redirectRoute - The route to rewrite if the tab is not supported
         */
        ensureTab: function (tabbedView, redirectRoute) {
            tabbedView.listenTo(tabbedView, 'badTab', function () {
                NavigationUtils.navigate(redirectRoute, { 
silent: true,
                });

                // If we don't have a matching route, call notFound
                if (!transitionUrl())
                    app.notFound();
true, replace: true });
            });
        },

        init: preventBlacklisted: function (options) {
            urls.cdn = if (_.contains(remoteConfig.timelines.BLACKLISTED_FORUMS, options.CDN_ROOT;
forum))
                window.top.location = 'https://help.disqus.com/customer/portal/articles/1689402-redirected-from-home';
        },

        preload: function () {
            this.preloadView = new (Marionette.ItemView.extend({ template: preloadTemplate }))();

            this.layout.showView(this.preloadView);
        },

        /*
         * Append a trailing slash to the current route if it
         * doesn't have one.
         *
         * Saves the current and previous route names as properties so it can
         * be used by the NavView.
         */
        handleRouteChange: function (routeName) {
            this.setCurrentRouteName(routeName);
            NavigationUtils.coerceTrailingSlash(window.location);
        },

        setCurrentRouteName: function (routeName) {
            this._previousRouteName = this.getCurrentRouteName();
            this._currentRouteName = routeName;
        },

        getCurrentRouteName: function () {
            return this._currentRouteName;
        },

        getPreviousRouteName: function () {
            return this._previousRouteName;
        },

        onboarding: function () {
            return this.ensureAuthenticated(function () {
                this.layout.showView(new WelcomeView({ session: this.session }), { lightBackground: true });
            });
        },

        _explore: function (options) {
            this.session.loadPromise()
                .always(Function.bind.call(function () {
                    var showOnboarding = this.session.isLoggedIn() && this.session.user.shouldHomeOnboard();
                    if (showOnboarding) {
                        options.collection = new ChannelCollection([], { listName: 'explore' });
                        this.layout.showView(new OnboardingView(options));
                    } else {
                        options.model = new ExploreViewModel();
                        this.layout.showView(new ExploreView(options));
                    }
                }, this));
        },

        explore: function () {
            return this.navigateToLandingPage({ replace: true });
        },

        exploreChannel: function () {
            return this.navigateToLandingPage({ replace: true });
        },

        exploreDiscussions: function () {
            return this.navigateToLandingPage({ replace: true });
        },

        // When user goes to /user, take them to /user/<username>
        renavigateToProfile: function (user) {
            var username = user.get('username');

            // Prevent potential infinite loop
            // .profile() -> .renavigateToProfile() -> .profile() -> ...
            // (happens when username never gets set to truthy value)
            if (!username) {
                this.navigateToLandingPage({ replace: true });
                return void this.home();
            }

            NavigationUtils.navigate('/by/' + username + '/', {
                replace: true,
            });
            this.profile(username);
        },

        settings: function (section) {
            return this.ensureAuthenticated(function () {
                this.layout.showView(new SettingsLayout({
                    session: this.session,
                    activeTab: section,
                    onboardingWithoutChannels: this.onboardingWithoutChannels,
                }));
            });
        },

        channelsPage: function () {
            // remove everything but discussdisqus

            // Channels page shows channels followed/managed by the authenticated user.
            // Don't allow anon users to visit the page.
            if (Session.isKnownToBeLoggedOut()) {
                NavigationUtils.navigate('/', { replace: true });
                return this.home();
            }

            this.ensureOnboardingComplete(function () {
                var model = new UniqueModel(ChannelsViewModel, { id: 'discover-view-model' });
                model.ensureFetched();

                this.layout.showView(new ChannelsView({
                    model: model,
                    onboardingWithoutChannels: this.onboardingWithoutChannels,
                }));
            });
        },

        search: function () {
            return this.navigateToLandingPage({ replace: true });
        },

        profile: function (username, feedName, subFeedName) {
            // If we get here and we aren't on the /by/ profile path,
            // then rewrite the URL to be correct. NavigationUtils knows
            // how to rewrite the home/user URL correctly, so just pass the
            // task off to there.
            if (window.location.pathname.indexOf('home/user') !== -1)
                NavigationUtils.navigate(window.location, { replace: true, silent: true });

            if (!username) {
                return this.ensureAuthenticated(function () {
                    var session = this.session;
                    var sessionUser = session.user;

                    if (!sessionUser.get('username'))
                        return void this.listenToOnce(session, 'change:id', this.renavigateToProfile);

                    return void this.renavigateToProfile(sessionUser);
                });
            }

            var userProfile = _.find(UniqueModel.pool(UserProfile), function (userProfile) {
                return userProfile.user.get('username') === username;
            });

            if (!userProfile)
                userProfile = new UniqueModel(UserProfile, { username: username });

            userProfile.ensureFetched();

            var view = new ProfileView({
                model: userProfile,
                activeTab: feedName,
                subTab: subFeedName,
            });
            this.ensureTab(view, '/by/' + username + '/');

            this.layout.showView(view);
        },

        home: function (feedName, callback) {
            var isKnownToBeLoggedOut = Session.isKnownToBeLoggedOut();

            if (isKnownToBeLoggedOut) {
                if (parseQueryString().email_verified)
                    // Always try to login in users who have the email_verified param
                    // in their url, so we can send them through onboarding if necessary
                    NavigationUtils.navigateToLogin();
                else
                    // Logged out users who were not sent to home via an email verification
                    // link should be taken to the main homepage
                    NavigationUtils.navigateToHomepage();

                return;
            }


            this.ensureOnboardingComplete(function () {
                // If we get here and we aren't on the / home page path,
                // then rewrite the URL to be correct. NavigationUtils knows
                // how to rewrite the /home/ to /.
                if (window.location.pathname === '/home/')
                    NavigationUtils.navigate(window.location, { replace: true, silent: true });

                var model, contentView;

                if (isKnownToBeLoggedOut) {
                    var exploreChannelCollection = new ChannelCollection([], {
                        listName: 'explore',
                    });
                    exploreChannelCollection.ensureFetched();
                    contentView = new AnonHomepageView({
                        collection: exploreChannelCollection,
                    });

                    this.layout.showView(contentView, { lightBackground: true });
                } else {
                    model = new UniqueModel(HomepageProfile, { id: 'home-view-model' });
                    model.ensureFetched();
                    contentView = new HomepageView({
                        model: model,
                        activeTab: feedName,
                        onboardingWithoutChannels: this.onboardingWithoutChannels,
                    });
                    this.ensureTab(contentView, '/');

                    this.layout.showView(contentView);
                }

                // Check that callback is a function before calling.
                // This is necessary since `home` is called by the router,
                // which may pass a query string as an argument.
                if (_.isFunction(callback))
                    callback();

                this.cleanLocalStorage();
            });
        },

        // Previously the Home feed view used local storage to determine whether
        // or not to show a banner message to the user. With the removal of those
        // banner views we can clean up local storage that they were using.
        cleanLocalStorage: function () {
            if (!localStorageSupported)
                return;

            try {
                window.localStorage.removeItem('dhome_v2oo');
                window.localStorage.removeItem('whatsNewViewsRemaining');
                window.localStorage.removeItem('v2SwitchoverViewsRemaining');
            } catch (err) {
                /* pass */
            }
        },

        account: function () {
            return NavigationUtils.navigate('/home/settings/account/', { trigger: true, replace: true });
        },

        notifications: function () {
            return NavigationUtils.navigate('/home/settings/email/', { trigger: true, replace: true });
        },

        ensureAdmin: function (routeHandler, args) {
            var session = this.session;

            // If we got here but the session hasn't been
            // fetched, fetch the session first, and then try again
            if (!session.fetched) {
                return void session.fetch().then(
                    _.bind(this.ensureAdmin, this, routeHandler, args),
                    _.bind(this.notFound, this));
            }

            // Checks if session user is a global admin, and
            // checks Jones config for any additional accounts
            if (!auth.getFromCookie().staff)
                return this.notFound();

            return routeHandler.apply(this, args);
        },

        followChannel: function (channelId) {
            if (channelId === 'disqusfun')
                return this.ensureAdmin(this._followChannel, arguments);

            return this._followChannel.apply(this, arguments);
        },

        _followChannel: function (channelId) {
            // Follow action will fail and prompt user to log in, so check first, before
            // replacing the url, so that the login page will have the correct return url
            this.ensureAuthenticated(function () {
                var channel = new UniqueModel(Channel, { slug: channelId });

                if (channel.primaryForum && !channel.primaryForum.get('isFollowing')) {
                    channel.primaryForum.follow();
                } else {
                    this.listenToOnce(channel, 'changeRelated:primaryForum', function () {
                        if (!channel.primaryForum.get('isFollowing'))
                            channel.primaryForum.follow();
                    });
                }

                NavigationUtils.navigate('/home/channel/' + channelId + '/', { trigger: true, replace: true });
            });
        },

        channels: function (channelId) {
            if (channelId !== 'discussdisqus')
                return this.navigateToLandingPage({ replace: true });

            if (channelId === 'disqusfun' || channelId === 'gabalafou-test')
                return this.ensureAdmin(this._channels, arguments);

            return this._channels.apply(this, arguments);
        },

        channelTopics: function (channelId, topicName) {
            if (channelId !== 'discussdisqus')
                return this.navigateToLandingPage({ replace: true });

            return this.channels(channelId, 'topic-' + topicName);
        },

        _channels: function (channelId, feedName) {
            var channelProfile = new UniqueModel(
                ChannelProfile,
                {
                    id: channelId, // must have id for UniqueModel
                    channel: channelId,
                }
            );

            channelProfile.ensureFetched();

            var contentView = new ChannelProfileView({
                model: channelProfile,
                activeTab: feedName,
            });
            this.ensureTab(contentView, 'home/channel/' + channelId + '/');
            this.layout.showView(contentView);
        },

        _forums: function (forumId, feedName) {
            var forumProfile = new UniqueModel(
                ForumProfile,
                {
                    id: forumId,
                }
            );

            var forum = forumProfile.forum;
            var self = this;

            // If this is the primary forum for a channel, redirect to the channel page
            
if (sidebarUtils.isSidebar())
                asEmbedApp(Router.prototype, Session.prototype);

            $(function 
(forum.channel) {
                NavigationUtils.navigate('/home/channel/' + forum.channel.id + '/', { trigger: true, replace: true });
                return;
            }

            forum.fetch().then(function 
() {
                if (forum.channel)
                    
self._init(options);
_forums(forumId);
            }, this.notFound);

            forumProfile.ensureFetched();

            var view = new ForumProfileView({
                model: forumProfile,
                activeTab: feedName,
                onboardingWithoutChannels: this.onboardingWithoutChannels,
            });
        },\r\n    };\r\n            this.ensureTab(view, '/home/forum/' + forumId + '/');

            this.layout.showView(view);
        },

        forums: function (forumId) {
            this.preventBlacklisted({ forum: forumId });

            if (forumId === 'disqus-disqusfun')
                return this.ensureAdmin(this._forums, arguments);

            return this._forums.apply(this, arguments);
        },

        topics: function () {
            return this.navigateToLandingPage({ replace: true });
        },

        inbox: function (feedName) {
            var view;
            var notifications = this.session.getOrCreateNotifications();

            // Kick off fetch(es) for items needed on the notifications view.
            // Notifications and counters will have already been fetched by
            // the Nav bar
            notifications.ensureFetchedRecommendations();

            // If the user isn't logged in via Disqus or an SSO account (via embed sidebar), show the logged out
            // notifications inbox.
            if (!this.isSSOAuthenticated && Session.isKnownToBeLoggedOut()) {
                view = new NotificationsLoggedOutView({
                    model: notifications,
                    onboardingWithoutChannels: this.onboardingWithoutChannels,
                });
            } else {

                if (window.location.search.indexOf('email_verified') > -1) {
                    var message = strings.interpolate(
                        gettext('Your email\'s verified! Have a look around -- %(Disqus)s is a lot more than comments'),
                        { Disqus: 'Disqus' }
                    );
                    this.messages.push({ message: message });
                }

                view = new NotificationsView({
                    model: notifications,
                    activeTab: feedName,
                    disableMOTD: this.disableMOTD,
                    onboardingWithoutChannels: this.onboardingWithoutChannels,
                });
            }

            this.ensureTab(view, '/home/inbox/');
            this.layout.showView(view);
        },

        _showDiscussionForm: function (forumId, options) {
            var discussionForm = new DiscussionCreateView({
                session: this.session,
                model: new DiscussionCreateViewModel({}, _.extend({ forum: forumId }, options)),
            });

            this.listenTo(discussionForm, 'createThread', function () {
                var thread = discussionForm.getThread();
                // Add the recently created thread to an extensible collection so that embedly
                // requests (if any) will be made before showing the newly created discussion.
                new ExtensibleCollection().add(thread);
                NavigationUtils.navigate(thread.getDiscussionRoute(), {
                    trigger: true,
                });
            });
            this.listenTo(discussionForm, 'cancelThread', function () {
                NavigationUtils.navigate('home/' + discussionForm.getForum().getForumRoute(), {
                    trigger: true,
                });
            });

            this.layout.showView(discussionForm);
        },

        startDiscussion: function (forumId) {
            // return if a non discussdisqus channel
            if (forumId.indexOf('channel-') !== -1 && forumId !== 'channel-discussdisqus')
                return this.navigateToLandingPage({ replace: true });

            // Must be logged in and on the primary forum for a channel in order to create a discussion
            return this.ensureAuthenticated(function () {
                this.ensureCanCreateOnChannel(function () {

                    this._showDiscussionForm.apply(this, arguments);
                }, forumId);
            }, arguments);
        },

        editDiscussion: function (forumId, threadSlug) {
            // return if a non discussdisqus channel
            if (forumId.indexOf('channel-') !== -1 && forumId !== 'channel-discussdisqus')
                return this.navigateToLandingPage({ replace: true });

            var session = this.session;
            var thread = Thread.getOrCreateThread(forumId, threadSlug);
            var fetchPromises = [thread.getEditPermissions(session)];

            // If we got here but the session hasn't been
            // fetched, fetch the session first, and then try again
            if (thread.shouldFetch())
                fetchPromises.push(thread.fetch());

            return $.when.apply($, fetchPromises).then(
                _.bind(function (canEdit) {
                    if (canEdit)
                        return this._showDiscussionForm(forumId, { thread: thread });

                    return void NavigationUtils.navigate(thread.getDiscussionRoute(),
                        { trigger: true, replace: true });
                }, this),
                _.bind(this.notFound, this)
            );
        },

        discussionPage: function (forumId, threadSlug, activeTab, options) {
            options = options || {};

            var thread = Thread.getOrCreateThread(forumId, threadSlug, options.threadFetchOptions);
            var model = DiscussionViewModel.getOrCreate({}, {
                channel: options.channel,
                thread: thread,
            });

            var discussionPage = new DiscussionPageView(_.extend({
                model: model,
                session: this.session,
                activeTab: activeTab,
                app: this,
            }, options));

            this.layout.showView(discussionPage, { lightBackground: true });
        },

        _discussion: function (forumId, threadSlug, activeTab, options) {
            this.preventBlacklisted({ forum: forumId });

            if (forumId === 'disqus-disqusfun')
                return this.ensureAdmin(this.discussionPage, [forumId, threadSlug, activeTab, options]);

            return this.discussionPage(forumId, threadSlug, activeTab, options);
        },

        discussion: function (forumId, threadSlug, activeTab) {
            if (forumId.indexOf('channel-') !== -1 && forumId !== 'channel-discussdisqus')
                return this.navigateToLandingPage({ replace: true });

            return this._discussion(forumId, threadSlug, activeTab);
        },

        channelDiscussion: function (channelId, forumId, threadSlug, activeTab, options) {
            if (forumId.indexOf('channel-') !== -1 && forumId !== 'channel-discussdisqus')
                return this.navigateToLandingPage({ replace: true });

            options = options || {};

            var channel = new UniqueModel(Channel, { slug: channelId });

            // Must fetch this for network threads linked through a channel.
            // User generated threads will end up fetching this again as
            // part of the forum fetch, but network threads won't, and they
            // need channel details for this view.
            if (channel.shouldFetch())
                channel.fetch();

            return this._discussion(forumId, threadSlug, activeTab, {
                channel: channel,
                threadFetchOptions: {
                    data: {
                        related: ['author'],
                    },
                },
                noEmbed: options.noEmbed,
            });
        },

        // Native = no embed, iframe-less comments section
        nativeDiscussion: function (forumId, threadId, activeTab) {
            if (forumId.indexOf('channel-') !== -1 && forumId !== 'channel-discussdisqus')
                return this.navigateToLandingPage({ replace: true });

            return this._discussion(forumId, threadId, activeTab, {
                noEmbed: true,
            });
        },

        // Native = no embed, iframe-less comments section
        nativeChannelDiscussion: function (channelId, forumId, threadSlug, activeTab) {
            if (channelId !== 'discussdisqus')
                return this.navigateToLandingPage({ replace: true });

            return this.channelDiscussion(channelId, forumId, threadSlug, activeTab, {
                noEmbed: true,
            });
        },

        notFound: NavigationUtils.notFoundRouteHandler,
    });

    return Router;
});

// https://c.disquscdn.com/next/16dccc7/home/js/main.com/next/16dccc7/home/js/Router.js

Replies to Router.js rss

Title Name Language When
completeReportUser.js disqus.com javascript 2 Months ago.