function projectsDnd() {

        if (Y.postmile.settings && !Y.postmile.settings.projectsReorder()) {
            return null;
        }

        if (projectsDndDelegate) {
            projectsDndDelegate.syncTargets(); // gpostmile.tasksSortable.delegate.syncTargets() ;
            return projectsDndDelegate;
        }

        // project list is both a drag and drop target
        projectsDndDelegate = new Y.DD.Delegate({
            cont: '#projects',
            nodes: '#projects li.project',
            // invalid: 'input',
            // valid: 'a',
            target: { padding: '-10 10 10 -10' }, // needed
            // constrain2node: '#projects',
            last: null
        });

        projectsDndDelegate.dd.removeInvalid('a');
        // projectsDndDelegate.dd.addInvalid( '.projecttitle' ) ;
        // projectsDndDelegate.dd.addInvalid( '.projectdetails' ) ;

        // plug it index
        projectsDndDelegate.dd.plug(Y.Plugin.DDProxy, {
            moveOnEnd: false,
            // cloneNode: true,
            last: null
        });

        // constrain projects to just the project list
        var projectsListNode = Y.one('#projects');
        if (projectsListNode) {
            projectsDndDelegate.dd.plug(Y.Plugin.DDConstrained, {
                constrain2node: projectsListNode,
                last: null
            });
        }

        /*
        // don't allow draggin up or down past list
        var projectsNode = Y.one( '#projects' ) ;
        if( projectsNode ) {
        projectsDndDelegate.dd.plug(Y.Plugin.DDNodeScroll, {
        node: projectsNode,	// get('parentNode')
        last: null
        });
        }
        */

        //Listen for drag:start events on projects
        projectsDndDelegate.on('drag:start', function (e) {

            // we need to make the menu stick up during drag by ignoring the mouse out caused by the drag proxy
            savedMouseOutHideDelay = projectsmenu.menuNav.get('mouseOutHideDelay');
            projectsmenu.menuNav.set('mouseOutHideDelay', 999999);

            savedCursor = document.body.style.cursor;
            document.body.style.cursor = 'move';
            var drag = e.target; //Get our drag object
            drag.get('node').setStyle('opacity', '.25');
            // innerHTML's parent includes sibs
            // and can't count on outerHTML in places like FF
            // so go back to data and templates to regen markup
            // drag.get('dragNode').set('innerHTML', drag.get('node').get('outerHTML') );	// innerHTML's parent includes sibs
            var id = drag.get('node').getAttribute('project');
            var project = Y.postmile.gpostmile.projects[id];
            var html = Y.postmile.templates.projectMenuItem(project, Y.postmile.gpostmile.project);
            drag.get('dragNode').set('innerHTML', html); // innerHTML's parent includes sibs
            drag.get('dragNode').setStyles({
                opacity: '.5',
                borderColor: drag.get('node').getStyle('borderColor'),
                backgroundColor: drag.get('node').getStyle('backgroundColor'),
                last: null
            });

            // attempt to stop event from bubbling down to tasks
            // actually, tasks are not an ancestor (or descendent) so surprised this happens
            // could be a useful feature if we want events to pass thru transparent later as Eran asked
            // e.stopPropagation();, prevent default, halt, return false, etc
        });

        projectsDndDelegate.on('drag:drag', function (e) {
            setLastY(e);
            // document.body.style.cursor = 'move' ;
        });

        projectsDndDelegate.on('drop:over', function (e) {

            var drag = e.drag.get('node'),
				dragDrag = e.drag.get('dragNode'),
				drop = e.drop.get('node');

            if (drop.get('tagName').toLowerCase() === 'li') {
                if (!goingUp) {	// todo: make this halt up or something positional instead of dynamic Y
                    drop = drop.get('nextSibling');
                }

                // is this coming from suggestions, or a reordering of projects?
                if (drag.hasClass('project')) {
                    e.drop.get('node').get('parentNode').insertBefore(drag, drop); // reordered project
                } else {
                    // drag from suggestion
                    // pull proxy from list instead of using drag
                    var list = Y.one('#projects');
                    var proxy = list.one('.proxy');
                    if (!proxy) {
                        // create proxy from project template
                        // (with slight adjustments, like suggestion attr and proxy class)
                        var anchor = drag.one('a');
                        var project = { "title": anchor.get('text'), "participantsCount": 0 };
                        var extraClasses = 'proxy addnewitem';
                        var extraAttrs = 'suggestion="' + drag.getAttribute('suggestion') + '"';
                        var extraContent = '';
                        var html = Y.postmile.templates.projectMenuItem(project, null); // , extraClasses, extraAttrs, extraContent ) ;
                        e.drop.get('node').get('parentNode').insertBefore(html, drop);
                    } else {
                        list.insertBefore(proxy, drop); // just move proxy
                    }
                }

                //Set the new parentScroll on the nodescroll plugin 
                if (e.drag.nodescroll) {
                    e.drag.nodescroll.set('parentScroll', e.drop.get('node').get('parentNode'));
                }
                //Resize this nodes shim, so we can drop on it later.
                e.drop.sizeShim();

            }
        });

        // Listen for drag:end events started on projects (and must end on projects since that's the only drop)
        projectsDndDelegate.on('drag:end', function (e) {

            projectsmenu.menuNav.set('mouseOutHideDelay', savedMouseOutHideDelay);
            savedMouseOutHideDelay = null; // thsi is also used as a flag to help task ignore these drags

            var drag = e.target;
            //Put our styles back
            drag.get('node').setStyles({
                visibility: '',
                opacity: '1'
            });

            Y.fire('postmile:projectReorder', drag.get('node'));
            document.body.style.cursor = savedCursor;

        });

        return projectsDndDelegate;
    }
// this is strictly for the projects list menu - nothing to do with tasks and suggestion - perhaps factor out somewhere else
this is strictly for the projects list menu - nothing to do with tasks and suggestion - perhaps factor out somewhere else
this is strictly for the projects list menu - nothing to do with tasks and suggestion - perhaps factor out somewhere else
function projectsDnd() {
        if (Y.postmile.settings && !Y.postmile.settings.projectsReorder()) {
            return null;
        }
        if (projectsDndDelegate) {
            projectsDndDelegate.syncTargets(); 
            return projectsDndDelegate;
        }
        projectsDndDelegate = new Y.DD.Delegate({
            cont: '#projects',
            nodes: '#projects li.project',
            target: { padding: '-10 10 10 -10' }, 
            last: null
        });
        projectsDndDelegate.dd.removeInvalid('a');
        projectsDndDelegate.dd.plug(Y.Plugin.DDProxy, {
            moveOnEnd: false,
            last: null
        });
        var projectsListNode = Y.one('#projects');
        if (projectsListNode) {
            projectsDndDelegate.dd.plug(Y.Plugin.DDConstrained, {
                constrain2node: projectsListNode,
                last: null
            });
        }
        projectsDndDelegate.on('drag:start', function (e) {
            savedMouseOutHideDelay = projectsmenu.menuNav.get('mouseOutHideDelay');
            projectsmenu.menuNav.set('mouseOutHideDelay', 999999);
            savedCursor = document.body.style.cursor;
            document.body.style.cursor = 'move';
            var drag = e.target; 
            drag.get('node').setStyle('opacity', '.25');
            // drag.get('dragNode').set('innerHTML', drag.get('node').get('outerHTML') );	
            var id = drag.get('node').getAttribute('project');
            var project = Y.postmile.gpostmile.projects[id];
            var html = Y.postmile.templates.projectMenuItem(project, Y.postmile.gpostmile.project);
            drag.get('dragNode').set('innerHTML', html); 
            drag.get('dragNode').setStyles({
                opacity: '.5',
                borderColor: drag.get('node').getStyle('borderColor'),
                backgroundColor: drag.get('node').getStyle('backgroundColor'),
                last: null
            });
        });
        projectsDndDelegate.on('drag:drag', function (e) {
            setLastY(e);
        });
        projectsDndDelegate.on('drop:over', function (e) {
            var drag = e.drag.get('node'),
				dragDrag = e.drag.get('dragNode'),
				drop = e.drop.get('node');
            if (drop.get('tagName').toLowerCase() === 'li') {
                if (!goingUp) {	
                    drop = drop.get('nextSibling');
                }
                if (drag.hasClass('project')) {
                    e.drop.get('node').get('parentNode').insertBefore(drag, drop); 
                } else {
                    var list = Y.one('#projects');
                    var proxy = list.one('.proxy');
                    if (!proxy) {
                        var anchor = drag.one('a');
                        var project = { "title": anchor.get('text'), "participantsCount": 0 };
                        var extraClasses = 'proxy addnewitem';
                        var extraAttrs = 'suggestion="' + drag.getAttribute('suggestion') + '"';
                        var extraContent = '';
                        var html = Y.postmile.templates.projectMenuItem(project, null); 
                        e.drop.get('node').get('parentNode').insertBefore(html, drop);
                    } else {
                        list.insertBefore(proxy, drop); 
                    }
                }
                if (e.drag.nodescroll) {
                    e.drag.nodescroll.set('parentScroll', e.drop.get('node').get('parentNode'));
                }
                e.drop.sizeShim();
            }
        });
        projectsDndDelegate.on('drag:end', function (e) {
            projectsmenu.menuNav.set('mouseOutHideDelay', savedMouseOutHideDelay);
            savedMouseOutHideDelay = null; 
            var drag = e.target;
            drag.get('node').setStyles({
                visibility: '',
                opacity: '1'
            });
            Y.fire('postmile:projectReorder', drag.get('node'));
            document.body.style.cursor = savedCursor;
        });
        return projectsDndDelegate;
    }
function projectsDnd ( ) { if ( Y . postmile . settings && ! Y . postmile . settings . projectsReorder ( ) ) { return null ; } if ( projectsDndDelegate ) { projectsDndDelegate . syncTargets ( ) ; return projectsDndDelegate ; } projectsDndDelegate = new Y . DD . Delegate ( { cont : '#projects' , nodes : '#projects li.project' , target : { padding : '-10 10 10 -10' } , last : null } ) ; projectsDndDelegate . dd . removeInvalid ( 'a' ) ; projectsDndDelegate . dd . plug ( Y . Plugin . DDProxy , { moveOnEnd : false , last : null } ) ; var projectsListNode = Y . one ( '#projects' ) ; if ( projectsListNode ) { projectsDndDelegate . dd . plug ( Y . Plugin . DDConstrained , { constrain2node : projectsListNode , last : null } ) ; } projectsDndDelegate . on ( 'drag:start' , function ( e ) { savedMouseOutHideDelay = projectsmenu . menuNav . get ( 'mouseOutHideDelay' ) ; projectsmenu . menuNav . set ( 'mouseOutHideDelay' , 999999 ) ; savedCursor = document . body . style . cursor ; document . body . style . cursor = 'move' ; var drag = e . target ; drag . get ( 'node' ) . setStyle ( 'opacity' , '.25' ) ; var id = drag . get ( 'node' ) . getAttribute ( 'project' ) ; var project = Y . postmile . gpostmile . projects [ id ] ; var html = Y . postmile . templates . projectMenuItem ( project , Y . postmile . gpostmile . project ) ; drag . get ( 'dragNode' ) . set ( 'innerHTML' , html ) ; drag . get ( 'dragNode' ) . setStyles ( { opacity : '.5' , borderColor : drag . get ( 'node' ) . getStyle ( 'borderColor' ) , backgroundColor : drag . get ( 'node' ) . getStyle ( 'backgroundColor' ) , last : null } ) ; } ) ; projectsDndDelegate . on ( 'drag:drag' , function ( e ) { setLastY ( e ) ; } ) ; projectsDndDelegate . on ( 'drop:over' , function ( e ) { var drag = e . drag . get ( 'node' ) , dragDrag = e . drag . get ( 'dragNode' ) , drop = e . drop . get ( 'node' ) ; if ( drop . get ( 'tagName' ) . toLowerCase ( ) === 'li' ) { if ( ! goingUp ) { drop = drop . get ( 'nextSibling' ) ; } if ( drag . hasClass ( 'project' ) ) { e . drop . get ( 'node' ) . get ( 'parentNode' ) . insertBefore ( drag , drop ) ; } else { var list = Y . one ( '#projects' ) ; var proxy = list . one ( '.proxy' ) ; if ( ! proxy ) { var anchor = drag . one ( 'a' ) ; var project = { "title" : anchor . get ( 'text' ) , "participantsCount" : 0 } ; var extraClasses = 'proxy addnewitem' ; var extraAttrs = 'suggestion="' + drag . getAttribute ( 'suggestion' ) + '"' ; var extraContent = '' ; var html = Y . postmile . templates . projectMenuItem ( project , null ) ; e . drop . get ( 'node' ) . get ( 'parentNode' ) . insertBefore ( html , drop ) ; } else { list . insertBefore ( proxy , drop ) ; } } if ( e . drag . nodescroll ) { e . drag . nodescroll . set ( 'parentScroll' , e . drop . get ( 'node' ) . get ( 'parentNode' ) ) ; } e . drop . sizeShim ( ) ; } } ) ; projectsDndDelegate . on ( 'drag:end' , function ( e ) { projectsmenu . menuNav . set ( 'mouseOutHideDelay' , savedMouseOutHideDelay ) ; savedMouseOutHideDelay = null ; var drag = e . target ; drag . get ( 'node' ) . setStyles ( { visibility : '' , opacity : '1' } ) ; Y . fire ( 'postmile:projectReorder' , drag . get ( 'node' ) ) ; document . body . style . cursor = savedCursor ; } ) ; return projectsDndDelegate ; }
this is strictly for the projects list menu - nothing to do with tasks and suggestion - perhaps factor out somewhere else
this is strictly for the projects list menu - nothing to do with tasks and suggestion - perhaps factor out somewhere else
// gpostmile.tasksSortable.delegate.syncTargets() ; // project list is both a drag and drop target // invalid: 'input', // valid: 'a', // needed // constrain2node: '#projects', // projectsDndDelegate.dd.addInvalid( '.projecttitle' ) ; // projectsDndDelegate.dd.addInvalid( '.projectdetails' ) ; // plug it index // cloneNode: true, // constrain projects to just the project list /*
        // don't allow draggin up or down past list
        var projectsNode = Y.one( '#projects' ) ;
        if( projectsNode ) {
        projectsDndDelegate.dd.plug(Y.Plugin.DDNodeScroll, {
        node: projectsNode,	// get('parentNode')
        last: null
        });
        }
        */ //Listen for drag:start events on projects // we need to make the menu stick up during drag by ignoring the mouse out caused by the drag proxy //Get our drag object // innerHTML's parent includes sibs // and can't count on outerHTML in places like FF // so go back to data and templates to regen markup // drag.get('dragNode').set('innerHTML', drag.get('node').get('outerHTML') );	// innerHTML's parent includes sibs // innerHTML's parent includes sibs // attempt to stop event from bubbling down to tasks // actually, tasks are not an ancestor (or descendent) so surprised this happens // could be a useful feature if we want events to pass thru transparent later as Eran asked // e.stopPropagation();, prevent default, halt, return false, etc // document.body.style.cursor = 'move' ; // todo: make this halt up or something positional instead of dynamic Y // is this coming from suggestions, or a reordering of projects? // reordered project // drag from suggestion // pull proxy from list instead of using drag // create proxy from project template // (with slight adjustments, like suggestion attr and proxy class) // , extraClasses, extraAttrs, extraContent ) ; // just move proxy //Set the new parentScroll on the nodescroll plugin  //Resize this nodes shim, so we can drop on it later. // Listen for drag:end events started on projects (and must end on projects since that's the only drop) // thsi is also used as a flag to help task ignore these drags //Put our styles back