<commit_before>

(function() {
    "use strict";

    console.log('StompSetup setup');
    var areWeInitialized = false;
    define([
        'angular'
    ], function(angular) {
        console.log('StompSetupCtrl define');

        var selfdict = {};
        selfdict.isInitialized = areWeInitialized = false;
        var scopeDict = {};

        function StompSetupCtrl($scope, $modal, $rootScope){
            console.log("in StompSetupCtrl");
            $scope.privateChannelMashover = 'private-channel-mashover';
            selfdict.scope = $scope;
            selfdict.pusher = null;
            selfdict.isInitialized = areWeInitialized = false;
            scopeDict['rootScope'] = $rootScope;

            // selfdict.scope = null;
            // selfdict.mph = null;
            // selfdict.callbackFunction = null;
            $scope.showDialog = selfdict.scope.showDialog = false;
            $scope.data = {
                privateChannelMashover : 'private-channel-mashover',
                prevChannel : 'private-channel-mashover',
                whichDismiss : "Cancel"
            };

            $scope.preserveState = function(){
                console.log("preserveState");
                // $scope.data.whichDismiss = 'Cancel';
                $scope.data.prevChannel = $scope.data.privateChannelMashover.slice(0);
                console.log("preserve " + $scope.data.prevDstSel + " from " + $scope.data.privateChannelMashover);
            };

            $scope.restoreState = function(){
                console.log("restoreState");
                // $scope.data.whichDismiss = 'Accept';
                console.log("restore " + $scope.data.privateChannelMashover + " from " + $scope.data.prevDstSel);
                $scope.data.privateChannelMashover = $scope.data.prevChannel.slice(0);
            };

            $scope.onAcceptChannel = function(){
                console.log("onAcceptChannel " + $scope.data.privateChannelMashover);
                selfdict.pusher = $scope.PusherClient(selfdict.eventDct, $scope.data.privateChannelMashover,
                    selfdict.callbackFunction);
            };

            $scope.displayPusherDialog = function(){
                // selfdict.scope.showModal(true);
                var $inj = angular.injector(['app']);
                var serv = $inj.get('CurrentMapTypeService');
                selfdict.mph = serv.getSelectedMapType();

                selfdict.eventDct = selfdict.mph.getEventDictionary();

                // selfdict.eventDct =
                        // {'client-MapXtntEvent' : selfdict.mph.retrievedBounds,
                        // 'client-MapClickEvent' : selfdict.mph.retrievedClick
                        // };

                selfdict.callbackFunction = null;
                scopeDict.rootScope.$broadcast('ShowChannelSelectorEvent');
                $scope.safeApply(function(){
                    selfdict.scope.showDialog = $scope.showDialog = true;
                });
            };

            $scope.PusherClient = function(eventDct, channel, cbfn)
            {
                console.log("PusherClient");
                this.eventDct = eventDct;
                var self = this;
                self.callbackfunction = cbfn;
                self.eventDct = eventDct;
                self.channel = channel;
                if(channel[0] == '/')
                {
                    var chlength = channel.length;
                    var channelsub = channel.substring(1);
                    channelsub = channelsub.substring(0, chlength-2);
                    channel = channelsub;
                }
                self.CHANNEL = channel; //'/' + channel + '/';
                console.log("with channel " + self.CHANNEL);

                var pusher = new Pusher('5c6bad75dc0dd1cec1a6');
                pusher.connection.bind('state_change', function(state) {
                    if( state.current === 'connected' ) {
                        // alert("Yipee! We've connected!");
                        console.log("Yipee! We've connected!");
                        }
                    else {
                        // alert("Oh-Noooo!, my Pusher connection failed");
                        console.log("Oh-Noooo!, my Pusher connection failed");
                        }
                    });
                var channelBind = pusher.subscribe(self.CHANNEL);
                /*
                channelBind.bind('client-MapXtntEvent', function(frame)
                 {  // Executed when a messge is received
                     console.log('frame is',frame);
                     self.eventDct.retrievedBounds(frame);
                     console.log("back from boundsRetriever");
                 }
                );
                 */

                channelBind.bind('client-MapXtntEvent', function(frame)
                {
                    console.log('frame is',frame);
                    selfdict.eventDct['client-MapXtntEvent'](frame);
                    console.log("back from boundsRetriever");
                });

                channelBind.bind('client-MapClickEvent', function(frame)
                {
                    console.log('frame is',frame);
                    selfdict.eventDct['client-MapClickEvent'](frame);
                    console.log("back from clickRetriever");
                });

                channelBind.bind('pusher:subscription_error', function(statusCode) {
                    //alert('Problem subscribing to "private-channel": ' + statusCode);
                    console.log('Problem subscribing to "private-channel": ' + statusCode);
                });
                channelBind.bind('pusher:subscription_succeeded', function() {
                    console.log('Successfully subscribed to "private-channel"');
                });

                var $inj = angular.injector(['app']);
                var serv = $inj.get('CurrentMapTypeService');
                selfdict.mph = serv.getSelectedMapType();

                console.log("CurrentMapTypeService got mph, call setPusherClient");
                selfdict.mph.setPusherClient(pusher, self.CHANNEL);
                if(self.callbackfunction != null){
                    self.callbackfunction(self.CHANNEL);
                }
                return pusher;
            };

            $scope.hitEnter = function(evt){
                if(angular.equals(evt.keyCode,13) && !(angular.equals($scope.name,null) || angular.equals($scope.name,''))){
                    $scope.save();
                }
            }; // end hitEnter

            $scope.safeApply = function(fn) {
                var phase = this.$root.$$phase;
                  if(phase == '$apply' || phase == '$digest') {
                      if(fn && (typeof(fn) === 'function')) {
                          fn();
                      }
                  } else {
                    this.$apply(fn);
                }
            };
        }

        StompSetupCtrl.prototype.isInitialized = function(){
            return areWeInitialized;
        }

        StompSetupCtrl.prototype.setupPusherClient = function(eventDct, cbfn)
        {
            selfdict.eventDct = eventDct;
            selfdict.callbackFunction = cbfn;
            console.log("toggleShow from " + selfdict.scope.showDialog);
            scopeDict.rootScope.$broadcast('ShowChannelSelectorEvent');
            selfdict.scope.safeApply(function(){
                selfdict.scope.showDialog = ! selfdict.scope.showDialog;
            });
            console.log("toggleShow after apply " + selfdict.scope.showDialog);

            // selfdict.scope.PusherClient(eventDct, selfdict.scope.privateChannelMashover, cbfn);
        };

        StompSetupCtrl.prototype.createPusherClient = function(eventDct, pusherChannel, cbfn)
        {
            selfdict.eventDct = eventDct;
            selfdict.callbackFunction = cbfn;
            selfdict.pusher = selfdict.scope.PusherClient(eventDct, pusherChannel, cbfn);
            return selfdict.pusher;
        };

            //selfdict.setupPusherClient = $scope.setupPusherClient;

        function init(App) {
            console.log('StompSetup init');
            // alert("areWeInitialized ?");
            // alert(areWeInitialized);
            // if(areWeInitialized == true){
                // alert("quick bailout");
                // return;
            // }
            selfdict.isInitialized = areWeInitialized = true;
            App.controller('StompSetupCtrl',  ['$scope', '$modal', '$rootScope', StompSetupCtrl]);

            App.directive("modalShowPusher", function () {
                var tpl = ' \

 \

 \

 \
                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> \

Create a Pusher Channel ID :
 \

 \

 \
                        <input type="text" name="input" ng-model="data.privateChannelMashover", ng-init="data.privateChannelMashover=\'private-channel-mashover\'"> \

channel name : {{data.privateChannelMashover}}
 \

 \

 \
                        <button type="button" class="btn btn-primary" ng-click="$parent.data.whichDismiss = \'Accept\';$parent.preserveState()" data-dismiss="modal">Accept</button> \
                        <button type="button" class="btn btn-primary" ng-click="$parent.data.whichDismiss = \'Cancel\';$parent.restoreState()" data-dismiss="modal">Cancel</button> \

 \

 \

 \
                ';
                return {
                    restrict: "A",
                    template : tpl,
                    scope: {
                        modalVisible: "=",
                        modalPdata: "="
                    },
                    link: function (scope, element, attrs) {
                        var localScope = scope;
                        //Hide or show the modal
                        scope.showModal = function (visible, elem) {
                            if (!elem){
                                elem = element;
                                console.log("elem is now :");
                                console.debug(elem);
                                console.log("how about $(elem)?");
                                var delem = $(elem);
                                console.debug(delem);
                            }
                            if (visible){
                                $(elem).modal311("show");
                            }
                            else{
                                $(elem).modal311("hide");
                            }
                        };

                        scope.$on('ShowChannelSelectorEvent', function() {
                            scope.showModal(true);
                        });

                        selfdict.scope.showModal = scope.showModal;

                        //Check to see if the modal-visible attribute exists
                        if (!attrs.modalVisible)
                        {

                            //The attribute isn't defined, show the modal by default
                            scope.showModal(true);

                        }
                        else
                        {

                            //Watch for changes to the modal-visible attribute
                            scope.$watch("modalVisible", function (newValue, oldValue) {
                                scope.showModal(newValue);
                                // scope.$parent.showDialog = newValue;
                                console.log("watch modalVisible  : ");
                                console.debug(scope.$parent.data);
                                // scope.$parent.preserveState();
                            });
                            //Watch for changes to the modal-mdata attribute
                            scope.$watch("modalPdata", function (newValue, oldValue) {
                                if( ! angular.isUndefinedOrNull(newValue)){
                                  localScope.$parent.data = newValue;
                                }
                                console.log("watch modalMdata scope.$parent data  : ");
                                console.debug(localScope.$parent.data);
                            });
                            //Watch for changes to the modal-mdata attribute
                            scope.$watch("data.privateChannelMashover", function (newValue, oldValue)
                            {
                                if( ! angular.isUndefinedOrNull(newValue)){
                                    localScope.$parent.data.privateChannelMashover = newValue;
                                }
                                // console.log("watch modalMdata scope.$parent data  : ");
                                // console.debug(localScope.$parent.data);
                            });

                            scope.$watch('scope.$parent.selfdict.scope.showDialog', function (newValue, oldValue) {
                                console.log("scope.$watch newValue : " + newValue);
                                console.log("scope.$watch 'scope.$parent.showDialog' : " + scope.$parent.showDialog);
                                scope.showModal(newValue);
                                //attrs.modalVisible = false;
                            });

                        }
                        //Update the visible value when the dialog is closed through UI actions (Ok, cancel, etc.)
                        $(element).on('hidden.bs.modal', function () {
                            scope.modalVisible = localScope.$parent.showDialog = false;
                            console.log("hide event called");
                            if (!scope.$$phase && !scope.$root.$$phase){
                                scope.$apply();
                            }
                            scope.$apply();
                            console.log("hidden modalMdata : ");
                            console.debug(scope.$parent.data);
                            console.log("whichDismiss : " + scope.$parent.data.whichDismiss);
                            if(scope.$parent.data.whichDismiss == "Accept"){
                                scope.$parent.onAcceptChannel();
                            }
                        });

                    }

                };
            });

            // StompSetupCtrl.self.scope = StompSetupCtrl.$scope;
            // SearcherCtrlMap.CurrentWebMapIdService= CurrentWebMapIdService;
            return StompSetupCtrl;
        }

        return { start: init, setupPusherClient : StompSetupCtrl.prototype.setupPusherClient,
                  createPusherClient : StompSetupCtrl.prototype.createPusherClient,
                  isInitialized : StompSetupCtrl.prototype.isInitialized};

    });

}).call(this);
<commit_msg>Removed necessity for typing 'private-channel-' in pusher channel setup dialog.  The controller maintains the unique name and prepends 'private-channel-' to it before subscribing or creatiing the url to send to new clients windows.<commit_after>

(function() {
    "use strict";

    console.log('StompSetup setup');
    var areWeInitialized = false;
    define([
        'angular'
    ], function(angular) {
        console.log('StompSetupCtrl define');

        var selfdict = {};
        selfdict.isInitialized = areWeInitialized = false;
        var scopeDict = {};

        function StompSetupCtrl($scope, $modal, $rootScope){
            console.log("in StompSetupCtrl");
            $scope.privateChannelMashover = 'mashchannel';
            selfdict.scope = $scope;
            selfdict.pusher = null;
            selfdict.isInitialized = areWeInitialized = false;
            scopeDict['rootScope'] = $rootScope;

            // selfdict.scope = null;
            // selfdict.mph = null;
            // selfdict.callbackFunction = null;
            $scope.showDialog = selfdict.scope.showDialog = false;
            $scope.data = {
                privateChannelMashover : 'mashchannel',
                prevChannel : 'mashchannel',
                whichDismiss : "Cancel"
            };

            $scope.preserveState = function(){
                console.log("preserveState");
                // $scope.data.whichDismiss = 'Cancel';
                $scope.data.prevChannel = $scope.data.privateChannelMashover.slice(0);
                console.log("preserve " + $scope.data.prevDstSel + " from " + $scope.data.privateChannelMashover);
            };

            $scope.restoreState = function(){
                console.log("restoreState");
                // $scope.data.whichDismiss = 'Accept';
                console.log("restore " + $scope.data.privateChannelMashover + " from " + $scope.data.prevDstSel);
                $scope.data.privateChannelMashover = $scope.data.prevChannel.slice(0);
            };

            $scope.onAcceptChannel = function(){
                console.log("onAcceptChannel " + $scope.data.privateChannelMashover);
                selfdict.pusher = $scope.PusherClient(selfdict.eventDct, $scope.data.privateChannelMashover,
                    selfdict.callbackFunction);
            };

            $scope.displayPusherDialog = function(){
                // selfdict.scope.showModal(true);
                var $inj = angular.injector(['app']);
                var serv = $inj.get('CurrentMapTypeService');
                selfdict.mph = serv.getSelectedMapType();

                selfdict.eventDct = selfdict.mph.getEventDictionary();

                // selfdict.eventDct =
                        // {'client-MapXtntEvent' : selfdict.mph.retrievedBounds,
                        // 'client-MapClickEvent' : selfdict.mph.retrievedClick
                        // };

                selfdict.callbackFunction = null;
                scopeDict.rootScope.$broadcast('ShowChannelSelectorEvent');
                $scope.safeApply(function(){
                    selfdict.scope.showDialog = $scope.showDialog = true;
                });
            };

            $scope.PusherClient = function(eventDct, channel, cbfn)
            {
                console.log("PusherClient");
                this.eventDct = eventDct;
                var self = this;
                self.callbackfunction = cbfn;
                self.eventDct = eventDct;
                self.channel = channel;
                if(channel[0] == '/')
                {
                    var chlength = channel.length;
                    var channelsub = channel.substring(1);
                    channelsub = channelsub.substring(0, chlength-2);
                    channel = channelsub;
                }

                self.CHANNEL = channel.indexOf("private-channel-") > -1 ? channel : 'private-channel-' + channel;
                console.log("with channel " + self.CHANNEL);

                var pusher = new Pusher('5c6bad75dc0dd1cec1a6');
                pusher.connection.bind('state_change', function(state) {
                    if( state.current === 'connected' ) {
                        // alert("Yipee! We've connected!");
                        console.log("Yipee! We've connected!");
                        }
                    else {
                        // alert("Oh-Noooo!, my Pusher connection failed");
                        console.log("Oh-Noooo!, my Pusher connection failed");
                        }
                    });
                var channelBind = pusher.subscribe(self.CHANNEL);
                /*
                channelBind.bind('client-MapXtntEvent', function(frame)
                 {  // Executed when a messge is received
                     console.log('frame is',frame);
                     self.eventDct.retrievedBounds(frame);
                     console.log("back from boundsRetriever");
                 }
                );
                 */

                channelBind.bind('client-MapXtntEvent', function(frame)
                {
                    console.log('frame is',frame);
                    selfdict.eventDct['client-MapXtntEvent'](frame);
                    console.log("back from boundsRetriever");
                });

                channelBind.bind('client-MapClickEvent', function(frame)
                {
                    console.log('frame is',frame);
                    selfdict.eventDct['client-MapClickEvent'](frame);
                    console.log("back from clickRetriever");
                });

                channelBind.bind('pusher:subscription_error', function(statusCode) {
                    //alert('Problem subscribing to "private-channel": ' + statusCode);
                    console.log('Problem subscribing to "private-channel": ' + statusCode);
                });
                channelBind.bind('pusher:subscription_succeeded', function() {
                    console.log('Successfully subscribed to "' + self.CHANNEL + 'r"');
                });

                var $inj = angular.injector(['app']);
                var serv = $inj.get('CurrentMapTypeService');
                selfdict.mph = serv.getSelectedMapType();

                console.log("CurrentMapTypeService got mph, call setPusherClient");
                selfdict.mph.setPusherClient(pusher, self.CHANNEL);
                if(self.callbackfunction != null){
                    self.callbackfunction(self.CHANNEL);
                }
                return pusher;
            };

            $scope.hitEnter = function(evt){
                if(angular.equals(evt.keyCode,13) && !(angular.equals($scope.name,null) || angular.equals($scope.name,''))){
                    $scope.save();
                }
            }; // end hitEnter

            $scope.safeApply = function(fn) {
                var phase = this.$root.$$phase;
                  if(phase == '$apply' || phase == '$digest') {
                      if(fn && (typeof(fn) === 'function')) {
                          fn();
                      }
                  } else {
                    this.$apply(fn);
                }
            };
        }

        StompSetupCtrl.prototype.isInitialized = function(){
            return areWeInitialized;
        }

        StompSetupCtrl.prototype.setupPusherClient = function(eventDct, cbfn)
        {
            selfdict.eventDct = eventDct;
            selfdict.callbackFunction = cbfn;
            console.log("toggleShow from " + selfdict.scope.showDialog);
            scopeDict.rootScope.$broadcast('ShowChannelSelectorEvent');
            selfdict.scope.safeApply(function(){
                selfdict.scope.showDialog = ! selfdict.scope.showDialog;
            });
            console.log("toggleShow after apply " + selfdict.scope.showDialog);

            // selfdict.scope.PusherClient(eventDct, selfdict.scope.privateChannelMashover, cbfn);
        };

        StompSetupCtrl.prototype.createPusherClient = function(eventDct, pusherChannel, cbfn)
        {
            selfdict.eventDct = eventDct;
            selfdict.callbackFunction = cbfn;
            selfdict.pusher = selfdict.scope.PusherClient(eventDct, pusherChannel, cbfn);
            return selfdict.pusher;
        };

            //selfdict.setupPusherClient = $scope.setupPusherClient;

        function init(App) {
            console.log('StompSetup init');
            // alert("areWeInitialized ?");
            // alert(areWeInitialized);
            // if(areWeInitialized == true){
                // alert("quick bailout");
                // return;
            // }
            selfdict.isInitialized = areWeInitialized = true;
            App.controller('StompSetupCtrl',  ['$scope', '$modal', '$rootScope', StompSetupCtrl]);

            App.directive("modalShowPusher", function () {
                var tpl = ' \

 \

 \

 \
                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> \

Create a Pusher Channel ID :
 \

 \

 \
                        <input type="text" name="input" ng-model="data.privateChannelMashover", ng-init="data.privateChannelMashover=\'mashchannel\'"> \

channel name : {{data.privateChannelMashover}}
 \

 \

 \
                        <button type="button" class="btn btn-primary" ng-click="$parent.data.whichDismiss = \'Accept\';$parent.preserveState()" data-dismiss="modal">Accept</button> \
                        <button type="button" class="btn btn-primary" ng-click="$parent.data.whichDismiss = \'Cancel\';$parent.restoreState()" data-dismiss="modal">Cancel</button> \

 \

 \

 \
                ';
                return {
                    restrict: "A",
                    template : tpl,
                    scope: {
                        modalVisible: "=",
                        modalPdata: "="
                    },
                    link: function (scope, element, attrs) {
                        var localScope = scope;
                        //Hide or show the modal
                        scope.showModal = function (visible, elem) {
                            if (!elem){
                                elem = element;
                                console.log("elem is now :");
                                console.debug(elem);
                                console.log("how about $(elem)?");
                                var delem = $(elem);
                                console.debug(delem);
                            }
                            if (visible){
                                $(elem).modal311("show");
                            }
                            else{
                                $(elem).modal311("hide");
                            }
                        };

                        scope.$on('ShowChannelSelectorEvent', function() {
                            scope.showModal(true);
                        });

                        selfdict.scope.showModal = scope.showModal;

                        //Check to see if the modal-visible attribute exists
                        if (!attrs.modalVisible)
                        {

                            //The attribute isn't defined, show the modal by default
                            scope.showModal(true);

                        }
                        else
                        {

                            //Watch for changes to the modal-visible attribute
                            scope.$watch("modalVisible", function (newValue, oldValue) {
                                scope.showModal(newValue);
                                // scope.$parent.showDialog = newValue;
                                console.log("watch modalVisible  : ");
                                console.debug(scope.$parent.data);
                                // scope.$parent.preserveState();
                            });
                            //Watch for changes to the modal-mdata attribute
                            scope.$watch("modalPdata", function (newValue, oldValue) {
                                if( ! angular.isUndefinedOrNull(newValue)){
                                  localScope.$parent.data = newValue;
                                }
                                console.log("watch modalMdata scope.$parent data  : ");
                                console.debug(localScope.$parent.data);
                            });
                            //Watch for changes to the modal-mdata attribute
                            scope.$watch("data.privateChannelMashover", function (newValue, oldValue)
                            {
                                if( ! angular.isUndefinedOrNull(newValue)){
                                    localScope.$parent.data.privateChannelMashover = newValue;
                                }
                                // console.log("watch modalMdata scope.$parent data  : ");
                                // console.debug(localScope.$parent.data);
                            });

                            scope.$watch('scope.$parent.selfdict.scope.showDialog', function (newValue, oldValue) {
                                console.log("scope.$watch newValue : " + newValue);
                                console.log("scope.$watch 'scope.$parent.showDialog' : " + scope.$parent.showDialog);
                                scope.showModal(newValue);
                                //attrs.modalVisible = false;
                            });

                        }
                        //Update the visible value when the dialog is closed through UI actions (Ok, cancel, etc.)
                        $(element).on('hidden.bs.modal', function () {
                            scope.modalVisible = localScope.$parent.showDialog = false;
                            console.log("hide event called");
                            if (!scope.$$phase && !scope.$root.$$phase){
                                scope.$apply();
                            }
                            scope.$apply();
                            console.log("hidden modalMdata : ");
                            console.debug(scope.$parent.data);
                            console.log("whichDismiss : " + scope.$parent.data.whichDismiss);
                            if(scope.$parent.data.whichDismiss == "Accept"){
                                scope.$parent.onAcceptChannel();
                            }
                        });

                    }

                };
            });

            // StompSetupCtrl.self.scope = StompSetupCtrl.$scope;
            // SearcherCtrlMap.CurrentWebMapIdService= CurrentWebMapIdService;
            return StompSetupCtrl;
        }

        return { start: init, setupPusherClient : StompSetupCtrl.prototype.setupPusherClient,
                  createPusherClient : StompSetupCtrl.prototype.createPusherClient,
                  isInitialized : StompSetupCtrl.prototype.isInitialized};

    });

}).call(this);
<|endoftext|>


<commit_before>//Express modules
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var mongoose = require('mongoose');
var mongoURI = 'mongodb://localhost:27017/macysApp';
var session = require('express-session');

//Mongoose Connection
mongoose.set('debug', true);
mongoose.connect(mongoURI);
mongoose.connection.once('open', function() {
console.log('Connected to mongoDB at: ', mongoURI);
});

//Express Connection
var port = 8080;
var app = express();

app
  .use(bodyParser.json())
  .use(cors())
  .use(express.static(__dirname + '/public'))
  .use(session({secret: 'secret'}));

//Controllers
var ProductsController = require('./api/controllers/ProductsController');
var CartController = require('./api/controllers/CartController.js');
var OrderController = require('./api/controllers/OrderController.js');
var UserController = require('./api/controllers/UserController.js');

//Endpoints -- Represents the View of the Backend --CRUD
app.post('/api/products', ProductsController.create);
app.get('/api/products', ProductsController.read);
app.get('/api/products/:id', ProductsController.readOne);
app.put('/api/products/:id', ProductsController.update);
app.delete('/api/products/:id', ProductsController.delete);

app.post('/api/users', UserController.create);
app.get('/api/users', UserController.read);
app.get('/api/users/:id', UserController.readOne);
app.put('/api/users/:id', UserController.update);
app.delete('/api/users/:id', UserController.delete);

app.post('/api/orders', OrderController.create);
app.get('/api/orders', OrderController.read);
app.get('/api/orders/:id', OrderController.readOne);
app.put('/api/orders/:id', OrderController.update);
app.delete('/api/orders/:id', OrderController.delete);

//CART

app.post('/api/cart', CartController.addProduct);
app.get('/api/cart', CartController.getCart);
app.delete('/api/cart/remove/:id', CartController.deleteItem);
app.put('/api/cart/updateItem', CartController.updateItem);

//Port verification
app.listen(port, function(){
  console.log("Listening on port: ", port);
});
<commit_msg>updated server file<commit_after>//Express modules
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
// var mongoose = require('mongoose');
// var mongoURI = 'mongodb://localhost:27017/macysApp';
var session = require('express-session');

//Mongoose Connection
// mongoose.set('debug', true);
// mongoose.connect(mongoURI);
// mongoose.connection.once('open', function() {
// console.log('Connected to mongoDB at: ', mongoURI);
// });

//Express Connection
var port = 8080;
var app = express();

app
  .use(bodyParser.json())
  .use(cors())
  .use(express.static(__dirname + '/public'))
  .use(session({secret: 'secret'}));

//Controllers
var ProductsController = require('./api/controllers/ProductsController');
var CartController = require('./api/controllers/CartController.js');
var OrderController = require('./api/controllers/OrderController.js');
var UserController = require('./api/controllers/UserController.js');

//Endpoints -- Represents the View of the Backend --CRUD
app.post('/api/products', ProductsController.create);
app.get('/api/products', ProductsController.read);
app.get('/api/products/:id', ProductsController.readOne);
app.put('/api/products/:id', ProductsController.update);
app.delete('/api/products/:id', ProductsController.delete);

app.post('/api/users', UserController.create);
app.get('/api/users', UserController.read);
app.get('/api/users/:id', UserController.readOne);
app.put('/api/users/:id', UserController.update);
app.delete('/api/users/:id', UserController.delete);

app.post('/api/orders', OrderController.create);
app.get('/api/orders', OrderController.read);
app.get('/api/orders/:id', OrderController.readOne);
app.put('/api/orders/:id', OrderController.update);
app.delete('/api/orders/:id', OrderController.delete);

//CART

app.post('/api/cart', CartController.addProduct);
app.get('/api/cart', CartController.getCart);
app.delete('/api/cart/remove/:id', CartController.deleteItem);
app.put('/api/cart/updateItem', CartController.updateItem);

//Port verification
app.listen(port, function(){
  console.log("Listening on port: ", port);
});
<|endoftext|>


<commit_before>( function ( $, mw ) {
	'use strict';

	mw.echo.special = {

		notcontinue: null,
		header: '',
		processing: false,

		/**
		 * Initialize the property in special notification page.
		 */
		initialize: function () {
			var skin = mw.config.get('skin');

			// Convert more link into a button
			$( '#mw-echo-more' )
				.addClass( 'mw-ui-button mw-ui-primary' )
				.css( 'margin', '0.5em 0 0 0' )
				.click( function ( e ) {
					e.preventDefault();
					if ( !mw.echo.special.processing ) {
						mw.echo.special.processing = true;
						mw.echo.special.loadMore();
					}
				}
			);
			mw.echo.special.notcontinue = mw.config.get( 'wgEchoNextContinue' );
			mw.echo.special.header = mw.config.get( 'wgEchoDateHeader' );

			// Set up each individual notification with eventlogging, a close
			// box and dismiss interface if it is dismissable.
			$( '.mw-echo-notification' ).each( function () {
				mw.echo.setupNotificationLogging( $( this ), 'archive' );
				if ( $( this ).find( '.mw-echo-dismiss' ).length ) {
					mw.echo.setUpDismissability( this );
				}
			} );

			$( '#mw-echo-moreinfo-link' ).click( function () {
				mw.echo.logInteraction( 'ui-help-click', 'archive' );
			} );
			$( '#mw-echo-pref-link' ).click( function () {
				mw.echo.logInteraction( 'ui-prefs-click', 'archive' );
			} );

			// Convert subtitle links into header icons for Vector and Monobook skins
			if ( skin === 'vector' || skin === 'monobook' ) {
				$( '#mw-echo-moreinfo-link, #mw-echo-pref-link' )
					.empty()
					.appendTo( '#firstHeading' );
				$( '#contentSub' ).empty();
			}

		},

		/**
		 * Load more notification records.
		 */
		loadMore: function () {
			var api = new mw.Api( { ajax: { cache: false } } ),
				notifications, data, container, $li, that = this, unread = [], apiData;

			apiData = {
				'action' : 'query',
				'meta' : 'notifications',
				'notformat' : 'html',
				'notprop' : 'index|list',
				'notcontinue': this.notcontinue,
				'notlimit': mw.config.get( 'wgEchoDisplayNum' )
			};

			api.get( mw.echo.desktop.appendUseLang( apiData ) ).done( function ( result ) {
				container = $( '#mw-echo-special-container' );
				notifications = result.query.notifications;
				unread = [];

				$.each( notifications.index, function ( index, id ) {
					data = notifications.list[id];

					if ( that.header !== data.timestamp.date ) {
						that.header = data.timestamp.date;
						$( '

' ).addClass( 'mw-echo-date-section' ).append( that.header ).appendTo( container );
					}

					$li = $( '

' )
						.data( 'details', data )
						.data( 'id', id )
						.addClass( 'mw-echo-notification' )
						.attr( {
							'data-notification-category': data.category,
							'data-notification-event': data.id,
							'data-notification-type': data.type
						} )
						.append( data['*'] )
						.appendTo( container );

					if ( !data.read ) {
						$li.addClass( 'mw-echo-unread' );
						unread.push( id );
					}

					mw.echo.setupNotificationLogging( $li, 'archive' );

					if ( $li.find( '.mw-echo-dismiss' ).length ) {
						mw.echo.setUpDismissability( $li );
					}
				} );

				that.notcontinue = notifications['continue'];
				if ( unread.length > 0 ) {
					that.markAsRead( unread );
				} else {
					that.onSuccess();
				}
			} ).fail( function () {
				that.onError();
			} );
		},

		/**
		 * Mark notifications as read.
		 */
		markAsRead: function ( unread ) {
			var api = new mw.Api(), that = this;

			api.post( mw.echo.desktop.appendUseLang( {
				'action' : 'echomarkread',
				'list' : unread.join( '|' ),
				'token': mw.user.tokens.get( 'editToken' )
			} ) ).done( function ( result ) {
				// update the badge if the link is enabled
				if ( result.query.echomarkread.count !== undefined &&
					$( '#pt-notifications').length && typeof mw.echo.overlay === 'object'
				) {
					mw.echo.overlay.updateCount( result.query.echomarkread.count, result.query.echomarkread.rawcount );
				}
				that.onSuccess();
			} ).fail( function () {
				that.onError();
			} );
		},

		onSuccess: function () {
			if ( !this.notcontinue ) {
				$( '#mw-echo-more' ).hide();
			}
			this.processing = false;
		},

		onError: function () {
			// Todo: Show detail error message based on error code
			$( '#mw-echo-more' ).text( mw.msg( 'echo-load-more-error' ) );
			this.processing = false;
		}
	};

	$( document ).ready( mw.echo.special.initialize );

} )( jQuery, mediaWiki );
<commit_msg>New hooks for external integration to notification intiialization<commit_after>( function ( $, mw ) {
	'use strict';

	var isInitialized = false;

	mw.echo.special = {

		notcontinue: null,
		header: '',
		processing: false,

		isInitialized: function() {
			return isInitialized;
		},

		/**
		 * Initialize the property in special notification page.
		 */
		initialize: function () {
			var skin = mw.config.get('skin');

			isInitialized = true;

			// Convert more link into a button
			$( '#mw-echo-more' )
				.addClass( 'mw-ui-button mw-ui-primary' )
				.css( 'margin', '0.5em 0 0 0' )
				.click( function ( e ) {
					e.preventDefault();
					if ( !mw.echo.special.processing ) {
						mw.echo.special.processing = true;
						mw.echo.special.loadMore();
					}
				}
			);
			mw.echo.special.notcontinue = mw.config.get( 'wgEchoNextContinue' );
			mw.echo.special.header = mw.config.get( 'wgEchoDateHeader' );

			// Set up each individual notification with eventlogging, a close
			// box and dismiss interface if it is dismissable.
			$( '.mw-echo-notification' ).each( function () {
				mw.echo.setupNotificationLogging( $( this ), 'archive' );
				if ( $( this ).find( '.mw-echo-dismiss' ).length ) {
					mw.echo.setUpDismissability( this );
				}
			} );

			$( '#mw-echo-moreinfo-link' ).click( function () {
				mw.echo.logInteraction( 'ui-help-click', 'archive' );
			} );
			$( '#mw-echo-pref-link' ).click( function () {
				mw.echo.logInteraction( 'ui-prefs-click', 'archive' );
			} );

			// Convert subtitle links into header icons for Vector and Monobook skins
			if ( skin === 'vector' || skin === 'monobook' ) {
				$( '#mw-echo-moreinfo-link, #mw-echo-pref-link' )
					.empty()
					.appendTo( '#firstHeading' );
				$( '#contentSub' ).empty();
			}

			mw.hook( 'ext.echo.special.onInitialize' ).fire( this );
		},

		/**
		 * Load more notification records.
		 */
		loadMore: function () {
			var api = new mw.Api( { ajax: { cache: false } } ),
				notifications, data, container, $li, that = this, unread = [], apiData;

			apiData = {
				'action' : 'query',
				'meta' : 'notifications',
				'notformat' : 'html',
				'notprop' : 'index|list',
				'notcontinue': this.notcontinue,
				'notlimit': mw.config.get( 'wgEchoDisplayNum' )
			};

			api.get( mw.echo.desktop.appendUseLang( apiData ) ).done( function ( result ) {
				container = $( '#mw-echo-special-container' );
				notifications = result.query.notifications;
				unread = [];

				$.each( notifications.index, function ( index, id ) {
					data = notifications.list[id];

					if ( that.header !== data.timestamp.date ) {
						that.header = data.timestamp.date;
						$( '

' ).addClass( 'mw-echo-date-section' ).append( that.header ).appendTo( container );
					}

					$li = $( '

' )
						.data( 'details', data )
						.data( 'id', id )
						.addClass( 'mw-echo-notification' )
						.attr( {
							'data-notification-category': data.category,
							'data-notification-event': data.id,
							'data-notification-type': data.type
						} )
						.append( data['*'] )
						.appendTo( container );

					if ( !data.read ) {
						$li.addClass( 'mw-echo-unread' );
						unread.push( id );
					}

					mw.hook( 'ext.echo.special.onLoadMore' ).fire( $li, data );
					mw.echo.setupNotificationLogging( $li, 'archive' );

					if ( $li.find( '.mw-echo-dismiss' ).length ) {
						mw.echo.setUpDismissability( $li );
					}
				} );

				that.notcontinue = notifications['continue'];
				if ( unread.length > 0 ) {
					that.markAsRead( unread );
				} else {
					that.onSuccess();
				}
			} ).fail( function () {
				that.onError();
			} );
		},

		/**
		 * Mark notifications as read.
		 */
		markAsRead: function ( unread ) {
			var api = new mw.Api(), that = this;

			api.post( mw.echo.desktop.appendUseLang( {
				'action' : 'echomarkread',
				'list' : unread.join( '|' ),
				'token': mw.user.tokens.get( 'editToken' )
			} ) ).done( function ( result ) {
				// update the badge if the link is enabled
				if ( result.query.echomarkread.count !== undefined &&
					$( '#pt-notifications').length && typeof mw.echo.overlay === 'object'
				) {
					mw.echo.overlay.updateCount( result.query.echomarkread.count, result.query.echomarkread.rawcount );
				}
				that.onSuccess();
			} ).fail( function () {
				that.onError();
			} );
		},

		onSuccess: function () {
			if ( !this.notcontinue ) {
				$( '#mw-echo-more' ).hide();
			}
			this.processing = false;
		},

		onError: function () {
			// Todo: Show detail error message based on error code
			$( '#mw-echo-more' ).text( mw.msg( 'echo-load-more-error' ) );
			this.processing = false;
		}
	};

	$( document ).ready( mw.echo.special.initialize );

} )( jQuery, mediaWiki );
<|endoftext|>


<commit_before>(function (tree) {

tree.Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) {
    this.elements = elements;
    this.extendList = extendList;
    this.condition = condition;
    this.currentFileInfo = currentFileInfo || {};
    this.isReferenced = isReferenced;
    if (!condition) {
        this.evaldCondition = true;
    }
};
tree.Selector.prototype = {
    type: "Selector",
    accept: function (visitor) {
        if (this.elements) {
            this.elements = visitor.visitArray(this.elements);
        }
        if (this.extendList) {
            this.extendList = visitor.visitArray(this.extendList);
        }
        if (this.condition) {
            this.condition = visitor.visit(this.condition);
        }
    },
    createDerived: function(elements, extendList, evaldCondition) {
        evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
        var newSelector = new(tree.Selector)(elements, extendList || this.extendList, this.condition, this.index, this.currentFileInfo, this.isReferenced);
        newSelector.evaldCondition = evaldCondition;
        return newSelector;
    },
    match: function (other) {
        var elements = this.elements,
            len = elements.length,
            oelements, olen, max, i;

        oelements = other.elements.map( function(v) {
            return v.combinator.value + (v.value.value || v.value);
        }).join("").match(/[,&#\.\w-]([\w-]|(\\.))*/g);
        // ^ regexp could be more simple but see test/less/css-escapes.less:17, doh!

        if (!oelements) {
            return 0;
        }

        if (oelements[0] === "&") {
            oelements.shift();
        }

        olen = oelements.length;
        if (olen === 0 || len < olen) {
            return 0;
        } else {
            max = Math.min(len, olen);
            for (i = 0; i < max; i++) {
                if (elements[i].value !== oelements[i]) {
                    return 0;
                }
            }
        }
        return max; // return number of matched elements
    },
    eval: function (env) {
        var evaldCondition = this.condition && this.condition.eval(env),
            elements = this.elements, extendList = this.extendList;

        elements = elements && elements.map(function (e) { return e.eval(env); });
        extendList = extendList && extendList.map(function(extend) { return extend.eval(env); });

        return this.createDerived(elements, extendList, evaldCondition);
    },
    genCSS: function (env, output) {
        var i, element;
        if ((!env || !env.firstSelector) && this.elements[0].combinator.value === "") {
            output.add(' ', this.currentFileInfo, this.index);
        }
        if (!this._css) {
            //TODO caching? speed comparison?
            for(i = 0; i < this.elements.length; i++) {
                element = this.elements[i];
                element.genCSS(env, output);
            }
        }
    },
    toCSS: tree.toCSS,
    markReferenced: function () {
        this.isReferenced = true;
    },
    getIsReferenced: function() {
        return !this.currentFileInfo.reference || this.isReferenced;
    },
    getIsOutput: function() {
        return this.evaldCondition;
    }
};

})(require('../tree'));
<commit_msg>Removed redundant code from tree.Selector.match()<commit_after>(function (tree) {

tree.Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) {
    this.elements = elements;
    this.extendList = extendList;
    this.condition = condition;
    this.currentFileInfo = currentFileInfo || {};
    this.isReferenced = isReferenced;
    if (!condition) {
        this.evaldCondition = true;
    }
};
tree.Selector.prototype = {
    type: "Selector",
    accept: function (visitor) {
        if (this.elements) {
            this.elements = visitor.visitArray(this.elements);
        }
        if (this.extendList) {
            this.extendList = visitor.visitArray(this.extendList);
        }
        if (this.condition) {
            this.condition = visitor.visit(this.condition);
        }
    },
    createDerived: function(elements, extendList, evaldCondition) {
        evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
        var newSelector = new(tree.Selector)(elements, extendList || this.extendList, this.condition, this.index, this.currentFileInfo, this.isReferenced);
        newSelector.evaldCondition = evaldCondition;
        return newSelector;
    },
    match: function (other) {
        var elements = this.elements,
            len = elements.length,
            oelements, olen, i;

        oelements = other.elements.map( function(v) {
            return v.combinator.value + (v.value.value || v.value);
        }).join("").match(/[,&#\.\w-]([\w-]|(\\.))*/g);
        // ^ regexp could be more simple but see test/less/css-escapes.less:17, doh!

        if (!oelements) {
            return 0;
        }

        if (oelements[0] === "&") {
            oelements.shift();
        }

        olen = oelements.length;
        if (olen === 0 || len < olen) {
            return 0;
        } else {
            for (i = 0; i < olen; i++) {
                if (elements[i].value !== oelements[i]) {
                    return 0;
                }
            }
        }
        return olen; // return number of matched elements
    },
    eval: function (env) {
        var evaldCondition = this.condition && this.condition.eval(env),
            elements = this.elements, extendList = this.extendList;

        elements = elements && elements.map(function (e) { return e.eval(env); });
        extendList = extendList && extendList.map(function(extend) { return extend.eval(env); });

        return this.createDerived(elements, extendList, evaldCondition);
    },
    genCSS: function (env, output) {
        var i, element;
        if ((!env || !env.firstSelector) && this.elements[0].combinator.value === "") {
            output.add(' ', this.currentFileInfo, this.index);
        }
        if (!this._css) {
            //TODO caching? speed comparison?
            for(i = 0; i < this.elements.length; i++) {
                element = this.elements[i];
                element.genCSS(env, output);
            }
        }
    },
    toCSS: tree.toCSS,
    markReferenced: function () {
        this.isReferenced = true;
    },
    getIsReferenced: function() {
        return !this.currentFileInfo.reference || this.isReferenced;
    },
    getIsOutput: function() {
        return this.evaldCondition;
    }
};

})(require('../tree'));
<|endoftext|>


<commit_before>// Copyright 2015 Esri
// Licensed under The MIT License(MIT);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//   http://opensource.org/licenses/MIT
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/* eslint-env node */
'use strict';

const fs = require('fs');
const path = require('path');
const Filter = require('broccoli-filter');
const cheerio = require('cheerio');
const beautify_js = require('js-beautify');
const beautify_html = require('js-beautify').html;
const _ = require('lodash');

const replaceRequireAndDefine = require('ember-cli-amd/lib/replace-require-and-define');

const amdLoadingTemplate = _.template(fs.readFileSync(path.join(__dirname, 'amd-loading.txt'), 'utf8'));
const indexFiles = ['index.html', 'tests/index.html'];

// Class for replacing, in the generated code, the AMD protected keyword 'require' and 'define'.
// We are replacing these keywords by non conflicting words.
// It uses the broccoli filter to go thru the different files (as string).
module.exports = class ConvertToAMD extends Filter {
  constructor(app, inputTree, options = {}) {
    super(inputTree, options);

    this.extensions = ['js', 'html'];

    // Options for the process
    this.loader = app.options.amd.loader;
    this.amdPackages = app.options.amd.packages || [];
    this.excludePaths = app.options.amd.excludePaths;
    this.loadingFilePath = app.options.amd.loadingFilePath || 'assets';
    this.rootURL = app.project.config(app.env).rootURL;

    // Because the filter is call for partial rebuild during 'ember serve', we need to
    // know what was added/removed for a partial build
    this.externalAmdModules = new Set();
    this.externalAmdModulesCache = new Map();

    // There are two index files that should be converted:
    // - index.html
    // - tests/index.html
    // We need to keep things separated as they don't load the same script set.
    this.indexHtmlCaches = {
      'index.html': {
        scriptsToLoad: [],
        loadingScript: path.join(this.rootURL, this.loadingFilePath, 'amd-loading.js'),
        afterLoadingScript: path.join(this.rootURL, this.loadingFilePath, 'after-amd-loading.js')
      },
      'tests/index.html': {
        scriptsToLoad: [],
        loadingScript: path.join(this.rootURL, 'tests/amd-loading.js'),
        afterLoadingScript: path.join(this.rootURL, 'tests/after-amd-loading.js')
      }
    };
  }

  getDestFilePath(relativePath) {
    relativePath = super.getDestFilePath(relativePath);
    if (!relativePath) {
      return null;
    }

    if (relativePath.indexOf('index.html') >= 0) {
      return relativePath;
    }

    for (let i = 0, len = this.excludePaths.length; i < len; i++) {
      if (relativePath.indexOf(this.excludePaths[i]) === 0) {
        return null;
      }
    }

    if (relativePath.indexOf('.js') >= 0) {
      return relativePath;
    }

    return null;
  }

  processString(code, relativePath) {
    if (relativePath.indexOf('.js') >= 0) {
      return this._processJsFile(code, relativePath);
    }

    return this._processIndexFile(code, relativePath);
  }

  _processIndexFile(code, relativePath) {

    const cheerioQuery = cheerio.load(code);

    // Get the collection of scripts
    // Scripts that have a 'src' will be loaded by AMD
    // Scripts that have a body will be assembled into a post loading file and loaded at the end of the AMD loading process
    const scriptElements = cheerioQuery('body > script');
    const scriptsToLoad = [];
    const inlineScripts = [];
    scriptElements.each(function () {
      if (cheerioQuery(this).attr('src')) {
        scriptsToLoad.push(`"${cheerioQuery(this).attr('src')}"`);
      } else {
        inlineScripts.push(cheerioQuery(this).html());
      }
    });

    this.indexHtmlCaches[relativePath].scriptsToLoad = scriptsToLoad;

    // If we have inline scripts, we will save them into a script file and load it as part of the amd loading
    if (inlineScripts.length > 0) {
      const afterLoadingScript = replaceRequireAndDefine(inlineScripts.join('\n\n'));
      fs.writeFileSync(path.join(this.outputPath, this.indexHtmlCaches[relativePath].afterLoadingScript), beautify_js(afterLoadingScript, {
        indent_size: 2,
        max_preserve_newlines: 1
      }));
      scriptsToLoad.push(`"${this.indexHtmlCaches[relativePath].afterLoadingScript}"`);
    }

    // Replace the original ember scripts by the amd ones
    scriptElements.remove();
    const amdScripts = [
      `<script src="${this.loader}" data-amd=true></script>`,
      `<script src="${this.indexHtmlCaches[relativePath].loadingScript}" data-amd-loading=true></script>`
    ];
    cheerioQuery('body').prepend(amdScripts.join('\n'));

    // Beautify the index.html
    return beautify_html(cheerioQuery.html(), {
      indent_size: 2,
      max_preserve_newlines: 0
    });
  }

  _processJsFile(code, relativePath) {

    const externalAmdModulesForFile = new Set();
    const modifiedSource = replaceRequireAndDefine(code, this.amdPackages, externalAmdModulesForFile);

    // Bookkeeping of what has changed for this file compared to previous builds
    if (externalAmdModulesForFile.size === 0) {
      // No more AMD references
      this.externalAmdModulesCache.delete(relativePath);
    } else {
      // Replace with the new set
      this.externalAmdModulesCache.set(relativePath, externalAmdModulesForFile);
    }

    return modifiedSource;
  }

  _buildModuleInfos() {

    // Build different arrays representing the modules for the injection in the start script
    const objs = [];
    const names = [];
    const adoptables = [];
    let index = 0;
    this.externalAmdModules.forEach((externalAmdModule) => {
      objs.push(`mod${index}`);
      names.push(`'${externalAmdModule}'`);
      adoptables.push(`{name:'${externalAmdModule}',obj:mod${index}}`);
      index++;
    });

    return {
      names: names.join(','),
      objects: objs.join(','),
      adoptables: adoptables.join(',')
    };
  }

  async build() {

    // Cache the previous state
    let moduleInfos = this._buildModuleInfos();
    const names = moduleInfos.names;

    const scripts = indexFiles.reduce((scripts, indexFile) => {
      scripts[indexFile] = this.indexHtmlCaches[indexFile].scriptsToLoad.join(',');
      return scripts;
    }, {});

    // Clear before each build since the filter is kept by ember-cli during 'ember serve'
    // and being reused without going thru postProcessTree. If we don't clean we may get
    // previous modules.
    this.externalAmdModules.clear();

    const result = await super.build();

    // Re-assemble the external AMD modules set with the updated cache
    this.externalAmdModulesCache.forEach(externalAmdModules => {
      externalAmdModules.forEach(externalAmdModule => {
        this.externalAmdModules.add(externalAmdModule);
      });
    });

    // Check if we have a new set of amd modules or a new set of scripts to load.
    // If we have then we need to rebuild the amd loading script
    moduleInfos = this._buildModuleInfos();

    indexFiles.forEach(indexFile => {

      const newScripts = this.indexHtmlCaches[indexFile].scriptsToLoad.join(',');
      if (names !== moduleInfos.names || scripts !== newScripts) {

        const loadingScript = amdLoadingTemplate(_.assign(moduleInfos, {
          scripts: newScripts
        }));

        fs.writeFileSync(path.join(this.outputPath, this.indexHtmlCaches[indexFile].loadingScript), beautify_js(loadingScript, {
          indent_size: 2,
          max_preserve_newlines: 1
        }));
      }

    });

    return result;
  }
}<commit_msg>small fix<commit_after>// Copyright 2015 Esri
// Licensed under The MIT License(MIT);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//   http://opensource.org/licenses/MIT
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/* eslint-env node */
'use strict';

const fs = require('fs');
const path = require('path');
const Filter = require('broccoli-filter');
const cheerio = require('cheerio');
const beautify_js = require('js-beautify');
const beautify_html = require('js-beautify').html;
const _ = require('lodash');

const replaceRequireAndDefine = require('ember-cli-amd/lib/replace-require-and-define');

const amdLoadingTemplate = _.template(fs.readFileSync(path.join(__dirname, 'amd-loading.txt'), 'utf8'));
const indexFiles = ['index.html', 'tests/index.html'];

// Class for replacing, in the generated code, the AMD protected keyword 'require' and 'define'.
// We are replacing these keywords by non conflicting words.
// It uses the broccoli filter to go thru the different files (as string).
module.exports = class ConvertToAMD extends Filter {
  constructor(app, inputTree, options = {}) {
    super(inputTree, options);

    this.extensions = ['js', 'html'];

    // Options for the process
    this.loader = app.options.amd.loader;
    this.amdPackages = app.options.amd.packages || [];
    this.excludePaths = app.options.amd.excludePaths;
    this.loadingFilePath = app.options.amd.loadingFilePath || 'assets';
    this.rootURL = app.project.config(app.env).rootURL;

    // Because the filter is call for partial rebuild during 'ember serve', we need to
    // know what was added/removed for a partial build
    this.externalAmdModules = new Set();
    this.externalAmdModulesCache = new Map();

    // There are two index files that should be converted:
    // - index.html
    // - tests/index.html
    // We need to keep things separated as they don't load the same script set.
    this.indexHtmlCaches = {
      'index.html': {
        scriptsToLoad: [],
        loadingScript: path.join(this.rootURL, this.loadingFilePath, 'amd-loading.js'),
        afterLoadingScript: path.join(this.rootURL, this.loadingFilePath, 'after-amd-loading.js')
      },
      'tests/index.html': {
        scriptsToLoad: [],
        loadingScript: path.join(this.rootURL, this.loadingFilePath, 'amd-loading-tests.js'),
        afterLoadingScript: path.join(this.rootURL, this.loadingFilePath, 'after-amd-loading-tests.js')
      }
    };
  }

  getDestFilePath(relativePath) {
    relativePath = super.getDestFilePath(relativePath);
    if (!relativePath) {
      return null;
    }

    if (relativePath.indexOf('index.html') >= 0) {
      return relativePath;
    }

    for (let i = 0, len = this.excludePaths.length; i < len; i++) {
      if (relativePath.indexOf(this.excludePaths[i]) === 0) {
        return null;
      }
    }

    if (relativePath.indexOf('.js') >= 0) {
      return relativePath;
    }

    return null;
  }

  processString(code, relativePath) {
    if (relativePath.indexOf('.js') >= 0) {
      return this._processJsFile(code, relativePath);
    }

    return this._processIndexFile(code, relativePath);
  }

  _processIndexFile(code, relativePath) {

    const cheerioQuery = cheerio.load(code);

    // Get the collection of scripts
    // Scripts that have a 'src' will be loaded by AMD
    // Scripts that have a body will be assembled into a post loading file and loaded at the end of the AMD loading process
    const scriptElements = cheerioQuery('body > script');
    const scriptsToLoad = [];
    const inlineScripts = [];
    scriptElements.each(function () {
      if (cheerioQuery(this).attr('src')) {
        scriptsToLoad.push(`"${cheerioQuery(this).attr('src')}"`);
      } else {
        inlineScripts.push(cheerioQuery(this).html());
      }
    });

    this.indexHtmlCaches[relativePath].scriptsToLoad = scriptsToLoad;

    // If we have inline scripts, we will save them into a script file and load it as part of the amd loading
    if (inlineScripts.length > 0) {
      const afterLoadingScript = replaceRequireAndDefine(inlineScripts.join('\n\n'));
      fs.writeFileSync(path.join(this.outputPath, this.indexHtmlCaches[relativePath].afterLoadingScript), beautify_js(afterLoadingScript, {
        indent_size: 2,
        max_preserve_newlines: 1
      }));
      scriptsToLoad.push(`"${this.indexHtmlCaches[relativePath].afterLoadingScript}"`);
    }

    // Replace the original ember scripts by the amd ones
    scriptElements.remove();
    const amdScripts = [
      `<script src="${this.loader}" data-amd=true></script>`,
      `<script src="${this.indexHtmlCaches[relativePath].loadingScript}" data-amd-loading=true></script>`
    ];
    cheerioQuery('body').prepend(amdScripts.join('\n'));

    // Beautify the index.html
    return beautify_html(cheerioQuery.html(), {
      indent_size: 2,
      max_preserve_newlines: 0
    });
  }

  _processJsFile(code, relativePath) {

    const externalAmdModulesForFile = new Set();
    const modifiedSource = replaceRequireAndDefine(code, this.amdPackages, externalAmdModulesForFile);

    // Bookkeeping of what has changed for this file compared to previous builds
    if (externalAmdModulesForFile.size === 0) {
      // No more AMD references
      this.externalAmdModulesCache.delete(relativePath);
    } else {
      // Replace with the new set
      this.externalAmdModulesCache.set(relativePath, externalAmdModulesForFile);
    }

    return modifiedSource;
  }

  _buildModuleInfos() {

    // Build different arrays representing the modules for the injection in the start script
    const objs = [];
    const names = [];
    const adoptables = [];
    let index = 0;
    this.externalAmdModules.forEach((externalAmdModule) => {
      objs.push(`mod${index}`);
      names.push(`'${externalAmdModule}'`);
      adoptables.push(`{name:'${externalAmdModule}',obj:mod${index}}`);
      index++;
    });

    return {
      names: names.join(','),
      objects: objs.join(','),
      adoptables: adoptables.join(',')
    };
  }

  async build() {

    // Cache the previous state
    let moduleInfos = this._buildModuleInfos();
    const names = moduleInfos.names;

    const scripts = indexFiles.reduce((scripts, indexFile) => {
      scripts[indexFile] = this.indexHtmlCaches[indexFile].scriptsToLoad.join(',');
      return scripts;
    }, {});

    // Clear before each build since the filter is kept by ember-cli during 'ember serve'
    // and being reused without going thru postProcessTree. If we don't clean we may get
    // previous modules.
    this.externalAmdModules.clear();

    const result = await super.build();

    // Re-assemble the external AMD modules set with the updated cache
    this.externalAmdModulesCache.forEach(externalAmdModules => {
      externalAmdModules.forEach(externalAmdModule => {
        this.externalAmdModules.add(externalAmdModule);
      });
    });

    // Check if we have a new set of amd modules or a new set of scripts to load.
    // If we have then we need to rebuild the amd loading script
    moduleInfos = this._buildModuleInfos();

    indexFiles.forEach(indexFile => {

      const newScripts = this.indexHtmlCaches[indexFile].scriptsToLoad.join(',');
      if (names !== moduleInfos.names || scripts !== newScripts) {

        const loadingScript = amdLoadingTemplate(_.assign(moduleInfos, {
          scripts: newScripts
        }));

        fs.writeFileSync(path.join(this.outputPath, this.indexHtmlCaches[indexFile].loadingScript), beautify_js(loadingScript, {
          indent_size: 2,
          max_preserve_newlines: 1
        }));
      }

    });

    return result;
  }
}<|endoftext|>


<commit_before>/**
 * Angular Directives For Accessible User Interface Widgets
 *
 * Copyright (C) Ian Kelly 2013-4
 */

'use strict';

(function() {

	var angularAccessibility = angular.module('angular-accessibility', []);

	/**
	* Directive for accessible forms
	*/
	angularAccessibility.directive('accessibleForm', function ($log) {
		return {
			retrict: 'A',
			link: function (scope, elem, attr, ctrl) {

				// it must have a name attribute
				if (!attr.name) {
					$log.error('accessibleForm must have a name attribute');
					return;
				}

				// the form is found on the scope by
				// its name property
				var form = scope[attr.name];

				// add a function that can focus the first element
				// to the scope, it might be useful elsewhere
				scope.focusFirst = function() {
					// makes use of the fact that the inputs
					// are in the order they appear on the page
					for (var key in form) {
						if (form.hasOwnProperty(key) && key.indexOf('$') !== 0) {
							var input = form[key];
							if (input.$invalid) {
								if (input.focus) {
									input.focus();
								}
								return true;
							}
						}
					}
					return false;
				};

				// handle the submit event
				elem.on('submit', function(e) {
					if (scope.focusFirst()) {
						e.preventDefault();
					}
				});
			}
		};
	});

	/**
	* Directive for an accessible checkbox
	*/
	angularAccessibility.directive('aCheckbox', function ($log, $compile) {
		return {
			restrict: 'E',
			requires: '^accessibleForm',
			template: ['<fieldset class="form-group">',
				'

',
				'',
				'
',
				'<input type="checkbox" class="form-control"></input>',
				'
',
				'</fieldset>'].join(''),
			link: function (scope, aCheckbox, attributes) {
				/* jshint maxstatements: 50 */

				var eLabel, eHelp, eInput, eFieldset, children, id;

				// the fieldset - should be the only child
				eFieldset = aCheckbox.children().eq(0);
				// the help and label
				children = eFieldset.children();
				eHelp = children.eq(0);
				eLabel = children.eq(1);
				// the input
				eInput = children.eq(2).children().eq(0);

				// get the id of the input
				id = attributes.id + '-checkbox';

				// set the help div up
				eHelp.attr('id', id + '-help');
				eHelp.text(attributes.help);

				// set the label up
				eLabel.attr('for', id);
				eLabel.text(attributes.label);

				// se the input up
				eInput.attr('id', id);
				eInput.attr('aria-describedby', id + '-help');
				eInput.attr('ng-model', attributes['ng-model']);

				// replace the input with the new fieldset
				aCheckbox.replaceWith(eFieldset);

				// recompile the created markup
				$compile(eFieldset)(scope);
			}
		};
	});

	/**
	* Directive for an Accessible Checbox Group  Element
	*/

	angularAccessibility.directive('aChecklist', function ($compile, $log) {
		return {
			// this is an element defintion
			restrict: 'E',
			// it must be contained in an accessible form
			requires: '^accessibleForm',
			// the template
			template: ['<fieldset class="form-group">',
				'<legend class="col-sm-3 control-label horizontal"></legend>',
				'
',
				'
',
				'',
				'<input type="checkbox"></input>',
				'',
				'

',
				'</fieldset>'].join(''),
			// converts the template to the final state
			link: function (scope, aInput, attributes) {
				/* jshint maxstatements: 50 */

				var eLegend, eLabel, eRepeat, eInput, eFieldset, name;

				// @todo - consider reverting this to jqLite
				eFieldset = aInput.children('fieldset');
				eLegend = eFieldset.children('legend');
				eRepeat = eFieldset.find('div.checkbox');
				eLabel =  eRepeat.children('label');
				eInput = eLabel.children('input');

				// iterate over all the attributes of the a-checkboxgroup
				// and assign them to the appropriate part of the template
				for (name in attributes.$attr) {
					if (attributes.$attr.hasOwnProperty(name)) {
						switch (name) {
						case 'legend':
							eLegend.text(attributes.legend);
							break;
						case 'label':
							eLabel.prepend('{{' + attributes.label + '}}');
							break;
						case 'repeat':
							eRepeat.attr('ng-repeat', attributes.repeat);
							break;
						case 'modelArray':
							eInput.attr('checklist-model', attributes.modelArray);
							break;
						case 'modelValue':
							eInput.attr('checklist-value', attributes.modelValue);
							break;
						default:
							// by default move the attribute to the input
							eInput.attr(attributes.$attr[name], attributes[name]);
							break;
						}
					}
				}

				// replace the input with the new fieldset
				aInput.replaceWith(eFieldset);

				// recompile the created markup
				// to expand the repeat and apply any other directives
				$compile(eFieldset)(scope);
			}
		};
	});

	/**
	* Directive for an Accessible Input  Element
	*/
	angularAccessibility.directive('aInput', function ($compile) {
		return {
			// this is an element defintion
			restrict: 'E',
			// it must be contained in an accessible form
			requires: '^accessibleForm',
			// the template
			template: ['<fieldset class="form-group">',
				'

',
				'

',
				'',
				'
',
				'<input blur-focus class="form-control"></input>',
				'
',
				'</fieldset>'].join(''),
			// converts the template to the final state
			link: function (scope, aInput, attributes) {
				/* jshint maxstatements: 50 */

				var eLabel, eHelp, eError, eInput, inputName,
					eFieldset, name, children, attributeName, formName, id;

				// the fieldset - should be the only child
				eFieldset = aInput.children().eq(0);
				// the help, error and label
				children = eFieldset.children();
				eHelp = children.eq(0);
				eError = children.eq(1);
				eLabel = children.eq(2);
				eInput = children.eq(3).children().eq(0);

				// iterate over all the attributes of the a-input
				// and assign them to the appropriate part of the template
				for (name in attributes.$attr) {
					if (attributes.$attr.hasOwnProperty(name)) {
						attributeName = attributes.$attr[name];
						switch (name) {
						case 'id':
							id = attributes.id + '-input';
							eHelp.attr('id', id + '-help');
							eError.attr('id', id + '-error');
							eInput.attr('id', id);
							eLabel.attr('for', id);
							break;
						case 'help':
							// set the help text
							eHelp.text(attributes[name]);
							break;
						case 'error':
							// set the help text
							eError.text(attributes[name]);
							break;
						case 'label':
							// set the help text
							eLabel.text(attributes[name]);
							break;
						case 'required':
							eInput.attr('required', 'true');
							eInput.attr('aria-required', 'true');
							break;
						default:
							// by default move the attribute to the input
							eInput.attr(attributeName, attributes[name]);
							break;
						}
						//aInput.removeAttr(attributeName);
					}
				}

				// find the accessible form name
				formName = aInput.closest('form').attr('name');
				inputName = formName + '.' + eInput.attr('name');
				// set up the validation failures
				eFieldset.attr('ng-class',
					'{\'has-error\': ' + inputName + '.failsValidation()}');
				eError.attr('ng-show', inputName + '.failsValidation()');
				eInput.attr('aria-invalid', '{{' + inputName + '.failsValidation()}}');
				eInput.attr('aria-describedby',
					eHelp.attr('id') + ' {{' + inputName + '.validationId()}}');
				eInput.attr('error-id', eError.attr('id'));

				// replace the input with the new fieldset
				aInput.replaceWith(eFieldset);

				// recompile the created markup - to apply blur-focus to the input
				$compile(eFieldset)(scope);
			}
		};
	});

	/**
	* Directive for an Accessible Input  Element
	*/
	angularAccessibility.directive('aSelect', function ($compile) {
		return {
			// this is an element defintion
			restrict: 'E',
			// it must be contained in an accessible form
			requires: '^accessibleForm',
			// the template
			template: ['<fieldset class="form-group">',
				'

',
				'

',
				'',
				'
',
				'<select blur-focus class="form-control"></input>',
				'
',
				'</fieldset>'].join(''),
			// converts the template to the final state
			link: function (scope, aSelect, attributes) {
				/* jshint maxstatements: 50 */

				var eLabel, eHelp, eError, eSelect, inputName,
					eFieldset, name, children, attributeName, formName, id;

				// the fieldset - should be the only child
				eFieldset = aSelect.children().eq(0);
				// the help, error and label
				children = eFieldset.children();
				eHelp = children.eq(0);
				eError = children.eq(1);
				eLabel = children.eq(2);
				eSelect = children.eq(3).children().eq(0);

				// iterate over all the attributes of the a-input
				// and assign them to the appropriate part of the template
				for (name in attributes.$attr) {
					if (attributes.$attr.hasOwnProperty(name)) {
						attributeName = attributes.$attr[name];
						switch (name) {
						case 'id':
							id = attributes.id + '-input';
							eHelp.attr('id', id + '-help');
							eError.attr('id', id + '-error');
							eSelect.attr('id', id);
							eLabel.attr('for', id);
							break;
						case 'help':
							// set the help text
							eHelp.text(attributes[name]);
							break;
						case 'error':
							// set the help text
							eError.text(attributes[name]);
							break;
						case 'label':
							// set the help text
							eLabel.text(attributes[name]);
							break;
						case 'required':
							eSelect.attr('required', 'true');
							eSelect.attr('aria-required', 'true');
							break;
						default:
							// by default move the attribute to the input
							eSelect.attr(attributeName, attributes[name]);
							break;
						}
					}
				}

				// find the accessible form name
				formName = aSelect.closest('form').attr('name');
				inputName = formName + '.' + eSelect.attr('name');
				// set up the validation failures
				eFieldset.attr('ng-class',
					'{\'has-error\': ' + inputName + '.failsValidation()}');
				eError.attr('ng-show', inputName + '.failsValidation()');
				eSelect.attr('aria-invalid', '{{' + inputName + '.failsValidation()}}');
				eSelect.attr('aria-describedby',
					eHelp.attr('id') + ' {{' + inputName + '.validationId()}}');
				eSelect.attr('error-id', eError.attr('id'));

				// replace the input with the new fieldset
				aSelect.replaceWith(eFieldset);

				// recompile the created markup - to apply blur-focus to the input
				$compile(eFieldset)(scope);
			}
		};
	});

	/**
	* Directive to detect visited state of all input fields
	*/
	angularAccessibility.directive('blurFocus', function ($log) {
		return {
			require: '?ngModel',
			link: function (scope, element, attrs, ctrl) {

				$log.log('wohoo');
				$log.log(ctrl);

				if (!ctrl) {
					return;
				}

				// this stops it applying to checkboxes
				if (element.attr('type') === 'checkbox') {
					return;
				}

				/**
				* Focuses the element of this input
				*/
				ctrl.focus = function () {
					element.focus();
				};

				/**
				* Whether the control fails validation
				* @return {Boolean} True = fails validation
				*/
				ctrl.failsValidation = function () {
					return !!ctrl.hasVisited && !!ctrl.$invalid;
				};

				/**
				* The ID of a validation error element
				* @return {String} Falsy = no validation message
				*                  String = ID of validation message
				*/
				ctrl.validationId = function () {
					if (ctrl.failsValidation()) {
						return element.attr('error-id');
					}
				};

				// on focus note that
				element.on('focus', function () {
					element.addClass('has-focus');

					scope.$apply(function () {
						ctrl.hasFocus = true;
					});
				});

				// on blur apply the had visited property
				element.on('blur', function () {
					$log.log('blur');
					element.removeClass('has-focus');
					element.addClass('has-visited');

					scope.$apply(function () {
						ctrl.hasFocus = false;
						ctrl.hasVisited = true;
					});
				});

				// if the form submits - assume we've visted all the fields
				element.closest('form').on('submit', function () {
					element.addClass('has-visited');

					scope.$apply(function () {
						ctrl.hasFocus = false;
						ctrl.hasVisited = true;
					});
				});
			}
		};
	});

})();
<commit_msg>Add flexible classes to templates<commit_after>/**
 * Angular Directives For Accessible User Interface Widgets
 *
 * Copyright (C) Ian Kelly 2013-4
 */

'use strict';

(function() {

	var angularAccessibility = angular.module('angular-accessibility', []);

	/**
	 * Constants
	 */
	angularAccessibility.constant('MODULE_VERSION', '0.0.0');

	/**
	 * Simple implementation of closest
	 *
	 * @param  {String} name	The name of the tag to find
	 * @return {Object|Boolean} The parent element with that name, or false
	 */
	angular.element.prototype.closest = function (name) {

		var cur, tagName;

		name = name.toUpperCase();

		for (cur = this; cur; cur = cur.parent()) {
			tagName = cur.prop('tagName');
			if (tagName === 'BODY') {
				break;
			}
			if (tagName === name) {
				return cur;
			}
		}

		return false;
	};

	/**
	* Directive for accessible forms
	*/
	angularAccessibility.directive('accessibleForm', function ($log) {
		return {
			retrict: 'A',
			link: function (scope, elem, attr, ctrl) {

				// it must have a name attribute
				if (!attr.name) {
					$log.error('accessibleForm must have a name attribute');
					return;
				}

				// the form is found on the scope by
				// its name property
				var form = scope[attr.name];

				// add a function that can focus the first element
				// to the scope, it might be useful elsewhere
				scope.focusFirst = function() {
					// makes use of the fact that the inputs
					// are in the order they appear on the page
					for (var key in form) {
						if (form.hasOwnProperty(key) && key.indexOf('$') !== 0) {
							var input = form[key];
							if (input.$invalid) {
								if (input.focus) {
									input.focus();
								}
								return true;
							}
						}
					}
					return false;
				};

				// handle the submit event
				elem.on('submit', function(e) {
					if (scope.focusFirst()) {
						e.preventDefault();
					}
				});
			}
		};
	});

	/**
	* Directive for an accessible checkbox
	*/
	angularAccessibility.directive('aCheckbox', function ($log, $compile) {
		return {
			restrict: 'E',
			requires: '^accessibleForm',
			template: ['<fieldset class="aa-fieldset">',
							'

',
							'',
							'
',
								'<input type="checkbox" class="aa-input"></input>',
							'
',
						'</fieldset>'].join(''),
			link: function (scope, aCheckbox, attributes) {
				/* jshint maxstatements: 20 */

				var eFieldset = aCheckbox.children().eq(0);
				var children = eFieldset.children();
				var eHelp = children.eq(0);
				var eLabel = children.eq(1);
				var eInputWrap = children.eq(2);
				var eInput = eInputWrap.children().eq(0);

				// get the id of the input
				var id = attributes.id + '-checkbox';

				// set the fieldset up
				eFieldset.addClass(attributes.classFieldset);

				// set the help div up
				eHelp.attr('id', id + '-help');
				eHelp.text(attributes.help);

				// set the label up
				eLabel.attr('for', id);
				eLabel.text(attributes.label);
				eLabel.addClass(attributes.classLabel);

				// set the input up
				eInput.attr('id', id);
				eInput.attr('aria-describedby', id + '-help');
				eInput.attr('ng-model', attributes['ng-model']);
				eInput.addClass(attributes.class);
				eInputWrap.addClass(attributes.classInputwrap);

				// replace the input with the new fieldset
				aCheckbox.replaceWith(eFieldset);

				// recompile the created markup
				$compile(eFieldset)(scope);
			}
		};
	});

	/**
	* Directive for an Accessible Checbox Group  Element
	*/

	angularAccessibility.directive('aChecklist', function ($compile, $log) {
		return {
			// this is an element defintion
			restrict: 'E',
			// it must be contained in an accessible form
			requires: '^accessibleForm',
			// the template
			template: ['<fieldset class="aa-fieldset">',
							'<legend class="aa-legend"></legend>',
							'
',
								'
',
									'<input type="checkbox" class="aa-checkbox-input"></input>',
									'',
								'
',
							'
',
						'</fieldset>'].join(''),
			// converts the template to the final state
			link: function (scope, aInput, attributes) {
				/* jshint maxstatements: 20 */

				var eFieldset = aInput.children().eq(0);
				var children = eFieldset.children();
				var eLegend = children.eq(0);
				var eCheckboxGroup = children.eq(1);
				var eCheckbox = eCheckboxGroup.children().eq(0);
				children = eCheckbox.children();
				var eInput = children.eq(0);
				var eLabel =  children.eq(1);

				// iterate over all the attributes of the a-checkboxgroup
				// and assign them to the appropriate part of the template
				for (var name in attributes.$attr) {
					if (attributes.$attr.hasOwnProperty(name)) {
						switch (name) {
						case 'id':
							eInput.attr('id', attributes.id);
							eLabel.attr('for', attributes.id); break;
						case 'legend':
							eLegend.text(attributes.legend); break;
						case 'label':
							eLabel.text('{{' + attributes.label + '}}'); break;
						case 'repeat':
							eCheckbox.attr('ng-repeat', attributes.repeat); break;
						case 'modelArray':
							eInput.attr('checklist-model', attributes.modelArray); break;
						case 'modelValue':
							eInput.attr('checklist-value', attributes.modelValue); break;
						case 'classFieldset':
							eFieldset.addClass(attributes.classFieldset); break;
						case 'classLegend':
							eLegend.addClass(attributes.classLegend); break;
						case 'classCheckboxGroup':
							eCheckboxGroup.addClass(attributes.classCheckboxGroup); break;
						case 'classCheckbox':
							eCheckbox.addClass(attributes.classCheckbox); break;
						case 'classLabel':
							eLabel.addClass(attributes.classLabel); break;
						case 'class':
							eInput.addClass(attributes.class); break;
						default:
							// by default move the attribute to the input
							eInput.attr(attributes.$attr[name], attributes[name]); break;
						}
					}
				}

				// replace the input with the new fieldset
				aInput.replaceWith(eFieldset);

				// recompile the created markup
				// to expand the repeat and apply any other directives
				$compile(eFieldset)(scope);
			}
		};
	});

	/**
	* Directive for an Accessible Input  Element
	*/
	angularAccessibility.directive('aInput', function ($compile) {
		return {
			// this is an element defintion
			restrict: 'E',
			// it must be contained in an accessible form
			requires: '^accessibleForm',
			// the template
			template: ['<fieldset class="aa-fieldset">',
							'

',
							'

',
							'',
							'
',
								'<input class="aa-input" blur-focus></input>',
							'
',
						'</fieldset>'].join(''),
			// converts the template to the final state
			link: function (scope, aInput, attributes) {
				/* jshint maxstatements: 21 */

				var eFieldset = aInput.children().eq(0);
				var children = eFieldset.children();
				var eHelp = children.eq(0);
				var eError = children.eq(1);
				var eLabel = children.eq(2);
				var eInputWrapper = children.eq(3);
				var eInput = eInputWrapper.children().eq(0);

				// iterate over all the attributes of the a-input
				// and assign them to the appropriate part of the template
				for (var name in attributes.$attr) {
					if (attributes.$attr.hasOwnProperty(name)) {
						switch (name) {
						case 'id':
							var id = attributes.id + '-input';
							eHelp.attr('id', id + '-help');
							eError.attr('id', id + '-error');
							eInput.attr('id', id);
							eLabel.attr('for', id); break;
						case 'help':
							eHelp.text(attributes.help); break;
						case 'error':
							eError.text(attributes.error); break;
						case 'label':
							eLabel.text(attributes.label);break;
						case 'required':
							eInput.attr('required', 'true');
							eInput.attr('aria-required', 'true'); break;
						case 'classInputwrap':
							eInputWrapper.addClass(attributes.classInputwrap); break;
						case 'classLabel':
							eLabel.addClass(attributes.classLabel); break;
						case 'classError':
							eError.addClass(attributes.classError); break;
						case 'classFieldset':
							eFieldset.addClass(attributes.classFieldset); break;
						case 'class':
							eInput.addClass(attributes.class); break;
						default:
							// by default move the attribute to the input
							eInput.attr(attributes.$attr[name], attributes[name]);
						}
					}
				}

				// find the accessible form name
				var formName = aInput.closest('form').attr('name');
				var inputName = formName + '.' + eInput.attr('name');
				// set up the validation failures
				eFieldset.attr('ng-class',
					'{\'has-error\': ' + inputName + '.failsValidation()}');
				eError.attr('ng-show', inputName + '.failsValidation()');
				eInput.attr('aria-invalid', '{{' + inputName + '.failsValidation()}}');
				eInput.attr('aria-describedby',
					eHelp.attr('id') + ' {{' + inputName + '.validationId()}}');
				eInput.attr('error-id', eError.attr('id'));

				// replace the input with the new fieldset
				aInput.replaceWith(eFieldset);

				// recompile the created markup - to apply blur-focus to the input
				$compile(eFieldset)(scope);
			}
		};
	});

	/**
	* Directive for an Accessible Input  Element
	*/
	angularAccessibility.directive('aSelect', function ($compile) {
		return {
			// this is an element defintion
			restrict: 'E',
			// it must be contained in an accessible form
			requires: '^accessibleForm',
			// the template
			template: ['<fieldset class="aa-fieldset">',
							'

',
							'

',
							'',
							'
',
								'<select blur-focus class="aa-select"></input>',
							'
',
						'</fieldset>'].join(''),
			link: function (scope, aSelect, attributes) {
				/* jshint maxstatements: 20 */

				// the fieldset - should be the only child
				var eFieldset = aSelect.children().eq(0);
				// the help, error and label
				var children = eFieldset.children();
				var eHelp = children.eq(0);
				var eError = children.eq(1);
				var eLabel = children.eq(2);
				var eSelectwrap = children.eq(3);
				var eSelect = eSelectwrap.children().eq(0);

				// iterate over all the attributes of the a-input
				// and assign them to the appropriate part of the template
				for (var name in attributes.$attr) {
					if (attributes.$attr.hasOwnProperty(name)) {
						switch (name) {
						case 'id':
							var id = attributes.id + '-input';
							eHelp.attr('id', id + '-help');
							eError.attr('id', id + '-error');
							eSelect.attr('id', id);
							eLabel.attr('for', id); break;
						case 'help':
							eHelp.text(attributes.help); break;
						case 'error':
							eError.text(attributes.error); break;
						case 'label':
							eLabel.text(attributes.label); break;
						case 'required':
							eSelect.attr('required', 'true');
							eSelect.attr('aria-required', 'true'); break;
						case 'classFieldset':
							eFieldset.addClass(attributes.classFieldset); break;
						case 'classError':
							eError.addClass(attributes.classError); break;
						case 'classSelectwrap':
							eSelectwrap.addClass(attributes.classSelectwrap); break;
						case 'classLabel':
							eLabel.addClass(attributes.classLabel); break;
						case 'class':
							eSelect.addClass(attributes.class); break;
						default:
							// by default move the attribute to the input
							eSelect.attr(attributes.$attr[name], attributes[name]);
						}
					}
				}

				// find the accessible form name
				var formName = aSelect.closest('form').attr('name');
				var inputName = formName + '.' + eSelect.attr('name');
				// set up the validation failures
				eFieldset.attr('ng-class',
					'{\'has-error\': ' + inputName + '.failsValidation()}');
				eError.attr('ng-show', inputName + '.failsValidation()');
				eSelect.attr('aria-invalid', '{{' + inputName + '.failsValidation()}}');
				eSelect.attr('aria-describedby',
					eHelp.attr('id') + ' {{' + inputName + '.validationId()}}');
				eSelect.attr('error-id', eError.attr('id'));

				// replace the input with the new fieldset
				aSelect.replaceWith(eFieldset);

				// recompile the created markup - to apply blur-focus to the input
				$compile(eFieldset)(scope);
			}
		};
	});

	/**
	* Directive to detect visited state of all input fields
	*/
	angularAccessibility.directive('blurFocus', function ($log) {
		return {
			require: '?ngModel',
			link: function (scope, element, attrs, ctrl) {

				if (!ctrl) {
					return;
				}

				/**
				* Focuses the element of this input
				*/
				ctrl.focus = function () {
					element.focus();
				};

				/**
				* Whether the control fails validation
				* @return {Boolean} True = fails validation
				*/
				ctrl.failsValidation = function () {
					return !!ctrl.hasVisited && !!ctrl.$invalid;
				};

				/**
				* The ID of a validation error element
				* @return {String} Falsy = no validation message
				*                  String = ID of validation message
				*/
				ctrl.validationId = function () {
					if (ctrl.failsValidation()) {
						return element.attr('error-id');
					}
				};

				// on focus note that
				element.on('focus', function () {
					element.addClass('has-focus');

					scope.$apply(function () {
						ctrl.hasFocus = true;
					});
				});

				// on blur apply the had visited property
				element.on('blur', function () {
					$log.log('blur');
					element.removeClass('has-focus');
					element.addClass('has-visited');

					scope.$apply(function () {
						ctrl.hasFocus = false;
						ctrl.hasVisited = true;
					});
				});

				// if the form submits - assume we've visted all the fields
				element.closest('form').on('submit', function () {
					element.addClass('has-visited');

					scope.$apply(function () {
						ctrl.hasFocus = false;
						ctrl.hasVisited = true;
					});
				});
			}
		};
	});

})();
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var moment = require('moment');
var config = require('app/config');
var Reflux = require('reflux');
var ServerActions = require('app/actions/server');

var ComponentStore = Reflux.createStore({
    init: function() {
        this.components = {};
        this.componentSummaries = [];
        this.lastUpdated = Date.now();

        this.listenTo(ServerActions.modulesFetched, this.populate);
    },

    get: function(name) {
        return this.components[name];
    },

    getAll: function() {
        return this.components;
    },

    getSummaries: function() {
        return this.componentSummaries;
    },

    getMostRecentlyCreated: function(limit) {
        return (
            _.sortBy(this.components, 'created')
            .reverse()
            .slice(0, limit || 10)
        );
    },

    getMostRecentlyUpdated: function(limit) {
        var mostRecent  = this.getMostRecentlyCreated();
        var lastUpdated = _.sortBy(this.components, 'modified').reverse();

        return _.without.apply(null,
            [lastUpdated].concat(mostRecent)
        ).slice(0, limit || 10);
    },

    getLastUpdated: function() {
        return this.lastUpdated;
    },

    populate: function(components) {
        this.lastUpdated = Date.now();
        components.map(this.addComponent.bind(this));
        this.trigger('change');
    },

    parseAuthor: function(component) {
        var distTags = component['dist-tags'] || {},
            latest   = component.versions[distTags.latest] || {};

        return (latest._npmUser || component.author).name;
    },

    parseComponentSummary: function(component) {
        return {
            name: component.name,
            description: component.description,
            author: this.parseAuthor(component),
            modified: moment.utc(component.time.modified),
            created: moment.utc(component.time.created),
            keywords: component.keywords.filter(this.isUncommonKeyword),
            downloads: component.downloads || 0,
            stars: component.starCount
        };
    },

    parseComponent: function(component) {
        var distTags = component['dist-tags'] || {},
            latest   = component.versions[distTags.latest] || {};

        component.created  = component.time.created;
        component.modified = component.time.modified;
        component.branch   = latest.gitHead || 'master';

        return component;
    },

    addComponent: function(component) {
        this.components[component.name] = this.parseComponent(component);

        var existing = _.find(this.componentSummaries, { name: component.name });
        _.pull(this.componentSummaries, existing);

        this.componentSummaries.push(this.parseComponentSummary(component));
    },

    isUncommonKeyword: function(keyword) {
        return config['exclude-keywords'].indexOf(keyword) === -1;
    }
});

module.exports = ComponentStore;<commit_msg>Added missing getSummary() method from component store<commit_after>'use strict';

var _ = require('lodash');
var moment = require('moment');
var config = require('app/config');
var Reflux = require('reflux');
var ServerActions = require('app/actions/server');

var ComponentStore = Reflux.createStore({
    init: function() {
        this.components = {};
        this.componentSummaries = [];
        this.lastUpdated = Date.now();

        this.listenTo(ServerActions.modulesFetched, this.populate);
    },

    get: function(name) {
        return this.components[name];
    },

    getSummary: function(name) {
        return _.find(this.componentSummaries, { name: name });
    },

    getAll: function() {
        return this.components;
    },

    getSummaries: function() {
        return this.componentSummaries;
    },

    getMostRecentlyCreated: function(limit) {
        return (
            _.sortBy(this.components, 'created')
            .reverse()
            .slice(0, limit || 10)
        );
    },

    getMostRecentlyUpdated: function(limit) {
        var mostRecent  = this.getMostRecentlyCreated();
        var lastUpdated = _.sortBy(this.components, 'modified').reverse();

        return _.without.apply(null,
            [lastUpdated].concat(mostRecent)
        ).slice(0, limit || 10);
    },

    getLastUpdated: function() {
        return this.lastUpdated;
    },

    populate: function(components) {
        this.lastUpdated = Date.now();
        components.map(this.addComponent.bind(this));
        this.trigger('change');
    },

    parseAuthor: function(component) {
        var distTags = component['dist-tags'] || {},
            latest   = component.versions[distTags.latest] || {};

        return (latest._npmUser || component.author).name;
    },

    parseComponentSummary: function(component) {
        return {
            name: component.name,
            description: component.description,
            author: this.parseAuthor(component),
            modified: moment.utc(component.time.modified),
            created: moment.utc(component.time.created),
            keywords: component.keywords.filter(this.isUncommonKeyword),
            downloads: component.downloads || 0,
            stars: component.starCount
        };
    },

    parseComponent: function(component) {
        var distTags = component['dist-tags'] || {},
            latest   = component.versions[distTags.latest] || {};

        component.created  = component.time.created;
        component.modified = component.time.modified;
        component.branch   = latest.gitHead || 'master';

        return component;
    },

    addComponent: function(component) {
        this.components[component.name] = this.parseComponent(component);

        var existing = _.find(this.componentSummaries, { name: component.name });
        _.pull(this.componentSummaries, existing);

        this.componentSummaries.push(this.parseComponentSummary(component));
    },

    isUncommonKeyword: function(keyword) {
        return config['exclude-keywords'].indexOf(keyword) === -1;
    }
});

module.exports = ComponentStore;<|endoftext|>