<commit_before>var _; //globals

describe("About Applying What We Have Learnt", function() {

  var products;

  beforeEach(function () {
    products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];
  });

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

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (imperative)", function () {

    var i,j,hasMushrooms, productsICanEat = [];

    for (i = 0; i < products.length; i+=1) {
        if (products[i].containsNuts === false) {
            hasMushrooms = false;
            for (j = 0; j < products[i].ingredients.length; j+=1) {
               if (products[i].ingredients[j] === "mushrooms") {
                  hasMushrooms = true;
               }
            }
            if (!hasMushrooms) productsICanEat.push(products[i]);
        }
    }

    expect(productsICanEat.length).toBe(FILL_ME_IN);
  });

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (functional)", function () {

      var productsICanEat = [];

      /* solve using filter() & all() / any() */

      expect(productsICanEat.length).toBe(FILL_ME_IN);
  });

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

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (imperative)", function () {

    var sum = 0;
    for(var i=1; i<1000; i+=1) {
      if (i % 3 === 0 || i % 5 === 0) {
        sum += i;
      }
    }

    expect(sum).toBe(FILL_ME_IN);
  });

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (functional)", function () {

    var sum = FILL_ME_IN;    /* try chaining range() and reduce() */

    expect(233168).toBe(FILL_ME_IN);
  });

  /*********************************************************************************/
   it("should count the ingredient occurrence (imperative)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    for (i = 0; i < products.length; i+=1) {
        for (j = 0; j < products[i].ingredients.length; j+=1) {
            ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
        }
    }

    expect(ingredientCount['mushrooms']).toBe(FILL_ME_IN);
  });

  it("should count the ingredient occurrence (functional)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    /* chain() together map(), flatten() and reduce() */

    expect(ingredientCount['mushrooms']).toBe(FILL_ME_IN);
  });

  /*********************************************************************************/
  /* UNCOMMENT FOR EXTRA CREDIT */
  /*
  it("should find the largest prime factor of a composite number", function () {

  });

  it("should find the largest palindrome made from the product of two 3 digit numbers", function () {

  });

  it("should find the smallest number divisible by each of the numbers 1 to 20", function () {

  });

  it("should find the difference between the sum of the squares and the square of the sums", function () {

  });

  it("should find the 10001st prime", function () {

  });
  */
});
<commit_msg>Javascript Koans Code Change<commit_after>var _; //globals

describe("About Applying What We Have Learnt", function() {

  var products;

  beforeEach(function () {
    products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];
  });

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

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (imperative)", function () {

    var i,j,hasMushrooms, productsICanEat = [];

    for (i = 0; i < products.length; i+=1) {
        if (products[i].containsNuts === false) {                   //find products that don't contain nuts
            hasMushrooms = false;
            for (j = 0; j < products[i].ingredients.length; j+=1) {
               if (products[i].ingredients[j] === "mushrooms") {    //find products that don't contain mushrooms
                  hasMushrooms = true;
               }
            }
            if (!hasMushrooms) productsICanEat.push(products[i]);
        }
    }

    expect(productsICanEat.length).toBe(1);
  });

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (functional)", function () {

      var productsICanEat = [];

      //function that checks if ingredient is not a mushroom
      var ingredientIsNotAMushroom = function(ingredient) {
        return (ingredient !== "mushrooms");
      };

      //function that checks if product has no nuts and no mushrooms
      var productContainsNoNutsAndNoMushrooms = function(product) {
        return (product.containsNuts === false && _(product.ingredients).all(ingredientIsNotAMushroom));
      };

      /* solve using filter() & all() / any() */
      productsICanEat = products.filter(productContainsNoNutsAndNoMushrooms);

      expect(productsICanEat.length).toBe(1);
  });

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

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (imperative)", function () {

    var sum = 0;
    for(var i=1; i<1000; i+=1) {
      if (i % 3 === 0 || i % 5 === 0) { //add 3, 6, 9, 12, etc. and 5, 10, 15, 20, etc. to sum
        sum += i;
      }
    }

    expect(sum).toBe(233168);
  });

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (functional)", function () {

    var sum = _.range(1, 1000).reduce(function(total, currentNumber) {
      return ( (currentNumber % 3 === 0 || currentNumber % 5 === 0) ? (total + currentNumber) : total );
    }, 0);    /* try chaining range() and reduce() */

    expect(233168).toBe(sum);
  });

  /*********************************************************************************/
   it("should count the ingredient occurrence (imperative)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    for (i = 0; i < products.length; i+=1) {
        for (j = 0; j < products[i].ingredients.length; j+=1) {  //calculate count of every ingredient in products array
            ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
        }
    }

    expect(ingredientCount['mushrooms']).toBe(2);
  });

  it("should count the ingredient occurrence (functional)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    //function that returns all of the product's ingredients as an array
    var getProductIngredients = function(product) {
      return product.ingredients;
    };

    //function that increments the passed in object's ingredient counters based on passed in ingredient name
    var countIngredients = function(ingredientCount, currentIngredient) {
      if(ingredientCount[currentIngredient] === undefined)
      {
        ingredientCount[currentIngredient] = 1;
      }
      else
      {
        ++ingredientCount[currentIngredient];
      }

      return ingredientCount;
    };

    /* chain() together map(), flatten() and reduce() */
    ingredientCount = _(products).chain().map(getProductIngredients).flatten().reduce(countIngredients, {}).value();

    expect(ingredientCount['mushrooms']).toBe(2);
  });

  /*********************************************************************************/
  /* UNCOMMENT FOR EXTRA CREDIT */

  it("should find the largest prime factor of a composite number", function () {
    //returns -1 if number is not a composite number
    var findLargestPrimeFactor = function(compositeNumber)
    {
      if(compositeNumber <= 2)
        return -1;

      //keep dividing the current number by all numbers less than it that haven't been checked yet
      var largestPrimeFactor = compositeNumber;
      var i = 2;
      while(largestPrimeFactor > i)
      {
        //the first division gives the largest factor; when it can't be divided into anymore then it will be the largest prime factor
        if(largestPrimeFactor % i === 0)
        {
          largestPrimeFactor /= i;
        }
        else
        {
          ++i;
        }
      }
      return (largestPrimeFactor >= compositeNumber) ? -1 : largestPrimeFactor;
    };

    expect(findLargestPrimeFactor(1)).toBe(-1); //not composite number
    expect(findLargestPrimeFactor(2)).toBe(-1); //not composite number
    expect(findLargestPrimeFactor(7)).toBe(-1); //not composite number
    expect(findLargestPrimeFactor(179)).toBe(-1); //not composite number
    expect(findLargestPrimeFactor(64)).toBe(2);
    expect(findLargestPrimeFactor(75)).toBe(5);
    expect(findLargestPrimeFactor(120)).toBe(5);
    expect(findLargestPrimeFactor(125)).toBe(5);
    expect(findLargestPrimeFactor(358)).toBe(179);
  });

  it("should find the largest palindrome made from the product of two 3 digit numbers", function () {
    //helper function that checks if number is a palindrome
    var isPalindromicNumber = function(number)
    {
      //convert passed in number to string type then compare the original numeric string to its reverse
      //if the original numeric string is equal to its reverse, then it is a palindrome
      var numberAsString = number.toString();
      return (numberAsString == numberAsString.split("").reverse().join(""));
    };

    var findLargestPalindrome = function() {
      var product = 0;
      var largestPalindrome = 0;
      for(var i = 999; i >= 100; --i) //999 to 100 represents all 3 digit numbers
      {
        for(var j = i; j >= 100; --j) //can start at i since j * i doesn't need to be checked because i * j and j * i is the same
        {
          product = i * j;
          if(isPalindromicNumber(product) && product > largestPalindrome) //store largest product that is a palindrome
          {
            largestPalindrome = product;
          }
        }
      }
      return largestPalindrome;
    };

    expect(findLargestPalindrome()).toBe(906609);
  });

  it("should find the smallest number divisible by each of the numbers 1 to 20", function () {
    //helper function that finds the greatest common divisor between two numbers
    var gcd = function(num1, num2) {
      if(num1 === num2 || num2 === 0)
      {
        return num1;
      }
      else if (num1 === 0)
      {
        return num2;
      }
      else
      {
        //to get the gcd, keep getting the gcd between the current and previous remainders until 0
        return gcd(num2, num1 % num2);
      }
    };

    //helper function that finds the least common multiple between two numbers
    var lcm = function(num1, num2) {
      if(num1 === num2)
      {
        return num1;
      }
      else if (num1 === 0 || num2 === 0)
      {
        return 0;
      }
      else
      {
        return ((num1 * num2) / gcd(num1, num2)); //multiply the two numbers and divide by the gcd to get the lcm
      }
    };

    var findLCMofOneToN = function(n) {
      if(n < 1)
        return 0;

      //can get the lcm of 1 to N by getting the lcm between the current number and the lcm of all previous numbers for every number in 1 to N
      var currentLCM = 1;
      for(var i = 2; i <= n; ++i)
      {
        currentLCM = lcm(currentLCM, i);
      }
      return currentLCM;
    };

    expect(findLCMofOneToN(20)).toBe(232792560);
  });

  it("should find the difference between the sum of the squares and the square of the sums", function () {
    //helper function that calculates sum of squares for array input by looping through the array
    var sumOfSquaresForArrayInput = function(arr) {
      return (arr.reduce(
        function(sum, i) {
          return sum + Math.pow(i, 2);
        }, 0));
    };

    //helper function that calculates sum of squares for array input by looping through the array
    var squareOfTheSumsForArrayInput = function(arr) {
      return (Math.pow(
        arr.reduce(
          function(sum, i) {
            return sum + i;
          }, 0),
        2));
    };

    //calculates the difference between the sum of the squares and the square of the sums for array input by looping through the array
    var differenceForArrayInput = function(arr) {
      return Math.abs(sumOfSquaresForArrayInput(arr) - squareOfTheSumsForArrayInput(arr));
    };

    expect(differenceForArrayInput(_.range(1, 21))).toBe(41230);

    //helper function that calculates sum of squares for first n numbers by using formula found here:
    //http://www.trans4mind.com/personal_development/mathematics/series/sumNaturalSquares.htm
    var sumOfSquaresForFirstNnumbers = function(n) {
      return ((n * (n + 1) * (2 * n + 1)) / 6);
    };

    //helper function that calculates square of sums for first n numbers by using formula found here:
    //http://www.mathwords.com/a/arithmetic_series.htm
    var squareOfTheSumsForFirstNnumbers = function(n) {
      return Math.pow((n * (n + 1)) / 2, 2);
    };

    //calculates the difference between the sum of the squares and the square of the sums for first n numbers by using math formulas
    var differenceForFirstNnumbers = function(n) {
      return Math.abs(sumOfSquaresForFirstNnumbers(n) - squareOfTheSumsForFirstNnumbers(n));
    };

    expect(differenceForFirstNnumbers(20)).toBe(41230);
    expect(differenceForArrayInput(_.range(1, 31))).toBe(differenceForFirstNnumbers(30));
  });

  it("should find the 10001st prime", function () {
    //helper function that loops through multiples of i in the passed in array; every multiple marked is not a prime number
    var markCompositeNumbers = function(compositeNumberCheckArray, i, maxNumber) {
      for(var j = i * i ; j < maxNumber; j += i) //can start at i ^ 2 since every composite number up to i ^ 2 will have already been marked
      {
        compositeNumberCheckArray[j - 2] = true; //start array index at 0, so the number 2 is actually represented by index 0
      }
    };

    var findNthPrime = function(n) {
      if(n < 1)
        return 0;

      //max number is a value that shouldn't be changed; it represents approximately how many numbers need to be searched to find the nth prime
      //the formula for how many numbers need to be searched uses a rough approximation formula found here:
      //http://en.wikipedia.org/wiki/Prime_number_theorem#Approximations_for_the_nth_prime_number
      var MAX_NUMBER = (n <= 6) ? 14 : (Math.ceil(n * (Math.log(n) + Math.log(Math.log(n)))));

      //to find the nth prime number, need to count number of primes found
      //a boolean array will be used to indicate if a number is prime or not prime (true = not prime), with the index representing a number
      //since anything that is a multiple of a number is not a prime, can find all nonprimes by finding multiples of primes
      var compositeNumberCheckArray = new Array(MAX_NUMBER);
      var primesFoundCounter = 0;
      for(var i = 2; i < MAX_NUMBER; ++i)
      {
        //skip numbers that aren't prime
        if(compositeNumberCheckArray[i - 2] === true) //start array index at 0, so the number 2 is actually represented by index 0
          continue;

        ++primesFoundCounter; //increment number of primes found

        if(primesFoundCounter === n)
          return i; //i is the nth prime number

        markCompositeNumbers(compositeNumberCheckArray, i, MAX_NUMBER); //mark all multiples of the current prime number as nonprime
      }

      return 0; //should not get here
    };

    expect(findNthPrime(1001)).toBe(7927);
  });
});<|endoftext|>


<commit_before>var _; //globals

describe("About Applying What We Have Learnt", function() {

  var products;

  beforeEach(function () {
    products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];
  });

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

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (imperative)", function () {

    var i,j,hasMushrooms, productsICanEat = [];

    for (i = 0; i < products.length; i+=1) {
        if (products[i].containsNuts === false) {
            hasMushrooms = false;
            for (j = 0; j < products[i].ingredients.length; j+=1) {
               if (products[i].ingredients[j] === "mushrooms") {
                  hasMushrooms = true;
               }
            }
            if (!hasMushrooms) productsICanEat.push(products[i]);
        }
    }

    expect(productsICanEat.length).toBe(FILL_ME_IN);
  });

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (functional)", function () {

      var productsICanEat = [];

      /* solve using filter() & all() / any() */

      expect(productsICanEat.length).toBe(FILL_ME_IN);
  });

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

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (imperative)", function () {

    var sum = 0;
    for(var i=1; i<1000; i+=1) {
      if (i % 3 === 0 || i % 5 === 0) {
        sum += i;
      }
    }

    expect(sum).toBe(FILL_ME_IN);
  });

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (functional)", function () {

    var sum = FILL_ME_IN;    /* try chaining range() and reduce() */

    expect(233168).toBe(FILL_ME_IN);
  });

  /*********************************************************************************/
   it("should count the ingredient occurrence (imperative)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    for (i = 0; i < products.length; i+=1) {
        for (j = 0; j < products[i].ingredients.length; j+=1) {
            ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
        }
    }

    expect(ingredientCount['mushrooms']).toBe(FILL_ME_IN);
  });

  it("should count the ingredient occurrence (functional)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    /* chain() together map(), flatten() and reduce() */

    expect(ingredientCount['mushrooms']).toBe(FILL_ME_IN);
  });

  /*********************************************************************************/
  /* UNCOMMENT FOR EXTRA CREDIT */
  /*
  it("should find the largest prime factor of a composite number", function () {

  });

  it("should find the largest palindrome made from the product of two 3 digit numbers", function () {

  });

  it("should find the smallest number divisible by each of the numbers 1 to 20", function () {

  });

  it("should find the difference between the sum of the squares and the square of the sums", function () {

  });

  it("should find the 10001st prime", function () {

  });
  */
});
<commit_msg>start aboutApplyingWhatWeHaveLearnt<commit_after>var _; //globals

describe("About Applying What We Have Learnt", function() {

  var products;

  beforeEach(function () {
    products = [
       { name: "Sonoma", ingredients: ["artichoke", "sundried tomatoes", "mushrooms"], containsNuts: false },
       { name: "Pizza Primavera", ingredients: ["roma", "sundried tomatoes", "goats cheese", "rosemary"], containsNuts: false },
       { name: "South Of The Border", ingredients: ["black beans", "jalapenos", "mushrooms"], containsNuts: false },
       { name: "Blue Moon", ingredients: ["blue cheese", "garlic", "walnuts"], containsNuts: true },
       { name: "Taste Of Athens", ingredients: ["spinach", "kalamata olives", "sesame seeds"], containsNuts: true }
    ];
  });

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

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (imperative)", function () {

    var i,j,hasMushrooms, productsICanEat = [];

    for (i = 0; i < products.length; i+=1) {
        if (products[i].containsNuts === false) {
            hasMushrooms = false;
            for (j = 0; j < products[i].ingredients.length; j+=1) {
               if (products[i].ingredients[j] === "mushrooms") {
                  hasMushrooms = true;
               }
            }
            if (!hasMushrooms) productsICanEat.push(products[i]);
        }
    }

    expect(productsICanEat.length).toBe(1);
  });

  it("given I'm allergic to nuts and hate mushrooms, it should find a pizza I can eat (functional)", function () {

      var productsICanEat = [];

      /* solve using filter() & all() / any() */

      expect(productsICanEat.length).toBe(FILL_ME_IN);
  });

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

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (imperative)", function () {

    var sum = 0;
    for(var i=1; i<1000; i+=1) {
      if (i % 3 === 0 || i % 5 === 0) {
        sum += i;
      }
    }

    expect(sum).toBe(FILL_ME_IN);
  });

  it("should add all the natural numbers below 1000 that are multiples of 3 or 5 (functional)", function () {

    var sum = FILL_ME_IN;    /* try chaining range() and reduce() */

    expect(233168).toBe(FILL_ME_IN);
  });

  /*********************************************************************************/
   it("should count the ingredient occurrence (imperative)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    for (i = 0; i < products.length; i+=1) {
        for (j = 0; j < products[i].ingredients.length; j+=1) {
            ingredientCount[products[i].ingredients[j]] = (ingredientCount[products[i].ingredients[j]] || 0) + 1;
        }
    }

    expect(ingredientCount['mushrooms']).toBe(FILL_ME_IN);
  });

  it("should count the ingredient occurrence (functional)", function () {
    var ingredientCount = { "{ingredient name}": 0 };

    /* chain() together map(), flatten() and reduce() */

    expect(ingredientCount['mushrooms']).toBe(FILL_ME_IN);
  });

  /*********************************************************************************/
  /* UNCOMMENT FOR EXTRA CREDIT */
  /*
  it("should find the largest prime factor of a composite number", function () {

  });

  it("should find the largest palindrome made from the product of two 3 digit numbers", function () {

  });

  it("should find the smallest number divisible by each of the numbers 1 to 20", function () {

  });

  it("should find the difference between the sum of the squares and the square of the sums", function () {

  });

  it("should find the 10001st prime", function () {

  });
  */
});
<|endoftext|>


<commit_before>/**
 * @author bhouston / http://exocortex.com/
 */

THREE.ColorConverter = {

	fromRGB: function ( color, r, g, b ) {

		return color.setRGB( r, g, b );

	},

	fromHex: function ( color, hex ) {

		return color.setHex( hex );

	},

	toHex: function ( color ) {

		return color.getHex();

	},

	toHexString: function ( color ) {

		return color.getHexString( color );

	},

	fromHSL: function ( color, h, s, l ) {

		return color.setHSL( h, s, l );
	},

	toHSL: function ( color ) {

		return color.getHSL( color );

	},

	fromHSV: function ( color, h, s, v ) {

		// https://gist.github.com/xpansive/1337890#file-index-js
		return color.setHSL( h, ( s * v ) / ( ( h = ( 2 - s ) * v ) < 1 ? h : ( 2 - h ) ), h * 0.5 );

	},

	toHSV: function () {

		var hsv = { h: 0, s: 0, v: 0 };

		return function( color ) {

			var hsl = color.getHSL();

			// based on https://gist.github.com/xpansive/1337890#file-index-js
			hsl.s *= ( hsl.l < 0.5 ) ? hsl.l : ( 1 - hsl.l );

			hsv.h = hsl.h;
			hsv.s = 2 * hsl.s / ( hsl.l + hsl.s );
			hsv.v = hsl.l + hsl.s;

			return hsv;

		}

	}(),

	fromStyle: function ( color, style ) {

		return color.setStyle( style );

	},

	toStyle: function ( color ) {

		return color.getStyle( color );

	}

};<commit_msg>remote flyweight pattern in ColorConverter.toHSV per @zz85's suggestion here: https://github.com/mrdoob/three.js/pull/3109#issuecomment-13923276<commit_after>/**
 * @author bhouston / http://exocortex.com/
 */

THREE.ColorConverter = {

	fromRGB: function ( color, r, g, b ) {

		return color.setRGB( r, g, b );

	},

	fromHex: function ( color, hex ) {

		return color.setHex( hex );

	},

	toHex: function ( color ) {

		return color.getHex();

	},

	toHexString: function ( color ) {

		return color.getHexString( color );

	},

	fromHSL: function ( color, h, s, l ) {

		return color.setHSL( h, s, l );
	},

	toHSL: function ( color ) {

		return color.getHSL( color );

	},

	fromHSV: function ( color, h, s, v ) {

		// https://gist.github.com/xpansive/1337890#file-index-js
		return color.setHSL( h, ( s * v ) / ( ( h = ( 2 - s ) * v ) < 1 ? h : ( 2 - h ) ), h * 0.5 );

	},

	toHSV: function( color ) {

		var hsl = color.getHSL();

		// based on https://gist.github.com/xpansive/1337890#file-index-js
		hsl.s *= ( hsl.l < 0.5 ) ? hsl.l : ( 1 - hsl.l );

		return {
			h: hsl.h,
			s: 2 * hsl.s / ( hsl.l + hsl.s ),
			v: hsl.l + hsl.s
		};

	},

	fromStyle: function ( color, style ) {

		return color.setStyle( style );

	},

	toStyle: function ( color ) {

		return color.getStyle( color );

	}

};<|endoftext|>


<commit_before>// example handler to handle kinesis stream input

// load environmental variables
require('dotenv').config()

var Worker = require('../../');

exports.handler = function(event, context) {
  console.log('osm-stats-version' + require('./package.json').version);

  event.Records.forEach(function(record) {
      // Kinesis data is base64 encoded so decode here
      var payload = new Buffer(record.kinesis.data, 'base64').toString('utf8');
      console.log('Payload:', payload);
      try {
        var worker = new Worker(function(err, changeset) {
          if (err) console.error(err);
          else console.log(changeset)
        });
        worker.addToDB(JSON.parse(payload));
      } catch (ex) {
        console.log('FAILURE', ex);
      }
  });

  context.succeed("SUCCESS");
};
<commit_msg>updated handler<commit_after>// example handler to handle kinesis stream input

// load environmental variables
require('dotenv').config()

var Worker = require('../../');
var Promise = require('bluebird');

exports.handler = function(event, context) {
  console.log('osm-stats-version' + require('./package.json').version);

  // loop through all records in batch
  console.log('Processing %s records', event.Records.length);

  var worker = new Worker(function(err, changeset) {
    if (err) console.error(err);
    else console.log(changeset)
  });
  Promise.map(event.Records, function (record) {
    var payload = new Buffer(record.kinesis.data, 'base64').toString('utf8');
    console.log('PAYLOAD:', payload);
    return worker.addToDB(JSON.parse(payload))
  }).then(function (result) {
    console.log('SUCCESS:', result);
    return context.succeed('Success');
  }).catch(function (err) {
    console.log('FAILURE: ', err);
   return context.fail('FFailure');
  })
};
<|endoftext|>


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

  var app = angular.module('viewCustom', ['angularLoad']);

  app.run(['$rootScope', '$location', '$window', function ($rootScope, $location, $window) {
    //record GA page view event to new primo tracker GA ID
    $rootScope.$on('$locationChangeSuccess', function (event) {
      //temporarily create a tracker specifically to new Primo
      if ($window.ga) {
        $window.ga(function () {
          $window.ga('create', 'UA-4365437-14', 'search.library.uq.edu.au', 'NewPrimoTracker');
        });
        $window.ga('NewPrimoTracker.send', 'pageview', { location: $location.url() });
      }
    });

  }]);

  app.component('prmTopBarBefore', {
    template: '
<uqlibrary-alerts></uqlibrary-alerts>
' +
      '
<uq-minimal-header show-login-button="false"></uq-minimal-header>
'
  });

  // from https://knowledge.exlibrisgroup.com/Primo/Community_Knowledge/How_to_create_a_%E2%80%98Report_a_Problem%E2%80%99_button_below_the_ViewIt_iframe
  app.component('prmFullViewServiceContainerAfter', {
    bindings: {parentCtrl: '<'},
    controller: function($scope){
      var vm = this;

      vm.targeturl = '';

      var recordId = '';
      if (!!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.search && !!vm.parentCtrl.item.pnx.search.recordid) {
        recordId = encodeURIComponent(vm.parentCtrl.item.pnx.search.recordid);
      }
      if (recordId === '') {
        // from http://stackoverflow.com/questions/11582512/how-to-get-url-parameters-with-javascript/11582513#11582513
        var fieldname = 'docid';
        var temp = encodeURIComponent((new RegExp('[?|&]' + fieldname + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
        if (temp !== null) {
          recordId = temp;
        }
      }

      var recordTitle = '';
      if (recordId !== '' && !!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.search && !!vm.parentCtrl.item.pnx.search.title && !!vm.parentCtrl.item.pnx.search.title[0]) {
        recordTitle = encodeURIComponent(vm.parentCtrl.item.pnx.search.title[0]);
      }
      if (recordTitle === '' && recordId !== '' && !!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.display && !!vm.parentCtrl.item.pnx.display.title && !!vm.parentCtrl.item.pnx.display.title[0]) {
        recordTitle = encodeURIComponent(vm.parentCtrl.item.pnx.display.title[0]);
      }

      var isIE11 = navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > -1;

      // if we are not IE11 and can get a docid and a title - add a button
      if (!isIE11 && recordId !== '' && recordTitle !== '') {
        var crmDomain = 'https://uqcurrent--tst1.custhelp.com'; // we can probably return the live url for all when this is in prod
        if (window.location.hostname === 'search.library.uq.edu.au') {
          crmDomain = 'https://support.my.uq.edu.au';
        }

        vm.targeturl = crmDomain + "/app/library/contact/report_problem/true/incidents.subject/" + recordTitle + "/incidents.c$summary/" + recordId;
      }
      // the button doesnt work in IE11 :( see PT #171563111
    },
    template : '
<getit-link-service>' +
        '<button class="help-button md-button md-primoExplore-theme md-ink-ripple" type="button" data-ng-click="buttonPressed($event)" aria-label="Report a Problem" aria-hidden="false">' +
        'Report a Problem' +
        '</button>' +
        '</getit-link-service>
'
  });

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

  /*In case of CENTRAL_PACKAGE - comment out the below line to replace the other module definition*/

  /*var app = angular.module('centralCustom', ['angularLoad']);*/

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

  /*
    * this is on hold until May, when the newspaper-articles exclusion will apparently move out of the url
    * Problems with this 'lock facets' code
    * it cant remove multiple facets on a subsequent load
    * eg
    * 1. search 'library' on homepage, it loads & locks facets newspaper_articles and reviews
    * 2. return to homepage and search 'books' - only one of 'reviews' and 'newspaper_articles' will be removed
    *
    * Incomplete:
    * - I havent quite got the physical items search working properly yet (&facet=tlevel,include,physical_items)
    * ** the immediate prior version handle tlevel, but is too slow - consider how it is handling tlevel & library, though
    * - and this still needs cleaning up
    *
    * sample searches:
    * https://uq-edu-primo-sb.hosted.exlibrisgroup.com/primo-explore/search?query=any,contains,frogs&tab=61uq_all&search_scope=61UQ_All&sortby=rank&vid=61UQ_DEV&facet=rtype,include,books&facets=locked
    * https://uq-edu-primo-sb.hosted.exlibrisgroup.com/primo-explore/search?query=any,contains,frogs&tab=61uq_all&search_scope=61UQ_All&sortby=rank&vid=61UQ_DEV&facet=rtype,include,media&facets=locked
    * https://uq-edu-primo-sb.hosted.exlibrisgroup.com/primo-explore/search?query=any,contains,frogs&tab=61uq_all&search_scope=61UQ_All&sortby=rank&vid=61UQ_DEV&facet=rtype,exclude,newspaper_articles&facet=rtype,exclude,reviews&offset=0&facets=locked
    *
   */

  // lock facets
  // Based on code supplied by Univerisity of Otago eg. https://otago.hosted.exlibrisgroup.com/primo-explore/search?query=any,contains,frogs&tab=default_tab&search_scope=All&vid=DUNEDIN&facet=rtype,exclude,reviews&offset=0&ref=http:%2F%2Fmarvin.otago.ac.nz
  // add '&facets=locked' tag to any referer to a search results page you want this to happen on
  // app.controller('prmExploreMainAfterController', function($scope) {
  //    setTimeout(function(){
  //      var tag = "facets=locked";
  //      if (!(window.location.search.indexOf(tag) > 0 && window.location.search.indexOf("facet=") > 0)) {
  //        return;
  //      }
  //
  //      waitForElementToDisplay('prm-breadcrumbs div div div button prm-icon > md-icon', 1000);
  //
  //      function waitForElementToDisplay(selector, time) {
  //        if (document.querySelector(selector) !== null) {
  //          // in the case where this is a second search via the homepage, we need to unlock previous locked ones
  //          // this means we need to hard code a list to check, because this page doesnt know what other search options are provided on the home page
  //          // if any future queries add different facets, this list will have to be updated
  //          // key = value in url eg books in facet=rtype,exclude,books
  //          // value = value on aria-label element of button to be clicked
  //          var validFacets = {
  //            'reviews': 'Reviews',
  //            'books': 'Books',
  //            'newspaper_articles': 'Newspaper Articles',
  //            'articles': 'Articles',
  //            'media': 'Video & Audio',
  //            'physical_items': 'Physical items'
  //          };
  //
  //          var queries = window.location.search.split('&');
  //          if (queries.length > 1) {
  //            var facetsInUrl = [];
  //            queries.map(function (e) {
  //              // get the facet in the from all the different types
  //              if (0 === e.indexOf("facet=rtype,exclude,")) {
  //                facetsInUrl.push(e.replace("facet=rtype,exclude,", ''));
  //              } else if (0 === e.indexOf("facet=rtype,include,")) {
  //                facetsInUrl.push(e.replace("facet=rtype,include,", ''));
  //              } else if (0 === e.indexOf("facet=tlevel,exclude,")) {
  //                facetsInUrl.push(e.replace("facet=tlevel,exclude,", ''));
  //              } else if (0 === e.indexOf("facet=tlevel,include,")) {
  //                facetsInUrl.push(e.replace("facet=tlevel,include,", ''));
  //              }
  //            });
  //
  //            // do all the settings first because the later facet removal refreshes the page, losing our tag
  //            var facet, ariaLabel, facetSelector;
  //            for (facet in validFacets) {
  //              if (facetsInUrl.indexOf(facet) !== -1) {
  //                // found in the url - lock it
  //                ariaLabel = 'Make this filter persistent throughout the session ' + validFacets[facet];
  //                facetSelector = document.querySelector('[aria-label="' + ariaLabel + '"]');
  //                if (facetSelector !== null) {
  //                  angular.element(facetSelector).triggerHandler('click');
  //                }
  //              }
  //            }
  //
  //            var thisFacet, ariaLabelLock, facetSelectorLock;
  //            for (facet in validFacets) {
  //              if (facetsInUrl.indexOf(facet) !== -1) {
  //                // skip any that are for this page
  //              } else {
  //                // remove a facet if it was locked from an earlier search
  //                thisFacet = validFacets[facet];
  //                ariaLabel = 'Remove Content type ' + thisFacet;
  //                facetSelector = document.querySelector('[aria-label="' + ariaLabel + '"]'); // the x (remove) button exists to click
  //                ariaLabelLock = 'Cancel persistence ' + thisFacet;
  //                facetSelectorLock = document.querySelector('[aria-label="' + ariaLabelLock + '"]'); // the 'locked' button exists - this is one we should remove
  //                if (facetSelector !== null && facetSelectorLock !== null) {
  //                  angular.element(facetSelector).triggerHandler('click');
  //                  //once this is clicked the page will refresh and wont have our tag on the end :(
  //                  // so only one is ever done :(
  //                }
  //              }
  //            }
  //
  //            return;
  //          }
  //          else {
  //            setTimeout(function () {
  //              waitForElementToDisplay(selector, time);
  //            }, time);
  //          }
  //        }
  //      }
  //    }, 2500);
  //  });
  //
  //  app.component('prmExploreMainAfter', {
  //    bindings: {
  //      parentCtrl: '<'
  //    },
  //    controller: 'prmExploreMainAfterController'
  //  });
  // End lock facets

  app.controller('prmOpenJournalInFullController', [
    function () {
      var vm = this;
      vm.$onInit = function () {
        var resourceType = vm.parentCtrl.result.pnx.display.type[0] || '';
        if (resourceType === 'journal') {
          vm.parentCtrl.isDirectLink = function () { return false; };
        }
      };
    }
  ]);

  app.component('prmOpenJournalInFull', {
    bindings: { parentCtrl: '<' },
    controller: 'prmOpenJournalInFullController'
  });

  app.component('prmSearchResultAvailabilityLineAfter', {
    bindings: { parentCtrl: '<' },
    template: '<prm-open-journal-in-full parent-ctrl="$ctrl.parentCtrl"></prm-open-journal-in-full>'
  });

  function insertScript(url) {
    var script = document.querySelector("script[src*='" + url + "']");
    if (!script) {
      var heads = document.getElementsByTagName("head");
      if (heads && heads.length) {
        var head = heads[0];
        if (head) {
          script = document.createElement('script');
          script.setAttribute('src', url);
          script.setAttribute('type', 'text/javascript');
          head.appendChild(script);
        }
      }
    }
  }

  function insertLink(link) {
    var linkTag = document.querySelector("link[href*='" + link.href + "']");
    if (!linkTag) {
      var heads = document.getElementsByTagName("head");
      if (heads && heads.length) {
        var head = heads[0];
        if (head) {
          linkTag = document.createElement('link');
          linkTag.setAttribute('href', link.href);
          linkTag.setAttribute('rel', link.rel);
          head.appendChild(linkTag);
        }
      }
    }
  }

  // this script should only be called on views that have UQ header showing
  var branchName = '/'; // default. Use for prod
  if (window.location.hostname === 'search.library.uq.edu.au') {
    if (/vid=61UQ_DEV/.test(window.location.href)) {
      branchName = '/primo-prod-dev/';
    }
  } else {
    if (/vid=61UQ_DEV/.test(window.location.href)) {
      branchName = '/primo-sand-box-dev/';
    } else if (/vid=61UQ/.test(window.location.href)) {
      branchName = '/primo-sand-box/';
    }
  }

  var links = [
    { rel: 'import', href: '//assets.library.uq.edu.au' + branchName + 'reusable-components/elements.vulcanized.html' },
    { rel: 'stylesheet', href: '//assets.library.uq.edu.au' + branchName + 'reusable-components/primo2/custom-styles.css' }
  ];
  insertLink(links[0]);
  insertLink(links[1]);

  var scripts = [
    '//assets.library.uq.edu.au' + branchName + 'reusable-components/webcomponentsjs/webcomponents-lite.min.js',
    '//assets.library.uq.edu.au' + branchName + 'reusable-components/resources/preloader.js',
    '//assets.library.uq.edu.au' + branchName + 'reusable-components/primo2/load.js',
  ];
  insertScript(scripts[0]);
  insertScript(scripts[1]);
  insertScript(scripts[2]);

  // Temporarily manually supply the style to hide all the Report A Problem button
  // because they get eleventy-three buttons if they dont have the latest style sheet (Chrome caches it horribly well)
  // This can probably be removed on our next load of work on Primo
  var css = 'div > getit-link-service { display: none; }',
      head = document.head || document.getElementsByTagName('head')[0],
      style = document.createElement('style');
  head.appendChild(style);
  style.setAttribute('type', 'text/css');
  style.appendChild(document.createTextNode(css));
})();
<commit_msg>look in the pnx.control for the recordid where it is a CDI record [PT #171852576]<commit_after>(function () {
  "use strict";

  var app = angular.module('viewCustom', ['angularLoad']);

  app.run(['$rootScope', '$location', '$window', function ($rootScope, $location, $window) {
    //record GA page view event to new primo tracker GA ID
    $rootScope.$on('$locationChangeSuccess', function (event) {
      //temporarily create a tracker specifically to new Primo
      if ($window.ga) {
        $window.ga(function () {
          $window.ga('create', 'UA-4365437-14', 'search.library.uq.edu.au', 'NewPrimoTracker');
        });
        $window.ga('NewPrimoTracker.send', 'pageview', { location: $location.url() });
      }
    });

  }]);

  app.component('prmTopBarBefore', {
    template: '
<uqlibrary-alerts></uqlibrary-alerts>
' +
      '
<uq-minimal-header show-login-button="false"></uq-minimal-header>
'
  });

  // based on https://knowledge.exlibrisgroup.com/Primo/Community_Knowledge/How_to_create_a_%E2%80%98Report_a_Problem%E2%80%99_button_below_the_ViewIt_iframe
  app.component('prmFullViewServiceContainerAfter', {
    bindings: {parentCtrl: '<'},
    controller: function($scope){
      var vm = this;

      vm.targeturl = '';

      var recordId = '';
      // no one knows what the TN actually means (per SVG), but in practice all the CDI records have it on their record id
      if (!!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.control && !!vm.parentCtrl.item.pnx.control.recordid
          && vm.parentCtrl.item.pnx.control.recordid[0] && vm.parentCtrl.item.pnx.control.recordid[0].startsWith('TN')) {
        recordId = encodeURIComponent(vm.parentCtrl.item.pnx.control.recordid);
      }
      if (recordId === '') {
        if (!!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.search && !!vm.parentCtrl.item.pnx.search.recordid) {
          recordId = encodeURIComponent(vm.parentCtrl.item.pnx.search.recordid);
        }
      }
      if (recordId === '') {
        // from http://stackoverflow.com/questions/11582512/how-to-get-url-parameters-with-javascript/11582513#11582513
        var fieldname = 'docid';
        var temp = encodeURIComponent((new RegExp('[?|&]' + fieldname + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
        if (temp !== null) {
          recordId = temp;
        }
      }

      var recordTitle = '';
      if (recordId !== '' && !!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.search && !!vm.parentCtrl.item.pnx.search.title && !!vm.parentCtrl.item.pnx.search.title[0]) {
        recordTitle = encodeURIComponent(vm.parentCtrl.item.pnx.search.title[0]);
      }
      if (recordTitle === '' && recordId !== '' && !!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.display && !!vm.parentCtrl.item.pnx.display.title && !!vm.parentCtrl.item.pnx.display.title[0]) {
        recordTitle = encodeURIComponent(vm.parentCtrl.item.pnx.display.title[0]);
      }

      var isIE11 = navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > -1;

      // if we are not IE11 and can get a docid and a title - add a button
      if (!isIE11 && recordId !== '' && recordTitle !== '') {
        var crmDomain = 'https://uqcurrent--tst1.custhelp.com'; // we can probably return the live url for all when this is in prod
        if (window.location.hostname === 'search.library.uq.edu.au') {
          crmDomain = 'https://support.my.uq.edu.au';
        }

        vm.targeturl = crmDomain + "/app/library/contact/report_problem/true/incidents.subject/" + recordTitle + "/incidents.c$summary/" + recordId;
      }
      // the button doesnt work in IE11 :( see PT #171563111
    },
    template : '
<getit-link-service>' +
        '<button class="help-button md-button md-primoExplore-theme md-ink-ripple" type="button" data-ng-click="buttonPressed($event)" aria-label="Report a Problem" aria-hidden="false">' +
        'Report a Problem' +
        '</button>' +
        '</getit-link-service>
'
  });

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

  /*In case of CENTRAL_PACKAGE - comment out the below line to replace the other module definition*/

  /*var app = angular.module('centralCustom', ['angularLoad']);*/

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

  /*
    * this is on hold until May, when the newspaper-articles exclusion will apparently move out of the url
    * Problems with this 'lock facets' code
    * it cant remove multiple facets on a subsequent load
    * eg
    * 1. search 'library' on homepage, it loads & locks facets newspaper_articles and reviews
    * 2. return to homepage and search 'books' - only one of 'reviews' and 'newspaper_articles' will be removed
    *
    * Incomplete:
    * - I havent quite got the physical items search working properly yet (&facet=tlevel,include,physical_items)
    * ** the immediate prior version handle tlevel, but is too slow - consider how it is handling tlevel & library, though
    * - and this still needs cleaning up
    *
    * sample searches:
    * https://uq-edu-primo-sb.hosted.exlibrisgroup.com/primo-explore/search?query=any,contains,frogs&tab=61uq_all&search_scope=61UQ_All&sortby=rank&vid=61UQ_DEV&facet=rtype,include,books&facets=locked
    * https://uq-edu-primo-sb.hosted.exlibrisgroup.com/primo-explore/search?query=any,contains,frogs&tab=61uq_all&search_scope=61UQ_All&sortby=rank&vid=61UQ_DEV&facet=rtype,include,media&facets=locked
    * https://uq-edu-primo-sb.hosted.exlibrisgroup.com/primo-explore/search?query=any,contains,frogs&tab=61uq_all&search_scope=61UQ_All&sortby=rank&vid=61UQ_DEV&facet=rtype,exclude,newspaper_articles&facet=rtype,exclude,reviews&offset=0&facets=locked
    *
   */

  // lock facets
  // Based on code supplied by Univerisity of Otago eg. https://otago.hosted.exlibrisgroup.com/primo-explore/search?query=any,contains,frogs&tab=default_tab&search_scope=All&vid=DUNEDIN&facet=rtype,exclude,reviews&offset=0&ref=http:%2F%2Fmarvin.otago.ac.nz
  // add '&facets=locked' tag to any referer to a search results page you want this to happen on
  // app.controller('prmExploreMainAfterController', function($scope) {
  //    setTimeout(function(){
  //      var tag = "facets=locked";
  //      if (!(window.location.search.indexOf(tag) > 0 && window.location.search.indexOf("facet=") > 0)) {
  //        return;
  //      }
  //
  //      waitForElementToDisplay('prm-breadcrumbs div div div button prm-icon > md-icon', 1000);
  //
  //      function waitForElementToDisplay(selector, time) {
  //        if (document.querySelector(selector) !== null) {
  //          // in the case where this is a second search via the homepage, we need to unlock previous locked ones
  //          // this means we need to hard code a list to check, because this page doesnt know what other search options are provided on the home page
  //          // if any future queries add different facets, this list will have to be updated
  //          // key = value in url eg books in facet=rtype,exclude,books
  //          // value = value on aria-label element of button to be clicked
  //          var validFacets = {
  //            'reviews': 'Reviews',
  //            'books': 'Books',
  //            'newspaper_articles': 'Newspaper Articles',
  //            'articles': 'Articles',
  //            'media': 'Video & Audio',
  //            'physical_items': 'Physical items'
  //          };
  //
  //          var queries = window.location.search.split('&');
  //          if (queries.length > 1) {
  //            var facetsInUrl = [];
  //            queries.map(function (e) {
  //              // get the facet in the from all the different types
  //              if (0 === e.indexOf("facet=rtype,exclude,")) {
  //                facetsInUrl.push(e.replace("facet=rtype,exclude,", ''));
  //              } else if (0 === e.indexOf("facet=rtype,include,")) {
  //                facetsInUrl.push(e.replace("facet=rtype,include,", ''));
  //              } else if (0 === e.indexOf("facet=tlevel,exclude,")) {
  //                facetsInUrl.push(e.replace("facet=tlevel,exclude,", ''));
  //              } else if (0 === e.indexOf("facet=tlevel,include,")) {
  //                facetsInUrl.push(e.replace("facet=tlevel,include,", ''));
  //              }
  //            });
  //
  //            // do all the settings first because the later facet removal refreshes the page, losing our tag
  //            var facet, ariaLabel, facetSelector;
  //            for (facet in validFacets) {
  //              if (facetsInUrl.indexOf(facet) !== -1) {
  //                // found in the url - lock it
  //                ariaLabel = 'Make this filter persistent throughout the session ' + validFacets[facet];
  //                facetSelector = document.querySelector('[aria-label="' + ariaLabel + '"]');
  //                if (facetSelector !== null) {
  //                  angular.element(facetSelector).triggerHandler('click');
  //                }
  //              }
  //            }
  //
  //            var thisFacet, ariaLabelLock, facetSelectorLock;
  //            for (facet in validFacets) {
  //              if (facetsInUrl.indexOf(facet) !== -1) {
  //                // skip any that are for this page
  //              } else {
  //                // remove a facet if it was locked from an earlier search
  //                thisFacet = validFacets[facet];
  //                ariaLabel = 'Remove Content type ' + thisFacet;
  //                facetSelector = document.querySelector('[aria-label="' + ariaLabel + '"]'); // the x (remove) button exists to click
  //                ariaLabelLock = 'Cancel persistence ' + thisFacet;
  //                facetSelectorLock = document.querySelector('[aria-label="' + ariaLabelLock + '"]'); // the 'locked' button exists - this is one we should remove
  //                if (facetSelector !== null && facetSelectorLock !== null) {
  //                  angular.element(facetSelector).triggerHandler('click');
  //                  //once this is clicked the page will refresh and wont have our tag on the end :(
  //                  // so only one is ever done :(
  //                }
  //              }
  //            }
  //
  //            return;
  //          }
  //          else {
  //            setTimeout(function () {
  //              waitForElementToDisplay(selector, time);
  //            }, time);
  //          }
  //        }
  //      }
  //    }, 2500);
  //  });
  //
  //  app.component('prmExploreMainAfter', {
  //    bindings: {
  //      parentCtrl: '<'
  //    },
  //    controller: 'prmExploreMainAfterController'
  //  });
  // End lock facets

  app.controller('prmOpenJournalInFullController', [
    function () {
      var vm = this;
      vm.$onInit = function () {
        var resourceType = vm.parentCtrl.result.pnx.display.type[0] || '';
        if (resourceType === 'journal') {
          vm.parentCtrl.isDirectLink = function () { return false; };
        }
      };
    }
  ]);

  app.component('prmOpenJournalInFull', {
    bindings: { parentCtrl: '<' },
    controller: 'prmOpenJournalInFullController'
  });

  app.component('prmSearchResultAvailabilityLineAfter', {
    bindings: { parentCtrl: '<' },
    template: '<prm-open-journal-in-full parent-ctrl="$ctrl.parentCtrl"></prm-open-journal-in-full>'
  });

  function insertScript(url) {
    var script = document.querySelector("script[src*='" + url + "']");
    if (!script) {
      var heads = document.getElementsByTagName("head");
      if (heads && heads.length) {
        var head = heads[0];
        if (head) {
          script = document.createElement('script');
          script.setAttribute('src', url);
          script.setAttribute('type', 'text/javascript');
          head.appendChild(script);
        }
      }
    }
  }

  function insertLink(link) {
    var linkTag = document.querySelector("link[href*='" + link.href + "']");
    if (!linkTag) {
      var heads = document.getElementsByTagName("head");
      if (heads && heads.length) {
        var head = heads[0];
        if (head) {
          linkTag = document.createElement('link');
          linkTag.setAttribute('href', link.href);
          linkTag.setAttribute('rel', link.rel);
          head.appendChild(linkTag);
        }
      }
    }
  }

  // this script should only be called on views that have UQ header showing
  var branchName = '/'; // default. Use for prod
  if (window.location.hostname === 'search.library.uq.edu.au') {
    if (/vid=61UQ_DEV/.test(window.location.href)) {
      branchName = '/primo-prod-dev/';
    }
  } else {
    if (/vid=61UQ_DEV/.test(window.location.href)) {
      branchName = '/primo-sand-box-dev/';
    } else if (/vid=61UQ/.test(window.location.href)) {
      branchName = '/primo-sand-box/';
    }
  }

  var links = [
    { rel: 'import', href: '//assets.library.uq.edu.au' + branchName + 'reusable-components/elements.vulcanized.html' },
    { rel: 'stylesheet', href: '//assets.library.uq.edu.au' + branchName + 'reusable-components/primo2/custom-styles.css' }
  ];
  insertLink(links[0]);
  insertLink(links[1]);

  var scripts = [
    '//assets.library.uq.edu.au' + branchName + 'reusable-components/webcomponentsjs/webcomponents-lite.min.js',
    '//assets.library.uq.edu.au' + branchName + 'reusable-components/resources/preloader.js',
    '//assets.library.uq.edu.au' + branchName + 'reusable-components/primo2/load.js',
  ];
  insertScript(scripts[0]);
  insertScript(scripts[1]);
  insertScript(scripts[2]);

  // Temporarily manually supply the style to hide all the Report A Problem button
  // because they get eleventy-three buttons if they dont have the latest style sheet (Chrome caches it horribly well)
  // This can probably be removed on our next load of work on Primo
  var css = 'div > getit-link-service { display: none; }',
      head = document.head || document.getElementsByTagName('head')[0],
      style = document.createElement('style');
  head.appendChild(style);
  style.setAttribute('type', 'text/css');
  style.appendChild(document.createTextNode(css));
})();
<|endoftext|>


<commit_before>var JIVOO = (function(parent, $, Cookies) {
  var my = parent.devbar = parent.devbar || {};

  var tools = [];

  var toolQueue = [];

  var $devbar = null;
  var $tools = null;
  var $more = null;
  var $moreMenu = null;

  var minimumWidth = null;

  var toolZIndex = 0;

  var stop = false;
  $(window).scroll(function() {
    stop = true;
  });

  var confGet = function(key, defaultValue) {
    var val = Cookies.get('jivoo-devbar-' + key);
    if (val === undefined)
      return defaultValue;
    return val;
  };

  var confSet = function(key, value) {
    Cookies.set('jivoo-devbar-' + key, value, { expires: 365, path: '/' });
  }

  function Tool(id, name, createContent) {
    this.id = id;
    this.name = name;
    this.createContent = createContent;
    this.$frame = null;
    this.$menuItem = null;
  }
  Tool.prototype.confGet = function(key, defaultValue) {
    return confGet(this.id + '-' + key, defaultValue);
  };
  Tool.prototype.confSet = function(key, value) {
    return confSet(this.id + '-' + key, value);
  };
  Tool.prototype.loadState = function() {
    if (!this.$frame)
      throw 'Frame not initialized!';
    var x = this.confGet('x', 0);
    var y = this.confGet('y', 0);
    var width = this.confGet('width', this.$frame.width());
    width = Math.max(width, 100);
    width = Math.min(width, $(window).width());
    this.$frame.width(width);
    var height = this.confGet('height', this.$frame.height());
    height = Math.max(height, 100);
    height = Math.min(height, $(window).height());
    this.$frame.height(height);
    x = Math.max(x, 0);
    y = Math.max(y, 0);
    x = Math.min(x, $(window).width() - this.$frame.width());
    y = Math.min(y, $(window).height() - this.$frame.height());
    this.$frame.css({top: y, left: x});
  };
  Tool.prototype.saveState = function() {
    if (!this.$frame)
      throw 'Frame not initialized!';
    var hidden = !this.$frame.is(':visible');
    this.confSet('x', parseInt(this.$frame.css('left')));
    this.confSet('y', parseInt(this.$frame.css('top')));
    this.confSet('width', this.$frame.width());
    this.confSet('height', this.$frame.height());
    this.confSet('open', this.$frame.is(':visible'));
  };
  Tool.prototype.createMenuItem = function() {
    this.$menuItem = $('
');
    var $link = $('');
    $link.text(this.name);
    this.$menuItem.append($link);
    var tool = this;
    this.$menuItem.click(function() {
      tool.toggle();
      return false;
    });
    if (this.confGet('open', 'false') !== 'false') {
      this.open();
    }
    return this.$menuItem;
  };
  Tool.prototype.createFrame = function() {
    var $frame = $('
');
    var $title = $('
');
    var $close = $('
X
');
    var $content = $('
');
    var showFrame = this.createContent($content, $frame);
    if (showFrame === false) {
      this.confSet('open', 'false');
      return false;
    }
    this.$frame = $frame;
    this.loadState();
    this.saveState();
    $title.html(this.name);
    $frame.append($close).append($title).append($content);
    var tool = this;
    $frame.draggable({
      scroll: false,
      containment: 'window',
      snap: true,
      snapMode: 'outer',
      handle: '.jivoo-frame-title',
      start: function(event, ui) {
        stop = false;
      },
      drag: function(event, ui) {
        if (stop) {
          stop = false;
          return false;
        }
      },
      stop: function(event, ui) {
        tool.saveState();
      }
    });
    $frame.mousedown(function(event) {
      tool.toTop();
    });
    $frame.resizable({
      containment: 'document',
      handles: 'all',
      stop: function(event, ui) {
        tool.saveState();
      }
    });
    $frame.hide();
    $close.click(function() {
      tool.close();
    });
    $('body').append($frame);
    return true;
  };
  Tool.prototype.open = function() {
    if (!this.$frame && !this.createFrame())
      return;
    this.$frame.show();
    this.toTop();
    this.saveState();
  };
  Tool.prototype.close = function() {
    if (!this.$frame)
      return;
    this.$frame.hide();
    this.saveState();
  };
  Tool.prototype.toggle = function() {
    if (!this.$frame && !this.createFrame())
      return;
    this.$frame.toggle();
    this.toTop();
    this.saveState();
  };
  Tool.prototype.toTop = function() {
    if (!this.$frame)
      return;
    this.$frame.css('zIndex', toolZIndex++);
  };

  var rearrangeTools = function() {
    $more.hide();
    $moreMenu.children().remove();
    $tools.children().each(function() {
      var x2 = $(this).position().left + $(this).width();
      if (x2 > $devbar.width()) {
        $(this).css('visibility', 'hidden');
        $more.show();
        $(this).clone(true).css('visibility', 'visible').prependTo($moreMenu);
      }
      else {
        $(this).css('visibility', 'visible');
      }
    });
  };

  var updateTools = function() {
    if (!$devbar)
      return;
    while (toolQueue.length > 0) {
      var tool = toolQueue.shift();
      var $menuItem = tool.createMenuItem();
      $tools.append($menuItem);
      tools.push(tool);
    }
    rearrangeTools();
  };

  my.addTool = function(id, name, contentFunction) {
    var tool = new Tool(id, name, contentFunction);
    toolQueue.push(tool);
    updateTools();
    return tool;
  };

  my.addAjaxTool = function(id, name, url) {
    return this.addTool(id, name, function($content) {
      $content.html('loading...');
      $.ajax({
        url: url,
        type: 'GET',
        dataType: 'html',
        success: function(data) {
          $content.html(data)
        },
        error: function(xhr, status, error) {
          $content.text(status + ': ' + error);
        }
      });
      return true;
    });
  };

  my.addLinkTool = function(id, name, url) {
    return this.addTool(id, name, function($content) {
      location.href = url;
      return false;
    });
  };

  var loadState = function() {
    if (!$devbar)
      throw 'Jivoo Devbar not initialized!';
    var x = confGet('x', 0);
    var y = confGet('y', 0);
    var width = confGet('width', $devbar.width());
    width = Math.max(width, minimumWidth);
    width = Math.min(width, $(window).width());
    $devbar.width(width);
    x = Math.max(x, 0);
    y = Math.max(y, 0);
    x = Math.min(x, $(window).width() - $devbar.width());
    y = Math.min(y, $(window).height() - $devbar.height());
    $devbar.css({top: y, left: x});
  };

  var saveState = function() {
    if (!$devbar)
      throw 'Jivoo Devbar not initialized!';
    confSet('x', $devbar.position().left);
    confSet('y', $devbar.position().top);
    confSet('width', $devbar.width());
    rearrangeTools();
  };

  my.toTop = function() {
    var zmax = 0;
    $('*').each(function() {
      var cur = parseInt($(this).css('z-index'));
      zmax = cur > zmax ? cur : zmax;
    });
    $devbar.css('z-index', zmax + 1);
    toolZIndex = zmax + 2;
  };

  my.showMoreMenu = function() {
    var xf = ($more.offset().left - $(window).scrollLeft()) / $(window).width();
    var yf = ($more.offset().top - $(window).scrollTop()) / $(window).height();
    $moreMenu.css({top: '', left: '', right: '', bottom: ''});
    if (xf < 0.5) {
      if (yf < 0.5)
        $moreMenu.css({top: '0', left: '100%'}); // top left
      else
        $moreMenu.css({bottom: '0', left: '100%'}); // bottom left
    }
    else {
      if (yf < 0.5)
        $moreMenu.css({top: '100%', right: '0'}); // top right
      else
        $moreMenu.css({bottom: '100%', right: '0'}); // bottom right
    }
    $moreMenu.show();
    var buttonPos = $more.position();
    $(document).one('click',function(){
      $moreMenu.hide();
    });
    return false;
  };

  my.hideMoreMenu = function() {
    $moreMenu.hide();
  };

  $(function() {
    $devbar = $('#jivoo-devbar');
    $tools = $devbar.children('.jivoo-devbar-tools');
    $more = $devbar.children('.jivoo-devbar-more');
    $more.hide();
    $moreMenu = $devbar.children('.jivoo-devbar-tools-more');
    $moreMenu.hide();

    var rightHandleWidth = $more.outerWidth() + $devbar.children('.ui-resizable-handle').outerWidth();
    minimumWidth = $devbar.children('.jivoo-devbar-handle').outerWidth() + rightHandleWidth;

    my.toTop();
    loadState();
    saveState();

    updateTools();

    $devbar.draggable({
      scroll: false,
      containment: 'window',
      handle: '.jivoo-devbar-handle',
      start: function(event, ui) {
        stop = false;
      },
      drag: function(event, ui) {
        if (stop) {
          stop = false;
          return false;
        }
      },
      stop: function(event, ui) {
        saveState();
      }
    });
    $(window).resize(function() {
      if ($devbar.width() > $(window).width())
        $devbar.width($(window).width());
      pos = $devbar.position();
      x = Math.min(pos.left, $(window).width() - $devbar.width());
      y = Math.min(pos.top, $(window).height() - $devbar.height());
      $devbar.css({top: y, left: x});
      saveState();
    });
    $devbar.resizable({
      handles: { e: '.ui-resizable-handle' },
      containment: 'document',
      minWidth: minimumWidth
    });

    $more.click(my.showMoreMenu);
  });

  return parent;
}(JIVOO || {}, jQuery, Cookies))

$(function() {
  var logTool = JIVOO.devbar.addTool('jivoo-log', 'Log', function ($content) {
    var $log = $('
');
    jivooLog.forEach(function(entry) {
      var $entry = $('

');
      var message = entry.message;
      if (entry.file) {
        message += ' in ' + entry.file + ' on line ' + entry.line + '';
      }
      $entry.html(message);
      switch (entry.type) {
      case 1: // QUERY
        console.debug(message);
        $entry.css('color', '#999');
        break;
      case 2: // DEBUG
        console.debug(message);
        $entry.css('color', '#99f');
        break;
      case 2: // NOTICE
        console.log(message);
        $entry.css('color', '#f00');
        break;
      case 4: // WARNING
        console.warn(message);
        $entry.css('color', '#f90');
        break;
      case 8: // ERROR
        console.error(message);
        $entry.css('color', '#f00');
        break;
      }
      $log.append($entry);
    });
    $content.append($log);
  });

  logTool.$menuItem.children('a').append($('').text(jivooLog.length));
});<commit_msg>Reposition frames on window resize.<commit_after>var JIVOO = (function(parent, $, Cookies) {
  var my = parent.devbar = parent.devbar || {};

  var tools = [];

  var toolQueue = [];

  var $devbar = null;
  var $tools = null;
  var $more = null;
  var $moreMenu = null;

  var minimumWidth = null;

  var toolZIndex = 0;

  var stop = false;
  $(window).scroll(function() {
    stop = true;
  });

  var confGet = function(key, defaultValue) {
    var val = Cookies.get('jivoo-devbar-' + key);
    if (val === undefined)
      return defaultValue;
    return val;
  };

  var confSet = function(key, value) {
    Cookies.set('jivoo-devbar-' + key, value, { expires: 365, path: '/' });
  }

  function Tool(id, name, createContent) {
    this.id = id;
    this.name = name;
    this.createContent = createContent;
    this.$frame = null;
    this.$menuItem = null;
  }
  Tool.prototype.confGet = function(key, defaultValue) {
    return confGet(this.id + '-' + key, defaultValue);
  };
  Tool.prototype.confSet = function(key, value) {
    return confSet(this.id + '-' + key, value);
  };
  Tool.prototype.loadState = function() {
    if (!this.$frame)
      throw 'Frame not initialized!';
    var x = this.confGet('x', 0);
    var y = this.confGet('y', 0);
    var width = this.confGet('width', this.$frame.width());
    width = Math.max(width, 100);
    width = Math.min(width, $(window).width());
    this.$frame.width(width);
    var height = this.confGet('height', this.$frame.height());
    height = Math.max(height, 100);
    height = Math.min(height, $(window).height());
    this.$frame.height(height);
    x = Math.max(x, 0);
    y = Math.max(y, 0);
    x = Math.min(x, $(window).width() - this.$frame.width());
    y = Math.min(y, $(window).height() - this.$frame.height());
    this.$frame.css({top: y, left: x});
  };
  Tool.prototype.saveState = function() {
    if (!this.$frame)
      throw 'Frame not initialized!';
    var hidden = !this.$frame.is(':visible');
    this.confSet('x', parseInt(this.$frame.css('left')));
    this.confSet('y', parseInt(this.$frame.css('top')));
    this.confSet('width', this.$frame.width());
    this.confSet('height', this.$frame.height());
    this.confSet('open', this.$frame.is(':visible'));
  };
  Tool.prototype.createMenuItem = function() {
    this.$menuItem = $('
');
    var $link = $('');
    $link.text(this.name);
    this.$menuItem.append($link);
    var tool = this;
    this.$menuItem.click(function() {
      tool.toggle();
      return false;
    });
    if (this.confGet('open', 'false') !== 'false') {
      this.open();
    }
    return this.$menuItem;
  };
  Tool.prototype.createFrame = function() {
    var $frame = $('
');
    var $title = $('
');
    var $close = $('
X
');
    var $content = $('
');
    var showFrame = this.createContent($content, $frame);
    if (showFrame === false) {
      this.confSet('open', 'false');
      return false;
    }
    this.$frame = $frame;
    this.loadState();
    this.saveState();
    $title.html(this.name);
    $frame.append($close).append($title).append($content);
    var tool = this;
    $frame.draggable({
      scroll: false,
      containment: 'window',
      snap: true,
      snapMode: 'outer',
      handle: '.jivoo-frame-title',
      start: function(event, ui) {
        stop = false;
      },
      drag: function(event, ui) {
        if (stop) {
          stop = false;
          return false;
        }
      },
      stop: function(event, ui) {
        tool.saveState();
      }
    });
    $frame.mousedown(function(event) {
      tool.toTop();
    });
    $frame.resizable({
      containment: 'document',
      handles: 'all',
      stop: function(event, ui) {
        tool.saveState();
      }
    });
    $frame.hide();
    $close.click(function() {
      tool.close();
    });
    $(window).resize(function() {
      if ($frame.width() > $(window).width())
        $frame.width($(window).width());
      var pos = $frame.position();
      var x = Math.min(pos.left, $(window).width() - $frame.width());
      var y = Math.min(pos.top, $(window).height() - $frame.height());
      $frame.css({top: y, left: x});
      saveState();
    });
    $('body').append($frame);
    return true;
  };
  Tool.prototype.open = function() {
    if (!this.$frame && !this.createFrame())
      return;
    this.$frame.show();
    this.toTop();
    this.saveState();
  };
  Tool.prototype.close = function() {
    if (!this.$frame)
      return;
    this.$frame.hide();
    this.saveState();
  };
  Tool.prototype.toggle = function() {
    if (!this.$frame && !this.createFrame())
      return;
    this.$frame.toggle();
    this.toTop();
    this.saveState();
  };
  Tool.prototype.toTop = function() {
    if (!this.$frame)
      return;
    this.$frame.css('zIndex', toolZIndex++);
  };

  var rearrangeTools = function() {
    $more.hide();
    $moreMenu.children().remove();
    $tools.children().each(function() {
      var x2 = $(this).position().left + $(this).width();
      if (x2 > $devbar.width()) {
        $(this).css('visibility', 'hidden');
        $more.show();
        $(this).clone(true).css('visibility', 'visible').prependTo($moreMenu);
      }
      else {
        $(this).css('visibility', 'visible');
      }
    });
  };

  var updateTools = function() {
    if (!$devbar)
      return;
    while (toolQueue.length > 0) {
      var tool = toolQueue.shift();
      var $menuItem = tool.createMenuItem();
      $tools.append($menuItem);
      tools.push(tool);
    }
    rearrangeTools();
  };

  my.addTool = function(id, name, contentFunction) {
    var tool = new Tool(id, name, contentFunction);
    toolQueue.push(tool);
    updateTools();
    return tool;
  };

  my.addAjaxTool = function(id, name, url) {
    return this.addTool(id, name, function($content) {
      $content.html('loading...');
      $.ajax({
        url: url,
        type: 'GET',
        dataType: 'html',
        success: function(data) {
          $content.html(data)
        },
        error: function(xhr, status, error) {
          $content.text(status + ': ' + error);
        }
      });
      return true;
    });
  };

  my.addLinkTool = function(id, name, url) {
    return this.addTool(id, name, function($content) {
      location.href = url;
      return false;
    });
  };

  var loadState = function() {
    if (!$devbar)
      throw 'Jivoo Devbar not initialized!';
    var x = confGet('x', 0);
    var y = confGet('y', 0);
    var width = confGet('width', $devbar.width());
    width = Math.max(width, minimumWidth);
    width = Math.min(width, $(window).width());
    $devbar.width(width);
    x = Math.max(x, 0);
    y = Math.max(y, 0);
    x = Math.min(x, $(window).width() - $devbar.width());
    y = Math.min(y, $(window).height() - $devbar.height());
    $devbar.css({top: y, left: x});
  };

  var saveState = function() {
    if (!$devbar)
      throw 'Jivoo Devbar not initialized!';
    confSet('x', $devbar.position().left);
    confSet('y', $devbar.position().top);
    confSet('width', $devbar.width());
    rearrangeTools();
  };

  my.toTop = function() {
    var zmax = 0;
    $('*').each(function() {
      var cur = parseInt($(this).css('z-index'));
      zmax = cur > zmax ? cur : zmax;
    });
    $devbar.css('z-index', zmax + 1);
    toolZIndex = zmax + 2;
  };

  my.showMoreMenu = function() {
    var xf = ($more.offset().left - $(window).scrollLeft()) / $(window).width();
    var yf = ($more.offset().top - $(window).scrollTop()) / $(window).height();
    $moreMenu.css({top: '', left: '', right: '', bottom: ''});
    if (xf < 0.5) {
      if (yf < 0.5)
        $moreMenu.css({top: '0', left: '100%'}); // top left
      else
        $moreMenu.css({bottom: '0', left: '100%'}); // bottom left
    }
    else {
      if (yf < 0.5)
        $moreMenu.css({top: '100%', right: '0'}); // top right
      else
        $moreMenu.css({bottom: '100%', right: '0'}); // bottom right
    }
    $moreMenu.show();
    var buttonPos = $more.position();
    $(document).one('click',function(){
      $moreMenu.hide();
    });
    return false;
  };

  my.hideMoreMenu = function() {
    $moreMenu.hide();
  };

  $(function() {
    $devbar = $('#jivoo-devbar');
    $tools = $devbar.children('.jivoo-devbar-tools');
    $more = $devbar.children('.jivoo-devbar-more');
    $more.hide();
    $moreMenu = $devbar.children('.jivoo-devbar-tools-more');
    $moreMenu.hide();

    var rightHandleWidth = $more.outerWidth() + $devbar.children('.ui-resizable-handle').outerWidth();
    minimumWidth = $devbar.children('.jivoo-devbar-handle').outerWidth() + rightHandleWidth;

    my.toTop();
    loadState();
    saveState();

    updateTools();

    $devbar.draggable({
      scroll: false,
      containment: 'window',
      handle: '.jivoo-devbar-handle',
      start: function(event, ui) {
        stop = false;
      },
      drag: function(event, ui) {
        if (stop) {
          stop = false;
          return false;
        }
      },
      stop: function(event, ui) {
        saveState();
      }
    });
    $(window).resize(function() {
      if ($devbar.width() > $(window).width())
        $devbar.width($(window).width());
      var pos = $devbar.position();
      var x = Math.min(pos.left, $(window).width() - $devbar.width());
      var y = Math.min(pos.top, $(window).height() - $devbar.height());
      $devbar.css({top: y, left: x});
      saveState();
    });
    $devbar.resizable({
      handles: { e: '.ui-resizable-handle' },
      containment: 'document',
      minWidth: minimumWidth
    });

    $more.click(my.showMoreMenu);
  });

  return parent;
}(JIVOO || {}, jQuery, Cookies))

$(function() {
  var logTool = JIVOO.devbar.addTool('jivoo-log', 'Log', function ($content) {
    var $log = $('
');
    jivooLog.forEach(function(entry) {
      var $entry = $('

');
      var message = entry.message;
      if (entry.file) {
        message += ' in ' + entry.file + ' on line ' + entry.line + '';
      }
      $entry.html(message);
      switch (entry.type) {
      case 1: // QUERY
        console.debug(message);
        $entry.css('color', '#999');
        break;
      case 2: // DEBUG
        console.debug(message);
        $entry.css('color', '#99f');
        break;
      case 2: // NOTICE
        console.log(message);
        $entry.css('color', '#f00');
        break;
      case 4: // WARNING
        console.warn(message);
        $entry.css('color', '#f90');
        break;
      case 8: // ERROR
        console.error(message);
        $entry.css('color', '#f00');
        break;
      }
      $log.append($entry);
    });
    $content.append($log);
  });

  logTool.$menuItem.children('a').append($('').text(jivooLog.length));
});
<|endoftext|>