<commit_before>Z.wrap('github/jillix/layout/v0.0.1/layout.js', function (require, module, exports) {

module.exports = init;

/*
    type: constructor
*/
function init (config, ready) {
    var self = this;
    var pageName = '_page_' + self._name;

    self._conf = {
        title: "",
        locale: null
    };

    config = $.extend(self._conf, config);

    // locale stuff
    self.locale = {};
    function verifyDeps() {

        if (typeof $ === "undefined") {
            throw new Error("jQuery is required for layout module");
        }

        if (config.locale && typeof $.cookie === "undefined") {
            throw new Error("jQuery cookie library is required when using locale");
        }
    }

    verifyDeps();

    // set locale
    self.locale.set = function (ev, data) {
        var locale = data.locale || data.value || data;
        var cookie = data.cookie || config.locale.cookie;
        $.cookie(cookie, locale);
        self.emit("localeSet", null, {
            locale: locale,
            cookie: cookie
        });
    };

    // get locale
    self.locale.get = function (ev, data) {
        var cookie = data && data.cookie || config.locale.cookie;
        if (typeof ev === "function") { data = { callback: ev }; }
        if (typeof data === "function") { data = { callback: data }; }
        var localeVal = $.cookie(cookie);
        data && data.callback(null, localeVal);
        return localeVal;
    };

    if (config.locale) {

        if (typeof config.locale === "string") {
            config.locale = {
                value: config.locale,
                cookie: "_loc"
            };
        }

        if (typeof config.locale.value !== "string") {
            throw new Error("config.locale.value shoud be a string.");
        }

        if (typeof config.locale.cookie !== "string") {
            throw new Error("config.locale.cookie shoud be a string.");
        }

        // Prevent locale overriding
        var cLoc = self.locale.get();
        if (cLoc && cLoc !== "undefined") { return; }
        self.locale.set(null, config.locale);
    }

    // set document title
    if (config.title) {
        self.title = config.title;
        document.title = config.title;
    }

    // attach state handler to instance
    self.page = page;
    self.transition = transition;
    self.render = render;
    self.$jq = $jq;

    // state handler to handle css in pages
    self.pageSelector = '.' + pageName;

    // render other views
    for (var view in self.view) {
        self.view[view].render([{page: pageName}]);
    }

    // get pages dom refs
    self.pages = $(self.pageSelector);

    // hide all pages in init state
    self.pages.hide();

    // handle not found
    if ((self.notFound = $(config.notFound))) {
        self.on('route', notFoundHandler);
    }

    ready();
}

/*
    type: actor
*/
function page (state, data) {
    var self = this;
    var target = data.show;
    var options = data.options;

    // return when no target page is given
    if (!target) {
        return;
    }

    // state found
    self._state = true;

    options = options || {};

    // hide not found
    if (self.notFound) {
        self.notFound.hide();
    }

    // set document title
    if (self.title) {
        document.title = self.title;
    }

    self.pages.hide();

    var targetPage = $(target);

    // animate page transition
    if (options.animate) {
        animate.call(self, targetPage, options.animate);

    // show requested page
    } else {
        targetPage.show();
    }
}

/*
    type: actor
    TODO: implement animations
*/
function transition (state, data) {

    if (!data) {
        return;
    }

    data.hide && $(data.hide).hide();
    data.show && $(data.show).show();
}

/*
    type: private
*/
function animate (elm, config) {
    var self = this;

    if (!elm || !config) {
        return;
    }

    for (var i = 0; i < config.length; ++i) {

        // get element
        elm = config[i].elm ? $(config[i].elm, elm) : elm;

        // handle show/hide
        if (config[i].fx === 'show' || config[i].fx === 'hide') {
            elm[config[i].fx]();

        // handle animateion
        } else {

            // set timing
            if (config[i].dd) {
                elm.css("-webkit-animation-duration", config[i].dd[0]);
                elm.css("-webkit-animation-delay", config[i].dd[1]);
            }

            var animate_class = 'animated ' + config[i].fx;

            // animation end handler
            elm.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', animation_end_handler(elm, animate_class));

            // start animation
            elm.addClass(animate_class);
            elm.show();
        }
    }
}

/*
    type: actor
*/
function render (event, data) {
    var self = this;
    var view = data.view;

    if (!self.view || !self.view[view] || !data) {
        return;
    }

    // TODO Handle pages on manual rendering
    // data.item && (data.item.page = '_page_' + self._name);

    // render data
    self.view[view].render([data.item]);
}

/*
    type: actor
    desc: mainpulate dom with jquery
*/
function $jq (event, data) {
    var self = this;
    var selector = data.selector;
    var method = data.method;
    var args = data.args;

    // call jquery function
    if ($.fn[method]) {

        // get selector from url
        if (typeof selector !== 'string') {

            // return when regexp is not found
            var re = new RegExp(selector[0]);
            if (!re.test(window.location)) {
                return;
            }

            selector = window.location.href.replace(re, selector[1]);

        } else {

            // get selector
            switch (selector) {
                case 'cur':
                    selector = event.currentTarget;
                    break;
                case 'src':
                    selector = event.srcElement;
                    break;
                case 'all':
                    selector = event.elms;
                    break;
            }
        }

        // call method
        selector = $(selector);
        selector[method].apply(selector, args);
    }
}

/*
    type: private
*/
function animation_end_handler (elm, animate_class) {
    return function () {
        elm.removeClass(animate_class);
    };
}

/*
    type: private
    TODO: needs to be tested
*/
function notFoundHandler (state) {
    var self = this;

    if (self._url === state.url) {
        return;
    }

    if (!self._state) {
        self.pages.hide();
        self.notFound.show();
    }

    self._state = false;
}

return module;

});
<commit_msg>Emit localeGet event. Handle setCookie option<commit_after>Z.wrap('github/jillix/layout/v0.0.1/layout.js', function (require, module, exports) {

module.exports = init;

/*
    type: constructor
*/
function init (config, ready) {
    var self = this;
    var pageName = '_page_' + self._name;

    self._conf = {
        title: "",
        locale: null
    };

    config = $.extend(self._conf, config);

    // locale stuff
    self.locale = {};
    function verifyDeps() {

        if (typeof $ === "undefined") {
            throw new Error("jQuery is required for layout module");
        }

        if (config.locale && typeof $.cookie === "undefined") {
            throw new Error("jQuery cookie library is required when using locale");
        }
    }

    verifyDeps();

    // set locale
    self.locale.set = function (ev, data) {
        var locale = data.locale || data.value || data;
        var cookie = data.cookie || config.locale.cookie;
        if (data.setCookie !== false) {
            $.cookie(cookie, locale);
        }

        self.emit("localeSet", null, {
            locale: locale,
            cookie: cookie,
            i18n: locale
        });
    };

    // get locale
    self.locale.get = function (ev, data) {
        var cookie = data && data.cookie || config.locale.cookie;
        if (typeof ev === "function") { data = { callback: ev }; }
        if (typeof data === "function") { data = { callback: data }; }
        var localeVal = $.cookie(cookie);
        data && typeof data.callback === "function" && data.callback(null, localeVal);
        self.emit("localeGet", null, {
            i18n: localeVal
        });
        return localeVal;
    };

    if (config.locale) {

        if (typeof config.locale === "string") {
            config.locale = {
                value: config.locale,
                cookie: "_loc"
            };
        }

        if (typeof config.locale.value !== "string") {
            throw new Error("config.locale.value shoud be a string.");
        }

        if (typeof config.locale.cookie !== "string") {
            throw new Error("config.locale.cookie shoud be a string.");
        }

        // Prevent locale overriding
        var cLoc = self.locale.get();
        self.locale.set(null, {
            value: config.locale.value,
            cookie: config.locale.cookie,
            setCookie: config.locale.value === cLoc || !cLoc
        });
    }

    // set document title
    if (config.title) {
        self.title = config.title;
        document.title = config.title;
    }

    // attach state handler to instance
    self.page = page;
    self.transition = transition;
    self.render = render;
    self.$jq = $jq;

    // state handler to handle css in pages
    self.pageSelector = '.' + pageName;

    // render other views
    for (var view in self.view) {
        self.view[view].render([{page: pageName}]);
    }

    // get pages dom refs
    self.pages = $(self.pageSelector);

    // hide all pages in init state
    self.pages.hide();

    // handle not found
    if ((self.notFound = $(config.notFound))) {
        self.on('route', notFoundHandler);
    }

    ready();
}

/*
    type: actor
*/
function page (state, data) {
    var self = this;
    var target = data.show;
    var options = data.options;

    // return when no target page is given
    if (!target) {
        return;
    }

    // state found
    self._state = true;

    options = options || {};

    // hide not found
    if (self.notFound) {
        self.notFound.hide();
    }

    // set document title
    if (self.title) {
        document.title = self.title;
    }

    self.pages.hide();

    var targetPage = $(target);

    // animate page transition
    if (options.animate) {
        animate.call(self, targetPage, options.animate);

    // show requested page
    } else {
        targetPage.show();
    }
}

/*
    type: actor
    TODO: implement animations
*/
function transition (state, data) {

    if (!data) {
        return;
    }

    data.hide && $(data.hide).hide();
    data.show && $(data.show).show();
}

/*
    type: private
*/
function animate (elm, config) {
    var self = this;

    if (!elm || !config) {
        return;
    }

    for (var i = 0; i < config.length; ++i) {

        // get element
        elm = config[i].elm ? $(config[i].elm, elm) : elm;

        // handle show/hide
        if (config[i].fx === 'show' || config[i].fx === 'hide') {
            elm[config[i].fx]();

        // handle animateion
        } else {

            // set timing
            if (config[i].dd) {
                elm.css("-webkit-animation-duration", config[i].dd[0]);
                elm.css("-webkit-animation-delay", config[i].dd[1]);
            }

            var animate_class = 'animated ' + config[i].fx;

            // animation end handler
            elm.one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', animation_end_handler(elm, animate_class));

            // start animation
            elm.addClass(animate_class);
            elm.show();
        }
    }
}

/*
    type: actor
*/
function render (event, data) {
    var self = this;
    var view = data.view;

    if (!self.view || !self.view[view] || !data) {
        return;
    }

    // TODO Handle pages on manual rendering
    // data.item && (data.item.page = '_page_' + self._name);

    // render data
    self.view[view].render([data.item]);
}

/*
    type: actor
    desc: mainpulate dom with jquery
*/
function $jq (event, data) {
    var self = this;
    var selector = data.selector;
    var method = data.method;
    var args = data.args;

    // call jquery function
    if ($.fn[method]) {

        // get selector from url
        if (typeof selector !== 'string') {

            // return when regexp is not found
            var re = new RegExp(selector[0]);
            if (!re.test(window.location)) {
                return;
            }

            selector = window.location.href.replace(re, selector[1]);

        } else {

            // get selector
            switch (selector) {
                case 'cur':
                    selector = event.currentTarget;
                    break;
                case 'src':
                    selector = event.srcElement;
                    break;
                case 'all':
                    selector = event.elms;
                    break;
            }
        }

        // call method
        selector = $(selector);
        selector[method].apply(selector, args);
    }
}

/*
    type: private
*/
function animation_end_handler (elm, animate_class) {
    return function () {
        elm.removeClass(animate_class);
    };
}

/*
    type: private
    TODO: needs to be tested
*/
function notFoundHandler (state) {
    var self = this;

    if (self._url === state.url) {
        return;
    }

    if (!self._state) {
        self.pages.hide();
        self.notFound.show();
    }

    self._state = false;
}

return module;

});
<|endoftext|>


<commit_before>$('document').ready( function(){
  addEmail();

  // Fix Broken Image
  var image_el = $('.poster')
  for (i = 0; i < image_el.length; i++) {
    if (image_el[i].src.search(/.N\/A/) !== -1) {
      console.log("No Image!");
      image_el[i].setAttribute("src", "../images/oscar.jpg");
    } else {
      console.log("Image loaded!")
    }
  }

  // Footer Date
  var today = new Date();
  var date = today.toDateString();
  var footer_el = document.getElementById('footer');
  footer_el.innerHTML = '
Copyright © ' + date + '

Anthony Ng | Crafted lovingly in San Francisco, California.
';

// Google Map API
function initialize() {

  var markers = [];
  var map = new google.maps.Map(document.getElementById('map-canvas'), {
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  var defaultBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(37.773493, -122.423864),
    new google.maps.LatLng(37.790147, -122.388974));
  map.fitBounds(defaultBounds);

  // Create the search box and link it to the UI element.
  var input = /** @type {HTMLInputElement} */(
    document.getElementById('pac-input'));
  map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

  var searchBox = new google.maps.places.SearchBox((input));

  // [START region_getplaces]
  // Listen for the event fired when the user selects an item from the
  // pick list. Retrieve the matching places for that item.
  google.maps.event.addListener(searchBox, 'places_changed', function() {
    var places = searchBox.getPlaces();

    if (places.length == 0) {
      return;
    }
    for (var i = 0, marker; marker = markers[i]; i++) {
      marker.setMap(null);
    }

    // For each place, get the icon, place name, and location.
    markers = [];
    var bounds = new google.maps.LatLngBounds();
    for (var i = 0, place; place = places[i]; i++) {
      var image = {
        url: place.icon,
        size: new google.maps.Size(71, 71),
        origin: new google.maps.Point(0, 0),
        anchor: new google.maps.Point(17, 34),
        scaledSize: new google.maps.Size(25, 25)
      };

      // Create a marker for each place.
      var marker = new google.maps.Marker({
        map: map,
        icon: image,
        title: place.name,
        position: place.geometry.location
      });

      markers.push(marker);

      bounds.extend(place.geometry.location);
    }

    map.fitBounds(bounds);
  });
  // [END region_getplaces]

  // Bias the SearchBox results towards places that are within the bounds of the
  // current map's viewport.
  google.maps.event.addListener(map, 'bounds_changed', function() {
    var bounds = map.getBounds();
    searchBox.setBounds(bounds);
  });
}

google.maps.event.addDomListener(window, 'load', initialize);

// background Video Button
var vid = document.getElementById("bgvid");
var pauseButton = document.getElementById("vidpause");
function vidFade() {
  vid.classList.add("stopfade");
}
vid.addEventListener('ended', function() {
// only functional if "loop" is removed
vid.pause();
// to capture IE10
vidFade();
});
pauseButton.addEventListener("click", function() {
  vid.classList.toggle("stopfade");
  if (vid.paused) {
    vid.play();
    pauseButton.innerHTML = "Pause";
  } else {
    vid.pause();
    pauseButton.innerHTML = "Paused";
  }
})

  // $('form').on('submit', function(event){
  //   event.preventDefault()
  //   $('form').nextAll().remove()
  //   $.ajax({
  //     type: 'GET',
  //     url: $(this).attr('action'),
  //     data: $(this).serialize()
  //   }).done(function(data) {
  //     $(".container").append(data)
  //   })
  // })
})

//Register Form
function addEmail() {
  $('.register').submit(function(event) {
    event.preventDefault();
    var url = $(this).attr('action');
    //convert a form into key/value pair data
    var data = $(this).serialize();

    // Testing
    console.log(url);
    console.log(data);

    $.ajax({
      type: 'POST',
      url: url,
      data: data

    }).success(function(response) {
      var thank_el = document.getElementById('thanks');
      thank_el.innerHTML = '
Thank you!
We have added your email address to the signup queue.
';
      console.log("ya")
    }).fail(function(response) {
      console.log("fail");
      console.log(data);
    })
  })
}<commit_msg>added countdown functnio<commit_after>$('document').ready( function(){
  addEmail();
  countdown();

  // Fix Broken Image
  var image_el = $('.poster')
  for (i = 0; i < image_el.length; i++) {
    if (image_el[i].src.search(/.N\/A/) !== -1) {
      console.log("No Image!");
      image_el[i].setAttribute("src", "../images/oscar.jpg");
    } else {
      console.log("Image loaded!")
    }
  }

  // Footer Date
  var today = new Date();
  var date = today.toDateString();
  var footer_el = document.getElementById('footer');
  footer_el.innerHTML = '
Copyright © ' + date + '

Anthony Ng | Crafted lovingly in San Francisco, California.
';

// Google Map API
function initialize() {

  var markers = [];
  var map = new google.maps.Map(document.getElementById('map-canvas'), {
    mapTypeId: google.maps.MapTypeId.ROADMAP
  });

  var defaultBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(37.773493, -122.423864),
    new google.maps.LatLng(37.790147, -122.388974));
  map.fitBounds(defaultBounds);

  // Create the search box and link it to the UI element.
  var input = /** @type {HTMLInputElement} */(
    document.getElementById('pac-input'));
  map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

  var searchBox = new google.maps.places.SearchBox((input));

  // [START region_getplaces]
  // Listen for the event fired when the user selects an item from the
  // pick list. Retrieve the matching places for that item.
  google.maps.event.addListener(searchBox, 'places_changed', function() {
    var places = searchBox.getPlaces();

    if (places.length == 0) {
      return;
    }
    for (var i = 0, marker; marker = markers[i]; i++) {
      marker.setMap(null);
    }

    // For each place, get the icon, place name, and location.
    markers = [];
    var bounds = new google.maps.LatLngBounds();
    for (var i = 0, place; place = places[i]; i++) {
      var image = {
        url: place.icon,
        size: new google.maps.Size(71, 71),
        origin: new google.maps.Point(0, 0),
        anchor: new google.maps.Point(17, 34),
        scaledSize: new google.maps.Size(25, 25)
      };

      // Create a marker for each place.
      var marker = new google.maps.Marker({
        map: map,
        icon: image,
        title: place.name,
        position: place.geometry.location
      });

      markers.push(marker);

      bounds.extend(place.geometry.location);
    }

    map.fitBounds(bounds);
  });
  // [END region_getplaces]

  // Bias the SearchBox results towards places that are within the bounds of the
  // current map's viewport.
  google.maps.event.addListener(map, 'bounds_changed', function() {
    var bounds = map.getBounds();
    searchBox.setBounds(bounds);
  });
}

google.maps.event.addDomListener(window, 'load', initialize);

// background Video Button
var vid = document.getElementById("bgvid");
var pauseButton = document.getElementById("vidpause");
function vidFade() {
  vid.classList.add("stopfade");
}
vid.addEventListener('ended', function() {
// only functional if "loop" is removed
vid.pause();
// to capture IE10
vidFade();
});
pauseButton.addEventListener("click", function() {
  vid.classList.toggle("stopfade");
  if (vid.paused) {
    vid.play();
    pauseButton.innerHTML = "Pause";
  } else {
    vid.pause();
    pauseButton.innerHTML = "Paused";
  }
})

  // $('form').on('submit', function(event){
  //   event.preventDefault()
  //   $('form').nextAll().remove()
  //   $.ajax({
  //     type: 'GET',
  //     url: $(this).attr('action'),
  //     data: $(this).serialize()
  //   }).done(function(data) {
  //     $(".container").append(data)
  //   })
  // })
})

//Register Form
function addEmail() {
  $('.register').submit(function(event) {
    event.preventDefault();
    var url = $(this).attr('action');
    //convert a form into key/value pair data
    var data = $(this).serialize();

    // Testing
    console.log(url);
    console.log(data);

    $.ajax({
      type: 'POST',
      url: url,
      data: data

    }).success(function(response) {
      var thank_el = document.getElementById('thanks');
      thank_el.innerHTML = '
Thank you!
We have added your email address to the signup queue.
';
      console.log("ya")
    }).fail(function(response) {
      console.log("fail");
      console.log(data);
    })
  })
}

function countdown() {
  Countdown until 2050

}<|endoftext|>


<commit_before>M.wrap('github/jillix/jlx-layout/v0.0.1/layout.js', function (require, module, exports) {

var Crud = require('github/jillix/jlx-crud/v0.0.1/crud');
var View = require('github/jillix/jlx-view/v0.0.1/view');

var config = {
    "title": "Mono Dev",
    "view": {
        "views": [{
            "id": "viewId",
            "to": "body"
        }]
        /*
            // custom code
            M.custom = {
                view: {
                    addCount: function (data) {
                        this.count = this.count || 0;
                        data.title = data.title + ' ' + (++this.count);
                        return data;
                    },
                    resetCount: function (html) {
                        this.count = 0;
                    }
                }
            };

            // view config
            "on": {
                "data": "M.custom.view.addCount",
                "done": "M.custom.view.resetCount"
            }
        */
    },
    "source": "sourceId",
    /*"read": {
        "q": {}
    },*/
    "data": [
        {title: 'Rendered with jlx-view', text: 'jlx-view binds content dynamically to a html snippet', 'test.dot.notation': 'this.is.a.dot.notation.field'},
        {title: 'Rendered with jlx-view', text: 'jlx-view binds content dynamically to a html snippet', 'test.dot.notation': 'this.is.a.dot.notation.field'},
        {title: 'Rendered with jlx-view', text: 'jlx-view binds content dynamically to a html snippet', 'test.dot.notation': 'this.is.a.dot.notation.field'}
    ]
};

function setupView (err, view) {
    var self = this;
    //var config = self.mono.config;

    if (err) {
        return self.emit('view', err);
    }

    // save view
    self.views.push(view);

    // append custom handlers
    if (config.view.on) {
        for (var event in config.view.on) {
            view.on[event] = Object.path(config.view.on[event]);
        }
    }

    // read data from server
    if (self.crud && config.read) {
        self.crud.read(config.read, function (err, data) {

            if (err) {
                return;
            }

            // set data
            if (data) {
                view.data = data;
            }

            // render html
            view.render();
        });

    // set data
    } else {

        // set data
        if (config.data) {
            view.data = config.data;
        }

        // render html and append it to the dom
        view.render();
        self.emit('view', null, view);
    }
}

function init () {
    var self = this;
    //var config = self.mono.config;

    // set document title
    if (config.title) {
        document.title = config.title;
    }

    // init view
    if (config.view && config.view.views) {

        self.views = [];

        // init view module
        var V = View(self);

        // get crud instance
        if (config.source) {
            self.crud = Crud(self)(config.source);
        }

        // emit ready when all views are loaded
        var count = 0;
        var viewCounter = function (err, view) {
            if (++count === config.view.views.length) {
                self.emit('ready');
            }
        };
        self.on('view', viewCounter);

        // load views
        for (var i = 0; i < config.view.views.length; ++i) {
            V(config.view.views[i], setupView);
        }

    } else {
        self.emit('ready');
    }
}

module.exports = init;

return module;

});
<commit_msg>using and testing the new bind lib module<commit_after>M.wrap('github/jillix/jlx-layout/v0.0.1/layout.js', function (require, module, exports) {

var Bind = require('github/jillix/bind/v0.0.1/bind');

function ready (err, bind) {
    var self = this;
    var config = self.mono.config;

    if (err) {
        return self.emit('error', err);
    }

    // append custom handlers
    if (config.on) {
        for (var event in config.on) {
            bind.on[event] = Object.path(config.view.on[event]);
        }
    }

    // set data
    if (config.data) {
        bind.data = config.data;
    }

    // read data
    if (config.read) {
        bind.read(config.read, function (err, data) {

            if (err) {
                return;
            }

            if (data) {
                bind.data = data;
            }

            // render
            bind.render();
            self.emit('ready');
        });
    } else {

        // render
        bind.render();
        self.emit('ready');
    }
}

function init () {
    var self = this;
    var config = self.mono.config = {
        "title": "Mono Dev",
        "bind": "bindId",
        "to": "body",
        "data": [
            {title: 'Rendered with bind', text: 'Bind binds content dynamically to a html snippet', 'test': {'dot': {'notation': 'deep value'}}},
            {title: 'Rendered with bind', text: 'Bind binds content dynamically to a html snippet', 'test': {'dot': {'notation': 'deep value'}}},
            {title: 'Rendered with bind', text: 'Bind binds content dynamically to a html snippet', 'test': {'dot': {'notation': 'deep value'}}}
        ],
        /*"read": {
            "q": {}
        },*/
        /*
            // custom code
            M.custom = {
                bind: {
                    addCount: function (data) {
                        this.count = this.count || 0;
                        data.title = data.title + ' ' + (++this.count);
                        return data;
                    },
                    resetCount: function (html) {
                        this.count = 0;
                    }
                }
            };

            // bind config
            "on": {
                "data": "M.custom.bind.addCount",
                "done": "M.custom.bind.resetCount"
            }
        */
    } || self.mono.config;

    // set document title
    if (config.title) {
        document.title = config.title;
    }

    if (config.bind && config.to) {
        Bind(self)(config.bind, config.to, ready);
    } else {
        self.emit('ready');
    }
}

module.exports = init;

return module;

});
<|endoftext|>


<commit_before>"use strict";
define(["sjcl", "chat/cryptoParams"], function (sjcl, cryptoParams) {
/**
 * @module chat/crypto
 * @exports Crypto
 */

/**
 * Offers methods to encrypt and decrypt using the configured standard parameters.
 * @constructor
 * @param {sjcl.bitArray} secretKey - The key used for encryption and decryption.
 */
function Crypto(secretKey) {
	// private:
	this._prp = new sjcl.cipher[cryptoParams.cipher](secretKey);
}

/**
 * Encrypts a String and returns a cipher-object.
 * @param {String} plaintext
 * @returns {Object} An Object holding the ciphertext and the IV.
 */
Crypto.prototype.encryptedObjFromString = function (plaintext) {
	if (typeof plaintext !== 'string') {
		throw TypeError('plaintext must be a string.');
	}
	plaintext = sjcl.codec.utf8String.toBits(plaintext);
	var iv = sjcl.random.randomWords(4, 0);
	var ct = sjcl.mode[cryptoParams.mode].encrypt(this._prp, plaintext, iv, cryptoParams.adata, cryptoParams.tagSize);
	return {
		iv: sjcl.codec.base64.fromBits(iv, 1),
		ct: sjcl.codec.base64.fromBits(ct, 1)
	};
};

/**
 * Decrypts a cipher-object to a String.
 * @param {Object} cipherObj - An Object holding the ciphertext and the IV.
 * @returns {String} plaintext
 */
Crypto.prototype.decryptedStringFromObj = function (cipherObj) {
	var iv = sjcl.codec.base64.toBits(cipherObj.iv);
	var ct = sjcl.codec.base64.toBits(cipherObj.ct);
	var plaintext = sjcl.mode[cryptoParams.mode].decrypt(this._prp, ct, iv, cryptoParams.adata, cryptoParams.tagSize);
	return sjcl.codec.utf8String.fromBits(plaintext);
};

return Crypto;

});
<commit_msg>added an optional options parameter to the Crypto functions to overwrite global settings<commit_after>"use strict";
define(['sjcl', 'chat/cryptoParams'], function (sjcl, cryptoParams) {
/**
 * @module chat/crypto
 * @exports Crypto
 */

/**
 * Offers methods to encrypt and decrypt using the configured standard parameters.
 * @constructor
 * @param {sjcl.bitArray} secretKey - The key used for encryption and decryption.
 */
function Crypto(secretKey) {
	// private:
	this._prp = new sjcl.cipher[cryptoParams.cipher](secretKey);
}

/**
 * Encrypts a String and returns a cipher-object.
 * @param {String} plaintext
 * @param {Object} [options] - Options to overwrite the global settings.
 * @returns {Object} An Object holding the ciphertext and the IV.
 */
Crypto.prototype.encryptedObjFromString = function (plaintext, options) {
	if (typeof plaintext !== 'string') {
		throw TypeError('plaintext must be a string.');
	}
	options = _.extend(_.clone(cryptoParams), options);
	plaintext = sjcl.codec.utf8String.toBits(plaintext);
	var iv = sjcl.random.randomWords(4, 0);
	var ct = sjcl.mode[options.mode].encrypt(this._prp, plaintext, iv, options.adata, options.tagSize);
	return {
		iv: sjcl.codec.base64.fromBits(iv, 1),
		ct: sjcl.codec.base64.fromBits(ct, 1)
	};
};

/**
 * Decrypts a cipher-object to a String.
 * @param {Object} cipherObj - An Object holding the ciphertext and the IV.
 * @param {Object} [options] - Options to overwrite the global settings.
 * @returns {String} plaintext
 */
Crypto.prototype.decryptedStringFromObj = function (cipherObj, options) {
	options = _.extend(_.clone(cryptoParams), options);
	var iv = sjcl.codec.base64.toBits(cipherObj.iv);
	var ct = sjcl.codec.base64.toBits(cipherObj.ct);
	var plaintext = sjcl.mode[options.mode].decrypt(this._prp, ct, iv, options.adata, options.tagSize);
	return sjcl.codec.utf8String.fromBits(plaintext);
};

return Crypto;

});
<|endoftext|>


<commit_before>/*****************************************************************************/
/* Imports */
/*****************************************************************************/
var DynamicTemplate = Iron.DynamicTemplate;

/*****************************************************************************/
/* Helpers */
/*****************************************************************************/
/**
 * Find the first Layout in the rendered parent hierarchy.
 */
findFirstLayout = function (view) {
  while (view) {
    if (view.kind === 'Iron.Layout')
      return view.__dynamicTemplate__;
    else
      view = view.parentView;
  }

  return null;
};

/*****************************************************************************/
/* Layout */
/*****************************************************************************/

/**
 * Dynamically render templates into regions.
 *
 * Layout inherits from Iron.DynamicTemplate and provides the ability to create
 * regions that a user can render templates or content blocks into. The layout
 * and each region is an instance of DynamicTemplate so the template and data
 * contexts are completely dynamic and programmable in javascript.
 */
Layout = function (options) {
  var self = this;

  Layout.__super__.constructor.apply(this, arguments);

  options = options || {};
  this.kind = 'Iron.Layout';
  this._regions = {};
  this._regionHooks = {};
  this.defaultTemplate('__IronDefaultLayout__');

  // if there's block content then render that
  // to the main region
  if (options.content)
    this.render(options.content);
};

/**
 * The default region for a layout where the main content will go.
 */
DEFAULT_REGION = Layout.DEFAULT_REGION = 'main';

/**
 * Inherits from Iron.DynamicTemplate which gives us the ability to set the
 * template and data context dynamically.
 */
Meteor._inherits(Layout, Iron.DynamicTemplate);

/**
 * Return the DynamicTemplate instance for a given region. If the region doesn't
 * exist it is created.
 *
 * The regions object looks like this:
 *
 *  {
 *    "main": DynamicTemplate,
 *    "footer": DynamicTemplate,
 *    .
 *    .
 *    .
 *  }
 */
Layout.prototype.region = function (name, options) {
  return this._ensureRegion(name, options);
};

/**
 * If we set a new template for the layout we should destroy all of the existing
 * regions.
 */
Layout.prototype.template = function (value) {
  if (arguments.length === 1 && value !== this._template) {
    // if we're setting a new layout template, destroy the existing regions
    // first.
    this.destroyRegions();
  }

  return Layout.__super__.template.apply(this, arguments);
};

/**
 * Destroy all child regions and reset the regions map.
 */
Layout.prototype.destroyRegions = function () {
  _.each(this._regions, function (dynamicTemplate) {
    dynamicTemplate.destroy();
  });

  this._regions = {};
};

/**
 * Set the template for a region.
 */
Layout.prototype.render = function (template, options) {
  // having options is usually good
  options = options || {};

  // let the user specify the region to render the template into
  var region = options.to || options.region || DEFAULT_REGION;

  // get the DynamicTemplate for this region
  var dynamicTemplate = this.region(region);

  // if we're in a rendering transaction, track that we've rendered this
  // particular region
  this._trackRenderedRegion(region);

  // set the template value for the dynamic template
  dynamicTemplate.template(template);

  // if we have data go ahead and set the data for the dynamic template,
  // otherwise, leave it be.
  if (options.data)
    dynamicTemplate.data(options.data);
};

/**
 * Returns true if the given region is defined and false otherwise.
 */
Layout.prototype.has = function (region) {
  region = region || Layout.DEFAULT_REGION;
  return !!this._regions[region];
};

/**
 * Returns an array of region keys.
 */
Layout.prototype.regionKeys = function () {
  return _.keys(this._regions);
};

/**
 * Clear a given region or the "main" region by default.
 */
Layout.prototype.clear = function (region) {
  region = region || Layout.DEFAULT_REGION;

  // we don't want to create a region if it didn't exist before
  if (this.has(region))
    this.region(region).template(null);

  // chain it up
  return this;
};

/**
 * Clear all regions.
 */
Layout.prototype.clearAll = function () {
  _.each(this._regions, function (dynamicTemplate) {
    dynamicTemplate.template(null);
  });

  // chain it up
  return this;
};

/**
 * Start tracking rendered regions.
 */
Layout.prototype.beginRendering = function (onComplete) {
  var self = this;
  if (this._finishRenderingTransaction)
    this._finishRenderingTransaction();

  this._finishRenderingTransaction = _.once(function () {
    var regions = self._endRendering({flush: false});
    onComplete && onComplete(regions);
  });

  Deps.afterFlush(this._finishRenderingTransaction);

  if (this._renderedRegions)
    throw new Error("You called beginRendering again before calling endRendering");
  this._renderedRegions = {};
};

/**
 * Track a rendered region if we're in a transaction.
 */
Layout.prototype._trackRenderedRegion = function (region) {
  if (!this._renderedRegions)
    return;
  this._renderedRegions[region] = true;
};

/**
 * Stop a rendering transaction and retrieve the rendered regions. This
 * shouldn't be called directly. Instead, pass an onComplete callback to the
 * beginRendering method.
 */
Layout.prototype._endRendering = function (opts) {
  // we flush here to ensure all of the {{#contentFor}} inclusions have had a
  // chance to render from our templates, otherwise we'll never know about
  // them.
  opts = opts || {};
  if (opts.flush !== false)
    Deps.flush();
  var renderedRegions = this._renderedRegions || {};
  this._renderedRegions = null;
  return _.keys(renderedRegions);
};

/**
 * View lifecycle hooks for regions.
 */
_.each(
  [
    'onRegionCreated',
    'onRegionMaterialized',
    'onRegionRendered',
    'onRegionDestroyed'
  ],
  function (hook) {
    Layout.prototype[hook] = function (cb) {
      var hooks = this._regionHooks[hook] = this._regionHooks[hook] || [];
      hooks.push(cb);
      return this;
    }
  }
);

/**
 * Returns the DynamicTemplate for a given region or creates it if it doesn't
 * exists yet.
 */
Layout.prototype._ensureRegion = function (name, options) {
 return this._regions[name] = this._regions[name] || this._createDynamicTemplate(name, options);
};

/**
 * Create a new DynamicTemplate instance.
 */
Layout.prototype._createDynamicTemplate = function (name, options) {
  var self = this;
  var tmpl = new Iron.DynamicTemplate(options);
  var capitalize = Iron.utils.capitalize;
  tmpl._region = name;

  _.each(['created', 'materialized', 'rendered', 'destroyed'], function (hook) {
    hook = capitalize(hook);
    tmpl['on' + hook](function (dynamicTemplate) {
      // "this" is the view instance
      var view = this;
      self._runRegionHooks('on' + 'Region' + hook, view, dynamicTemplate);
    });
  });

  return tmpl;
};

Layout.prototype._runRegionHooks = function (name, regionView, regionDynamicTemplate) {
  var layout = this;
  var hooks = this._regionHooks[name] || [];
  var hook;

  for (var i = 0; i < hooks.length; i++) {
    hook = hooks[i];
    // keep the "thisArg" pointing to the view, but make the first parameter to
    // the callback teh dynamic template instance.
    hook.call(regionView, regionDynamicTemplate.region, regionDynamicTemplate, this);
  }
};

/*****************************************************************************/
/* UI Helpers */
/*****************************************************************************/

/**
 * Create a region in the closest layout ancestor.
 *
 * Examples:
 *
 *      {{> yield "aside"}}
 *
 *
 *

 *      {{> yield}}
 *

 *
 *
 *      {{> yield "footer"}}
 *
 */
UI.registerHelper('yield', Template.__create__('yield', function () {
  var layout = findFirstLayout(this);

  if (!layout)
    throw new Error("No Iron.Layout found so you can't use yield!");

  // Example options: {{> yield region="footer"}} or {{> yield "footer"}}
  var options = DynamicTemplate.getInclusionArguments(this);
  var region;

  if (_.isString(options)) {
    region = options;
  } else if (_.isObject(options)) {
    region = options.region;
  }

  // if there's no region specified we'll assume you meant the main region
  region = region || DEFAULT_REGION;

  // Add the region to the layout if it doesn't exist already and call the
  // create() method on the new DynamicTemplate to create the UI.Component and
  // return it. DynamicTemplate is not an instance of UI.Component.
  return layout.region(region).create();
}));

/**
 * Render a template into a region in the closest layout ancestor from within
 * your template markup.
 *
 * Examples:
 *
 *  {{#contentFor "footer"}}
 *    Footer stuff
 *  {{/contentFor}}
 *
 *  {{> contentFor region="footer" template="SomeTemplate" data=someData}}
 *
 * Note: The helper is a UI.Component object instead of a function so that
 * Meteor UI does not create a Deps.Dependency.
 */
UI.registerHelper('contentFor', Template.__create__('contentFor', function () {
  var layout = findFirstLayout(this);

  if (!layout)
    throw new Error("No Iron.Layout found so you can't use contentFor!");

  var options = DynamicTemplate.getInclusionArguments(this) || {}
  var content = this.templateContentBlock;
  var template = options.template;
  var data = options.data;
  var region;

  if (_.isString(options))
    region = options;
  else if (_.isObject(options))
    region = options.region;
  else
    throw new Error("Which region is this contentFor block supposed to be for?");

  // set the region to a provided template or the content directly.
  layout.region(region).template(template || content);

  // tell the layout to track this as a rendered region if we're in a
  // rendering transaction.
  layout._trackRenderedRegion(region);

  // if we have some data then set the data context
  if (data)
    layout.region(region).data(data);

  // just render nothing into this area of the page since the dynamic template
  // will do the actual rendering into the right region.
  return null;
}));

/**
 * Let people use Layout directly from their templates!
 *
 * Example:
 *  {{#Layout template="MyTemplate"}}
 *    Main content goes here
 *
 *    {{#contentFor "footer"}}
 *      footer goes here
 *    {{/contentFor}}
 *  {{/Layout}}
 */
UI.registerHelper('Layout', Template.__create__('layout', function () {
  var args = Iron.DynamicTemplate.args(this);

  var layout = new Layout({
    template: function () { return args('template'); },
    data: function () { return args('data'); },
    content: this.templateContentBlock
  });

  return layout.create();
}));

/*****************************************************************************/
/* Namespacing */
/*****************************************************************************/
Iron.Layout = Layout;
<commit_msg>fix render method to properly set data<commit_after>/*****************************************************************************/
/* Imports */
/*****************************************************************************/
var DynamicTemplate = Iron.DynamicTemplate;

/*****************************************************************************/
/* Helpers */
/*****************************************************************************/
/**
 * Find the first Layout in the rendered parent hierarchy.
 */
findFirstLayout = function (view) {
  while (view) {
    if (view.kind === 'Iron.Layout')
      return view.__dynamicTemplate__;
    else
      view = view.parentView;
  }

  return null;
};

/*****************************************************************************/
/* Layout */
/*****************************************************************************/

/**
 * Dynamically render templates into regions.
 *
 * Layout inherits from Iron.DynamicTemplate and provides the ability to create
 * regions that a user can render templates or content blocks into. The layout
 * and each region is an instance of DynamicTemplate so the template and data
 * contexts are completely dynamic and programmable in javascript.
 */
Layout = function (options) {
  var self = this;

  Layout.__super__.constructor.apply(this, arguments);

  options = options || {};
  this.kind = 'Iron.Layout';
  this._regions = {};
  this._regionHooks = {};
  this.defaultTemplate('__IronDefaultLayout__');

  // if there's block content then render that
  // to the main region
  if (options.content)
    this.render(options.content);
};

/**
 * The default region for a layout where the main content will go.
 */
DEFAULT_REGION = Layout.DEFAULT_REGION = 'main';

/**
 * Inherits from Iron.DynamicTemplate which gives us the ability to set the
 * template and data context dynamically.
 */
Meteor._inherits(Layout, Iron.DynamicTemplate);

/**
 * Return the DynamicTemplate instance for a given region. If the region doesn't
 * exist it is created.
 *
 * The regions object looks like this:
 *
 *  {
 *    "main": DynamicTemplate,
 *    "footer": DynamicTemplate,
 *    .
 *    .
 *    .
 *  }
 */
Layout.prototype.region = function (name, options) {
  return this._ensureRegion(name, options);
};

/**
 * If we set a new template for the layout we should destroy all of the existing
 * regions.
 */
Layout.prototype.template = function (value) {
  if (arguments.length === 1 && value !== this._template) {
    // if we're setting a new layout template, destroy the existing regions
    // first.
    this.destroyRegions();
  }

  return Layout.__super__.template.apply(this, arguments);
};

/**
 * Destroy all child regions and reset the regions map.
 */
Layout.prototype.destroyRegions = function () {
  _.each(this._regions, function (dynamicTemplate) {
    dynamicTemplate.destroy();
  });

  this._regions = {};
};

/**
 * Set the template for a region.
 */
Layout.prototype.render = function (template, options) {
  // having options is usually good
  options = options || {};

  // let the user specify the region to render the template into
  var region = options.to || options.region || DEFAULT_REGION;

  // get the DynamicTemplate for this region
  var dynamicTemplate = this.region(region);

  // if we're in a rendering transaction, track that we've rendered this
  // particular region
  this._trackRenderedRegion(region);

  // set the template value for the dynamic template
  dynamicTemplate.template(template);

  // if we have data go ahead and set the data for the dynamic template,
  // otherwise, leave it be.
  if (typeof options.data !== 'undefined')
    dynamicTemplate.data(options.data);
};

/**
 * Returns true if the given region is defined and false otherwise.
 */
Layout.prototype.has = function (region) {
  region = region || Layout.DEFAULT_REGION;
  return !!this._regions[region];
};

/**
 * Returns an array of region keys.
 */
Layout.prototype.regionKeys = function () {
  return _.keys(this._regions);
};

/**
 * Clear a given region or the "main" region by default.
 */
Layout.prototype.clear = function (region) {
  region = region || Layout.DEFAULT_REGION;

  // we don't want to create a region if it didn't exist before
  if (this.has(region))
    this.region(region).template(null);

  // chain it up
  return this;
};

/**
 * Clear all regions.
 */
Layout.prototype.clearAll = function () {
  _.each(this._regions, function (dynamicTemplate) {
    dynamicTemplate.template(null);
  });

  // chain it up
  return this;
};

/**
 * Start tracking rendered regions.
 */
Layout.prototype.beginRendering = function (onComplete) {
  var self = this;
  if (this._finishRenderingTransaction)
    this._finishRenderingTransaction();

  this._finishRenderingTransaction = _.once(function () {
    var regions = self._endRendering({flush: false});
    onComplete && onComplete(regions);
  });

  Deps.afterFlush(this._finishRenderingTransaction);

  if (this._renderedRegions)
    throw new Error("You called beginRendering again before calling endRendering");
  this._renderedRegions = {};
};

/**
 * Track a rendered region if we're in a transaction.
 */
Layout.prototype._trackRenderedRegion = function (region) {
  if (!this._renderedRegions)
    return;
  this._renderedRegions[region] = true;
};

/**
 * Stop a rendering transaction and retrieve the rendered regions. This
 * shouldn't be called directly. Instead, pass an onComplete callback to the
 * beginRendering method.
 */
Layout.prototype._endRendering = function (opts) {
  // we flush here to ensure all of the {{#contentFor}} inclusions have had a
  // chance to render from our templates, otherwise we'll never know about
  // them.
  opts = opts || {};
  if (opts.flush !== false)
    Deps.flush();
  var renderedRegions = this._renderedRegions || {};
  this._renderedRegions = null;
  return _.keys(renderedRegions);
};

/**
 * View lifecycle hooks for regions.
 */
_.each(
  [
    'onRegionCreated',
    'onRegionMaterialized',
    'onRegionRendered',
    'onRegionDestroyed'
  ],
  function (hook) {
    Layout.prototype[hook] = function (cb) {
      var hooks = this._regionHooks[hook] = this._regionHooks[hook] || [];
      hooks.push(cb);
      return this;
    }
  }
);

/**
 * Returns the DynamicTemplate for a given region or creates it if it doesn't
 * exists yet.
 */
Layout.prototype._ensureRegion = function (name, options) {
 return this._regions[name] = this._regions[name] || this._createDynamicTemplate(name, options);
};

/**
 * Create a new DynamicTemplate instance.
 */
Layout.prototype._createDynamicTemplate = function (name, options) {
  var self = this;
  var tmpl = new Iron.DynamicTemplate(options);
  var capitalize = Iron.utils.capitalize;
  tmpl._region = name;

  _.each(['created', 'materialized', 'rendered', 'destroyed'], function (hook) {
    hook = capitalize(hook);
    tmpl['on' + hook](function (dynamicTemplate) {
      // "this" is the view instance
      var view = this;
      self._runRegionHooks('on' + 'Region' + hook, view, dynamicTemplate);
    });
  });

  return tmpl;
};

Layout.prototype._runRegionHooks = function (name, regionView, regionDynamicTemplate) {
  var layout = this;
  var hooks = this._regionHooks[name] || [];
  var hook;

  for (var i = 0; i < hooks.length; i++) {
    hook = hooks[i];
    // keep the "thisArg" pointing to the view, but make the first parameter to
    // the callback teh dynamic template instance.
    hook.call(regionView, regionDynamicTemplate.region, regionDynamicTemplate, this);
  }
};

/*****************************************************************************/
/* UI Helpers */
/*****************************************************************************/

/**
 * Create a region in the closest layout ancestor.
 *
 * Examples:
 *
 *      {{> yield "aside"}}
 *
 *
 *

 *      {{> yield}}
 *

 *
 *
 *      {{> yield "footer"}}
 *
 */
UI.registerHelper('yield', Template.__create__('yield', function () {
  var layout = findFirstLayout(this);

  if (!layout)
    throw new Error("No Iron.Layout found so you can't use yield!");

  // Example options: {{> yield region="footer"}} or {{> yield "footer"}}
  var options = DynamicTemplate.getInclusionArguments(this);
  var region;

  if (_.isString(options)) {
    region = options;
  } else if (_.isObject(options)) {
    region = options.region;
  }

  // if there's no region specified we'll assume you meant the main region
  region = region || DEFAULT_REGION;

  // Add the region to the layout if it doesn't exist already and call the
  // create() method on the new DynamicTemplate to create the UI.Component and
  // return it. DynamicTemplate is not an instance of UI.Component.
  return layout.region(region).create();
}));

/**
 * Render a template into a region in the closest layout ancestor from within
 * your template markup.
 *
 * Examples:
 *
 *  {{#contentFor "footer"}}
 *    Footer stuff
 *  {{/contentFor}}
 *
 *  {{> contentFor region="footer" template="SomeTemplate" data=someData}}
 *
 * Note: The helper is a UI.Component object instead of a function so that
 * Meteor UI does not create a Deps.Dependency.
 */
UI.registerHelper('contentFor', Template.__create__('contentFor', function () {
  var layout = findFirstLayout(this);

  if (!layout)
    throw new Error("No Iron.Layout found so you can't use contentFor!");

  var options = DynamicTemplate.getInclusionArguments(this) || {}
  var content = this.templateContentBlock;
  var template = options.template;
  var data = options.data;
  var region;

  if (_.isString(options))
    region = options;
  else if (_.isObject(options))
    region = options.region;
  else
    throw new Error("Which region is this contentFor block supposed to be for?");

  // set the region to a provided template or the content directly.
  layout.region(region).template(template || content);

  // tell the layout to track this as a rendered region if we're in a
  // rendering transaction.
  layout._trackRenderedRegion(region);

  // if we have some data then set the data context
  if (data)
    layout.region(region).data(data);

  // just render nothing into this area of the page since the dynamic template
  // will do the actual rendering into the right region.
  return null;
}));

/**
 * Let people use Layout directly from their templates!
 *
 * Example:
 *  {{#Layout template="MyTemplate"}}
 *    Main content goes here
 *
 *    {{#contentFor "footer"}}
 *      footer goes here
 *    {{/contentFor}}
 *  {{/Layout}}
 */
UI.registerHelper('Layout', Template.__create__('layout', function () {
  var args = Iron.DynamicTemplate.args(this);

  var layout = new Layout({
    template: function () { return args('template'); },
    data: function () { return args('data'); },
    content: this.templateContentBlock
  });

  return layout.create();
}));

/*****************************************************************************/
/* Namespacing */
/*****************************************************************************/
Iron.Layout = Layout;
<|endoftext|>


<commit_before>/*
 * Copyright 2012 soundarapandian
 * Licensed under the Apache License, Version 2.0
 *
 * 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.
 */
$(document).ready(function() {
  /*Timer control
  For detailed usage visit the below link
  http://keith-wood.name/countdownRef.html
  */
  $(".timer").countdown({
    until: '+30d',
    labels: ['Years', 'Months', 'Weeks', 'Days', 'Hrs', 'Mins', 'Secs']
  });
});
<commit_msg>timer<commit_after>/*
 * Copyright 2012 soundarapandian
 * Licensed under the Apache License, Version 2.0
 *
 * 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.
 */
$(document).ready(function() {
  /*Timer control
  For detailed usage visit the below link
  http://keith-wood.name/countdownRef.html
  */
  $(".timer").countdown({
    until: '+1o',
    labels: ['Years', 'Months', 'Weeks', 'Days', 'Hrs', 'Mins', 'Secs']
  });
});
<|endoftext|>


<commit_before>/*jslint node: true */
'use strict';

angular.module('myApp.controllers', [])
    .controller('LakeListCtrl', [
        '$scope', 'UserLocationService', 'LakeDataProviderService', 'LatLngDistanceService',
        function($scope, UserLocationService, LakeDataProviderService, LatLngDistanceService) {
            /* Controller for the lake list */
            var lakeList = LakeDataProviderService.getListOfLakesWithDescription();

            /* jshint unused:false */
            var userLocation = UserLocationService.getUserLocation()
                .then(function success(res) {
                    var lakeListWithDistance = lakeList.map(function(lake) {
                        // distance calculated by long/lat in meters
                        var distance = LatLngDistanceService.distanceTo(res, lake.location);

                        return {
                            'name': lake.name,
                            'description': lake.description,
                            'attributes': lake.attributes,
                            'distance': distance / 1000
                        };
                    });

                    $scope.lakeList = lakeListWithDistance;
                }, function error() {
                    $scope.lakeList = lakeList; // no distance nor locations
                });
        }
    ])
    .controller('MapCtrl', ['$scope', '$modal', 'leafletData', 'leafletEvents', 'LakeDataProviderService', 'UserLocationService', 'mapCenter',
        function($scope, $modal, leafletData, leafletEvents, LakeDataProviderService, UserLocationService, mapCenter) {
            /* Controller for the lake map providing an overview */
            angular.extend($scope, {
                center: mapCenter,
                defaults: {
                    tileLayer: 'https://{s}.tiles.mapbox.com/v3/foobar123.j5b19dpp/{z}/{x}/{y}.png',
                    tileLayerOptions: {
                        attribution: '© Mapbox © OpenStreetMap contributors',
                        detectRetina: true,
                        reuseTiles: true,
                    }
                }
            });

            $scope.markers = LakeDataProviderService.getLakeLocationMarkers();

            var userLocationMarkerIcon = {
                'iconUrl': 'public/img/marker-red.png',
                'shadowUrl': 'public/img/marker-shadow.png',
                'iconSize': [25, 41],
                'shadowSize': [41, 41],
                'popupAnchor': [0, -39]
            };

            /* jshint unused:false */
            var userLocation = UserLocationService.getUserLocation()
                .then(function success(res) {
                    $scope.markers.userLocationMarker = {
                        'lat': res.lat,
                        'lng': res.lng,
                        'icon': userLocationMarkerIcon,
                        'message': 'Aktueller Standpunkt'
                    };
                });

            $scope.$on('leafletDirectiveMarker.click', function(event, leafletEvent) {
                if (leafletEvent.markerName !== 'userLocationMarker') {
                    /* jshint unused:false */
                    var modalInstance = $modal.open({
                        'controller': 'ModalInstanceCtrl',
                        'templateUrl': 'public/partials/lakeDescriptionModal.html',
                        'resolve': {
                            'data': function() {
                                return $scope.markers[leafletEvent.markerName].data;
                            }
                        }
                    });
                }
            });
        }
    ])
    .controller('MainCtrl', ['$scope', '$window', '$modal', 'appTitle', 'footNotice', 'contributors', 'labInfo',
        function($scope, $window, $modal, appTitle, footNotice, contributors, labInfo) {
            var footCols = 0;
            $window.document.title = appTitle; // set page title

            $scope.title = appTitle; // sets h1

            // build footer and increment column count for bootstrap grid cols
            $scope.footNotice = footNotice;
            footCols++;

            $scope.contributors = contributors;
            footCols++;

            // logo and link with title
            $scope.labInfo = labInfo;
            footCols++;

            if (footCols > 0) {
                $scope.footerColumns = (12 / footCols); // FIXME: what about 5, 7 and so on?
            } else {
                $scope.footerCloumns = 1;
            }

            // show help modal
            $scope.showHelpModal = function() {
                /* jshint unused:false */
                var modalInstance = $modal.open({
                    'controller': 'ModalInstanceCtrl',
                    'templateUrl': 'public/partials/faq.html',
                    'resolve': {
                        'data': function() {
                            return null;
                        }
                    }
                });
            };
        }
    ])
    .controller('ModalInstanceCtrl', ['$scope', '$modalInstance', 'data',
        function($scope, $modalInstance, data) {
            $scope.data = data;
            $scope.dismiss = function() {
                $modalInstance.dismiss();
            };
        }
    ]);
<commit_msg>implemented ascending sorting of lakes by distance (closes #22)<commit_after>/*jslint node: true */
'use strict';

angular.module('myApp.controllers', [])
    .controller('LakeListCtrl', [
        '$scope', 'UserLocationService', 'LakeDataProviderService', 'LatLngDistanceService',
        function($scope, UserLocationService, LakeDataProviderService, LatLngDistanceService) {
            /* Controller for the lake list */
            var lakeList = LakeDataProviderService.getListOfLakesWithDescription();

            /* jshint unused:false */
            var userLocation = UserLocationService.getUserLocation()
                .then(function success(res) {
                    var lakeListWithDistance = lakeList.map(function(lake) {
                        // distance calculated by long/lat in meters
                        var distance = LatLngDistanceService.distanceTo(res, lake.location);

                        return {
                            'name': lake.name,
                            'description': lake.description,
                            'attributes': lake.attributes,
                            'distance': distance / 1000
                        };
                    });

                    lakeListWithDistance.sort(function compare(a, b) {
                        return a.distance - b.distance;
                    });

                    $scope.lakeList = lakeListWithDistance;
                }, function error() {
                    $scope.lakeList = lakeList; // no distance nor locations
                });
        }
    ])
    .controller('MapCtrl', ['$scope', '$modal', 'leafletData', 'leafletEvents', 'LakeDataProviderService', 'UserLocationService', 'mapCenter',
        function($scope, $modal, leafletData, leafletEvents, LakeDataProviderService, UserLocationService, mapCenter) {
            /* Controller for the lake map providing an overview */
            angular.extend($scope, {
                center: mapCenter,
                defaults: {
                    tileLayer: 'https://{s}.tiles.mapbox.com/v3/foobar123.j5b19dpp/{z}/{x}/{y}.png',
                    tileLayerOptions: {
                        attribution: '© Mapbox © OpenStreetMap contributors',
                        detectRetina: true,
                        reuseTiles: true,
                    }
                }
            });

            $scope.markers = LakeDataProviderService.getLakeLocationMarkers();

            var userLocationMarkerIcon = {
                'iconUrl': 'public/img/marker-red.png',
                'shadowUrl': 'public/img/marker-shadow.png',
                'iconSize': [25, 41],
                'shadowSize': [41, 41],
                'popupAnchor': [0, -39]
            };

            /* jshint unused:false */
            var userLocation = UserLocationService.getUserLocation()
                .then(function success(res) {
                    $scope.markers.userLocationMarker = {
                        'lat': res.lat,
                        'lng': res.lng,
                        'icon': userLocationMarkerIcon,
                        'message': 'Aktueller Standpunkt'
                    };
                });

            $scope.$on('leafletDirectiveMarker.click', function(event, leafletEvent) {
                if (leafletEvent.markerName !== 'userLocationMarker') {
                    /* jshint unused:false */
                    var modalInstance = $modal.open({
                        'controller': 'ModalInstanceCtrl',
                        'templateUrl': 'public/partials/lakeDescriptionModal.html',
                        'resolve': {
                            'data': function() {
                                return $scope.markers[leafletEvent.markerName].data;
                            }
                        }
                    });
                }
            });
        }
    ])
    .controller('MainCtrl', ['$scope', '$window', '$modal', 'appTitle', 'footNotice', 'contributors', 'labInfo',
        function($scope, $window, $modal, appTitle, footNotice, contributors, labInfo) {
            var footCols = 0;
            $window.document.title = appTitle; // set page title

            $scope.title = appTitle; // sets h1

            // build footer and increment column count for bootstrap grid cols
            $scope.footNotice = footNotice;
            footCols++;

            $scope.contributors = contributors;
            footCols++;

            // logo and link with title
            $scope.labInfo = labInfo;
            footCols++;

            if (footCols > 0) {
                $scope.footerColumns = (12 / footCols); // FIXME: what about 5, 7 and so on?
            } else {
                $scope.footerCloumns = 1;
            }

            // show help modal
            $scope.showHelpModal = function() {
                /* jshint unused:false */
                var modalInstance = $modal.open({
                    'controller': 'ModalInstanceCtrl',
                    'templateUrl': 'public/partials/faq.html',
                    'resolve': {
                        'data': function() {
                            return null;
                        }
                    }
                });
            };
        }
    ])
    .controller('ModalInstanceCtrl', ['$scope', '$modalInstance', 'data',
        function($scope, $modalInstance, data) {
            $scope.data = data;
            $scope.dismiss = function() {
                $modalInstance.dismiss();
            };
        }
    ]);
<|endoftext|>


<commit_before>angular.module('editTasting', []).controller('EditTastingController', ['$scope', '$routeParams', '$http',
    function ($scope, $routeParams, $http) {
        //TODO for some reason 200 ok is always received even if we call /plaa/plaa
        $scope.tasting = {}
        $http.get('/api/beers').
            success(function(data) {
                $scope.beers = _.pluck(data.beers, 'name')
            }).
            error(function(data, status, headers, config) {
                console.log('ERROR', status)
            });
        $scope.tastingId = $routeParams.tastingId
        $scope.onType = function(x) { console.log('onType', x) }
        $scope.save = function(tasting) { console.log("save", tasting); console.log(tasting) }
    }]
);
<commit_msg>Use helper func<commit_after>angular.module('editTasting', []).controller('EditTastingController', ['$scope', '$routeParams', '$http',
    function ($scope, $routeParams, $http) {
        //TODO for some reason 200 ok is always received even if we call /plaa/plaa
        $scope.tasting = {}
        $http.get('/api/beers').
            success(function(data) {
                $scope.beers = _.pluck(data.beers, 'name')
            }).
            error(function(data, status, headers, config) {
                console.log('ERROR', status)
            });
        $scope.tastingId = $routeParams.tastingId
        $scope.onType = function(x) { console.log('onType', x) }
        $scope.save = save
        function save(tasting) { console.log("save", tasting); console.log(tasting) }
    }]
);
<|endoftext|>


<commit_before>var VisualScheduleCard = {
    name: 'VisualScheduleCard',
    dom_target: undefined,
    term: 'current',
    ck_student_schedule: false,
    ck_instructor_schedule: false,
    day_label_offset: 0,

    hide_card: function() {
        if (window.user.student || window.user.instructor) {
            return false;
        }
        return true;
    },

    render_init: function(term, course_index) {
        if (VisualScheduleCard.hide_card()) {
            $("#VisualScheduleCard").hide();
            return;
        }
        WSData.fetch_visual_schedule_term(VisualScheduleCard.term,
                                          VisualScheduleCard.render_handler,
                                          VisualScheduleCard.render_handler);
    },

    render_handler: function() {
        var schedule_data = WSData.visual_schedule_data(VisualScheduleCard.term);
        var default_period = VisualScheduleCard._get_default_period(schedule_data.periods);

        VisualScheduleCard.display_schedule_for_period(default_period);
    },

    _render_error: function() {
        $("#VisualScheduleCard").hide();
    },

    _get_period_lables: function(schedule_data){
        var periods = {};
        $(schedule_data.periods).each(function(idx, period){
            periods[period.id] = {'start_date': period.start_date,
                'end_date': period.end_date};
        });
        return periods;
    },

    _get_data_for_period: function(course_data, term){
        var days = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
        var visual_data = {
            //has_early_fall_start: ((course_data && course_data.has_early_fall_start) ||
            //                       (instructed_course_data &&
            //                        instructed_course_data.has_early_fall_start)),
            is_pce: window.user.pce,
            total_sections: course_data.sections.length,
            quarter: term.quarter,
            year: term.year,
            //year: course_data ? course_data.year : instructed_course_data.year,
            //quarter: course_data ? course_data.quarter : instructed_course_data.quarter,
            //term: term,
            //summer_term: course_data ? course_data.summer_term : instructed_course_data.summer_term,
            latest_ending: 0,
            earliest_start: 24*60,
            monday: [],
            tuesday: [],
            wednesday: [],
            thursday: [],
            friday: [],
            saturday: [],
            sunday: [],
            display_hours: [],
            day_class: "five-day",
            courses_meeting_tbd: [],
            courses_no_meeting: [],
            meets_saturday: false,
            meets_sunday: false
        };

        var set_meeting = function(course_data) {
            $.each(course_data.sections, function(section_index) {
                var section = this;
                $.each(section.meetings, function(){
                    var meeting = this;
                    var has_meetings = VisualScheduleCard._meeting_has_meetings(meeting);
                    var seen = false;
                    if (!meeting.days_tbd && has_meetings) {

                        var start_parts = meeting.start_time.split(":");
                        var start_minutes = parseInt(start_parts[0], 10) * 60 + parseInt(start_parts[1], 10);

                        var end_parts = meeting.end_time.split(":");
                        var end_minutes = parseInt(end_parts[0], 10) * 60 + parseInt(end_parts[1], 10);

                        if (start_minutes < visual_data.earliest_start) {
                            visual_data.earliest_start = start_minutes;
                        }
                        if (end_minutes > visual_data.latest_ending) {
                            visual_data.latest_ending = end_minutes;
                        }

                        var meeting_info = {
                            is_meeting: true,
                            is_instructor: section.is_teaching,
                            start: start_minutes,
                            end: end_minutes,
                            color_id: section.color_id,
                            curriculum: section.curriculum_abbr,
                            course_number: section.course_number,
                            //term: term,
                            section_id: section.section_id,
                            section_index: section_index,
                            building_tbd: meeting.building_tbd,
                            building: meeting.building,
                            building_name: meeting.building_name,
                            room_tbd: meeting.room_tbd,
                            room: meeting.room,
                            latitude: meeting.latitude,
                            longitude: meeting.longitude,
                            early_fall_start: section.early_fall_start,
                            has_early_fall_start: course_data.has_early_fall_start
                        };
                        if(course_data.meets_saturday && course_data.meets_sunday){
                            visual_data.day_class = "seven-day";
                        } else if(course_data.meets_saturday || course_data.meets_sunday){
                            visual_data.day_class = "seven-day";
                        } else {

                        }

                        visual_data.meets_saturday = course_data.meets_saturday;
                        visual_data.meets_sunday = course_data.meets_sunday;

                        $.each(days, function(){
                            day = this.toString();
                            if (meeting.meeting_days[day]) {
                                visual_data[day].push(meeting_info);
                            }
                        });
                    }
                    else if (meeting.days_tbd){
                        $.each(visual_data.courses_meeting_tbd, function () {
                            if (this.section_index === section_index) {
                                seen = true;
                                return false;
                            }
                        });

                        // has meetings that are TBD
                        if (!seen) {
                            visual_data.courses_meeting_tbd.push({
                                color_id: section.color_id,
                                curriculum: section.curriculum_abbr,
                                course_number: section.course_number,
                                section_id: section.section_id,
                                section_index: section_index
                            });
                        }
                    }
                    else {
                        $.each(visual_data.courses_no_meeting, function () {
                            if (this.section_index === section_index) {
                                seen = true;
                                return false;
                            }
                        });

                        // Has no meetings, not TBD (eg individual start PCE courses)
                        if (!seen) {
                            visual_data.courses_no_meeting.push({
                                color_id: section.color_id,
                                curriculum: section.curriculum_abbr,
                                course_number: section.course_number,
                                section_id: section.section_id,
                                section_index: section_index
                            });
                        }
                    }
                });
            });
        };
        var day, day_index, i, height, top;

        if (course_data) {
            set_meeting(course_data);
        }

        // Make it so the start and end times are always on the hour:
        var start_hour = parseInt(visual_data.earliest_start / 60, 10);

        if ((start_hour * 60) === visual_data.earliest_start) {
            visual_data.start_time = (start_hour * 60) - 60;
        }
        else {
            visual_data.start_time = (start_hour * 60);
        }

        var end_hour = parseInt(visual_data.latest_ending / 60, 10) + 1;
        if ((end_hour * 60) === visual_data.latest_ending) {
            visual_data.end_time = (end_hour * 60) - 60;
        }
        else {
            visual_data.end_time = (end_hour * 60);
        }

        i = 0;
        var position_index = 0;
        // We don't want to add the last hour - it's just off the end of the visual schedule
        for (i = visual_data.start_time; i <= visual_data.end_time - 1; i += 60) {
            visual_data.display_hours.push({
                                               hour: (i / 60),
                                               position: i,
                                               hour_count: position_index
                                           });
            position_index += 1;
        }

        visual_data.total_hours = (visual_data.end_time - visual_data.start_time) / 60;

        var hours_count = parseInt((visual_data.end_time - visual_data.start_time) / 60, 0);
        if (hours_count <= 6) {
            visual_data.schedule_hours_class = "six-hour";
        }
        else if (hours_count <= 12) {
            visual_data.schedule_hours_class = "twelve-hour";
        }
        else {
            visual_data.schedule_hours_class = "twelve-plus";
        }

        for (day_index = 0; day_index < days.length; day_index++) {
            day = days[day_index];
            i = 0;
            while (i < visual_data[day].length) {

                top = VisualScheduleCard.get_scaled_percentage(visual_data[day][i].start, visual_data.start_time, visual_data.end_time);
                height =  VisualScheduleCard.get_scaled_percentage(visual_data[day][i].end, visual_data.start_time, visual_data.end_time) - top;
                visual_data[day][i].top=top;
                visual_data[day][i].height=height;
                i += 1;
            }

            var start_at_hr = true;
            var position_start = visual_data.start_time;
            while (position_start < visual_data.end_time) {
                var position_end = position_start + 30;
                top = VisualScheduleCard.get_scaled_percentage(position_start, visual_data.start_time, visual_data.end_time);
                height =  VisualScheduleCard.get_scaled_percentage(position_end, visual_data.start_time, visual_data.end_time) - top;
                visual_data[day].push({
                                          is_meeting: false,
                                          start_at_hr: start_at_hr,
                                          top:top,
                                          height:height,
                                          start: position_start,
                                          end: position_end});
                position_start = position_end;
                start_at_hr = !start_at_hr;
            }
        }
        return visual_data;
    },
    _meeting_has_meetings: function(meeting){
        var has_meeting = false;
        $.each(meeting.meeting_days, function (idx, meeting) {
            if (meeting !== null){
                has_meeting = true;
            }
        });
        return has_meeting;
    },
    get_scaled_percentage: function(pos, min, max) {
        var base_percentage = (pos - min) / (max - min);
        var offset_percentage = (VisualScheduleCard.day_label_offset * 2) + (base_percentage * (100 - (VisualScheduleCard.day_label_offset * 2)));

        // The second one is for positioning the last hour label.
        return offset_percentage - VisualScheduleCard.day_label_offset;
    },
    add_events: function(term) {
        $(".show_visual_map").on("click", function(ev) {
            var building_name = ev.currentTarget.getAttribute("rel");
            building_name = building_name.replace(/[^a-z0-9]/gi, '_');
            var building = ev.currentTarget.getAttribute("rel");
            building = building.replace(/[^a-z0-9]/gi, '_');
            WSData.log_interaction("show_map_from_visual_card_"+building, term);
        });

        $("a.schedule-period-anchor").on("click", function(ev){
            var period_id = $(this).attr('data-period_id');
            VisualScheduleCard.display_schedule_for_period(period_id);
            return false;
        });
    },

    render_schedule: function(data){
        var source = $("#visual_schedule_card_content").html();
        var template = Handlebars.compile(source);
        var t = template(data);
        VisualScheduleCard.dom_target.html(t);
        VisualScheduleCard.add_events();

    },

    display_schedule_for_period: function(period_id){
        var schedule_data = WSData.visual_schedule_data(VisualScheduleCard.term),
            period,
            processed_period;

        if(period_id === "finals"){
            // Render VS with first period data to get correct labels
            processed_period = VisualScheduleCard._get_processed_data_for_period(0);
            processed_period.active_period_id = period_id;
            processed_period.sr_finals = VisualScheduleCard._get_finals_period(schedule_data.periods).sections;
            VisualScheduleCard.render_schedule(processed_period);

            period = VisualScheduleCard._get_finals_period(schedule_data.periods);
            var target = $("#schedule_area").first();
            FinalExamSchedule.render(period, schedule_data.term, false, target);
        } else {
            processed_period = VisualScheduleCard._get_processed_data_for_period(period_id);
            processed_period.sr_finals = VisualScheduleCard._get_finals_period(schedule_data.periods).sections;
            VisualScheduleCard.render_schedule(processed_period);
        }
        LogUtils.cardLoaded(VisualScheduleCard.name, VisualScheduleCard.dom_target);
    },

    _get_processed_data_for_period: function(period_id){
        var schedule_data = WSData.visual_schedule_data(VisualScheduleCard.term),
            period = schedule_data.periods[period_id];
        var processed_period = VisualScheduleCard._get_data_for_period(period, schedule_data.term);
        var period_labels = VisualScheduleCard._get_period_lables(schedule_data);
        processed_period.schedule_periods = period_labels;
        processed_period.active_period_id = period_id;
        return processed_period;
    },

    _get_finals_period: function(periods){
        var finals_period;
        $(periods).each(function(idx, period){
            if (period.id === "finals"){
                finals_period = period;
            }
        });
        return finals_period;
    },

    _get_default_period: function(periods){
        var today = moment.utc(window.card_display_dates.comparison_date, "YYYY-MM-DD"),
            default_period,
            i;

        $.each(periods, function(idx, period){
            if (moment.utc(period.start_date, "YYYY-MM-DD").isSameOrBefore(today) &&
                            moment.utc(period.end_date, "YYYY-MM-DD").isSameOrAfter(today)){
                default_period = period.id;
            }
        });

        if (default_period === undefined){
            default_period = Object.keys(periods)[0];
        }

        return default_period;
    }

};

/* node.js exports */
if (typeof exports === "undefined") {
    var exports = {};
}
exports.VisualScheduleCard = VisualScheduleCard;
<commit_msg>resolves test<commit_after>var VisualScheduleCard = {
    name: 'VisualScheduleCard',
    dom_target: undefined,
    term: 'current',
    ck_student_schedule: false,
    ck_instructor_schedule: false,
    day_label_offset: 0,

    hide_card: function() {
        if (window.user.student || window.user.instructor) {
            return false;
        }
        return true;
    },

    render_init: function(term, course_index) {
        if (VisualScheduleCard.hide_card()) {
            $("#VisualScheduleCard").hide();
            return;
        }
        WSData.fetch_visual_schedule_term(VisualScheduleCard.term,
                                          VisualScheduleCard.render_handler,
                                          VisualScheduleCard.render_handler);
    },

    render_handler: function() {
        var schedule_data = WSData.visual_schedule_data(VisualScheduleCard.term);
        var default_period = VisualScheduleCard._get_default_period(schedule_data.periods);

        VisualScheduleCard.display_schedule_for_period(default_period);
    },

    _render_error: function() {
        $("#VisualScheduleCard").hide();
    },

    _get_period_lables: function(schedule_data){
        var periods = {};
        $(schedule_data.periods).each(function(idx, period){
            periods[period.id] = {'start_date': period.start_date,
                'end_date': period.end_date};
        });
        return periods;
    },

    _get_data_for_period: function(course_data, term){
        var days = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
        var visual_data = {
            //has_early_fall_start: ((course_data && course_data.has_early_fall_start) ||
            //                       (instructed_course_data &&
            //                        instructed_course_data.has_early_fall_start)),
            is_pce: window.user.pce,
            total_sections: course_data.sections.length,
            quarter: term.quarter,
            year: term.year,
            //year: course_data ? course_data.year : instructed_course_data.year,
            //quarter: course_data ? course_data.quarter : instructed_course_data.quarter,
            //term: term,
            //summer_term: course_data ? course_data.summer_term : instructed_course_data.summer_term,
            latest_ending: 0,
            earliest_start: 24*60,
            monday: [],
            tuesday: [],
            wednesday: [],
            thursday: [],
            friday: [],
            saturday: [],
            sunday: [],
            display_hours: [],
            day_class: "five-day",
            courses_meeting_tbd: [],
            courses_no_meeting: [],
            meets_saturday: false,
            meets_sunday: false
        };

        var set_meeting = function(course_data) {
            $.each(course_data.sections, function(section_index) {
                var section = this;
                $.each(section.meetings, function(){
                    var meeting = this;
                    var has_meetings = VisualScheduleCard._meeting_has_meetings(meeting);
                    var seen = false;
                    if (!meeting.days_tbd && has_meetings) {

                        var start_parts = meeting.start_time.split(":");
                        var start_minutes = parseInt(start_parts[0], 10) * 60 + parseInt(start_parts[1], 10);

                        var end_parts = meeting.end_time.split(":");
                        var end_minutes = parseInt(end_parts[0], 10) * 60 + parseInt(end_parts[1], 10);

                        if (start_minutes < visual_data.earliest_start) {
                            visual_data.earliest_start = start_minutes;
                        }
                        if (end_minutes > visual_data.latest_ending) {
                            visual_data.latest_ending = end_minutes;
                        }

                        var meeting_info = {
                            is_meeting: true,
                            is_instructor: section.is_teaching,
                            start: start_minutes,
                            end: end_minutes,
                            color_id: section.color_id,
                            curriculum: section.curriculum_abbr,
                            course_number: section.course_number,
                            //term: term,
                            section_id: section.section_id,
                            section_index: section_index,
                            building_tbd: meeting.building_tbd,
                            building: meeting.building,
                            building_name: meeting.building_name,
                            room_tbd: meeting.room_tbd,
                            room: meeting.room,
                            latitude: meeting.latitude,
                            longitude: meeting.longitude,
                            early_fall_start: section.early_fall_start,
                            has_early_fall_start: course_data.has_early_fall_start
                        };
                        if(course_data.meets_saturday && course_data.meets_sunday){
                            visual_data.day_class = "seven-day";
                        } else if(course_data.meets_saturday || course_data.meets_sunday){
                            visual_data.day_class = "seven-day";
                        } else {

                        }

                        visual_data.meets_saturday = course_data.meets_saturday;
                        visual_data.meets_sunday = course_data.meets_sunday;

                        $.each(days, function(){
                            day = this.toString();
                            if (meeting.meeting_days[day]) {
                                visual_data[day].push(meeting_info);
                            }
                        });
                    }
                    else if (meeting.days_tbd){
                        $.each(visual_data.courses_meeting_tbd, function () {
                            if (this.section_index === section_index) {
                                seen = true;
                                return false;
                            }
                        });

                        // has meetings that are TBD
                        if (!seen) {
                            visual_data.courses_meeting_tbd.push({
                                color_id: section.color_id,
                                curriculum: section.curriculum_abbr,
                                course_number: section.course_number,
                                section_id: section.section_id,
                                section_index: section_index
                            });
                        }
                    }
                    else {
                        $.each(visual_data.courses_no_meeting, function () {
                            if (this.section_index === section_index) {
                                seen = true;
                                return false;
                            }
                        });

                        // Has no meetings, not TBD (eg individual start PCE courses)
                        if (!seen) {
                            visual_data.courses_no_meeting.push({
                                color_id: section.color_id,
                                curriculum: section.curriculum_abbr,
                                course_number: section.course_number,
                                section_id: section.section_id,
                                section_index: section_index
                            });
                        }
                    }
                });
            });
        };
        var day, day_index, i, height, top;

        if (course_data) {
            set_meeting(course_data);
        }

        // Make it so the start and end times are always on the hour:
        var start_hour = parseInt(visual_data.earliest_start / 60, 10);

        if ((start_hour * 60) === visual_data.earliest_start) {
            visual_data.start_time = (start_hour * 60) - 60;
        }
        else {
            visual_data.start_time = (start_hour * 60);
        }

        var end_hour = parseInt(visual_data.latest_ending / 60, 10) + 1;
        if ((end_hour * 60) === visual_data.latest_ending) {
            visual_data.end_time = (end_hour * 60) - 60;
        }
        else {
            visual_data.end_time = (end_hour * 60);
        }

        i = 0;
        var position_index = 0;
        // We don't want to add the last hour - it's just off the end of the visual schedule
        for (i = visual_data.start_time; i <= visual_data.end_time - 1; i += 60) {
            visual_data.display_hours.push({
                                               hour: (i / 60),
                                               position: i,
                                               hour_count: position_index
                                           });
            position_index += 1;
        }

        visual_data.total_hours = (visual_data.end_time - visual_data.start_time) / 60;

        var hours_count = parseInt((visual_data.end_time - visual_data.start_time) / 60, 0);
        if (hours_count <= 6) {
            visual_data.schedule_hours_class = "six-hour";
        }
        else if (hours_count <= 12) {
            visual_data.schedule_hours_class = "twelve-hour";
        }
        else {
            visual_data.schedule_hours_class = "twelve-plus";
        }

        for (day_index = 0; day_index < days.length; day_index++) {
            day = days[day_index];
            i = 0;
            while (i < visual_data[day].length) {

                top = VisualScheduleCard.get_scaled_percentage(visual_data[day][i].start, visual_data.start_time, visual_data.end_time);
                height =  VisualScheduleCard.get_scaled_percentage(visual_data[day][i].end, visual_data.start_time, visual_data.end_time) - top;
                visual_data[day][i].top=top;
                visual_data[day][i].height=height;
                i += 1;
            }

            var start_at_hr = true;
            var position_start = visual_data.start_time;
            while (position_start < visual_data.end_time) {
                var position_end = position_start + 30;
                top = VisualScheduleCard.get_scaled_percentage(position_start, visual_data.start_time, visual_data.end_time);
                height =  VisualScheduleCard.get_scaled_percentage(position_end, visual_data.start_time, visual_data.end_time) - top;
                visual_data[day].push({
                                          is_meeting: false,
                                          start_at_hr: start_at_hr,
                                          top:top,
                                          height:height,
                                          start: position_start,
                                          end: position_end});
                position_start = position_end;
                start_at_hr = !start_at_hr;
            }
        }
        return visual_data;
    },
    _meeting_has_meetings: function(meeting){
        var has_meeting = false;
        $.each(meeting.meeting_days, function (idx, meeting) {
            if (meeting !== null){
                has_meeting = true;
            }
        });
        return has_meeting;
    },
    get_scaled_percentage: function(pos, min, max) {
        var base_percentage = (pos - min) / (max - min);
        var offset_percentage = (VisualScheduleCard.day_label_offset * 2) + (base_percentage * (100 - (VisualScheduleCard.day_label_offset * 2)));

        // The second one is for positioning the last hour label.
        return offset_percentage - VisualScheduleCard.day_label_offset;
    },
    add_events: function(term) {
        $(".show_visual_map").on("click", function(ev) {
            var building_name = ev.currentTarget.getAttribute("rel");
            building_name = building_name.replace(/[^a-z0-9]/gi, '_');
            var building = ev.currentTarget.getAttribute("rel");
            building = building.replace(/[^a-z0-9]/gi, '_');
            WSData.log_interaction("show_map_from_visual_card_"+building, term);
        });

        $("a.schedule-period-anchor").on("click", function(ev){
            var period_id = $(this).attr('data-period_id');
            VisualScheduleCard.display_schedule_for_period(period_id);
            return false;
        });
    },

    render_schedule: function(data){
        var source = $("#visual_schedule_card_content").html();
        var template = Handlebars.compile(source);
        var t = template(data);
        VisualScheduleCard.dom_target.html(t);
        VisualScheduleCard.add_events();

    },

    display_schedule_for_period: function(period_id){
        var schedule_data = WSData.visual_schedule_data(VisualScheduleCard.term),
            period,
            processed_period;

        if(period_id === "finals"){
            // Render VS with first period data to get correct labels
            processed_period = VisualScheduleCard._get_processed_data_for_period(0);
            processed_period.active_period_id = period_id;
            if (VisualScheduleCard._get_finals_period(schedule_data.periods).hasOwnProperty('sections')){
                processed_period.sr_finals = VisualScheduleCard._get_finals_period(schedule_data.periods).sections;
            }
            VisualScheduleCard.render_schedule(processed_period);

            period = VisualScheduleCard._get_finals_period(schedule_data.periods);
            var target = $("#schedule_area").first();
            FinalExamSchedule.render(period, schedule_data.term, false, target);
        } else {
            processed_period = VisualScheduleCard._get_processed_data_for_period(period_id);
            if (VisualScheduleCard._get_finals_period(schedule_data.periods).hasOwnProperty('sections')){
                processed_period.sr_finals = VisualScheduleCard._get_finals_period(schedule_data.periods).sections;
            }
            VisualScheduleCard.render_schedule(processed_period);
        }
        LogUtils.cardLoaded(VisualScheduleCard.name, VisualScheduleCard.dom_target);
    },

    _get_processed_data_for_period: function(period_id){
        var schedule_data = WSData.visual_schedule_data(VisualScheduleCard.term),
            period = schedule_data.periods[period_id];
        var processed_period = VisualScheduleCard._get_data_for_period(period, schedule_data.term);
        var period_labels = VisualScheduleCard._get_period_lables(schedule_data);
        processed_period.schedule_periods = period_labels;
        processed_period.active_period_id = period_id;
        return processed_period;
    },

    _get_finals_period: function(periods){
        var finals_period;
        $(periods).each(function(idx, period){
            if (period.id === "finals"){
                finals_period = period;
            }
        });
        return finals_period;
    },

    _get_default_period: function(periods){
        var today = moment.utc(window.card_display_dates.comparison_date, "YYYY-MM-DD"),
            default_period,
            i;

        $.each(periods, function(idx, period){
            if (moment.utc(period.start_date, "YYYY-MM-DD").isSameOrBefore(today) &&
                            moment.utc(period.end_date, "YYYY-MM-DD").isSameOrAfter(today)){
                default_period = period.id;
            }
        });

        if (default_period === undefined){
            default_period = Object.keys(periods)[0];
        }

        return default_period;
    }

};

/* node.js exports */
if (typeof exports === "undefined") {
    var exports = {};
}
exports.VisualScheduleCard = VisualScheduleCard;
<|endoftext|>