function bindInviteOverlay() {
        var inviteOverlayNode = Y.one("#invite-overlay");
        var inviteEmails = Y.one("#invite-emails");
        var inviteMessage = Y.one("#invite-message");
        var inviteButton = Y.one("#invite-invite");
        var cancelButton = Y.one("#invite-cancel");
        var xButton = Y.one("#invite-close");
        var launchInvite = Y.one(".launch-invite");

        inviteOverlayNode.removeClass('postmile-loading');

        function showOverlay() {
            // could clear here
            // overlay.set( 'centered', true ) ;
            renderInvite(); // clears data
            inviteOverlay.show();
        }

        inviteOverlay = new Y.Overlay({
            srcNode: inviteOverlayNode,
            // centered	: true,
            // constrain   : true,
            // render	  : true,
            visible: false,
            plugins: [
			Y.Plugin.OverlayModal,
			Y.Plugin.OverlayKeepaligned,
			{ fn: Y.Plugin.OverlayAutohide, cfg: {
			    focusedOutside: false  // disables the Overlay from auto-hiding on losing focus
			}
			}
		]
        });

        inviteOverlay.render();
        inviteOverlay.hide();

        /* inviteOverlay.on( 'blur', function( e ) { overlay.hide() } ) ;*/

        inviteOverlayNode.delegate('click', function (e) {
            var t = e.currentTarget;
            var id = t.getAttribute('participant');
            if (t.hasClass('selected')) {
                t.removeClass('selected');
            } else {
                t.addClass('selected');
            }
            gpostmile.contacts[id].selected = t.hasClass('selected');

        }, '.participant');

        inviteButton.on('click', function (e) {

            // needs to be URL encoded since it's a query param
            var message = encodeURIComponent(inviteMessage.get('value'));

            var uri = "/project/" + gpostmile.project.id + "/participants?message=" + message;

            var newParticipants = inviteEmails.get('value').replace(/^\s+|\s+$/g, "");
            newParticipants = newParticipants.split(',');
            newParticipants = newParticipants.map(function (s) { return s.replace(/^\s+|\s+$/g, ""); });
            newParticipants = newParticipants.filter(function (s) { return s.indexOf('@') >= 0; });

            var participants = newParticipants;
            var c, l;
            for (/*var*/c = 0, l = gpostmile.contacts.length; c < l; c++) {
                if (gpostmile.contacts[c].selected) {
                    participants.push(gpostmile.contacts[c].id);
                }
            }

            var jp = { "participants": participants };
            var json = JSON.stringify(jp);

            if (participants.length > 0) {

                var confirmInvite = function (response, myarg) { // response has id, rev, status

                    if (response.status === "ok") {

                        // getJson( "/project/" + gpostmile.project.id, Y.postmile.project.renderProjectParticipants ) ;
                        gpostmile.project.participants = response.participants;
                        Y.fire('postmile:renderProjectParticipants', gpostmile.project);

                        /* instead of locally turning participant into contact
                        rely on streaming contact update
                        for (var c=0, l=newParticipants.length; c < l; c++) {
                        var newContact = { }
                        gpostmile.contacts.push( newParticipants[c].id ) ;
                        gpostmile.contacts[ newParticipants[c].id ] = newParticipants[c] ;
                        }
                        */

                        // already s/b hidden: overlay.hide() ;

                        // clear selected nodes and data
                        // this clearing is now redundant as we clear upon launch
                        inviteOverlayNode.all('.participant').removeClass('selected');
                        var i, l;
                        for (/*var*/i = 0, l = gpostmile.contacts.length; i < l; ++i) {
                            var contact = gpostmile.contacts[i];
                            gpostmile.contacts[contact.id].selected = false;
                        }

                        // clear text fields
                        inviteEmails.set('value', '');
                        inviteMessage.set('value', '');

                        Y.fire('postmile:inform', 'Invitation sent', 'You have invited ' + participants.length + ' participants.');

                    } else {

                        Y.fire('postmile:inform', 'Invitation failed', 'Failed to invite new participants.');
                    }
                };
                postJson(uri, json, confirmInvite);
            }

            inviteOverlay.hide(); // don't wait for response 

        });

        cancelButton.on('click', function (e) {
            inviteOverlay.hide();
        });

        xButton.on('click', function (e) {
            inviteOverlay.hide();
        });

        launchInvite.on('click', function (e) {
            var pm = Y.one('#project-participants-menu');
            pm.addClass('menu-hidden');
            showOverlay();
        });

    }
/**
    * binds for various overlays
    * event listeners with simple inline/inner func handlers
    *
    */
binds for various overlays
event listeners with simple inline/inner func handlers
binds for various overlays event listeners with simple inline / inner func handlers
function bindInviteOverlay() {
        var inviteOverlayNode = Y.one("#invite-overlay");
        var inviteEmails = Y.one("#invite-emails");
        var inviteMessage = Y.one("#invite-message");
        var inviteButton = Y.one("#invite-invite");
        var cancelButton = Y.one("#invite-cancel");
        var xButton = Y.one("#invite-close");
        var launchInvite = Y.one(".launch-invite");
        inviteOverlayNode.removeClass('postmile-loading');
        function showOverlay() {
            renderInvite(); 
            inviteOverlay.show();
        }
        inviteOverlay = new Y.Overlay({
            srcNode: inviteOverlayNode,
            visible: false,
            plugins: [
			Y.Plugin.OverlayModal,
			Y.Plugin.OverlayKeepaligned,
			{ fn: Y.Plugin.OverlayAutohide, cfg: {
			    focusedOutside: false  
			}
			}
		]
        });
        inviteOverlay.render();
        inviteOverlay.hide();
        inviteOverlayNode.delegate('click', function (e) {
            var t = e.currentTarget;
            var id = t.getAttribute('participant');
            if (t.hasClass('selected')) {
                t.removeClass('selected');
            } else {
                t.addClass('selected');
            }
            gpostmile.contacts[id].selected = t.hasClass('selected');
        }, '.participant');
        inviteButton.on('click', function (e) {
            var message = encodeURIComponent(inviteMessage.get('value'));
            var uri = "/project/" + gpostmile.project.id + "/participants?message=" + message;
            var newParticipants = inviteEmails.get('value').replace(/^\s+|\s+$/g, "");
            newParticipants = newParticipants.split(',');
            newParticipants = newParticipants.map(function (s) { return s.replace(/^\s+|\s+$/g, ""); });
            newParticipants = newParticipants.filter(function (s) { return s.indexOf('@') >= 0; });
            var participants = newParticipants;
            var c, l;
            for (c = 0, l = gpostmile.contacts.length; c < l; c++) {
                if (gpostmile.contacts[c].selected) {
                    participants.push(gpostmile.contacts[c].id);
                }
            }
            var jp = { "participants": participants };
            var json = JSON.stringify(jp);
            if (participants.length > 0) {
                var confirmInvite = function (response, myarg) { 
                    if (response.status === "ok") {
                        gpostmile.project.participants = response.participants;
                        Y.fire('postmile:renderProjectParticipants', gpostmile.project);
                        inviteOverlayNode.all('.participant').removeClass('selected');
                        var i, l;
                        for (i = 0, l = gpostmile.contacts.length; i < l; ++i) {
                            var contact = gpostmile.contacts[i];
                            gpostmile.contacts[contact.id].selected = false;
                        }
                        inviteEmails.set('value', '');
                        inviteMessage.set('value', '');
                        Y.fire('postmile:inform', 'Invitation sent', 'You have invited ' + participants.length + ' participants.');
                    } else {
                        Y.fire('postmile:inform', 'Invitation failed', 'Failed to invite new participants.');
                    }
                };
                postJson(uri, json, confirmInvite);
            }
            inviteOverlay.hide(); 
        });
        cancelButton.on('click', function (e) {
            inviteOverlay.hide();
        });
        xButton.on('click', function (e) {
            inviteOverlay.hide();
        });
        launchInvite.on('click', function (e) {
            var pm = Y.one('#project-participants-menu');
            pm.addClass('menu-hidden');
            showOverlay();
        });
    }
function bindInviteOverlay ( ) { var inviteOverlayNode = Y . one ( "#invite-overlay" ) ; var inviteEmails = Y . one ( "#invite-emails" ) ; var inviteMessage = Y . one ( "#invite-message" ) ; var inviteButton = Y . one ( "#invite-invite" ) ; var cancelButton = Y . one ( "#invite-cancel" ) ; var xButton = Y . one ( "#invite-close" ) ; var launchInvite = Y . one ( ".launch-invite" ) ; inviteOverlayNode . removeClass ( 'postmile-loading' ) ; function showOverlay ( ) { renderInvite ( ) ; inviteOverlay . show ( ) ; } inviteOverlay = new Y . Overlay ( { srcNode : inviteOverlayNode , visible : false , plugins : [ Y . Plugin . OverlayModal , Y . Plugin . OverlayKeepaligned , { fn : Y . Plugin . OverlayAutohide , cfg : { focusedOutside : false } } ] } ) ; inviteOverlay . render ( ) ; inviteOverlay . hide ( ) ; inviteOverlayNode . delegate ( 'click' , function ( e ) { var t = e . currentTarget ; var id = t . getAttribute ( 'participant' ) ; if ( t . hasClass ( 'selected' ) ) { t . removeClass ( 'selected' ) ; } else { t . addClass ( 'selected' ) ; } gpostmile . contacts [ id ] . selected = t . hasClass ( 'selected' ) ; } , '.participant' ) ; inviteButton . on ( 'click' , function ( e ) { var message = encodeURIComponent ( inviteMessage . get ( 'value' ) ) ; var uri = "/project/" + gpostmile . project . id + "/participants?message=" + message ; var newParticipants = inviteEmails . get ( 'value' ) . replace ( / ^\s+|\s+$ / g , "" ) ; newParticipants = newParticipants . split ( ',' ) ; newParticipants = newParticipants . map ( function ( s ) { return s . replace ( / ^\s+|\s+$ / g , "" ) ; } ) ; newParticipants = newParticipants . filter ( function ( s ) { return s . indexOf ( '@' ) >= 0 ; } ) ; var participants = newParticipants ; var c , l ; for ( c = 0 , l = gpostmile . contacts . length ; c < l ; c ++ ) { if ( gpostmile . contacts [ c ] . selected ) { participants . push ( gpostmile . contacts [ c ] . id ) ; } } var jp = { "participants" : participants } ; var json = JSON . stringify ( jp ) ; if ( participants . length > 0 ) { var confirmInvite = function ( response , myarg ) { if ( response . status === "ok" ) { gpostmile . project . participants = response . participants ; Y . fire ( 'postmile:renderProjectParticipants' , gpostmile . project ) ; inviteOverlayNode . all ( '.participant' ) . removeClass ( 'selected' ) ; var i , l ; for ( i = 0 , l = gpostmile . contacts . length ; i < l ; ++ i ) { var contact = gpostmile . contacts [ i ] ; gpostmile . contacts [ contact . id ] . selected = false ; } inviteEmails . set ( 'value' , '' ) ; inviteMessage . set ( 'value' , '' ) ; Y . fire ( 'postmile:inform' , 'Invitation sent' , 'You have invited ' + participants . length + ' participants.' ) ; } else { Y . fire ( 'postmile:inform' , 'Invitation failed' , 'Failed to invite new participants.' ) ; } } ; postJson ( uri , json , confirmInvite ) ; } inviteOverlay . hide ( ) ; } ) ; cancelButton . on ( 'click' , function ( e ) { inviteOverlay . hide ( ) ; } ) ; xButton . on ( 'click' , function ( e ) { inviteOverlay . hide ( ) ; } ) ; launchInvite . on ( 'click' , function ( e ) { var pm = Y . one ( '#project-participants-menu' ) ; pm . addClass ( 'menu-hidden' ) ; showOverlay ( ) ; } ) ; }
binds for various overlays
 event listeners with simple inline/inner func handlers
binds for various overlays event listeners with simple inline / inner func handlers
// could clear here // overlay.set( 'centered', true ) ; // clears data // centered	: true, // constrain   : true, // render	  : true, // disables the Overlay from auto-hiding on losing focus /* inviteOverlay.on( 'blur', function( e ) { overlay.hide() } ) ;*/ // needs to be URL encoded since it's a query param /*var*/ // response has id, rev, status // getJson( "/project/" + gpostmile.project.id, Y.postmile.project.renderProjectParticipants ) ; /* instead of locally turning participant into contact
                        rely on streaming contact update
                        for (var c=0, l=newParticipants.length; c < l; c++) {
                        var newContact = { }
                        gpostmile.contacts.push( newParticipants[c].id ) ;
                        gpostmile.contacts[ newParticipants[c].id ] = newParticipants[c] ;
                        }
                        */ // already s/b hidden: overlay.hide() ; // clear selected nodes and data // this clearing is now redundant as we clear upon launch /*var*/ // clear text fields // don't wait for response 