<commit_before>'use strict';

/**
 * @ngdoc overview
 * @name cCheckApp
 * @description
 * # cCheckApp
 *
 * Main module of the application.
 */

// Helper function
// check if item exists in array
  function existsIn(item, array) {
    var result = false;
    array.forEach(function(entry) {
      if(entry.localeCompare(item) === 0) {
        result = true;
      }
    });
      return result;
  }

angular
  .module('cCheckApp', [
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngRoute',
    'ngSanitize',
    'ngTouch',
    'ui.bootstrap',
    'ngDialog'
  ])
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider
      .when('/main', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl'
      })
      .when('/about', {
        templateUrl: 'views/about.html',
        controller: 'AboutCtrl'
      })
      .when('/login', {
        templateUrl: 'views/login.html',
        controller: 'LoginCtrl'
      })
      .when('/unauthorized', {
        templateUrl: 'views/unauthorized.html'
      })
      .when('/addTrainee', {
        templateUrl: 'views/addtrainee.html',
        controller: 'AddFightersCtrl'
      })
      .when('/allTrainees', {
        templateUrl: 'views/allfighters.html',
        controller: 'AllFightersCtrl'
      })
      .when('/addSession', {
        templateUrl: 'views/addsession.html',
        controller: 'AddSessionCtrl'
      })
      .when('/allSessions', {
        templateUrl: 'views/allsessions.html',
        controller: 'AllSessionsCtrl'
      })
      .otherwise({
        redirectTo: '/about'
      });

      // Html 5 mode, need to fix rewrites to use
      /*
      $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
      });*/

  }])
  .constant('API_URL', 'http://localhost:8000/') // http://localhost:8000/ https://ccheckapi.herokuapp.com/
  .run(['$rootScope', '$location', 'authService', function($rootScope, $location, authService) {
    // Route changes settings for authentication

    // routes that don't require authentication
    var skipAuth = ['/', '/login', '/about'];
    // routes only for trainers
    var trainersOnly = ['/addTrainee', '/allTrainees', '/addSession', '/allSessions' ];

    $rootScope.$on('$routeChangeError', function(event, current, previous, eventObj) {
      if (eventObj.authenticated === false) {
        $location.path('/login');
      }
    });

    $rootScope.$on('$routeChangeStart', function () {
      var attemptedRoute = $location.path();
      if(!existsIn(attemptedRoute, skipAuth) && !authService.loggedIn())
      {
        // if path requires authentication and user is not logged in
        $location.path('/login');
      }
      else if(existsIn(attemptedRoute, trainersOnly) && !existsIn('trainer', authService.permissions()))
      {
        //
        $location.path('/unauthorized');
      }
    });
  }])
  .config(function ($httpProvider) {
    $httpProvider.interceptors.push('authInterceptor');
  })
  .config(function($resourceProvider) {
    $resourceProvider.defaults.stripTrailingSlashes = false;
  })
  .config(function (datepickerConfig) {
      datepickerConfig.showButtonBar = false;
    })
  .controller('NavController', ['$scope', '$location', 'authService', function($scope, $location, authService) {
    $scope.isActive = function(viewLocation) {
      return viewLocation === $location.path();
    };
    $scope.logout = function() {
      authService.logout();
      $location.path('/login');
    };
    $scope.loggedIn = function() {
      if(authService.loggedIn()) {
        return true;
      }
      else {
        return false;
      }
    };

    $scope.user = authService.getUser();
    $scope.isTrainer = function() {
      return existsIn('trainer', authService.permissions());
    };
  }]);
<commit_msg>adding filter, then removed as it was not needed<commit_after>'use strict';

/**
 * @ngdoc overview
 * @name cCheckApp
 * @description
 * # cCheckApp
 *
 * Main module of the application.
 */

// Helper function
// check if item exists in array
  function existsIn(item, array) {
    var result = false;
    array.forEach(function(entry) {
      if(entry.localeCompare(item) === 0) {
        result = true;
      }
    });
      return result;
  }

angular
  .module('cCheckApp', [
    'ngAnimate',
    'ngCookies',
    'ngResource',
    'ngRoute',
    'ngSanitize',
    'ngTouch',
    'ui.bootstrap',
    'ngDialog'
  ])
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider
      .when('/main', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl'
      })
      .when('/about', {
        templateUrl: 'views/about.html',
        controller: 'AboutCtrl'
      })
      .when('/login', {
        templateUrl: 'views/login.html',
        controller: 'LoginCtrl'
      })
      .when('/unauthorized', {
        templateUrl: 'views/unauthorized.html'
      })
      .when('/addTrainee', {
        templateUrl: 'views/addtrainee.html',
        controller: 'AddFightersCtrl'
      })
      .when('/allTrainees', {
        templateUrl: 'views/allfighters.html',
        controller: 'AllFightersCtrl'
      })
      .when('/addSession', {
        templateUrl: 'views/addsession.html',
        controller: 'AddSessionCtrl'
      })
      .when('/allSessions', {
        templateUrl: 'views/allsessions.html',
        controller: 'AllSessionsCtrl'
      })
      .otherwise({
        redirectTo: '/about'
      });

      // Html 5 mode, need to fix rewrites to use
      /*
      $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
      });*/

  }])
  .constant('API_URL', 'http://localhost:8000/') // http://localhost:8000/ https://ccheckapi.herokuapp.com/
  .run(['$rootScope', '$location', 'authService', function($rootScope, $location, authService) {
    // Route changes settings for authentication

    // routes that don't require authentication
    var skipAuth = ['/', '/login', '/about'];
    // routes only for trainers
    var trainersOnly = ['/addTrainee', '/allTrainees', '/addSession', '/allSessions' ];

    $rootScope.$on('$routeChangeError', function(event, current, previous, eventObj) {
      if (eventObj.authenticated === false) {
        $location.path('/login');
      }
    });

    $rootScope.$on('$routeChangeStart', function () {
      var attemptedRoute = $location.path();
      if(!existsIn(attemptedRoute, skipAuth) && !authService.loggedIn())
      {
        // if path requires authentication and user is not logged in
        $location.path('/login');
      }
      else if(existsIn(attemptedRoute, trainersOnly) && !existsIn('trainer', authService.permissions()))
      {
        //
        $location.path('/unauthorized');
      }
    });
  }])
  .config(function ($httpProvider) {
    $httpProvider.interceptors.push('authInterceptor');
  })
  .config(function($resourceProvider) {
    $resourceProvider.defaults.stripTrailingSlashes = false;
  })
  .config(function (datepickerConfig) {
      datepickerConfig.showButtonBar = false;
    })
  .controller('NavController', ['$scope', '$location', 'authService', function($scope, $location, authService) {
    $scope.isActive = function(viewLocation) {
      return viewLocation === $location.path();
    };
    $scope.logout = function() {
      authService.logout();
      $location.path('/login');
    };
    $scope.loggedIn = function() {
      if(authService.loggedIn()) {
        return true;
      }
      else {
        return false;
      }
    };

    $scope.user = authService.getUser();
    $scope.isTrainer = function() {
      return existsIn('trainer', authService.permissions());
    };
  }])
  .filter('isArcher', function() {
    return function(input) {
      var out = [];
      for (var i = 0; i < input.length; i++) {
        if(input[i].is_archer)
          out.push(input[i])
      }
      return out;
    };
  });
<|endoftext|>


<commit_before>(function(w) {
    'use strict';

    w.app = angular.module('AnnotatedTutorial', ['app-templates', 'ngSanitize', 'angularMoment', 'RecursionHelper']);

    app.factory('annotatedTutorialServer', function() {
        if (typeof(DEVELOPMENT) === 'undefined') {
            return 'http://redbud.cs.umanitoba.ca';
            //return '//dorado.cs.umanitoba.ca:8000'; // production environment
        } else {
            return 'http://127.0.0.1:8000'; // development environment
        }
    });

    app.factory('currentParticipant', function() {
        var pseudonym = ''//'Assiniboine';//localStorage.getItem('pseudonym');

        if (!pseudonym) {
            while (!pseudonym) {
                pseudonym = prompt('Please, enter your pseudonym');
            }

            localStorage.setItem('pseudonym', pseudonym);
          }

        return pseudonym;
    });

})(window);<commit_msg>update url to new server<commit_after>(function(w) {
    'use strict';

    w.app = angular.module('AnnotatedTutorial', ['app-templates', 'ngSanitize', 'angularMoment', 'RecursionHelper']);

    app.factory('annotatedTutorialServer', function() {
        if (typeof(DEVELOPMENT) === 'undefined') {
            return 'http://rengas.cs.umanitoba.ca';
            //return '//dorado.cs.umanitoba.ca:8000'; // production environment
        } else {
            return 'http://127.0.0.1:8000'; // development environment
        }
    });

    app.factory('currentParticipant', function() {
        var pseudonym = ''//'Assiniboine';//localStorage.getItem('pseudonym');

        if (!pseudonym) {
            while (!pseudonym) {
                pseudonym = prompt('Please, enter your pseudonym');
            }

            localStorage.setItem('pseudonym', pseudonym);
          }

        return pseudonym;
    });

})(window);<|endoftext|>


<commit_before>'use strict';

var app = require('ampersand-app');

// BELONGS IN MODEL
var State = require('ampersand-state');

var Model = State.extend({
    session: {
        ready: {
            type: 'boolean',
            default: false
        },
        opened: {
            type: 'boolean',
            default: false
        }
    },
    derived: {
        loadStatus: {
            deps: ['ready'],
            fn: function () {
                return this.ready ? 'Ready! Click to begin' : 'Loading...';
            },
        }
    },
    open: function (attribute) {
        this.opened = true;
    },
});

// END

// BELONGS IN VIEW
var View = require('ampersand-view');
var View = View.extend({
    bindings: {
        'model.loadStatus': {
            type: 'text',
            hook: 'load-status'
        },
        'model.opened': {
            type: 'booleanClass',
            selector: '#splash-screen',
            name: 'hidden'
        }
    },
    events: {
        "click #splash-screen": 'notify',
    },
    notify: function (evt) {
        var screenfull = require('screenfull');

        if (screenfull.enabled) {
            screenfull.request();
        }
        this.model.open();
    },
});

// END

module.exports = app.extend({
    init: function(){
        var app = this;
        window.level = app;

        app.model = new Model();
        // app.router = new Router({pushState: true});

        var domready = require('domready');
        domready(function () {
            app.view = new View({
                el: document.body,
                model: app.model
            });
        //     // app.view.render();
        //     app.router.on('openMenu', app.page.openMenu, app.page);
        //     app.router.on('closeMenu', app.page.closeMenu, app.page);
        //     app.router.history.start();
            app.ready();
        });
    },
    ready: function () {
        this.model.ready = true;
        window.console.log('Level is now ready');
    },
});

module.exports.init();
<commit_msg>rename views<commit_after>'use strict';

var app = require('ampersand-app');

// BELONGS IN MODEL
var State = require('ampersand-state');

var Main = State.extend({
    session: {
        ready: {
            type: 'boolean',
            default: false
        },
        opened: {
            type: 'boolean',
            default: false
        }
    },
    derived: {
        loadStatus: {
            deps: ['ready'],
            fn: function () {
                return this.ready ? 'Ready! Click to begin' : 'Loading...';
            },
        }
    },
    open: function (attribute) {
        this.opened = true;
    },
});

// END

// BELONGS IN VIEW
var View = require('ampersand-view');
var MainView = View.extend({
    bindings: {
        'model.loadStatus': {
            type: 'text',
            hook: 'load-status'
        },
        'model.opened': {
            type: 'booleanClass',
            selector: '#splash-screen',
            name: 'hidden'
        }
    },
    events: {
        "click #splash-screen": 'notify',
    },
    notify: function (evt) {
        var screenfull = require('screenfull');

        if (screenfull.enabled) {
            screenfull.request();
        }
        this.model.open();
    },
});

// END

module.exports = app.extend({
    init: function(){
        var app = this;
        window.level = app;

        app.model = new Main();
        // app.router = new Router({pushState: true});

        var domready = require('domready');
        domready(function () {
            app.view = new MainView({
                el: document.body,
                model: app.model
            });
        //     // app.view.render();
        //     app.router.on('openMenu', app.page.openMenu, app.page);
        //     app.router.on('closeMenu', app.page.closeMenu, app.page);
        //     app.router.history.start();
            app.ready();
        });
    },
    ready: function () {
        this.model.ready = true;
        window.console.log('Level is now ready');
    },
});

module.exports.init();
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

(function(document) {
  'use strict';

  // Grab a reference to our auto-binding template
  // and give it some initial binding values
  // Learn more about auto-binding templates at http://goo.gl/Dx1u2g
  var app = document.querySelector('#app');
  app.name='Joe Bloggs';
  app.headline='Headline';
  var locationsRef = new Firebase('https://pwsbooking.firebaseio.com/locations');
  app.locations = [];
  locationsRef.on('value', function(snapshot){
    //console.log(snapshot.val());
    app.locations = snapshot.val();
    console.log(app.locations);
  });
  app.displayInstalledToast = function() {
    // Check to make sure caching is actually enabled—it won't be in the dev environment.
    if (!document.querySelector('platinum-sw-cache').disabled) {
      document.querySelector('#caching-complete').show();
    }
  };

  // Listen for template bound event to know when bindings
  // have resolved and content has been stamped to the page
  app.addEventListener('dom-change', function() {
    console.log('Our app is ready to rock!');
  });

  // See https://github.com/Polymer/polymer/issues/1381
  window.addEventListener('WebComponentsReady', function() {
    // imports are loaded and elements have been registered
  });

  // Main area's paper-scroll-header-panel custom condensing transformation of
  // the appName in the middle-container and the bottom title in the bottom-container.
  // The appName is moved to top and shrunk on condensing. The bottom sub title
  // is shrunk to nothing on condensing.
  addEventListener('paper-header-transform', function(e) {
    var appName = document.querySelector('#mainToolbar .app-name');
    var middleContainer = document.querySelector('#mainToolbar .middle-container');
    var bottomContainer = document.querySelector('#mainToolbar .bottom-container');
    var detail = e.detail;
    var heightDiff = detail.height - detail.condensedHeight;
    var yRatio = Math.min(1, detail.y / heightDiff);
    var maxMiddleScale = 0.50;  // appName max size when condensed. The smaller the number the smaller the condensed size.
    var scaleMiddle = Math.max(maxMiddleScale, (heightDiff - detail.y) / (heightDiff / (1-maxMiddleScale))  + maxMiddleScale);
    var scaleBottom = 1 - yRatio;

    // Move/translate middleContainer
    Polymer.Base.transform('translate3d(0,' + yRatio * 100 + '%,0)', middleContainer);

    // Scale bottomContainer and bottom sub title to nothing and back
    Polymer.Base.transform('scale(' + scaleBottom + ') translateZ(0)', bottomContainer);

    // Scale middleContainer appName
    Polymer.Base.transform('scale(' + scaleMiddle + ') translateZ(0)', appName);
  });

  // Close drawer after menu item is selected if drawerPanel is narrow
  // app.onDataRouteClick = function() {
  //   var drawerPanel = document.querySelector('#paperDrawerPanel');
  //   if (drawerPanel.narrow) {
  //     drawerPanel.closeDrawer();
  //   }
  // };

  // Scroll page to top and expand header
  app.scrollPageToTop = function() {
    document.getElementById('mainContainer').scrollTop = 0;
  };

})(document);
<commit_msg>added on-click listener<commit_after>/*
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

(function(document) {
  'use strict';

  // Grab a reference to our auto-binding template
  // and give it some initial binding values
  // Learn more about auto-binding templates at http://goo.gl/Dx1u2g
  var app = document.querySelector('#app');
  app.myname='Joe Bloggs';
  app.headline='Headline';
  var locationsRef = new Firebase('https://pwsbooking.firebaseio.com/locations');
  app.location = '';
  app.locations = [];
  locationsRef.on('value', function(snapshot){
    //console.log(snapshot.val());
    app.locations = snapshot.val();
    //console.log(app.locations);
  });

  app.displayInstalledToast = function() {
    // Check to make sure caching is actually enabled—it won't be in the dev environment.
    if (!document.querySelector('platinum-sw-cache').disabled) {
      document.querySelector('#caching-complete').show();
    }
  };

  // Listen for template bound event to know when bindings
  // have resolved and content has been stamped to the page
  app.addEventListener('dom-change', function() {
    console.log('Our app is ready to rock!');
  });

  app.addBooking = function() {
    console.log('thanks for your submission');
    var booking = {
      name: '',
      date: '',
      time: '',
      location: '',
      email: ''
    };
    console.log(booking);
  };

  // See https://github.com/Polymer/polymer/issues/1381
  window.addEventListener('WebComponentsReady', function() {
    // imports are loaded and elements have been registered
  });

  // Main area's paper-scroll-header-panel custom condensing transformation of
  // the appName in the middle-container and the bottom title in the bottom-container.
  // The appName is moved to top and shrunk on condensing. The bottom sub title
  // is shrunk to nothing on condensing.
  addEventListener('paper-header-transform', function(e) {
    var appName = document.querySelector('#mainToolbar .app-name');
    var middleContainer = document.querySelector('#mainToolbar .middle-container');
    var bottomContainer = document.querySelector('#mainToolbar .bottom-container');
    var detail = e.detail;
    var heightDiff = detail.height - detail.condensedHeight;
    var yRatio = Math.min(1, detail.y / heightDiff);
    var maxMiddleScale = 0.50;  // appName max size when condensed. The smaller the number the smaller the condensed size.
    var scaleMiddle = Math.max(maxMiddleScale, (heightDiff - detail.y) / (heightDiff / (1-maxMiddleScale))  + maxMiddleScale);
    var scaleBottom = 1 - yRatio;

    // Move/translate middleContainer
    Polymer.Base.transform('translate3d(0,' + yRatio * 100 + '%,0)', middleContainer);

    // Scale bottomContainer and bottom sub title to nothing and back
    Polymer.Base.transform('scale(' + scaleBottom + ') translateZ(0)', bottomContainer);

    // Scale middleContainer appName
    Polymer.Base.transform('scale(' + scaleMiddle + ') translateZ(0)', appName);
  });

  // Close drawer after menu item is selected if drawerPanel is narrow
  // app.onDataRouteClick = function() {
  //   var drawerPanel = document.querySelector('#paperDrawerPanel');
  //   if (drawerPanel.narrow) {
  //     drawerPanel.closeDrawer();
  //   }
  // };

  // Scroll page to top and expand header
  app.scrollPageToTop = function() {
    document.getElementById('mainContainer').scrollTop = 0;
  };

})(document);
<|endoftext|>


<commit_before>/**
 * @TODO
 * - we should create new *.js file for each big page to avoid Cthulhu code ...
 */
(function() {
	'use strict';
	var wheelEvent = {
		init() {
			// doing different things depends on window.location.hash
			wheelEvent.navBar();
			wheelEvent.footer();
			var page = window.location.hash.split('/');
			// deleting '#' with substring
			switch (page[0].substring(1)) {
				// home page
				case '':
					// @TODO home page
					wheelEvent.homePage();
					break;

				// 404
				default:
					// @TODO page 404
					break;
			}
		},
		navBar() {
			var navBar = $(
				'' +
					'
' +
						'
cloudFirst Link With Icon
' +
						'
Second Link
' +
						'

' +
						'
Subheader
' +
						'
Third Link With Waves
' +
					'
' +
					'menu' +
				''
			);
			$('header').empty();
			$('header').append(navBar);
			navBar.find('.button-collapse').sideNav({
				menuWidth: 300,
				// Choose whether you can drag to open on touch screens
				draggable: true,
				// swipe right to left to open menu
				edge: 'left',
				// Closes side-nav on  clicks
				closeOnClick: true
			});
		},
		footer() {
			// @TODO footer ?
		},
		homePage() {
			console.log('homePage');
			// ctrl + k + 4 for better view
			/**
			 * FUNCTIONS
			 */
			var goToConnectedPage = function(isUserOk) {
				// @TODO change hash to next page then update

				// trigger leavePage of previous page
				$('main').children().trigger('leavePage', function() {
					// then display newPage
					if (isUserOk) {
						$('main').html(
							'
Bravo
' +
							'
Vous êtes bien connecté
'
						);
					}
					if (!isUserOk) {
						$('main').html(
							'
Erreur
' +
							'
Impossible de manipuler la base de données
'
						);
					}
				});
			};
			var createUserIfDoesntExist = function(socialNetworkUser, callback) {
				window.get.currentUser(function(user) {
					if (!user) {
						window.push.createUser(socialNetworkUser.displayName, socialNetworkUser.email, socialNetworkUser.photoURL, callback);
					}
					if (user) {
						callback(true);
					}
				});
			};
			var loginWithProvider = function(provider) {
				try {
					firebase.auth().signInWithPopup(provider).then(function(result) {
						// This gives you a Facebook Access Token. You can use it to access the Facebook API.
						// var token = result.credential.accessToken;
						// The signed-in user info.
						var socialNetworkUser = result.user;
						console.info('logged successfully', socialNetworkUser);
						createUserIfDoesntExist(socialNetworkUser, goToConnectedPage);
					}).catch(function(error) {
						// Handle Errors here.
						var errorCode = error.code;
						var errorMessage = error.message;
						// The email of the user's account used.
						var email = error.email;
						// The firebase.auth.AuthCredential type that was used.
						var credential = error.credential;
						// ...
						console.warn('logged failed', errorCode, errorMessage, email, credential);
					});
				} catch (e) {
					console.error(e);
				}
			};
			// home block & ids
			var id = {
				home: wheelEvent.guid(),
				btnConnectFB: wheelEvent.guid(),
				btnConnectG: wheelEvent.guid()
			};
			var home = $(
				'
' +
					'
' +
						'
WheelEvent
' +
						'
' +
							'Description du site
' +
							'Eu commodo ad aliquip nostrud irure consectetur mollit et in in ut deserunt deserunt eu deserunt ' +
							'exercitation ullamco quis cillum incididunt occaecat aliquip esse eu in ea veniam est non occaecat ' +
							'eu consequat consequat in voluptate magna sint esse est voluptate voluptate esse minim tempor labore ' +
						'
' +
						'Connexion via FB' +
						'Connexion via Google' +
					'
' +
				'
'
			);
			home.attr('id', id.home);
			home.find('#' + id.btnConnectFB).click(function() {
				console.log('connection btn');
				var provider = new firebase.auth.FacebookAuthProvider();
				loginWithProvider(provider);
			});
			home.find('#' + id.btnConnectG).click(function() {
				console.log('connection btn');
				var provider = new firebase.auth.GoogleAuthProvider();
				loginWithProvider(provider);
			});

			// manipulate container
			$('main').addClass('valign-wrapper');
			// you must call `$('main').children().trigger('leavePage');` before changing page
			home.on('leavePage', function(e, callback) {
				home.slideUp(300, function() {
					$('main').removeClass('valign-wrapper');
					home.remove();
					if (typeof callback === 'function') {
						callback();
					}
				});
			});

			// @TODO move this in another function ?
			// check if we are changing page or intiate app, then add home to page
			if ($('main').children().length === 0) {
				$('main').append(home);
			} else {
				$('main').children().trigger('leavePage', function() {
					$('main').append(home);
				});
			}

			// @TODO disconnect button when connected
			// $('#logout').click(function logout() {
			// 	firebase.auth().signOut().then(function() {
			// 		console.info('Sign-out successful.');
			// 	}).catch(function(error) {
			// 		console.warn('An error happened.', error);
			// 	});
			// });
		},
		guid() {
			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
				var r = Math.random() * 16 | 0;
				var v = c === 'x' ? r : (r & 0x3 | 0x8);
				return v.toString(16);
			});
		},
		// toString obfuscation
		toString() {
			return 'object';
		}
	};
	window.app = {
		init: wheelEvent.init
	};
	// @TODO make browser listen to window.location.hash change to detect pageChange
})();
<commit_msg>better view management<commit_after>/**
 * @NOTE
 * - Create new *.js file for each big page to avoid Cthulhu code ...
 *  -> see main.js, var scriptToLoad
 */
(function() {
	'use strict';
	// ctrl+k+3 for better view
	/**
	 * Initialize les objet principaux de la vue
	 * Usage :
		 * 	$(element).wheelEventInitialize('maSuperPage', {
		 *		onRender: function(){
		 *			// action lors du render terminé de l'element
		 *		},
		 *		onChangePage: function() {
		 *			// action lors de la suppression terminé de l'élément
		 *		},
		 * 		mustBeConnected: false // @TODO vérifie que l'user est connecté avant d'afficher la page
		 *	});
	 *	$(element).trigger('render');
	 * @param  {Object} method pour les trigger onRender et onChangePage
	 */
	$.fn.wheelEventInitialize = function(logName = 'noname', options = {}) {
		console.info('wheelEventInitialize', this);
		if (logName.constructor !== String) {
			console.warn('logName must be a String');
			return;
		}
		if (options.constructor !== Object) {
			console.warn('options must be a Object');
			return;
		}
		this.data('logName', logName);
		/**
		 * Processus de changement d'élément sur la vue :
		 * this == $(element)
		 * oldPage == element actuellement présent dans la page
		 *
		 * quand $(element).trigger('render');
		 * 	this.render
		 * 		oldPage.beforeChangePage
		 * 		oldPage.slideUp
		 * 		->	oldPage.onChangePage
		 * 			oldPage.afterChangePage
		 * 			this.beforeRender
		 * 		<-	this.slideDown
		 * 		this.onRender
		 */
		var defaultOptions = {
			onRender: function() {
				console.info('wheelEventInitialize : onRender', $(this).data('logName'));
				console.log('onRender');
			},
			onChangePage: function() {
				console.info('wheelEventInitialize : onChangePage', $(this).data('logName'));
				console.log('leaving page');
			},
			mustBeConnected: false
		};
		var base = {
			render: function() {
				console.info('wheelEventInitialize : render', $(this).data('logName'));
				if ($('main').children().length === 0) {
					$('main').append($(this));
					$(this).trigger('beforeRender');
				} else {
					$('main').children().trigger('beforeChangePage', [this]);
				}
			},
			beforeChangePage: function(e, newPage) {
				console.info('wheelEventInitialize : beforeChangePage', $(this).data('logName'));
				var _this = this;
				$(this).slideUp(700, function() {
					$(_this).trigger('onChangePage');
					$(_this).trigger('afterChangePage', [newPage]);
				});
			},
			afterChangePage: function(e, newPage) {
				console.info('wheelEventInitialize : afterChangePage', $(this).data('logName'));
				$(this).remove();
				$('main').append($(newPage));
				$(newPage).trigger('beforeRender');
			},
			beforeRender: function() {
				console.info('wheelEventInitialize : beforeRender', $(this).data('logName'));
				var _this = this;
				$(this).css('display', 'none');
				$(_this).trigger('onRender');
				$(this).slideDown(700);
			}
		};
		var opt = Object.assign(defaultOptions, options, base);
		this.on('onRender', opt.onRender);
		this.on('onChangePage', opt.onChangePage);
		this.on('beforeChangePage', opt.beforeChangePage);
		this.on('afterChangePage', opt.afterChangePage);
		this.on('beforeRender', opt.beforeRender);
		this.on('render', opt.render);
	};

	var wheelEvent = {
		init() {
			// doing different things depends on window.location.hash
			wheelEvent.navBar();
			wheelEvent.footer();

			var onHashChange = function() {
				var page = window.location.hash.split('/');
				// deleting '#' with substring
				switch (page[0].substring(1)) {
					// home page
					case '':
						// @TODO home page
						wheelEvent.homePage();
						break;

					// 404
					default:
						wheelEvent.pageNotFound();
						break;
				}
			};
			// cross browser hash change detection
			if (!('onhashchange' in window)) {
				var oldHref = location.href;
				setInterval(function() {
					var newHref = location.href;
					if (oldHref !== newHref) {
						var _oldHref = oldHref;
						oldHref = newHref;
						onHashChange.call(window, {
							type: 'hashchange',
							newURL: newHref,
							oldURL: _oldHref
						});
					}
				}, 100);
			} else if (window.addEventListener) {
				window.addEventListener('hashchange', onHashChange, false);
			} else if (window.attachEvent) {
				window.attachEvent('onhashchange', onHashChange);
			}
			onHashChange();
		},
		navBar() {
			var navBar = $(
				'' +
					'
' +
						'
cloudFirst Link With Icon
' +
						'
Second Link
' +
						'

' +
						'
Subheader
' +
						'
Third Link With Waves
' +
					'
' +
					'menu' +
				''
			);
			$('header').empty();
			$('header').append(navBar);
			navBar.find('.button-collapse').sideNav({
				menuWidth: 300,
				// Choose whether you can drag to open on touch screens
				draggable: true,
				// swipe right to left to open menu
				edge: 'left',
				// Closes side-nav on  clicks
				closeOnClick: true
			});
		},
		footer() {
			// @TODO footer ?
		},
		homePage() {
			console.info('wheelEvent.homePage()');
			// ctrl + k + 4 for better view
			/**
			 * FUNCTIONS
			 */
			/**
			 * fonction temporaire, il suffit de changer window.location.hash pour changer de page
			 * @param {Boolean} isUserOk true if correctly connected
			 */
			var goToConnectedPage = function(isUserOk) {
				// @TODO change hash to next page then update

				// trigger leavePage of previous page
				$('main').children().trigger('leavePage', function() {
					// then display newPage
					if (isUserOk) {
						$('main').html(
							'
Bravo
' +
							'
Vous êtes bien connecté
'
						);
					}
					if (!isUserOk) {
						$('main').html(
							'
Erreur
' +
							'
Impossible de manipuler la base de données
'
						);
					}
				});
			};
			var createUserIfDoesntExist = function(socialNetworkUser, callback) {
				window.get.currentUser(function(user) {
					if (!user) {
						window.push.createUser(socialNetworkUser.displayName, socialNetworkUser.email, socialNetworkUser.photoURL, callback);
					}
					if (user) {
						callback(true);
					}
				});
			};
			var loginWithProvider = function(provider) {
				try {
					firebase.auth().signInWithPopup(provider).then(function(result) {
						// This gives you a Facebook Access Token. You can use it to access the Facebook API.
						// var token = result.credential.accessToken;
						// The signed-in user info.
						var socialNetworkUser = result.user;
						console.info('logged successfully', socialNetworkUser);
						createUserIfDoesntExist(socialNetworkUser, goToConnectedPage);
					}).catch(function(error) {
						// Handle Errors here.
						var errorCode = error.code;
						var errorMessage = error.message;
						// The email of the user's account used.
						var email = error.email;
						// The firebase.auth.AuthCredential type that was used.
						var credential = error.credential;
						// ...
						console.warn('logged failed', errorCode, errorMessage, email, credential);
					});
				} catch (e) {
					console.error(e);
				}
			};
			// home block & ids
			var id = {
				home: wheelEvent.guid(),
				btnConnectFB: wheelEvent.guid(),
				btnConnectG: wheelEvent.guid()
			};
			var home = $(
				'
' +
					'
' +
						'
WheelEvent
' +
						'
' +
							'Description du site
' +
							'Eu commodo ad aliquip nostrud irure consectetur mollit et in in ut deserunt deserunt eu deserunt ' +
							'exercitation ullamco quis cillum incididunt occaecat aliquip esse eu in ea veniam est non occaecat ' +
							'eu consequat consequat in voluptate magna sint esse est voluptate voluptate esse minim tempor labore ' +
						'
' +
						'Connexion via FB' +
						'Connexion via Google' +
					'
' +
				'
'
			);
			home.wheelEventInitialize('homePage', {
				onRender: function() {
					console.info('wheelEventInitialize : onRender', $(this).data('logName'));
					$('main').addClass('valign-wrapper');
				},
				onChangePage: function() {
					console.info('wheelEventInitialize : onChangePage', $(this).data('logName'));
					$('main').removeClass('valign-wrapper');
				}
			});
			home.attr('id', id.home);
			home.find('#' + id.btnConnectFB).click(function() {
				console.log('connection btn');
				var provider = new firebase.auth.FacebookAuthProvider();
				loginWithProvider(provider);
			});
			home.find('#' + id.btnConnectG).click(function() {
				console.log('connection btn');
				var provider = new firebase.auth.GoogleAuthProvider();
				loginWithProvider(provider);
			});

			// @TODO move this in another function ?
			// check if we are changing page or intiate app, then add home to page
			home.trigger('render');

			// @TODO disconnect button when connected
			// $('#logout').click(function logout() {
			// 	firebase.auth().signOut().then(function() {
			// 		console.info('Sign-out successful.');
			// 	}).catch(function(error) {
			// 		console.warn('An error happened.', error);
			// 	});
			// });
		},
		pageNotFound() {
			console.info('wheelEvent.pageNotFound()');
			var pageNotFound = $(
				'
' +
					'
' +
						'
Erreur 404
' +
						'
' +
							'Page introuvable ou inexistante' +
						'
' +
					'
' +
				'
'
			);
			pageNotFound.wheelEventInitialize('pageNotFound');
			pageNotFound.trigger('render');
		},
		guid() {
			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
				var r = Math.random() * 16 | 0;
				var v = c === 'x' ? r : (r & 0x3 | 0x8);
				return v.toString(16);
			});
		},
		toString() {
			// toString obfuscation
			return 'Object';
		}
	};
	window.app = {
		init: wheelEvent.init
	};
})();
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

(function(document) {
  'use strict';

  // Grab a reference to our auto-binding template
  // and give it some initial binding values
  // Learn more about auto-binding templates at http://goo.gl/Dx1u2g
  var app = document.querySelector('#app');

  app.moduleDescriptionWebrtc = "With the WebRTC connector all users exchange changes directly with each other. While WebRTC is not the most reliable connector, messages are propagated with almost no delay.\n\
\n\
* Very fast message propagation (not noticeable)\n\
* Very easy to use\n\
* Very little server load (you still have to set up a [signaling server](http://www.html5rocks.com/en/tutorials/webrtc/infrastructure/))\n\
* Not suited for a large amount of collaborators\n\
* WebRTC is not supported in all browsers, and some have troubles communicating with each other\n\
* Works only in the browser"

  app.moduleDescriptionWebsockets = "With the websockets connector you can set up a central server that saves changes and communicates with clients.\n\
This option is very similar to other shared editing frameworks that require a central server.\n\
Because the websocket connector is build on top of [socket.io](socket.io), this connector is a rock solid choice\n\
if you require high reliability.\n\
\n\
* Extremely reliable\n\
* Very easy to use\n\
* Some server load\n\
* You can set up a central server that persists changes\n\
* Falls back to http-communication, if websockets are not supported\n\
* Work with nodejs and in the browser"

  app.moduleDescriptionXmpp = "XMPP is a well known federated protocol to exchange data. This is definitely an interesting choice if you require high scalability.\n\
\n\
* Can act as a Connector for a scaling number of users\n\
* Sophisticated Rights Management\n\
* Federated\n\
* Works with nodejs and in the browser"

  app.moduleDescriptionIndexeddb = "Use the IndexedDB database adapter to store your shared data\n\
persistently in the browser. The next time you join the session,\n\
your changes will still be there.\n\
\n\
* Minimizes the amount of data exchanged between server and client\n\
* Makes offline editing possible\n\
* Not supported by all browsers"

  app.moduleDescriptionMemory = "Use the Memory database adapter to store your shared data\n\
efficiently in-memory. The next time you join the session,\n\
your changes will be lost\n\
\n\
* Supported by all browsers"

  app.moduleDescriptionMap = "Use the Y.Map type to map key-value pairs.\n\
```\n\
// Create a new Y.Map type\n\
y.share.map.set('new map type', Y.Map).then(function (map) {\n\
  // Observe the map type\n\
  map.observePath(['my value'], function (value) {\n\
    console.log(\"You created a new value:\", value)\n\
  })\n\
  // Now we create a new property\n\
  map.set('my value', 42) // => \"You created a new value: 42\"\n\
  // And retrieve the value\n\
  map.get('my value') // => 42\n\
})\n\
```"

  app.moduleDescriptionArray = "Use the Y.Array type to handle shared lists of data.\n\
```\n\
// Observe the array type\n\
y.share.array.observe(function (events) {\n\
  for (var i = 0; i < events.length; i++) {\n\
    console.log(\"New event: \", events[i])\n\
  }\n\
})\n\
y.share.array.insert(0, [1])\n\
  // => \"New event: {type: \"Insert\", position: 0, value: 1}\"\n\
y.share.array.delete(0, 1)\n\
  // => \"New event: {type: \"Delete\", position: 0, length: 1}\"\n\
```"

  app.moduleDescriptionText = "Use the Y.Text type to share text content, and bind it to\n\
arbitrary input elements (E.g. input, textarea, or any element that has the *contenteditable* property)\n\
```\n\
// bind text to the first p element that is contenteditable\n\
y.share.text.bind(document.querySelector(\"p[contenteditable]\"))\n\
```"

  app.moduleDescriptionRichtext = "Use the Y.RichText type to share rich text, and bind it to\n\
  the [quill editor](http://quilljs.com/).\n\
\n\
```\n\
// bind richtext to an instance of quill\n\
y.share.richtext.bind(document.querySelector(\"quill\"))\n\
```"

  app.moduleDescriptionXml = "Use the Y.Xml type to share XML content, and bind it to\n\
the the browser DOM to observe the real-time changes\n\
\n\
**NOTE:** This type is currently migrating and not available in yjs@1.0.*\n\
```\n\
// create a DOM double binding\n\
var shared_dom = y.share.xml.getDOM()\n\
// and append it to the body\n\
document.body.append(shared_dom)\n\
```"

  function createBlogpostDefinition (date, name) {
    return {
      date: date,
      url: '/article/' + name + '.md',
      title: name
    }
  }

  app.blogposts = [
    createBlogpostDefinition("19 November 2015", "Yjs Release 0.6"),
    createBlogpostDefinition("13 May 2015", "Yjs Release 0.5"),
    createBlogpostDefinition("10 February 2015", "Yjs Release 0.4")
  ]

  app.blogpostUrlToName = function blogpostUrlToName (url) {
    url = url.split('/')
    return url[url.length - 1].slice(0, -3)
  }

  app.displayInstalledToast = function() {
    // Check to make sure caching is actually enabled—it won't be in the dev environment.
    if (!document.querySelector('platinum-sw-cache').disabled) {
      document.querySelector('#caching-complete').show();
    }
  };

  // Listen for template bound event to know when bindings
  // have resolved and content has been stamped to the page
  app.addEventListener('dom-change', function() {
    console.log('Our app is ready to rock!');
    var t = document.getElementById('mainToolbar')
    if (app._isMobile) {
      t.classList.remove('tall')
    } else {
      t.classList.add('tall')
    }
    function loadScript (url) {
      var tag = document.createElement('script')
      tag.src = url
      document.head.appendChild(tag)
    }

    loadScript('./bower_components/yjs/Examples/Textarea/index.js')
    loadScript('./bower_components/yjs/Examples/Jigsaw/index.js')
    loadScript('./bower_components/yjs/Examples/Chat/index.js')
    loadScript('./bower_components/yjs/Examples/Ace/index.js')
    loadScript('./bower_components/yjs/Examples/Quill/index.js')
  });

  // See https://github.com/Polymer/polymer/issues/1381
  window.addEventListener('WebComponentsReady', function() {
    // imports are loaded and elements have been registered
  });

  // Main area's paper-scroll-header-panel custom condensing transformation of
  // the appName in the middle-container and the bottom title in the bottom-container.
  // The appName is moved to top and shrunk on condensing. The bottom sub title
  // is shrunk to nothing on condensing.
  addEventListener('paper-header-transform', function(e) {
    var appName = document.querySelector('#mainToolbar .app-name');
    var middleContainer = document.querySelector('#mainToolbar .middle-container');
    var bottomContainer = document.querySelector('#mainToolbar .bottom-container');
    var detail = e.detail;
    var heightDiff = detail.height - detail.condensedHeight;
    var yRatio = Math.min(1, detail.y / heightDiff);
    var maxMiddleScale = 0.50;  // appName max size when condensed. The smaller the number the smaller the condensed size.
    var scaleMiddle = Math.max(maxMiddleScale, (heightDiff - detail.y) / (heightDiff / (1-maxMiddleScale))  + maxMiddleScale);
    var scaleBottom = 1 - yRatio;

    // Move/translate middleContainer
    Polymer.Base.transform('translate3d(0,' + yRatio * 100 + '%,0)', middleContainer);

    // Scale bottomContainer and bottom sub title to nothing and back
    Polymer.Base.transform('scale(' + scaleBottom + ') translateZ(0)', bottomContainer);

    // Scale middleContainer appName
    Polymer.Base.transform('scale(' + scaleMiddle + ') translateZ(0)', appName);
  });

  // Close drawer after menu item is selected if drawerPanel is narrow
  app.onDataRouteClick = function() {
    var drawerPanel = document.querySelector('#paperDrawerPanel');
    if (drawerPanel.narrow) {
      drawerPanel.closeDrawer();
    }
  };

  // Scroll page to top and expand header
  app.scrollPageToTop = function() {
    document.getElementById('mainContainer').scrollTop = 0;
  };

  app.getMainMode = function (isMobile) {
    return isMobile ? 'scroll' : 'cover'
  }

  app.properties._isMobile = {
    type: String,
    notify: true,
    observer: 'setMainToolbarClass'
  }

  app.setMainToolbarClass = function (isMobile) {
    var tb = document.getElementById('mainToolbar')
    if (tb == null) {
      app.initialToolbarClass = isMobile ? '' : 'tall'
      return
    }

    if (isMobile) {
      tb.classList.remove('tall')
    } else {
      tb.classList.add('tall')
    }
  }

  var loadAnatomyIframeToken = false
  app.loadAnatomyIframe = function loadAnatomyIframe () {
    if (!loadAnatomyIframeToken) {
      loadAnatomyIframeToken = true
      var container = document.querySelector('#putAnatomyIframeHere')
      while (container.children[0] != null) {
        container.children[0].remove()
      }
      var iframe = document.createElement('iframe')
      iframe.setAttribute('src', 'http://dbis.rwth-aachen.de/3dnrt/yjs_demo/')
      container.appendChild(iframe)
    }
  }

  app.topologyTotal = {
    "nodes":[
      {"name":"Client 1","group":1},
      {"name":"Client 2","group":2},
      {"name":"Client 3","group":3},
      {"name":"Client 4","group":4},
      {"name":"Client 5","group":5},
      {"name":"Client 6","group":6}
    ],
    "links":[
      {"source":0,"target":0},
      {"source":0,"target":1},
      {"source":0,"target":2},
      {"source":0,"target":3},
      {"source":0,"target":4},
      {"source":0,"target":5},

      {"source":1,"target":1},
      {"source":1,"target":2},
      {"source":1,"target":3},
      {"source":1,"target":4},
      {"source":1,"target":5},

      {"source":2,"target":2},
      {"source":2,"target":3},
      {"source":2,"target":4},
      {"source":2,"target":5},

      {"source":3,"target":3},
      {"source":3,"target":4},
      {"source":3,"target":5},

      {"source":4,"target":4},
      {"source":4,"target":5}
    ]
  }
  app.topologyStar = {
    "nodes":[
      {"name":"Server","group":1},
      {"name":"Client 1","group":0},
      {"name":"Client 2","group":0},
      {"name":"Client 3","group":0},
      {"name":"Client 4","group":0},
      {"name":"Client 5","group":0},
      {"name":"Client 6","group":0}
    ],
    "links":[
      {"source":0,"target":1},
      {"source":0,"target":2},
      {"source":0,"target":3},
      {"source":0,"target":4},
      {"source":0,"target":5},
      {"source":0,"target":6}
    ]
  }

  app.topologyFederated = {
    "nodes":[
      {"name":"XMPP Server","group":1}, // 0
      {"name":"XMPP Server","group":2}, // 1
      {"name":"XMPP Server","group":3}, // 2
      {"name":"Client","group":0}, // 3
      {"name":"Client","group":0}, // 4
      {"name":"Client","group":0}, // 5
      {"name":"Client","group":0}, // 6
      {"name":"Client","group":0}, // 7
      {"name":"Client","group":0}  // 8
    ],
    "links":[
      {"source":0,"target":3},
      {"source":0,"target":4},
      {"source":1,"target":5},
      {"source":2,"target":6},
      {"source":2,"target":7},
      {"source":2,"target":8},

      {"source":0,"target":1},
      {"source":0,"target":2},
      {"source":1,"target":2}
    ]
  }

})(document);
<commit_msg>Fixed internet explorer #1<commit_after>/*
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/

(function(document) {
  'use strict';

  // Grab a reference to our auto-binding template
  // and give it some initial binding values
  // Learn more about auto-binding templates at http://goo.gl/Dx1u2g
  var app = document.querySelector('#app');

  app.moduleDescriptionWebrtc = "With the WebRTC connector all users exchange changes directly with each other. While WebRTC is not the most reliable connector, messages are propagated with almost no delay.\n\
\n\
* Very fast message propagation (not noticeable)\n\
* Very easy to use\n\
* Very little server load (you still have to set up a [signaling server](http://www.html5rocks.com/en/tutorials/webrtc/infrastructure/))\n\
* Not suited for a large amount of collaborators\n\
* WebRTC is not supported in all browsers, and some have troubles communicating with each other\n\
* Works only in the browser"

  app.moduleDescriptionWebsockets = "With the websockets connector you can set up a central server that saves changes and communicates with clients.\n\
This option is very similar to other shared editing frameworks that require a central server.\n\
Because the websocket connector is build on top of [socket.io](socket.io), this connector is a rock solid choice\n\
if you require high reliability.\n\
\n\
* Extremely reliable\n\
* Very easy to use\n\
* Some server load\n\
* You can set up a central server that persists changes\n\
* Falls back to http-communication, if websockets are not supported\n\
* Work with nodejs and in the browser"

  app.moduleDescriptionXmpp = "XMPP is a well known federated protocol to exchange data. This is definitely an interesting choice if you require high scalability.\n\
\n\
* Can act as a Connector for a scaling number of users\n\
* Sophisticated Rights Management\n\
* Federated\n\
* Works with nodejs and in the browser"

  app.moduleDescriptionIndexeddb = "Use the IndexedDB database adapter to store your shared data\n\
persistently in the browser. The next time you join the session,\n\
your changes will still be there.\n\
\n\
* Minimizes the amount of data exchanged between server and client\n\
* Makes offline editing possible\n\
* Not supported by all browsers"

  app.moduleDescriptionMemory = "Use the Memory database adapter to store your shared data\n\
efficiently in-memory. The next time you join the session,\n\
your changes will be lost\n\
\n\
* Supported by all browsers"

  app.moduleDescriptionMap = "Use the Y.Map type to map key-value pairs.\n\
```\n\
// Create a new Y.Map type\n\
y.share.map.set('new map type', Y.Map).then(function (map) {\n\
  // Observe the map type\n\
  map.observePath(['my value'], function (value) {\n\
    console.log(\"You created a new value:\", value)\n\
  })\n\
  // Now we create a new property\n\
  map.set('my value', 42) // => \"You created a new value: 42\"\n\
  // And retrieve the value\n\
  map.get('my value') // => 42\n\
})\n\
```"

  app.moduleDescriptionArray = "Use the Y.Array type to handle shared lists of data.\n\
```\n\
// Observe the array type\n\
y.share.array.observe(function (events) {\n\
  for (var i = 0; i < events.length; i++) {\n\
    console.log(\"New event: \", events[i])\n\
  }\n\
})\n\
y.share.array.insert(0, [1])\n\
  // => \"New event: {type: \"Insert\", position: 0, value: 1}\"\n\
y.share.array.delete(0, 1)\n\
  // => \"New event: {type: \"Delete\", position: 0, length: 1}\"\n\
```"

  app.moduleDescriptionText = "Use the Y.Text type to share text content, and bind it to\n\
arbitrary input elements (E.g. input, textarea, or any element that has the *contenteditable* property)\n\
```\n\
// bind text to the first p element that is contenteditable\n\
y.share.text.bind(document.querySelector(\"p[contenteditable]\"))\n\
```"

  app.moduleDescriptionRichtext = "Use the Y.RichText type to share rich text, and bind it to\n\
  the [quill editor](http://quilljs.com/).\n\
\n\
```\n\
// bind richtext to an instance of quill\n\
y.share.richtext.bind(document.querySelector(\"quill\"))\n\
```"

  app.moduleDescriptionXml = "Use the Y.Xml type to share XML content, and bind it to\n\
the the browser DOM to observe the real-time changes\n\
\n\
**NOTE:** This type is currently migrating and not available in yjs@1.0.*\n\
```\n\
// create a DOM double binding\n\
var shared_dom = y.share.xml.getDOM()\n\
// and append it to the body\n\
document.body.append(shared_dom)\n\
```"

  function createBlogpostDefinition (date, name) {
    return {
      date: date,
      url: '/article/' + name + '.md',
      title: name
    }
  }

  app.blogposts = [
    createBlogpostDefinition("19 November 2015", "Yjs Release 0.6"),
    createBlogpostDefinition("13 May 2015", "Yjs Release 0.5"),
    createBlogpostDefinition("10 February 2015", "Yjs Release 0.4")
  ]

  app.blogpostUrlToName = function blogpostUrlToName (url) {
    url = url.split('/')
    return url[url.length - 1].slice(0, -3)
  }

  app.displayInstalledToast = function() {
    // Check to make sure caching is actually enabled—it won't be in the dev environment.
    if (!document.querySelector('platinum-sw-cache').disabled) {
      document.querySelector('#caching-complete').show();
    }
  };

  // Listen for template bound event to know when bindings
  // have resolved and content has been stamped to the page
  app.addEventListener('dom-change', function() {
    console.log('Our app is ready to rock!');
    var t = document.getElementById('mainToolbar')
    if (app._isMobile) {
      t.classList.remove('tall')
    } else {
      t.classList.add('tall')
    }
    function loadScript (url) {
      var tag = document.createElement('script')
      tag.src = url
      document.head.appendChild(tag)
    }

    loadScript('./bower_components/yjs/Examples/Textarea/index.js')
    loadScript('./bower_components/yjs/Examples/Jigsaw/index.js')
    loadScript('./bower_components/yjs/Examples/Chat/index.js')
    loadScript('./bower_components/yjs/Examples/Ace/index.js')
    loadScript('./bower_components/yjs/Examples/Quill/index.js')
  });

  // See https://github.com/Polymer/polymer/issues/1381
  window.addEventListener('WebComponentsReady', function() {
    // imports are loaded and elements have been registered
  });

  // Main area's paper-scroll-header-panel custom condensing transformation of
  // the appName in the middle-container and the bottom title in the bottom-container.
  // The appName is moved to top and shrunk on condensing. The bottom sub title
  // is shrunk to nothing on condensing.
  addEventListener('paper-header-transform', function(e) {
    var appName = document.querySelector('#mainToolbar .app-name');
    var middleContainer = document.querySelector('#mainToolbar .middle-container');
    var bottomContainer = document.querySelector('#mainToolbar .bottom-container');
    var detail = e.detail;
    var heightDiff = detail.height - detail.condensedHeight;
    var yRatio = Math.min(1, detail.y / heightDiff);
    var maxMiddleScale = 0.50;  // appName max size when condensed. The smaller the number the smaller the condensed size.
    var scaleMiddle = Math.max(maxMiddleScale, (heightDiff - detail.y) / (heightDiff / (1-maxMiddleScale))  + maxMiddleScale);
    var scaleBottom = 1 - yRatio;

    // Move/translate middleContainer
    Polymer.Base.transform('translate3d(0,' + yRatio * 100 + '%,0)', middleContainer);

    // Scale bottomContainer and bottom sub title to nothing and back
    Polymer.Base.transform('scale(' + scaleBottom + ') translateZ(0)', bottomContainer);

    // Scale middleContainer appName
    Polymer.Base.transform('scale(' + scaleMiddle + ') translateZ(0)', appName);
  });

  // Close drawer after menu item is selected if drawerPanel is narrow
  app.onDataRouteClick = function() {
    var drawerPanel = document.querySelector('#paperDrawerPanel');
    if (drawerPanel.narrow) {
      drawerPanel.closeDrawer();
    }
  };

  // Scroll page to top and expand header
  app.scrollPageToTop = function() {
    document.getElementById('mainContainer').scrollTop = 0;
  };

  app.getMainMode = function (isMobile) {
    return isMobile ? 'scroll' : 'cover'
  }

  if (app.properties == null) {
    app.properties = {}
  }

  app.properties._isMobile = {
    type: String,
    notify: true,
    observer: 'setMainToolbarClass'
  }

  app.setMainToolbarClass = function (isMobile) {
    var tb = document.getElementById('mainToolbar')
    if (tb == null) {
      app.initialToolbarClass = isMobile ? '' : 'tall'
      return
    }

    if (isMobile) {
      tb.classList.remove('tall')
    } else {
      tb.classList.add('tall')
    }
  }

  var loadAnatomyIframeToken = false
  app.loadAnatomyIframe = function loadAnatomyIframe () {
    if (!loadAnatomyIframeToken) {
      loadAnatomyIframeToken = true
      var container = document.querySelector('#putAnatomyIframeHere')
      while (container.children[0] != null) {
        container.children[0].remove()
      }
      var iframe = document.createElement('iframe')
      iframe.setAttribute('src', 'http://dbis.rwth-aachen.de/3dnrt/yjs_demo/')
      container.appendChild(iframe)
    }
  }

  app.topologyTotal = {
    "nodes":[
      {"name":"Client 1","group":1},
      {"name":"Client 2","group":2},
      {"name":"Client 3","group":3},
      {"name":"Client 4","group":4},
      {"name":"Client 5","group":5},
      {"name":"Client 6","group":6}
    ],
    "links":[
      {"source":0,"target":0},
      {"source":0,"target":1},
      {"source":0,"target":2},
      {"source":0,"target":3},
      {"source":0,"target":4},
      {"source":0,"target":5},

      {"source":1,"target":1},
      {"source":1,"target":2},
      {"source":1,"target":3},
      {"source":1,"target":4},
      {"source":1,"target":5},

      {"source":2,"target":2},
      {"source":2,"target":3},
      {"source":2,"target":4},
      {"source":2,"target":5},

      {"source":3,"target":3},
      {"source":3,"target":4},
      {"source":3,"target":5},

      {"source":4,"target":4},
      {"source":4,"target":5}
    ]
  }
  app.topologyStar = {
    "nodes":[
      {"name":"Server","group":1},
      {"name":"Client 1","group":0},
      {"name":"Client 2","group":0},
      {"name":"Client 3","group":0},
      {"name":"Client 4","group":0},
      {"name":"Client 5","group":0},
      {"name":"Client 6","group":0}
    ],
    "links":[
      {"source":0,"target":1},
      {"source":0,"target":2},
      {"source":0,"target":3},
      {"source":0,"target":4},
      {"source":0,"target":5},
      {"source":0,"target":6}
    ]
  }

  app.topologyFederated = {
    "nodes":[
      {"name":"XMPP Server","group":1}, // 0
      {"name":"XMPP Server","group":2}, // 1
      {"name":"XMPP Server","group":3}, // 2
      {"name":"Client","group":0}, // 3
      {"name":"Client","group":0}, // 4
      {"name":"Client","group":0}, // 5
      {"name":"Client","group":0}, // 6
      {"name":"Client","group":0}, // 7
      {"name":"Client","group":0}  // 8
    ],
    "links":[
      {"source":0,"target":3},
      {"source":0,"target":4},
      {"source":1,"target":5},
      {"source":2,"target":6},
      {"source":2,"target":7},
      {"source":2,"target":8},

      {"source":0,"target":1},
      {"source":0,"target":2},
      {"source":1,"target":2}
    ]
  }

})(document);
<|endoftext|>


<commit_before>import Immutable from 'immutable'

export const CHOOSE_NICK = 'CHOOSE_NICK'
export const ADD_COMMENT = 'ADD_COMMENT'

/*
 * action creators
 */

export function setNick(nick) {
  return { type: CHOOSE_NICK, nick }
}

export function addLocalComment(nick, text) {
  return { type: ADD_COMMENT,
    comment: Immutable.Map({
      nick: nick, // figure out how to pass own nick here
      ISOTime: new Date().toISOString(),
      text: text
    })
  }
}

export function addComment(nick, ISOTime, text) {
  return { type: ADD_COMMENT,
    comment: Immutable.Map({
      nick: nick,
      ISOTime: ISOTime,
      text: text
    })
  }
}
<commit_msg>Remove the old actions.js<commit_after><|endoftext|>


<commit_before>/** @module */

import Vue from 'vue';
import _ from 'lodash';
import * as Misc from '@/helpers/Misc';
import { def } from './common';
import batchedAdd from '../batchedAdd';

let nextBufferId = 0;

/** The IRC buffer instance */
export default class BufferState {
    constructor(name, networkid, state, messageDict) {
        // Enumerable properties that become reactive under Vue
        this.id = nextBufferId++;
        this.networkid = networkid;
        this.name = name;
        this.topics = [];
        this.key = '';
        this.joined = false;
        this.enabled = true;
        this.created_at = null;
        this.users = Object.create(null);
        this.modes = Object.create(null);
        this.flags = {
            unread: 0,
            alert_on: 'default',
            has_opened: false,
            channel_badkey: false,
            chathistory_available: true,
            requested_modes: false,
            requested_banlist: false,
        };
        this.settings = { };
        this.last_read = 0;
        this.active_timeout = null;
        this.message_count = 0;
        this.current_input = '';

        Vue.observable(this);

        // Some non-enumerable properties (vues $watch won't cover these properties)
        def(this, 'state', state, false);
        def(this, 'messageDict', messageDict, false);

        let messagesObj = {
            networkid: this.networkid,
            buffer: this.name,
            messages: [],
        };
        this.messageDict.push(messagesObj);
        def(this, 'messagesObj', messagesObj, false);

        def(this, 'addMessageBatch', createMessageBatch(this), false);
        def(this, 'addUserBatch', createUserBatch(this), false);

        // If we don't have away-notify then we need to manually update our nicklist
        // to get the current away statuses
        let awayNotifyEnabled = this.getNetwork().ircClient.network.cap.isEnabled('away-notify');
        if (this.isChannel() && !awayNotifyEnabled) {
            startWhoLoop(this);
        }
    }

    get topic() {
        return this.topics.length === 0 ?
            '' :
            this.topics[this.topics.length - 1];
    }

    set topic(newVal) {
        this.topics.push(newVal);
    }

    getNetwork() {
        return this.state.getNetwork(this.networkid);
    }

    getMessages() {
        let bufMessages = _.find(this.messageDict, {
            networkid: this.networkid,
            buffer: this.name,
        });

        return bufMessages ?
            bufMessages.messages :
            [];
    }

    isServer() {
        return this.name === '*';
    }

    isChannel() {
        let chanPrefixes = ['#', '&'];
        let ircNetwork = this.getNetwork().ircClient.network;
        if (ircNetwork && ircNetwork.options.CHANTYPES) {
            chanPrefixes = ircNetwork.options.CHANTYPES;
        }

        return chanPrefixes.indexOf(this.name[0]) > -1;
    }

    isQuery() {
        let chanPrefixes = ['#', '&'];
        let ircNetwork = this.getNetwork().ircClient.network;
        if (ircNetwork && ircNetwork.options.CHANTYPES) {
            chanPrefixes = ircNetwork.options.CHANTYPES;
        }

        return chanPrefixes.indexOf(this.name[0]) === -1 &&
            !this.isSpecial() &&
            !this.isServer();
    }

    isSpecial() {
        // Special buffer names (Usually controller queries, like *status or *raw).
        // Server buffer '*' is not included in this classification.
        let name = this.name;
        return name[0] === '*' && name.length > 1;
    }

    isUserAnOp(nick) {
        let user = this.state.getUser(this.networkid, nick);
        if (!user) {
            return false;
        }

        let userBufferInfo = user.buffers[this.id];
        if (!userBufferInfo) {
            return false;
        }

        let modes = userBufferInfo.modes;
        let opModes = ['Y', 'y', 'q', 'a', 'o', 'h'];
        let hasOp = _.find(modes, mode => opModes.indexOf(mode.toLowerCase()) > -1);

        return !!hasOp;
    }

    /**
     * Get a users prefix symbol on a buffer from its modes
     * @param {Object} user The user object
     */
    userModePrefix(user) {
        // The user may not be on the buffer
        if (!user.buffers[this.id]) {
            return '';
        }

        let modes = user.buffers[this.id].modes;
        if (modes.length === 0) {
            return '';
        }

        let network = this.getNetwork();
        let netPrefixes = network.ircClient.network.options.PREFIX;
        // Find the first (highest) netPrefix in the users buffer modes
        let prefix = _.find(netPrefixes, p => modes.indexOf(p.mode) > -1);

        return prefix ?
            prefix.symbol :
            '';
    }

    /**
     * Get a users mode on a buffer
     * @param user {Object} The user object
     */
    userMode(user) {
        // The user may not be on the buffer
        if (!user.buffers[this.id]) {
            return '';
        }

        let modes = user.buffers[this.id].modes;
        if (modes.length === 0) {
            return '';
        }

        let network = this.getNetwork();
        let netPrefixes = network.ircClient.network.options.PREFIX;
        // Find the first (highest) netPrefix in the users buffer modes
        let prefix = _.find(netPrefixes, p => modes.indexOf(p.mode) > -1);

        return prefix ?
            prefix.mode :
            '';
    }

    setting(name, val) {
        if (typeof val !== 'undefined') {
            this.state.$set(this.settings, name, val);
            return val;
        }

        // Check the buffer specific settings before reverting to global settings
        let result = typeof this.settings[name] !== 'undefined' ?
            this.settings[name] :
            this.state.setting('buffers.' + name);

        return result;
    }

    rename(newName) {
        let network = this.getNetwork();
        let oldName = this.name;
        let setActive = this.state.getActiveBuffer() === this;

        this.name = newName;
        if (setActive) {
            this.state.setActiveBuffer(network.id, newName);
        }

        // update the buffer name on our messages
        let bufferMessages = _.find(this.messageDict, { networkid: network.id, buffer: oldName });
        bufferMessages.buffer = newName;
    }

    flag(name, val) {
        if (typeof val !== 'undefined') {
            this.state.$set(this.flags, name, val);
            return val;
        }

        return this.flags[name];
    }

    requestScrollback(_direction) {
        let direction = _direction || 'backward';
        let time = '';
        // Negative number gets messages before the timestamps, positive gets messages after
        let numMessages = -50;

        // Going backwards takes the earliest message we already have and requests messages
        // before it. Going forward takes the last message we have and requests messages after
        // it.

        if (direction === 'backward') {
            let lastMessage = this.getMessages().reduce((earliest, current) => {
                let validType = earliest.type !== 'traffic';
                if (validType && earliest.time && earliest.time < current.time) {
                    return earliest;
                }
                return current;
            }, this.getMessages()[0]);

            numMessages = -50;
            time = lastMessage ?
                new Date(lastMessage.time) :
                new Date();
        } else if (direction === 'forward') {
            let firstMessage = this.getMessages().reduce((latest, current) => {
                let validType = latest.type !== 'traffic';
                if (validType && latest.time && latest.time > current.time) {
                    return latest;
                }
                return current;
            }, this.getMessages()[0]);

            numMessages = 50;
            time = firstMessage ?
                new Date(firstMessage.time) :
                new Date();
        } else {
            throw new Error('Invalid direction for requestScrollback(): ' + _direction);
        }

        let irc = this.getNetwork().ircClient;
        let timeStr = Misc.dateIso(time);
        irc.raw(`CHATHISTORY ${this.name} timestamp=${timeStr} message_count=${numMessages}`);
        irc.once('batch end chathistory', (event) => {
            if (event.commands.length === 0) {
                this.flags.chathistory_available = false;
            } else {
                this.flags.chathistory_available = true;
            }
        });
    }

    markAsRead(delayed) {
        if (this.active_timeout) {
            clearTimeout(this.active_timeout);
            this.active_timeout = null;
        }
        if (delayed) {
            this.active_timeout = setTimeout(
                this.markAsRead.bind(this),
                10000,
                false
            );
        } else {
            this.last_read = Date.now();
            this.flag('highlight', false);

            // If running under a bouncer, set it on the server-side too
            let network = this.getNetwork();
            let allowedUpdate = !network ? false : this.isChannel() || this.isQuery();
            if (allowedUpdate && network.connection.bncname) {
                let lastMessage = this.getMessages().reduce((latest, current) => {
                    if (latest.time && latest.time > current.time) {
                        return latest;
                    }
                    return current;
                }, this.getMessages()[0]);

                if (!lastMessage) {
                    return;
                }

                network.ircClient.bnc.bufferSeen(
                    network.connection.bncname,
                    this.name,
                    new Date(lastMessage.time),
                );
            }
        }
    }

    incrementFlag(flagName) {
        this.flags[flagName] = (this.flags[flagName] || 0) + 1;
    }

    addUser(user) {
        this.addUserBatch(user);
    }

    removeUser(nick) {
        let userObj = this.state.getUser(this.networkid, nick);

        // A user could be queued to be added, so make sure it's not there as it
        // would just be added again. Eg. user joins/parts during a flood
        _.pull(this.addUserBatch.queue(), userObj);

        this.state.$delete(this.users, nick.toLowerCase());

        if (userObj) {
            delete userObj.buffers[this.id];
        }
    }

    clearUsers() {
        // Users could be queued to be added, so make sure to clear them as they
        // would just be added again. Eg. user joins/parts during a flood
        this.addUserBatch && this.addUserBatch.queue().splice(0);

        _.each(this.users, (userObj, nick) => {
            delete userObj.buffers[this.id];
        });

        this.state.$set(this, 'users', {});
    }

    addMessage(message) {
        this.addMessageBatch(message);
    }

    say(message, opts = {}) {
        let network = this.getNetwork();
        let newMessage = {
            time: Date.now(),
            nick: network.nick,
            message: message,
            type: opts.type || 'privmsg',
        };

        this.state.addMessage(this, newMessage);

        let fnNames = {
            privmsg: 'say',
            action: 'action',
            notice: 'notice',
        };
        let fnName = fnNames[opts.type] || 'say';
        network.ircClient[fnName](this.name, message);
    }

    join() {
        if (!this.isChannel()) {
            return;
        }

        let network = this.getNetwork();
        network.ircClient.join(this.name, this.key || '');
    }

    part(reason) {
        if (!this.isChannel()) {
            return;
        }

        let network = this.getNetwork();
        network.ircClient.part(this.name, reason || '');
    }
}

/**
 * Batch up floods of addUsers for a huge performance gain.
 * Generally happens when reconnecting to a BNC
 */
function createUserBatch(bufferState) {
    let addSingleUser = (u) => {
        bufferState.state.$set(bufferState.users, u.nick.toLowerCase(), u);
    };
    let addMultipleUsers = (users) => {
        let o = _.clone(bufferState.users);
        users.forEach((u) => {
            o[u.nick.toLowerCase()] = u;
        });
        bufferState.users = o;
    };

    return batchedAdd(addSingleUser, addMultipleUsers);
}

/**
 * batch up floods of new messages for a huge performance gain
 */
function createMessageBatch(bufferState) {
    let addSingleMessage = (newMessage) => {
        bufferState.messagesObj.messages.push(newMessage);
        trimMessages();
        bufferState.message_count++;
    };
    let addMultipleMessages = (newMessages) => {
        bufferState.messagesObj.messages = bufferState.messagesObj.messages.concat(newMessages);
        trimMessages();
        bufferState.message_count++;
    };
    let trimMessages = () => {
        let scrollbackSize = bufferState.setting('scrollback_size');
        let length = bufferState.messagesObj.messages.length;

        if (bufferState.messagesObj.messages.length > scrollbackSize) {
            bufferState.messagesObj.messages.splice(0, length - scrollbackSize);
        }
    };

    return batchedAdd(addSingleMessage, addMultipleMessages);
}

// Update our user list status every 30seconds to get each users current away status
function startWhoLoop(bufferState) {
    nextLoop();

    function nextLoop() {
        setTimeout(updateWhoStatusLoop, 30000);
    }

    function updateWhoStatusLoop() {
        // Make sure the network buffer still exists
        let network = bufferState.state.getNetwork(bufferState.networkid);
        if (!network) {
            return;
        }

        if (!network.bufferByName(bufferState.name)) {
            return;
        }

        let whoLoop = bufferState.setting('who_loop');
        let isJoined = bufferState.joined;
        let networkConnected = network.state === 'connected';

        if (whoLoop && networkConnected && isJoined) {
            network.ircClient.who(bufferState.name, () => {
                nextLoop();
            });
        } else {
            nextLoop();
        }
    }
}
<commit_msg>Fix who polling<commit_after>/** @module */

import Vue from 'vue';
import _ from 'lodash';
import * as Misc from '@/helpers/Misc';
import { def } from './common';
import batchedAdd from '../batchedAdd';

let nextBufferId = 0;

/** The IRC buffer instance */
export default class BufferState {
    constructor(name, networkid, state, messageDict) {
        // Enumerable properties that become reactive under Vue
        this.id = nextBufferId++;
        this.networkid = networkid;
        this.name = name;
        this.topics = [];
        this.key = '';
        this.joined = false;
        this.enabled = true;
        this.created_at = null;
        this.users = Object.create(null);
        this.modes = Object.create(null);
        this.flags = {
            unread: 0,
            alert_on: 'default',
            has_opened: false,
            channel_badkey: false,
            chathistory_available: true,
            requested_modes: false,
            requested_banlist: false,
        };
        this.settings = { };
        this.last_read = 0;
        this.active_timeout = null;
        this.message_count = 0;
        this.current_input = '';

        Vue.observable(this);

        // Some non-enumerable properties (vues $watch won't cover these properties)
        def(this, 'state', state, false);
        def(this, 'messageDict', messageDict, false);

        let messagesObj = {
            networkid: this.networkid,
            buffer: this.name,
            messages: [],
        };
        this.messageDict.push(messagesObj);
        def(this, 'messagesObj', messagesObj, false);

        def(this, 'addMessageBatch', createMessageBatch(this), false);
        def(this, 'addUserBatch', createUserBatch(this), false);

        // poll who to update away status if away-notify is not enabled
        if (this.isChannel()) {
            maybeStartWhoLoop(this);
        }
    }

    get topic() {
        return this.topics.length === 0 ?
            '' :
            this.topics[this.topics.length - 1];
    }

    set topic(newVal) {
        this.topics.push(newVal);
    }

    getNetwork() {
        return this.state.getNetwork(this.networkid);
    }

    getMessages() {
        let bufMessages = _.find(this.messageDict, {
            networkid: this.networkid,
            buffer: this.name,
        });

        return bufMessages ?
            bufMessages.messages :
            [];
    }

    isServer() {
        return this.name === '*';
    }

    isChannel() {
        let chanPrefixes = ['#', '&'];
        let ircNetwork = this.getNetwork().ircClient.network;
        if (ircNetwork && ircNetwork.options.CHANTYPES) {
            chanPrefixes = ircNetwork.options.CHANTYPES;
        }

        return chanPrefixes.indexOf(this.name[0]) > -1;
    }

    isQuery() {
        let chanPrefixes = ['#', '&'];
        let ircNetwork = this.getNetwork().ircClient.network;
        if (ircNetwork && ircNetwork.options.CHANTYPES) {
            chanPrefixes = ircNetwork.options.CHANTYPES;
        }

        return chanPrefixes.indexOf(this.name[0]) === -1 &&
            !this.isSpecial() &&
            !this.isServer();
    }

    isSpecial() {
        // Special buffer names (Usually controller queries, like *status or *raw).
        // Server buffer '*' is not included in this classification.
        let name = this.name;
        return name[0] === '*' && name.length > 1;
    }

    isUserAnOp(nick) {
        let user = this.state.getUser(this.networkid, nick);
        if (!user) {
            return false;
        }

        let userBufferInfo = user.buffers[this.id];
        if (!userBufferInfo) {
            return false;
        }

        let modes = userBufferInfo.modes;
        let opModes = ['Y', 'y', 'q', 'a', 'o', 'h'];
        let hasOp = _.find(modes, mode => opModes.indexOf(mode.toLowerCase()) > -1);

        return !!hasOp;
    }

    /**
     * Get a users prefix symbol on a buffer from its modes
     * @param {Object} user The user object
     */
    userModePrefix(user) {
        // The user may not be on the buffer
        if (!user.buffers[this.id]) {
            return '';
        }

        let modes = user.buffers[this.id].modes;
        if (modes.length === 0) {
            return '';
        }

        let network = this.getNetwork();
        let netPrefixes = network.ircClient.network.options.PREFIX;
        // Find the first (highest) netPrefix in the users buffer modes
        let prefix = _.find(netPrefixes, p => modes.indexOf(p.mode) > -1);

        return prefix ?
            prefix.symbol :
            '';
    }

    /**
     * Get a users mode on a buffer
     * @param user {Object} The user object
     */
    userMode(user) {
        // The user may not be on the buffer
        if (!user.buffers[this.id]) {
            return '';
        }

        let modes = user.buffers[this.id].modes;
        if (modes.length === 0) {
            return '';
        }

        let network = this.getNetwork();
        let netPrefixes = network.ircClient.network.options.PREFIX;
        // Find the first (highest) netPrefix in the users buffer modes
        let prefix = _.find(netPrefixes, p => modes.indexOf(p.mode) > -1);

        return prefix ?
            prefix.mode :
            '';
    }

    setting(name, val) {
        if (typeof val !== 'undefined') {
            this.state.$set(this.settings, name, val);
            return val;
        }

        // Check the buffer specific settings before reverting to global settings
        let result = typeof this.settings[name] !== 'undefined' ?
            this.settings[name] :
            this.state.setting('buffers.' + name);

        return result;
    }

    rename(newName) {
        let network = this.getNetwork();
        let oldName = this.name;
        let setActive = this.state.getActiveBuffer() === this;

        this.name = newName;
        if (setActive) {
            this.state.setActiveBuffer(network.id, newName);
        }

        // update the buffer name on our messages
        let bufferMessages = _.find(this.messageDict, { networkid: network.id, buffer: oldName });
        bufferMessages.buffer = newName;
    }

    flag(name, val) {
        if (typeof val !== 'undefined') {
            this.state.$set(this.flags, name, val);
            return val;
        }

        return this.flags[name];
    }

    requestScrollback(_direction) {
        let direction = _direction || 'backward';
        let time = '';
        // Negative number gets messages before the timestamps, positive gets messages after
        let numMessages = -50;

        // Going backwards takes the earliest message we already have and requests messages
        // before it. Going forward takes the last message we have and requests messages after
        // it.

        if (direction === 'backward') {
            let lastMessage = this.getMessages().reduce((earliest, current) => {
                let validType = earliest.type !== 'traffic';
                if (validType && earliest.time && earliest.time < current.time) {
                    return earliest;
                }
                return current;
            }, this.getMessages()[0]);

            numMessages = -50;
            time = lastMessage ?
                new Date(lastMessage.time) :
                new Date();
        } else if (direction === 'forward') {
            let firstMessage = this.getMessages().reduce((latest, current) => {
                let validType = latest.type !== 'traffic';
                if (validType && latest.time && latest.time > current.time) {
                    return latest;
                }
                return current;
            }, this.getMessages()[0]);

            numMessages = 50;
            time = firstMessage ?
                new Date(firstMessage.time) :
                new Date();
        } else {
            throw new Error('Invalid direction for requestScrollback(): ' + _direction);
        }

        let irc = this.getNetwork().ircClient;
        let timeStr = Misc.dateIso(time);
        irc.raw(`CHATHISTORY ${this.name} timestamp=${timeStr} message_count=${numMessages}`);
        irc.once('batch end chathistory', (event) => {
            if (event.commands.length === 0) {
                this.flags.chathistory_available = false;
            } else {
                this.flags.chathistory_available = true;
            }
        });
    }

    markAsRead(delayed) {
        if (this.active_timeout) {
            clearTimeout(this.active_timeout);
            this.active_timeout = null;
        }
        if (delayed) {
            this.active_timeout = setTimeout(
                this.markAsRead.bind(this),
                10000,
                false
            );
        } else {
            this.last_read = Date.now();
            this.flag('highlight', false);

            // If running under a bouncer, set it on the server-side too
            let network = this.getNetwork();
            let allowedUpdate = !network ? false : this.isChannel() || this.isQuery();
            if (allowedUpdate && network.connection.bncname) {
                let lastMessage = this.getMessages().reduce((latest, current) => {
                    if (latest.time && latest.time > current.time) {
                        return latest;
                    }
                    return current;
                }, this.getMessages()[0]);

                if (!lastMessage) {
                    return;
                }

                network.ircClient.bnc.bufferSeen(
                    network.connection.bncname,
                    this.name,
                    new Date(lastMessage.time),
                );
            }
        }
    }

    incrementFlag(flagName) {
        this.flags[flagName] = (this.flags[flagName] || 0) + 1;
    }

    addUser(user) {
        this.addUserBatch(user);
    }

    removeUser(nick) {
        let userObj = this.state.getUser(this.networkid, nick);

        // A user could be queued to be added, so make sure it's not there as it
        // would just be added again. Eg. user joins/parts during a flood
        _.pull(this.addUserBatch.queue(), userObj);

        this.state.$delete(this.users, nick.toLowerCase());

        if (userObj) {
            delete userObj.buffers[this.id];
        }
    }

    clearUsers() {
        // Users could be queued to be added, so make sure to clear them as they
        // would just be added again. Eg. user joins/parts during a flood
        this.addUserBatch && this.addUserBatch.queue().splice(0);

        _.each(this.users, (userObj, nick) => {
            delete userObj.buffers[this.id];
        });

        this.state.$set(this, 'users', {});
    }

    addMessage(message) {
        this.addMessageBatch(message);
    }

    say(message, opts = {}) {
        let network = this.getNetwork();
        let newMessage = {
            time: Date.now(),
            nick: network.nick,
            message: message,
            type: opts.type || 'privmsg',
        };

        this.state.addMessage(this, newMessage);

        let fnNames = {
            privmsg: 'say',
            action: 'action',
            notice: 'notice',
        };
        let fnName = fnNames[opts.type] || 'say';
        network.ircClient[fnName](this.name, message);
    }

    join() {
        if (!this.isChannel()) {
            return;
        }

        let network = this.getNetwork();
        network.ircClient.join(this.name, this.key || '');
    }

    part(reason) {
        if (!this.isChannel()) {
            return;
        }

        let network = this.getNetwork();
        network.ircClient.part(this.name, reason || '');
    }
}

/**
 * Batch up floods of addUsers for a huge performance gain.
 * Generally happens when reconnecting to a BNC
 */
function createUserBatch(bufferState) {
    let addSingleUser = (u) => {
        bufferState.state.$set(bufferState.users, u.nick.toLowerCase(), u);
    };
    let addMultipleUsers = (users) => {
        let o = _.clone(bufferState.users);
        users.forEach((u) => {
            o[u.nick.toLowerCase()] = u;
        });
        bufferState.users = o;
    };

    return batchedAdd(addSingleUser, addMultipleUsers);
}

/**
 * batch up floods of new messages for a huge performance gain
 */
function createMessageBatch(bufferState) {
    let addSingleMessage = (newMessage) => {
        bufferState.messagesObj.messages.push(newMessage);
        trimMessages();
        bufferState.message_count++;
    };
    let addMultipleMessages = (newMessages) => {
        bufferState.messagesObj.messages = bufferState.messagesObj.messages.concat(newMessages);
        trimMessages();
        bufferState.message_count++;
    };
    let trimMessages = () => {
        let scrollbackSize = bufferState.setting('scrollback_size');
        let length = bufferState.messagesObj.messages.length;

        if (bufferState.messagesObj.messages.length > scrollbackSize) {
            bufferState.messagesObj.messages.splice(0, length - scrollbackSize);
        }
    };

    return batchedAdd(addSingleMessage, addMultipleMessages);
}

// Update our user list status every 30seconds to get each users current away status
function maybeStartWhoLoop(bufferState) {
    let network = bufferState.state.getNetwork(bufferState.networkid);

    if (network.state === 'connected') {
        // network is connected start the loop if its needed
        maybeLoop();
    } else {
        // network is not conencted wait until it is
        bufferState.state.$once('irc.raw.001', () => {
            maybeLoop();
        });
    }

    function maybeLoop() {
        if (network.ircClient.network.cap.isEnabled('away-notify')) {
            // network has away-notify so who loop is not needed
            return;
        }
        nextLoop();
    }

    function nextLoop() {
        setTimeout(updateWhoStatusLoop, 30000);
    }

    function updateWhoStatusLoop() {
        // Make sure the network buffer still exists
        if (!network) {
            return;
        }

        // Make sure the buffer still exists
        if (!network.bufferByName(bufferState.name)) {
            return;
        }

        let whoLoop = bufferState.setting('who_loop');
        let isJoined = bufferState.joined;
        let networkConnected = network.state === 'connected';

        if (whoLoop && networkConnected && isJoined) {
            network.ircClient.who(bufferState.name, () => {
                nextLoop();
            });
        } else {
            nextLoop();
        }
    }
}
<|endoftext|>


<commit_before>import { createStore } from 'redux';
import reducer from 'reducers/reducers.js';

const initialState = {
  selectedkey: 0, // Currently selected component
  kexp: 1.0,
  krdel: 1.0,
  components: [ // Energy components array
    {
      carrier: 'ELECTRICIDAD',
      ctype: 'SUMINISTRO',
      originoruse: 'EPB',
      values: [9.67,7.74,4.84,4.35,2.42,2.90,3.87,3.39,2.42,3.87,5.80,7.74]
    },
    {
      carrier: 'ELECTRICIDAD',
      ctype: 'SUMINISTRO',
      originoruse: 'NEPB',
      values: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    },
    {
      carrier: 'MEDIOAMBIENTE',
      ctype: 'SUMINISTRO',
      originoruse: 'EPB',
      values: [21.48,17.18,10.74,9.66,5.37,6.44,8.59,7.52,5.37,8.59,12.89,17.18]
    },
    {
      carrier: 'MEDIOAMBIENTE',
      ctype: 'PRODUCCION',
      originoruse: 'COGENERACION',
      values: [21.48,17.18,10.74,9.66,5.37,6.44,8.59,7.52,5.37,8.59,12.89,17.18]
    }
  ]

};

export default createStore (
  reducer,
  initialState
);
<commit_msg>store: use ejemplo3PVBdC.csv as initial values<commit_after>import { createStore } from 'redux';
import reducer from 'reducers/reducers.js';

const initialState = {
  selectedkey: 0, // Currently selected component
  kexp: 1.0,
  krdel: 1.0,
  components: [ // Energy components array (ejemplo3PVBdC.csv)
    {
      carrier: 'ELECTRICIDAD',
      ctype: 'SUMINISTRO',
      originoruse: 'EPB',
      values: [9.67,7.74,4.84,4.35,2.42,2.90,3.87,3.39,2.42,3.87,5.80,7.74]
    },
    {
      carrier: 'ELECTRICIDAD',
      ctype: 'PRODUCCION',
      originoruse: 'INSITU',
      values: [1.13,1.42,1.99,2.84,4.82,5.39,5.67,5.11,4.54,3.40,2.27,1.42]
    },
    {
      carrier: 'MEDIOAMBIENTE',
      ctype: 'SUMINISTRO',
      originoruse: 'EPB',
      values: [21.48,17.18,10.74,9.66,5.37,6.44,8.59,7.52,5.37,8.59,12.89,17.18]
    },
    {
      carrier: 'MEDIOAMBIENTE',
      ctype: 'PRODUCCION',
      originoruse: 'INSITU',
      values: [21.48,17.18,10.74,9.66,5.37,6.44,8.59,7.52,5.37,8.59,12.89,17.18]
    }
  ]

};

export default createStore (
  reducer,
  initialState
);
<|endoftext|>