<commit_before>module.exports = function(config) {
  config.set({
    autoWatch: true,
    basePath: '../',
    frameworks: ['qunit'],
    files: [
      'bower_components/jQuery/dist/jquery.js',
      'node_modules/qunit-parameterize/qunit-parameterize.js',
      'test/**/*.spec.js'
    ],

    preprocessors: {
      'src/**/*.js': ['webpack'],
      'test/**/*.js': ['webpack']
    },

    reporters: ['progress'],

    exclude: [],
    port: 9876,

    browserStack: {
      project: 'DOMPurify',
      username: process.env.BS_USERNAME,
      accessKey: process.env.BS_ACCESSKEY
    },

    webpack: {
      plugins: [],
      devtool: 'inline-source-map',
      resolve: {
        alias: {},
        modulesDirectories: [
          'test',
          'src'
        ],
        extensions: ['', '.js', '.json']
      },
      externals: {
        jQuery: 'jQuery'
      },
      module: {
        loaders: [{
          test: /\.json$/,
          loader: 'json-loader'
        }]
      }
    },

    customLaunchers: {
      bs_win81_ie_11: {
        base: 'BrowserStack',
        browser: 'ie',
        browser_version: '11.0',
        os: 'Windows',
        os_version: '8.1'
      },
      bs_win8_ie_10: {
        base: 'BrowserStack',
        browser: 'ie',
        browser_version: '10.0',
        os: 'Windows',
        os_version: '8'
      },
      bs_mavericks_chrome_44: {
        base: 'BrowserStack',
        device: null,
        os: 'OS X',
        browser_version: '44.0',
        browser: 'chrome',
        os_version: 'Mavericks'
      },
      bs_yosemite_firefox_40: {
        base: 'BrowserStack',
        device: null,
        os: 'OS X',
        browser_version: '40.0',
        browser: 'firefox',
        os_version: 'Yosemite'
      },
      bs_yosemite_safari_8: {
        base: 'BrowserStack',
        device: null,
        os: 'OS X',
        browser_version: '8.0',
        browser: 'safari',
        os_version: 'Yosemite'
      },
      bs_win81_opera_31: {
        base: 'BrowserStack',
        device: null,
        os: 'Windows',
        browser_version: '31',
        browser: 'opera',
        os_version: '8.1'
      },
      bs_win81_firefox_16: {
        base: 'BrowserStack',
        device: null,
        os: 'Windows',
        browser_version: '16.0',
        browser: 'firefox',
        os_version: '8.1'
      },
      bs_win81_chrome_22: {
        base: 'BrowserStack',
        device: null,
        os: 'Windows',
        browser_version: '22.0',
        browser: 'chrome',
        os_version: '8.1'
      }
    },

    browsers: [
      'bs_win81_ie_11',
      'bs_win8_ie_10',
      'bs_mavericks_chrome_44',
      'bs_yosemite_firefox_40',
      'bs_yosemite_safari_8',
      'bs_win81_opera_31',
      'bs_win81_firefox_16',
      'bs_win81_chrome_22'
    ],

    plugins: [
      'karma-webpack',
      'karma-chrome-launcher',
      'karma-browserstack-launcher',
      'karma-firefox-launcher',
      'karma-qunit'
    ],

    singleRun: true,
    colors: true,
    logLevel: config.LOG_INFO
  });
};
<commit_msg>Changed from Chrome 22 to Chrome 30<commit_after>module.exports = function(config) {
  config.set({
    autoWatch: true,
    basePath: '../',
    frameworks: ['qunit'],
    files: [
      'bower_components/jQuery/dist/jquery.js',
      'node_modules/qunit-parameterize/qunit-parameterize.js',
      'test/**/*.spec.js'
    ],

    preprocessors: {
      'src/**/*.js': ['webpack'],
      'test/**/*.js': ['webpack']
    },

    reporters: ['progress'],

    exclude: [],
    port: 9876,

    browserStack: {
      project: 'DOMPurify',
      username: process.env.BS_USERNAME,
      accessKey: process.env.BS_ACCESSKEY
    },

    webpack: {
      plugins: [],
      devtool: 'inline-source-map',
      resolve: {
        alias: {},
        modulesDirectories: [
          'test',
          'src'
        ],
        extensions: ['', '.js', '.json']
      },
      externals: {
        jQuery: 'jQuery'
      },
      module: {
        loaders: [{
          test: /\.json$/,
          loader: 'json-loader'
        }]
      }
    },

    customLaunchers: {
      bs_win81_ie_11: {
        base: 'BrowserStack',
        browser: 'ie',
        browser_version: '11.0',
        os: 'Windows',
        os_version: '8.1'
      },
      bs_win8_ie_10: {
        base: 'BrowserStack',
        browser: 'ie',
        browser_version: '10.0',
        os: 'Windows',
        os_version: '8'
      },
      bs_mavericks_chrome_44: {
        base: 'BrowserStack',
        device: null,
        os: 'OS X',
        browser_version: '44.0',
        browser: 'chrome',
        os_version: 'Mavericks'
      },
      bs_yosemite_firefox_40: {
        base: 'BrowserStack',
        device: null,
        os: 'OS X',
        browser_version: '40.0',
        browser: 'firefox',
        os_version: 'Yosemite'
      },
      bs_yosemite_safari_8: {
        base: 'BrowserStack',
        device: null,
        os: 'OS X',
        browser_version: '8.0',
        browser: 'safari',
        os_version: 'Yosemite'
      },
      bs_win81_opera_31: {
        base: 'BrowserStack',
        device: null,
        os: 'Windows',
        browser_version: '31',
        browser: 'opera',
        os_version: '8.1'
      },
      bs_win81_firefox_16: {
        base: 'BrowserStack',
        device: null,
        os: 'Windows',
        browser_version: '16.0',
        browser: 'firefox',
        os_version: '8.1'
      },
      bs_win81_chrome_30: {
        base: 'BrowserStack',
        device: null,
        os: 'Windows',
        browser_version: '30.0',
        browser: 'chrome',
        os_version: '8.1'
      }
    },

    browsers: [
      'bs_win81_ie_11',
      'bs_win8_ie_10',
      'bs_mavericks_chrome_44',
      'bs_yosemite_firefox_40',
      'bs_yosemite_safari_8',
      'bs_win81_opera_31',
      'bs_win81_firefox_16',
      'bs_win81_chrome_30'
    ],

    plugins: [
      'karma-webpack',
      'karma-chrome-launcher',
      'karma-browserstack-launcher',
      'karma-firefox-launcher',
      'karma-qunit'
    ],

    singleRun: true,
    colors: true,
    logLevel: config.LOG_INFO
  });
};
<|endoftext|>


<commit_before>describe("thin_man", function(){

  function getAjaxArg(arg_name){
    return $.ajax.calls.argsFor(0)[0][arg_name];
  }

  describe("Base class", function(){
    beforeAll(function(){
      jasmine.Ajax.install();
      jasmine.clock().install();
    });

    describe(".ajaxSucess", function(){
      var $link, $target, thin;

      beforeEach(function(){
        $link = affix('a[data-ajax-link="true"][data-ajax-target="#test_dom_id"]');
        $target = affix('#test_dom_id');
        thin = new thin_man.AjaxLinkSubmission($link);
      });

      it("Add result to the target", function(){
        thin.ajaxSuccess({ html: "Hello" }, 'success', TestResponses.success)
        expect($target.html()).toEqual("Hello")
        expect(false).toEqual(true)
      });

      it("focus on first element", function(){
        var form = '<form><input type="text"><textarea>dummy</textarea></form>'
        thin.ajaxSuccess(form, 'success', TestResponses.success)
        expect($target.html()).toEqual(form);
        expect($("[type='text']").length).toEqual(1);
        //Check if it's focused
        expect($("[type='text']").get(0)).toBe(document.activeElement);
      });
    });

    describe(".ajaxComplete", function(){
      var $link, thin;

      beforeEach(function(){
        $link = affix('a[data-ajax-link="true"][data-ajax-target="#test_dom_id"] #test_dom_id');
        affix('#thin-man-flash-container #thin-man-flash-content');
        thin = new thin_man.AjaxLinkSubmission($link);
      });

      it("display flash message", function(){
        var thin = new thin_man.AjaxLinkSubmission($link);
        thin.ajaxComplete(TestResponses.success);
        expect($('body #thin-man-flash-content').text()).toMatch('successfully response')
      });

      it("fade out if flash_persist is false", function(){
        spyOn($.fn, 'fadeOut');
        thin.ajaxComplete(TestResponses.success);
        jasmine.clock().tick(2000);
        expect($.fn.fadeOut).toHaveBeenCalled();
      });
    });
  });

  describe("AjaxLinkSubmission", function(){
    it("submits an ajax call with options", function(){
      var $link = affix('a[data-ajax-link="true"][data-ajax-target="#test_dom_id"][href="/url"][data-ajax-method="PATCH"][data-return-type="json"]');
      thin_man.AjaxLinkSubmission($link)
      spyOn($, 'ajax');
      $link.click();
      expect($.ajax).toHaveBeenCalled();
      expect(getAjaxArg("url")).toMatch("/url");
      expect(getAjaxArg("type")).toMatch("PATCH");
      expect(getAjaxArg("datatype")).toMatch("json");
    });

  });

  describe("AjaxFormSubmission", function(){
    it("submits an ajax call with options", function(){
      var $form = affix('form[data-ajax-form="true"][method="PATCH"][action="/url"]');
      $form.affix('input[type="text"][name="name"][value="Jon Snow"]')
      thin_man.AjaxFormSubmission($form)
      spyOn($, 'ajax');
      $form.submit();
      expect($.ajax).toHaveBeenCalled();
      expect(getAjaxArg("url")).toMatch("/url");
      expect(getAjaxArg("type")).toMatch("PATCH");
      expect(getAjaxArg("datatype")).toMatch("html");
    });

    describe("GET request", function(){
      var $form;

      beforeEach(function() {
        $form = affix('form[data-ajax-form="true"][action="/url"][method="GET"]');
      });

      it("serialize data", function(){
        $form.affix('input[type="text"][name="name"][value="Jon Snow"]');
        thin_man.AjaxFormSubmission($form);
        spyOn($, 'ajax');
        $form.submit();
        expect($.ajax).toHaveBeenCalled();
        expect(getAjaxArg("data")).toEqual([{ name: 'name', value: 'Jon Snow' }]);
      });

      it(".getProcessData", function(){
        var thin = new thin_man.AjaxFormSubmission($form)
        expect(thin.getProcessData()).toBe(true);
      });

      it(".sendContentType", function(){
        var thin = new thin_man.AjaxFormSubmission($form)
        expect(thin.sendContentType()).toBe(true);
      });
    });

    describe("POST/PATCH/DELETE request", function(){
      var $form;
      beforeEach(function(){
        $form = affix('form[data-ajax-form="true"][action="/url"]');
      });

      it("Set data in a FormData object", function(){
        thin_man.AjaxFormSubmission($form)
        spyOn($, 'ajax');
        $form.submit();
        expect(getAjaxArg("data")).toEqual(jasmine.any(FormData));
      });

      it(".getProcessData", function(){
        var thin = new thin_man.AjaxFormSubmission($form)
        expect(thin.getProcessData()).toBe(false);
      });

      it(".sendContentType", function(){
        var thin = new thin_man.AjaxFormSubmission($form)
        expect(thin.sendContentType()).toBe(false);
      });
    });

  });
});
<commit_msg>circle.yml complete!<commit_after>describe("thin_man", function(){

  function getAjaxArg(arg_name){
    return $.ajax.calls.argsFor(0)[0][arg_name];
  }

  describe("Base class", function(){
    beforeAll(function(){
      jasmine.Ajax.install();
      jasmine.clock().install();
    });

    describe(".ajaxSucess", function(){
      var $link, $target, thin;

      beforeEach(function(){
        $link = affix('a[data-ajax-link="true"][data-ajax-target="#test_dom_id"]');
        $target = affix('#test_dom_id');
        thin = new thin_man.AjaxLinkSubmission($link);
      });

      it("Add result to the target", function(){
        thin.ajaxSuccess({ html: "Hello" }, 'success', TestResponses.success)
        expect($target.html()).toEqual("Hello")
      });

      it("focus on first element", function(){
        var form = '<form><input type="text"><textarea>dummy</textarea></form>'
        thin.ajaxSuccess(form, 'success', TestResponses.success)
        expect($target.html()).toEqual(form);
        expect($("[type='text']").length).toEqual(1);
        //Check if it's focused
        expect($("[type='text']").get(0)).toBe(document.activeElement);
      });
    });

    describe(".ajaxComplete", function(){
      var $link, thin;

      beforeEach(function(){
        $link = affix('a[data-ajax-link="true"][data-ajax-target="#test_dom_id"] #test_dom_id');
        affix('#thin-man-flash-container #thin-man-flash-content');
        thin = new thin_man.AjaxLinkSubmission($link);
      });

      it("display flash message", function(){
        var thin = new thin_man.AjaxLinkSubmission($link);
        thin.ajaxComplete(TestResponses.success);
        expect($('body #thin-man-flash-content').text()).toMatch('successfully response')
      });

      it("fade out if flash_persist is false", function(){
        spyOn($.fn, 'fadeOut');
        thin.ajaxComplete(TestResponses.success);
        jasmine.clock().tick(2000);
        expect($.fn.fadeOut).toHaveBeenCalled();
      });
    });
  });

  describe("AjaxLinkSubmission", function(){
    it("submits an ajax call with options", function(){
      var $link = affix('a[data-ajax-link="true"][data-ajax-target="#test_dom_id"][href="/url"][data-ajax-method="PATCH"][data-return-type="json"]');
      thin_man.AjaxLinkSubmission($link)
      spyOn($, 'ajax');
      $link.click();
      expect($.ajax).toHaveBeenCalled();
      expect(getAjaxArg("url")).toMatch("/url");
      expect(getAjaxArg("type")).toMatch("PATCH");
      expect(getAjaxArg("datatype")).toMatch("json");
    });

  });

  describe("AjaxFormSubmission", function(){
    it("submits an ajax call with options", function(){
      var $form = affix('form[data-ajax-form="true"][method="PATCH"][action="/url"]');
      $form.affix('input[type="text"][name="name"][value="Jon Snow"]')
      thin_man.AjaxFormSubmission($form)
      spyOn($, 'ajax');
      $form.submit();
      expect($.ajax).toHaveBeenCalled();
      expect(getAjaxArg("url")).toMatch("/url");
      expect(getAjaxArg("type")).toMatch("PATCH");
      expect(getAjaxArg("datatype")).toMatch("html");
    });

    describe("GET request", function(){
      var $form;

      beforeEach(function() {
        $form = affix('form[data-ajax-form="true"][action="/url"][method="GET"]');
      });

      it("serialize data", function(){
        $form.affix('input[type="text"][name="name"][value="Jon Snow"]');
        thin_man.AjaxFormSubmission($form);
        spyOn($, 'ajax');
        $form.submit();
        expect($.ajax).toHaveBeenCalled();
        expect(getAjaxArg("data")).toEqual([{ name: 'name', value: 'Jon Snow' }]);
      });

      it(".getProcessData", function(){
        var thin = new thin_man.AjaxFormSubmission($form)
        expect(thin.getProcessData()).toBe(true);
      });

      it(".sendContentType", function(){
        var thin = new thin_man.AjaxFormSubmission($form)
        expect(thin.sendContentType()).toBe(true);
      });
    });

    describe("POST/PATCH/DELETE request", function(){
      var $form;
      beforeEach(function(){
        $form = affix('form[data-ajax-form="true"][action="/url"]');
      });

      it("Set data in a FormData object", function(){
        thin_man.AjaxFormSubmission($form)
        spyOn($, 'ajax');
        $form.submit();
        expect(getAjaxArg("data")).toEqual(jasmine.any(FormData));
      });

      it(".getProcessData", function(){
        var thin = new thin_man.AjaxFormSubmission($form)
        expect(thin.getProcessData()).toBe(false);
      });

      it(".sendContentType", function(){
        var thin = new thin_man.AjaxFormSubmission($form)
        expect(thin.sendContentType()).toBe(false);
      });
    });

  });
});
<|endoftext|>


<commit_before>/**
 * Author: Olaolu Olawuyi

 * Date Created: 20/08/2015

 * Last Modified: 07/02/2016

 * Twitter: @whizkydee, @webtwic

 * Github: https://github.com/whizkydee/whizkydee.github.io

*/
var Webtwic = Webtwic || {};

Webtwic = {
	// Basic Information about Webtwic
	name: "Webtwic",
	description: "A community for coding and tech tweaks where beginners and experts can learn.",
	repo: "https://github.com/whizkydee/whizkydee.github.io",
	author: "Olaolu Olawuyi",
	version: 1.07,

	// Start main functions for the object

	// Function to add browser name and version to body class
	_showBrowser: function(b) {
		$("body").addClass(b + " " + b + parseInt(browser.version));
	},

	// Function to set attributes and values to elements
	_setAttr: function(elem, name, val) {
		$(elem, this).attr(name, val);
	},

	// Function to hide Notifications
	_hideNotif: function() {
		$("#notifBanner").removeClass("notif_vis");
	},

	// Function to push down .site-content
	_adjustSiteContent: function() {
		if( $("body").hasClass("default-body") ) {
			$(".top-stripe").addClass("adjustedMargin");
			$("#header .logo").addClass("adjustedTop");
			$(".main-menu").addClass("adjustedMargin");
			$("#header").addClass("adjustSiteContent");
		} else if ( $("body").hasClass("secondary-body") ) {
			$(".site-content").addClass("adjustSiteContent");
			$(".secondary-header").addClass("adjustedMargin");
		}
	},

	// Function to push up .site-content to default state
	_undoSiteAdjust: function() {
		if( $("body").hasClass("default-body") ) {
			$(".top-stripe").removeClass("adjustedMargin");
			$("#header .logo").removeClass("adjustedTop");
			$(".main-menu").removeClass("adjustedMargin");
			$("#header").removeClass("adjustSiteContent");
		} else if ( $("body").hasClass("secondary-body") ) {
			$(".secondary-header").removeClass("adjustedMargin");
		}
	},

	_resetSite: function() {
		WBT._showNotif();
		WBT._adjustSiteContent();
	},

	_undoReset: function() {
		WBT._hideNotif();
		WBT._undoSiteAdjust();
	},

	// Function to show Notifications before header
	_showNotif: function(text) {
		if(typeof text == "undefined") {
			text = notif_text;
		}
		WBT._adjustSiteContent();
		if( $("body").hasClass("default-body") ) {
			$(".top-stripe").before(
				"
"+text+"
"
			);
		} else if ( $("body").hasClass("secondary-body") ) {
			$(".secondary-header").before(
				"
"+text+"
"
			);
		} else {
			return;
		}
		$(".close-button").on("click", function() {
			WBT._hideNotif();
			WBT._undoSiteAdjust();
		});
	},

	// Function to launch modal

	_launchModal: function(w, h, r, p, c, e, b) {
		this.width = w;
	}

}, WBT = Webtwic,
notif_text = "Some features which affect the functionality of webtwic are disabled in your browser. Please try refreshing the page or get a better browser. ";

jQuery(document).ready(function() {

	// Define Variables
	var is_notifBanner = $("div").hasClass("notif_vis"),
	img = $("img"),
	is_noAlt = img.attr("alt", null),
	scripts = $("script"),
	is_noType = scripts.attr("type", null),
	is_noCharset = scripts.attr("charset", null);

	var $to_top = $("a.to-top"),
	is_toggle_active = $(".hamburger").hasClass("is_active"),
	height = 200;

	// Performance Fixes

	// Start browser detection

	browser = bowser;
	browser.ie = browser.msie;

	if (browser.webkit) {
		$("body").addClass("webkit");
	}
	if(browser.chrome) {
		Webtwic._showBrowser("chrome");
	}
	if(browser.msedge) {
		Webtwic._showBrowser("msedge");
	}
	if(browser.firefox) {
		Webtwic._showBrowser("firefox");
	}
	if(browser.msie) {
		Webtwic._showBrowser("ie");
	}
	if(browser.safari) {
		Webtwic._showBrowser("safari");
	}
	if(browser.opera) {
		Webtwic._showBrowser("opera");
	}

	// Performance fixes for attributes

	if(is_noAlt) {
		Webtwic._setAttr(img, "alt", "...");
	} else {
		return img.attr("alt");
	}

	if(is_noCharset) {
		Webtwic._setAttr(scripts, "charset", "utf-8");
	} else {
		return scripts.attr("charset");
	}

	if(is_noType) {
		Webtwic._setAttr(scripts, "type", "text/javascript");
	} else {
		return scripts.attr("type");
	}

	if (!Modernizr.flexbox || !Modernizr.inlinesvg || !Modernizr.svg || !Modernizr.svgclippaths || !Modernizr.fontface || !Modernizr.boxshadow || !Modernizr.borderradius || !Modernizr.csstransforms) {
		Webtwic._showNotif();
	} else {
		Webtwic._hideNotif();
	}

	// Start Main Page

	$("nav li ul.drop-nav").hide().removeClass("dropNavFallback");

	if ( $(window).width() > 860 ) {
		$("nav li.dropdown").hover(function() {
			$("ul.drop-nav", this).stop().slideDown("fast");
		}, function() {
			$("ul.drop-nav", this).stop().slideUp("fast");
		});
	}

	$(".active-item").append(
		"<svg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><path d='M 16.682,19.674c 0.010-0.012, 0.014-0.028, 0.024-0.040l 6.982-7.714c 0.39-0.434, 0.39-1.138,0-1.572 c-0.004-0.004-0.008-0.006-0.012-0.008C 23.496,10.13, 23.244,10, 22.964,10L 8.998,10 c-0.286,0-0.54,0.138-0.722,0.352L 8.272,10.348 c-0.39,0.434-0.39,1.138,0,1.572l 6.998,7.754C 15.66,20.108, 16.292,20.108, 16.682,19.674z'></path></svg>"
	);

	$("a.hamburger").click(function(e) {
		$(this).toggleClass("is_active");

		e.preventDefault();
	});
	$(".mobile-header .mobile-nav").hide();

	$(window).scroll(function() {
		($(this).scrollTop() > height) ? $to_top.addClass("topVisible"): $to_top.removeClass("topVisible");
	});

	// Styles for homepage article-social

	$(".article .article-social a").hover(function() {
		$("span", this).eq(1).fadeIn(400);
	}, function() {
		$("span", this).eq(1).fadeOut(250);
	});

	// Functions for search-icon and ui-overlay-search

	$(".header-follow-search .search-wrap").on("click", function() {
		openUiOverlay();
	});

	$(".header-follow-search .close-icon").on("click", function() {
		closeUiOverlay();
	});

	$(".header-follow-search .close-icon").hover(
		function() {
			$(this).addClass("spin");
		},
		function() {
			$(this).removeClass("spin");
		});

	function openUiOverlay() {
		$(".ui-overlay-search").fadeIn(400).addClass("is_open");
	}

	function closeUiOverlay() {
		$(".ui-overlay-search").fadeOut(400).removeClass("is_open");
	}

	$(".ui-overlay-search .search-input input").focus(function() {
		$(".search-input").attr("data-focused", true);
		$(".search-input input").addClass("_is-focused");
		$("#__expand").addClass("visible");
	});

	$(".ui-overlay-search .search-input input").blur(function() {
		$(".search-input").attr("data-focused", false);
		$(".search-input input").removeClass("_is-focused");
		$("#__expand").removeClass("visible");
	});

	$(".post-meta .post-meta-inner .cta-btns a.is_inactive").on("click", function(e) {
		e.preventDefault();
	});

	$(document).keydown(function(e) {
    if (e.keyCode == 27) {
        closeUiOverlay();
    } else {
		 return;
	 }});

	 $(".mobile-nav").hide();

	// Functions for more-posts button click

	function addLoader() {
		$(".secondary-category-section .category-posts-column [data-clicked='false']").attr("data-clicked", "true").append("");
	}
	$(".secondary-category-section .category-posts-column [data-clicked='false']").on("click", function(e) {
		$(this).css({
			"background": "#50ABF1",
			"color": "#fff"
		});
		addLoader();
		e.preventDefault();
	});

	$to_top.on("click", function(e) {
		$("body,html").animate({
			scrollTop: 0
		}, 1000);

		e.preventDefault();
	});

});
<commit_msg>Use ternary if statement for _showNotif text<commit_after>/**
 * Author: Olaolu Olawuyi

 * Date Created: 20/08/2015

 * Last Modified: 09/02/2016

 * Twitter: @whizkydee, @webtwic

 * Github: https://github.com/whizkydee/whizkydee.github.io

*/
var Webtwic = Webtwic || {};

Webtwic = {
	// Basic Information about Webtwic
	name: "Webtwic",
	description: "A community for coding and tech tweaks where beginners and experts can learn.",
	repo: "https://github.com/whizkydee/whizkydee.github.io",
	author: "Olaolu Olawuyi",
	version: 1.07,

	// Start main functions for the object

	// Function to add browser name and version to body class
	_showBrowser: function(b) {
		$("body").addClass(b + " " + b + parseInt(browser.version));
	},

	// Function to set attributes and values to elements
	_setAttr: function(elem, name, val) {
		$(elem, this).attr(name, val);
	},

	// Function to hide Notifications
	_hideNotif: function() {
		$("#notifBanner").removeClass("notif_vis");
	},

	// Function to push down .site-content
	_adjustSiteContent: function() {
		if( $("body").hasClass("default-body") ) {
			$(".top-stripe").addClass("adjustedMargin");
			$("#header .logo").addClass("adjustedTop");
			$(".main-menu").addClass("adjustedMargin");
			$("#header").addClass("adjustSiteContent");
		} else if ( $("body").hasClass("secondary-body") ) {
			$(".site-content").addClass("adjustSiteContent");
			$(".secondary-header").addClass("adjustedMargin");
		}
	},

	// Function to push up .site-content to default state
	_undoSiteAdjust: function() {
		if( $("body").hasClass("default-body") ) {
			$(".top-stripe").removeClass("adjustedMargin");
			$("#header .logo").removeClass("adjustedTop");
			$(".main-menu").removeClass("adjustedMargin");
			$("#header").removeClass("adjustSiteContent");
		} else if ( $("body").hasClass("secondary-body") ) {
			$(".secondary-header").removeClass("adjustedMargin");
		}
	},

	_resetSite: function() {
		WBT._showNotif();
		WBT._adjustSiteContent();
	},

	_undoReset: function() {
		WBT._hideNotif();
		WBT._undoSiteAdjust();
	},

	// Function to show Notifications before header
	_showNotif: function(text) {
		var text = (typeof text == "undefined") ? notif_text : text;
		WBT._adjustSiteContent();
		if( $("body").hasClass("default-body") ) {
			$(".top-stripe").before(
				"
"+text+"
"
			);
		} else if ( $("body").hasClass("secondary-body") ) {
			$(".secondary-header").before(
				"
"+text+"
"
			);
		} else {
			return;
		}
		$(".close-button").on("click", function() {
			WBT._hideNotif();
			WBT._undoSiteAdjust();
		});
	},

	// Function to launch modal

	_launchModal: function(w, h, r, p, c, e, b) {
		this.width = w;
	}

}, WBT = Webtwic,
notif_text = "Some features which affect the functionality of webtwic are disabled in your browser. Please try refreshing the page or get a better browser. ";

jQuery(document).ready(function() {

	// Define Variables
	var is_notifBanner = $("div").hasClass("notif_vis"),
	img = $("img"),
	is_noAlt = img.attr("alt", null),
	scripts = $("script"),
	is_noType = scripts.attr("type", null),
	is_noCharset = scripts.attr("charset", null);

	var $to_top = $("a.to-top"),
	is_toggle_active = $(".hamburger").hasClass("is_active"),
	height = 200;

	// Performance Fixes

	// Start browser detection

	browser = bowser;
	browser.ie = browser.msie;

	if (browser.webkit) {
		$("body").addClass("webkit");
	}
	if(browser.chrome) {
		Webtwic._showBrowser("chrome");
	}
	if(browser.msedge) {
		Webtwic._showBrowser("msedge");
	}
	if(browser.firefox) {
		Webtwic._showBrowser("firefox");
	}
	if(browser.msie) {
		Webtwic._showBrowser("ie");
	}
	if(browser.safari) {
		Webtwic._showBrowser("safari");
	}
	if(browser.opera) {
		Webtwic._showBrowser("opera");
	}

	// Performance fixes for attributes

	if(is_noAlt) {
		Webtwic._setAttr(img, "alt", "...");
	} else {
		return img.attr("alt");
	}

	if(is_noCharset) {
		Webtwic._setAttr(scripts, "charset", "utf-8");
	} else {
		return scripts.attr("charset");
	}

	if(is_noType) {
		Webtwic._setAttr(scripts, "type", "text/javascript");
	} else {
		return scripts.attr("type");
	}

	if (!Modernizr.flexbox || !Modernizr.inlinesvg || !Modernizr.svg || !Modernizr.svgclippaths || !Modernizr.fontface || !Modernizr.boxshadow || !Modernizr.borderradius || !Modernizr.csstransforms) {
		Webtwic._showNotif();
	} else {
		Webtwic._hideNotif();
	}

	// Start Main Page

	$("nav li ul.drop-nav").hide().removeClass("dropNavFallback");

	if ( $(window).width() > 860 ) {
		$("nav li.dropdown").hover(function() {
			$("ul.drop-nav", this).stop().slideDown("fast");
		}, function() {
			$("ul.drop-nav", this).stop().slideUp("fast");
		});
	}

	$(".active-item").append(
		"<svg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'><path d='M 16.682,19.674c 0.010-0.012, 0.014-0.028, 0.024-0.040l 6.982-7.714c 0.39-0.434, 0.39-1.138,0-1.572 c-0.004-0.004-0.008-0.006-0.012-0.008C 23.496,10.13, 23.244,10, 22.964,10L 8.998,10 c-0.286,0-0.54,0.138-0.722,0.352L 8.272,10.348 c-0.39,0.434-0.39,1.138,0,1.572l 6.998,7.754C 15.66,20.108, 16.292,20.108, 16.682,19.674z'></path></svg>"
	);

	$("a.hamburger").click(function(e) {
		$(this).toggleClass("is_active");

		e.preventDefault();
	});
	$(".mobile-header .mobile-nav").hide();

	$(window).scroll(function() {
		($(this).scrollTop() > height) ? $to_top.addClass("topVisible"): $to_top.removeClass("topVisible");
	});

	// Styles for homepage article-social

	$(".article .article-social a").hover(function() {
		$("span", this).eq(1).fadeIn(400);
	}, function() {
		$("span", this).eq(1).fadeOut(250);
	});

	// Functions for search-icon and ui-overlay-search

	$(".header-follow-search .search-wrap").on("click", function() {
		openUiOverlay();
	});

	$(".header-follow-search .close-icon").on("click", function() {
		closeUiOverlay();
	});

	$(".header-follow-search .close-icon").hover(
		function() {
			$(this).addClass("spin");
		},
		function() {
			$(this).removeClass("spin");
		});

	function openUiOverlay() {
		$(".ui-overlay-search").fadeIn(400).addClass("is_open");
	}

	function closeUiOverlay() {
		$(".ui-overlay-search").fadeOut(400).removeClass("is_open");
	}

	$(".ui-overlay-search .search-input input").focus(function() {
		$(".search-input").attr("data-focused", true);
		$(".search-input input").addClass("_is-focused");
		$("#__expand").addClass("visible");
	});

	$(".ui-overlay-search .search-input input").blur(function() {
		$(".search-input").attr("data-focused", false);
		$(".search-input input").removeClass("_is-focused");
		$("#__expand").removeClass("visible");
	});

	$(".post-meta .post-meta-inner .cta-btns a.is_inactive").on("click", function(e) {
		e.preventDefault();
	});

	$(document).keydown(function(e) {
    if (e.keyCode == 27) {
        closeUiOverlay();
    } else {
		 return;
	 }});

	 $(".mobile-nav").hide();

	// Functions for more-posts button click

	function addLoader() {
		$(".secondary-category-section .category-posts-column [data-clicked='false']").attr("data-clicked", "true").append("");
	}
	$(".secondary-category-section .category-posts-column [data-clicked='false']").on("click", function(e) {
		$(this).css({
			"background": "#50ABF1",
			"color": "#fff"
		});
		addLoader();
		e.preventDefault();
	});

	$to_top.on("click", function(e) {
		$("body,html").animate({
			scrollTop: 0
		}, 1000);

		e.preventDefault();
	});

});
<|endoftext|>


<commit_before>const DEFAULT_OPTIONS = { universeMapping: { 1: 1 } }

/**
 * A fivetwelve driver for the Arduino Leonardo ETH with DMX512 isolated shield
 * @see https://www.tindie.com/products/Conceptinetics/25kv-isolated-dmx-512-shield-for-arduino-r2/
 */
export default class ArduinoLeonardoETHDriver {

  /**
   * Initializes the driver for the given serialport.
   * @param {object} serialport A ready configured USBPort instance.
   * @param {object} options Options
   * universeMapping: A mapping of fivetwelve universe-numbers to universes.
   */
  constructor(serialport, options = {}) {
    this.serialport = serialport

    this.options = Object.assign({}, DEFAULT_OPTIONS, options)
  }

  /**
   * Sends the given values to the dmx-interface over the serialport.
   * @param {Buffer} buffer A buffer with the dmx-values to be sent.
   * @param {Number} universe The 1-based universe-number.
   * @returns {Promise} A promise that will be resolved when the buffer is
   *   completely sent.
   */
  send(buffer, universe) {
    const usbProUniverse = this.options.universeMapping[universe]

    if (!usbProUniverse) {
      return Promise.reject(new Error('No USB universum found'))
    }

    return this.sendPacket(buffer)
  }

  /**
   * Sends a single packet to the usbpro.
   * @param {Buffer} data The message payload.
   * @returns {Promise} A promise indicating when the data has been sent.
   * @private
   */
  sendPacket(data) {
    return this.write(data)
  }

  /**
   * Writes the raw data to the serialport.
   * @param {Buffer} buffer A buffer to be sent to the serialport.
   * @returns {Promise} a promise that is resolved when the buffer was completely sent.
   * @private
   */
  write(buffer) {
    // @TODO: DEBUG
    // console.log('Arduino', buffer)
    return new Promise((resolve, reject) => {
      if (this.serialport === null) {
        return reject(new Error('🔥 NO SERIALPORT CONNECTED 🔥'))
      }
      return this.serialport.send(buffer).then(result => {
        // USBOutTransferResult - { bytesWritten: 512, status: "ok" }
        if (result.status === 'ok') {
          return resolve(result.data)
        }
        return reject(new Error(`Status not "ok". Instead recieved status "${result.status}"`))
      }).catch(reject)
    })
    // There is no serialport yet
  }
}
<commit_msg>fix(error-handling): promise resolving<commit_after>const DEFAULT_OPTIONS = { universeMapping: { 1: 1 } }

/**
 * A fivetwelve driver for the Arduino Leonardo ETH with DMX512 isolated shield
 * @see https://www.tindie.com/products/Conceptinetics/25kv-isolated-dmx-512-shield-for-arduino-r2/
 */
export default class ArduinoLeonardoETHDriver {

  /**
   * Initializes the driver for the given serialport.
   * @param {object} serialport A ready configured USBPort instance.
   * @param {object} options Options
   * universeMapping: A mapping of fivetwelve universe-numbers to universes.
   */
  constructor(serialport, options = {}) {
    this.serialport = serialport

    this.options = Object.assign({}, DEFAULT_OPTIONS, options)
  }

  /**
   * Sends the given values to the dmx-interface over the serialport.
   * @param {Buffer} buffer A buffer with the dmx-values to be sent.
   * @param {Number} universe The 1-based universe-number.
   * @returns {Promise} A promise that will be resolved when the buffer is
   *   completely sent.
   */
  send(buffer, universe) {
    const usbProUniverse = this.options.universeMapping[universe]

    if (!usbProUniverse) {
      return Promise.reject(new Error('No USB universum found'))
    }

    return this.sendPacket(buffer)
  }

  /**
   * Sends a single packet to the usbpro.
   * @param {Buffer} data The message payload.
   * @returns {Promise} A promise indicating when the data has been sent.
   * @private
   */
  sendPacket(data) {
    return this.write(data)
  }

  /**
   * Writes the raw data to the serialport.
   * @param {Buffer} buffer A buffer to be sent to the serialport.
   * @returns {Promise} a promise that is resolved when the buffer was completely sent.
   * @private
   */
  write(buffer) {
    // @TODO: DEBUG
    // console.log('Arduino', buffer)
    return new Promise((resolve, reject) => {
      if (this.serialport === null) {
        console.error(new Error('🔥 NO SERIALPORT CONNECTED 🔥'))
      }
      return this.serialport.send(buffer).then(result => {
        // USBOutTransferResult - { bytesWritten: 512, status: "ok" }
        if (result.status !== 'ok') {
          console.error(new Error(`Status not "ok". Instead recieved status "${result.status}"`))
        }
        return resolve(result.data)
      }).catch(error => {
        console.error(error)
        return resolve()
      })
    })
    // There is no serialport yet
  }
}
<|endoftext|>


<commit_before>(function(){
"use strict";

glow.data = {
    count: {},
    map: {},
    sector: {}
};

var ROOT = "data/json/";

// Load the next file of json data before timeout seconds have elapsed.
glow.fetchCount = function(timeout) {
    // We don't request data.sector until the page flips, but
    // but we want to be ready with the right url.
    var sector = glow.data.count.next.next.replace('count', 'arc');
    getData(glow.data.count.next.next, timeout, function(r) {
        glow.data.count.next = r;
        glow.data.sector.next = sector;
    });
};

// Load the next file of json data before timeout seconds have elapsed.
glow.fetchMap = function(timeout) {
    getData(glow.data.map.next.next, timeout, function(r) {
        glow.data.map.next = r;
    });
};

// $.getJSON with an error parameter.
var getJSON = function(url, success, error) {
    $.ajax({url: ROOT + url, dataType: 'json',
            success: success, error: error});
};

// Reload the page if we couldn't fetch any data after a few retries. This
// drops us back into the loading screen with error messaging.
var fetchFailure = function() {
    window.location.reload();
};

// We have timeout seconds to pull the next chunk of data.
// Start by waiting timeout/2 seconds before the first attempt.
// If that fails, retry every 5 seconds until we run out of time.
var getData = function(url, timeout, success) {
    var error = setTimeout(fetchFailure, timeout * 1000),
        remaining = timeout / 2;

    var success_ = function(data, textStatus, xhr) {
        dbg('Success', url);
        clearTimeout(error);
        success(data, textStatus, xhr);
    };

    var fetch = function(timeout) {
        setTimeout(function() {
            getJSON(url, success_, function() {
                dbg('Error, retrying', url);
                if (!glow.stop) {
                    remaining -= 5;
                    fetch(5);
                }
            });
        }, timeout * 1000);
    };
    fetch(remaining);
};

glow.toggleView = function() {
    if (glow.view == "map") {
        glow.view = "chart";
        $("#sunburst").show();
        if (!glow.sector) initSunburst();
    } else {
        glow.view = "map";
        $("#sunburst").hide();
    }
    sizePageElements();
    $("body").toggleClass("view-sector", glow.view == "chart");
}

function sizePageElements() {
    var $geo = $("#geo");
    $("#sunburst, #geo").css("height", $("body").height() - 248);
    $("#chart")[0].width = $("#sunburst").width() - 300;
    $("#chart")[0].height = $("#sunburst").height();
    if (glow.sector) glow.sector.redraw();
    if ($geo.width() / $geo.height() > 2) {
        glow.map.scale = $geo.height() / 1650;
    } else {
        glow.map.scale = $geo.width() / 3600;
    }
    $("#mapdata, #pings").css({
        "top": $geo.height() - 1650 * glow.map.scale,
        "left": ($geo.width() - 3600 * glow.map.scale) / 2
    });
    $("#mapdata").css({
        "-moz-transform": "scale(" + glow.map.scale + ")",
        "-webkit-transform": "scale(" + glow.map.scale + ")",
        "-o-transform": "scale(" + glow.map.scale + ")"
    });
    if ($("#geo").height)
    $("#pings").css({
        width: $mc.width() + "px",
        height: $mc.height() + "px"
    });
    $("#pings")[0].width=$mc.width();
    $("#pings")[0].height=$mc.height();
}
$(window).resize(vast.debounce(sizePageElements, 500, this));

function initSunburst() {
  var loader = loading();
  $.getJSON(ROOT + glow.data.sector.next, function(r) {
      dbg('sector data loaded');
      processGeo(r.data, function(decodedData) {
          dbg('processing done');
          clearInterval(loader);
          glow.sector = $("#chart").arcChart({data: decodedData});
          $("#crumb").click(glow.sector.zoomOut);
      });
  });
}

function loading() {
    var c = $('#chart'),
        ctx = c[0].getContext('2d'),
        wedges = 8,
        cnt = 0;
    return setInterval(function(){
        ctx.save();
        ctx.fillStyle = 'rgba(227, 159, 28, .1)';
        ctx.translate(c[0].width / 2, c[0].height / 2);
        ctx.clearRect(-70, -70, 140, 140);
        for (var i = 0; i < 8; i++) {
            ctx.rotate(Math.PI / 4);
            if (i == cnt) {
                ctx.save();
                ctx.shadowColor = 'rgba(227, 159, 28, .8)';
                ctx.shadowBlur = 5;
                ctx.fillStyle = 'rgb(227, 159, 28)';
                wedge();
                ctx.restore();
            } else {
                wedge();
            }
        }
        function wedge() {
            ctx.beginPath();
            ctx.arc(0, 0, 60, 0, Math.PI / 8, 0);
            ctx.arc(0, 0, 20, Math.PI / 8, 0, 1);
            ctx.lineTo(60, 0);
            ctx.stroke();
            ctx.fill();
        }
        cnt = ++cnt % 8;
        ctx.restore();
    }, 90);
}

function processGeo(_data, cb) {
    $.getScript("locale/" + glow.locale + "/countries.js", function() {
        dbg('loaded countries');
        $.getScript("media/regions.js", function() {
            dbg('loaded regions');
            cb.call(null, [null, _data[1], decodeGeo(_data[2], 1)]);
        });
    });
}

var _continents = {
    "EU": "Europe",
    "NA": "North America",
    "AS": "Asia",
    "SA": "South America",
    "AF": "Africa",
    "OC": "Oceania"
};
function decodeGeo(data, depth, parent) {
    if (!data) return;
    var i, name, row,
        ret = [], o;
    for (i=0; i < data.length; i++) {
        row = data[i];
        switch (depth) {
            case 1:
                name = gettext(_continents[row[0]]) || row[0];
                break;
            case 2:
                name = _countries[row[0]] || row[0];
                break;
            case 3:
                name = _regions[parent][row[0]] || row[0];
                break;
            default:
                name = row[0];
        }
        ret.push([name, row[1], decodeGeo(row[2], depth+1, row[0])]);
    }
    return ret;
}

$("#chart").bind("update", function(e, list, current) {
    var $ul = $("#rankedlist").empty(),
        $crumb = $("#crumb").empty(),
        i;

    if (current) {
        $crumb.append(current[2][0]);
    }

    $ul.undelegate().delegate("li a", "click", function(e) {
        e.preventDefault();
        var $li = $(this).closest("li");
        glow.sector.zoomIn($li.index());
    })
    for (i=0; i<list.length; i++) {
        $ul.append("
" + list[i][2][0] + " " + numberfmt(list[i][2][1]) + "
");
    }

});

glow.init = function() {
    $.getJSON(ROOT + glow.time + "/count.json", function(r) {
        glow.data.count.next = r;
        glow.data.sector.next = glow.time + "/arc.json";
        glow.count.playNext();
        glow.bar.playNext();

        loadMap(function() {
            $.getJSON(ROOT + glow.time + "/map.json", function(r) {
                glow.data.map.next = r;
                glow.map.playNext();
            });
        });
    });

    initCounter();
    initBars();
    initMap();
    sizePageElements();

    $(".menu").click(glow.toggleView);
};

})();
<commit_msg>arcchart can now handle funkier data<commit_after>(function(){
"use strict";

glow.data = {
    count: {},
    map: {},
    sector: {}
};

var ROOT = "data/json/";

// Load the next file of json data before timeout seconds have elapsed.
glow.fetchCount = function(timeout) {
    // We don't request data.sector until the page flips, but
    // but we want to be ready with the right url.
    var sector = glow.data.count.next.next.replace('count', 'arc');
    getData(glow.data.count.next.next, timeout, function(r) {
        glow.data.count.next = r;
        glow.data.sector.next = sector;
    });
};

// Load the next file of json data before timeout seconds have elapsed.
glow.fetchMap = function(timeout) {
    getData(glow.data.map.next.next, timeout, function(r) {
        glow.data.map.next = r;
    });
};

// $.getJSON with an error parameter.
var getJSON = function(url, success, error) {
    $.ajax({url: ROOT + url, dataType: 'json',
            success: success, error: error});
};

// Reload the page if we couldn't fetch any data after a few retries. This
// drops us back into the loading screen with error messaging.
var fetchFailure = function() {
    window.location.reload();
};

// We have timeout seconds to pull the next chunk of data.
// Start by waiting timeout/2 seconds before the first attempt.
// If that fails, retry every 5 seconds until we run out of time.
var getData = function(url, timeout, success) {
    var error = setTimeout(fetchFailure, timeout * 1000),
        remaining = timeout / 2;

    var success_ = function(data, textStatus, xhr) {
        dbg('Success', url);
        clearTimeout(error);
        success(data, textStatus, xhr);
    };

    var fetch = function(timeout) {
        setTimeout(function() {
            getJSON(url, success_, function() {
                dbg('Error, retrying', url);
                if (!glow.stop) {
                    remaining -= 5;
                    fetch(5);
                }
            });
        }, timeout * 1000);
    };
    fetch(remaining);
};

glow.toggleView = function() {
    if (glow.view == "map") {
        glow.view = "chart";
        $("#sunburst").show();
        if (!glow.sector) initSunburst();
    } else {
        glow.view = "map";
        $("#sunburst").hide();
    }
    sizePageElements();
    $("body").toggleClass("view-sector", glow.view == "chart");
}

function sizePageElements() {
    var $geo = $("#geo");
    $("#sunburst, #geo").css("height", $("body").height() - 248);
    $("#chart")[0].width = $("#sunburst").width() - 300;
    $("#chart")[0].height = $("#sunburst").height();
    if (glow.sector) glow.sector.redraw();
    if ($geo.width() / $geo.height() > 2) {
        glow.map.scale = $geo.height() / 1650;
    } else {
        glow.map.scale = $geo.width() / 3600;
    }
    $("#mapdata, #pings").css({
        "top": $geo.height() - 1650 * glow.map.scale,
        "left": ($geo.width() - 3600 * glow.map.scale) / 2
    });
    $("#mapdata").css({
        "-moz-transform": "scale(" + glow.map.scale + ")",
        "-webkit-transform": "scale(" + glow.map.scale + ")",
        "-o-transform": "scale(" + glow.map.scale + ")"
    });
    if ($("#geo").height)
    $("#pings").css({
        width: $mc.width() + "px",
        height: $mc.height() + "px"
    });
    $("#pings")[0].width=$mc.width();
    $("#pings")[0].height=$mc.height();
}
$(window).resize(vast.debounce(sizePageElements, 500, this));

function initSunburst() {
  var loader = loading();
  $.getJSON(ROOT + glow.data.sector.next, function(r) {
      dbg('sector data loaded');
      processGeo(r.data, function(decodedData) {
          dbg('processing done');
          clearInterval(loader);
          glow.sector = $("#chart").arcChart({data: decodedData});
          $("#crumb").click(glow.sector.zoomOut);
      });
  });
}

function loading() {
    var c = $('#chart'),
        ctx = c[0].getContext('2d'),
        wedges = 8,
        cnt = 0;
    return setInterval(function(){
        ctx.save();
        ctx.fillStyle = 'rgba(227, 159, 28, .1)';
        ctx.translate(c[0].width / 2, c[0].height / 2);
        ctx.rotate(-Math.PI/16);
        ctx.clearRect(-70, -70, 140, 140);
        for (var i = 0; i < 8; i++) {
            ctx.rotate(Math.PI / 4);
            if (i == cnt) {
                ctx.save();
                ctx.shadowColor = 'rgba(227, 159, 28, .8)';
                ctx.shadowBlur = 5;
                ctx.fillStyle = 'rgb(227, 159, 28)';
                wedge();
                ctx.restore();
            } else {
                wedge();
            }
        }
        function wedge() {
            ctx.beginPath();
            ctx.arc(0, 0, 60, 0, Math.PI / 8, 0);
            ctx.arc(0, 0, 20, Math.PI / 8, 0, 1);
            ctx.lineTo(60, 0);
            ctx.stroke();
            ctx.fill();
        }
        cnt = ++cnt % 8;
        ctx.restore();
    }, 90);
}

function processGeo(_data, cb) {
    $.getScript("locale/" + glow.locale + "/countries.js", function() {
        dbg('loaded countries');
        $.getScript("media/regions.js", function() {
            dbg('loaded regions');
            cb.call(null, [null, _data[1], decodeGeo(_data[2], 1)]);
        });
    });
}

var _continents = {
    "EU": "Europe",
    "NA": "North America",
    "AS": "Asia",
    "SA": "South America",
    "AF": "Africa",
    "OC": "Oceania"
};
function decodeGeo(data, depth, parent) {
    if (!data) return;
    var i, name, row,
        ret = [], o;
    for (i=0; i < data.length; i++) {
        row = data[i];
        name = row[0] || "<Unknown>";
        switch (depth) {
            case 1:
                name = gettext(_continents[row[0]]) || name;
                break;
            case 2:
                name = _countries[row[0]] || name;
                break;
            case 3:
                if (_regions[parent]) {
                    name = _regions[parent][row[0]] || name
                }
        }
        ret.push([name, row[1], decodeGeo(row[2], depth+1, row[0])]);
    }
    return ret;
}

$("#chart").bind("update", function(e, list, current) {
    var $ul = $("#rankedlist").empty(),
        $crumb = $("#crumb").empty(),
        i;

    if (current) {
        $crumb.append(current[2][0]);
    }

    $ul.undelegate().delegate("li a", "click", function(e) {
        e.preventDefault();
        var $li = $(this).closest("li");
        glow.sector.zoomIn($li.index());
    })
    for (i=0; i<list.length; i++) {
        $ul.append("
" + list[i][2][0] + " " + numberfmt(list[i][2][1]) + "
");
    }

});

glow.init = function() {
    $.getJSON(ROOT + glow.time + "/count.json", function(r) {
        glow.data.count.next = r;
        glow.data.sector.next = glow.time + "/arc.json";
        glow.count.playNext();
        glow.bar.playNext();

        loadMap(function() {
            $.getJSON(ROOT + glow.time + "/map.json", function(r) {
                glow.data.map.next = r;
                glow.map.playNext();
            });
        });
    });

    initCounter();
    initBars();
    initMap();
    sizePageElements();

    $(".menu").click(glow.toggleView);
};

})();
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { View, StyleSheet, AppState, ActivityIndicator } from 'react-native';
import NavigationViewContainer from './navigation/NavigationViewContainer';
import { Map, List } from 'immutable';
import NavigationModal from '../components/NavigationModal';
import * as snapshotUtil from '../utils/snapshot';
import { NavigationActions } from 'react-navigation';
import {
  initializeSessionState,
  activate,
  deactivate,
  resetSessionStateFromSnapshot,
} from '../modules/session/SessionState';
import { resetCurrentUser } from './user/UserState';
import store from '../redux/store';
import Orientation from 'react-native-orientation';

const styles = StyleSheet.create({
  centered: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const mapStateToProps = state => ({
  isReady: state.getIn(['session', 'isReady']),
  currentUser: state.getIn(['user', 'currentUser']),
  currentPage: state.getIn(['navigatorState', 'index']),
  pages: state.getIn(['navigatorState', 'routes']),
});

const mapDispatchToProps = dispatch => ({
  initializeSessionState: () => dispatch(initializeSessionState()),
  resetCurrentUser: () => dispatch(resetCurrentUser()),
  activate: () => dispatch(activate()),
  deactivate: () => dispatch(deactivate()),
  resetSessionStateFromSnapshot: snapshot => dispatch(resetSessionStateFromSnapshot(snapshot)),
  navigate: route => dispatch(NavigationActions.navigate({ routeName: route })),
  resetRoute: () => dispatch(NavigationActions.reset({
    index: 0,
    actions: [
      NavigationActions.navigate({ routeName: 'Home' }),
    ],
  })),
});

@connect(mapStateToProps, mapDispatchToProps)
export default class AppViewContainer extends Component {

  static propTypes = {
    isReady: PropTypes.bool.isRequired,
    initializeSessionState: PropTypes.func.isRequired,
    activate: PropTypes.func.isRequired,
    deactivate: PropTypes.func.isRequired,
    resetSessionStateFromSnapshot: PropTypes.func.isRequired,
    navigate: PropTypes.func.isRequired,
    resetCurrentUser: PropTypes.func.isRequired,
    resetRoute: PropTypes.func.isRequired,
    currentUser: PropTypes.instanceOf(Map),
    currentPage: PropTypes.number,
    pages: PropTypes.instanceOf(List),
  };

  state = {
    currentState: AppState.currentState,
    previousState: null,
  };

  componentDidMount() {
    AppState.addEventListener('change', this._handleAppStateChange);

    /* Haetaan viimeisin tila */
    snapshotUtil.resetSnapshot()
    .then((snapshot) => {
      /* Jos viimeisin tila löytyi */
      if (snapshot) {
        this.props.resetSessionStateFromSnapshot(snapshot);
        this.props.activate();
      }
      /* Ei löytynyt. Aloitetaan alusta */
      else {
        this.props.initializeSessionState();
      }

      /* Tallennetaan uusin tila aina kun statea päivitetään */
      store.subscribe(() => {
        snapshotUtil.saveSnapshot(store.getState());
      });
    });
  }

  _handleAppStateChange = (appState) => {
    const previous = this.state.currentState;

    this.setState({ currentState: appState, previousState: previous });

    if (this.state.currentState === 'active') {
      this.props.activate();
    } else if (this.state.currentState === 'inactive' || this.state.currentState === 'background') {
      this.props.deactivate();
    }
  };

  shouldRenderNavigationModal = () => {
    const route = this.props.pages.get(this.props.currentPage).get('routeName');

    return route !== 'Settings' && route !== 'Home' && route !== 'Ending' && route !== 'Login';
  };

  renderNavigationModal = () => this.shouldRenderNavigationModal() ? (
    <NavigationModal
      resetRoute={this.props.resetRoute}
      resetCurrentUser={this.props.resetCurrentUser}
      phase={this.props.pages.get(this.props.currentPage - 1).get('key') === 'Mood' ? 'moods' : 'other'}
      shouldSave={this.props.currentPage !== 1}
      currentUser={this.props.currentUser}
      quit={() => this.props.navigate('Ending')}
    />
    ) : null;

  render() {
    if (!this.props.isReady) {
      return (
        <View style={styles.centered}>
          <ActivityIndicator />
        </View>
      );
    }

    return (
      <View style={{ flex: 1 }}>
        <NavigationViewContainer />
        {this.renderNavigationModal()}
      </View>
    );
  }
}
<commit_msg>Remove navigation modal and useless props from AppView<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { View, StyleSheet, AppState, ActivityIndicator } from 'react-native';
import NavigationViewContainer from './navigation/NavigationViewContainer';
import * as snapshotUtil from '../utils/snapshot';
import {
  initializeSessionState,
  activate,
  deactivate,
  resetSessionStateFromSnapshot,
} from '../modules/session/SessionState';
import store from '../redux/store';

const styles = StyleSheet.create({
  centered: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const mapStateToProps = state => ({
  isReady: state.getIn(['session', 'isReady']),
  currentUser: state.getIn(['user', 'currentUser']),
  currentPage: state.getIn(['navigatorState', 'index']),
  pages: state.getIn(['navigatorState', 'routes']),
});

const mapDispatchToProps = dispatch => ({
  initializeSessionState: () => dispatch(initializeSessionState()),
  activate: () => dispatch(activate()),
  deactivate: () => dispatch(deactivate()),
  resetSessionStateFromSnapshot: snapshot => dispatch(resetSessionStateFromSnapshot(snapshot)),
});

@connect(mapStateToProps, mapDispatchToProps)
export default class AppViewContainer extends Component {

  static propTypes = {
    isReady: PropTypes.bool.isRequired,
    initializeSessionState: PropTypes.func.isRequired,
    activate: PropTypes.func.isRequired,
    deactivate: PropTypes.func.isRequired,
    resetSessionStateFromSnapshot: PropTypes.func.isRequired,
  };

  state = {
    currentState: AppState.currentState,
    previousState: null,
  };

  componentDidMount() {
    AppState.addEventListener('change', this._handleAppStateChange);

    /* Haetaan viimeisin tila */
    snapshotUtil.resetSnapshot()
    .then((snapshot) => {
      /* Jos viimeisin tila löytyi */
      if (false && snapshot) {
        this.props.resetSessionStateFromSnapshot(snapshot);
        this.props.activate();
      }
      /* Ei löytynyt. Aloitetaan alusta */
      else {
        this.props.initializeSessionState();
      }

      /* Tallennetaan uusin tila aina kun statea päivitetään */
      store.subscribe(() => {
        snapshotUtil.saveSnapshot(store.getState());
      });
    });
  }

  _handleAppStateChange = (appState) => {
    const previous = this.state.currentState;

    this.setState({ currentState: appState, previousState: previous });

    if (this.state.currentState === 'active') {
      this.props.activate();
    } else if (this.state.currentState === 'inactive' || this.state.currentState === 'background') {
      this.props.deactivate();
    }
  };

  render() {
    if (!this.props.isReady) {
      return (
        <View style={styles.centered}>
          <ActivityIndicator />
        </View>
      );
    }

    return (
      <View style={{ flex: 1 }}>
        <NavigationViewContainer />
      </View>
    );
  }
}
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import Slugify from 'slugify';
import React from 'react';

import { InpageNavSection } from '../../scripts/uikit/inpage-nav';

/**
 * The section component
 */
const Section = ( page ) => {

	const HeadingTag = `h${ page.level ? page.level : 2 }`;

	return (

						<HeadingTag className="section__header" id={ Slugify( page.section ).toLowerCase() }>
							 { page.section }
						</HeadingTag>

	)};

Section.propTypes = {
	/**
	 * section: This important section
	 */
	section: PropTypes.string.isRequired,
};

Section.defaultProps = {
};

export default Section;
<commit_msg>constrain length of nav/section header<commit_after>import PropTypes from 'prop-types';
import Slugify from 'slugify';
import React from 'react';

import { InpageNavSection } from '../../scripts/uikit/inpage-nav';

/**
 * The section component
 */
const Section = ( page ) => {

	const HeadingTag = `h${ page.level ? page.level : 2 }`;

	return (

						<HeadingTag className="section__header" id={ Slugify( page.section ).toLowerCase() }>
							 { page.section }
						</HeadingTag>

	)};

Section.propTypes = {
	/**
	 * section: This important section
	 */
	section: PropTypes.string.isRequired,
};

Section.defaultProps = {
};

export default Section;
<|endoftext|>


<commit_before>'use strict';
var express = require('express');

var http = require('http');
var path = require('path');
var multiparty = require('multiparty');
var FormData = require('form-data');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var rs = require('request-promise');

var passport = require('passport');
var GoogleStrategy = require('passport-google-oauth20').Strategy;
var LocalStrategy = require('passport-local').Strategy;
var jwt = require('jsonwebtoken');
var expressJwt = require('express-jwt');

var serviceIp = process.env.SERVICE_IP || '127.0.0.1';
var webIp = process.env.WEB_IP || 'localhost';
var serviceRoot = 'http://' + serviceIp + ':5555/api';
var port = process.env.PORT || '8000';

var app = express();

app.set('port', port);
app.use(express.static(path.join(__dirname, 'app')));
app.use(bodyParser.urlencoded({extended: 'true'}));
app.use(bodyParser.json());

passport.serializeUser(function(user, done) {
    done(null, user.name);
});

passport.deserializeUser(function(userName, done) {
	if (userName === 'Chris') {
		done({name: 'Chris'});
	}
	done('error', null);
});

var auth = function(req, res, next) {
	if (!req.isAuthenticated()) {
		res.send(401);
	}
	else {
		next();
	}
	//- See more at: https://vickev.com/#!/article/authentication-in-single-page-applications-node-js-passportjs-angularjs
};

passport.use(new GoogleStrategy({
	//see https://console.developers.google.com to get the clientID and clientSecret
		clientID: 'abc',//GOOGLE_CLIENT_ID,
		clientSecret: '123',//GOOGLE_CLIENT_SECRET,
		callbackURL: 'http://' + webIp + '/auth/google/callback'
		//add this to the html:   Google
	},
	function(accessToken, refreshToken, profile, cb) {
//    User.findOrCreate({ googleId: profile.id }, function (err, user) {
//      return cb(err, user);
//    });
		console.log("INSIDE GOOGLE STRATEGY FUNCTION:", profile);
		return cb(null, profile); //?? not sure about this
	}
));

passport.use('local-login', new LocalStrategy({
    // by default, local strategy uses username and password, we will override with email
    usernameField : 'email',
    passwordField : 'ipAddress',
    passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, ipAddress, done) { // callback with email and ipAddress from our form

	console.log("INSIDE LOCAL STRATEGY FUNCTION:", {email: email, ipAddress: ipAddress});
	return done(null, {name:'Chris', email: email, ipAddress: ipAddress});
}));
app.use(passport.initialize());

function headersFromRequest(request) {
	var headers = {};
	if (request.headers['Content-Type']) {
		headers['Content-Type'] = request.headers['Content-Type'];
	}
	if (request.headers['Content-Length']) {
		headers['Content-Length'] = request.headers['Content-Length'];
	}
	if (request.headers.requestinguser) {
		headers.RequestingUser = request.headers.requestinguser;
	}
	return headers;
}

function performRecipeListGET(searchString, recipeBookUserId) {
	var uri = serviceRoot + '/recipe';
	if (searchString) {
		uri += '?searchString=' + searchString;
	}
	if(searchString && recipeBookUserId) {
		uri += '&recipeBook=' + recipeBookUserId;
	}
	if(!searchString && recipeBookUserId) {
		uri += '?recipeBook=' + recipeBookUserId;
	}

	var getOptions = {
		uri : uri,
		json : true,
		simple: false,
		resolveWithFullResponse: true
	};
	return rs.get(getOptions);
}

function performRecipeGET(recipeId, request) {
	var getOptions = {
		uri : serviceRoot + '/recipe/' + recipeId,
		headers: headersFromRequest(request),
		json : true,
		simple: false,
		resolveWithFullResponse: true
	};
	return rs.get(getOptions);
}

function performRecipePOST(recipe, request) {
	var postOptions = {
		uri : serviceRoot + '/recipe',
		headers : headersFromRequest(request),
		json : true,
		body : recipe,
		simple: false,
		resolveWithFullResponse: true
	};
	return rs.post(postOptions);
}

function performRecipePUT(recipe, request) {
	var postOptions = {
		uri : serviceRoot + '/recipe/' + recipe.recipeId,
		headers : headersFromRequest(request),
		json : true,
		body : recipe,
		simple: false,
		resolveWithFullResponse: true
	};
	return rs.put(postOptions);
}

function performUserPOST(user) {
	var postOptions = {
		uri : serviceRoot + '/user',
		headers : {
			'Content-Type' : 'application/json',
			'Content-Length' : user.length
		},
		json : true,
		body : user,
		simple: false,
		resolveWithFullResponse: true
	};
	return rs.post(postOptions);
}

function performUserGETByEmail(email) {
	var getOptions = {
			uri : serviceRoot + '/user?email=' + email,
			json : true,
			simple: false,
			resolveWithFullResponse: true
	};

	return rs.get(getOptions);
}

function performUserGET(userId) {
	var getOptions = {
			uri : serviceRoot + '/user/' + userId,
			json : true,
			simple: false,
			resolveWithFullResponse: true
	};

	return rs.get(getOptions);
}

function performRecipeBookGET(userId) {
	var getOptions = {
		uri : serviceRoot + '/user/' + userId + '/recipe-book',
		json : true,
		simple: false,
		resolveWithFullResponse: true
	};

	return rs.get(getOptions);
}

function performRecipeBookPOSTRecipe(recipeIdToPost, userId, request) {
	var postOptions = {
		uri : serviceRoot + '/user/' + userId + '/recipe-book',
		headers : headersFromRequest(request),
		json : true,
		body : recipeIdToPost,
		simple: false,
		resolveWithFullResponse: true
	};

	return rs.post(postOptions);
}

function performRecipeBookDELETERecipe(userId, recipeId, request) {
	var deleteOptions = {
		uri : serviceRoot + '/user/' + userId + '/recipe-book/' + recipeId,
		headers : headersFromRequest(request),
		json : true,
		simple: false,
		resolveWithFullResponse: true
	};

	return rs.del(deleteOptions);
}

app.get('/api/recipe', function(request, response, next) {
	performRecipeListGET(request.query.searchString, request.query.recipeBook).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error getting recipes: ', error);
	});
});

app.get('/api/recipe/:recipeId', function(request, response, next) {
	var recipeId = request.params.recipeId;
	performRecipeGET(recipeId, request).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error getting recipe with id ' + recipeId + ': ', error);
	});
});

app.post('/api/recipe', function(request, response, next) {
	var recipe = request.body;
	performRecipePOST(recipe, request).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error posting a new recipe:', recipe, 'Error:', error);
	});
});

app.put('/api/recipe/:recipeId', function(request, response, next) {
	var recipe = request.body;
	performRecipePUT(recipe, request).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error putting a new recipe:', recipe, 'Error:', error);
	});
});

app.post('/api/recipe/:recipeId/image', function(request, response, next) {
	var recipeId =  request.params.recipeId;
	var form = new multiparty.Form();

	form.on("part", function(part){
		if(part.filename)
		{
			var form = new FormData();
			form.append("file", part, {filename: part.filename,contentType: part["content-type"]});

			var url = serviceRoot + '/recipe/' + recipeId + '/image';
			var r = rs.post(
				url,
				{ "headers":
					{"transfer-encoding": "chunked"}
				},
				function(err, res, body){
					response.send(res);
				});

			r._form = form;
		}
	});

	form.on("error", function(error){
		console.log(error);
		// response.send(error);
	});

	form.parse(request);
});

app.post('/api/user', function(request, response, next) {
	var user = request.body;
	performUserPOST(user).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error posting a new user:', user, 'Error:', error);
	});
});

app.get('/api/user', function(request, response, next) {
	var email = request.query.email;
	performUserGETByEmail(email).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Could not get a user with email:', email, 'Error:', error);
	});
});

app.get('/api/user/:userId', function(request, response, next) {
	var userId =  request.params.userId;
	performUserGET(userId).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Could not get a user with id:', userId, 'Error:', error);
	});
});

app.get('/auth/google', passport.authenticate('google', { scope: ['profile'] }));

app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }),
	function(req, res) {
		// Successful authentication, redirect home.
		res.redirect('/');
	}
);

app.post('/login', passport.authenticate('local-login', {
    successRedirect : '/', // redirect to the secure profile section
    failureRedirect : '/login', // redirect back to the signup page if there is an error
    failureFlash : true // allow flash messages
}));

app.get('/api/user/:userId/recipe-book', function(request, response, next) {
	var userId = request.params.userId;
	performRecipeBookGET(userId).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error getting recipe book for user with id ', userId, 'Error: ', error);
	});
});

app.post('/api/user/:userId/recipe-book', function(request, response, next) {
	var userId = request.params.userId;
	var recipeId = request.body;
	performRecipeBookPOSTRecipe(recipeId, userId, request).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error posting a new recipeId to user recipe book.  RecipeId: ', recipeId, " UserId: ", userId, 'Error:', error);
	});
});

app.delete('/api/user/:userId/recipe-book/:recipeId', function(request, response, next) {
	var userId = request.params.userId;
	var recipeId = request.params.recipeId;
	performRecipeBookDELETERecipe(userId, recipeId, request).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error deleting a recipeId from a user recipe book.  UserId: ', userId, " RecipeId: ", recipeId, 'Error:', error);
	});
});

app.post('/auth', passport.authenticate(
  'local-login', {
    session: false
  }), serialize, generateToken, respond);

function serialize(req, res, next) {
	  db.updateOrCreate(req.user, function(err, user){
	    if(err) {return next(err);}
	    // we store the updated information in req.user again
	    req.user = {
	      id: user.email,
	      name: user.name,
	      email: user.email,
	      ipAddress: user.ipAddress
	    };
	    next();
	  });
	}

var db = {
  updateOrCreate: function(user, cb){
    // db dummy, we just cb the user
    cb(null, user);
  }
};

function generateToken(req, res, next) {
	req.token = jwt.sign(
			{
				id: req.user.id,
				email: req.user.email,
				ipAddress: req.user.ipAddress
			},
			'server secret'
			//,{expiresInMinutes: 120}
	);
	next();
}

function respond(req, res) {
	  res.status(200).json({
	    user: req.user,
	    token: req.token
	  });
}

var authenticate = expressJwt({secret : 'server secret'});
app.get('/test-auth', authenticate, function(request, response, next) {
	response.json({auth: 'success', user: request.user});
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});<commit_msg>accurate status codes in file upload response<commit_after>'use strict';
var express = require('express');

var http = require('http');
var path = require('path');
var multiparty = require('multiparty');
var FormData = require('form-data');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var rs = require('request-promise');

var passport = require('passport');
var GoogleStrategy = require('passport-google-oauth20').Strategy;
var LocalStrategy = require('passport-local').Strategy;
var jwt = require('jsonwebtoken');
var expressJwt = require('express-jwt');

var serviceIp = process.env.SERVICE_IP || '127.0.0.1';
var webIp = process.env.WEB_IP || 'localhost';
var serviceRoot = 'http://' + serviceIp + ':5555/api';
var port = process.env.PORT || '8000';

var app = express();

app.set('port', port);
app.use(express.static(path.join(__dirname, 'app')));
app.use(bodyParser.urlencoded({extended: 'true'}));
app.use(bodyParser.json());

passport.serializeUser(function(user, done) {
    done(null, user.name);
});

passport.deserializeUser(function(userName, done) {
	if (userName === 'Chris') {
		done({name: 'Chris'});
	}
	done('error', null);
});

var auth = function(req, res, next) {
	if (!req.isAuthenticated()) {
		res.send(401);
	}
	else {
		next();
	}
	//- See more at: https://vickev.com/#!/article/authentication-in-single-page-applications-node-js-passportjs-angularjs
};

passport.use(new GoogleStrategy({
	//see https://console.developers.google.com to get the clientID and clientSecret
		clientID: 'abc',//GOOGLE_CLIENT_ID,
		clientSecret: '123',//GOOGLE_CLIENT_SECRET,
		callbackURL: 'http://' + webIp + '/auth/google/callback'
		//add this to the html:   Google
	},
	function(accessToken, refreshToken, profile, cb) {
//    User.findOrCreate({ googleId: profile.id }, function (err, user) {
//      return cb(err, user);
//    });
		console.log("INSIDE GOOGLE STRATEGY FUNCTION:", profile);
		return cb(null, profile); //?? not sure about this
	}
));

passport.use('local-login', new LocalStrategy({
    // by default, local strategy uses username and password, we will override with email
    usernameField : 'email',
    passwordField : 'ipAddress',
    passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, ipAddress, done) { // callback with email and ipAddress from our form

	console.log("INSIDE LOCAL STRATEGY FUNCTION:", {email: email, ipAddress: ipAddress});
	return done(null, {name:'Chris', email: email, ipAddress: ipAddress});
}));
app.use(passport.initialize());

function headersFromRequest(request) {
	var headers = {};
	if (request.headers['Content-Type']) {
		headers['Content-Type'] = request.headers['Content-Type'];
	}
	if (request.headers['Content-Length']) {
		headers['Content-Length'] = request.headers['Content-Length'];
	}
	if (request.headers.requestinguser) {
		headers.RequestingUser = request.headers.requestinguser;
	}
	return headers;
}

function performRecipeListGET(searchString, recipeBookUserId) {
	var uri = serviceRoot + '/recipe';
	if (searchString) {
		uri += '?searchString=' + searchString;
	}
	if(searchString && recipeBookUserId) {
		uri += '&recipeBook=' + recipeBookUserId;
	}
	if(!searchString && recipeBookUserId) {
		uri += '?recipeBook=' + recipeBookUserId;
	}

	var getOptions = {
		uri : uri,
		json : true,
		simple: false,
		resolveWithFullResponse: true
	};
	return rs.get(getOptions);
}

function performRecipeGET(recipeId, request) {
	var getOptions = {
		uri : serviceRoot + '/recipe/' + recipeId,
		headers: headersFromRequest(request),
		json : true,
		simple: false,
		resolveWithFullResponse: true
	};
	return rs.get(getOptions);
}

function performRecipePOST(recipe, request) {
	var postOptions = {
		uri : serviceRoot + '/recipe',
		headers : headersFromRequest(request),
		json : true,
		body : recipe,
		simple: false,
		resolveWithFullResponse: true
	};
	return rs.post(postOptions);
}

function performRecipePUT(recipe, request) {
	var postOptions = {
		uri : serviceRoot + '/recipe/' + recipe.recipeId,
		headers : headersFromRequest(request),
		json : true,
		body : recipe,
		simple: false,
		resolveWithFullResponse: true
	};
	return rs.put(postOptions);
}

function performUserPOST(user) {
	var postOptions = {
		uri : serviceRoot + '/user',
		headers : {
			'Content-Type' : 'application/json',
			'Content-Length' : user.length
		},
		json : true,
		body : user,
		simple: false,
		resolveWithFullResponse: true
	};
	return rs.post(postOptions);
}

function performUserGETByEmail(email) {
	var getOptions = {
			uri : serviceRoot + '/user?email=' + email,
			json : true,
			simple: false,
			resolveWithFullResponse: true
	};

	return rs.get(getOptions);
}

function performUserGET(userId) {
	var getOptions = {
			uri : serviceRoot + '/user/' + userId,
			json : true,
			simple: false,
			resolveWithFullResponse: true
	};

	return rs.get(getOptions);
}

function performRecipeBookGET(userId) {
	var getOptions = {
		uri : serviceRoot + '/user/' + userId + '/recipe-book',
		json : true,
		simple: false,
		resolveWithFullResponse: true
	};

	return rs.get(getOptions);
}

function performRecipeBookPOSTRecipe(recipeIdToPost, userId, request) {
	var postOptions = {
		uri : serviceRoot + '/user/' + userId + '/recipe-book',
		headers : headersFromRequest(request),
		json : true,
		body : recipeIdToPost,
		simple: false,
		resolveWithFullResponse: true
	};

	return rs.post(postOptions);
}

function performRecipeBookDELETERecipe(userId, recipeId, request) {
	var deleteOptions = {
		uri : serviceRoot + '/user/' + userId + '/recipe-book/' + recipeId,
		headers : headersFromRequest(request),
		json : true,
		simple: false,
		resolveWithFullResponse: true
	};

	return rs.del(deleteOptions);
}

app.get('/api/recipe', function(request, response, next) {
	performRecipeListGET(request.query.searchString, request.query.recipeBook).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error getting recipes: ', error);
	});
});

app.get('/api/recipe/:recipeId', function(request, response, next) {
	var recipeId = request.params.recipeId;
	performRecipeGET(recipeId, request).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error getting recipe with id ' + recipeId + ': ', error);
	});
});

app.post('/api/recipe', function(request, response, next) {
	var recipe = request.body;
	performRecipePOST(recipe, request).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error posting a new recipe:', recipe, 'Error:', error);
	});
});

app.put('/api/recipe/:recipeId', function(request, response, next) {
	var recipe = request.body;
	performRecipePUT(recipe, request).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error putting a new recipe:', recipe, 'Error:', error);
	});
});

app.post('/api/recipe/:recipeId/image', function(request, response, next) {
	var recipeId =  request.params.recipeId;
	var form = new multiparty.Form();

	form.on("part", function(part){
		if(part.filename)
		{
			var form = new FormData();
			form.append("file", part, {filename: part.filename,contentType: part["content-type"]});

			var url = serviceRoot + '/recipe/' + recipeId + '/image';
			var r = rs.post(
				url,
				{ "headers":
					{"transfer-encoding": "chunked"}
				},
				function(err, res, body){
					response.statusCode = res.statusCode;
					response.send(res);
			});

			r._form = form;
		}
	});

	form.on("error", function(error){
		console.log(error);
	});

	form.parse(request);
});

app.post('/api/user', function(request, response, next) {
	var user = request.body;
	performUserPOST(user).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error posting a new user:', user, 'Error:', error);
	});
});

app.get('/api/user', function(request, response, next) {
	var email = request.query.email;
	performUserGETByEmail(email).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Could not get a user with email:', email, 'Error:', error);
	});
});

app.get('/api/user/:userId', function(request, response, next) {
	var userId =  request.params.userId;
	performUserGET(userId).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Could not get a user with id:', userId, 'Error:', error);
	});
});

app.get('/auth/google', passport.authenticate('google', { scope: ['profile'] }));

app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }),
	function(req, res) {
		// Successful authentication, redirect home.
		res.redirect('/');
	}
);

app.post('/login', passport.authenticate('local-login', {
    successRedirect : '/', // redirect to the secure profile section
    failureRedirect : '/login', // redirect back to the signup page if there is an error
    failureFlash : true // allow flash messages
}));

app.get('/api/user/:userId/recipe-book', function(request, response, next) {
	var userId = request.params.userId;
	performRecipeBookGET(userId).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error getting recipe book for user with id ', userId, 'Error: ', error);
	});
});

app.post('/api/user/:userId/recipe-book', function(request, response, next) {
	var userId = request.params.userId;
	var recipeId = request.body;
	performRecipeBookPOSTRecipe(recipeId, userId, request).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error posting a new recipeId to user recipe book.  RecipeId: ', recipeId, " UserId: ", userId, 'Error:', error);
	});
});

app.delete('/api/user/:userId/recipe-book/:recipeId', function(request, response, next) {
	var userId = request.params.userId;
	var recipeId = request.params.recipeId;
	performRecipeBookDELETERecipe(userId, recipeId, request).then(function(data) {
		response.statusCode = data.statusCode;
		response.json(data.body);
	})
	.catch(function(error) {
		console.log('Error deleting a recipeId from a user recipe book.  UserId: ', userId, " RecipeId: ", recipeId, 'Error:', error);
	});
});

app.post('/auth', passport.authenticate(
  'local-login', {
    session: false
  }), serialize, generateToken, respond);

function serialize(req, res, next) {
	  db.updateOrCreate(req.user, function(err, user){
	    if(err) {return next(err);}
	    // we store the updated information in req.user again
	    req.user = {
	      id: user.email,
	      name: user.name,
	      email: user.email,
	      ipAddress: user.ipAddress
	    };
	    next();
	  });
	}

var db = {
  updateOrCreate: function(user, cb){
    // db dummy, we just cb the user
    cb(null, user);
  }
};

function generateToken(req, res, next) {
	req.token = jwt.sign(
			{
				id: req.user.id,
				email: req.user.email,
				ipAddress: req.user.ipAddress
			},
			'server secret'
			//,{expiresInMinutes: 120}
	);
	next();
}

function respond(req, res) {
	  res.status(200).json({
	    user: req.user,
	    token: req.token
	  });
}

var authenticate = expressJwt({secret : 'server secret'});
app.get('/test-auth', authenticate, function(request, response, next) {
	response.json({auth: 'success', user: request.user});
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});<|endoftext|>