<commit_before>odoo.define('web.WebClient', function (require) {
"use strict";

var AbstractWebClient = require('web.AbstractWebClient');
var core = require('web.core');
var data = require('web.data');
var data_manager = require('web.data_manager');
var framework = require('web.framework');
var Menu = require('web.Menu');
var Model = require('web.DataModel');
var session = require('web.session');
var SystrayMenu = require('web.SystrayMenu');
var UserMenu = require('web.UserMenu');

return AbstractWebClient.extend({
    events: {
        'click .oe_logo_edit_admin': 'logo_edit',
        'click .oe_logo img': function(ev) {
            ev.preventDefault();
            return this.clear_uncommitted_changes().then(function() {
                framework.redirect("/web" + (core.debug ? "?debug" : ""));
            });
        },
    },
    show_application: function() {
        var self = this;
        self.toggle_bars(true);

        self.update_logo();

        // Menu is rendered server-side thus we don't want the widget to create any dom
        self.menu = new Menu(self);
        self.menu.setElement(this.$el.parents().find('.oe_application_menu_placeholder'));
        self.menu.on('menu_click', this, this.on_menu_action);

        // Create the user menu (rendered client-side)
        self.user_menu = new UserMenu(self);
        var $user_menu_placeholder = $('body').find('.oe_user_menu_placeholder').show();
        var user_menu_loaded = self.user_menu.appendTo($user_menu_placeholder);

        // Create the systray menu (rendered server-side)
        self.systray_menu = new SystrayMenu(self);
        self.systray_menu.setElement(this.$el.parents().find('.oe_systray'));
        var systray_menu_loaded = self.systray_menu.start();

        // Start the menu once both systray and user menus are rendered
        // to prevent overflows while loading
        $.when(systray_menu_loaded, user_menu_loaded).done(function() {
            self.menu.start();
        });

        self.bind_hashchange();
        self.set_title();
        if (self.client_options.action_post_login) {
            self.action_manager.do_action(self.client_options.action_post_login);
            delete(self.client_options.action_post_login);
        }
    },
    toggle_bars: function(value) {
        this.$('tr:has(td.navbar),.oe_leftbar').toggle(value);
    },
    update_logo: function() {
        var company = session.company_id;
        var img = session.url('/web/binary/company_logo' + '?db=' + session.db + (company ? '&company=' + company : ''));
        this.$('.oe_logo img').attr('src', '').attr('src', img);
        this.$('.oe_logo_edit').toggleClass('oe_logo_edit_admin', session.uid === 1);
    },
    logo_edit: function(ev) {
        var self = this;
        ev.preventDefault();
        self.alive(new Model("res.users").get_func("read")(session.uid, ["company_id"])).then(function(res) {
            self.rpc("/web/action/load", { action_id: "base.action_res_company_form" }).done(function(result) {
                result.res_id = res.company_id[0];
                result.target = "new";
                result.views = [[false, 'form']];
                result.flags = {
                    action_buttons: true,
                    headless: true,
                };
                self.action_manager.do_action(result).then(function () {
                    var form = self.action_manager.dialog_widget.views.form.controller;
                    form.on("on_button_cancel", self.action_manager, self.action_manager.dialog_stop);
                    form.on('record_saved', self, function() {
                        self.action_manager.dialog_stop();
                        self.update_logo();
                    });
                });
            });
        });
        return false;
    },
    bind_hashchange: function() {
        var self = this;
        $(window).bind('hashchange', this.on_hashchange);

        var state = $.bbq.getState(true);
        if (_.isEmpty(state) || state.action === "login") {
            self.menu.is_bound.done(function() {
                new Model("res.users").call("read", [session.uid, ["action_id"]]).done(function(data) {
                    if(data.action_id) {
                        self.action_manager.do_action(data.action_id[0]);
                        self.menu.open_action(data.action_id[0]);
                    } else {
                        var first_menu_id = self.menu.$el.find("a:first").data("menu");
                        if(first_menu_id) {
                            self.menu.menu_click(first_menu_id);
                        }
                    }
                });
            });
        } else {
            $(window).trigger('hashchange');
        }
    },
    on_hashchange: function(event) {
        var self = this;
        var stringstate = event.getState(false);
        if (!_.isEqual(this._current_state, stringstate)) {
            var state = event.getState(true);
            if(!state.action && state.menu_id) {
                self.menu.is_bound.done(function() {
                    self.menu.menu_click(state.menu_id);
                });
            } else {
                state._push_me = false;  // no need to push state back...
                this.action_manager.do_load_state(state, !!this._current_state).then(function () {
                    var action = self.action_manager.get_inner_action();
                    if (action) {
                        self.menu.open_action(action.action_descr.id);
                    }
                });
            }
        }
        this._current_state = stringstate;
    },
    on_menu_action: function(options) {
        var self = this;
        return this.menu_dm.add(data_manager.load_action(options.action_id))
            .then(function (result) {
                return self.action_mutex.exec(function() {
                    if (options.needaction) {
                        result.context = new data.CompoundContext(result.context, {
                            search_default_message_needaction: true,
                            search_disable_custom_filters: true,
                        });
                    }
                    var completed = $.Deferred();
                    $.when(self.action_manager.do_action(result, {
                        clear_breadcrumbs: true,
                        action_menu_id: self.menu.current_menu,
                    })).fail(function() {
                        self.menu.open_menu(options.previous_menu_id);
                    }).always(function() {
                        completed.resolve();
                    });
                    setTimeout(function() {
                        completed.resolve();
                    }, 2000);
                    // We block the menu when clicking on an element until the action has correctly finished
                    // loading. If something crash, there is a 2 seconds timeout before it's unblocked.
                    return completed;
                });
            });
    },
    toggle_fullscreen: function(fullscreen) {
        this._super(fullscreen);
        if (!fullscreen) {
            this.menu.reflow();
        }
    },
});

});
<commit_msg>[FIX] web: company image not update when use 'Edit Company data' button<commit_after>odoo.define('web.WebClient', function (require) {
"use strict";

var AbstractWebClient = require('web.AbstractWebClient');
var core = require('web.core');
var data = require('web.data');
var data_manager = require('web.data_manager');
var framework = require('web.framework');
var Menu = require('web.Menu');
var Model = require('web.DataModel');
var session = require('web.session');
var SystrayMenu = require('web.SystrayMenu');
var UserMenu = require('web.UserMenu');

return AbstractWebClient.extend({
    events: {
        'click .oe_logo_edit_admin': 'logo_edit',
        'click .oe_logo img': function(ev) {
            ev.preventDefault();
            return this.clear_uncommitted_changes().then(function() {
                framework.redirect("/web" + (core.debug ? "?debug" : ""));
            });
        },
    },
    show_application: function() {
        var self = this;
        self.toggle_bars(true);

        self.update_logo();

        // Menu is rendered server-side thus we don't want the widget to create any dom
        self.menu = new Menu(self);
        self.menu.setElement(this.$el.parents().find('.oe_application_menu_placeholder'));
        self.menu.on('menu_click', this, this.on_menu_action);

        // Create the user menu (rendered client-side)
        self.user_menu = new UserMenu(self);
        var $user_menu_placeholder = $('body').find('.oe_user_menu_placeholder').show();
        var user_menu_loaded = self.user_menu.appendTo($user_menu_placeholder);

        // Create the systray menu (rendered server-side)
        self.systray_menu = new SystrayMenu(self);
        self.systray_menu.setElement(this.$el.parents().find('.oe_systray'));
        var systray_menu_loaded = self.systray_menu.start();

        // Start the menu once both systray and user menus are rendered
        // to prevent overflows while loading
        $.when(systray_menu_loaded, user_menu_loaded).done(function() {
            self.menu.start();
        });

        self.bind_hashchange();
        self.set_title();
        if (self.client_options.action_post_login) {
            self.action_manager.do_action(self.client_options.action_post_login);
            delete(self.client_options.action_post_login);
        }
    },
    toggle_bars: function(value) {
        this.$('tr:has(td.navbar),.oe_leftbar').toggle(value);
    },
    update_logo: function(reload) {
        var company = session.company_id;
        var img = session.url('/web/binary/company_logo' + '?db=' + session.db + (company ? '&company=' + company : ''));
        this.$('.o_sub_menu_logo img').attr('src', '').attr('src', img + (reload ? "#" + Date.now() : ''));
        this.$('.oe_logo_edit').toggleClass('oe_logo_edit_admin', session.uid === 1);
    },
    logo_edit: function(ev) {
        var self = this;
        ev.preventDefault();
        self.alive(new Model("res.users").get_func("read")(session.uid, ["company_id"])).then(function(res) {
            self.rpc("/web/action/load", { action_id: "base.action_res_company_form" }).done(function(result) {
                result.res_id = res.company_id[0];
                result.target = "new";
                result.views = [[false, 'form']];
                result.flags = {
                    action_buttons: true,
                    headless: true,
                };
                self.action_manager.do_action(result).then(function () {
                    var form = self.action_manager.dialog_widget.views.form.controller;
                    form.on("on_button_cancel", self.action_manager, self.action_manager.dialog_stop);
                    form.on('record_saved', self, function() {
                        self.action_manager.dialog_stop();
                        self.update_logo();
                    });
                });
            });
        });
        return false;
    },
    bind_hashchange: function() {
        var self = this;
        $(window).bind('hashchange', this.on_hashchange);

        var state = $.bbq.getState(true);
        if (_.isEmpty(state) || state.action === "login") {
            self.menu.is_bound.done(function() {
                new Model("res.users").call("read", [session.uid, ["action_id"]]).done(function(data) {
                    if(data.action_id) {
                        self.action_manager.do_action(data.action_id[0]);
                        self.menu.open_action(data.action_id[0]);
                    } else {
                        var first_menu_id = self.menu.$el.find("a:first").data("menu");
                        if(first_menu_id) {
                            self.menu.menu_click(first_menu_id);
                        }
                    }
                });
            });
        } else {
            $(window).trigger('hashchange');
        }
    },
    on_hashchange: function(event) {
        var self = this;
        var stringstate = event.getState(false);
        if (!_.isEqual(this._current_state, stringstate)) {
            var state = event.getState(true);
            if(!state.action && state.menu_id) {
                self.menu.is_bound.done(function() {
                    self.menu.menu_click(state.menu_id);
                });
            } else {
                state._push_me = false;  // no need to push state back...
                this.action_manager.do_load_state(state, !!this._current_state).then(function () {
                    var action = self.action_manager.get_inner_action();
                    if (action) {
                        self.menu.open_action(action.action_descr.id);
                    }
                });
            }
        }
        this._current_state = stringstate;
    },
    on_menu_action: function(options) {
        var self = this;
        return this.menu_dm.add(data_manager.load_action(options.action_id))
            .then(function (result) {
                return self.action_mutex.exec(function() {
                    if (options.needaction) {
                        result.context = new data.CompoundContext(result.context, {
                            search_default_message_needaction: true,
                            search_disable_custom_filters: true,
                        });
                    }
                    var completed = $.Deferred();
                    $.when(self.action_manager.do_action(result, {
                        clear_breadcrumbs: true,
                        action_menu_id: self.menu.current_menu,
                    })).fail(function() {
                        self.menu.open_menu(options.previous_menu_id);
                    }).always(function() {
                        completed.resolve();
                    });
                    setTimeout(function() {
                        completed.resolve();
                    }, 2000);
                    // We block the menu when clicking on an element until the action has correctly finished
                    // loading. If something crash, there is a 2 seconds timeout before it's unblocked.
                    return completed;
                });
            });
    },
    toggle_fullscreen: function(fullscreen) {
        this._super(fullscreen);
        if (!fullscreen) {
            this.menu.reflow();
        }
    },
});

});
<|endoftext|>


<commit_before><commit_msg>Add roundDecimal() function, edit the function's comment. Add the console.log("Library has finished loading."); statement<commit_after>/*
 * Developed by Radu Puspana
 * Date August 2017
 * Version 1.0
 */

// Round the n-th decimal of a float number
// number        Number  the floating point number to be rounded
// decimalIndex  Number  the decimal position to be rounded
//   E.g  decimalIndex = 1, the first digit shuld be rounded
//   E.g  decimalIndex = 2, the second digit shuld be rounded
// return        Number  the number with a rounded decimal
function roundDecimal(number, decimalIndex) {
    var multiplier = Math.pow(10, decimalIndex || 0);
    return Math.round(number * multiplier) / multiplier;
}

console.log("Library has finished loading.");
<|endoftext|>


<commit_before>$(function() {
function NewProperty(propName, bed, price, pets, location, imageName, description) {
    this.propName = propName;
    this.bed = bed;
    this.price = price;
    this.pets = pets;
    this.location = location;
    this.imageName = imageName;
    this.description = description;
  }

NewProperty.prototype.toHtml = function() {
  return '

' + this.propName + '

$ ' + this.price + '

Beds: ' + this.bed + '

Pets Allowed: ' + this.pets + '

<button class="small" id="email">Email</button>

'
}

var addProperty = function(propName, bed, price, pets, location, imageName, description) {
    var property = new NewProperty(propName, bed, price, pets, location, imageName, description);
    $("#listings").append(property.toHtml());
  }

addProperty("Trendy Apartment",     0, 1100, "Yes", "Seattle",      "property1.jpg",  "This is a dope ass apartment");
addProperty("Total Dive",           3, 1800, "No",  "Capitol-Hill", "property2.jpg",  "This place is horrifically dirty but if you're a tough sob it'll do.");
addProperty("Charming Space",       0, 950,  "Yes", "Renton",       "property3.jpg",  "Cute little apartment in the heart of of Renton.");
addProperty("Modern Lodge",         3, 1800, "No",  "Renton",       "property4.jpg",  "It's old and creeky but it looks cool!");
addProperty("Fremont Manor",    3, 2100, "Yes", "Fremont",      "property5.jpg",  "Group living at its best. And optional orgies every Tuesday night.");
addProperty("The Love Pad",         1, 750,  "Yes", "Capitol-Hill", "property6.jpg",  "Only the sexy need apply");
addProperty("Castle",               1, 850,  "No",  "Seattle",      "property7.jpg",  "It's a castle, 'nuff said. Rent it and be a baller who live in a castle.");
addProperty("Capitol-Hill Home",    3, 5000, "No",  "Capitol-Hill", "property8.jpg",  "Great house in a friendly neighbourhood.");
addProperty("Room from Saw",        1, 300,  "No",  "Renton",       "property9.jpg",  "This place is comparable to a nightmare, you won't be able to sleep much.");
addProperty("Pope's Palace",        1, 1800, "No",  "Seattle",      "property10.jpg", "Availability is extremely limited but it's a wonderful space if you are accepted.");
addProperty("Survivor Hut",         0, 200,  "No",  "Fremont",      "property11.jpg", "Test your wit and deception by living underneath this leaf hut.");
addProperty("Homey Home",           3, 1750, "No",  "Capitol-Hill", "property12.jpg", "Spacious and loving home perfect for a close group of friends.");
addProperty("Haunted House",        2, 1100, "No",  "capitolHill",  "property13.jpg", "Frequently frequented by ghoules and ghosts but other than that it is a wonderful house.");
addProperty("Trendy Space",         1, 1300, "No",  "Renton",       "property14.jpg", "This place is perfect for hipsters.");
addProperty("The Shire",            1, 900,  "No",  "Seattle",      "property15.jpg", "Stay warm in the winter and cool in the summer while living under this cozy grassy knoll. ");
addProperty("Cozy Igloo",           2, 750,  "No",  "Seattle",      "property16.jpg", "This place is great eh!");
addProperty("Master suite",         0, 1250, "No",  "Fremont",      "property17.jpg", "Upscale and very fancy. Only rich people who walk their cats will be accepted.");
addProperty("Cool Apartment",       2, 1200, "No",  "Seattle",      "property18.jpg", "It's pretty cool so you should apply quickly.");
addProperty("Renton Home",          3, 1900, "No",  "Renton",       "property19.jpg", "Big home with lots of bathrooms and a hot tub time machine.");
addProperty("Biggest Loser House",  3, 2100, "No",  "Fremont",      "property20.jpg", "Get temporarily fit in this intense living arrangement. Only +300 pounders need apply.");

//~~~~~~~~~~~~ FILTERS START HERE!!!!!!!!!!!!!!!!!! ~~~~~~~~~~~~~~~~

/* this function is used for a basic filter search by the user. The user only searches using the city drop down list */
  function locationSearch() {
    $(".propertyBox").each(function() {
      if (($(this).data("location")) != ($("#locationSelect").val())) {
          $(this).fadeOut(1000);
      }
      if ($("input:checkbox").is(":checked")) {
        //call this function only if checkbox is selected
        petCheckbox();
      }
      if ($("#bed option:selected")) {
        //call this function if bed selector is selected
        bedSelector();
      }
      if (($("#min-price").val() != "") || ($("#max-price").val() != "")) {
        //call this function if input text has values
        priceFilter();
        // console.log("i'm working");
      }
    });
  }
  /*this function will be called if user selects checkbox that states
  he or she owns a pet and would like to filter the apartment listings based off pet availability*/
  function petCheckbox() {
    $(".propertyBox").each(function() {
      if ($(this).data("pets") != "Yes") {
        $(this).fadeOut(1000);
      }
    });
  }
  /*this function will be called in the locationSearch function. depending on the user's selection, a specific case will be run. */
  function bedSelector() {
    $(".propertyBox").each(function() {
    console.log("bed function ran");
      if ($(this).data("bed") != ($("#bed").val())) {
        $(this).fadeOut(1000);
      }
    });
  }

/*this function is to filter listings based off of the user's minimum price and maximum price that are placed in the input text element */
  function priceFilter() {
    //get the value for each input text: Min Price & Max Price
    var minPrice = document.getElementById('min-price').value;
    var maxPrice = document.getElementById('max-price').value;

    $(".propertyBox").each(function() {
      if ($(this).data("price") < minPrice && minPrice != "") {
        $(this).fadeOut(1000);
      }
      if ($(this).data("price") > maxPrice && maxPrice != "") {
        $(this).fadeOut(1000);
      }
    });
  }

  $("#list").on("click", locationSearch);

  // $("#email").on("click", location.href('mailto:brook@codefellows.org'))

});

<commit_msg>add listing.js<commit_after>$(function() {
function NewProperty(propName, bed, price, pets, location, imageName) {
    this.propName = propName;
    this.bed = bed;
    this.price = price;
    this.pets = pets;
    this.location = location;
    this.imageName = imageName;
  }

NewProperty.prototype.toHtml = function() {
  return '

' + this.propName + '

$ ' + this.price + '

Beds: ' + this.bed + '

Pets Allowed: ' + this.pets + '

'
}

var addProperty = function(propName, bed, price, pets, location, imageName) {
    var property = new NewProperty(propName, bed, price, pets, location, imageName);
    $("#listings").append(property.toHtml());
  }

addProperty("Trendy Apartment",     0, 1100, "Yes", "Seattle",      "property1.jpg",  "This is a dope ass apartment");
addProperty("Total Dive",           3, 1800, "No",  "Capitol-Hill", "property2.jpg",  "This place is horrifically dirty but if you're a tough sob it'll do.");
addProperty("Charming Space",       0, 950,  "Yes", "Renton",       "property3.jpg",  "Cute little apartment in the heart of of Renton.");
addProperty("Modern Lodge",         3, 1800, "No",  "Renton",       "property4.jpg",  "It's old and creeky but it looks cool!");
addProperty("Fremont Manor",    3, 2100, "Yes", "Fremont",      "property5.jpg",  "Group living at its best. And optional orgies every Tuesday night.");
addProperty("The Love Pad",         1, 750,  "Yes", "Capitol-Hill", "property6.jpg",  "Only the sexy need apply");
addProperty("Castle",               1, 850,  "No",  "Seattle",      "property7.jpg",  "It's a castle, 'nuff said. Rent it and be a baller who live in a castle.");
addProperty("Capitol-Hill Home",    3, 5000, "No",  "Capitol-Hill", "property8.jpg",  "Great house in a friendly neighbourhood.");
addProperty("Room from Saw",        1, 300,  "No",  "Renton",       "property9.jpg",  "This place is comparable to a nightmare, you won't be able to sleep much.");
addProperty("Pope's Palace",        1, 1800, "No",  "Seattle",      "property10.jpg", "Availability is extremely limited but it's a wonderful space if you are accepted.");
addProperty("Survivor Hut",         0, 200,  "No",  "Fremont",      "property11.jpg", "Test your wit and deception by living underneath this leaf hut.");
addProperty("Homey Home",           3, 1750, "No",  "Capitol-Hill", "property12.jpg", "Spacious and loving home perfect for a close group of friends.");
addProperty("Haunted House",        2, 1100, "No",  "capitolHill",  "property13.jpg", "Frequently frequented by ghoules and ghosts but other than that it is a wonderful house.");
addProperty("Trendy Space",         1, 1300, "No",  "Renton",       "property14.jpg", "This place is perfect for hipsters.");
addProperty("The Shire",            1, 900,  "No",  "Seattle",      "property15.jpg", "Stay warm in the winter and cool in the summer while living under this cozy grassy knoll. ");
addProperty("Cozy Igloo",           2, 750,  "No",  "Seattle",      "property16.jpg", "This place is great eh!");
addProperty("Master suite",         0, 1250, "No",  "Fremont",      "property17.jpg", "Upscale and very fancy. Only rich people who walk their cats will be accepted.");
addProperty("Cool Apartment",       2, 1200, "No",  "Seattle",      "property18.jpg", "It's pretty cool so you should apply quickly.");
addProperty("Renton Home",          3, 1900, "No",  "Renton",       "property19.jpg", "Big home with lots of bathrooms and a hot tub time machine.");
addProperty("Biggest Loser House",  3, 2100, "No",  "Fremont",      "property20.jpg", "Get temporarily fit in this intense living arrangement. Only +300 pounders need apply.");

//~~~~~~~~~~~~ FILTERS START HERE!!!!!!!!!!!!!!!!!! ~~~~~~~~~~~~~~~~

/* this function is used for a basic filter search by the user. The user only searches using the city drop down list */
  function locationSearch() {
    $(".propertyBox").each(function() {
      if (($(this).data("location")) != ($("#locationSelect").val())) {
          $(this).fadeOut(1000);
      }
      if ($("input:checkbox").is(":checked")) {
        //call this function only if checkbox is selected
        petCheckbox();
      }
      if ($("#bed option:selected")) {
        //call this function if bed selector is selected
        bedSelector();
      }
      if (($("#min-price").val() != "") || ($("#max-price").val() != "")) {
        //call this function if input text has values
        priceFilter();
        // console.log("i'm working");
      }
    });
  }
  /*this function will be called if user selects checkbox that states
  he or she owns a pet and would like to filter the apartment listings based off pet availability*/
  function petCheckbox() {
    $(".propertyBox").each(function() {
      if ($(this).data("pets") != "Yes") {
        $(this).fadeOut(1000);
      }
    });
  }
  /*this function will be called in the locationSearch function. depending on the user's selection, a specific case will be run. */
  function bedSelector() {
    $(".propertyBox").each(function() {
    console.log("bed function ran");
      if ($(this).data("bed") != ($("#bed").val())) {
        $(this).fadeOut(1000);
      }
    });
  }

/*this function is to filter listings based off of the user's minimum price and maximum price that are placed in the input text element */
  function priceFilter() {
    //get the value for each input text: Min Price & Max Price
    var minPrice = document.getElementById('min-price').value;
    var maxPrice = document.getElementById('max-price').value;

    $(".propertyBox").each(function() {
      if ($(this).data("price") < minPrice && minPrice != "") {
        $(this).fadeOut(1000);
      }
      if ($(this).data("price") > maxPrice && maxPrice != "") {
        $(this).fadeOut(1000);
      }
    });
  }

  $("#list").on("click", locationSearch);

});

<|endoftext|>


<commit_before>// Provide the ``appname`` and ``appsecret`` as shown in your developer console.
Appbase.credentials("twitter", "2cac84749bc429ad7017bb1685eafaf4");
// In this app **$rootScope** is used for
// changing the routes and managing visibility of navigation bar.
angular.module('twitter', ['ngRoute', 'ngAppbase', 'ngSanitize', 'vs-repeat'])
  .run(function ($rootScope, userSession, $location) {
    "use strict";
    $rootScope.exit = function () {
      userSession.exit();
      $location.path('/global');
    };
    $rootScope.gotoProfile = function (userId) {
      $location.path('/profile/' + userId);
    };
    $rootScope.search = function (text) {
      $location.path('/search/' + text);
    };
    $rootScope.goHome = function (feed) {
      $location.path('/home/' + feed);
    };
    $rootScope.hideNav = function () {
      $rootScope.$broadcast('hideNav', [1]);
    };
    $rootScope.showNav = function () {
      $rootScope.$broadcast('showNav');
    };
    $rootScope.load = function () {
      $location.path('/loading');
    };
    $rootScope.convertToVisibleTime = function (timestamp) {
      return new Date(timestamp).toTwitterRelativeTime();
    };
        $rootScope.urlify = function (text) {
            var urlRegex = /(https?:\/\/[^\s]+)/g;
            return text.replace(urlRegex, function(url) {
                console.log("urlregex matched, ", url);
                return '' + url + '';
            });
        };
  })
  // Code for route management.
  .config(function ($routeProvider) {
    "use strict";
    $routeProvider.when('/', {
      controller: 'global',
      templateUrl: 'views/global.html'
    }).when('/loading', {
        controller: 'loading',
        templateUrl: 'views/loading.html'
      }).when('/search/:text', {
        controller: 'search',
        templateUrl: 'views/search.html'
      }).when('/profile/:userId', {
        controller: 'profile',
        templateUrl: 'views/profile.html'
      }).when('/home/:feed', {
        controller: 'home',
        templateUrl: 'views/home.html'
      }).otherwise({
        redirectTo: '/'
      });
  })
  // **Controller: global**.
  // Show all tweets when no one is logged in.
  .controller('global', function ($scope, userSession, $location, $rootScope, $appbaseRef) {
    "use strict";
    // Hide *navbar* if no one is logged in
    $rootScope.hideNav();
    $scope.convertToVisibleTime = $rootScope.convertToVisibleTime;
        $scope.urlify = $rootScope.urlify;
    // Called when the user enters name or when already logged in.
    $scope.login = function () {
      userSession.setUser($scope.userId.replace(/ /g, "_"));
      $location.path('/loading');
    };
    // Checks if a user is already logged in the session.
    if ($scope.userId === userSession.getUser()) {$scope.login(); }
    // Show all tweets under *global/tweets* using ``bindEdges``, in reverse order of their priorities.
    $appbaseRef('global/tweets').$bindEdges($scope,'tweets', false, false, {}, true);
    $scope.tweetsDisplayed = 8
  })
  // **Controller: search**.
  // Search's for tweets in Appbase and shows results.
    .controller('search', function ($scope, $rootScope, $routeParams) {
    "use strict";
    // Getting the 'query text' from route parameters.
    $scope.currentQuery = $routeParams.text;
        $scope.urlify = $rootScope.urlify;
    // Searching in the namespace: __tweet__ for vertices, which contain 'query text' in the property: __msg__.
    Appbase.search('tweet', {text: $routeParams.text, properties: ['msg']}, function (error, array) {
      if (!error) {
        $scope.tweets = array;
        $scope.$apply();
      }
    });
  })
  // **Controller: Loading**.
  // It inits the __data__ factory, which is used everywhere in the app to fetch and set data from/to Appbase.
  // After the _init_ completes, it takes the user to _home_ screen, showing personal tweets of the user.
  .controller('loading', function ($rootScope, $scope, userSession, data) {
    "use strict";
    if (!userSession.getUser()) {
      $rootScope.exit();
      return;
    }
    data.init(function () {
      $scope.$apply(function () {
        $rootScope.goHome('personal');
      });
    });
  })
  // **Controller: navbar**.
  // Handles button clicks and visibility of buttons.
  .controller('navbar', function ($scope, userSession, $rootScope) {
    "use strict";
    $scope.bahar = true;
    // Called when user enters a text in the search box and presses enter key.
    $scope.search = function () {
      $rootScope.search($scope.searchText);
      $scope.searchText = '';
    };
    $scope.$on('showNav', function () {
      $scope.bahar = false;
    });
    $scope.$on('hideNav', function () {
      $scope.bahar = true;
    });
    $scope.exit = function () {
      $rootScope.exit();
    };
    $scope.gotoProfile = function (userId) {
      if (userId === undefined) { userId = userSession.getUser(); }
      $rootScope.gotoProfile(userId);
    };
    $scope.goHome = function (feed) {
      $rootScope.goHome(feed);
    };
  })
  // **Controller: home**.
  // This is what the user sees first when logged in. It shows the personal and global tweet feeds
  // The personal tweet feed: shows tweets from people he follows.
  // The global feed: tweets by everyone
  .controller('home', function ($scope, userSession, $rootScope, $appbaseRef, $routeParams, data) {
    "use strict";
    // Check if the session is properly initiated,
    // i.e. the 'data' factory set the flag 'initComplete' in userSession.
    if (!userSession.initComplete) {
      if (!userSession.getUser()) {
        $rootScope.exit();
      } else {
        $rootScope.load();
      }
      return;
    }
    $scope.convertToVisibleTime = $rootScope.convertToVisibleTime;
        $scope.urlify = $rootScope.urlify;
    $rootScope.showNav();

    // Get __feed__ from route parameters.
    var feed = $routeParams.feed === undefined ? 'global' : $routeParams.feed,
      usrRef = Appbase.ref('user/' + userSession.getUser() + '/following');
    $scope.tweetsDisplayed = 15;
    $scope.peopleDisplayed = 8;
    $scope.userName = userSession.getUser();
    $scope.gotoProfile = $rootScope.gotoProfile;
    // Show _People on Twitter_, user's _Followers_ and _Followings_.
    $appbaseRef(data.refs.allUsers).$bindEdges($scope,'people', false, false, {}, true);
    $appbaseRef(data.refs.usersFollowers).$bindEdges($scope, 'followers');
    $appbaseRef(data.refs.usersFollowing).$bindEdges($scope, 'following');

    // Called when user posts a new tweet.
    $scope.addTweet = function () {
      data.addTweet($scope.msg);
      $scope.msg = '';
    };
    if (feed === 'global') {
      // Show all tweets.
      $appbaseRef(data.refs.globalTweets).$bindEdges($scope,'tweets', false, false, {}, true);
    } else {
      // Fetch tweets of the people followed by the user. Every following's tweets are pushed into `arraysOfTweets` as an array,
      // and in the end, these arrays are merged into personalTweets by calling `personalTweets.concat.apply(personalTweets, arraysOfTweets)`
      // in _home.html_.
      $scope.personalTweets = [];
      $scope.arraysOfTweets = [];
      $scope.arraysOfTweets.push($appbaseRef('user/' + userSession.getUser() + '/tweets').$bindEdges($scope));
      usrRef.on('edge_added', function (error, followUserRef) {
        if (error) {throw error; }
        $scope.arraysOfTweets.push($appbaseRef(followUserRef).$outVertex('tweets').$bindEdges($scope));
      });
      $scope.$on('$destroy', function () {
        // Stop listening to user's followings when the view is destroyed.
        usrRef.off();
      });
    }
  })
  // **Controller: profile**.
  // Where a user's followings, followers and tweets are shown.
  // A user can also see other's profiles and choose to follow/unfollow the person from his/her profile.
  .controller('profile', function ($scope, userSession, $rootScope, $routeParams, $appbaseRef, data) {
    "use strict";
    if (!userSession.initComplete) {
      if (!userSession.getUser()) {
        $rootScope.exit();
      } else {
        $rootScope.load();
      }
      return;
    }
    $scope.convertToVisibleTime = $rootScope.convertToVisibleTime;
    $rootScope.showNav();

    // Get the userId from route params.
    var userId = $routeParams.userId;
    $scope.userId = $routeParams.userId;
    // Check whether this profile is of the logged in user.
    $scope.isMe = userSession.getUser() === userId;
    $scope.userName = $routeParams.userId;
    $scope.isReady = false;

    // Check whether this user is being followed by the logged in user.
    // This has to be an async function, as it interacts with the Appbase server.
    if (!$scope.isMe) {
      data.isUserBeingFollowed(userId, function (boolean) {
        // If true, _unfollow_ button will appear, otherwise _follow_ one.
        $scope.isBeingFollowed = boolean;
        // Show _follow_ or _unfollow_ buttons only when the data is arrived.
        $scope.isReady = true;
      });
    }
    $scope.gotoProfile = $rootScope.gotoProfile;
    $scope.follow = function (userId) {
      $scope.isBeingFollowed = true;
      data.follow(userId);
    };
    $scope.unFollow = function (userId) {
      $scope.isBeingFollowed = false;
      data.unFollow(userId);
    };
    $scope.addTweet = function () {
      data.addTweet($scope.msg);
      $scope.msg = '';
    };
    // Fetch user's followers, followings and tweets.
    $appbaseRef('user/' + userId + '/followers').$bindEdges($scope, 'followers');
    $appbaseRef('user/' + userId + '/following').$bindEdges($scope, 'following');
    $appbaseRef('user/' + userId + '/tweets').$bindEdges($scope, 'tweets');
  })
  // **Factory: data**.
  //Stores frequently useful Appbase references and interacts with Appbase for data needs
  .factory('data', function (userSession) {
    "use strict";
    // Appbase references
    var refs = {
      globalTweets: Appbase.ref('global/tweets'),
      allUsers: Appbase.ref('global/users')
    }, data = {  // Factory to be exported
      refs: refs
    };
    // Called when the user just logs in.
    // It sets required references and creates basic data for a new user.
    data.init = function (ready) {
      var userId = userSession.getUser();
      refs.user = Appbase.create('user', userSession.getUser());
      refs.usersTweets = refs.user.outVertex('tweets');
      refs.usersFollowers = refs.user.outVertex('followers');
      refs.usersFollowing = refs.user.outVertex('following');
      refs.user.on('properties', function (error, ref, snap) {
        refs.user.off();
        if (error) {throw error; }
        if (snap.properties().name === undefined) {
          // The user logged in for the first time.
          Appbase.ref('global/users').setEdge(refs.user, userId);
          // Set user's name
          refs.user.setData({
            name: userId
          });
          // Create vertices which will store user's followers, followings and tweets.
          refs.user.setEdge(Appbase.create('misc', Appbase.uuid()), 'tweets', function (error) {
            if (error) {throw error; }
            refs.user.setEdge(Appbase.create('misc', Appbase.uuid()), 'followers', function (error) {
              if (error) {throw error; }
              refs.user.setEdge(Appbase.create('misc', Appbase.uuid()), 'following', function (error) {
                if (error) {throw error; }
                //Set the flag true in userSession
                userSession.initComplete = true;
                ready();
              });
            });
          });
        } else {
          // The user exists in Appbase.
          userSession.initComplete = true;
          ready();
        }
      });
    };
    data.addTweet = function (msg) {
      //Create a new 'tweet' vertex and store the tweet message
      var tweetRef = Appbase.create('tweet', Appbase.uuid());
      tweetRef.setData({ 'msg': msg, 'by': userSession.getUser() }, function (error, tweetRef) {
        if (error) {throw error; }
        // Add this tweet as an edge, in user's own tweets and global tweets.
        // We really don't care about the edge's name here
        var randomEdgeName = Appbase.uuid();
        refs.usersTweets.setEdge(tweetRef, randomEdgeName);
        refs.globalTweets.setEdge(tweetRef, randomEdgeName);
      });
    };
    // Checks whether provided userId is being followed by the logged in user
    data.isUserBeingFollowed = function (userId, callback) {
      refs.usersFollowing.outVertex(userId).isValid(function (error, bool) {
        if (error) {throw error; }
        callback(bool);
      });
    };
    data.follow = function (userId) {
      refs.usersFollowing.setEdge(Appbase.ref('user/' + userId), userId);
      Appbase.ref('user/' + userId + '/followers').setEdge(refs.user, userSession.getUser());
    };
    data.unFollow = function (userId) {
      refs.usersFollowing.removeEdge(userId);
      Appbase.ref('user/' + userId + '/followers').removeEdge(userSession.getUser());
    };
    return data;
  })
  // Stores logged in user's id.
  .factory('userSession', function () {
    "use strict";
    var userSession = {};
    userSession.initComplete = false;
    userSession.setUser = function (userId) {
      localStorage.setItem("currentLoggedInUser", userId);
    };
    userSession.exit = function () {
      localStorage.removeItem("currentLoggedInUser");
    };
    userSession.getUser = function () {
      return localStorage.getItem("currentLoggedInUser");
    };
    return userSession;
  })
  .directive('whenScrolled', function() {
    return function(scope, elm, attr) {
      var raw = elm[0];
      elm.bind('scroll', function() {
        if (raw.scrollTop + raw.offsetHeight + 1 >= raw.scrollHeight) { // + 1 added, as a workaround for: (raw.scrollTop + raw.offsetHeight- raw.scrollHeight) would always stop at -1.
          scope.$apply(attr.whenScrolled);
        }
      });
    };
  });
<commit_msg>open links in a new tab<commit_after>// Provide the ``appname`` and ``appsecret`` as shown in your developer console.
Appbase.credentials("twitter", "2cac84749bc429ad7017bb1685eafaf4");
// In this app **$rootScope** is used for
// changing the routes and managing visibility of navigation bar.
angular.module('twitter', ['ngRoute', 'ngAppbase', 'ngSanitize', 'vs-repeat'])
  .run(function ($rootScope, userSession, $location) {
    "use strict";
    $rootScope.exit = function () {
      userSession.exit();
      $location.path('/global');
    };
    $rootScope.gotoProfile = function (userId) {
      $location.path('/profile/' + userId);
    };
    $rootScope.search = function (text) {
      $location.path('/search/' + text);
    };
    $rootScope.goHome = function (feed) {
      $location.path('/home/' + feed);
    };
    $rootScope.hideNav = function () {
      $rootScope.$broadcast('hideNav', [1]);
    };
    $rootScope.showNav = function () {
      $rootScope.$broadcast('showNav');
    };
    $rootScope.load = function () {
      $location.path('/loading');
    };
    $rootScope.convertToVisibleTime = function (timestamp) {
      return new Date(timestamp).toTwitterRelativeTime();
    };
        $rootScope.urlify = function (text) {
            var urlRegex = /(https?:\/\/[^\s]+)/g;
            return text.replace(urlRegex, function(url) {
                console.log("urlregex matched, ", url);
                return '' + url + '';
            });
        };
  })
  // Code for route management.
  .config(function ($routeProvider) {
    "use strict";
    $routeProvider.when('/', {
      controller: 'global',
      templateUrl: 'views/global.html'
    }).when('/loading', {
        controller: 'loading',
        templateUrl: 'views/loading.html'
      }).when('/search/:text', {
        controller: 'search',
        templateUrl: 'views/search.html'
      }).when('/profile/:userId', {
        controller: 'profile',
        templateUrl: 'views/profile.html'
      }).when('/home/:feed', {
        controller: 'home',
        templateUrl: 'views/home.html'
      }).otherwise({
        redirectTo: '/'
      });
  })
  // **Controller: global**.
  // Show all tweets when no one is logged in.
  .controller('global', function ($scope, userSession, $location, $rootScope, $appbaseRef) {
    "use strict";
    // Hide *navbar* if no one is logged in
    $rootScope.hideNav();
    $scope.convertToVisibleTime = $rootScope.convertToVisibleTime;
        $scope.urlify = $rootScope.urlify;
    // Called when the user enters name or when already logged in.
    $scope.login = function () {
      userSession.setUser($scope.userId.replace(/ /g, "_"));
      $location.path('/loading');
    };
    // Checks if a user is already logged in the session.
    if ($scope.userId === userSession.getUser()) {$scope.login(); }
    // Show all tweets under *global/tweets* using ``bindEdges``, in reverse order of their priorities.
    $appbaseRef('global/tweets').$bindEdges($scope,'tweets', false, false, {}, true);
    $scope.tweetsDisplayed = 8
  })
  // **Controller: search**.
  // Search's for tweets in Appbase and shows results.
    .controller('search', function ($scope, $rootScope, $routeParams) {
    "use strict";
    // Getting the 'query text' from route parameters.
    $scope.currentQuery = $routeParams.text;
        $scope.urlify = $rootScope.urlify;
    // Searching in the namespace: __tweet__ for vertices, which contain 'query text' in the property: __msg__.
    Appbase.search('tweet', {text: $routeParams.text, properties: ['msg']}, function (error, array) {
      if (!error) {
        $scope.tweets = array;
        $scope.$apply();
      }
    });
  })
  // **Controller: Loading**.
  // It inits the __data__ factory, which is used everywhere in the app to fetch and set data from/to Appbase.
  // After the _init_ completes, it takes the user to _home_ screen, showing personal tweets of the user.
  .controller('loading', function ($rootScope, $scope, userSession, data) {
    "use strict";
    if (!userSession.getUser()) {
      $rootScope.exit();
      return;
    }
    data.init(function () {
      $scope.$apply(function () {
        $rootScope.goHome('personal');
      });
    });
  })
  // **Controller: navbar**.
  // Handles button clicks and visibility of buttons.
  .controller('navbar', function ($scope, userSession, $rootScope) {
    "use strict";
    $scope.bahar = true;
    // Called when user enters a text in the search box and presses enter key.
    $scope.search = function () {
      $rootScope.search($scope.searchText);
      $scope.searchText = '';
    };
    $scope.$on('showNav', function () {
      $scope.bahar = false;
    });
    $scope.$on('hideNav', function () {
      $scope.bahar = true;
    });
    $scope.exit = function () {
      $rootScope.exit();
    };
    $scope.gotoProfile = function (userId) {
      if (userId === undefined) { userId = userSession.getUser(); }
      $rootScope.gotoProfile(userId);
    };
    $scope.goHome = function (feed) {
      $rootScope.goHome(feed);
    };
  })
  // **Controller: home**.
  // This is what the user sees first when logged in. It shows the personal and global tweet feeds
  // The personal tweet feed: shows tweets from people he follows.
  // The global feed: tweets by everyone
  .controller('home', function ($scope, userSession, $rootScope, $appbaseRef, $routeParams, data) {
    "use strict";
    // Check if the session is properly initiated,
    // i.e. the 'data' factory set the flag 'initComplete' in userSession.
    if (!userSession.initComplete) {
      if (!userSession.getUser()) {
        $rootScope.exit();
      } else {
        $rootScope.load();
      }
      return;
    }
    $scope.convertToVisibleTime = $rootScope.convertToVisibleTime;
        $scope.urlify = $rootScope.urlify;
    $rootScope.showNav();

    // Get __feed__ from route parameters.
    var feed = $routeParams.feed === undefined ? 'global' : $routeParams.feed,
      usrRef = Appbase.ref('user/' + userSession.getUser() + '/following');
    $scope.tweetsDisplayed = 15;
    $scope.peopleDisplayed = 8;
    $scope.userName = userSession.getUser();
    $scope.gotoProfile = $rootScope.gotoProfile;
    // Show _People on Twitter_, user's _Followers_ and _Followings_.
    $appbaseRef(data.refs.allUsers).$bindEdges($scope,'people', false, false, {}, true);
    $appbaseRef(data.refs.usersFollowers).$bindEdges($scope, 'followers');
    $appbaseRef(data.refs.usersFollowing).$bindEdges($scope, 'following');

    // Called when user posts a new tweet.
    $scope.addTweet = function () {
      data.addTweet($scope.msg);
      $scope.msg = '';
    };
    if (feed === 'global') {
      // Show all tweets.
      $appbaseRef(data.refs.globalTweets).$bindEdges($scope,'tweets', false, false, {}, true);
    } else {
      // Fetch tweets of the people followed by the user. Every following's tweets are pushed into `arraysOfTweets` as an array,
      // and in the end, these arrays are merged into personalTweets by calling `personalTweets.concat.apply(personalTweets, arraysOfTweets)`
      // in _home.html_.
      $scope.personalTweets = [];
      $scope.arraysOfTweets = [];
      $scope.arraysOfTweets.push($appbaseRef('user/' + userSession.getUser() + '/tweets').$bindEdges($scope));
      usrRef.on('edge_added', function (error, followUserRef) {
        if (error) {throw error; }
        $scope.arraysOfTweets.push($appbaseRef(followUserRef).$outVertex('tweets').$bindEdges($scope));
      });
      $scope.$on('$destroy', function () {
        // Stop listening to user's followings when the view is destroyed.
        usrRef.off();
      });
    }
  })
  // **Controller: profile**.
  // Where a user's followings, followers and tweets are shown.
  // A user can also see other's profiles and choose to follow/unfollow the person from his/her profile.
  .controller('profile', function ($scope, userSession, $rootScope, $routeParams, $appbaseRef, data) {
    "use strict";
    if (!userSession.initComplete) {
      if (!userSession.getUser()) {
        $rootScope.exit();
      } else {
        $rootScope.load();
      }
      return;
    }
    $scope.convertToVisibleTime = $rootScope.convertToVisibleTime;
    $rootScope.showNav();

    // Get the userId from route params.
    var userId = $routeParams.userId;
    $scope.userId = $routeParams.userId;
    // Check whether this profile is of the logged in user.
    $scope.isMe = userSession.getUser() === userId;
    $scope.userName = $routeParams.userId;
    $scope.isReady = false;

    // Check whether this user is being followed by the logged in user.
    // This has to be an async function, as it interacts with the Appbase server.
    if (!$scope.isMe) {
      data.isUserBeingFollowed(userId, function (boolean) {
        // If true, _unfollow_ button will appear, otherwise _follow_ one.
        $scope.isBeingFollowed = boolean;
        // Show _follow_ or _unfollow_ buttons only when the data is arrived.
        $scope.isReady = true;
      });
    }
    $scope.gotoProfile = $rootScope.gotoProfile;
    $scope.follow = function (userId) {
      $scope.isBeingFollowed = true;
      data.follow(userId);
    };
    $scope.unFollow = function (userId) {
      $scope.isBeingFollowed = false;
      data.unFollow(userId);
    };
    $scope.addTweet = function () {
      data.addTweet($scope.msg);
      $scope.msg = '';
    };
    // Fetch user's followers, followings and tweets.
    $appbaseRef('user/' + userId + '/followers').$bindEdges($scope, 'followers');
    $appbaseRef('user/' + userId + '/following').$bindEdges($scope, 'following');
    $appbaseRef('user/' + userId + '/tweets').$bindEdges($scope, 'tweets');
  })
  // **Factory: data**.
  //Stores frequently useful Appbase references and interacts with Appbase for data needs
  .factory('data', function (userSession) {
    "use strict";
    // Appbase references
    var refs = {
      globalTweets: Appbase.ref('global/tweets'),
      allUsers: Appbase.ref('global/users')
    }, data = {  // Factory to be exported
      refs: refs
    };
    // Called when the user just logs in.
    // It sets required references and creates basic data for a new user.
    data.init = function (ready) {
      var userId = userSession.getUser();
      refs.user = Appbase.create('user', userSession.getUser());
      refs.usersTweets = refs.user.outVertex('tweets');
      refs.usersFollowers = refs.user.outVertex('followers');
      refs.usersFollowing = refs.user.outVertex('following');
      refs.user.on('properties', function (error, ref, snap) {
        refs.user.off();
        if (error) {throw error; }
        if (snap.properties().name === undefined) {
          // The user logged in for the first time.
          Appbase.ref('global/users').setEdge(refs.user, userId);
          // Set user's name
          refs.user.setData({
            name: userId
          });
          // Create vertices which will store user's followers, followings and tweets.
          refs.user.setEdge(Appbase.create('misc', Appbase.uuid()), 'tweets', function (error) {
            if (error) {throw error; }
            refs.user.setEdge(Appbase.create('misc', Appbase.uuid()), 'followers', function (error) {
              if (error) {throw error; }
              refs.user.setEdge(Appbase.create('misc', Appbase.uuid()), 'following', function (error) {
                if (error) {throw error; }
                //Set the flag true in userSession
                userSession.initComplete = true;
                ready();
              });
            });
          });
        } else {
          // The user exists in Appbase.
          userSession.initComplete = true;
          ready();
        }
      });
    };
    data.addTweet = function (msg) {
      //Create a new 'tweet' vertex and store the tweet message
      var tweetRef = Appbase.create('tweet', Appbase.uuid());
      tweetRef.setData({ 'msg': msg, 'by': userSession.getUser() }, function (error, tweetRef) {
        if (error) {throw error; }
        // Add this tweet as an edge, in user's own tweets and global tweets.
        // We really don't care about the edge's name here
        var randomEdgeName = Appbase.uuid();
        refs.usersTweets.setEdge(tweetRef, randomEdgeName);
        refs.globalTweets.setEdge(tweetRef, randomEdgeName);
      });
    };
    // Checks whether provided userId is being followed by the logged in user
    data.isUserBeingFollowed = function (userId, callback) {
      refs.usersFollowing.outVertex(userId).isValid(function (error, bool) {
        if (error) {throw error; }
        callback(bool);
      });
    };
    data.follow = function (userId) {
      refs.usersFollowing.setEdge(Appbase.ref('user/' + userId), userId);
      Appbase.ref('user/' + userId + '/followers').setEdge(refs.user, userSession.getUser());
    };
    data.unFollow = function (userId) {
      refs.usersFollowing.removeEdge(userId);
      Appbase.ref('user/' + userId + '/followers').removeEdge(userSession.getUser());
    };
    return data;
  })
  // Stores logged in user's id.
  .factory('userSession', function () {
    "use strict";
    var userSession = {};
    userSession.initComplete = false;
    userSession.setUser = function (userId) {
      localStorage.setItem("currentLoggedInUser", userId);
    };
    userSession.exit = function () {
      localStorage.removeItem("currentLoggedInUser");
    };
    userSession.getUser = function () {
      return localStorage.getItem("currentLoggedInUser");
    };
    return userSession;
  })
  .directive('whenScrolled', function() {
    return function(scope, elm, attr) {
      var raw = elm[0];
      elm.bind('scroll', function() {
        if (raw.scrollTop + raw.offsetHeight + 1 >= raw.scrollHeight) { // + 1 added, as a workaround for: (raw.scrollTop + raw.offsetHeight- raw.scrollHeight) would always stop at -1.
          scope.$apply(attr.whenScrolled);
        }
      });
    };
  });
<|endoftext|>


<commit_before>/* global TrelloPowerUp */
var Promise = TrelloPowerUp.Promise;
var t = TrelloPowerUp.iframe();

var gFormUrl = '';
var cardName = '';
var cardShortLink = '';
// var userName = t.arg('user');
// var userName = document.getElementsByClassName("js-member-name")[0].innerText;
var userName = $(".js-member-name").text();

// this function we be called once on initial load
// and then called each time something changes
t.render(function(){
  // t.card('members')
  // .get('members')
  // .filter(function(member){
  //   return member.email.indexOf('Alejandro Lizardo Celiz') == 0;
  // })
  // .then(function(members){
  //   console.log(members);
  //   userName = members.map(function(a){ return a.email; });
  //   console.log(userName);
  // })

  return Promise.all([
    t.get('board', 'shared', 'url'),
    t.card('name', 'url'),
    t.card('members').get('members')
  ])
  .spread(function(savedGFormUrl, cardData, members){
    if(savedGFormUrl){
      gFormUrl = savedGFormUrl;
    } else {
      document.getElementById('overlay-message')
      .textContent = 'Please add form url on settings';
    }
    if(cardData){
      cardName = cardData.name;
      cardUrl = cardData.url;
    }
    userName = $(".js-member-name").text();
    console.log($(".js-member-name").text());
    console.log(members);
    console.log(members[0].fullName);
    // members
    // .filter(function(member){
    //   return member.email.indexOf('Alejandro Lizardo Celiz') == 0;
    // })
    // .then(function(members){
    //   console.log(members);
    //   userName = members.map(function(a){ return a.email; });
    //   console.log(userName);
    // })
  })
  .then(function(){
    document.getElementsByTagName('iframe')[0].src = gFormUrl +
    "?embedded=true&entry.995291397=" + cardName +
    "&entry.33315152=" + userName +
    "&entry.1600294234=" + cardUrl;
  })

});

// close overlay if user clicks outside our content
document.addEventListener('click', function(e) {
  if(e.target.tagName == 'BODY') {
    t.closeOverlay().done();
  }
});

// close overlay if user presses escape key
document.addEventListener('keyup', function(e) {
  if(e.keyCode == 27) {
    t.closeOverlay().done();
  }
});
<commit_msg>Current User<commit_after>/* global TrelloPowerUp */
var Promise = TrelloPowerUp.Promise;
var t = TrelloPowerUp.iframe();

var gFormUrl = '';
var cardName = '';
var cardShortLink = '';
// var userName = t.arg('user');
// var userName = document.getElementsByClassName("js-member-name")[0].innerText;
var userName = $(".js-member-name").text();

// this function we be called once on initial load
// and then called each time something changes
t.render(function(){
  // t.card('members')
  // .get('members')
  // .filter(function(member){
  //   return member.email.indexOf('Alejandro Lizardo Celiz') == 0;
  // })
  // .then(function(members){
  //   console.log(members);
  //   userName = members.map(function(a){ return a.email; });
  //   console.log(userName);
  // })

  return Promise.all([
    t.get('board', 'shared', 'url'),
    t.card('name', 'url'),
    t.card('members').get('members')
  ])
  .spread(function(savedGFormUrl, cardData, members){
    if(savedGFormUrl){
      gFormUrl = savedGFormUrl;
    } else {
      document.getElementById('overlay-message')
      .textContent = 'Please add form url on settings';
    }
    if(cardData){
      cardName = cardData.name;
      cardUrl = cardData.url;
    }
    userName = $(".js-member-name", parent.document).text();
    console.log($(".js-member-name", parent.document).text());
    console.log(members);
    console.log(members[0].fullName);
    // members
    // .filter(function(member){
    //   return member.email.indexOf('Alejandro Lizardo Celiz') == 0;
    // })
    // .then(function(members){
    //   console.log(members);
    //   userName = members.map(function(a){ return a.email; });
    //   console.log(userName);
    // })
  })
  .then(function(){
    document.getElementsByTagName('iframe')[0].src = gFormUrl +
    "?embedded=true&entry.995291397=" + cardName +
    "&entry.33315152=" + userName +
    "&entry.1600294234=" + cardUrl;
  })

});

// close overlay if user clicks outside our content
document.addEventListener('click', function(e) {
  if(e.target.tagName == 'BODY') {
    t.closeOverlay().done();
  }
});

// close overlay if user presses escape key
document.addEventListener('keyup', function(e) {
  if(e.keyCode == 27) {
    t.closeOverlay().done();
  }
});
<|endoftext|>


<commit_before>// Avoid `console` errors in browsers that lack a console.
(function () {
    var method;
    var noop = function () {
    };
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());

// Place any jQuery/helper plugins in here.

//Performs a smooth page scroll to an anchor on the same page.
$(function () {
    $('a[href*="#"]:not([href="#"])').click(function () {
        if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) {
            var target = $(this.hash);
            target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
            if (target.length) {
                $('html, body').animate({
                    scrollTop: target.offset().top
                }, 1000);
                return false;
            }
        }
    });
});

// preloader script

$('body').waitForImages(function () {
    $('#f_page').removeClass('hide');
    $('#f_loader').addClass('hide');
});

// simple slider use if needed
//$(function () {
//    var pageSliderElements = $('.SLIDER_ELEMENTS_CLASS_HERE');
//    (function backgroundAnimation(index) {
//        pageSliderElements.addClass('nonOpaque');
//        pageSliderElements.removeClass('nonOpaque').eq(index).addClass('nonOpaque');
//        setTimeout(function () {
//            backgroundAnimation((index + 1) % pageSliderElements.length);
//        }, 6000);
//    }(0));
//});

// Mouse move animations
//$('#f_categories').mousemove(function (e) {
//    var x = (e.pageX * -1 / 25 + $(window).width() / 50);
//    $('.categories').css({'transform': 'translateX(' + x + 'px)', 'transition': 'transform 50ms ease'});
//}).mouseout(function () {
//    $(this).removeAttr("style");
//});

//timer function
function myTimer(elem, maxTime, timeStep) {
    var i = 0;
    test();
    function test() {
        setTimeout(function () {
            elem.text(i);
            i++;
            if (i < maxTime) {
                test();
            } else {
                console.log('end');
                return false;
            }
        }, timeStep);
    }
}

//character counter for any textarea
function charCounter(textAreaEl, counterEl, maxText) {
    $(counterEl).text(maxText);
    var remaining = maxText - $(textAreaEl).val().length;
    $(counterEl).text(remaining);
    $(textAreaEl).keyup(function () {
        remaining = maxText - $(textAreaEl).val().length;
        if ($(textAreaEl).val().length >= maxText) {
            $(this).val($(this).val().substr(0, maxText))
        }
        $(counterEl).text(remaining);
    });
}

/*page controller for one page websites*/
function pageController() {
    switch (true) {
        case (window.location.href.indexOf("about") > -1):

            break;
        case (window.location.href.indexOf("methodic") > -1):

            break;
        case (window.location.href.indexOf("parents") > -1):

            break;
        case (window.location.href.indexOf("training") > -1):

            break;
        case (window.location.href.indexOf("weekdays") > -1):

            break;
        case (window.location.href.indexOf("gallery") > -1):

            break;
        case (window.location.href.indexOf("contactUs") > -1):

            break;
        default:

            break;
    }
}

/*typing text animation plugin*/

function drawLetters(a) {
    var q = a.text().split('').length,
        l = a.text().split('');

    a.text('');
    myTimer();
    function myTimer() {
        var i = 0;
        test();
        function test() {
            setTimeout(function () {
                a.append('' + l[i] + '');
                i++;
                if (i < q) {
                    test();
                } else {
                    return false;
                }
                setTimeout(function () {
                    a.find('.flash').addClass('light');
                }, 200);
            }, 80);
        }

    }
}
<commit_msg>adds helper comment<commit_after>// Avoid `console` errors in browsers that lack a console.
(function () {
    var method;
    var noop = function () {
    };
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());

// Place any jQuery/helper plugins in here.

//Performs a smooth page scroll to an anchor on the same page.
$(function () {
    $('a[href*="#"]:not([href="#"])').click(function () {
        if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) {
            var target = $(this.hash);
            target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
            if (target.length) {
                $('html, body').animate({
                    scrollTop: target.offset().top
                }, 1000);
                return false;
            }
        }
    });
});

// preloader script

$('body').waitForImages(function () {
    $('#f_page').removeClass('hide');
    $('#f_loader').addClass('hide');
});

// simple slider use if needed
//$(function () {
//    var pageSliderElements = $('.SLIDER_ELEMENTS_CLASS_HERE');
//    (function backgroundAnimation(index) {
//        pageSliderElements.addClass('nonOpaque');
//        pageSliderElements.removeClass('nonOpaque').eq(index).addClass('nonOpaque');
//        setTimeout(function () {
//            backgroundAnimation((index + 1) % pageSliderElements.length);
//        }, 6000);
//    }(0));
//});

// Mouse move animations
//$('#f_categories').mousemove(function (e) {
//    var x = (e.pageX * -1 / 25 + $(window).width() / 50);
//    $('.categories').css({'transform': 'translateX(' + x + 'px)', 'transition': 'transform 50ms ease'});
//}).mouseout(function () {
//    $(this).removeAttr("style");
//});

//timer function
function myTimer(elem, maxTime, timeStep) {
    var i = 0;
    test();
    function test() {
        setTimeout(function () {
            elem.text(i);
            i++;
            if (i < maxTime) {
                test();
            } else {
                console.log('end');
                return false;
            }
        }, timeStep);
    }
}

//character counter for any textarea
function charCounter(textAreaEl, counterEl, maxText) {
    $(counterEl).text(maxText);
    var remaining = maxText - $(textAreaEl).val().length;
    $(counterEl).text(remaining);
    $(textAreaEl).keyup(function () {
        remaining = maxText - $(textAreaEl).val().length;
        if ($(textAreaEl).val().length >= maxText) {
            $(this).val($(this).val().substr(0, maxText))
        }
        $(counterEl).text(remaining);
    });
}

/*page controller for one page websites*/
function pageController() {
    switch (true) {
        case (window.location.href.indexOf("about") > -1):

            break;
        case (window.location.href.indexOf("methodic") > -1):

            break;
        case (window.location.href.indexOf("parents") > -1):

            break;
        case (window.location.href.indexOf("training") > -1):

            break;
        case (window.location.href.indexOf("weekdays") > -1):

            break;
        case (window.location.href.indexOf("gallery") > -1):

            break;
        case (window.location.href.indexOf("contactUs") > -1):

            break;
        default:

            break;
    }
}

/*typing text animation plugin*/

function drawLetters(a) {
    var q = a.text().split('').length,
        l = a.text().split('');

    a.text('');
    myTimer();
    function myTimer() {
        var i = 0;
        test();
        function test() {
            setTimeout(function () {
                a.append('' + l[i] + '');
                i++;
                if (i < q) {
                    test();
                } else {
                    return false;
                }
                setTimeout(function () {
                    a.find('.flash').addClass('light');
                }, 200);
            }, 80);
        }

    }
}

//for form validation use https://github.com/jzaefferer/jquery-validation
<|endoftext|>


<commit_before>---
# Do not remove `---` tags. These are the frontmatter tags for Jekyll variables.
---
/**
 * This script contains helper functions for the agreement checkboxes on `Getting Help` page.
 *
 * Please see `/getting-help/service-section.html` for usage.
 */

'use strict';

$(
    function () {
        const $privacyConsent = $('#privacyConsent');
        const $supportAgreementConsent = $('#supportAgreementConsent');
        const $orderButton = $('#order-now-btn');
        const $redirectScreen = $('#redirectScreen');
        const $loader = $redirectScreen.find('.redirect-loader');
        const $errorContainer = $redirectScreen.find('.redirect-error');
        const $linkBack = $redirectScreen.find('#linkBack');
        const $consentCheckboxes = $("input[type='checkbox'].consent");

        const orderUrl = "{{site.data.payment_config.orderUrl}}";

        let apiUrl;
        if ("{{jekyll.environment}}" === "development") {
            apiUrl = "{{site.data.payment_config.devApiUrl}}";
        } else {
            apiUrl = "{{site.data.payment_config.prodApiUrl}}";
        }

        $consentCheckboxes.change(() => {
            changeElementState($orderButton, isConsentObtained());
        });

        $orderButton.click(() => {
            if (isConsentObtained()) {
                submitOrder();
            }
        });

        $linkBack.click(e => {
            e.preventDefault();
            hideRedirect();
        });

        /**
         * Checks if all consent checkboxes are checked.
         *
         * @return {boolean} true if all checkboxes are checked
         */
        function isConsentObtained () {
            return $consentCheckboxes.length == $consentCheckboxes.filter(":checked").length;
        }

        /**
         * Changes element disabled/enabled state.
         *
         * @param {jQuery} element the element, which state will be changed
         * @param {boolean} enabled if state is `true` the element will be enabled, otherwise it
         * will be disabled
         */
        function changeElementState(element, enabled) {
            if (enabled) {
                element.removeAttr('disabled');
                element.removeClass('disabled');
            } else {
                element.attr('disabled', true);
                element.addClass('disabled');
            }
        }

        /**
         * Submit order handler.
         */
        function submitOrder() {
            const privacyConsent = $privacyConsent.prop("checked");
            const supportAgreementConsent = $supportAgreementConsent.prop("checked");
            const data = JSON.stringify({privacyConsent, supportAgreementConsent});
            const transactionUrl = `${apiUrl}/transaction`;
            sendPaymentTransaction(transactionUrl, data);
        }

        /**
         * The user's consent.
         *
         *
Contains user's consents for services and data processing flows.
         *
         * @typedef {Object} Consent
         * @property {boolean} privacyConsent indicates whether the user give a consent to
         * process his personal information
         * @property {boolean} supportAgreementConsent indicates whether the user agree to be bound by the
         * terms of Development Support Agreement
         */

        /**
         * Generates the payment processing transaction.
         *
         *
Sends the transaction data and returns the transaction ID. If the request is successful,
         * redirects to the Payment screen.
         *
         * @param {string} transactionUrl the transaction API URL
         * @param {Consent} data the Consent transaction data
         */
        function sendPaymentTransaction(transactionUrl, data) {
            showRedirect();
            $.ajax(transactionUrl, {
                type: 'POST',
                data: data,
                contentType: 'application/json',
                success: (data) => {
                    const obj = JSON.parse(data);
                    const paymentUrl = `${orderUrl}&CUSTOMERID=${obj.id}`;
                    window.location = paymentUrl;
                    hideRedirect();
                },
                error: (jqXhr) => {
                    console.error(jqXhr.status + ': ' + jqXhr.statusText);
                    showErrorMessage();
                }
            });
        }

        /**
         * Shows the redirect screen.
         */
        function showRedirect() {
            initRedirectScreenState();
            $redirectScreen.show();
        }

        /**
         * Hides the loader and shows the error message.
         */
        function showErrorMessage() {
            $loader.hide();
            $errorContainer.show();
        }

        /**
         *  Hides the redirect screen.
         */
        function hideRedirect() {
            $redirectScreen.hide();
        }

        /**
         *  Inits the redirect screen.
         */
        function initRedirectScreenState() {
            $errorContainer.hide();
            $loader.show();
        }
    }
);
<commit_msg>Add copyright<commit_after>---
# Do not remove `---` tags. These are the frontmatter tags for Jekyll variables.
---

/*
 * Copyright 2020, TeamDev. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * This script contains helper functions for the agreement checkboxes on `Getting Help` page.
 *
 * Please see `/getting-help/service-section.html` for usage.
 */

'use strict';

$(
    function () {
        const $privacyConsent = $('#privacyConsent');
        const $supportAgreementConsent = $('#supportAgreementConsent');
        const $orderButton = $('#order-now-btn');
        const $redirectScreen = $('#redirectScreen');
        const $loader = $redirectScreen.find('.redirect-loader');
        const $errorContainer = $redirectScreen.find('.redirect-error');
        const $linkBack = $redirectScreen.find('#linkBack');
        const $consentCheckboxes = $("input[type='checkbox'].consent");

        const orderUrl = "{{site.data.payment_config.orderUrl}}";

        let apiUrl;
        if ("{{jekyll.environment}}" === "development") {
            apiUrl = "{{site.data.payment_config.devApiUrl}}";
        } else {
            apiUrl = "{{site.data.payment_config.prodApiUrl}}";
        }

        $consentCheckboxes.change(() => {
            changeElementState($orderButton, isConsentObtained());
        });

        $orderButton.click(() => {
            if (isConsentObtained()) {
                submitOrder();
            }
        });

        $linkBack.click(e => {
            e.preventDefault();
            hideRedirect();
        });

        /**
         * Checks if all consent checkboxes are checked.
         *
         * @return {boolean} true if all checkboxes are checked
         */
        function isConsentObtained () {
            return $consentCheckboxes.length == $consentCheckboxes.filter(":checked").length;
        }

        /**
         * Changes element disabled/enabled state.
         *
         * @param {jQuery} element the element, which state will be changed
         * @param {boolean} enabled if state is `true` the element will be enabled, otherwise it
         * will be disabled
         */
        function changeElementState(element, enabled) {
            if (enabled) {
                element.removeAttr('disabled');
                element.removeClass('disabled');
            } else {
                element.attr('disabled', true);
                element.addClass('disabled');
            }
        }

        /**
         * Submit order handler.
         */
        function submitOrder() {
            const privacyConsent = $privacyConsent.prop("checked");
            const supportAgreementConsent = $supportAgreementConsent.prop("checked");
            const data = JSON.stringify({privacyConsent, supportAgreementConsent});
            const transactionUrl = `${apiUrl}/transaction`;
            sendPaymentTransaction(transactionUrl, data);
        }

        /**
         * The user's consent.
         *
         *
Contains user's consents for services and data processing flows.
         *
         * @typedef {Object} Consent
         * @property {boolean} privacyConsent indicates whether the user give a consent to
         * process his personal information
         * @property {boolean} supportAgreementConsent indicates whether the user agree to be bound by the
         * terms of Development Support Agreement
         */

        /**
         * Generates the payment processing transaction.
         *
         *
Sends the transaction data and returns the transaction ID. If the request is successful,
         * redirects to the Payment screen.
         *
         * @param {string} transactionUrl the transaction API URL
         * @param {Consent} data the Consent transaction data
         */
        function sendPaymentTransaction(transactionUrl, data) {
            showRedirect();
            $.ajax(transactionUrl, {
                type: 'POST',
                data: data,
                contentType: 'application/json',
                success: (data) => {
                    const obj = JSON.parse(data);
                    const paymentUrl = `${orderUrl}&CUSTOMERID=${obj.id}`;
                    window.location = paymentUrl;
                    hideRedirect();
                },
                error: (jqXhr) => {
                    console.error(jqXhr.status + ': ' + jqXhr.statusText);
                    showErrorMessage();
                }
            });
        }

        /**
         * Shows the redirect screen.
         */
        function showRedirect() {
            initRedirectScreenState();
            $redirectScreen.show();
        }

        /**
         * Hides the loader and shows the error message.
         */
        function showErrorMessage() {
            $loader.hide();
            $errorContainer.show();
        }

        /**
         *  Hides the redirect screen.
         */
        function hideRedirect() {
            $redirectScreen.hide();
        }

        /**
         *  Inits the redirect screen.
         */
        function initRedirectScreenState() {
            $errorContainer.hide();
            $loader.show();
        }
    }
);
<|endoftext|>