<commit_before>/**
  * Based on XML_Utility functions submitted by troels_kn.
  * credit also to adios, who helped with reg exps:
  * http://www.sitepoint.com/forums/showthread.php?t=201052
  *
  * A replacement for Xinha.getHTML
  *
  * Features:
  *   - Generates XHTML code
  *   - Much faster than Xinha.getHTML
  *   - Eliminates the hacks to accomodate browser quirks
  *   - Returns correct code for Flash objects and scripts
  *   - Formats html in an indented, readable format in html mode
  *   - Preserves script and pre formatting
  *   - Preserves formatting in comments
  *   - Removes contenteditable from body tag in full-page mode
  *   - Supports only7BitPrintablesInURLs config option
  *   - Supports htmlRemoveTags config option
  */

function GetHtmlImplementation(editor) {
    this.editor = editor;
}

GetHtmlImplementation._pluginInfo = {
	name          : "GetHtmlImplementation TransformInnerHTML",
	version       : "1.0",
	developer     : "Nelson Bright",
	developer_url : "http://www.brightworkweb.com/",
	sponsor       : "",
    sponsor_url   : "",
	license       : "htmlArea"
};

Xinha.RegExpCache = [
/*00*/  /<\s*\/?([^\s\/>]+)[\s*\/>]/gi,//lowercase tags
/*01*/  /(\s+)_moz[^=>]*=[^\s>]*/gi,//strip _moz attributes
/*02*/  /\s*=\s*(([^'"][^>\s]*)([>\s])|"([^"]+)"|'([^']+)')/g,// find attributes
/*03*/  /\/>/g,//strip singlet terminators
/*04*/  /<(br|hr|img|input|link|meta|param|embed|area)((\s*\S*="[^"]*")*)>/g,//terminate singlet tags
/*05*/  /(<\w+\s+(\w*="[^"]*"\s+)*)(checked|compact|declare|defer|disabled|ismap|multiple|no(href|resize|shade|wrap)|readonly|selected)([\s>])/gi,//expand singlet attributes
/*06*/  /(="[^']*)'([^'"]*")/,//check quote nesting
/*07*/  /&(?=(?!(#[0-9]{2,5};|[a-zA-Z0-9]{2,6};|#x[0-9a-fA-F]{2,4};))[^<]*>)/g,//expand query ampersands not in html entities
/*08*/  /<\s+/g,//strip tagstart whitespace
/*09*/  /\s+(\/)?>/g,//trim whitespace
/*10*/  /\s{2,}/g,//trim extra whitespace
/*11*/  /\s+([^=\s]+)((="[^"]+")|([\s>]))/g,// lowercase attribute names
/*12*/  /\s+contenteditable(=[^>\s\/]*)?/gi,//strip contenteditable
/*13*/  /((href|src)=")([^\s]*)"/g, //find href and src for stripBaseHref()
/*14*/  /<\/?(div|p|h[1-6]|table|tr|td|th|ul|ol|li|dl|dt|dd|blockquote|object|br|hr|img|embed|param|pre|script|html|head|body|meta|link|title|area|input|form|textarea|select|option)[^>]*>/g,
/*15*/  /<\/(div|p|h[1-6]|table|tr|ul|ol|dl|blockquote|object|html|head|body|script|form|select)( [^>]*)?>/g,//blocklevel closing tag
/*16*/  /<(div|p|h[1-6]|table|tr|ul|ol|dl|blockquote|object|html|head|body|script|form|select)( [^>]*)?>/g,//blocklevel opening tag
/*17*/  /<(td|th|li|dt|dd|option|br|hr|embed|param|pre|meta|link|title|area|input|textarea)[^>]*>/g,//singlet tag or output on 1 line
/*18*/  /(^|<\/(pre|script)>)(\s|[^\s])*?(<(pre|script)[^>]*>|$)/g,//find content NOT inside pre and script tags
/*19*/  /(
]*>)([\s\S])*?(<\/pre>)/g,//find content inside pre tags
/*20*/  /(^|)([\s\S]*?)(?=|$)/g,//find content NOT inside comments
/*21*/  /\S*=""/g, //find empty attributes
/*22*/  /|<\?[\s\S]*?\?>|<\/?\w[^>]*>/g, //find all tags, including comments and php
/*23*/  /(^|<\/script>)[\s\S]*?(');//strip returns added into scripts
    return s;
};

Xinha.getHTML = function(root, outputRoot, editor) {
	var html = "";
	var c = Xinha.RegExpCache;

	if(root.nodeType == 11) {//document fragment
	    //we can't get innerHTML from the root (type 11) node, so we
	    //copy all the child nodes into a new div and get innerHTML from the div
	    var div = document.createElement("div");
	    var temp = root.insertBefore(div,root.firstChild);
	    for (j = temp.nextSibling; j; j = j.nextSibling) {
	    		temp.appendChild(j.cloneNode(true));
	    }
		html += temp.innerHTML.replace(c[23], function(strn) { //skip content inside script tags
			strn = strn.replace(c[22], function(tag){
				if(/^<[!\?]/.test(tag)) return tag; //skip comments and php tags
				else return editor.cleanHTML(tag)});
			return strn;
		});

	} else {

		var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';
		if (outputRoot) { //only happens with  tag in fullpage mode
			html += "<" + root_tag;
			var attrs = root.attributes; // strangely, this doesn't work in moz
			for (i = 0; i < attrs.length; ++i) {
				var a = attrs.item(i);
				if (!a.specified) {
				  continue;
				}
				var name = a.nodeName.toLowerCase();
				var value = a.nodeValue;
				html += " " + name + '="' + value + '"';
			}
			html += ">";
		}
		if(root_tag == "html") {
			innerhtml = editor._doc.documentElement.innerHTML;
		} else {
			innerhtml = root.innerHTML;
		}
		//pass tags to cleanHTML() one at a time
		//includes support for htmlRemoveTags config option
		html += innerhtml.replace(c[23], function(strn) { //skip content inside script tags
			strn = strn.replace(c[22], function(tag){
				if(/^<[!\?]/.test(tag)) return tag; //skip comments and php tags
				else if(!(editor.config.htmlRemoveTags && editor.config.htmlRemoveTags.test(tag.replace(/<([^\s>\/]+)/,'$1'))))
					return editor.cleanHTML(tag);
				else return ''});
			return strn;
		});
		//IE drops  all
,
,
 tags in a list except the last one
		if(Xinha.is_ie) {
			html = html.replace(/<(li|dd|dt)( [^>]*)?>/g,'</$1><$1$2>').
				replace(/(<[uod]l[^>]*>[\s\S]*?)<\/(li|dd|dt)>/g, '$1').
				replace(/\s*<\/(li|dd|dt)>(\s*<\/(li|dd|dt)>)+/g, '</$1>').
				replace(/(
][\s\S]*?)(<\/d[dt]>)+/g, '$1
');
		}
		if(Xinha.is_gecko)
			html = html.replace(/
\n$/, ''); //strip trailing
 added by moz
		//Cleanup redundant whitespace before

 in IE and Mozilla
		html = html.replace(/\s*(<\/(li|dd|dt)>)/g, '$1');
		if (outputRoot) {
			html += "</" + root_tag + ">";
		}
		html = Xinha.indent(html);
	};
//	html = Xinha.htmlEncode(html);

	return html;
};

/**
  * Escapes dollar signs ($) to make them safe to use in regex replacement functions by replacing each $ in the input with $$.
  *
  * This is advisable any time the replacement string for a call to replace() is a variable and could contain dollar signs that should not be interpreted as references to captured groups (e.g., when you want the text "$10" and not the first captured group followed by a 0).
  * See http://trac.xinha.org/ticket/1337
  */
Xinha._escapeDollars = function(str) {
  return str.replace(/\$/g, "$$$$");
};
<commit_msg>TransformInnerHtml handling of object tag - ticket #1497<commit_after>/**
  * Based on XML_Utility functions submitted by troels_kn.
  * credit also to adios, who helped with reg exps:
  * http://www.sitepoint.com/forums/showthread.php?t=201052
  *
  * A replacement for Xinha.getHTML
  *
  * Features:
  *   - Generates XHTML code
  *   - Much faster than Xinha.getHTML
  *   - Eliminates the hacks to accomodate browser quirks
  *   - Returns correct code for Flash objects and scripts
  *   - Formats html in an indented, readable format in html mode
  *   - Preserves script and pre formatting
  *   - Preserves formatting in comments
  *   - Removes contenteditable from body tag in full-page mode
  *   - Supports only7BitPrintablesInURLs config option
  *   - Supports htmlRemoveTags config option
  */

function GetHtmlImplementation(editor) {
    this.editor = editor;
}

GetHtmlImplementation._pluginInfo = {
	name          : "GetHtmlImplementation TransformInnerHTML",
	version       : "1.0",
	developer     : "Nelson Bright",
	developer_url : "http://www.brightworkweb.com/",
	sponsor       : "",
    sponsor_url   : "",
	license       : "htmlArea"
};

Xinha.RegExpCache = [
/*00*/  /<\s*\/?([^\s\/>]+)[\s*\/>]/gi,//lowercase tags
/*01*/  /(\s+)_moz[^=>]*=[^\s>]*/gi,//strip _moz attributes
/*02*/  /\s*=\s*(([^'"][^>\s]*)([>\s])|"([^"]+)"|'([^']+)')/g,// find attributes
/*03*/  /\/>/g,//strip singlet terminators
/*04*/  /<(br|hr|img|input|link|meta|param|embed|area)((\s*\S*="[^"]*")*)>/g,//terminate singlet tags
/*05*/  /(<\w+\s+(\w*="[^"]*"\s+)*)(checked|compact|declare|defer|disabled|ismap|multiple|no(href|resize|shade|wrap)|readonly|selected)([\s>])/gi,//expand singlet attributes
/*06*/  /(="[^']*)'([^'"]*")/,//check quote nesting
/*07*/  /&(?=(?!(#[0-9]{2,5};|[a-zA-Z0-9]{2,6};|#x[0-9a-fA-F]{2,4};))[^<]*>)/g,//expand query ampersands not in html entities
/*08*/  /<\s+/g,//strip tagstart whitespace
/*09*/  /\s+(\/)?>/g,//trim whitespace
/*10*/  /\s{2,}/g,//trim extra whitespace
/*11*/  /\s+([^=\s]+)((="[^"]+")|([\s>]))/g,// lowercase attribute names
/*12*/  /\s+contenteditable(=[^>\s\/]*)?/gi,//strip contenteditable
/*13*/  /((href|src)=")([^\s]*)"/g, //find href and src for stripBaseHref()
/*14*/  /<\/?(div|p|h[1-6]|table|tr|td|th|ul|ol|li|dl|dt|dd|blockquote|object|br|hr|img|embed|param|pre|script|html|head|body|meta|link|title|area|input|form|textarea|select|option)[^>]*>/g,
/*15*/  /<\/(div|p|h[1-6]|table|tr|ul|ol|dl|blockquote|html|head|body|script|form|select)( [^>]*)?>/g,//blocklevel closing tag
/*16*/  /<(div|p|h[1-6]|table|tr|ul|ol|dl|blockquote|object|html|head|body|script|form|select)( [^>]*)?>/g,//blocklevel opening tag
/*17*/  /<(td|th|li|dt|dd|option|br|hr|embed|param|pre|meta|link|title|area|input|textarea)[^>]*>/g,//singlet tag or output on 1 line
/*18*/  /(^|<\/(pre|script)>)(\s|[^\s])*?(<(pre|script)[^>]*>|$)/g,//find content NOT inside pre and script tags
/*19*/  /(
]*>)([\s\S])*?(<\/pre>)/g,//find content inside pre tags
/*20*/  /(^|)([\s\S]*?)(?=|$)/g,//find content NOT inside comments
/*21*/  /\S*=""/g, //find empty attributes
/*22*/  /|<\?[\s\S]*?\?>|<\/?\w[^>]*>/g, //find all tags, including comments and php
/*23*/  /(^|<\/script>)[\s\S]*?(');//strip returns added into scripts
    return s;
};

Xinha.getHTML = function(root, outputRoot, editor) {
	var html = "";
	var c = Xinha.RegExpCache;

	if(root.nodeType == 11) {//document fragment
	    //we can't get innerHTML from the root (type 11) node, so we
	    //copy all the child nodes into a new div and get innerHTML from the div
	    var div = document.createElement("div");
	    var temp = root.insertBefore(div,root.firstChild);
	    for (j = temp.nextSibling; j; j = j.nextSibling) {
	    		temp.appendChild(j.cloneNode(true));
	    }
		html += temp.innerHTML.replace(c[23], function(strn) { //skip content inside script tags
			strn = strn.replace(c[22], function(tag){
				if(/^<[!\?]/.test(tag)) return tag; //skip comments and php tags
				else return editor.cleanHTML(tag)});
			return strn;
		});

	} else {

		var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';
		if (outputRoot) { //only happens with  tag in fullpage mode
			html += "<" + root_tag;
			var attrs = root.attributes; // strangely, this doesn't work in moz
			for (i = 0; i < attrs.length; ++i) {
				var a = attrs.item(i);
				if (!a.specified) {
				  continue;
				}
				var name = a.nodeName.toLowerCase();
				var value = a.nodeValue;
				html += " " + name + '="' + value + '"';
			}
			html += ">";
		}
		if(root_tag == "html") {
			innerhtml = editor._doc.documentElement.innerHTML;
		} else {
			innerhtml = root.innerHTML;
		}
		//pass tags to cleanHTML() one at a time
		//includes support for htmlRemoveTags config option
		html += innerhtml.replace(c[23], function(strn) { //skip content inside script tags
			strn = strn.replace(c[22], function(tag){
				if(/^<[!\?]/.test(tag)) return tag; //skip comments and php tags
				else if(!(editor.config.htmlRemoveTags && editor.config.htmlRemoveTags.test(tag.replace(/<([^\s>\/]+)/,'$1'))))
					return editor.cleanHTML(tag);
				else return ''});
			return strn;
		});
		//IE drops  all
,
,
 tags in a list except the last one
		if(Xinha.is_ie) {
			html = html.replace(/<(li|dd|dt)( [^>]*)?>/g,'</$1><$1$2>').
				replace(/(<[uod]l[^>]*>[\s\S]*?)<\/(li|dd|dt)>/g, '$1').
				replace(/\s*<\/(li|dd|dt)>(\s*<\/(li|dd|dt)>)+/g, '</$1>').
				replace(/(
][\s\S]*?)(<\/d[dt]>)+/g, '$1
');
		}
		if(Xinha.is_gecko)
			html = html.replace(/
\n$/, ''); //strip trailing
 added by moz
		//Cleanup redundant whitespace before

 in IE and Mozilla
		html = html.replace(/\s*(<\/(li|dd|dt)>)/g, '$1');
		if (outputRoot) {
			html += "</" + root_tag + ">";
		}
		html = Xinha.indent(html);
	};
//	html = Xinha.htmlEncode(html);

	return html;
};

/**
  * Escapes dollar signs ($) to make them safe to use in regex replacement functions by replacing each $ in the input with $$.
  *
  * This is advisable any time the replacement string for a call to replace() is a variable and could contain dollar signs that should not be interpreted as references to captured groups (e.g., when you want the text "$10" and not the first captured group followed by a 0).
  * See http://trac.xinha.org/ticket/1337
  */
Xinha._escapeDollars = function(str) {
  return str.replace(/\$/g, "$$$$");
};
<|endoftext|>


<commit_before>/* eslint-env node */
'use strict';

module.exports = {
  name: 'ilios-loading',
  contentFor: function (type, config) {
    if (type === 'head') {
      //inline this CSS so it is parsed the fastest
      return `

      `;
    }
    if (type === 'test-body-footer') {
      return `<script src="${config.rootURL}ilios-loading/remove-loader-tests.js"></script>`;
    }

    if (type === 'body') {
      return `

          <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 392.11 392.11" aria-hidden='true'>
            <title>Ilios is Loading</title>
            <path d="M371.83,461.83c-77.62-89.13-98.6-113.11-30.25-93.76-62.12-34.35-30.23-36.41,87.67-44.87-117.91-8.47-149.8-10.52-87.67-44.87-68.34,19.35-47.37-4.63,30.26-93.76-89.12,77.62-113.11,98.6-93.76,30.25-34.35,62.12-36.41,30.23-44.87-87.68-8.47,117.91-10.53,149.8-44.87,87.68,19.35,68.34-4.64,47.37-93.76-30.26,77.62,89.13,98.59,113.11,30.25,93.76,62.12,34.35,30.23,36.41-87.68,44.87,117.91,8.47,149.8,10.52,87.68,44.87,68.34-19.35,47.37,4.63-30.25,93.76,89.12-77.62,113.11-98.6,93.76-30.25,34.35-62.12,36.41-30.23,44.87,87.68,8.47-117.91,10.52-149.8,44.87-87.68C258.71,363.23,282.7,384.21,371.83,461.83Z" transform="translate(-37.14 -127.14)"/>
            <circle class='first-circle' cx="50%" cy="50%" r="25%"/>
            <circle class='second-circle' cx="50%" cy="50%" r="25%"/>
            <circle class='third-circle' cx="50%" cy="50%" r="25%"/>
          </svg>

      `;
    }
  },
};
<commit_msg>Re-add loading indicator class<commit_after>/* eslint-env node */
'use strict';

module.exports = {
  name: 'ilios-loading',
  contentFor: function (type, config) {
    if (type === 'head') {
      //inline this CSS so it is parsed the fastest
      return `

      `;
    }
    if (type === 'test-body-footer') {
      return `<script src="${config.rootURL}ilios-loading/remove-loader-tests.js"></script>`;
    }

    if (type === 'body') {
      return `

          <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 392.11 392.11" aria-hidden='true'>
            <title>Ilios is Loading</title>
            <path d="M371.83,461.83c-77.62-89.13-98.6-113.11-30.25-93.76-62.12-34.35-30.23-36.41,87.67-44.87-117.91-8.47-149.8-10.52-87.67-44.87-68.34,19.35-47.37-4.63,30.26-93.76-89.12,77.62-113.11,98.6-93.76,30.25-34.35,62.12-36.41,30.23-44.87-87.68-8.47,117.91-10.53,149.8-44.87,87.68,19.35,68.34-4.64,47.37-93.76-30.26,77.62,89.13,98.59,113.11,30.25,93.76,62.12,34.35,30.23,36.41-87.68,44.87,117.91,8.47,149.8,10.52,87.68,44.87,68.34-19.35,47.37,4.63-30.25,93.76,89.12-77.62,113.11-98.6,93.76-30.25,34.35-62.12,36.41-30.23,44.87,87.68,8.47-117.91,10.52-149.8,44.87-87.68C258.71,363.23,282.7,384.21,371.83,461.83Z" transform="translate(-37.14 -127.14)"/>
            <circle class='first-circle' cx="50%" cy="50%" r="25%"/>
            <circle class='second-circle' cx="50%" cy="50%" r="25%"/>
            <circle class='third-circle' cx="50%" cy="50%" r="25%"/>
          </svg>

      `;
    }
  },
};
<|endoftext|>


<commit_before>/* global window, $, jsSHA, Promise */

window.correlations = (function () {
    /**
     * Handle any errors by logging them.
     */
    function handleError(error) {
        console.error(error.message);
    }

    var correlationData = {};

    function getDataURL(product) {
        if (product === 'Firefox') {
            return 'https://analysis-output.telemetry.mozilla.org/top-signatures-correlations/data/';
        } else if (product === 'FennecAndroid') {
            return 'https://analysis-output.telemetry.mozilla.org/top-fennec-signatures-correlations/data/';
        } else {
            return null;
        }
    }

    function loadChannelsData(product) {
        return Promise.resolve()
        .then(function () {
            if (correlationData[product]) {
                return correlationData[product];
            }

            var dataURL = getDataURL(product);
            if (!dataURL) {
                console.warn('Correlation results unavailable for the "' + product + '" product.');
                return null;
            }

            return fetch(dataURL + 'all.json.gz')
            .then(function (response) {
                return response.json();
            })
            .then(function (totals) {
                correlationData[product] = {
                    'date': totals['date'],
                };

                var channels = $('#mainbody').data('channels');

                channels.forEach(function (ch) {
                    correlationData[product][ch] = {
                        'total': totals[ch],
                        'signatures': {},
                    };
                });
            })
            .then(function () {
                return correlationData[product];
            });
        });
    }

    function loadCorrelationData(signature, channel, product) {
        return loadChannelsData(product)
        .then(function (channelsData) {
            if (!channelsData || !channelsData[channel] || signature in channelsData[channel]['signatures']) {
                return;
            }

            var shaObj = new jsSHA('SHA-1', 'TEXT');
            shaObj.update(signature);
            var sha1signature = shaObj.getHash('HEX');

            return fetch(getDataURL(product) + channel + '/' + sha1signature + '.json.gz')
            .then(function (response) {
                return response.json();
            })
            .then(function (data) {
                correlationData[product][channel]['signatures'][signature] = data;
            });
        })
        .catch(handleError)
        .then(function () {
            return correlationData;
        });
    }

    function itemToLabel(item) {
        return Object.getOwnPropertyNames(item)
        .map(function (key) {
            return key + ' = ' + item[key];
        })
        .join(' ∧ ');
    }

    // Convert the number to a user-readable percentage with four digits.
    // We use the same number of digits for any number (e.g. 100.0%, 03.45%) so
    // that the results are aligned, also when copied and pasted.
    function toPercentage(num) {
        var result = (num * 100).toFixed(2);

        if (result === '100.00') {
            return '100.0';
        }

        if (result.length < 5) {
            return '0' + result;
        }

        return result;
    }

    function confidenceInterval(count1, total1, count2, total2) {
        var prop1 = count1 / total1;
        var prop2 = count2 / total2;
        var diff = prop1 - prop2;

        // Wald 95% confidence interval for the difference between the proportions.
        var standard_error = Math.sqrt(prop1 * (1 - prop1) / total1 + prop2 * (1 - prop2) / total2);
        var ci = [diff - 1.96 * standard_error, diff + 1.96 * standard_error];

        // Yates continuity correction for the confidence interval.
        var correction = 0.5 * (1.0 / total1 + 1.0 / total2);

        return [ci[0] - correction, ci[1] + correction];
    }

    function sortCorrelationData(correlationData, total_reference, total_group) {
        return correlationData
        .sort(function (a, b) {
            // Sort by the number of attributes first (results with a smaller number of attributes
            // are easier to read and are often the most interesting ones).
            var rule_a_len = Object.keys(a.item).length;
            var rule_b_len = Object.keys(b.item).length;

            if (rule_a_len < rule_b_len) {
                return -1;
            }

            if (rule_a_len > rule_b_len) {
                return 1;
            }

            // Then, sort by percentage difference between signature and
            // overall (using the lower endpoint of the confidence interval
            // of the difference).
            var ciA = null;
            if (a.prior) {
                // If one of the two elements has a prior that alters a rule's
                // distribution significantly, sort by the percentage of the rule
                // given the prior.
                ciA = confidenceInterval(
                    a.prior.count_group,
                    a.prior.total_group,
                    a.prior.count_reference,
                    a.prior.total_reference
                );
            }
            else {
                ciA = confidenceInterval(
                    a.count_group, total_group, a.count_reference, total_reference
                );
            }

            var ciB = null;
            if (b.prior) {
                ciB = confidenceInterval(
                    b.prior.count_group,
                    b.prior.total_group,
                    b.prior.count_reference,
                    b.prior.total_reference
                );
            }
            else {
                ciB = confidenceInterval(
                    b.count_group, total_group, b.count_reference, total_reference
                );
            }

            return Math.min(Math.abs(ciB[0]), Math.abs(ciB[1])) - Math.min(Math.abs(ciA[0]), Math.abs(ciA[1]));
        });
    }

    function getResults(signature, channel, product) {
        return loadCorrelationData(signature, channel, product)
        .then(function (data) {

            if (!data[product]) {
                return 'No correlation data was generated for the "' + product + '" product.';
            }

            if (!data[product][channel]) {
                return 'No correlation data was generated for the "' + channel + '" channel and the "' + product + '" product.';
            }

            var signatureData = data[product][channel]['signatures'][signature];

            if (!signatureData || !signatureData.results) {
                return 'No correlation data was generated for the signature "' + signature + '" on the "' + channel + '" channel, for the "' + product + '" product.';
            }

            var correlationData = signatureData.results;
            if (correlationData.length === 0) {
                return 'No correlations found for the signature "' + signature + '" on the "' + channel + '" channel, for the "' + product + '" product.';
            }

            var total_reference = data[product][channel].total;
            var total_group = signatureData.total;

            var results = sortCorrelationData(correlationData, total_reference, total_group)
            .map(function (line) {
                var percentGroup = toPercentage(line.count_group / total_group);
                var percentRef = toPercentage(line.count_reference / total_reference);

                var result = '(' + percentGroup + '% in signature vs ' + percentRef + '% overall) ' + itemToLabel(line.item);

                // If the rule has a prior that alters its distribution significantly, print it after the rule.
                if (line.prior && line.prior.total_group && line.prior.total_reference) {
                    var percentGroupGivenPrior = toPercentage(line.prior.count_group / line.prior.total_group);
                    var percentRefGivenPrior = toPercentage(line.prior.count_reference / line.prior.total_reference);
                    result += ' [' + percentGroupGivenPrior + '% vs ' + percentRefGivenPrior + '% if ' + itemToLabel(line.prior.item) + ']';
                }

                return result;
            });

            if (signatureData.top_words) {
                results.push('');
                results.push('Top words: ' + signatureData.top_words.join(', '));
            }

            return results;
        })
        .catch(handleError);
    }

    return {
        getCorrelations: getResults,
    };
})();
<commit_msg>Bug 1388419 correlations js errors on report index (#3897)<commit_after>/* global window, $, jsSHA, Promise */

window.correlations = (function () {
    /**
     * Handle any errors by logging them.
     */
    function handleError(error) {
        console.error(error.message);
    }

    var correlationData = {};

    function getDataURL(product) {
        if (product === 'Firefox') {
            return 'https://analysis-output.telemetry.mozilla.org/top-signatures-correlations/data/';
        } else if (product === 'FennecAndroid') {
            return 'https://analysis-output.telemetry.mozilla.org/top-fennec-signatures-correlations/data/';
        } else {
            return null;
        }
    }

    function loadChannelsData(product) {
        return Promise.resolve()
        .then(function () {
            if (correlationData[product]) {
                return correlationData[product];
            }

            var dataURL = getDataURL(product);
            if (!dataURL) {
                console.warn('Correlation results unavailable for the "' + product + '" product.');
                return null;
            }

            return fetch(dataURL + 'all.json.gz')
            .then(function (response) {
                return response.json();
            })
            .then(function (totals) {
                correlationData[product] = {
                    'date': totals.date,
                };

                var channels = $('#mainbody').data('channels');
                if (!channels) {
                    channels = [$('#mainbody').data('channel')];
                }
                if (!channels || !channels.length) {
                    throw new Error('No channel or channels dataset attribute set');
                }

                channels.forEach(function (ch) {
                    correlationData[product][ch] = {
                        'total': totals[ch],
                        'signatures': {},
                    };
                });
                return correlationData[product];
            });
        });
    }

    function loadCorrelationData(signature, channel, product) {
        return loadChannelsData(product)
        .then(function (channelsData) {
            if (!channelsData || !channelsData[channel] || signature in channelsData[channel].signatures) {
                return;
            }

            var shaObj = new jsSHA('SHA-1', 'TEXT');
            shaObj.update(signature);
            var sha1signature = shaObj.getHash('HEX');

            return fetch(getDataURL(product) + channel + '/' + sha1signature + '.json.gz')
            .then(function (response) {
                return response.json();
            })
            .then(function (data) {
                correlationData[product][channel].signatures[signature] = data;
            });
        })
        .catch(handleError)
        .then(function () {
            return correlationData;
        });
    }

    function itemToLabel(item) {
        return Object.getOwnPropertyNames(item)
        .map(function (key) {
            return key + ' = ' + item[key];
        })
        .join(' ∧ ');
    }

    // Convert the number to a user-readable percentage with four digits.
    // We use the same number of digits for any number (e.g. 100.0%, 03.45%) so
    // that the results are aligned, also when copied and pasted.
    function toPercentage(num) {
        var result = (num * 100).toFixed(2);

        if (result === '100.00') {
            return '100.0';
        }

        if (result.length < 5) {
            return '0' + result;
        }

        return result;
    }

    function confidenceInterval(count1, total1, count2, total2) {
        var prop1 = count1 / total1;
        var prop2 = count2 / total2;
        var diff = prop1 - prop2;

        // Wald 95% confidence interval for the difference between the proportions.
        var standard_error = Math.sqrt(prop1 * (1 - prop1) / total1 + prop2 * (1 - prop2) / total2);
        var ci = [diff - 1.96 * standard_error, diff + 1.96 * standard_error];

        // Yates continuity correction for the confidence interval.
        var correction = 0.5 * (1.0 / total1 + 1.0 / total2);

        return [ci[0] - correction, ci[1] + correction];
    }

    function sortCorrelationData(correlationData, total_reference, total_group) {
        return correlationData
        .sort(function (a, b) {
            // Sort by the number of attributes first (results with a smaller number of attributes
            // are easier to read and are often the most interesting ones).
            var rule_a_len = Object.keys(a.item).length;
            var rule_b_len = Object.keys(b.item).length;

            if (rule_a_len < rule_b_len) {
                return -1;
            }

            if (rule_a_len > rule_b_len) {
                return 1;
            }

            // Then, sort by percentage difference between signature and
            // overall (using the lower endpoint of the confidence interval
            // of the difference).
            var ciA = null;
            if (a.prior) {
                // If one of the two elements has a prior that alters a rule's
                // distribution significantly, sort by the percentage of the rule
                // given the prior.
                ciA = confidenceInterval(
                    a.prior.count_group,
                    a.prior.total_group,
                    a.prior.count_reference,
                    a.prior.total_reference
                );
            }
            else {
                ciA = confidenceInterval(
                    a.count_group, total_group, a.count_reference, total_reference
                );
            }

            var ciB = null;
            if (b.prior) {
                ciB = confidenceInterval(
                    b.prior.count_group,
                    b.prior.total_group,
                    b.prior.count_reference,
                    b.prior.total_reference
                );
            }
            else {
                ciB = confidenceInterval(
                    b.count_group, total_group, b.count_reference, total_reference
                );
            }

            return Math.min(Math.abs(ciB[0]), Math.abs(ciB[1])) - Math.min(Math.abs(ciA[0]), Math.abs(ciA[1]));
        });
    }

    function getResults(signature, channel, product) {
        return loadCorrelationData(signature, channel, product)
        .then(function (data) {

            if (!data[product]) {
                return 'No correlation data was generated for the "' + product + '" product.';
            }

            if (!data[product][channel]) {
                return 'No correlation data was generated for the "' + channel + '" channel and the "' + product + '" product.';
            }

            var signatureData = data[product][channel].signatures[signature];

            if (!signatureData || !signatureData.results) {
                return 'No correlation data was generated for the signature "' + signature + '" on the "' + channel + '" channel, for the "' + product + '" product.';
            }

            var correlationData = signatureData.results;
            if (correlationData.length === 0) {
                return 'No correlations found for the signature "' + signature + '" on the "' + channel + '" channel, for the "' + product + '" product.';
            }

            var total_reference = data[product][channel].total;
            var total_group = signatureData.total;

            var results = sortCorrelationData(correlationData, total_reference, total_group)
            .map(function (line) {
                var percentGroup = toPercentage(line.count_group / total_group);
                var percentRef = toPercentage(line.count_reference / total_reference);

                var result = '(' + percentGroup + '% in signature vs ' + percentRef + '% overall) ' + itemToLabel(line.item);

                // If the rule has a prior that alters its distribution significantly, print it after the rule.
                if (line.prior && line.prior.total_group && line.prior.total_reference) {
                    var percentGroupGivenPrior = toPercentage(line.prior.count_group / line.prior.total_group);
                    var percentRefGivenPrior = toPercentage(line.prior.count_reference / line.prior.total_reference);
                    result += ' [' + percentGroupGivenPrior + '% vs ' + percentRefGivenPrior + '% if ' + itemToLabel(line.prior.item) + ']';
                }

                return result;
            });

            if (signatureData.top_words) {
                results.push('');
                results.push('Top words: ' + signatureData.top_words.join(', '));
            }

            return results;
        })
        .catch(handleError);
    }

    return {
        getCorrelations: getResults,
    };
})();
<|endoftext|>


<commit_before>binaryVerticalOrderTraversal.js
<commit_msg>add desc<commit_after>// Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bottom, column by column).

// If two nodes are in the same row and column, the order should be from left to right.

// Examples:

// Given binary tree [3,9,20,null,null,15,7],
//    3
//   /\
//  /  \
//  9  20
//     /\
//    /  \
//   15   7
// return its vertical order traversal as:
// [
//   [9],
//   [3,15],
//   [20],
//   [7]
// ]
// Given binary tree [3,9,8,4,0,1,7],
//      3
//     /\
//    /  \
//    9   8
//   /\  /\
//  /  \/  \
//  4  01   7
// return its vertical order traversal as:
// [
//   [4],
//   [9],
//   [3,0,1],
//   [8],
//   [7]
// ]
// Given binary tree [3,9,8,4,0,1,7,null,null,null,2,5] (0's right child is 2 and 1's left child is 5),
//      3
//     /\
//    /  \
//    9   8
//   /\  /\
//  /  \/  \
//  4  01   7
//     /\
//    /  \
//    5   2
// return its vertical order traversal as:
// [
//   [4],
//   [9,5],
//   [3,0,1],
//   [8,2],
//   [7]
// ]
<|endoftext|>


<commit_before>/* global Backbone */
/* global $ */
/* global _ */

(function() {

  "use strict";

  // private:
  var adjustOffset = function(options) {
    var leftOffset = options.triggerEl.offset().left;
    return {left : leftOffset};
  };

  // public:
  Backbone.Dropdown = Backbone.Popover.extend({
    initialize: function(args) {
      Backbone.Popover.prototype.initialize.call(this, args);
      var thisref = this;

      this.$el.on('focusout', function() {
        thisref.hide();
      });

      // dropdown can open down (default) or up (optional)
      // but it can never be right or left
      if (!(this.options.placement == "top" || this.options.placement == "bottom"))
        this.options.placement = "bottom";
    },

    render: function() {
      Backbone.Popover.prototype.render.call(this);

      this.$el.offset(adjustOffset(this.options))
        .find('.bb-tooltip-arrow').css('left', '15%');

      return this;
    },

    show: function() {
      Backbone.Popover.prototype.show.call(this);
      this.$el.focus();
    }
  })
})();
<commit_msg>Fix - Dropdown is not reopened when it is closed by focusout and click is on triggerEl<commit_after>/* global Backbone */
/* global $ */
/* global _ */

(function() {

  "use strict";

  // private:
  var adjustOffset = function(options) {
    var leftOffset = options.triggerEl.offset().left;
    return {left : leftOffset};
  };

  // public:
  Backbone.Dropdown = Backbone.Popover.extend({
    initialize: function(args) {
      Backbone.Popover.prototype.initialize.call(this, args);
      var thisref = this;

      this.$el.on('focusout', function() {
        thisref.hide();
      });

      // dropdown can open down (default) or up (optional)
      // but it can never be right or left
      if (!(this.options.placement == "top" || this.options.placement == "bottom"))
        this.options.placement = "bottom";
    },

    render: function() {
      Backbone.Popover.prototype.render.call(this);

      this.$el.offset(adjustOffset(this.options))
        .find('.bb-tooltip-arrow').css('left', '15%');

      return this;
    },

    show: function() {
      Backbone.Popover.prototype.show.call(this);
      this.$el.focus();
    },

    hide: function() {
      Backbone.Popover.prototype.hide.call(this);
      this.isShown = true;
      var thisref = this;
      setTimeout(function() {
        thisref.isShown = false;
      }, 100);
    }
  })
})();
<|endoftext|>


<commit_before>import {Button} from 'widget/button'
import {ButtonGroup} from './buttonGroup'
import {compose} from 'compose'
import {connect} from 'store'
import {selectFrom} from 'stateUtils'
import FloatingBox from 'widget/floatingBox'
import Icon from 'widget/icon'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import styles from './buttonPopup.module.css'

const mapStateToProps = state => ({
    dimensions: selectFrom(state, 'dimensions') || []
})

class ButtonPopup extends React.Component {
    buttonRef = React.createRef()
    popupRef = React.createRef()
    state = {
        showPopup: false
    }

    constructor() {
        super()
        this.handleBlur = this.handleBlur.bind(this)
    }

    render() {
        const {className} = this.props
        const {showPopup} = this.state
        return (

                {this.renderButton()}
                {showPopup ? this.renderPopup() : null}

        )
    }

    renderButton() {
        const {onClick} = this.props
        return onClick
            ? this.renderMultiButton()
            : this.renderSingleButton()
    }

    renderSingleButton() {
        const {disabled, chromeless, shape, look, icon, tooltip, tooltipPlacement, width, onMouseOver, onMouseOut} = this.props
        return (
            <Button
                ref={this.buttonRef}
                chromeless={chromeless}
                shape={shape}
                look={look}
                icon={icon}
                tooltip={tooltip}
                tooltipPlacement={tooltipPlacement}
                width={width}
                onClick={() => this.togglePopup()}
                onMouseOver={onMouseOver}
                onMouseOut={onMouseOut}
                disabled={disabled}
                label={this.getLabel()}
                tail={
                    <Icon name={this.getIcon()} dimmed={this.getIconDimmed()}/>
                }
            />
        )
    }

    renderMultiButton() {
        const {disabled, chromeless, shape, look, icon, tooltip, tooltipPlacement, width, onClick, onMouseOver, onMouseOut} = this.props
        return (
            <ButtonGroup
                ref={this.buttonRef}
                spacing='none'
                onMouseOver={onMouseOver}
                onMouseOut={onMouseOut}>
                <Button
                    chromeless={chromeless}
                    shape={shape}
                    look={look}
                    icon={icon}
                    tooltip={tooltip}
                    tooltipPlacement={tooltipPlacement}
                    width={width}
                    onClick={e => onClick && onClick(e)}
                    disabled={disabled}
                    label={this.getLabel()}
                />
                <Button
                    chromeless={chromeless}
                    shape={shape}
                    look={look}
                    icon={this.getIcon()}
                    iconDimmed={this.getIconDimmed()}
                    tooltip={tooltip}
                    tooltipPlacement={tooltipPlacement}
                    width={width}
                    onClick={() => this.togglePopup()}
                    disabled={disabled}
                />
            </ButtonGroup>
        )
    }

    getLabel() {
        const {label} = this.props
        const {selectedOption} = this.state
        return (selectedOption && (selectedOption.buttonLabel || selectedOption.label)) || label
    }

    getIcon() {
        const {placement} = this.props
        return placement === 'above' ? 'chevron-up' : 'chevron-down'
    }

    getIconDimmed() {
        const {showPopup} = this.state
        return showPopup
    }

    renderPopup() {
        const {vPlacement, hPlacement} = this.props
        return this.buttonRef.current && (
            <FloatingBox
                ref={this.popupRef}
                element={this.buttonRef.current}
                className={[
                    styles.popup,
                    styles[`placement-${vPlacement}`]
                ].join(' ')}
                vPlacement={vPlacement}
                hPlacement={hPlacement}
                onBlur={this.handleBlur}>
                {this.renderContent()}
            </FloatingBox>
        )
    }

    renderContent() {
        const {children} = this.props
        return _.isFunction(children)
            ? children(this.handleBlur)
            : children
    }

    togglePopup() {
        this.setState(({showPopup}) => ({showPopup: !showPopup}))
    }

    hidePopup() {
        this.setState({showPopup: false})
    }

    handleBlur(e) {
        const {stayOpenOnBlur} = this.props
        if (e) {
            if (!stayOpenOnBlur) {
                const isButtonClick = e => this.buttonRef.current && this.buttonRef.current.contains(e.target)
                const isPopupClick = e => this.popupRef.current && this.popupRef.current && this.popupRef.current.contains(e.target)
                if (!isButtonClick(e) && !isPopupClick(e)) {
                    this.hidePopup()
                }
            }
        } else {
            this.hidePopup()
        }
    }
}

export default compose(
    ButtonPopup,
    connect(mapStateToProps)
)

ButtonPopup.propTypes = {
    children: PropTypes.any,
    chromeless: PropTypes.any,
    className: PropTypes.string,
    disabled: PropTypes.any,
    hPlacement: PropTypes.any,
    icon: PropTypes.string,
    label: PropTypes.any,
    look: PropTypes.string,
    shape: PropTypes.oneOf(['rectangle', 'pill']),
    stayOpenOnBlur: PropTypes.any,
    tooltip: PropTypes.string,
    tooltipPlacement: PropTypes.string,
    vPlacement: PropTypes.oneOf(['above', 'below', 'over-above', 'over-below']),
    width: PropTypes.string,
    onClick: PropTypes.func,
    onMouseOut: PropTypes.func,
    onMouseOver: PropTypes.func,
}

ButtonPopup.defaultProps = {
    vPlacement: 'below',
    hPlacement: 'over-right'
}
<commit_msg>Cleanup.<commit_after>import {Button} from 'widget/button'
import {ButtonGroup} from './buttonGroup'
import {compose} from 'compose'
import {connect} from 'store'
import {selectFrom} from 'stateUtils'
import FloatingBox from 'widget/floatingBox'
import Icon from 'widget/icon'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import styles from './buttonPopup.module.css'

const mapStateToProps = state => ({
    dimensions: selectFrom(state, 'dimensions') || []
})

class ButtonPopup extends React.Component {
    buttonRef = React.createRef()
    popupRef = React.createRef()
    state = {
        showPopup: false
    }

    constructor() {
        super()
        this.handleBlur = this.handleBlur.bind(this)
    }

    render() {
        const {className} = this.props
        const {showPopup} = this.state
        return (

                {this.renderButton()}
                {showPopup ? this.renderPopup() : null}

        )
    }

    renderButton() {
        const {onClick} = this.props
        return onClick
            ? this.renderMultiButton()
            : this.renderSingleButton()
    }

    renderSingleButton() {
        const {disabled, chromeless, shape, look, icon, tooltip, tooltipPlacement, width, onMouseOver, onMouseOut} = this.props
        return (
            <Button
                ref={this.buttonRef}
                chromeless={chromeless}
                shape={shape}
                look={look}
                icon={icon}
                tooltip={tooltip}
                tooltipPlacement={tooltipPlacement}
                width={width}
                onClick={() => this.togglePopup()}
                onMouseOver={onMouseOver}
                onMouseOut={onMouseOut}
                disabled={disabled}
                label={this.getLabel()}
                tail={
                    <Icon name={this.getIcon()} dimmed={this.getIconDimmed()}/>
                }
            />
        )
    }

    renderMultiButton() {
        const {disabled, chromeless, shape, look, icon, tooltip, tooltipPlacement, width, onClick, onMouseOver, onMouseOut} = this.props
        return (
            <ButtonGroup
                ref={this.buttonRef}
                spacing='none'
                onMouseOver={onMouseOver}
                onMouseOut={onMouseOut}>
                <Button
                    chromeless={chromeless}
                    shape={shape}
                    look={look}
                    icon={icon}
                    tooltip={tooltip}
                    tooltipPlacement={tooltipPlacement}
                    width={width}
                    onClick={e => onClick && onClick(e)}
                    disabled={disabled}
                    label={this.getLabel()}
                />
                <Button
                    chromeless={chromeless}
                    shape={shape}
                    look={look}
                    icon={this.getIcon()}
                    iconDimmed={this.getIconDimmed()}
                    tooltip={tooltip}
                    tooltipPlacement={tooltipPlacement}
                    width={width}
                    onClick={() => this.togglePopup()}
                    disabled={disabled}
                />
            </ButtonGroup>
        )
    }

    getLabel() {
        const {label} = this.props
        const {selectedOption} = this.state
        return (selectedOption && (selectedOption.buttonLabel || selectedOption.label)) || label
    }

    getIcon() {
        const {placement} = this.props
        return placement === 'above' ? 'chevron-up' : 'chevron-down'
    }

    getIconDimmed() {
        const {showPopup} = this.state
        return showPopup
    }

    renderPopup() {
        const {vPlacement, hPlacement} = this.props
        return this.buttonRef.current && (
            <FloatingBox
                ref={this.popupRef}
                element={this.buttonRef.current}
                className={[
                    styles.popup,
                    styles[`placement-${vPlacement}`]
                ].join(' ')}
                vPlacement={vPlacement}
                hPlacement={hPlacement}
                onBlur={this.handleBlur}>
                {this.renderContent()}
            </FloatingBox>
        )
    }

    renderContent() {
        const {children} = this.props
        return _.isFunction(children)
            ? children(this.handleBlur)
            : children
    }

    togglePopup() {
        this.setState(({showPopup}) => ({showPopup: !showPopup}))
    }

    hidePopup() {
        this.setState({showPopup: false})
    }

    handleBlur(e) {
        const {stayOpenOnBlur} = this.props
        if (e) {
            if (!stayOpenOnBlur) {
                const isButtonClick = e => this.buttonRef.current && this.buttonRef.current.contains(e.target)
                const isPopupClick = e => this.popupRef.current && this.popupRef.current.contains(e.target)
                if (!isButtonClick(e) && !isPopupClick(e)) {
                    this.hidePopup()
                }
            }
        } else {
            this.hidePopup()
        }
    }
}

export default compose(
    ButtonPopup,
    connect(mapStateToProps)
)

ButtonPopup.propTypes = {
    children: PropTypes.any,
    chromeless: PropTypes.any,
    className: PropTypes.string,
    disabled: PropTypes.any,
    hPlacement: PropTypes.any,
    icon: PropTypes.string,
    label: PropTypes.any,
    look: PropTypes.string,
    shape: PropTypes.oneOf(['rectangle', 'pill']),
    stayOpenOnBlur: PropTypes.any,
    tooltip: PropTypes.string,
    tooltipPlacement: PropTypes.string,
    vPlacement: PropTypes.oneOf(['above', 'below', 'over-above', 'over-below']),
    width: PropTypes.string,
    onClick: PropTypes.func,
    onMouseOut: PropTypes.func,
    onMouseOver: PropTypes.func,
}

ButtonPopup.defaultProps = {
    vPlacement: 'below',
    hPlacement: 'over-right'
}
<|endoftext|>


<commit_before>Ext.define('ExtJsSample.controller.MessageController', {
    extend: 'Ext.app.Controller',
    stores: [
        'MessageStore'
    ],
    models: [
        'Message'
    ],
    views: [
        'message.List',
        'message.Create',
        'message.Edit'
    ],
    init: function () {
        this.control({
            'messageList': {
                itemdblclick: this.editMessage,
                removeitem: this.removeMessage
            },
            'messageList > toolbar > button[action=create]': {
                click: this.onCreateMessage
            },
            'messageCreate button[action=save]': {
                click: this.doCreateMessage
            },
            'messageCreate button[action=save]': {
                click: this.updateMessage
            }
        });
    },
    editMessage: function (grid, record) {
        var view = Ext.widget('messageEdit');
        view.down('form').loadRecord(record);
    },
    removeMessage: function (msg) {
        Ext.Msg.confirm('Remove Message', 'Are you sure?', function (button) {
            if (button == 'yes') {
                Ext.getStore("MessageStore").remove(msg);
            }
        }, this);
    },
    onCreateMessage: function () {
        var view = Ext.widget('messageCreate');
    },
    doCreateMessage: function (button) {
        var win = button.up('window'),
            form = win.down('form'),
            values = form.getValues(),
            store = Ext.getStore("MessageStore");
        if (form.getForm().isValid()) {
            store.add(values);
            win.close();
        }
    },
    updateMessage: function (button) {
        var win = button.up('window'),
            form = win.down('form'),
            record = form.getRecord(),
            values = form.getValues(),
            store = Ext.getStore("MessageStore");
        if (form.getForm().isValid()) {
            record.set(values);
            win.close();
        }
    }
});<commit_msg>Fix create\update issue in Message controller<commit_after>Ext.define('ExtJsSample.controller.MessageController', {
    extend: 'Ext.app.Controller',
    stores: [
        'MessageStore'
    ],
    models: [
        'Message'
    ],
    views: [
        'message.List',
        'message.Create',
        'message.Edit'
    ],
    init: function () {
        this.control({
            'messageList': {
                itemdblclick: this.editMessage,
                removeitem: this.removeMessage
            },
            'messageList > toolbar > button[action=create]': {
                click: this.onCreateMessage
            },
            'messageCreate button[action=save]': {
                click: this.doCreateMessage
            },
            'messageEdit button[action=save]': {
                click: this.updateMessage
            }
        });
    },
    editMessage: function (grid, record) {
        var view = Ext.widget('messageEdit');
        view.down('form').loadRecord(record);
    },
    removeMessage: function (msg) {
        Ext.Msg.confirm('Remove Message', 'Are you sure?', function (button) {
            if (button == 'yes') {
                Ext.getStore("MessageStore").remove(msg);
            }
        }, this);
    },
    onCreateMessage: function () {
        var view = Ext.widget('messageCreate');
    },
    doCreateMessage: function (button) {
        var win = button.up('window'),
            form = win.down('form'),
            values = form.getValues(),
            store = Ext.getStore("MessageStore");
        if (form.getForm().isValid()) {
            store.add(values);
            win.close();
        }
    },
    updateMessage: function (button) {
        var win = button.up('window'),
            form = win.down('form'),
            record = form.getRecord(),
            values = form.getValues(),
            store = Ext.getStore("MessageStore");
        if (form.getForm().isValid()) {
            record.set(values);
            win.close();
        }
    }
});<|endoftext|>


<commit_before>//
// Emapic panel
//

$('html body').append("\n" +
"
\n"+
"

" +
"

\n" +
"

\n" +
"

\n" +
"
");

var emapic = emapic || {};

(function(emapic) {

    var titlesidebarPanel = $('#titlesidebarPanel'),
    closesidebarPanel = $('#closesidebarPanel'),
    navContainer = $('#navContainer'),
    sidebarPanel,
    closesidebarPanelHtml = "<button type='button' title='" + emapic.utils.getI18n('js_close_panel', 'Cerrar') + "' onclick='emapic.sidebarPanelClose();'></button>",
    navHtml = "<button id='FirstButton' title='" + emapic.utils.getI18n('js_go_first', 'Ir al primero') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToFirst();'></button>\n" +
    "<button id='PrevButton' title='" + emapic.utils.getI18n('js_go_previous', 'Ir al anterior') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToPrevious();'></button>\n" +
    "<input type='text' id='CurrentFeatureNumber' maxlength='7'></input>/\n" +
    "<button id='NextButton' title='" + emapic.utils.getI18n('js_go_next', 'Ir al siguiente') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToNext();'></button>\n" +
    "<button id='LastButton' title='" + emapic.utils.getI18n('js_go_last', 'Ir al último') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToLast();'></button>\n",
    currentFeature = null,
    oldIcon = null,
    currentMarker = null,
    nrLayers,
    selectedLayerNr,
    layers;

    emapic.modules = emapic.modules || {};
    emapic.modules.panel = emapic.modules.panel || {};

    emapic.disableIndivLayerExclusiveComponents = emapic.utils.overrideFunction(emapic.disableIndivLayerExclusiveComponents, null, function() {
        oldIcon = null;
        currentMarker = null;
        emapic.sidebarPanelClose();
    });

    emapic.enableIndivLayerExclusiveComponents = emapic.utils.overrideFunction(emapic.enableIndivLayerExclusiveComponents, null, function() {
        oldIcon = null;
        currentMarker = null;
        emapic.sidebarPanelClose();
    });

    emapic.initializeMap = emapic.utils.overrideFunction(emapic.initializeMap, null, function() {
        sidebarPanel = L.control.sidebar('sidebarPanel', {
            position: 'topright',
            autoPan: false,
            closeButton: false
        });
        bodysidebarPanel();
        emapic.map.addControl(sidebarPanel);
        $('#CurrentFeatureNumber').keydown(featureNumberKeydown);
    });

    function bodysidebarPanel() {
        navContainer.html(navHtml);
        closesidebarPanel.html(closesidebarPanelHtml);
    }

    emapic.sidebarPanelClose = emapic.utils.overrideFunction(emapic.sidebarPanelClose, null, function() {
        sidebarPanel.hide();
        emapic.modules.panel.getColorPanelUnselect();
        currentFeature = null;
    });

    emapic.modules.panel.getPanelTitleHTML = function(properties) {
        return "
" + emapic.utils.getI18n('js_see_answers', 'Ver respuestas') + "
\n";
    };

    emapic.modules.panel.updateData = function(number) {
        currentFeature = number;
        var currentFeatureInput = $('#CurrentFeatureNumber');
        $('#TotalFeatures').text(nrLayers);
        currentFeatureInput.attr("size", (nrLayers.toString().length < 3) ? 3 : nrLayers.toString().length);
        currentFeatureInput.attr("maxlength", nrLayers.toString().length);
        currentFeatureInput.val(currentFeature + 1);
        $('#PrevButton').prop('disabled', currentFeature === 0);
        $('#NextButton').prop('disabled', currentFeature === (nrLayers - 1));
        var title = emapic.modules.panel.getPanelTitleHTML(layers[number].feature.properties);
        if (title !== null) {
            titlesidebarPanel.html(title);
            titlesidebarPanel.show();
        } else {
            titlesidebarPanel.hide();
        }
        $("#indivData").html(emapic.getPopupHtml(layers[number].feature.properties));
        if (!(emapic.map.getBounds().contains(layers[number].getLatLng()))) {
            emapic.map.setView(layers[number].getLatLng());
        }
    };

    emapic.modules.panel.getColorPanelSelect = function(number) {
        oldIcon = layers[number].options.icon;
        layers[number].setIcon(emapic.modules.panel.getSelectedIcon(layers[number].feature.properties));
    };

    emapic.modules.panel.getColorPanelUnselect = function() {
        if (currentMarker !== null && oldIcon !== null) {
            currentMarker.setIcon(oldIcon);
        }
        currentMarker = null;
        oldIcon = null;
    };

    emapic.modules.panel.getSelectedIcon = function(properties) {
        return L.divIcon({
            className: 'svg-marker',
            html: emapic.utils.getGlyphiconMarkerIconHtml(null, emapic.getIconColor(properties), 0.5, 7),
            iconAnchor: [16.5, 45]
        });
    };

    emapic.modules.panel.goToRegister = function(number) {
        if (number !== null && currentFeature !== number) {
            emapic.modules.panel.getColorPanelUnselect();
            currentMarker = layers[number];
            emapic.modules.panel.getColorPanelSelect(number);
            emapic.modules.panel.updateData(number);
        }
    };

    emapic.modules.panel.goToFirst =  function () {
        emapic.modules.panel.goToRegister(0);
    };

    emapic.modules.panel.goToLast = function () {
        emapic.modules.panel.goToRegister(layers.length - 1);
    };

    emapic.modules.panel.goToPrevious = function () {
        emapic.modules.panel.goToRegister(currentFeature - 1);
    };

    emapic.modules.panel.goToNext = function () {
        emapic.modules.panel.goToRegister(currentFeature + 1);
    };

    emapic.modules.panel.getDisplayedFeature = function() {
        return currentFeature !== null ? layers[currentFeature].feature : null;
    };

    emapic.indivVotesLayerOnEachFeature = emapic.utils.overrideFunction(emapic.indivVotesLayerOnEachFeature, null, function(data) {
        data.layer.unbindPopup();
        data.layer.on('click', function(e) {
            layers = emapic.getIndivVotesLayerLeafletLayers();
            nrLayers = layers.length;
            selectedLayerNr = null;
            for (var i = 0; i < nrLayers; i++) {
                if (layers[i].feature === data.feature) {
                    selectedLayerNr = i;
                    break;
                }
            }
            if (selectedLayerNr === null) {
                console.error("Can't find layer for panel.");
                return;
            }
            if (currentFeature === null) {
                emapic.sidebarPanelClose();
            }
            emapic.modules.panel.goToRegister(selectedLayerNr);
            sidebarPanel.show();
        });
    });

    function featureNumberKeydown(e) {
        if (emapic.utils.filterKeydownOnlyDigits(e)) {
            var key = e.keyCode || e.which;
            if (key === 13) {
                var valueCurrentNumber = parseInt($("#CurrentFeatureNumber").val(), 10);
                if (valueCurrentNumber <= 0) {
                    valueCurrentNumber = 1;
                } else if (valueCurrentNumber > nrLayers) {
                    valueCurrentNumber = nrLayers;
                }
                emapic.modules.panel.goToRegister(valueCurrentNumber - 1);
            }
        }
    }

}(emapic));
<commit_msg>Small improvement in panel module<commit_after>//
// Emapic panel
//

$('html body').append("\n" +
"
\n"+
"

" +
"

\n" +
"

\n" +
"

\n" +
"
");

var emapic = emapic || {};

(function(emapic) {

    var titlesidebarPanel = $('#titlesidebarPanel'),
    closesidebarPanel = $('#closesidebarPanel'),
    navContainer = $('#navContainer'),
    sidebarPanel,
    closesidebarPanelHtml = "<button type='button' title='" + emapic.utils.getI18n('js_close_panel', 'Cerrar') + "' onclick='emapic.sidebarPanelClose();'></button>",
    navHtml = "<button id='FirstButton' title='" + emapic.utils.getI18n('js_go_first', 'Ir al primero') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToFirst();'></button>\n" +
    "<button id='PrevButton' title='" + emapic.utils.getI18n('js_go_previous', 'Ir al anterior') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToPrevious();'></button>\n" +
    "<input type='text' id='CurrentFeatureNumber' maxlength='7'></input>/\n" +
    "<button id='NextButton' title='" + emapic.utils.getI18n('js_go_next', 'Ir al siguiente') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToNext();'></button>\n" +
    "<button id='LastButton' title='" + emapic.utils.getI18n('js_go_last', 'Ir al último') + "' class='btn btn-default btn-xs' onclick='emapic.modules.panel.goToLast();'></button>\n",
    currentFeature = null,
    oldIcon = null,
    currentMarker = null,
    nrLayers,
    selectedLayerNr,
    layers;

    emapic.modules = emapic.modules || {};
    emapic.modules.panel = emapic.modules.panel || {};

    emapic.disableIndivLayerExclusiveComponents = emapic.utils.overrideFunction(emapic.disableIndivLayerExclusiveComponents, null, function() {
        oldIcon = null;
        currentMarker = null;
        if (currentFeature !== null) {
            emapic.sidebarPanelClose();
        }
    });

    emapic.enableIndivLayerExclusiveComponents = emapic.utils.overrideFunction(emapic.enableIndivLayerExclusiveComponents, null, function() {
        oldIcon = null;
        currentMarker = null;
        if (currentFeature !== null) {
            emapic.sidebarPanelClose();
        }
    });

    emapic.initializeMap = emapic.utils.overrideFunction(emapic.initializeMap, null, function() {
        sidebarPanel = L.control.sidebar('sidebarPanel', {
            position: 'topright',
            autoPan: false,
            closeButton: false
        });
        bodysidebarPanel();
        emapic.map.addControl(sidebarPanel);
        $('#CurrentFeatureNumber').keydown(featureNumberKeydown);
    });

    function bodysidebarPanel() {
        navContainer.html(navHtml);
        closesidebarPanel.html(closesidebarPanelHtml);
    }

    emapic.sidebarPanelClose = emapic.utils.overrideFunction(emapic.sidebarPanelClose, null, function() {
        sidebarPanel.hide();
        emapic.modules.panel.getColorPanelUnselect();
        currentFeature = null;
    });

    emapic.modules.panel.getPanelTitleHTML = function(properties) {
        return "
" + emapic.utils.getI18n('js_see_answers', 'Ver respuestas') + "
\n";
    };

    emapic.modules.panel.updateData = function(number) {
        currentFeature = number;
        var currentFeatureInput = $('#CurrentFeatureNumber');
        $('#TotalFeatures').text(nrLayers);
        currentFeatureInput.attr("size", (nrLayers.toString().length < 3) ? 3 : nrLayers.toString().length);
        currentFeatureInput.attr("maxlength", nrLayers.toString().length);
        currentFeatureInput.val(currentFeature + 1);
        $('#PrevButton').prop('disabled', currentFeature === 0);
        $('#NextButton').prop('disabled', currentFeature === (nrLayers - 1));
        var title = emapic.modules.panel.getPanelTitleHTML(layers[number].feature.properties);
        if (title !== null) {
            titlesidebarPanel.html(title);
            titlesidebarPanel.show();
        } else {
            titlesidebarPanel.hide();
        }
        $("#indivData").html(emapic.getPopupHtml(layers[number].feature.properties));
        if (!(emapic.map.getBounds().contains(layers[number].getLatLng()))) {
            emapic.map.setView(layers[number].getLatLng());
        }
    };

    emapic.modules.panel.getColorPanelSelect = function(number) {
        oldIcon = layers[number].options.icon;
        layers[number].setIcon(emapic.modules.panel.getSelectedIcon(layers[number].feature.properties));
    };

    emapic.modules.panel.getColorPanelUnselect = function() {
        if (currentMarker !== null && oldIcon !== null) {
            currentMarker.setIcon(oldIcon);
        }
        currentMarker = null;
        oldIcon = null;
    };

    emapic.modules.panel.getSelectedIcon = function(properties) {
        return L.divIcon({
            className: 'svg-marker',
            html: emapic.utils.getGlyphiconMarkerIconHtml(null, emapic.getIconColor(properties), 0.5, 7),
            iconAnchor: [16.5, 45]
        });
    };

    emapic.modules.panel.goToRegister = function(number) {
        if (number !== null && currentFeature !== number) {
            emapic.modules.panel.getColorPanelUnselect();
            currentMarker = layers[number];
            emapic.modules.panel.getColorPanelSelect(number);
            emapic.modules.panel.updateData(number);
        }
    };

    emapic.modules.panel.goToFirst =  function () {
        emapic.modules.panel.goToRegister(0);
    };

    emapic.modules.panel.goToLast = function () {
        emapic.modules.panel.goToRegister(layers.length - 1);
    };

    emapic.modules.panel.goToPrevious = function () {
        emapic.modules.panel.goToRegister(currentFeature - 1);
    };

    emapic.modules.panel.goToNext = function () {
        emapic.modules.panel.goToRegister(currentFeature + 1);
    };

    emapic.modules.panel.getDisplayedFeature = function() {
        return currentFeature !== null ? layers[currentFeature].feature : null;
    };

    emapic.indivVotesLayerOnEachFeature = emapic.utils.overrideFunction(emapic.indivVotesLayerOnEachFeature, null, function(data) {
        data.layer.unbindPopup();
        data.layer.on('click', function(e) {
            layers = emapic.getIndivVotesLayerLeafletLayers();
            nrLayers = layers.length;
            selectedLayerNr = null;
            for (var i = 0; i < nrLayers; i++) {
                if (layers[i].feature === data.feature) {
                    selectedLayerNr = i;
                    break;
                }
            }
            if (selectedLayerNr === null) {
                console.error("Can't find layer for panel.");
                return;
            }
            if (currentFeature === null) {
                emapic.sidebarPanelClose();
            }
            emapic.modules.panel.goToRegister(selectedLayerNr);
            sidebarPanel.show();
        });
    });

    function featureNumberKeydown(e) {
        if (emapic.utils.filterKeydownOnlyDigits(e)) {
            var key = e.keyCode || e.which;
            if (key === 13) {
                var valueCurrentNumber = parseInt($("#CurrentFeatureNumber").val(), 10);
                if (valueCurrentNumber <= 0) {
                    valueCurrentNumber = 1;
                } else if (valueCurrentNumber > nrLayers) {
                    valueCurrentNumber = nrLayers;
                }
                emapic.modules.panel.goToRegister(valueCurrentNumber - 1);
            }
        }
    }

}(emapic));
<|endoftext|>


<commit_before>WYMeditor.STRINGS['pt-BR'] = {
  Bold: 'Negrito',
	Strong:			 'Resaltar',
	Emphasis:		 'Itálico',
	Superscript:		'Sobre escrito',
	Subscript:		'Sub escrito ',
	Ordered_List:	 'Lista ordenada',
	Unordered_List:	 'Lista desordenada',
	Indent:			 'Indentado',
	Outdent:			'Desidentar',
	Undo:			 'Desfazer',
	Redo:			 'Refazer',
	Link:			 'Link',
	Unlink:			 'Remover Link',
	Image:			'Imagem',
	Table:			'Tabela',
	HTML:			 'HTML',
	Paragraph:		'Parágrafo',
	Heading_1:		'Título 1',
	Heading_2:		'Título 2',
	Heading_3:		'Título 3',
	Heading_4:		'Título 4',
	Heading_5:		'Título 5',
	Heading_6:		'Título 6',
	Preformatted:	 'Preformatado',
	Blockquote:		 'Citação',
	Table_Header:	 'Título de tabela',
	URL:				'URL',
	Title:			'Título',
	Alternative_Text: 'Texto alternativo',
	Caption:			'Legenda',
	Summary:			'Summary',
	Number_Of_Rows:	 'Número de linhas',
	Number_Of_Cols:	 'Número de colunas',
	Submit:			 'Enviar',
	Cancel:			 'Cancelar',
	Choose:			 'Selecionar',
	Preview:			'Previsualizar',
	Paste_From_Word:	'Copiar do Word',
	Tools:			'Ferramentas',
	Containers:		 'Conteneiners',
	Classes:			'Classes',
	Status:			 'Estado',
	Source_Code:		'Código fonte'
};

<commit_msg>missing portuguese translations for wymeditor<commit_after>WYMeditor.STRINGS['pt-BR'] = {
	Bold: 'Negrito',
	Strong: 'Resaltar',
	Emphasis: 'Itálico',
	Superscript: 'Sobre escrito',
	Subscript: 'Sub escrito ',
	Ordered_List: 'Lista ordenada',
	Unordered_List: 'Lista desordenada',
	Indent: 'Indentado',
	Outdent: 'Desidentar',
	Undo: 'Desfazer',
	Redo: 'Refazer',
	Link: 'Link',
	Unlink: 'Remover Link',
	Image: 'Imagem',
	Table: 'Tabela',
	HTML: 'HTML',
	Paragraph: 'Parágrafo',
	Heading_1: 'Título 1',
	Heading_2: 'Título 2',
	Heading_3: 'Título 3',
	Heading_4: 'Título 4',
	Heading_5: 'Título 5',
	Heading_6: 'Título 6',
	Preformatted: 'Preformatado',
	Blockquote: 'Citação',
	Table_Header: 'Título de tabela',
	URL: 'URL',
	Title: 'Título',
	Alternative_Text: 'Texto alternativo',
	Caption: 'Legenda',
	Summary: 'Summary',
	Number_Of_Rows: 'Número de linhas',
	Number_Of_Cols: 'Número de colunas',
	Insert: 'Inserir',
	Submit: 'Enviar',
	Cancel: 'Cancelar',
	Choose: 'Selecionar',
	Preview: 'Previsualizar',
	Paste_From_Word: 'Copiar do Word',
	Tools: 'Ferramentas',
	Containers: 'Conteneiners',
	Classes: 'Classes',
	Status: 'Estado',
	Source_Code: 'Código fonte',
	Css_Class: 'Aplicar classe CSS'
};
<|endoftext|>


<commit_before>/**
 * Controller for the product view
 *
 * Links:
 * http://blog.nebithi.com/angularjs-dos-and-donts/
 *
 * Problems:
 * http://stackoverflow.com/questions/12618342/ng-model-does-not-update-controller-value
 * http://stackoverflow.com/questions/18880737/how-do-i-use-rootscope-in-angular-to-store-variables
 * Each time a ng-controller is found, another $scope is created, which is why $rootScope is sometimes necessary
 * http://stackoverflow.com/questions/27770402/ng-repeat-not-updating-after-array-update#answer-27771130
 *
 * TODO controllers tend to clutter unnecessary business logic, refactor to utilities/services
 */
angular.module('emagScoresApp')
    .run(function ($rootScope) {
        //TODO products doesn't have to be on root scope
        $rootScope.products = [];
        $rootScope.paginator = {
            maxPages: 5,
            currentPage: 1,
            resultsPerPage: 5
        };
        $rootScope.search = { keyword : '' };
    })
    .controller('ProductController', function($rootScope, $scope, $log, ProductFactory, ProductService, CategoryFactory) {
        // current active browse type -> category nav/search
        //$scope.type = '';
        $scope.searchInputEnter = function (keyEvent) {
            if (keyEvent.which === 13) {
                $rootScope.type = 'title';
                $scope.retrieveTotalNrOfProducts($rootScope.type, $rootScope.search.keyword);
                // reset pagination
                $rootScope.paginator.currentPage = 1;
                $scope.displaySearchProducts();
            }
        };

        $scope.pageChanged = function() {
            $log.log("Changed to 2: " + $rootScope.paginator.currentPage);
            if ($rootScope.type === 'title')
                $scope.displaySearchProducts();
            else
                $scope.displayProducts();
        };

        $scope.ratingStyleClass = function(ratingScore, index) {
            if (ratingScore >= (index + 1) * 20)
                return 'fa fa-star';
            else if (ratingScore > index * 20)
                return 'fa fa-star-half-o';
            else
                return 'fa fa-star-o';
        };

        $scope.setProduct = function(data) {
            ProductFactory.setProduct(data);
        };

        $scope.emagBase = "http://www.emag.ro";
        $scope.displayProducts = function () {
            ProductService.retrieveProducts($rootScope.subcategory.name, $rootScope.paginator.currentPage, $rootScope.paginator.resultsPerPage)
                .then(function (json) {
                    // promise fulfilled
                    $rootScope.products = json;
                }, function(error) {
                    // display error message in UI
                });
        };
        $scope.displaySearchProducts = function () {
            ProductService.searchProducts($rootScope.search.keyword, $rootScope.paginator.currentPage, $rootScope.paginator.resultsPerPage)
                .then(function (json) {
                    // promise fulfilled
                    $rootScope.products = json;
                }, function(error) {
                    // display error message in UI
                });
        };
        $scope.retrieveTotalNrOfProducts = function (type, keyword) {
            ProductService.retrieveTotalNrOfProducts({ type : type, keyword : keyword })
                .then(function (total) {
                    // promise fulfilled
                    $rootScope.paginator.total = total;
                }, function(error) {
                    // display error message in UI
                });
        };

/*        CategoryFactory.initCategory(function (data) {
            $scope.subcategory = data;
            $scope.retrieveTotalNrOfProducts('category', $scope.subcategory.name);
        });*/

        /**
         * Listens to category changed events coming from category view
         */
        $scope.$on('categoryChanged', function () {
            $rootScope.type = 'category';
            $rootScope.subcategory = CategoryFactory.getCategory();
            $scope.retrieveTotalNrOfProducts($rootScope.type, $rootScope.subcategory.name);
            // reset pagination
            $rootScope.paginator.currentPage = 1;
            $scope.displayProducts();
        });
});<commit_msg>remove commented code<commit_after>/**
 * Controller for the product view
 *
 * Links:
 * http://blog.nebithi.com/angularjs-dos-and-donts/
 *
 * Problems:
 * http://stackoverflow.com/questions/12618342/ng-model-does-not-update-controller-value
 * http://stackoverflow.com/questions/18880737/how-do-i-use-rootscope-in-angular-to-store-variables
 * Each time a ng-controller is found, another $scope is created, which is why $rootScope is sometimes necessary
 * http://stackoverflow.com/questions/27770402/ng-repeat-not-updating-after-array-update#answer-27771130
 *
 * TODO controllers tend to clutter unnecessary business logic, refactor to utilities/services
 */
angular.module('emagScoresApp')
    .run(function ($rootScope) {
        //TODO products doesn't have to be on root scope
        $rootScope.products = [];
        $rootScope.paginator = {
            maxPages: 5,
            currentPage: 1,
            resultsPerPage: 5
        };
        $rootScope.search = { keyword : '' };
    })
    .controller('ProductController', function($rootScope, $scope, $log, ProductFactory, ProductService, CategoryFactory) {
        // current active browse type -> category nav/search
        //$scope.type = '';
        $scope.searchInputEnter = function (keyEvent) {
            if (keyEvent.which === 13) {
                $rootScope.type = 'title';
                $scope.retrieveTotalNrOfProducts($rootScope.type, $rootScope.search.keyword);
                // reset pagination
                $rootScope.paginator.currentPage = 1;
                $scope.displaySearchProducts();
            }
        };

        $scope.pageChanged = function() {
            $log.log("Changed to 2: " + $rootScope.paginator.currentPage);
            if ($rootScope.type === 'title')
                $scope.displaySearchProducts();
            else
                $scope.displayProducts();
        };

        $scope.ratingStyleClass = function(ratingScore, index) {
            if (ratingScore >= (index + 1) * 20)
                return 'fa fa-star';
            else if (ratingScore > index * 20)
                return 'fa fa-star-half-o';
            else
                return 'fa fa-star-o';
        };

        $scope.setProduct = function(data) {
            ProductFactory.setProduct(data);
        };

        $scope.emagBase = "http://www.emag.ro";
        $scope.displayProducts = function () {
            ProductService.retrieveProducts($rootScope.subcategory.name, $rootScope.paginator.currentPage, $rootScope.paginator.resultsPerPage)
                .then(function (json) {
                    // promise fulfilled
                    $rootScope.products = json;
                }, function(error) {
                    // display error message in UI
                });
        };
        $scope.displaySearchProducts = function () {
            ProductService.searchProducts($rootScope.search.keyword, $rootScope.paginator.currentPage, $rootScope.paginator.resultsPerPage)
                .then(function (json) {
                    // promise fulfilled
                    $rootScope.products = json;
                }, function(error) {
                    // display error message in UI
                });
        };
        $scope.retrieveTotalNrOfProducts = function (type, keyword) {
            ProductService.retrieveTotalNrOfProducts({ type : type, keyword : keyword })
                .then(function (total) {
                    // promise fulfilled
                    $rootScope.paginator.total = total;
                }, function(error) {
                    // display error message in UI
                });
        };

        /**
         * Listens to category changed events coming from category view
         */
        $scope.$on('categoryChanged', function () {
            $rootScope.type = 'category';
            $rootScope.subcategory = CategoryFactory.getCategory();
            $scope.retrieveTotalNrOfProducts($rootScope.type, $rootScope.subcategory.name);
            // reset pagination
            $rootScope.paginator.currentPage = 1;
            $scope.displayProducts();
        });
});<|endoftext|>


<commit_before>'use strict';

var assign           = require('es5-ext/object/assign')
  , create           = require('es5-ext/object/create')
  , eq               = require('es5-ext/object/eq')
  , setPrototypeOf   = require('es5-ext/object/set-prototype-of')
  , forOf            = require('es6-iterator/for-of')
  , isIterable       = require('es6-iterator/is-iterable')
  , setCopy          = require('es6-set/ext/copy')
  , setEvery         = require('es6-set/ext/every')
  , setSome          = require('es6-set/ext/some')
  , d                = require('d/d')
  , lazy             = require('d/lazy')
  , Set              = require('observable-set/create-read-only')(
	require('es6-set/polyfill')
)
  , ReadOnly         = require('observable-set/create-read-only')(
	require('es6-set/primitive')
)
  , defineObservable = require('../utils/define-set-observable')
  , observePass      = require('../utils/observe-pass-through')
  , serialize        = require('../serialize/value')

  , forEach = Array.prototype.forEach
  , defineProperties = Object.defineProperties
  , Multiple;

Multiple = module.exports = function (object, sKey, value) {
	var iterate, desc;
	if (!(this instanceof Multiple)) return new Multiple(object, sKey);
	Set.call(this);
	defineProperties(this, {
		object: d('', object),
		__sKey__: d('', sKey)
	});
	if (value == null) return;
	desc = object._getDescriptor_(sKey);
	iterate = function (value) {
		if (value == null) return;
		value = desc._normalizeValue_(value);
		if (value == null) return;
		if (this.eIndexOf(value) !== -1) return;
		this.push(value);
	};
	if (isIterable(value)) forOf(value, iterate, this.__setData__);
	else forEach.call(value, iterate, this.__setData__);
};
setPrototypeOf(Multiple, Set);

Multiple.prototype = create(Set.prototype, assign({
	constructor: d(Multiple),
	copy: d(setCopy),
	every: d(setEvery),
	some: d(setSome),
	_doClear_: d(function (dbEvent) {
		var event;
		if (!this.__isObservable__) {
			this._clear();
			return;
		}
		if (!this.__postponed__) {
			this._clear();
			this.emit('change', { type: 'clear', dbjs: dbEvent });
			return;
		}
		event = this.__postponedEvent__;
		if (!event) {
			event = this.__postponedEvent__ =
				{ deleted: new ReadOnly(this, serialize) };
		} else {
			this.forEach(function (value) {
				if (event.added && event.added.has(value)) {
					event.added._delete(value);
					return;
				}
				if (!event.deleted) event.deleted = new ReadOnly(null, serialize);
				event.deleted._add(value);
			}, this);
		}
		if (dbEvent) event.dbjs = dbEvent;
		this._clear();
	}),
	_noteAdd_: d(function (value) {
		var event = this.__postponedEvent__;
		if (!event) event = this.__postponedEvent__ = {};
		if (event.deleted && event.deleted.has(value)) {
			event.deleted._delete(value);
			return;
		}
		if (!event.added) event.added = new ReadOnly(null, serialize);
		event.added._add(value);
	}),
	_noteDelete_: d(function (value) {
		var event = this.__postponedEvent__;
		if (!event) event = this.__postponedEvent__ = {};
		if (event.added && event.added.has(value)) {
			event.added._delete(value);
			return;
		}
		if (!event.deleted) event.deleted = new ReadOnly(null, serialize);
		event.deleted._add(value);
	}),
	_update_: d(function (value, dbEvent) {
		var index, setData, desc, iterate, l, isObservable;
		if (value == null) {
			if (!this.__size__) return;
			this._doClear_();
			return;
		}
		setData = this.__setData__;
		desc = this.object.__descriptors__[this.sKey] ||
			this.object.__descriptorPrototype__;
		index = 0;
		l = setData.length;
		isObservable = this.__isObservable__;
		if (isObservable) ++this._postponed_;
		iterate = function (value) {
			var i;
			if (value == null) return;
			value = desc._normalizeValue_(value);
			if (value == null) return;
			if (eq(setData[index], value)) {
				++index;
				return;
			}
			i = setData.eIndexOf(value);
			if (i === -1) {
				if (index === setData.length) setData.push(value);
				else setData.splice(index, 0, value);
				++l;
				this.emit('_add', index, value);
				if (isObservable) this._noteAdd_(value);
				++index;
				return;
			}
			if (i < index) return;
			setData.splice(i, 1);
			this.emit('_delete', i, value);
			setData.splice(index, 0, value);
			this.emit('_add', index, value);
			++index;
		};
		if (isIterable(value)) forOf(value, iterate, this);
		else forEach.call(value, iterate, this);
		if ((index === 0) && l) {
			if (isObservable) --this._postponed_;
			this._doClear_(dbEvent);
			return;
		}
		while (l > index) {
			value = setData.pop();
			this.emit('_delete', --l, value);
			if (isObservable) this._noteDelete_(value);
		}
		if (dbEvent && this.__postponedEvent__) {
			this.__postponedEvent__.dbjs = dbEvent;
		}
		if (isObservable) --this._postponed_;
	}),
	_updateGetter_: d(function (getter) {
		if (this.__isObservable__) return;
		this._update_(getter ? getter.call(this.object, observePass) : null);
	}),
	_triggerObservable_: d(function () {
		var dynamicValue, desc;
		dynamicValue = this.object._getDynamicValue_(this.__sKey__);
		if (dynamicValue.value === null) {
			this._update_(null);
			return;
		}
		desc = this.object.__descriptors__[this.__sKey__] ||
			this.object.__descriptorPrototype__;
		if (!desc.multiple) return;
		this._update_(dynamicValue.value);
	})
}, lazy({
	_dynamicListeners_: d(function () { return []; },
		{ cacheName: '__dynamicListeners__', desc: '' })
})));
defineObservable(Multiple.prototype, Multiple.prototype._triggerObservable_);
<commit_msg>Update up to changes in es6-set<commit_after>'use strict';

var eIndexOf         = require('es5-ext/array/#/e-index-of')
  , assign           = require('es5-ext/object/assign')
  , create           = require('es5-ext/object/create')
  , eq               = require('es5-ext/object/eq')
  , setPrototypeOf   = require('es5-ext/object/set-prototype-of')
  , forOf            = require('es6-iterator/for-of')
  , isIterable       = require('es6-iterator/is-iterable')
  , setCopy          = require('es6-set/ext/copy')
  , setEvery         = require('es6-set/ext/every')
  , setSome          = require('es6-set/ext/some')
  , d                = require('d/d')
  , lazy             = require('d/lazy')
  , Set              = require('observable-set/create-read-only')(
	require('es6-set/polyfill')
)
  , ReadOnly         = require('observable-set/create-read-only')(
	require('es6-set/primitive')
)
  , defineObservable = require('../utils/define-set-observable')
  , observePass      = require('../utils/observe-pass-through')
  , serialize        = require('../serialize/value')

  , forEach = Array.prototype.forEach
  , defineProperties = Object.defineProperties
  , Multiple;

Multiple = module.exports = function (object, sKey, value) {
	var iterate, desc;
	if (!(this instanceof Multiple)) return new Multiple(object, sKey);
	Set.call(this);
	defineProperties(this, {
		object: d('', object),
		__sKey__: d('', sKey)
	});
	if (value == null) return;
	desc = object._getDescriptor_(sKey);
	iterate = function (value) {
		if (value == null) return;
		value = desc._normalizeValue_(value);
		if (value == null) return;
		if (eIndexOf.call(this, value) !== -1) return;
		this.push(value);
	};
	if (isIterable(value)) forOf(value, iterate, this.__setData__);
	else forEach.call(value, iterate, this.__setData__);
};
setPrototypeOf(Multiple, Set);

Multiple.prototype = create(Set.prototype, assign({
	constructor: d(Multiple),
	copy: d(setCopy),
	every: d(setEvery),
	some: d(setSome),
	_doClear_: d(function (dbEvent) {
		var event;
		if (!this.__isObservable__) {
			this._clear();
			return;
		}
		if (!this.__postponed__) {
			this._clear();
			this.emit('change', { type: 'clear', dbjs: dbEvent });
			return;
		}
		event = this.__postponedEvent__;
		if (!event) {
			event = this.__postponedEvent__ =
				{ deleted: new ReadOnly(this, serialize) };
		} else {
			this.forEach(function (value) {
				if (event.added && event.added.has(value)) {
					event.added._delete(value);
					return;
				}
				if (!event.deleted) event.deleted = new ReadOnly(null, serialize);
				event.deleted._add(value);
			}, this);
		}
		if (dbEvent) event.dbjs = dbEvent;
		this._clear();
	}),
	_noteAdd_: d(function (value) {
		var event = this.__postponedEvent__;
		if (!event) event = this.__postponedEvent__ = {};
		if (event.deleted && event.deleted.has(value)) {
			event.deleted._delete(value);
			return;
		}
		if (!event.added) event.added = new ReadOnly(null, serialize);
		event.added._add(value);
	}),
	_noteDelete_: d(function (value) {
		var event = this.__postponedEvent__;
		if (!event) event = this.__postponedEvent__ = {};
		if (event.added && event.added.has(value)) {
			event.added._delete(value);
			return;
		}
		if (!event.deleted) event.deleted = new ReadOnly(null, serialize);
		event.deleted._add(value);
	}),
	_update_: d(function (value, dbEvent) {
		var index, setData, desc, iterate, l, isObservable;
		if (value == null) {
			if (!this.__size__) return;
			this._doClear_();
			return;
		}
		setData = this.__setData__;
		desc = this.object.__descriptors__[this.sKey] ||
			this.object.__descriptorPrototype__;
		index = 0;
		l = setData.length;
		isObservable = this.__isObservable__;
		if (isObservable) ++this._postponed_;
		iterate = function (value) {
			var i;
			if (value == null) return;
			value = desc._normalizeValue_(value);
			if (value == null) return;
			if (eq(setData[index], value)) {
				++index;
				return;
			}
			i = eIndexOf.call(setData, value);
			if (i === -1) {
				if (index === setData.length) setData.push(value);
				else setData.splice(index, 0, value);
				++l;
				this.emit('_add', index, value);
				if (isObservable) this._noteAdd_(value);
				++index;
				return;
			}
			if (i < index) return;
			setData.splice(i, 1);
			this.emit('_delete', i, value);
			setData.splice(index, 0, value);
			this.emit('_add', index, value);
			++index;
		};
		if (isIterable(value)) forOf(value, iterate, this);
		else forEach.call(value, iterate, this);
		if ((index === 0) && l) {
			if (isObservable) --this._postponed_;
			this._doClear_(dbEvent);
			return;
		}
		while (l > index) {
			value = setData.pop();
			this.emit('_delete', --l, value);
			if (isObservable) this._noteDelete_(value);
		}
		if (dbEvent && this.__postponedEvent__) {
			this.__postponedEvent__.dbjs = dbEvent;
		}
		if (isObservable) --this._postponed_;
	}),
	_updateGetter_: d(function (getter) {
		if (this.__isObservable__) return;
		this._update_(getter ? getter.call(this.object, observePass) : null);
	}),
	_triggerObservable_: d(function () {
		var dynamicValue, desc;
		dynamicValue = this.object._getDynamicValue_(this.__sKey__);
		if (dynamicValue.value === null) {
			this._update_(null);
			return;
		}
		desc = this.object.__descriptors__[this.__sKey__] ||
			this.object.__descriptorPrototype__;
		if (!desc.multiple) return;
		this._update_(dynamicValue.value);
	})
}, lazy({
	_dynamicListeners_: d(function () { return []; },
		{ cacheName: '__dynamicListeners__', desc: '' })
})));
defineObservable(Multiple.prototype, Multiple.prototype._triggerObservable_);
<|endoftext|>