<commit_before>(function (exports, node) {

	var GameState = node.GameState;
	var GameMsg = node.GameMsg;
	var GameDB = node.GameDB;
	var PlayerList = node.PlayerList;
	var GameLoop = node.GameLoop;
	var Utils = node.Utils;

	/*
	 * Game
	 *
	 */

	/**
	 * Expose constructor
	 */
	exports.Game = Game;

	function Game (settings, gamesocketclient) {

		// TODO: transform into private variables, otherwise they can accidentally
		// modified  by the execution of the loops functions

		// If not defined they take default settings
		this.name = settings.name || "A standard game";
		this.description = settings.description || 'No Description';

		this.observer = ('undefined' !== typeof settings.observer) ? settings.observer : false;

		this.gameLoop = new GameLoop(settings.loops);

		// TODO: gameState should be inside player
		this.player = null;
		this.gameState = new GameState();

		this.automatic_step = settings.automatic_step || false;

		this.minPlayers = settings.minPlayers || 1;
		this.maxPlayers = settings.maxPlayers || 1000;

		// TODO: Check this
		this.init = settings.init || this.init;

		this.gsc = gamesocketclient;

		this.pl = new PlayerList();

		this.memory = new GameDB();

		var that = this;
		var say = GameMsg.actions.SAY + '.';
		var set = GameMsg.actions.SET + '.';
		var get = GameMsg.actions.GET + '.';
		var IN  = GameMsg.IN;
		var OUT = GameMsg.OUT;

		// INCOMING EVENTS
		var incomingListeners = function() {

			// Get

			// TODO: can we avoid the double emit?
			node.on( IN + get + 'DATA', function(msg){
				node.emit(msg.text, msg.data);
			});

			// Set
			node.on( IN + set + 'STATE', function(msg){
				that.memory.add(msg.from, msg.text, msg.data);
			});

			node.on( IN + set + 'DATA', function(msg){
				that.memory.add(msg.from, msg.text, msg.data);
			});

			// Say

			// If the message is from the server, update the game state
			// If the message is from a player, update the player state
			node.on( IN + say + 'STATE', function(msg){

				// Player exists
				if (that.pl.exist(msg.from)) {
					//node.log('updatePlayer', 'DEBUG);
					that.pl.updatePlayerState(msg.from, msg.data);
					node.emit('UPDATED_PLIST');
					that.pl.checkState();
				}
				// Assume this is the server for now
				// TODO: assign a string-id to the server
				else {
					//node.log('updateState: ' + msg.from + ' -- ' + new GameState(msg.data), 'DEBUG');
					that.updateState(msg.data);
				}
			});

			node.on( IN + say + 'PLIST', function (msg) {
				that.pl = new PlayerList({}, msg.data);
				node.emit('UPDATED_PLIST');
				that.pl.checkState();
			});
		}();

		var outgoingListeners = function() {

			// SAY

			node.on( OUT + say + 'HI', function(){
				// Upon establishing a successful connection with the server
				// Enter the first state
				if (that.automatic_step) {
					that.updateState(that.next());
				}
				else {
					// The game is ready to step when necessary;
					that.gameState.is = GameState.iss.LOADED;
					that.gsc.sendSTATE(GameMsg.actions.SAY, that.gameState);
				}
			});

			node.on( OUT + say + 'STATE', function (state, to) {
				//node.log('BBBB' + p + ' ' + args[0] + ' ' + args[1] + ' ' + args[2], 'DEBUG');
				that.gsc.sendSTATE(GameMsg.actions.SAY, state, to);
			});

			node.on( OUT + say + 'TXT', function (text, to) {
				that.gsc.sendTXT(text,to);
			});

			node.on( OUT + say + 'DATA', function (data, to, key) {
				that.gsc.sendDATA(GameMsg.actions.SAY, data, to, key);
			});

			// SET

			node.on( OUT + set + 'STATE', function (state, to) {
				that.gsc.sendSTATE(GameMsg.actions.SET, state, to);
			});

			node.on( OUT + set + 'DATA', function (data, to, key) {
				that.gsc.sendDATA(GameMsg.actions.SET, data, to, key);
			});

			// GET

			node.on( OUT + get + 'DATA', function (data, to, key) {
				that.gsc.sendDATA(GameMsg.actions.SAY, data, to, key);
			});

		}();

		var internalListeners = function() {

			node.on('STATEDONE', function() {
				// If we go auto
				if (that.automatic_step) {
//					node.log('WE PLAY AUTO', 'DEBUG');
//					node.log(that.pl);
//					node.log(that.pl.size());
					var morePlayers = ('undefined' !== that.minPlayers) ? that.minPlayers - that.pl.size() : 0 ;
					node.log(morePlayers);

					if ( morePlayers > 0 ) {
						node.emit('OUT.say.TXT', morePlayers + ' player/s still needed to play the game');
						node.log( morePlayers + ' player/s still needed to play the game');
					}
					// TODO: differentiate between before the game starts and during the game
					else {
						node.emit('OUT.say.TXT', this.minPlayers + ' players ready. Game can proceed');
						node.log( that.pl.size() + ' players ready. Game can proceed');
						that.updateState(that.next());
					}
				}
//				else {
//					node.log('WAITING FOR MONITOR TO STEP', 'DEBUG');
//				}
			});

			node.on('DONE', function(msg) {
				that.gameState.is = GameState.iss.DONE;
				that.publishState();
			});

			node.on('WAIT', function(msg) {
				that.gameState.paused = true;
				that.publishState();
			});

			node.on('WINDOW_LOADED', function(){
				if (that.isGameReady()) {
					node.emit('LOADED');
				}
			});

			node.on('GAME_LOADED', function() {
				if (that.isGameReady()) {
					node.emit('LOADED');
				}
			});

			node.on('LOADED', function(){
				that.gameState.is =  GameState.iss.PLAYING;
				//node.log('STTTEEEP ' + that.gameState.state, 'DEBUG');
				that.gsc.clearBuffer();
			});

		}();

	}

	// Dealing with the STATE

	Game.prototype.pause = function() {
		this.gameState.paused = true;
	};

	Game.prototype.resume = function() {
		this.gameState.paused = false;
	};

	Game.prototype.next = function(times) {
		if (!times) return this.gameLoop.next(this.gameState);
		return this.gameLoop.jumpTo(this.gameState, Math.abs(times));
	};

	Game.prototype.previous = function (times) {
		if (!times) return this.gameLoop.previous(this.gameState);
		return this.gameLoop.jumpTo(this.gameState, -Math.abs(times));
	};

	Game.prototype.jumpTo = function (jump) {
		var gs = this.gameLoop.jumpTo(this.gameState, jump);
		if (!gs) return false;
		return this.updateState(gs);
	};

//	Game.prototype.is = function(is) {
//		//node.log('IS ' + is);
//		this.gameState.is = is;
//		// TODO Check whether we should do it here or no
//		// this.publishState();
//	};

	Game.prototype.publishState = function() {
		//node.log('Publishing ' + this.gameState, 'DEBUG');
		this.gsc.gmg.state = this.gameState;
		// Important: SAY

		if (!this.observer) {
			var stateEvent = GameMsg.OUT + GameMsg.actions.SAY + '.STATE';
			node.emit(stateEvent,this.gameState,'ALL');
		}

		node.emit('STATECHANGE');
		node.log('New State = ' + this.gameState);
	};

	Game.prototype.updateState = function(state) {

		//node.log('New state is going to be ' + new GameState(state));

		if (this.step(state) !== false){
			this.paused = false;
			this.gameState.is =  GameState.iss.LOADED;
			if (this.isGameReady()) {
				node.emit('LOADED');
			}
		}
		else {
			node.log('Error in stepping', 'ERR');
			// TODO: implement sendERR
			node.emit('TXT','State was not updated');
			// Removed
			//this.publishState(); // Notify anyway what happened
		}
	};

	Game.prototype.step = function(state) {

		var gameState = state || this.next();
		if (gameState) {
			var func = this.gameLoop.getFunction(gameState);

			if (func) {
				gameState.is = GameState.iss.LOADING;
				this.gameState = gameState;

				// This could speed up the loading in other client,
				// but now causes problems of multiple update
				this.publishState();

				// Local Listeners from previous state are erased before proceeding
				// to next one
				node.node.clearLocalListeners();
				return func.call(node.game);
			}
		}

		return false;

	};

	Game.prototype.dump = function(reverse) {
		return this.memory.dump(reverse);
	}

	Game.prototype.init = function() {

	//	var header = this.window.addHeader(document.getElementById('root'), 'header');
	//	header.innerHTML = '
'+ this.name + '
';
	//	header.innerHTML += '
' + this.description + '
';
	//	var button = this.window.addButton(header,'sendbutton');
	//
	//	var that = this;
	//	button.onclick = function() {
	//	  that.DONEWAIT('FUNZIA');
	//	};
	};

	Game.prototype.isGameReady = function() {

		//node.log('GameState is : ' + this.gameState.is, 'DEBUG');

		if (this.gameState.is < GameState.iss.LOADED) return false;

		// Check if there is a gameWindow obj and whether it is loading
		if (node.window) {

			// node.log('WindowState is ' + node.window.state, 'DEBUG');
			return (node.window.state >= GameState.iss.LOADED) ? true : false;
		}

		return true;
	};

})(
	'undefined' != typeof node ? node : module.exports
  , 'undefined' != typeof node ? node : module.parent.exports
);
<commit_msg>Fixed waiting screen. Introduced auto_wait<commit_after>(function (exports, node) {

	var GameState = node.GameState;
	var GameMsg = node.GameMsg;
	var GameDB = node.GameDB;
	var PlayerList = node.PlayerList;
	var GameLoop = node.GameLoop;
	var Utils = node.Utils;

	/*
	 * Game
	 *
	 */

	/**
	 * Expose constructor
	 */
	exports.Game = Game;

	function Game (settings, gamesocketclient) {

		// TODO: transform into private variables, otherwise they can accidentally
		// modified  by the execution of the loops functions

		// If not defined they take default settings
		this.name = settings.name || 'A standard game';
		this.description = settings.description || 'No Description';

		this.observer = ('undefined' !== typeof settings.observer) ? settings.observer
																   : false;

		this.gameLoop = new GameLoop(settings.loops);

		// TODO: gameState should be inside player
		this.player = null;
		this.gameState = new GameState();

		this.auto_step = ('undefined' !== typeof settings.auto_step) ? settings.auto_step
																	 : true;
		this.auto_wait = ('undefined' !== typeof settings.auto_wait) ? settings.auto_wait
																	 : false;

		this.minPlayers = settings.minPlayers || 1;
		this.maxPlayers = settings.maxPlayers || 1000;

		// TODO: Check this
		this.init = settings.init || this.init;

		this.gsc = gamesocketclient;

		this.pl = new PlayerList();

		this.memory = new GameDB();

		var that = this;
		var say = GameMsg.actions.SAY + '.';
		var set = GameMsg.actions.SET + '.';
		var get = GameMsg.actions.GET + '.';
		var IN  = GameMsg.IN;
		var OUT = GameMsg.OUT;

		// INCOMING EVENTS
		var incomingListeners = function() {

			// Get

			// TODO: can we avoid the double emit?
			node.on( IN + get + 'DATA', function(msg){
				node.emit(msg.text, msg.data);
			});

			// Set
			node.on( IN + set + 'STATE', function(msg){
				that.memory.add(msg.from, msg.text, msg.data);
			});

			node.on( IN + set + 'DATA', function(msg){
				that.memory.add(msg.from, msg.text, msg.data);
			});

			// Say

			// If the message is from the server, update the game state
			// If the message is from a player, update the player state
			node.on( IN + say + 'STATE', function(msg){

				// Player exists
				if (that.pl.exist(msg.from)) {
					//node.log('updatePlayer', 'DEBUG);
					that.pl.updatePlayerState(msg.from, msg.data);
					node.emit('UPDATED_PLIST');
					that.pl.checkState();
				}
				// Assume this is the server for now
				// TODO: assign a string-id to the server
				else {
					//node.log('updateState: ' + msg.from + ' -- ' + new GameState(msg.data), 'DEBUG');
					that.updateState(msg.data);
				}
			});

			node.on( IN + say + 'PLIST', function (msg) {
				that.pl = new PlayerList({}, msg.data);
				node.emit('UPDATED_PLIST');
				that.pl.checkState();
			});
		}();

		var outgoingListeners = function() {

			// SAY

			node.on( OUT + say + 'HI', function(){
				// Upon establishing a successful connection with the server
				// Enter the first state
				if (that.auto_step) {
					that.updateState(that.next());
				}
				else {
					// The game is ready to step when necessary;
					that.gameState.is = GameState.iss.LOADED;
					that.gsc.sendSTATE(GameMsg.actions.SAY, that.gameState);
				}
			});

			node.on( OUT + say + 'STATE', function (state, to) {
				//node.log('BBBB' + p + ' ' + args[0] + ' ' + args[1] + ' ' + args[2], 'DEBUG');
				that.gsc.sendSTATE(GameMsg.actions.SAY, state, to);
			});

			node.on( OUT + say + 'TXT', function (text, to) {
				that.gsc.sendTXT(text,to);
			});

			node.on( OUT + say + 'DATA', function (data, to, key) {
				that.gsc.sendDATA(GameMsg.actions.SAY, data, to, key);
			});

			// SET

			node.on( OUT + set + 'STATE', function (state, to) {
				that.gsc.sendSTATE(GameMsg.actions.SET, state, to);
			});

			node.on( OUT + set + 'DATA', function (data, to, key) {
				that.gsc.sendDATA(GameMsg.actions.SET, data, to, key);
			});

			// GET

			node.on( OUT + get + 'DATA', function (data, to, key) {
				that.gsc.sendDATA(GameMsg.actions.SAY, data, to, key);
			});

		}();

		var internalListeners = function() {

			// All the players are done?
			node.on('STATEDONE', function() {
				// If we go auto
				if (that.auto_step) {
//					node.log('WE PLAY AUTO', 'DEBUG');
//					node.log(that.pl);
//					node.log(that.pl.size());
					var morePlayers = ('undefined' !== that.minPlayers) ? that.minPlayers - that.pl.size() : 0 ;
					node.log(morePlayers);

					if ( morePlayers > 0 ) {
						node.emit('OUT.say.TXT', morePlayers + ' player/s still needed to play the game');
						node.log( morePlayers + ' player/s still needed to play the game');
					}
					// TODO: differentiate between before the game starts and during the game
					else {
						node.emit('OUT.say.TXT', this.minPlayers + ' players ready. Game can proceed');
						node.log( that.pl.size() + ' players ready. Game can proceed');
						that.updateState(that.next());
					}
				}

//				else {
//					node.log('WAITING FOR MONITOR TO STEP', 'DEBUG');
//				}
			});

			node.on('DONE', function(msg) {
				that.gameState.is = GameState.iss.DONE;
				that.publishState();

				if (this.auto_wait) {
					if (node.window) {
						node.emit('WAITING...');
					}
				}
			});

			node.on('WAIT', function(msg) {
				that.gameState.paused = true;
				that.publishState();
			});

			node.on('WINDOW_LOADED', function(){
				if (that.isGameReady()) {
					node.emit('LOADED');
				}
			});

			node.on('GAME_LOADED', function() {
				if (that.isGameReady()) {
					node.emit('LOADED');
				}
			});

			node.on('LOADED', function(){
				that.gameState.is =  GameState.iss.PLAYING;
				//node.log('STTTEEEP ' + that.gameState.state, 'DEBUG');
				that.gsc.clearBuffer();
			});

		}();

	}

	// Dealing with the STATE

	Game.prototype.pause = function() {
		this.gameState.paused = true;
	};

	Game.prototype.resume = function() {
		this.gameState.paused = false;
	};

	Game.prototype.next = function(times) {
		if (!times) return this.gameLoop.next(this.gameState);
		return this.gameLoop.jumpTo(this.gameState, Math.abs(times));
	};

	Game.prototype.previous = function (times) {
		if (!times) return this.gameLoop.previous(this.gameState);
		return this.gameLoop.jumpTo(this.gameState, -Math.abs(times));
	};

	Game.prototype.jumpTo = function (jump) {
		var gs = this.gameLoop.jumpTo(this.gameState, jump);
		if (!gs) return false;
		return this.updateState(gs);
	};

//	Game.prototype.is = function(is) {
//		//node.log('IS ' + is);
//		this.gameState.is = is;
//		// TODO Check whether we should do it here or no
//		// this.publishState();
//	};

	Game.prototype.publishState = function() {
		//node.log('Publishing ' + this.gameState, 'DEBUG');
		this.gsc.gmg.state = this.gameState;
		// Important: SAY

		if (!this.observer) {
			var stateEvent = GameMsg.OUT + GameMsg.actions.SAY + '.STATE';
			node.emit(stateEvent,this.gameState,'ALL');
		}

		node.emit('STATECHANGE');

		node.log('New State = ' + this.gameState);
	};

	Game.prototype.updateState = function(state) {

		//node.log('New state is going to be ' + new GameState(state));

		if (this.step(state) !== false){
			this.paused = false;
			this.gameState.is =  GameState.iss.LOADED;
			if (this.isGameReady()) {
				node.emit('LOADED');
			}
		}
		else {
			node.log('Error in stepping', 'ERR');
			// TODO: implement sendERR
			node.emit('TXT','State was not updated');
			// Removed
			//this.publishState(); // Notify anyway what happened
		}
	};

	Game.prototype.step = function(state) {

		var gameState = state || this.next();
		if (gameState) {
			var func = this.gameLoop.getFunction(gameState);

			if (func) {
				gameState.is = GameState.iss.LOADING;
				this.gameState = gameState;

				// This could speed up the loading in other client,
				// but now causes problems of multiple update
				this.publishState();

				// Local Listeners from previous state are erased before proceeding
				// to next one
				node.node.clearLocalListeners();
				return func.call(node.game);
			}
		}

		return false;

	};

	Game.prototype.dump = function(reverse) {
		return this.memory.dump(reverse);
	}

	Game.prototype.init = function() {

	//	var header = this.window.addHeader(document.getElementById('root'), 'header');
	//	header.innerHTML = '
'+ this.name + '
';
	//	header.innerHTML += '
' + this.description + '
';
	//	var button = this.window.addButton(header,'sendbutton');
	//
	//	var that = this;
	//	button.onclick = function() {
	//	  that.DONEWAIT('FUNZIA');
	//	};
	};

	Game.prototype.isGameReady = function() {

		//node.log('GameState is : ' + this.gameState.is, 'DEBUG');

		if (this.gameState.is < GameState.iss.LOADED) return false;

		// Check if there is a gameWindow obj and whether it is loading
		if (node.window) {

			// node.log('WindowState is ' + node.window.state, 'DEBUG');
			return (node.window.state >= GameState.iss.LOADED) ? true : false;
		}

		return true;
	};

})(
	'undefined' != typeof node ? node : module.exports
  , 'undefined' != typeof node ? node : module.parent.exports
);
<|endoftext|>


<commit_before>import Entry from 'admin-config/lib/Entry';

export default class ListController {
    constructor($scope, $stateParams, $location, $anchorScroll, ReadQueries, progression, view, dataStore, totalItems) {
        this.$scope = $scope;
        this.$stateParams = $stateParams;
        this.$location = $location;
        this.$anchorScroll = $anchorScroll;
        this.ReadQueries = ReadQueries;
        this.progression = progression;
        this.view = view;
        this.entity = view.getEntity();
        this.loadingPage = false;
        this.search = $stateParams.search;
        this.dataStore = dataStore;
        this.fields = view.fields();
        this.listActions = view.listActions();
        this.totalItems = totalItems;
        this.page = $stateParams.page || 1;
        this.infinitePagination = this.view.infinitePagination();
        this.entryCssClasses = this.view.getEntryCssClasses.bind(this.view);
        this.nextPageCallback = this.nextPage.bind(this);
        this.setPageCallback = this.setPage.bind(this);
        this.sortField = this.$stateParams.sortField || this.view.getSortFieldName();
        this.sortDir = this.$stateParams.sortDir || this.view.sortDir();
        this.queryPromises = [];

        if ($scope.selectionUpdater) {
            $scope.selection = $scope.selection || [];
            $scope.$watch('selection', $scope.selectionUpdater);
        } else {
            $scope.selection = null;
        }

        $scope.$on('$destroy', this.destroy.bind(this));
    }

    nextPage(page) {
        if (this.loadingPage) {
            return;
        }

        let view = this.view,
            dataStore = this.dataStore;

        this.progression.start();

        const references = view.getReferences();
        let data;

        let queryPromise = this.ReadQueries
            .getAll(view, page, this.search, this.sortField, this.sortDir)
            .then(response => {
                data = response.data;
                return this.ReadQueries.getReferenceData(view.fields(), data);
            })
            .then((referenceData) => {
                this.progression.done();

                for (var name in referenceData) {
                    Entry.createArrayFromRest(
                        referenceData[name],
                        [references[name].targetField()],
                        references[name].targetEntity().name(),
                        references[name].targetEntity().identifier().name()
                    ).map(entry => dataStore.addEntry(references[name].targetEntity().uniqueId + '_values', entry));
                }
            })
        this.queryPromises.push(queryPromise);
        // make sure all preceding promises complete before loading data into store
        Promise.all(this.queryPromises)
            .then(() => {
                view.mapEntries(data)
                    .map(entry => {
                        dataStore.fillReferencesValuesFromEntry(entry, references, true);
                        dataStore.addEntry(this.entity.uniqueId, entry);
                    });

                this.loadingPage = false;
            });
    }

    setPage(number) {
        this.$location.search('page', number);
        this.$anchorScroll(0);
    }

    destroy() {
        this.$scope = undefined;
        this.$stateParams = undefined;
        this.$location = undefined;
        this.$anchorScroll = undefined;
        this.dataStore = undefined;
    }
}

ListController.$inject = ['$scope', '$stateParams', '$location', '$anchorScroll', 'ReadQueries', 'progression', 'view', 'dataStore', 'totalItems'];
<commit_msg>Fix infinite pagination not updating list component when receiving new data<commit_after>import Entry from 'admin-config/lib/Entry';

export default class ListController {
    constructor($scope, $stateParams, $location, $anchorScroll, ReadQueries, progression, view, dataStore, totalItems) {
        this.$scope = $scope;
        this.$stateParams = $stateParams;
        this.$location = $location;
        this.$anchorScroll = $anchorScroll;
        this.ReadQueries = ReadQueries;
        this.progression = progression;
        this.view = view;
        this.entity = view.getEntity();
        this.loadingPage = false;
        this.search = $stateParams.search;
        this.dataStore = dataStore;
        this.fields = view.fields();
        this.listActions = view.listActions();
        this.totalItems = totalItems;
        this.page = $stateParams.page || 1;
        this.infinitePagination = this.view.infinitePagination();
        this.entryCssClasses = this.view.getEntryCssClasses.bind(this.view);
        this.nextPageCallback = this.nextPage.bind(this);
        this.setPageCallback = this.setPage.bind(this);
        this.sortField = this.$stateParams.sortField || this.view.getSortFieldName();
        this.sortDir = this.$stateParams.sortDir || this.view.sortDir();
        this.queryPromises = [];

        if ($scope.selectionUpdater) {
            $scope.selection = $scope.selection || [];
            $scope.$watch('selection', $scope.selectionUpdater);
        } else {
            $scope.selection = null;
        }

        $scope.$on('$destroy', this.destroy.bind(this));
    }

    nextPage(page) {
        if (this.loadingPage) {
            return;
        }

        let view = this.view,
            dataStore = this.dataStore;

        this.progression.start();

        const references = view.getReferences();
        let data;
        const toAddToDatastore = [];

        let queryPromise = this.ReadQueries
            .getAll(view, page, this.search, this.sortField, this.sortDir)
            .then(response => {
                data = response.data;
                return this.ReadQueries.getReferenceData(view.fields(), data);
            })
            .then((referenceData) => {
                this.progression.done();

                for (var name in referenceData) {
                    Entry.createArrayFromRest(
                        referenceData[name],
                        [references[name].targetField()],
                        references[name].targetEntity().name(),
                        references[name].targetEntity().identifier().name()
                    ).map(entry => {
                        toAddToDatastore.push([
                            references[name].targetEntity().uniqueId + '_values',
                            entry
                        ])
                    });
                }
            });
        this.queryPromises.push(queryPromise);
        // make sure all preceding promises complete before loading data into store
        Promise.all(this.queryPromises)
            .then(() => {
                this.$scope.$apply(() => {
                    toAddToDatastore.map((args) => {
                        this.dataStore.addEntry(...args);
                    });

                    view.mapEntries(data)
                        .map(entry => {
                            this.dataStore.fillReferencesValuesFromEntry(entry, references, true);
                            this.dataStore.addEntry(this.entity.uniqueId, entry);
                        });
                    this.loadingPage = false;
                });
            });
    }

    setPage(number) {
        this.$location.search('page', number);
        this.$anchorScroll(0);
    }

    destroy() {
        this.$scope = undefined;
        this.$stateParams = undefined;
        this.$location = undefined;
        this.$anchorScroll = undefined;
        this.dataStore = undefined;
    }
}

ListController.$inject = ['$scope', '$stateParams', '$location', '$anchorScroll', 'ReadQueries', 'progression', 'view', 'dataStore', 'totalItems'];
<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  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.
 */

// System modules.
var fs = require('fs');
var path = require('path');

// Third-party modules.
var Q = require('q');

// Local modules.
var utils = require('./utils');

// Globals
var origDir = process.cwd();
var ccaRoot = path.join(__dirname, '..');

var cordova = require('cordova');
var cordovaLib = cordova.cordova_lib;
var hooks = require('./hooks');

/******************************************************************************/

function fixEnv() {
  // Add flags for building with Gradle
  if (typeof process.env.ANDROID_BUILD == 'undefined') {
    process.env.ANDROID_BUILD = 'gradle';
  }
}

/******************************************************************************/

function main() {
  var commandLineFlags = require('./parse-command-line')();
  utils.exit.pause_on_exit = commandLineFlags.pause_on_exit;

  var command = commandLineFlags._[0];
  var packageVersion = require('../package').version;

  // Colorize after parseCommandLine to avoid --help being printed in red.
  utils.colorizeConsole();

  // TODO: Add env detection to Cordova.
  fixEnv();

  hooks.registerHooks();

  function printCcaVersionPrefix() {
    console.log('cca v' + packageVersion);
  }

  if (command == 'exec') {
    return require('./tools-check').fixEnv()
    .then(function() {
      require('./exec')(process.argv.slice(3));
    }).done(null, utils.fatal);
  }

  if (commandLineFlags.v) {
    command = 'version';
  }
  if (commandLineFlags.h || !command) {
    command = 'help';
  }

  function beforeCordovaPrepare() {
    if (commandLineFlags['skip-upgrade']) {
      return Q.when();
    }
    if (!fs.existsSync(path.join('www', 'manifest.json'))) {
      return Q.reject('This is not a cca project (no www/manifest.json file). Perhaps you meant to use the cordova-cli?');
    }
    return require('./upgrade-project').upgradeProjectIfStale();
  }

  function forwardCurrentCommandToCordova() {
    // Unregister some event handlers in cordova-lib EventEmitter. Otherwise
    // double printouts will happen because cordova-cli registers its own
    // handlers. This is only relevant when --verbose or -d flag is used.
    cordovaLib.events.removeListener('results', console.log);
    cordovaLib.events.removeListener('log', console.log);
    cordovaLib.events.removeListener('warn', console.warn);
    cordovaLib.events.removeListener('verbose', console.log);

    // TODO: Can we replace use of CLI here?  Calls to cordova-lib cordova.raw?
    return cordova.cli(process.argv);
  }

  function printVersionThenPrePrePrepareThenForwardCommandToCordova() {
    printCcaVersionPrefix();
    return beforeCordovaPrepare()
      .then(forwardCurrentCommandToCordova);
  }

  var commandActions = {
    'pre-prepare': function() {
      return require('./pre-prepare')();
    },
    'update-app': function() {
      // TODO: deprecated command, use post-prepare instead
      return commandActions['post-prepare']();
    },
    'post-prepare': function() {
      return require('./post-prepare')();
    },
    'checkenv': function() {
      printCcaVersionPrefix();
      return require('./tools-check')();
    },
    'push': function() {
      printCcaVersionPrefix();
      return Q.fcall(function() {
        var extraFlag = commandLineFlags._[1] || '';
        if (extraFlag) {
          require('optimist').showHelp(console.log);
          return Q.reject('Flag "' + extraFlag + '" not understood.  Did you mean `--target=' + extraFlag + '`?');
        }
        return require('./push-to-harness')(commandLineFlags.target, commandLineFlags.watch);
      });
    },
    'run': function() {
      printCcaVersionPrefix();
      return Q.fcall(function() {
        var platform = commandLineFlags._[1];
        if (platform === 'chrome') {
          // TODO: For some reason --user-data-dir and --load-and-launch-app do not play well together.  Seems you must still quit Chrome Canary first for this to work.
          var spawn = require('child_process').spawn;
          chromeAppRunRoot = null;
          if (fs.existsSync('www/manifest.json')) {
            chromeAppRunRoot = 'www';
          } else if (fs.existsSync('manifest.json')) {
            chromeAppRunRoot = '.';
          }
          spawn('open', ['-n', '-a', 'Google Chrome Canary', '--args', '--user-data-dir=/tmp/cca_chrome_data_dir', '--load-and-launch-app=' + path.resolve(chromeAppRunRoot)]); // '--disable-web-security'
          return;
        }
        return forwardCurrentCommandToCordova();
      });
    },
    'create': function() {
      printCcaVersionPrefix();
      return Q.fcall(function() {
        var destAppDir = commandLineFlags._[1] || '';
        if (!destAppDir) {
          require('optimist').showHelp(console.log);
          return Q.reject('No output directory given.');
        }
        // resolve turns relative paths into absolute
        destAppDir = path.resolve(destAppDir);
        var packageId = commandLineFlags._[2] || '';
        var appName = commandLineFlags._[3] || '';
        return require('./create-app')(destAppDir, ccaRoot, origDir, packageId, appName, commandLineFlags);
      });
    },
    'upgrade': function() {
      printCcaVersionPrefix();
      return require('./upgrade-project').upgradeProject(commandLineFlags.y);
    },
    'version': function() {
      console.log(packageVersion);
      return Q.when();
    },
    'help': function() {
      printCcaVersionPrefix();
      require('optimist').showHelp(console.log);
      return Q.when();
    },
    'platform': function() {
      printCcaVersionPrefix();
      // Do not run auto-upgrade step if doing a platforms command
      return forwardCurrentCommandToCordova();
    },
    'platforms': function() {
      printCcaVersionPrefix();
      // Do not run auto-upgrade step if doing a platforms command
      return forwardCurrentCommandToCordova();
    },
    'analytics': function() {
      // Do nothing.  This is handled as a special-case below.
      return Q.when();
    },
    'build': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'compile': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'emulate': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'plugin': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'plugins': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'prepare': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'serve': printVersionThenPrePrePrepareThenForwardCommandToCordova,
  };

  // TODO(mmocny): The following few lines seem to make global changes that affect all other subcommands.
  // May want to break this out to a module as an "init" step that every other step ensures has been called.
  cordovaLib.cordova.config.setAutoPersist(false);
  var projectRoot = cordovaLib.cordova.findProjectRoot();
  if (projectRoot) {
    cordovaLib.cordova.config(projectRoot, require('./default-config')(ccaRoot));
    process.chdir(projectRoot);
    // signing keys
    if (!process.env.DEBUG_SIGNING_PROPERTIES_FILE && fs.existsSync('android-debug-keys.properties')) {
      process.env.DEBUG_SIGNING_PROPERTIES_FILE = path.resolve('android-debug-keys.properties');
    }
    if (!process.env.RELEASE_SIGNING_PROPERTIES_FILE && fs.existsSync('android-release-keys.properties')) {
      process.env.RELEASE_SIGNING_PROPERTIES_FILE = path.resolve('android-release-keys.properties');
    }
  }

  if (!commandActions.hasOwnProperty(command)) {
    utils.fatal('Invalid command: ' + command + '. Use --help for usage.');
  }

  // In verbose mode, print all cordova events
  if (commandLineFlags.d) {
    // TODO: its possible we want to console.log the results for some cordova commands even in non-verbose mode
    cordovaLib.events.on('results', console.log);
    cordovaLib.events.on('log', console.log);
    cordovaLib.events.on('warn', console.warn);
    cordovaLib.events.on('verbose', console.log);
  }

  // If the command is an analytics command, act accordingly.
  // We do this now because it's a special case.  If this is the user's first command, a prompt doesn't make sense.
  var analyticsLoader = require('./analytics-loader');
  if (command === 'analytics') {
    analyticsLoader.analyticsCommand(commandLineFlags._[1]);
  }

  analyticsLoader.getAnalyticsModule()
  .then(function(analytics) {
    analytics.sendEvent('cca', command);
  }).then(commandActions[command])
  .then(null, function(e) {
    if (e instanceof cordovaLib.CordovaError) {
      utils.fatal(e.message.replace(/\bcordova /, 'cca '));
    } else {
      throw e;
    }
  }).done();
}

if (require.main === module) {
    main();
} else {
    module.exports.parseCLI = main;
}
<commit_msg>Implement cca run canary<commit_after>#!/usr/bin/env node
/**
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  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.
 */

// System modules.
var fs = require('fs');
var path = require('path');

// Third-party modules.
var Q = require('q');

// Local modules.
var utils = require('./utils');

// Globals
var origDir = process.cwd();
var ccaRoot = path.join(__dirname, '..');

var cordova = require('cordova');
var cordovaLib = cordova.cordova_lib;
var hooks = require('./hooks');

/******************************************************************************/

function fixEnv() {
  // Add flags for building with Gradle
  if (typeof process.env.ANDROID_BUILD == 'undefined') {
    process.env.ANDROID_BUILD = 'gradle';
  }
}

/******************************************************************************/

function main() {
  var commandLineFlags = require('./parse-command-line')();
  utils.exit.pause_on_exit = commandLineFlags.pause_on_exit;

  var command = commandLineFlags._[0];
  var packageVersion = require('../package').version;

  // Colorize after parseCommandLine to avoid --help being printed in red.
  utils.colorizeConsole();

  // TODO: Add env detection to Cordova.
  fixEnv();

  hooks.registerHooks();

  function printCcaVersionPrefix() {
    console.log('cca v' + packageVersion);
  }

  if (command == 'exec') {
    return require('./tools-check').fixEnv()
    .then(function() {
      require('./exec')(process.argv.slice(3));
    }).done(null, utils.fatal);
  }

  if (commandLineFlags.v) {
    command = 'version';
  }
  if (commandLineFlags.h || !command) {
    command = 'help';
  }

  function beforeCordovaPrepare() {
    if (commandLineFlags['skip-upgrade']) {
      return Q.when();
    }
    if (!fs.existsSync(path.join('www', 'manifest.json'))) {
      return Q.reject('This is not a cca project (no www/manifest.json file). Perhaps you meant to use the cordova-cli?');
    }
    return require('./upgrade-project').upgradeProjectIfStale();
  }

  function forwardCurrentCommandToCordova() {
    // Unregister some event handlers in cordova-lib EventEmitter. Otherwise
    // double printouts will happen because cordova-cli registers its own
    // handlers. This is only relevant when --verbose or -d flag is used.
    cordovaLib.events.removeListener('results', console.log);
    cordovaLib.events.removeListener('log', console.log);
    cordovaLib.events.removeListener('warn', console.warn);
    cordovaLib.events.removeListener('verbose', console.log);

    // TODO: Can we replace use of CLI here?  Calls to cordova-lib cordova.raw?
    return cordova.cli(process.argv);
  }

  function printVersionThenPrePrePrepareThenForwardCommandToCordova() {
    printCcaVersionPrefix();
    return beforeCordovaPrepare()
      .then(forwardCurrentCommandToCordova);
  }

  var commandActions = {
    'pre-prepare': function() {
      return require('./pre-prepare')();
    },
    'update-app': function() {
      // TODO: deprecated command, use post-prepare instead
      return commandActions['post-prepare']();
    },
    'post-prepare': function() {
      return require('./post-prepare')();
    },
    'checkenv': function() {
      printCcaVersionPrefix();
      return require('./tools-check')();
    },
    'push': function() {
      printCcaVersionPrefix();
      return Q.fcall(function() {
        var extraFlag = commandLineFlags._[1] || '';
        if (extraFlag) {
          require('optimist').showHelp(console.log);
          return Q.reject('Flag "' + extraFlag + '" not understood.  Did you mean `--target=' + extraFlag + '`?');
        }
        return require('./push-to-harness')(commandLineFlags.target, commandLineFlags.watch);
      });
    },
    'run': function() {
      printCcaVersionPrefix();
      return Q.fcall(function() {
        var platform = commandLineFlags._[1];
        if (platform === 'chrome' || platform === 'canary') {
          // TODO: For some reason --user-data-dir and --load-and-launch-app do not play well together.  Seems you must still quit Chrome Canary first for this to work.
          var spawn = require('child_process').spawn;
          chromeAppRunRoot = null;
          if (fs.existsSync('www/manifest.json')) {
            chromeAppRunRoot = 'www';
          } else if (fs.existsSync('manifest.json')) {
            chromeAppRunRoot = '.';
          } else {
            return Q.reject('Not a chrome app.');
          }
          var chrome = 'Google Chrome' + (platform === 'canary' ? ' Canary' : '');
          var chromeArgs = ['--load-and-launch-app=' + path.resolve(chromeAppRunRoot)]; // '--disable-web-security'
          if (platform === 'canary') {
            chromeArgs.push('--user-data-dir=/tmp/cca_chrome_data_dir');
          }
          spawn('open', ['-n', '-a', chrome, '--args'].concat(chromeArgs));
          return;
        }
        return forwardCurrentCommandToCordova();
      });
    },
    'create': function() {
      printCcaVersionPrefix();
      return Q.fcall(function() {
        var destAppDir = commandLineFlags._[1] || '';
        if (!destAppDir) {
          require('optimist').showHelp(console.log);
          return Q.reject('No output directory given.');
        }
        // resolve turns relative paths into absolute
        destAppDir = path.resolve(destAppDir);
        var packageId = commandLineFlags._[2] || '';
        var appName = commandLineFlags._[3] || '';
        return require('./create-app')(destAppDir, ccaRoot, origDir, packageId, appName, commandLineFlags);
      });
    },
    'upgrade': function() {
      printCcaVersionPrefix();
      return require('./upgrade-project').upgradeProject(commandLineFlags.y);
    },
    'version': function() {
      console.log(packageVersion);
      return Q.when();
    },
    'help': function() {
      printCcaVersionPrefix();
      require('optimist').showHelp(console.log);
      return Q.when();
    },
    'platform': function() {
      printCcaVersionPrefix();
      // Do not run auto-upgrade step if doing a platforms command
      return forwardCurrentCommandToCordova();
    },
    'platforms': function() {
      printCcaVersionPrefix();
      // Do not run auto-upgrade step if doing a platforms command
      return forwardCurrentCommandToCordova();
    },
    'analytics': function() {
      // Do nothing.  This is handled as a special-case below.
      return Q.when();
    },
    'build': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'compile': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'emulate': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'plugin': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'plugins': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'prepare': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'serve': printVersionThenPrePrePrepareThenForwardCommandToCordova,
  };

  // TODO(mmocny): The following few lines seem to make global changes that affect all other subcommands.
  // May want to break this out to a module as an "init" step that every other step ensures has been called.
  cordovaLib.cordova.config.setAutoPersist(false);
  var projectRoot = cordovaLib.cordova.findProjectRoot();
  if (projectRoot) {
    cordovaLib.cordova.config(projectRoot, require('./default-config')(ccaRoot));
    process.chdir(projectRoot);
    // signing keys
    if (!process.env.DEBUG_SIGNING_PROPERTIES_FILE && fs.existsSync('android-debug-keys.properties')) {
      process.env.DEBUG_SIGNING_PROPERTIES_FILE = path.resolve('android-debug-keys.properties');
    }
    if (!process.env.RELEASE_SIGNING_PROPERTIES_FILE && fs.existsSync('android-release-keys.properties')) {
      process.env.RELEASE_SIGNING_PROPERTIES_FILE = path.resolve('android-release-keys.properties');
    }
  }

  if (!commandActions.hasOwnProperty(command)) {
    utils.fatal('Invalid command: ' + command + '. Use --help for usage.');
  }

  // In verbose mode, print all cordova events
  if (commandLineFlags.d) {
    // TODO: its possible we want to console.log the results for some cordova commands even in non-verbose mode
    cordovaLib.events.on('results', console.log);
    cordovaLib.events.on('log', console.log);
    cordovaLib.events.on('warn', console.warn);
    cordovaLib.events.on('verbose', console.log);
  }

  // If the command is an analytics command, act accordingly.
  // We do this now because it's a special case.  If this is the user's first command, a prompt doesn't make sense.
  var analyticsLoader = require('./analytics-loader');
  if (command === 'analytics') {
    analyticsLoader.analyticsCommand(commandLineFlags._[1]);
  }

  analyticsLoader.getAnalyticsModule()
  .then(function(analytics) {
    analytics.sendEvent('cca', command);
  }).then(commandActions[command])
  .then(null, function(e) {
    if (e instanceof cordovaLib.CordovaError) {
      utils.fatal(e.message.replace(/\bcordova /, 'cca '));
    } else {
      throw e;
    }
  }).done();
}

if (require.main === module) {
    main();
} else {
    module.exports.parseCLI = main;
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  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.
 */

// System modules.
var path = require('path');

// Third-party modules.
var Q = require('q');

// Local modules.
var utils = require('./utils');

// Globals
var origDir = process.cwd();
var ccaRoot = path.join(__dirname, '..');

/******************************************************************************/

function fixEnv() {
  var shelljs = require('shelljs');
  if (utils.isWindows()) {
    // Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
    var javacInPath = !shelljs.which('javac');
    var hasJavaHome = !!process.env.JAVA_HOME;
    if (hasJavaHome && !javacInPath) {
      process.env.PATH += ';' + process.env.JAVA_HOME + '\\bin';
    } else if (!hasJavaHome || !javacInPath) {
      var firstJdkDir =
          shelljs.ls(process.env.ProgramFiles + '\\java\\jdk*')[0] ||
          shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
          shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
      if (firstJdkDir) {
        if (!javacInPath) {
          process.env.PATH += ';' + firstJdkDir + '\\bin';
        }
        process.env.JAVA_HOME = firstJdkDir;
        console.log('Set JAVA_HOME to ' + firstJdkDir);
      }
    }
  }
}

/******************************************************************************/

function main() {
  var commandLineFlags = require('./parse_command_line')();
  utils.exit.pause_on_exit = commandLineFlags.pause_on_exit;

  var command = commandLineFlags._[0];
  var packageVersion = require('../package').version;

  if (commandLineFlags.v) {
    command = 'version';
  }
  if (commandLineFlags.h || !command) {
    command = 'help';
  }

  // Colorize after parseCommandLine to avoid --help being printed in red.
  utils.colorizeConsole();

  // TODO: Add env detection to Cordova.
  fixEnv();

  function printCcaVersionPrefix() {
    console.log('cca v' + packageVersion);
    return Q();
  }

  function beforeCordovaPrepare() {
    if (commandLineFlags['skip-upgrade']) {
      return Q();
    }
    return require('./auto-upgrade')();
  }

  function forwardCurrentCommandToCordova() {
    require('cordova/src/cli')(process.argv);
    return Q();
  }

  function printVersionThenPrePrePrepareThenForwardCommandToCordova() {
    return printCcaVersionPrefix()
      .then(beforeCordovaPrepare)
      .then(forwardCurrentCommandToCordova);
  }

  var commandActions = {
    'pre-prepare': function() {
      return require('./pre-prepare')();
    },
    'update-app': function() {
      // TODO: deprecated command, use post-prepare instead
      return commandActions['post-prepare']();
    },
    'post-prepare': function() {
      return require('./post-prepare')();
    },
    'checkenv': function() {
      return printCcaVersionPrefix()
      .then(require('./tools-check'));
    },
    'push': function() {
      return printCcaVersionPrefix()
      .then(function() {
        return require('./push-to-harness')(commandLineFlags.target, commandLineFlags.watch);
      });
    },
    'run': function() {
      return printCcaVersionPrefix()
      .then(beforeCordovaPrepare)
      .then(function() {
        var platform = commandLineFlags._[1];
        if (platform === 'chrome') {
          // TODO: improve
          var chromePath = '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary';
          var args = ['--profile-directory=/dev/null', '--load-and-launch-app=' + path.join('www')];
          var childProcess = require('child_process');
          childProcess.spawn(chromePath, args);
          return Q();
        }
        return forwardCurrentCommandToCordova();
      });
    },
    'create': function() {
      return printCcaVersionPrefix()
      .then(function() {
        var destAppDir = commandLineFlags._[1] || '';
        if (!destAppDir) {
          require('optimist').showHelp(console.log);
          return Q.reject('No output directory given.');
        }
        // resolve turns relative paths into absolute
        destAppDir = path.resolve(destAppDir);
        return require('./tools-check')()
          .then(function() {
            return require('./create-app')(destAppDir, ccaRoot, origDir, commandLineFlags)
          });
      });
    },
    'upgrade': function() {
      return printCcaVersionPrefix()
      .then(require('./upgrade-project'));
    },
    'version': function() {
      console.log(packageVersion);
      return Q();
    },
    'help': function() {
      return printCcaVersionPrefix()
      .then(function() {
        require('optimist').showHelp(console.log);
        return Q();
      });
    },
    'platform': function() {
      return printCcaVersionPrefix().then(forwardCurrentCommandToCordova);
    },
    'platforms': function() {
      return printCcaVersionPrefix().then(forwardCurrentCommandToCordova);
    },
    'build': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'compile': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'emulate': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'plugin': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'plugins': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'prepare': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'serve': printVersionThenPrePrePrepareThenForwardCommandToCordova,
  };

  // TODO(mmocny): The following few lines seem to make global changes that affect all other subcommands.
  // May want to break this out to a module as an "init" step that every other step ensures has been called.
  var cordovaLib = require('cordova-lib');
  cordovaLib.cordova.config.setAutoPersist(false);
  var projectRoot = cordovaLib.cordova.findProjectRoot();
  if (projectRoot) {
    cordovaLib.cordova.config(projectRoot, require('./default-config')(ccaRoot));
    process.chdir(projectRoot);
  }

  if (!commandActions.hasOwnProperty(command)) {
    utils.fatal('Invalid command: ' + command + '. Use --help for usage.');
  }

  // start hack to enable logging :(.
  var cliDummyArgs = [0, 0, 'foo'];
  if (commandLineFlags.d) {
    cliDummyArgs.push('--verbose');
  }
  try {
    require('cordova/src/cli')(cliDummyArgs);
  } catch(e) {}
  // end hack

  commandActions[command]().done(null, utils.fatal);
}

if (require.main === module) {
    main();
} else {
    module.exports.parseCLI = main;
}
<commit_msg>Enable cordova command logging via cordova-lib event listening<commit_after>#!/usr/bin/env node
/**
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  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.
 */

// System modules.
var path = require('path');

// Third-party modules.
var Q = require('q');

// Local modules.
var utils = require('./utils');

// Globals
var origDir = process.cwd();
var ccaRoot = path.join(__dirname, '..');

/******************************************************************************/

function fixEnv() {
  var shelljs = require('shelljs');
  if (utils.isWindows()) {
    // Windows java installer doesn't add javac to PATH, nor set JAVA_HOME (ugh).
    var javacInPath = !shelljs.which('javac');
    var hasJavaHome = !!process.env.JAVA_HOME;
    if (hasJavaHome && !javacInPath) {
      process.env.PATH += ';' + process.env.JAVA_HOME + '\\bin';
    } else if (!hasJavaHome || !javacInPath) {
      var firstJdkDir =
          shelljs.ls(process.env.ProgramFiles + '\\java\\jdk*')[0] ||
          shelljs.ls('C:\\Program Files\\java\\jdk*')[0] ||
          shelljs.ls('C:\\Program Files (x86)\\java\\jdk*')[0];
      if (firstJdkDir) {
        if (!javacInPath) {
          process.env.PATH += ';' + firstJdkDir + '\\bin';
        }
        process.env.JAVA_HOME = firstJdkDir;
        console.log('Set JAVA_HOME to ' + firstJdkDir);
      }
    }
  }
}

/******************************************************************************/

function main() {
  var commandLineFlags = require('./parse_command_line')();
  utils.exit.pause_on_exit = commandLineFlags.pause_on_exit;

  var command = commandLineFlags._[0];
  var packageVersion = require('../package').version;

  if (commandLineFlags.v) {
    command = 'version';
  }
  if (commandLineFlags.h || !command) {
    command = 'help';
  }

  // Colorize after parseCommandLine to avoid --help being printed in red.
  utils.colorizeConsole();

  // TODO: Add env detection to Cordova.
  fixEnv();

  function printCcaVersionPrefix() {
    console.log('cca v' + packageVersion);
    return Q();
  }

  function beforeCordovaPrepare() {
    if (commandLineFlags['skip-upgrade']) {
      return Q();
    }
    return require('./auto-upgrade')();
  }

  function forwardCurrentCommandToCordova() {
    require('cordova/src/cli')(process.argv);
    return Q();
  }

  function printVersionThenPrePrePrepareThenForwardCommandToCordova() {
    return printCcaVersionPrefix()
      .then(beforeCordovaPrepare)
      .then(forwardCurrentCommandToCordova);
  }

  var commandActions = {
    'pre-prepare': function() {
      return require('./pre-prepare')();
    },
    'update-app': function() {
      // TODO: deprecated command, use post-prepare instead
      return commandActions['post-prepare']();
    },
    'post-prepare': function() {
      return require('./post-prepare')();
    },
    'checkenv': function() {
      return printCcaVersionPrefix()
      .then(require('./tools-check'));
    },
    'push': function() {
      return printCcaVersionPrefix()
      .then(function() {
        return require('./push-to-harness')(commandLineFlags.target, commandLineFlags.watch);
      });
    },
    'run': function() {
      return printCcaVersionPrefix()
      .then(beforeCordovaPrepare)
      .then(function() {
        var platform = commandLineFlags._[1];
        if (platform === 'chrome') {
          // TODO: improve
          var chromePath = '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary';
          var args = ['--profile-directory=/dev/null', '--load-and-launch-app=' + path.join('www')];
          var childProcess = require('child_process');
          childProcess.spawn(chromePath, args);
          return Q();
        }
        return forwardCurrentCommandToCordova();
      });
    },
    'create': function() {
      return printCcaVersionPrefix()
      .then(function() {
        var destAppDir = commandLineFlags._[1] || '';
        if (!destAppDir) {
          require('optimist').showHelp(console.log);
          return Q.reject('No output directory given.');
        }
        // resolve turns relative paths into absolute
        destAppDir = path.resolve(destAppDir);
        return require('./tools-check')()
          .then(function() {
            return require('./create-app')(destAppDir, ccaRoot, origDir, commandLineFlags)
          });
      });
    },
    'upgrade': function() {
      return printCcaVersionPrefix()
      .then(require('./upgrade-project'));
    },
    'version': function() {
      console.log(packageVersion);
      return Q();
    },
    'help': function() {
      return printCcaVersionPrefix()
      .then(function() {
        require('optimist').showHelp(console.log);
        return Q();
      });
    },
    'platform': function() {
      return printCcaVersionPrefix().then(forwardCurrentCommandToCordova);
    },
    'platforms': function() {
      return printCcaVersionPrefix().then(forwardCurrentCommandToCordova);
    },
    'build': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'compile': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'emulate': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'plugin': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'plugins': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'prepare': printVersionThenPrePrePrepareThenForwardCommandToCordova,
    'serve': printVersionThenPrePrePrepareThenForwardCommandToCordova,
  };

  // TODO(mmocny): The following few lines seem to make global changes that affect all other subcommands.
  // May want to break this out to a module as an "init" step that every other step ensures has been called.
  var cordovaLib = require('cordova-lib');
  cordovaLib.cordova.config.setAutoPersist(false);
  var projectRoot = cordovaLib.cordova.findProjectRoot();
  if (projectRoot) {
    cordovaLib.cordova.config(projectRoot, require('./default-config')(ccaRoot));
    process.chdir(projectRoot);
  }

  if (!commandActions.hasOwnProperty(command)) {
    utils.fatal('Invalid command: ' + command + '. Use --help for usage.');
  }

  // In verbose mode, print all cordova events
  if (commandLineFlags.d) {
    // TODO: its possible we want to console.log the results for some cordova commands even in non-verbose mode
    cordovaLib.events.on('results', console.log);
    cordovaLib.events.on('log', console.log);
    cordovaLib.events.on('warn', console.warn);
    cordovaLib.events.on('verbose', console.log);
  }

  commandActions[command]().done(null, utils.fatal);
}

if (require.main === module) {
    main();
} else {
    module.exports.parseCLI = main;
}
<|endoftext|>


<commit_before>/*
 *   处理特殊键的兼容性问题
 */
UE.plugins['keystrokes'] = function() {
    var me = this;
    var collapsed = true;
    me.addListener('keydown', function(type, evt) {
        var keyCode = evt.keyCode || evt.which,
            rng = me.selection.getRange();

        //处理全选的情况
        if(!rng.collapsed && !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && (keyCode >= 65 && keyCode <=90
            || keyCode >= 48 && keyCode <= 57 ||
            keyCode >= 96 && keyCode <= 111 || {
                    13:1,
                    8:1,
                    46:1
                }[keyCode])
            ){

            var tmpNode = rng.startContainer;
            if(domUtils.isFillChar(tmpNode)){
                rng.setStartBefore(tmpNode)
            }
            tmpNode = rng.endContainer;
            if(domUtils.isFillChar(tmpNode)){
                rng.setEndAfter(tmpNode)
            }
            rng.txtToElmBoundary();
            //结束边界可能放到了br的前边，要把br包含进来
            // x[xxx]

            if(rng.endContainer && rng.endContainer.nodeType == 1){
                tmpNode = rng.endContainer.childNodes[rng.endOffset];
                if(tmpNode && domUtils.isBr(tmpNode)){
                    rng.setEndAfter(tmpNode);
                }
            }
            if(rng.startOffset == 0){
                tmpNode = rng.startContainer;
                if(domUtils.isBoundaryNode(tmpNode,'firstChild') ){
                    tmpNode = rng.endContainer;
                    if(rng.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode,'lastChild')){
                        me.fireEvent('saveScene');
                        me.body.innerHTML = '
'+(browser.ie ? '' : '
')+'
';
                        rng.setStart(me.body.firstChild,0).setCursor(false,true);
                        me._selectionChange();
                        return;
                    }
                }
            }
        }

        //处理backspace
        if (keyCode == 8) {
            rng = me.selection.getRange();
            collapsed = rng.collapsed;
            if(me.fireEvent('delkeydown',evt)){
                return;
            }
            var start,end;
            //避免按两次删除才能生效的问题
            if(rng.collapsed && rng.inFillChar()){
                start = rng.startContainer;

                if(domUtils.isFillChar(start)){
                    rng.setStartBefore(start).shrinkBoundary(true).collapse(true);
                    domUtils.remove(start)
                }else{
                    start.nodeValue = start.nodeValue.replace(new RegExp('^' + domUtils.fillChar ),'');
                    rng.startOffset--;
                    rng.collapse(true).select(true)
                }
            }

            //解决选中control元素不能删除的问题
            if (start = rng.getClosedNode()) {
                me.fireEvent('saveScene');
                rng.setStartBefore(start);
                domUtils.remove(start);
                rng.setCursor();
                me.fireEvent('saveScene');
                domUtils.preventDefault(evt);
                return;
            }
            //阻止在table上的删除
            if (!browser.ie) {
                start = domUtils.findParentByTagName(rng.startContainer, 'table', true);
                end = domUtils.findParentByTagName(rng.endContainer, 'table', true);
                if (start && !end || !start && end || start !== end) {
                    evt.preventDefault();
                    return;
                }
            }

        }
        //处理tab键的逻辑
        if (keyCode == 9) {
            //不处理以下标签
            var excludeTagNameForTabKey = {
                'ol' : 1,
                'ul' : 1,
                'table':1
            };
            //处理组件里的tab按下事件
            if(me.fireEvent('tabkeydown',evt)){
                domUtils.preventDefault(evt);
                return;
            }
            var range = me.selection.getRange();
            me.fireEvent('saveScene');
            for (var i = 0,txt = '',tabSize = me.options.tabSize|| 4,tabNode =  me.options.tabNode || ' '; i < tabSize; i++) {
                txt += tabNode;
            }
            var span = me.document.createElement('span');
            span.innerHTML = txt + domUtils.fillChar;
            if (range.collapsed) {
                range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
            } else {
                //普通的情况
                start = domUtils.findParent(range.startContainer, filterFn);
                end = domUtils.findParent(range.endContainer, filterFn);
                if (start && end && start === end) {
                    range.deleteContents();
                    range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
                } else {
                    var bookmark = range.createBookmark(),
                        filterFn = function(node) {
                            return domUtils.isBlockElm(node) && !excludeTagNameForTabKey[node.tagName.toLowerCase()]

                        };
                    range.enlarge(true);
                    var bookmark2 = range.createBookmark(),
                        current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
                    while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
                        current.insertBefore(span.cloneNode(true).firstChild, current.firstChild);
                        current = domUtils.getNextDomNode(current, false, filterFn);
                    }
                    range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select();
                }
            }
            domUtils.preventDefault(evt)
        }
        //trace:1634
        //ff的del键在容器空的时候，也会删除
        if(browser.gecko && keyCode == 46){
            range = me.selection.getRange();
            if(range.collapsed){
                start = range.startContainer;
                if(domUtils.isEmptyBlock(start)){
                    var parent = start.parentNode;
                    while(domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)){
                        start = parent;
                        parent = parent.parentNode;
                    }
                    if(start === parent.lastChild)
                        evt.preventDefault();
                    return;
                }
            }
        }
    });
    me.addListener('keyup', function(type, evt) {
        var keyCode = evt.keyCode || evt.which,
            rng,me = this;
        if(keyCode == 8){
            if(me.fireEvent('delkeyup')){
                return;
            }
            rng = me.selection.getRange();
            if(rng.collapsed){
                var tmpNode,
                    autoClearTagName = ['h1','h2','h3','h4','h5','h6'];
                if(tmpNode = domUtils.findParentByTagName(rng.startContainer,autoClearTagName,true)){
                    if(domUtils.isEmptyBlock(tmpNode)){
                        var pre = tmpNode.previousSibling;
                        if(pre && pre.nodeName != 'TABLE'){
                            domUtils.remove(tmpNode);
                            rng.setStartAtLast(pre).setCursor(false,true);
                            return;
                        }else{
                            var next = tmpNode.nextSibling;
                            if(next && next.nodeName != 'TABLE'){
                                domUtils.remove(tmpNode);
                                rng.setStartAtFirst(next).setCursor(false,true);
                                return;
                            }
                        }
                    }
                }
                //处理当删除到body时，要重新给p标签展位
                if(domUtils.isBody(rng.startContainer)){
                    var tmpNode = domUtils.createElement(me.document,'p',{
                        'innerHTML' : browser.ie ? domUtils.fillChar : '
'
                    });
                    rng.insertNode(tmpNode).setStart(tmpNode,0).setCursor(false,true);
                }
            }

            //chrome下如果删除了inline标签，浏览器会有记忆，在输入文字还是会套上刚才删除的标签，所以这里再选一次就不会了
            if( !collapsed && (rng.startContainer.nodeType == 3 || rng.startContainer.nodeType == 1 && domUtils.isEmptyBlock(rng.startContainer))){
                if(browser.ie){
                    var span = rng.document.createElement('span');
                    rng.insertNode(span).setStartBefore(span).collapse(true);
                    rng.select();
                    domUtils.remove(span)
                }else{
                    rng.select()
                }

            }
        }

    })
};<commit_msg>针对tab键按下的fix<commit_after>/*
 *   处理特殊键的兼容性问题
 */
UE.plugins['keystrokes'] = function() {
    var me = this;
    var collapsed = true;
    me.addListener('keydown', function(type, evt) {
        var keyCode = evt.keyCode || evt.which,
            rng = me.selection.getRange();

        //处理全选的情况
        if(!rng.collapsed && !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && (keyCode >= 65 && keyCode <=90
            || keyCode >= 48 && keyCode <= 57 ||
            keyCode >= 96 && keyCode <= 111 || {
                    13:1,
                    8:1,
                    46:1
                }[keyCode])
            ){

            var tmpNode = rng.startContainer;
            if(domUtils.isFillChar(tmpNode)){
                rng.setStartBefore(tmpNode)
            }
            tmpNode = rng.endContainer;
            if(domUtils.isFillChar(tmpNode)){
                rng.setEndAfter(tmpNode)
            }
            rng.txtToElmBoundary();
            //结束边界可能放到了br的前边，要把br包含进来
            // x[xxx]

            if(rng.endContainer && rng.endContainer.nodeType == 1){
                tmpNode = rng.endContainer.childNodes[rng.endOffset];
                if(tmpNode && domUtils.isBr(tmpNode)){
                    rng.setEndAfter(tmpNode);
                }
            }
            if(rng.startOffset == 0){
                tmpNode = rng.startContainer;
                if(domUtils.isBoundaryNode(tmpNode,'firstChild') ){
                    tmpNode = rng.endContainer;
                    if(rng.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode,'lastChild')){
                        me.fireEvent('saveScene');
                        me.body.innerHTML = '
'+(browser.ie ? '' : '
')+'
';
                        rng.setStart(me.body.firstChild,0).setCursor(false,true);
                        me._selectionChange();
                        return;
                    }
                }
            }
        }

        //处理backspace
        if (keyCode == 8) {
            rng = me.selection.getRange();
            collapsed = rng.collapsed;
            if(me.fireEvent('delkeydown',evt)){
                return;
            }
            var start,end;
            //避免按两次删除才能生效的问题
            if(rng.collapsed && rng.inFillChar()){
                start = rng.startContainer;

                if(domUtils.isFillChar(start)){
                    rng.setStartBefore(start).shrinkBoundary(true).collapse(true);
                    domUtils.remove(start)
                }else{
                    start.nodeValue = start.nodeValue.replace(new RegExp('^' + domUtils.fillChar ),'');
                    rng.startOffset--;
                    rng.collapse(true).select(true)
                }
            }

            //解决选中control元素不能删除的问题
            if (start = rng.getClosedNode()) {
                me.fireEvent('saveScene');
                rng.setStartBefore(start);
                domUtils.remove(start);
                rng.setCursor();
                me.fireEvent('saveScene');
                domUtils.preventDefault(evt);
                return;
            }
            //阻止在table上的删除
            if (!browser.ie) {
                start = domUtils.findParentByTagName(rng.startContainer, 'table', true);
                end = domUtils.findParentByTagName(rng.endContainer, 'table', true);
                if (start && !end || !start && end || start !== end) {
                    evt.preventDefault();
                    return;
                }
            }

        }
        //处理tab键的逻辑
        if (keyCode == 9) {
            //不处理以下标签
            var excludeTagNameForTabKey = {
                'ol' : 1,
                'ul' : 1,
                'table':1
            };
            //处理组件里的tab按下事件
            if(me.fireEvent('tabkeydown',evt)){
                domUtils.preventDefault(evt);
                return;
            }
            var range = me.selection.getRange();
            me.fireEvent('saveScene');
            for (var i = 0,txt = '',tabSize = me.options.tabSize|| 4,tabNode =  me.options.tabNode || ' '; i < tabSize; i++) {
                txt += tabNode;
            }
            var span = me.document.createElement('span');
            span.innerHTML = txt + domUtils.fillChar;
            if (range.collapsed) {
                range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
            } else {
                var filterFn = function(node) {
                    return domUtils.isBlockElm(node) && !excludeTagNameForTabKey[node.tagName.toLowerCase()]

                };
                //普通的情况
                start = domUtils.findParent(range.startContainer, filterFn,true);
                end = domUtils.findParent(range.endContainer, filterFn,true);
                if (start && end && start === end) {
                    range.deleteContents();
                    range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
                } else {
                    var bookmark = range.createBookmark();
                    range.enlarge(true);
                    var bookmark2 = range.createBookmark(),
                        current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
                    while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
                        current.insertBefore(span.cloneNode(true).firstChild, current.firstChild);
                        current = domUtils.getNextDomNode(current, false, filterFn);
                    }
                    range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select();
                }
            }
            domUtils.preventDefault(evt)
        }
        //trace:1634
        //ff的del键在容器空的时候，也会删除
        if(browser.gecko && keyCode == 46){
            range = me.selection.getRange();
            if(range.collapsed){
                start = range.startContainer;
                if(domUtils.isEmptyBlock(start)){
                    var parent = start.parentNode;
                    while(domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)){
                        start = parent;
                        parent = parent.parentNode;
                    }
                    if(start === parent.lastChild)
                        evt.preventDefault();
                    return;
                }
            }
        }
    });
    me.addListener('keyup', function(type, evt) {
        var keyCode = evt.keyCode || evt.which,
            rng,me = this;
        if(keyCode == 8){
            if(me.fireEvent('delkeyup')){
                return;
            }
            rng = me.selection.getRange();
            if(rng.collapsed){
                var tmpNode,
                    autoClearTagName = ['h1','h2','h3','h4','h5','h6'];
                if(tmpNode = domUtils.findParentByTagName(rng.startContainer,autoClearTagName,true)){
                    if(domUtils.isEmptyBlock(tmpNode)){
                        var pre = tmpNode.previousSibling;
                        if(pre && pre.nodeName != 'TABLE'){
                            domUtils.remove(tmpNode);
                            rng.setStartAtLast(pre).setCursor(false,true);
                            return;
                        }else{
                            var next = tmpNode.nextSibling;
                            if(next && next.nodeName != 'TABLE'){
                                domUtils.remove(tmpNode);
                                rng.setStartAtFirst(next).setCursor(false,true);
                                return;
                            }
                        }
                    }
                }
                //处理当删除到body时，要重新给p标签展位
                if(domUtils.isBody(rng.startContainer)){
                    var tmpNode = domUtils.createElement(me.document,'p',{
                        'innerHTML' : browser.ie ? domUtils.fillChar : '
'
                    });
                    rng.insertNode(tmpNode).setStart(tmpNode,0).setCursor(false,true);
                }
            }

            //chrome下如果删除了inline标签，浏览器会有记忆，在输入文字还是会套上刚才删除的标签，所以这里再选一次就不会了
            if( !collapsed && (rng.startContainer.nodeType == 3 || rng.startContainer.nodeType == 1 && domUtils.isEmptyBlock(rng.startContainer))){
                if(browser.ie){
                    var span = rng.document.createElement('span');
                    rng.insertNode(span).setStartBefore(span).collapse(true);
                    rng.select();
                    domUtils.remove(span)
                }else{
                    rng.select()
                }

            }
        }

    })
};<|endoftext|>


<commit_before>/* 处理特殊键的兼容性问题 */
UE.plugins['keystrokes'] = function() {
    var me = this;
    var collapsed = true;
    me.addListener('keydown', function(type, evt) {
        var keyCode = evt.keyCode || evt.which,
            rng = me.selection.getRange();

        //处理全选的情况
        if(!rng.collapsed && !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && (keyCode >= 65 && keyCode <=90
            || keyCode >= 48 && keyCode <= 57 ||
            keyCode >= 96 && keyCode <= 111 || {
                    13:1,
                    8:1,
                    46:1
                }[keyCode])
            ){

            var tmpNode = rng.startContainer;
            if(domUtils.isFillChar(tmpNode)){
                rng.setStartBefore(tmpNode)
            }
            tmpNode = rng.endContainer;
            if(domUtils.isFillChar(tmpNode)){
                rng.setEndAfter(tmpNode)
            }
            rng.txtToElmBoundary();
            //结束边界可能放到了br的前边，要把br包含进来
            // x[xxx]

            if(rng.endContainer && rng.endContainer.nodeType == 1){
                tmpNode = rng.endContainer.childNodes[rng.endOffset];
                if(tmpNode && domUtils.isBr(tmpNode)){
                    rng.setEndAfter(tmpNode);
                }
            }
            if(rng.startOffset == 0){
                tmpNode = rng.startContainer;
                if(domUtils.isBoundaryNode(tmpNode,'firstChild') ){
                    tmpNode = rng.endContainer;
                    if(rng.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode,'lastChild')){
                        me.fireEvent('saveScene');
                        me.body.innerHTML = '
'+(browser.ie ? '' : '
')+'
';
                        rng.setStart(me.body.firstChild,0).setCursor(false,true);
                        me._selectionChange();
                        return;
                    }
                }
            }
        }

        //处理backspace
        if (keyCode == keymap.Backspace) {
            rng = me.selection.getRange();
            collapsed = rng.collapsed;
            if(me.fireEvent('delkeydown',evt)){
                return;
            }
            var start,end;
            //避免按两次删除才能生效的问题
            if(rng.collapsed && rng.inFillChar()){
                start = rng.startContainer;

                if(domUtils.isFillChar(start)){
                    rng.setStartBefore(start).shrinkBoundary(true).collapse(true);
                    domUtils.remove(start)
                }else{
                    start.nodeValue = start.nodeValue.replace(new RegExp('^' + domUtils.fillChar ),'');
                    rng.startOffset--;
                    rng.collapse(true).select(true)
                }
            }

            //解决选中control元素不能删除的问题
            if (start = rng.getClosedNode()) {
                me.fireEvent('saveScene');
                rng.setStartBefore(start);
                domUtils.remove(start);
                rng.setCursor();
                me.fireEvent('saveScene');
                domUtils.preventDefault(evt);
                return;
            }
            //阻止在table上的删除
            if (!browser.ie) {
                start = domUtils.findParentByTagName(rng.startContainer, 'table', true);
                end = domUtils.findParentByTagName(rng.endContainer, 'table', true);
                if (start && !end || !start && end || start !== end) {
                    evt.preventDefault();
                    return;
                }
            }

        }
        //处理tab键的逻辑
        if (keyCode == keymap.Tab) {
            //不处理以下标签
            var excludeTagNameForTabKey = {
                'ol' : 1,
                'ul' : 1,
                'table':1
            };
            //处理组件里的tab按下事件
            if(me.fireEvent('tabkeydown',evt)){
                domUtils.preventDefault(evt);
                return;
            }
            var range = me.selection.getRange();
            me.fireEvent('saveScene');
            for (var i = 0,txt = '',tabSize = me.options.tabSize|| 4,tabNode =  me.options.tabNode || ' '; i < tabSize; i++) {
                txt += tabNode;
            }
            var span = me.document.createElement('span');
            span.innerHTML = txt + domUtils.fillChar;
            if (range.collapsed) {
                range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
            } else {
                var filterFn = function(node) {
                    return domUtils.isBlockElm(node) && !excludeTagNameForTabKey[node.tagName.toLowerCase()]

                };
                //普通的情况
                start = domUtils.findParent(range.startContainer, filterFn,true);
                end = domUtils.findParent(range.endContainer, filterFn,true);
                if (start && end && start === end) {
                    range.deleteContents();
                    range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
                } else {
                    var bookmark = range.createBookmark();
                    range.enlarge(true);
                    var bookmark2 = range.createBookmark(),
                        current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
                    while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
                        current.insertBefore(span.cloneNode(true).firstChild, current.firstChild);
                        current = domUtils.getNextDomNode(current, false, filterFn);
                    }
                    range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select();
                }
            }
            domUtils.preventDefault(evt)
        }
        //trace:1634
        //ff的del键在容器空的时候，也会删除
        if(browser.gecko && keyCode == 46){
            range = me.selection.getRange();
            if(range.collapsed){
                start = range.startContainer;
                if(domUtils.isEmptyBlock(start)){
                    var parent = start.parentNode;
                    while(domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)){
                        start = parent;
                        parent = parent.parentNode;
                    }
                    if(start === parent.lastChild)
                        evt.preventDefault();
                    return;
                }
            }
        }
    });
    me.addListener('keyup', function(type, evt) {
        var keyCode = evt.keyCode || evt.which,
            rng,me = this;
        if(keyCode == keymap.Backspace){
            if(me.fireEvent('delkeyup')){
                return;
            }
            rng = me.selection.getRange();
            if(rng.collapsed){
                var tmpNode,
                    autoClearTagName = ['h1','h2','h3','h4','h5','h6'];
                if(tmpNode = domUtils.findParentByTagName(rng.startContainer,autoClearTagName,true)){
                    if(domUtils.isEmptyBlock(tmpNode)){
                        var pre = tmpNode.previousSibling;
                        if(pre && pre.nodeName != 'TABLE'){
                            domUtils.remove(tmpNode);
                            rng.setStartAtLast(pre).setCursor(false,true);
                            return;
                        }else{
                            var next = tmpNode.nextSibling;
                            if(next && next.nodeName != 'TABLE'){
                                domUtils.remove(tmpNode);
                                rng.setStartAtFirst(next).setCursor(false,true);
                                return;
                            }
                        }
                    }
                }
                //处理当删除到body时，要重新给p标签展位
                if(domUtils.isBody(rng.startContainer)){
                    var tmpNode = domUtils.createElement(me.document,'p',{
                        'innerHTML' : browser.ie ? domUtils.fillChar : '
'
                    });
                    rng.insertNode(tmpNode).setStart(tmpNode,0).setCursor(false,true);
                }
            }

            //chrome下如果删除了inline标签，浏览器会有记忆，在输入文字还是会套上刚才删除的标签，所以这里再选一次就不会了
            if( !collapsed && (rng.startContainer.nodeType == 3 || rng.startContainer.nodeType == 1 && domUtils.isEmptyBlock(rng.startContainer))){
                if(browser.ie){
                    var span = rng.document.createElement('span');
                    rng.insertNode(span).setStartBefore(span).collapse(true);
                    rng.select();
                    domUtils.remove(span)
                }else{
                    rng.select()
                }

            }
        }

    })
};<commit_msg>修复在编辑区域打不开 chrome 控制台的问题<commit_after>/* 处理特殊键的兼容性问题 */
UE.plugins['keystrokes'] = function() {
    var me = this;
    var collapsed = true;
    me.addListener('keydown', function(type, evt) {
        var keyCode = evt.keyCode || evt.which,
            rng = me.selection.getRange();

        //处理全选的情况
        if(!rng.collapsed && !(evt.ctrlKey || evt.shiftKey || evt.altKey || evt.metaKey) && (keyCode >= 65 && keyCode <=90
            || keyCode >= 48 && keyCode <= 57 ||
            keyCode >= 96 && keyCode <= 111 || {
                    13:1,
                    8:1,
                    46:1
                }[keyCode])
            ){

            var tmpNode = rng.startContainer;
            if(domUtils.isFillChar(tmpNode)){
                rng.setStartBefore(tmpNode)
            }
            tmpNode = rng.endContainer;
            if(domUtils.isFillChar(tmpNode)){
                rng.setEndAfter(tmpNode)
            }
            rng.txtToElmBoundary();
            //结束边界可能放到了br的前边，要把br包含进来
            // x[xxx]

            if(rng.endContainer && rng.endContainer.nodeType == 1){
                tmpNode = rng.endContainer.childNodes[rng.endOffset];
                if(tmpNode && domUtils.isBr(tmpNode)){
                    rng.setEndAfter(tmpNode);
                }
            }
            if(rng.startOffset == 0){
                tmpNode = rng.startContainer;
                if(domUtils.isBoundaryNode(tmpNode,'firstChild') ){
                    tmpNode = rng.endContainer;
                    if(rng.endOffset == (tmpNode.nodeType == 3 ? tmpNode.nodeValue.length : tmpNode.childNodes.length) && domUtils.isBoundaryNode(tmpNode,'lastChild')){
                        me.fireEvent('saveScene');
                        me.body.innerHTML = '
'+(browser.ie ? '' : '
')+'
';
                        rng.setStart(me.body.firstChild,0).setCursor(false,true);
                        me._selectionChange();
                        return;
                    }
                }
            }
        }

        //处理backspace
        if (keyCode == keymap.Backspace) {
            rng = me.selection.getRange();
            collapsed = rng.collapsed;
            if(me.fireEvent('delkeydown',evt)){
                return;
            }
            var start,end;
            //避免按两次删除才能生效的问题
            if(rng.collapsed && rng.inFillChar()){
                start = rng.startContainer;

                if(domUtils.isFillChar(start)){
                    rng.setStartBefore(start).shrinkBoundary(true).collapse(true);
                    domUtils.remove(start)
                }else{
                    start.nodeValue = start.nodeValue.replace(new RegExp('^' + domUtils.fillChar ),'');
                    rng.startOffset--;
                    rng.collapse(true).select(true)
                }
            }

            //解决选中control元素不能删除的问题
            if (start = rng.getClosedNode()) {
                me.fireEvent('saveScene');
                rng.setStartBefore(start);
                domUtils.remove(start);
                rng.setCursor();
                me.fireEvent('saveScene');
                domUtils.preventDefault(evt);
                return;
            }
            //阻止在table上的删除
            if (!browser.ie) {
                start = domUtils.findParentByTagName(rng.startContainer, 'table', true);
                end = domUtils.findParentByTagName(rng.endContainer, 'table', true);
                if (start && !end || !start && end || start !== end) {
                    evt.preventDefault();
                    return;
                }
            }

        }
        //处理tab键的逻辑
        if (keyCode == keymap.Tab) {
            //不处理以下标签
            var excludeTagNameForTabKey = {
                'ol' : 1,
                'ul' : 1,
                'table':1
            };
            //处理组件里的tab按下事件
            if(me.fireEvent('tabkeydown',evt)){
                domUtils.preventDefault(evt);
                return;
            }
            var range = me.selection.getRange();
            me.fireEvent('saveScene');
            for (var i = 0,txt = '',tabSize = me.options.tabSize|| 4,tabNode =  me.options.tabNode || ' '; i < tabSize; i++) {
                txt += tabNode;
            }
            var span = me.document.createElement('span');
            span.innerHTML = txt + domUtils.fillChar;
            if (range.collapsed) {
                range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
            } else {
                var filterFn = function(node) {
                    return domUtils.isBlockElm(node) && !excludeTagNameForTabKey[node.tagName.toLowerCase()]

                };
                //普通的情况
                start = domUtils.findParent(range.startContainer, filterFn,true);
                end = domUtils.findParent(range.endContainer, filterFn,true);
                if (start && end && start === end) {
                    range.deleteContents();
                    range.insertNode(span.cloneNode(true).firstChild).setCursor(true);
                } else {
                    var bookmark = range.createBookmark();
                    range.enlarge(true);
                    var bookmark2 = range.createBookmark(),
                        current = domUtils.getNextDomNode(bookmark2.start, false, filterFn);
                    while (current && !(domUtils.getPosition(current, bookmark2.end) & domUtils.POSITION_FOLLOWING)) {
                        current.insertBefore(span.cloneNode(true).firstChild, current.firstChild);
                        current = domUtils.getNextDomNode(current, false, filterFn);
                    }
                    range.moveToBookmark(bookmark2).moveToBookmark(bookmark).select();
                }
            }
            domUtils.preventDefault(evt)
        }
        //trace:1634
        //ff的del键在容器空的时候，也会删除
        if(browser.gecko && keyCode == 46){
            range = me.selection.getRange();
            if(range.collapsed){
                start = range.startContainer;
                if(domUtils.isEmptyBlock(start)){
                    var parent = start.parentNode;
                    while(domUtils.getChildCount(parent) == 1 && !domUtils.isBody(parent)){
                        start = parent;
                        parent = parent.parentNode;
                    }
                    if(start === parent.lastChild)
                        evt.preventDefault();
                    return;
                }
            }
        }

        /* 修复在编辑区域快捷键 (Mac:meta+alt+I; Win:ctrl+shift+I) 打不开 chrome 控制台的问题 */
        browser.chrome && me.on('keydown', function(type, e){
            var keyCode = e.keyCode || e.which;
            if (((e.metaKey && e.altKey) || (e.ctrlKey && e.shiftKey)) && keyCode == 73) {
                return true;
            }
        });
    });
    me.addListener('keyup', function(type, evt) {
        var keyCode = evt.keyCode || evt.which,
            rng,me = this;
        if(keyCode == keymap.Backspace){
            if(me.fireEvent('delkeyup')){
                return;
            }
            rng = me.selection.getRange();
            if(rng.collapsed){
                var tmpNode,
                    autoClearTagName = ['h1','h2','h3','h4','h5','h6'];
                if(tmpNode = domUtils.findParentByTagName(rng.startContainer,autoClearTagName,true)){
                    if(domUtils.isEmptyBlock(tmpNode)){
                        var pre = tmpNode.previousSibling;
                        if(pre && pre.nodeName != 'TABLE'){
                            domUtils.remove(tmpNode);
                            rng.setStartAtLast(pre).setCursor(false,true);
                            return;
                        }else{
                            var next = tmpNode.nextSibling;
                            if(next && next.nodeName != 'TABLE'){
                                domUtils.remove(tmpNode);
                                rng.setStartAtFirst(next).setCursor(false,true);
                                return;
                            }
                        }
                    }
                }
                //处理当删除到body时，要重新给p标签展位
                if(domUtils.isBody(rng.startContainer)){
                    var tmpNode = domUtils.createElement(me.document,'p',{
                        'innerHTML' : browser.ie ? domUtils.fillChar : '
'
                    });
                    rng.insertNode(tmpNode).setStart(tmpNode,0).setCursor(false,true);
                }
            }

            //chrome下如果删除了inline标签，浏览器会有记忆，在输入文字还是会套上刚才删除的标签，所以这里再选一次就不会了
            if( !collapsed && (rng.startContainer.nodeType == 3 || rng.startContainer.nodeType == 1 && domUtils.isEmptyBlock(rng.startContainer))){
                if(browser.ie){
                    var span = rng.document.createElement('span');
                    rng.insertNode(span).setStartBefore(span).collapse(true);
                    rng.select();
                    domUtils.remove(span)
                }else{
                    rng.select()
                }

            }
        }

    })
};<|endoftext|>