简体   繁体   中英

How to structure javascript when including another php file

I am attempting to build a small web application but I'm not clear how to communicate between different parts of the page. I will use my specific functionality to demonstrate my question.

All of my pages use a generic toolbar. Since this toolbar is used on multiple pages, it is in its own PHP file, which I include using

<?php include("../toolbar.php"); ?>

The toolbar includes a log in button. When clicked, this opens a modal login dialog (in this case the Facebook login dialog). When a user logs in, his or her name is displayed in the toolbar, and the log in button is replaced by a 'logout' button. Since this behavior is the same no matter which page the user is viewing, I created a toolbar.js file to display the log in modal and update the username/button appropriately.

However, on most pages, logging in or out from the toolbar needs to also update the contents of the main page. I can not guarantee that every page that includes toolbar.php will have to do anything when the log in status changes, but most will.

Similarly, the reverse is possible - a certain page might have a 'log in' button outside the toolbar. When this is used, the toolbar needs to update.

What is the best way to handle this?

Current implementation - this might be awful…

In toolbar.js I am basically calling a function, 'userSignedIn', whenever the user logs in (and an equivalent for log out). toolbar.js, implements this itself (it needs to update its button and user name label).

Then, if the main page (lets call it mainPage.php) needs to anything additional, I am re-using this same function to 'tack on' the additional actions. On load of that page, I do the following:

var originalUserSignedIn = userSignedIn;
userSignedIn = function() {
    originalUserSignedIn();
    customUserSignedIn();
}

customUserSignedIn is a function within mainPage.js, where I perform the additional actions. I have not yet implemented a solution for the opposite (sign in from mainPage.php needs to update toolbar.php).

I guess coming from an objective-C background, I am attempting something analogous to calling 'super' in a method implementation.

One way to do it is to initialize an empty array to hold callback functions and the sign function to call them, before any of the other javascript:

var userSignedInCallbacks = [];

var userSignedIn = function() {
    for (var i = 0; i < userSignedInCallbacks.length; i++) {
        userSignedInCallbacks[i]();
    }
}

Then, toolbar and main page js will both just add their appropriate callbacks to the array:

userSignedInCallbacks.push(function() {
    // ...
});

Finally, the login actions in either the toolbar or main page will both just call userSignedIn() .

One way you could do this is by using the publisher-subscriber pattern for handling communications between different modules in your page so that every modules is only coupled on an event interface.

I created a very simple example here . It doesn't handle the logout process but you can still see how things could be structured.

HTML

<div id="toolbar">
    <button class="login">Login</button>
</div>

<div id="another-section">
    <button class="login">Login</button>
</div>

<div id="login-dialog">
     <button class="login">Do login!</button>
</div>

JS

//in EventBus.js
var EventBus = {
    subscribers: {},
    publish: function (eventName) {
        var args = Array.prototype.slice.call(arguments, 1),
            subscribers = this.subscribers[eventName] || [],
            i = 0,
            len = subscribers.length,
            s;

        for (; i < len; i++) {
            s = subscribers[i];

            s.fn.apply(s.scope, args);
        }

    },
    subscribe: function (eventName, fn, scope) {
        var subs = this.subscribers[eventName] = this.subscribers[eventName]  || [];
        subs.push({ fn: fn, scope: scope });
    }
};

//in toolbar.js
function Toolbar(el, eventBus) {
    var $el = this.$el = $(el),
        $loginButton = $('button.login', $el);

    $loginButton.click(function () {
        eventBus.publish('userWantsToLogin');
    });

    eventBus.subscribe('userLoggedIn', function () {
        $loginButton.html('Logout');
        //change button handlers to handle logout...
    });
}

//in another-section.js
function AnotherSection(el, eventBus) {
    var $el = this.$el = $(el),
        $loginButton = $('button.login', $el);

    $loginButton.click(function () {
        eventBus.publish('userWantsToLogin');
    });

    eventBus.subscribe('userLoggedIn', function () {
        $loginButton.html('Logout');
        //change button handlers to handle logout...
    });
}

//in main.js
$(function () {
    var $loginDialog = $('#login-dialog');

    $loginDialog.dialog({ autoOpen: false});

    $('button.login', $loginDialog).click(function () {
        EventBus.publish('userLoggedIn');
    });

    EventBus.subscribe('userWantsToLogin', function () {
        $loginDialog.dialog('open');
    });

    new Toolbar('#toolbar', EventBus);
    new AnotherSection('#another-section', EventBus);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM