<commit_before>/*!
 * @module report
 * @author kael, chriscai
 * @date @DATE
 * Copyright (c) 2014 kael, chriscai
 * Licensed under the MIT license.
 */
var BJ_REPORT = (function(global) {
    if (global.BJ_REPORT) return global.BJ_REPORT;

    var _error = [];
    var _config = {
        id: 0,
        uin: 0,
        url: "",
        combo: 1,
        ext: {},
        level: 4, // 1-debug 2-info 4-error
        ignore: [],
        random: 1,
        delay: 1000,
        submit: null
    };

    var _isOBJByType = function(o, type) {
        return Object.prototype.toString.call(o) === "[object " + (type || "Object") + "]";
    };

    var _isOBJ = function(obj) {
        var type = typeof obj;
        return type === "object" && !!obj;
    };

    var _isEmpty = function(obj) {
        if (obj === null) return true;
        if(_isOBJByType(obj , 'Number')){
            return false;
        }
        return !obj;
    };

    var orgError = global.onerror;
    // rewrite window.oerror
    global.onerror = function(msg, url, line, col, error) {
        var newMsg = msg;

        if (error && error.stack) {
            newMsg = _processStackMsg(error);
        }

        if (_isOBJByType(newMsg, "Event")) {
            newMsg += newMsg.type ? ("--" + newMsg.type + "--" + (newMsg.target ? (newMsg.target.tagName + "::" + newMsg.target.src) : "")) : "";
        }

        report.push({
            msg: newMsg,
            target: url,
            rowNum: line,
            colNum: col
        });

        _send();
        orgError && orgError.apply(global, arguments);
    };

    var _processError = function(errObj) {
        try {
            if (errObj.stack) {
                var url = errObj.stack.match("https?://[^\n]+");
                url = url ? url[0] : "";
                var rowCols = url.match(":(\\d+):(\\d+)");
                if (!rowCols) {
                    rowCols = [0, 0, 0];
                }

                var stack = _processStackMsg(errObj);
                return {
                    msg: stack,
                    rowNum: rowCols[1],
                    colNum: rowCols[2],
                    target: url.replace(rowCols[0], "")
                };
            } else {
                return errObj;
            }
        } catch (err) {
            return errObj;
        }
    };

    var _processStackMsg = function(error) {
        var stack = error.stack.replace(/\n/gi, "").split(/\bat\b/).slice(0, 5).join("@").replace(/\?[^:]+/gi, "");
        var msg = error.toString();
        if (stack.indexOf(msg) < 0) {
            stack = msg + "@" + stack;
        }
        return stack;
    };

    var _error_tostring = function(error, index) {
        var param = [];
        var params = [];
        var stringify = [];
        if (_isOBJ(error)) {
            error.level = error.level || _config.level;
            for (var key in error) {
                var value = error[key];
                if (!_isEmpty(value)) {
                    if (_isOBJ(value)) {
                        try {
                            value = JSON.stringify(value);
                        } catch (err) {
                            value = "[BJ_REPORT detect value stringify error] " + err.toString();
                        }
                    }
                    stringify.push(key + ":" + value);
                    param.push(key + "=" + encodeURIComponent(value));
                    params.push(key + "[" + index + "]=" + encodeURIComponent(value));
                }
            }
        }

        // msg[0]=msg&target[0]=target -- combo report
        // msg:msg,target:target -- ignore
        // msg=msg&target=target -- report with out combo
        return [params.join("&"), stringify.join(","), param.join("&")];
    };

    var _imgs = [];
    var _submit = function(url) {
        if (_config.submit) {
            _config.submit(url);
        } else {
            var _img = new Image();
            _imgs.push(_img);
            _img.src = url;
        }
    };

    var error_list = [];
    var comboTimeout = 0;
    var _send = function(isReoprtNow) {
        if (!_config.report) return;

        while (_error.length) {
            var isIgnore = false;
            var error = _error.shift();
            var error_str = _error_tostring(error, error_list.length);
            if (_isOBJByType(_config.ignore, "Array")) {
                for (var i = 0, l = _config.ignore.length; i < l; i++) {
                    var rule = _config.ignore[i];
                    if ((_isOBJByType(rule, "RegExp") && rule.test(error_str[1])) ||
                        (_isOBJByType(rule, "Function") && rule(error, error_str[1]))) {
                        isIgnore = true;
                        break;
                    }
                }
            }
            if (!isIgnore) {
                if (_config.combo) {
                    error_list.push(error_str[0]);
                } else {
                    _submit(_config.report + error_str[2] + "&_t=" + (+new Date));
                }
                _config.onReport && (_config.onReport(_config.id, error));
            }
        }

        // 合并上报
        var count = error_list.length;
        if (count) {
            var comboReport = function() {
                clearTimeout(comboTimeout);
                _submit(_config.report + error_list.join("&") + "&count=" + count + "&_t=" + (+new Date));
                comboTimeout = 0;
                error_list = [];
            };

            if (isReoprtNow) {
                comboReport(); // 立即上报
            } else if (!comboTimeout) {
                comboTimeout = setTimeout(comboReport, _config.delay); // 延迟上报
            }
        }
    };

    var report = {
        push: function(msg) { // 将错误推到缓存池
            if (Math.random() >= _config.random) {
                return report;
            }
            _error.push(_isOBJ(msg) ? _processError(msg) : {
                msg: msg
            });
            _send();
            return report;
        },
        report: function(msg) { // error report
            msg && report.push(msg);
            _send(true);
            return report;
        },
        info: function(msg) { // info report
            if (!msg) {
                return report;
            }
            if (_isOBJ(msg)) {
                msg.level = 2;
            } else {
                msg = {
                    msg: msg,
                    level: 2
                };
            }
            report.push(msg);
            return report;
        },
        debug: function(msg) { // debug report
            if (!msg) {
                return report;
            }
            if (_isOBJ(msg)) {
                msg.level = 1;
            } else {
                msg = {
                    msg: msg,
                    level: 1
                };
            }
            report.push(msg);
            return report;
        },
        init: function(config) { // 初始化
            if (_isOBJ(config)) {
                for (var key in config) {
                    _config[key] = config[key];
                }
            }
            // 没有设置id将不上报
            var id = parseInt(_config.id, 10);
            if (id) {
                _config.report = (_config.url || "//badjs2.qq.com/badjs") + "?id=" + id + "&uin=" + parseInt(_config.uin || (document.cookie.match(/\buin=\D+(\d+)/) || [])[1], 10) + "&from=" + encodeURIComponent(location.href) + "&ext=" + JSON.stringify(_config.ext) + "&";
            }
            return report;
        },

        __onerror__: global.onerror
    };

    typeof console !== "undefined" && console.error && setTimeout(function() {
        var err = ((location.hash || '').match(/([#&])BJ_ERROR=([^&$]+)/) || [])[2];
        err && console.error("BJ_ERROR", decodeURIComponent(err).replace(/(:\d+:\d+)\s*/g, '$1\n'));
    }, 0);

    return report;

}(window));

if (typeof exports !== "undefined") {
    if (typeof module !== "undefined" && module.exports) {
        exports = module.exports = BJ_REPORT;
    }
    exports.BJ_REPORT = BJ_REPORT;
}
<commit_msg>reset ext<commit_after>/*!
 * @module report
 * @author kael, chriscai
 * @date @DATE
 * Copyright (c) 2014 kael, chriscai
 * Licensed under the MIT license.
 */
var BJ_REPORT = (function(global) {
    if (global.BJ_REPORT) return global.BJ_REPORT;

    var _error = [];
    var _config = {
        id: 0,
        uin: 0,
        url: "",
        combo: 1,
        ext: null,
        level: 4, // 1-debug 2-info 4-error
        ignore: [],
        random: 1,
        delay: 1000,
        submit: null
    };

    var _isOBJByType = function(o, type) {
        return Object.prototype.toString.call(o) === "[object " + (type || "Object") + "]";
    };

    var _isOBJ = function(obj) {
        var type = typeof obj;
        return type === "object" && !!obj;
    };

    var _isEmpty = function(obj) {
        if (obj === null) return true;
        if (_isOBJByType(obj, 'Number')) {
            return false;
        }
        return !obj;
    };

    var orgError = global.onerror;
    // rewrite window.oerror
    global.onerror = function(msg, url, line, col, error) {
        var newMsg = msg;

        if (error && error.stack) {
            newMsg = _processStackMsg(error);
        }

        if (_isOBJByType(newMsg, "Event")) {
            newMsg += newMsg.type ? ("--" + newMsg.type + "--" + (newMsg.target ? (newMsg.target.tagName + "::" + newMsg.target.src) : "")) : "";
        }

        report.push({
            msg: newMsg,
            target: url,
            rowNum: line,
            colNum: col
        });

        _send();
        orgError && orgError.apply(global, arguments);
    };

    var _processError = function(errObj) {
        try {
            if (errObj.stack) {
                var url = errObj.stack.match("https?://[^\n]+");
                url = url ? url[0] : "";
                var rowCols = url.match(":(\\d+):(\\d+)");
                if (!rowCols) {
                    rowCols = [0, 0, 0];
                }

                var stack = _processStackMsg(errObj);
                return {
                    msg: stack,
                    rowNum: rowCols[1],
                    colNum: rowCols[2],
                    target: url.replace(rowCols[0], "")
                };
            } else {
                return errObj;
            }
        } catch (err) {
            return errObj;
        }
    };

    var _processStackMsg = function(error) {
        var stack = error.stack.replace(/\n/gi, "").split(/\bat\b/).slice(0, 5).join("@").replace(/\?[^:]+/gi, "");
        var msg = error.toString();
        if (stack.indexOf(msg) < 0) {
            stack = msg + "@" + stack;
        }
        return stack;
    };

    var _error_tostring = function(error, index) {
        var param = [];
        var params = [];
        var stringify = [];
        if (_isOBJ(error)) {
            error.level = error.level || _config.level;
            for (var key in error) {
                var value = error[key];
                if (!_isEmpty(value)) {
                    if (_isOBJ(value)) {
                        try {
                            value = JSON.stringify(value);
                        } catch (err) {
                            value = "[BJ_REPORT detect value stringify error] " + err.toString();
                        }
                    }
                    stringify.push(key + ":" + value);
                    param.push(key + "=" + encodeURIComponent(value));
                    params.push(key + "[" + index + "]=" + encodeURIComponent(value));
                }
            }
        }

        // msg[0]=msg&target[0]=target -- combo report
        // msg:msg,target:target -- ignore
        // msg=msg&target=target -- report with out combo
        return [params.join("&"), stringify.join(","), param.join("&")];
    };

    var _imgs = [];
    var _submit = function(url) {
        if (_config.submit) {
            _config.submit(url);
        } else {
            var _img = new Image();
            _imgs.push(_img);
            _img.src = url;
        }
    };

    var error_list = [];
    var comboTimeout = 0;
    var _send = function(isReoprtNow) {
        if (!_config.report) return;

        while (_error.length) {
            var isIgnore = false;
            var error = _error.shift();
            var error_str = _error_tostring(error, error_list.length);
            if (_isOBJByType(_config.ignore, "Array")) {
                for (var i = 0, l = _config.ignore.length; i < l; i++) {
                    var rule = _config.ignore[i];
                    if ((_isOBJByType(rule, "RegExp") && rule.test(error_str[1])) ||
                        (_isOBJByType(rule, "Function") && rule(error, error_str[1]))) {
                        isIgnore = true;
                        break;
                    }
                }
            }
            if (!isIgnore) {
                if (_config.combo) {
                    error_list.push(error_str[0]);
                } else {
                    _submit(_config.report + error_str[2] + "&_t=" + (+new Date));
                }
                _config.onReport && (_config.onReport(_config.id, error));
            }
        }

        // 合并上报
        var count = error_list.length;
        if (count) {
            var comboReport = function() {
                clearTimeout(comboTimeout);
                _submit(_config.report + error_list.join("&") + "&count=" + error_list.length + "&_t=" + (+new Date));
                comboTimeout = 0;
                error_list = [];
            };

            if (isReoprtNow) {
                comboReport(); // 立即上报
            } else if (!comboTimeout) {
                comboTimeout = setTimeout(comboReport, _config.delay); // 延迟上报
            }
        }
    };

    var report = {
        push: function(msg) { // 将错误推到缓存池
            // 抽样
            if (Math.random() >= _config.random) {
                return report;
            }

            var data = _isOBJ(msg) ? _processError(msg) : {
                msg: msg
            };
            // ext 有默认值, 且上报不包含 ext, 使用默认 ext
            if (_config.ext && !data.ext) {
                data.ext = _config.ext;
            }
            _error.push(data);
            _send();
            return report;
        },
        report: function(msg) { // error report
            msg && report.push(msg);
            _send(true);
            return report;
        },
        info: function(msg) { // info report
            if (!msg) {
                return report;
            }
            if (_isOBJ(msg)) {
                msg.level = 2;
            } else {
                msg = {
                    msg: msg,
                    level: 2
                };
            }
            report.push(msg);
            return report;
        },
        debug: function(msg) { // debug report
            if (!msg) {
                return report;
            }
            if (_isOBJ(msg)) {
                msg.level = 1;
            } else {
                msg = {
                    msg: msg,
                    level: 1
                };
            }
            report.push(msg);
            return report;
        },
        init: function(config) { // 初始化
            if (_isOBJ(config)) {
                for (var key in config) {
                    _config[key] = config[key];
                }
            }
            // 没有设置id将不上报
            var id = parseInt(_config.id, 10);
            if (id) {
                _config.report = (_config.url || "//badjs2.qq.com/badjs") +
                    "?id=" + id +
                    "&from=" + encodeURIComponent(location.href) +
                    "&uin=" + parseInt(_config.uin || (document.cookie.match(/\buin=\D+(\d+)/) || [])[1], 10) +
                    "&";
            }
            return report;
        },

        __onerror__: global.onerror
    };

    typeof console !== "undefined" && console.error && setTimeout(function() {
        var err = ((location.hash || '').match(/([#&])BJ_ERROR=([^&$]+)/) || [])[2];
        err && console.error("BJ_ERROR", decodeURIComponent(err).replace(/(:\d+:\d+)\s*/g, '$1\n'));
    }, 0);

    return report;

}(window));

if (typeof exports !== "undefined") {
    if (typeof module !== "undefined" && module.exports) {
        exports = module.exports = BJ_REPORT;
    }
    exports.BJ_REPORT = BJ_REPORT;
}
<|endoftext|>


<commit_before>(function() {
  var tickSpeed = 1,
      date = Date,
      now = Date.now || function() { return +new Date; },
      then = now(),
      when = then,

  warpTimestamp = function() {
    var rightNow = now();
    then += (rightNow - when) * tickSpeed;
    when = rightNow;
    return then;
  },

  warped = function() {
    if (!(this instanceof Date))
      return date();

    var args = arguments;
    if (args[0] === true)
      return new date;

    switch (args.length) {
      case 0: return new date(warpTimestamp());
      case 1: return new date(args[0]);
      case 2: return new date(args[0], args[1]);
      case 3: return new date(args[0], args[1], args[2]);
      case 4: return new date(args[0], args[1], args[2], args[3]);
      case 5: return new date(args[0], args[1], args[2], args[3], args[4]);
      default: return new date(args[0], args[1], args[2], args[3], args[4], args[5]);
    }
  };

  warped.now = function(unwarped) {
    return unwarped? now() : warpTimestamp();
  };

  warped.UTC = Date.UTC;
  warped.parse = Date.parse;

  warped.warp = Date.warp = {
    on: function() {
      Date = warped;
      warpTimestamp();
    },
    off: function() {
      Date = date;
    },
    setSpeed: function(speed) {
      tickSpeed = speed;
      warpTimestamp();
    },
    reset: function() {
      tickSpeed = 1;
      when = then = now();
    },
    setDate: function(newDate) {
      if (typeof newDate == 'number')
        then = newDate;
      else if (newDate instanceof date)
        then = +newDate;
    },
    date: Date
  };

  Date = warped;
})();
<commit_msg>Adds `Date.warp.jump()` function.<commit_after>(function() {
  var y = 'years',
      mo = 'months',
      w = 'weeks',
      d = 'days',
      h = 'hours'
      m = 'minutes',
      s = 'seconds',
      ms = 'milliseconds',

      units = {
        y: y,
        yr: y,
        yrs: y,
        year: y,
        mo: mo,
        mos: mo,
        month: mo,
        w: w,
        wk: w,
        wks: w,
        week: w,
        d: d,
        day: d,
        h: h,
        hr: h,
        hrs: h,
        hour: h,
        m: m,
        min: m,
        mins: m,
        minute: m,
        s: s,
        sec: s,
        secs: s,
        second: s,
        ms: ms,
        milli: ms,
        millis: ms,
        millisecond: ms
      },

      tickSpeed = 1,
      date = Date,
      now = Date.now || function() { return +new Date; },
      then = now(),
      when = then,

      warpTimestamp = function() {
        var rightNow = now();
        then += (rightNow - when) * tickSpeed;
        when = rightNow;
        return then;
      },

      warped = function() {
        if (!(this instanceof Date))
          return date();

        var args = arguments;
        if (args[0] === true)
          return new date;

        switch (args.length) {
          case 0: return new date(warpTimestamp());
          case 1: return new date(args[0]);
          case 2: return new date(args[0], args[1]);
          case 3: return new date(args[0], args[1], args[2]);
          case 4: return new date(args[0], args[1], args[2], args[3]);
          case 5: return new date(args[0], args[1], args[2], args[3], args[4]);
          default: return new date(args[0], args[1], args[2], args[3], args[4], args[5]);
        }
      };

  warped.now = function(unwarped) {
    return unwarped? now() : warpTimestamp();
  };

  warped.UTC = Date.UTC;
  warped.parse = Date.parse;

  warped.warp = Date.warp = {
    jump: function(amount) {
      var newDate = new date(then),
          addMs = function(ms) { newDate = newDate.setMilliseconds(newDate.getMilliseconds() + ms); };

      for (var unit in amount) {
        var num = amount[unit];
        if (unit in units)
          unit = units[unit];

        switch (unit) {
          case y:
            newDate.setFullYear(newDate.getFullYear() + num); break;
          case mo:
            newDate.setMonth(newDate.getMonth() + num); break;
          case w:
            addMs(6.048e8 * num); break;
          case d:
            addMs(8.64e7 * num); break;
          case h:
            addMs(3.6e6 * num); break;
          case m:
            addMs(6e4 * num); break;
          case s:
            addMs(1e3 * num); break;
          case ms:
            addMs(num); break;
        }
      }

      then = +newDate;
    },
    setSpeed: function(speed) {
      tickSpeed = speed;
      warpTimestamp();
    },
    setDate: function(newDate) {
      if (typeof newDate == 'number')
        then = newDate;
      else if (newDate instanceof date)
        then = +newDate;
    },
    on: function() {
      Date = warped;
      warpTimestamp();
    },
    off: function() {
      Date = date;
    },
    reset: function() {
      tickSpeed = 1;
      when = then = now();
    },
    date: Date
  };

  Date = warped;
})();
<|endoftext|>


<commit_before>// Copyright (c) 2016 Oasiswork.
// All Rights Reserved.
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file,
// You can obtain one at
// http://mozilla.org/MPL/2.0/.

/*
* Globals variables
*/
var iframeID     = 'dentifriceIframe',
msgPrefix    = '[Dentifrice]',
msgPrefixLen = msgPrefix.length,
lang         = 'en',
target;

/*
* Main Dentifrice Module
*/
var dentifrice = (function () {
    'use strict';

    // Define some global variables and defaults
    var
    settings     = {},

    defaults     = {
        targetId       : 'dentifrice-textarea',
        templateUrl    : null,
        stylesUrl      : 'styles.html',
        configUrl      : 'configuration.json',
        title          : 'Dentifrice Newsletter',
        lang           : null,
        log            : true,
        debug          : false,
        hideTarget     : true,
        anchorId       : null,
        replaceAnchor  : false,
        width          : 850,
        height         : parseInt(window.outerHeight*0.8)
    },

    locales      = {
        'en' : {
            'Please validate' : 'Please validate your edition first !'
        },
        'fr' : {
            'Please validate' : "Veuillez valider l'éditeur !"
        }
    };

    /**
    * Initialize language to, in order of preference :
    *   - language provided in settings
    *   - browser language
    *   - defaults to 'en'
    */
    var _initLang = function () {
        var userLang = navigator.language || navigator.userLanguage;
        if ( settings.lang && (settings.lang in locales) ) {
            lang = settings.lang;
        } else if ( userLang in locales) {
            lang = userLang;
        }
        logger._debug('Setting locale to: ' + lang);
    };

    /**
    * Returns the translated string matching "text" parameter
    */
    var _ = function (text) {
        var locale = locales[lang];
        return ( text in locale ? locale[text] : text );
    };

    /**
    * Initialize settings from provided dictionnary
    */
    var _initSettings = function (options) {
        for (var option in defaults) {
            if (defaults.hasOwnProperty(option)) {
                settings[option] = options.hasOwnProperty(option) ? options[option] : defaults[option];
            }
        }
    };

    /**
    * Find the element where the generated HTML is to be pushed to
    */
    var _findTarget = function () {
        var element = document.getElementById(settings.targetId);
        if ( !element || 0 === element.length) {
            logger._warn('Could not find element with ID: ' + settings.targetId);
            return false;
        } else {
            logger._debug('Found element matching selector: ' + settings.targetId);
            return element;
        }
    };

    //Global
    var _showValidationAlert = function () {
        if(document.getElementById('dentifriceValidationAlert') === null) {

            var iframe = document.getElementById(iframeID);

            var divCheck = document.createElement('div');
            divCheck.id = "dentifriceValidationAlert";
            divCheck.textContent = _('Please validate');

            iframe.parentNode.insertBefore(divCheck, iframe);

            var rect = iframe.getBoundingClientRect();
            var iframeTop = rect.top + iframe.parentNode.scrollTop;
            var heightElement = divCheck.offsetHeight;
            var widthElement = divCheck.offsetWidth;
            var posTop = parseFloat(iframeTop) - parseFloat(heightElement) - 4;
            var posLeft = parseFloat(settings.width) - parseFloat(widthElement);

            divCheck.style.cssText = 'position: relative; top: -10px; left: ' + posLeft + 'px; opacity: 1;';

            window.scrollTo(0, posTop -50);
            setTimeout(function(){
                if(divCheck.parentNode !== null) {
                    divCheck.parentNode.removeChild(divCheck);
                }
            }, 2000);

        }
    };

    var init_dentifrice = function(options) {
        // initialize settings
        logger._info('Initializing settings');
        _initSettings(options);

        // Initialize language
        logger._info('Initializing locale');
        _initLang();

        // Get the target element
        logger._info('Getting target element');
        target = _findTarget();

        // Listen to messages from the iframe
        logger._info('Setting up postMessages listener');
        dentifrice_postMessage.setupMessageListener();
    };

    return {
        checkIfValidated : function() {
            if(target.value === "") {
                _showValidationAlert();
                return false;
            } else {
                return true;
            }
        },
        getSettings : function() {
            return settings;
        },
        init_dentifrice : init_dentifrice,
        bootstrap : function(options) {
            // initialize
            init_dentifrice(options);

            // First check if template url was provided
            // else, give up straight away
            if ( !settings.templateUrl ) {
                logger._warn('No template URL provided');
                // Return false so we can test on the calling page
                return false;
            }

            if (target) {

                // Load the editor
                logger._info('Initializing editor');
                _initEditor.init();

                return true;

            } else {

                logger._warn('Target element not found, aborting');
                // Return false so we can test on the calling page
                return false;

            }
        }
    };

})();

/*
* Logger Module
*/

var logger = (function () {
    var dentifrice_settings = dentifrice.getSettings();
    /**
    * Print messages to the console using provided level.
    */
    var _output = function (type, msg, enabled) {
        if (true === enabled && 'object' === typeof window.console) {
            console[type]('Dentifrice: ' + msg);
        }
    };
    return {
        /**
        * Log warning messages to console.
        * Always logged regardless of the 'log' setting.
        */
        _warn : function (msg) {
            _output('warn', msg, true);
        },

        /**
        * Log information messages to console.
        * Only displayed if 'log' setting is true.
        */
        _info : function (msg) {
            _output('info', msg, dentifrice_settings.log);
        },

        /**
        * Log debug messages to console.
        * Only displayed if 'debug' setting is true.
        */
        _debug : function (msg) {
            _output('log', msg, dentifrice_settings.debug);
        }
    };

})();

/*
* PostMessage Listener
*/

var dentifrice_postMessage = (function() {

    /**
    * Attach postMessage listener
    */
    var setupMessageListener = function () {
        var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
        var eventer = window[eventMethod];
        var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
        eventer(messageEvent, messageListener, false);
    };

    /*
    * Callback listener for postMessages
    */
    var messageListener = function (event) {

        function isMessageForUs () {
            return msgPrefix === (('' + msg).substr(0,msgPrefixLen));
        }

        var msg = event.data;
        if(msg.length > msgPrefixLen && typeof msg === 'string' && isMessageForUs()) {
            logger._debug('Received postmessage :' + msg);
            try {
                // we expect to receive JSON in the message payload
                var jsonMessage = JSON.parse(msg.substr(msgPrefixLen));

                // Check if type is defined
                if(jsonMessage.type == 'final_html') {
                    target.value = messageJson.content;
                }else {
                    logger._warn('Received message did not match any known type');
                }

            } catch(e) {
                logger._warn('Could not decode message. Not JSON: ' + msg.substr(msgPrefixLen));
            }

        }else {
            logger._debug('Received postmessage, but not for us :' + msg);
        }

    };

    return {
        setupMessageListener : setupMessageListener
    };

})();

/**
* Initialize the editor
*/

var _initEditor = (function () {
    var init = function() {
        dentifrice_settings = dentifrice.getSettings();
        // Hide the target and prepare iframe
        if (dentifrice_settings.hideTarget) {
            target.style.display = 'none';
        }

        var assetsUrlBase = dentifrice_settings.templateUrl.replace(/\/[^\/]*$/, '/');
        var absTest = /^https?:\/\/|^\/\//i;

        // Prepare template URL
        var templateUrlEncoded = encodeURIComponent(dentifrice_settings.templateUrl);

        // Prepare CSS URL
        var stylesUrlEncoded = encodeURIComponent(assetsUrlBase + dentifrice_settings.stylesUrl);
        // If an absolute stylesUrl was provided, use it instead
        if ( absTest.test(dentifrice_settings.stylesUrl) ) {
            stylesUrlEncoded = encodeURIComponent(dentifrice_settings.stylesUrl);
        }

        // Prepare config URL
        var configUrlEncoded = encodeURIComponent(assetsUrlBase + dentifrice_settings.configUrl);
        // f an absolute configUrl was provided, use it instead
        if ( absTest.test(dentifrice_settings.configUrl) ) {
            configUrlEncoded = encodeURIComponent(dentifrice_settings.configUrl);
        }

        // Get our own URL to use as base for the iFrame src
        var bootstrapRoot = '';
        var allScripts = document.getElementsByTagName('script');
        var re = /^(.*)dentifrice\.(min\.)*js(.*)/;
        [].forEach.call(allScripts, function (tag) {
            var src = tag.getAttribute('src');
            var match = re.exec(src);
            if (match) {
                // Found a base url to use
                bootstrapRoot = match[1];
            }
        });

        var editorUrl = bootstrapRoot + 'editor.html?template=' + templateUrlEncoded + '&styles=' + stylesUrlEncoded + '&config=' + configUrlEncoded + '&lang=' + lang + '&title=' + dentifrice_settings.title;

        var iframe = document.createElement('iframe');

        iframe.id = iframeID;
        iframe.setAttribute('src', editorUrl);
        iframe.style.border = '0';
        iframe.style.width = dentifrice_settings.width + 'px';
        iframe.style.height = dentifrice_settings.height + 'px';

        if (dentifrice_settings.anchorId) {
            var anchor = document.getElementById(dentifrice_settings.anchorId);
            if (0 === anchor.length) {
                logger._warn('Could not find anchor element with ID: ' + dentifrice_settings.anchorId);
            } else {
                logger._debug('Found anchor element with ID: ' + dentifrice_settings.anchorId);
                if (dentifrice_settings.replaceAnchor) {
                    logger._debug('Replacing anchor element with editor');
                    anchor.parentNode.replaceChild(iframe, anchor);
                } else {
                    logger._debug('Inserting editor inside anchor element');
                    anchor.appendChild(iframe);
                }
            }
        } else {
            target.parentNode.insertBefore(iframe, target.nextSibling);
        }
    };

    /*
    * Return init function
    */
    return {
        init: init
    };
})();
<commit_msg>expose postmessage handler for easy override<commit_after>// Copyright (c) 2016 Oasiswork.
// All Rights Reserved.
//
// This Source Code Form is subject to the
// terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file,
// You can obtain one at
// http://mozilla.org/MPL/2.0/.

/*
* Globals variables
*/
var iframeID     = 'dentifriceIframe',
msgPrefix    = '[Dentifrice]',
msgPrefixLen = msgPrefix.length,
lang         = 'en',
target;

/*
* Main Dentifrice Module
*/
var dentifrice = (function () {
    'use strict';

    // Define some global variables and defaults
    var
    settings     = {},

    defaults     = {
        targetId       : 'dentifrice-textarea',
        templateUrl    : null,
        stylesUrl      : 'styles.html',
        configUrl      : 'configuration.json',
        title          : 'Dentifrice Newsletter',
        lang           : null,
        log            : true,
        debug          : false,
        hideTarget     : true,
        anchorId       : null,
        replaceAnchor  : false,
        width          : 850,
        height         : parseInt(window.outerHeight*0.8)
    },

    locales      = {
        'en' : {
            'Please validate' : 'Please validate your edition first !'
        },
        'fr' : {
            'Please validate' : "Veuillez valider l'éditeur !"
        }
    };

    /**
    * Initialize language to, in order of preference :
    *   - language provided in settings
    *   - browser language
    *   - defaults to 'en'
    */
    var _initLang = function () {
        var userLang = navigator.language || navigator.userLanguage;
        if ( settings.lang && (settings.lang in locales) ) {
            lang = settings.lang;
        } else if ( userLang in locales) {
            lang = userLang;
        }
        logger._debug('Setting locale to: ' + lang);
    };

    /**
    * Returns the translated string matching "text" parameter
    */
    var _ = function (text) {
        var locale = locales[lang];
        return ( text in locale ? locale[text] : text );
    };

    /**
    * Initialize settings from provided dictionnary
    */
    var _initSettings = function (options) {
        for (var option in defaults) {
            if (defaults.hasOwnProperty(option)) {
                settings[option] = options.hasOwnProperty(option) ? options[option] : defaults[option];
            }
        }
    };

    /**
    * Find the element where the generated HTML is to be pushed to
    */
    var _findTarget = function () {
        var element = document.getElementById(settings.targetId);
        if ( !element || 0 === element.length) {
            logger._warn('Could not find element with ID: ' + settings.targetId);
            return false;
        } else {
            logger._debug('Found element matching selector: ' + settings.targetId);
            return element;
        }
    };

    //Global
    var _showValidationAlert = function () {
        if(document.getElementById('dentifriceValidationAlert') === null) {

            var iframe = document.getElementById(iframeID);

            var divCheck = document.createElement('div');
            divCheck.id = "dentifriceValidationAlert";
            divCheck.textContent = _('Please validate');

            iframe.parentNode.insertBefore(divCheck, iframe);

            var rect = iframe.getBoundingClientRect();
            var iframeTop = rect.top + iframe.parentNode.scrollTop;
            var heightElement = divCheck.offsetHeight;
            var widthElement = divCheck.offsetWidth;
            var posTop = parseFloat(iframeTop) - parseFloat(heightElement) - 4;
            var posLeft = parseFloat(settings.width) - parseFloat(widthElement);

            divCheck.style.cssText = 'position: relative; top: -10px; left: ' + posLeft + 'px; opacity: 1;';

            window.scrollTo(0, posTop -50);
            setTimeout(function(){
                if(divCheck.parentNode !== null) {
                    divCheck.parentNode.removeChild(divCheck);
                }
            }, 2000);

        }
    };

    var init_dentifrice = function(options) {
        // initialize settings
        logger._info('Initializing settings');
        _initSettings(options);

        // Initialize language
        logger._info('Initializing locale');
        _initLang();

        // Get the target element
        logger._info('Getting target element');
        target = _findTarget();

        // Listen to messages from the iframe
        logger._info('Setting up postMessages listener');
        dentifrice_postMessage.setupMessageListener();
    };

    return {
        checkIfValidated : function() {
            if(target.value === "") {
                _showValidationAlert();
                return false;
            } else {
                return true;
            }
        },
        getSettings : function() {
            return settings;
        },
        init_dentifrice : init_dentifrice,
        bootstrap : function(options) {
            // initialize
            init_dentifrice(options);

            // First check if template url was provided
            // else, give up straight away
            if ( !settings.templateUrl ) {
                logger._warn('No template URL provided');
                // Return false so we can test on the calling page
                return false;
            }

            if (target) {

                // Load the editor
                logger._info('Initializing editor');
                _initEditor.init();

                return true;

            } else {

                logger._warn('Target element not found, aborting');
                // Return false so we can test on the calling page
                return false;

            }
        }
    };

})();

/*
* Logger Module
*/

var logger = (function () {
    var dentifrice_settings = dentifrice.getSettings();
    /**
    * Print messages to the console using provided level.
    */
    var _output = function (type, msg, enabled) {
        if (true === enabled && 'object' === typeof window.console) {
            console[type]('Dentifrice: ' + msg);
        }
    };
    return {
        /**
        * Log warning messages to console.
        * Always logged regardless of the 'log' setting.
        */
        _warn : function (msg) {
            _output('warn', msg, true);
        },

        /**
        * Log information messages to console.
        * Only displayed if 'log' setting is true.
        */
        _info : function (msg) {
            _output('info', msg, dentifrice_settings.log);
        },

        /**
        * Log debug messages to console.
        * Only displayed if 'debug' setting is true.
        */
        _debug : function (msg) {
            _output('log', msg, dentifrice_settings.debug);
        }
    };

})();

/*
* PostMessage Listener
*/

var dentifrice_postMessage = (function() {

    /**
    * Attach postMessage listener
    */
    var setupMessageListener = function () {
        var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
        var eventer = window[eventMethod];
        var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
        eventer(messageEvent, messageListener, false);
    };

    /*
    * Callback listener for postMessages
    */
    var messageListener = function (event) {

        function isMessageForUs () {
            return msgPrefix === (('' + msg).substr(0,msgPrefixLen));
        }

        var msg = event.data;
        if(msg.length > msgPrefixLen && typeof msg === 'string' && isMessageForUs()) {
            logger._debug('Received postmessage :' + msg);
            try {
                // we expect to receive JSON in the message payload
                var jsonMessage = JSON.parse(msg.substr(msgPrefixLen));

                // Call our handler to do something with the message
                dentifrice_postMessage.handlePostMessage(jsonMessage);

            } catch(e) {
                logger._warn('Could not decode message. Not JSON: ' + msg.substr(msgPrefixLen));
            }

        }else {
            logger._debug('Received postmessage, but not for us :' + msg);
        }

    };

    var handlePostMessage = function (data) {
        // Check if type is defined
        if(data.type === 'final_html') {
            if (target !== undefined)
                target.value = data.content;
        } else {
            logger._warn('Received message did not match any known type');
        }
    };

    return {
        setupMessageListener : setupMessageListener,
        // expose postmessage handler for easy override
        handlePostMessage: handlePostMessage
    };

})();

/**
* Initialize the editor
*/

var _initEditor = (function () {
    var init = function() {
        dentifrice_settings = dentifrice.getSettings();
        // Hide the target and prepare iframe
        if (dentifrice_settings.hideTarget) {
            target.style.display = 'none';
        }

        var assetsUrlBase = dentifrice_settings.templateUrl.replace(/\/[^\/]*$/, '/');
        var absTest = /^https?:\/\/|^\/\//i;

        // Prepare template URL
        var templateUrlEncoded = encodeURIComponent(dentifrice_settings.templateUrl);

        // Prepare CSS URL
        var stylesUrlEncoded = encodeURIComponent(assetsUrlBase + dentifrice_settings.stylesUrl);
        // If an absolute stylesUrl was provided, use it instead
        if ( absTest.test(dentifrice_settings.stylesUrl) ) {
            stylesUrlEncoded = encodeURIComponent(dentifrice_settings.stylesUrl);
        }

        // Prepare config URL
        var configUrlEncoded = encodeURIComponent(assetsUrlBase + dentifrice_settings.configUrl);
        // f an absolute configUrl was provided, use it instead
        if ( absTest.test(dentifrice_settings.configUrl) ) {
            configUrlEncoded = encodeURIComponent(dentifrice_settings.configUrl);
        }

        // Get our own URL to use as base for the iFrame src
        var bootstrapRoot = '';
        var allScripts = document.getElementsByTagName('script');
        var re = /^(.*)dentifrice\.(min\.)*js(.*)/;
        [].forEach.call(allScripts, function (tag) {
            var src = tag.getAttribute('src');
            var match = re.exec(src);
            if (match) {
                // Found a base url to use
                bootstrapRoot = match[1];
            }
        });

        var editorUrl = bootstrapRoot + 'editor.html?template=' + templateUrlEncoded + '&styles=' + stylesUrlEncoded + '&config=' + configUrlEncoded + '&lang=' + lang + '&title=' + dentifrice_settings.title;

        var iframe = document.createElement('iframe');

        iframe.id = iframeID;
        iframe.setAttribute('src', editorUrl);
        iframe.style.border = '0';
        iframe.style.width = dentifrice_settings.width + 'px';
        iframe.style.height = dentifrice_settings.height + 'px';

        if (dentifrice_settings.anchorId) {
            var anchor = document.getElementById(dentifrice_settings.anchorId);
            if (0 === anchor.length) {
                logger._warn('Could not find anchor element with ID: ' + dentifrice_settings.anchorId);
            } else {
                logger._debug('Found anchor element with ID: ' + dentifrice_settings.anchorId);
                if (dentifrice_settings.replaceAnchor) {
                    logger._debug('Replacing anchor element with editor');
                    anchor.parentNode.replaceChild(iframe, anchor);
                } else {
                    logger._debug('Inserting editor inside anchor element');
                    anchor.appendChild(iframe);
                }
            }
        } else {
            target.parentNode.insertBefore(iframe, target.nextSibling);
        }
    };

    /*
    * Return init function
    */
    return {
        init: init
    };
})();
<|endoftext|>


<commit_before>/**
 * @license Copyright (c) 2011 Brian Cavalier
 * LICENSE: see the LICENSE.txt file. If file is missing, this file is subject
 * to the MIT License at: http://www.opensource.org/licenses/mit-license.php.
 */

(function(define, undef) {
define([], function() {

	var freeze = Object.freeze || function() {};

	/*
		Constructor: Deferred
		Creates a new Deferred
	*/
	function Deferred() {
		var deferred, promise, resolver, result, listeners, tail;

		function thenImpl(callback, errback, progback) {
			var d, listener;

			listener = {
				deferred: (d = Deferred()),
				resolve: callback,
				reject: errback,
				progress: progback
			};

			if(listeners) {
				tail = tail.next = listener;
			} else {
				listeners = tail = listener;
			}

			return d.promise;
		}

		function then(callback, errback, progback) {
			return thenImpl(callback, errback, progback);
		}

		function resolve(val) {
			complete('resolve', val);
		}

		function reject(err) {
			complete('reject', err);
		}

		function progress(update) {
			var listener, progress;

			listener = listeners;

			while(listener) {
				progress = listener.progress;
				progress && progress(update);
				listener = listener.next;
			}
		}

		function complete(which, val) {
			// Save original thenImpl
			var origThen = thenImpl;

			// Replace thenImpl with one that immediately notifies
			// with the result.
			thenImpl = function newThen(callback, errback) {
				var promise = origThen(callback, errback);
				notify(which, result);
				return promise;
			};

			// Replace complete so that this Deferred
			// can only be completed once.  Note that this leaves
			// notify() intact so that it can be used in the
			// rewritten thenImpl above.
			complete = function alreadyCompleted() {
				throw new Error("Promise already completed");
			};

			// Final result of this Deferred.  This is immutable
			result = val;

			// Notify listeners
			notify(which, val);
		}

		function notify(which, val) {
			// Traverse all listeners registered directly with this Deferred,
			// also making sure to handle chained thens
			while(listeners) {
				var listener, ldeferred, newResult, handler;

				listener  = listeners;
				ldeferred = listener.deferred;
				listeners = listeners.next;

				handler = listener[which];
				if(handler) {
					try {
						newResult = handler(result);

						if(isPromise(newResult)) {
							// If the handler returned a promise, chained deferreds
							// should complete only after that promise does.
							newResult.then(ldeferred.resolve, ldeferred.reject, ldeferred.progress);

						} else {
							// Complete deferred from chained then()
							ldeferred[which](newResult === undef ? result : newResult);

						}
					} catch(e) {
						// Exceptions cause chained deferreds to complete
						// TODO: Should this always reject()?
						ldeferred[which](result);
					}
				}
			}
		}

		// The full Deferred object, with both Promise and Resolver parts
		deferred = {};

		// Promise and Resolver parts

		// Expose Promise API
		promise = deferred.promise  = {
			then: (deferred.then = then)
		};

		// Expose Resolver API
		resolver = deferred.resolver = {
			resolve:  (deferred.resolve  = resolve),
			reject:   (deferred.reject   = reject),
			progress: (deferred.progress = progress)
		};

		// Freeze Promise and Resolver APIs
		freeze(promise);
		freeze(resolver);

		return deferred;
	}

	/*
		Function: isPromise
		Determines if promiseOrValue is a promise or not.
	*/
	function isPromise(promiseOrValue) {
		return promiseOrValue && typeof promiseOrValue.then === 'function';
	}

	/*
		Function: when
	*/
	function when(promiseOrValue, callback, errback, progressHandler) {
		var result;

		if(arguments.length == 1) {
			// If exactly one arg, assume the caller wants a promise to
			// be returned, no matter what.  If promiseOrValue is a
			// promise, return it.  If it's a value, return a new
			// promise, with promiseOrValue as the resolution value.
			if(isPromise(promiseOrValue)) {
				result = promiseOrValue;
			} else {
				result = Deferred();
				result.resolve(promiseOrValue);
				// Make sure we return only the promise
				result = result.promise;
			}
		} else {
			// If callback args were provided, implement the "traditional"
			// when behavior, and return the result of registering
			// the callbacks with promiseOrValue if it is a promise,
			// or the result of invoking callback with promiseOrValue.
			result = isPromise(promiseOrValue)
				? promiseOrValue.then(callback, errback, progressHandler)
				: callback(promiseOrValue);
		}

		return result;
	}

	/*
		Function: some
	*/
	function some(promisesOrValues, howMany) {
		var toResolve, results, deferred;

		toResolve = Math.max(0, Math.min(howMany, promises.length));
		results = [];
		deferred = Deferred();

		// Resolver for promises.  Captures the value and resolves
		// the returned promise when toResolve reaches zero.
		// Overwrites resolver var with a noop once promise has
		// be resolved to cover case where n < promises.length
		function resolver(val) {
			results.push(val);
			if(--toResolve == 0) {
				resolver = noop;
				deferred.resolve(results);
			}
		}

		// Wrapper so that resolver can be replaced
		function resolve(val) {
			resolver(val);
		}

		// Rejecter for promises.  Rejects returned promise
		// immediately, and overwrites rejecter var with a noop
		// once promise to cover case where n < promises.length.
		// TODO: Consider rejecting only when N (or promises.length - N?)
		// promises have been rejected instead of only one?
		function rejecter(err) {
			rejecter = noop;
			deferred.reject(err);
		}

		// Wrapper so that rejecer can be replaced
		function reject(err) {
			rejecter(err);
		}

		function handleProgress(update) {
			handleProgress = noop;
			deferred.progress(update);
		}

		function progress(update) {
			handleProgress(update);
		}

		for (var i = 0; i < promisesOrValues.length; i++) {
			when(promisesOrValues[i], resolve, reject, progress);
		}

		// TODO: Return Promise instead of Deferred
		return deferred;
	}

	/*
		Function: all
	*/
	function all(promisesOrValues, callback, errback, progressHandler) {
		return some(promisesOrValues, promisesOrValues.length, callback, errback, progressHandler);
	}

	/*
		Function: any
	*/
	function any() {
		return some(promisesOrValues, 1, callback, errback, progressHandler);
	}

	/*
		Section: Public API
	*/

	when.Deferred  = Deferred;

	when.isPromise = isPromise;
	when.some      = some;
	when.all       = all;
	when.any       = any;

	return when;

});
})(typeof define != 'undefined' ? define : function(deps, factory){
    // global when, if not loaded via require
    this.when = factory();
});<commit_msg>Adding version number<commit_after>/**
 * @license Copyright (c) 2011 Brian Cavalier
 * LICENSE: see the LICENSE.txt file. If file is missing, this file is subject
 * to the MIT License at: http://www.opensource.org/licenses/mit-license.php.
 */

/*
	File: when.js
	Version: 0.5
*/

(function(define, undef) {
define([], function() {

	var freeze = Object.freeze || function() {};

	/*
		Constructor: Deferred
		Creates a new Deferred
	*/
	function Deferred() {
		var deferred, promise, resolver, result, listeners, tail;

		function thenImpl(callback, errback, progback) {
			var d, listener;

			listener = {
				deferred: (d = Deferred()),
				resolve: callback,
				reject: errback,
				progress: progback
			};

			if(listeners) {
				tail = tail.next = listener;
			} else {
				listeners = tail = listener;
			}

			return d.promise;
		}

		function then(callback, errback, progback) {
			return thenImpl(callback, errback, progback);
		}

		function resolve(val) {
			complete('resolve', val);
		}

		function reject(err) {
			complete('reject', err);
		}

		function progress(update) {
			var listener, progress;

			listener = listeners;

			while(listener) {
				progress = listener.progress;
				progress && progress(update);
				listener = listener.next;
			}
		}

		function complete(which, val) {
			// Save original thenImpl
			var origThen = thenImpl;

			// Replace thenImpl with one that immediately notifies
			// with the result.
			thenImpl = function newThen(callback, errback) {
				var promise = origThen(callback, errback);
				notify(which, result);
				return promise;
			};

			// Replace complete so that this Deferred
			// can only be completed once.  Note that this leaves
			// notify() intact so that it can be used in the
			// rewritten thenImpl above.
			complete = function alreadyCompleted() {
				throw new Error("Promise already completed");
			};

			// Final result of this Deferred.  This is immutable
			result = val;

			// Notify listeners
			notify(which, val);
		}

		function notify(which, val) {
			// Traverse all listeners registered directly with this Deferred,
			// also making sure to handle chained thens
			while(listeners) {
				var listener, ldeferred, newResult, handler;

				listener  = listeners;
				ldeferred = listener.deferred;
				listeners = listeners.next;

				handler = listener[which];
				if(handler) {
					try {
						newResult = handler(result);

						if(isPromise(newResult)) {
							// If the handler returned a promise, chained deferreds
							// should complete only after that promise does.
							newResult.then(ldeferred.resolve, ldeferred.reject, ldeferred.progress);

						} else {
							// Complete deferred from chained then()
							ldeferred[which](newResult === undef ? result : newResult);

						}
					} catch(e) {
						// Exceptions cause chained deferreds to complete
						// TODO: Should this always reject()?
						ldeferred[which](result);
					}
				}
			}
		}

		// The full Deferred object, with both Promise and Resolver parts
		deferred = {};

		// Promise and Resolver parts

		// Expose Promise API
		promise = deferred.promise  = {
			then: (deferred.then = then)
		};

		// Expose Resolver API
		resolver = deferred.resolver = {
			resolve:  (deferred.resolve  = resolve),
			reject:   (deferred.reject   = reject),
			progress: (deferred.progress = progress)
		};

		// Freeze Promise and Resolver APIs
		freeze(promise);
		freeze(resolver);

		return deferred;
	}

	/*
		Function: isPromise
		Determines if promiseOrValue is a promise or not.
	*/
	function isPromise(promiseOrValue) {
		return promiseOrValue && typeof promiseOrValue.then === 'function';
	}

	/*
		Function: when
	*/
	function when(promiseOrValue, callback, errback, progressHandler) {
		var result;

		if(arguments.length == 1) {
			// If exactly one arg, assume the caller wants a promise to
			// be returned, no matter what.  If promiseOrValue is a
			// promise, return it.  If it's a value, return a new
			// promise, with promiseOrValue as the resolution value.
			if(isPromise(promiseOrValue)) {
				result = promiseOrValue;
			} else {
				result = Deferred();
				result.resolve(promiseOrValue);
				// Make sure we return only the promise
				result = result.promise;
			}
		} else {
			// If callback args were provided, implement the "traditional"
			// when behavior, and return the result of registering
			// the callbacks with promiseOrValue if it is a promise,
			// or the result of invoking callback with promiseOrValue.
			result = isPromise(promiseOrValue)
				? promiseOrValue.then(callback, errback, progressHandler)
				: callback(promiseOrValue);
		}

		return result;
	}

	/*
		Function: some
	*/
	function some(promisesOrValues, howMany) {
		var toResolve, results, deferred;

		toResolve = Math.max(0, Math.min(howMany, promises.length));
		results = [];
		deferred = Deferred();

		// Resolver for promises.  Captures the value and resolves
		// the returned promise when toResolve reaches zero.
		// Overwrites resolver var with a noop once promise has
		// be resolved to cover case where n < promises.length
		function resolver(val) {
			results.push(val);
			if(--toResolve == 0) {
				resolver = noop;
				deferred.resolve(results);
			}
		}

		// Wrapper so that resolver can be replaced
		function resolve(val) {
			resolver(val);
		}

		// Rejecter for promises.  Rejects returned promise
		// immediately, and overwrites rejecter var with a noop
		// once promise to cover case where n < promises.length.
		// TODO: Consider rejecting only when N (or promises.length - N?)
		// promises have been rejected instead of only one?
		function rejecter(err) {
			rejecter = noop;
			deferred.reject(err);
		}

		// Wrapper so that rejecer can be replaced
		function reject(err) {
			rejecter(err);
		}

		function handleProgress(update) {
			handleProgress = noop;
			deferred.progress(update);
		}

		function progress(update) {
			handleProgress(update);
		}

		for (var i = 0; i < promisesOrValues.length; i++) {
			when(promisesOrValues[i], resolve, reject, progress);
		}

		// TODO: Return Promise instead of Deferred
		return deferred;
	}

	/*
		Function: all
	*/
	function all(promisesOrValues, callback, errback, progressHandler) {
		return some(promisesOrValues, promisesOrValues.length, callback, errback, progressHandler);
	}

	/*
		Function: any
	*/
	function any() {
		return some(promisesOrValues, 1, callback, errback, progressHandler);
	}

	/*
		Section: Public API
	*/

	when.Deferred  = Deferred;

	when.isPromise = isPromise;
	when.some      = some;
	when.all       = all;
	when.any       = any;

	return when;

});
})(typeof define != 'undefined' ? define : function(deps, factory){
    // global when, if not loaded via require
    this.when = factory();
});<|endoftext|>


<commit_before>handle_file = function() {
    var input = d3.select(this).remove();
    var files = this.files; // FileList
    var l_dbg = d3.select('#list');
    for (var i=0, fmeta; fmeta=files[i]; i++) {
        l_dbg.append('li').text(fmeta.name + ' ' + fmeta.size + ' ' + fmeta.type);
        // fmeta.size; // bytes
        // fmeta.type; // mime
        if (!fmeta.type.match('text/.*')) { // probably text/csv would be enough
            continue;
        };
        var reader = new FileReader();
        reader.onload = function(e) {
            var csv_string = e.target.result;
            l_dbg.append('li').text('read '+ csv_string.length/1024.0 + 'kB');
            process_csv_array(d3.csv.parse(csv_string, type));
            l_dbg.append('li').text('parsed');
        };

        reader.readAsText(fmeta);
    };
};
d3.select('input[name=file]').on('change', handle_file);

// *********

var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0) * 0.8;
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0) * 0.8;

var margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = w - margin.left - margin.right,
    height = h - margin.top - margin.bottom;

var formatDate = d3.time.format("%Y-%m-%d %I:%M %p");

var x = d3.scale.linear()
    .range([0, width]);

var y = d3.scale.linear()
    .range([height, 0]);

var color_v = d3.scale.linear()
    .range([0.5, 1]);
var color_h = d3.scale.linear()
    .range([0, 360]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

var line = d3.svg.line()
    .x(function(d) { return x(d.weight); })
    .y(function(d) { return y(d.fat); });

var title = d3.select("body").append("h2")
    .text("Chart");

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var path = svg.append("path")
    .datum([])
    .attr("class", "line")
    .attr("d", line);
var dot = svg.append("circle")
    .attr("r", "10")
    .attr("cx", 30)
    .attr("cy", 30)
    .style("stroke", "black")
    .style("stroke-width", 3)
    .style("fill", "green");
var pathlines = [];
var pathlines_to_close = [];
var pathlines_closing = false;

var step_axis = d3.svg.axis().orient("top").ticks(4);
var slider_step = d3.select("#slider_step").call(d3.slider().value(100).min(1).max(500).step(1).axis(step_axis).on("slide", function(e, v) {
    d3.select(".slider_step_value").text(v);
}));
var slider_length = d3.select("#slider_length").call(d3.slider().value(7).min(1).max(7).step(1).axis(true).on("slide", function(e, v) {
    d3.select(".slider_length_value").text(v);
}));

var render = function(data) {
    /*
    var last_transition = path.transition()
      .delay(10)
      .duration(160)
      .ease("linear");
    */
    var last_transition = dot.transition();
    var p_transition;

    var first_idx = 0;
    var previous_idx = first_idx;
    var render_tick = function() {
        // render7
        var length = +d3.select(".slider_length_value").text();
        var max_previous_day = d3.time.day.offset(data[first_idx].date, length*-1);
        var make_transition = function(current_idx) {
            var current_data = data.map(function(d, idx) {
              if (idx < previous_idx) return data[previous_idx];
              if (idx > current_idx) return data[current_idx];
              return d;
            });
            last_transition = last_transition.transition()
                .duration(duration)
                .attr("d", line(current_data))
            return last_transition;
        };
        var make_transition_line = function(current_idx) {
            if (current_idx < 1) return last_transition; // no previous point
            current_data = data.filter(function(d, idx) {
              if (idx > current_idx) return false;
              return (current_idx - idx) <= 1;
            });
            time_delta = data[current_idx].date.getTime() - data[current_idx-1].date.getTime();
            var t_duration = transition_duration(time_delta);
            var color = d3.hsl(color_h(current_idx), 0.51, color_v(current_idx));
            var pathline =  svg.append("path")
                .datum([])
                .attr("class", "pathline")
                .attr("d", line([current_data[0], current_data[0]]));
            p_transition = pathline.transition()
                .duration(t_duration)
                .attr('d', line(current_data))
                .style('stroke', color.toString());
            pathlines.push([data[current_idx].date, pathline, line([current_data[1], current_data[1]]), time_delta]);
            while (pathlines.length && pathlines[0][0].getTime() < max_previous_day.getTime())
                pathlines_to_close.push(pathlines.shift());
            last_transition = last_transition.transition()
                .duration(t_duration/2)
                .style("opacity", 0.8)
                .transition()
                .style("opacity", 1);
            return last_transition;
        };
        /*
        while ((first_idx - previous_idx > 3) && (previous_idx < first_idx) && (data[previous_idx].date.getTime() < max_previous_day.getTime())) {
            // catch up with head
            previous_idx++;
            last_transition = make_transition(first_idx);
        };
        last_transition = make_transition(first_idx);
        */
        last_transition = make_transition_line(first_idx);
        // eo render7

        first_idx++
        if (first_idx < data.length) last_transition.each("end", function() {
            d3.select('#list').append('li').text("last transition ends <" + previous_idx + "," + first_idx + ">");
            render_tick();
            close_pathline();
        });
    };

    var transition_duration = function(time_delta) {
        var duration = +d3.select(".slider_step_value").text();
        return (time_delta*0.0023) * duration / 3600
    };

    var close_pathline = function() {
        if (pathlines_closing) return;
        pathlines_closing = true;
        var elem = pathlines_to_close.shift();
        if (elem === undefined) {
            pathlines_closing = false;
            return; // empty
        }
        try {
            elem[1].transition()
                .duration(transition_duration(elem[3])/4)
                .attr("d", elem[2])
                .each("end", function() {
                    d3.select(this).remove();
                    pathlines_closing = false;
                    close_pathline();
                });
        } catch(e) {
            console.error("error in transition close: %o", e);
            pathlines_closing = false;
        }
    }
    render_tick();
};

var process_csv_array = function(data) {
  x.domain(d3.extent(data, function(d) { return d.weight; }));
  y.domain(d3.extent(data, function(d) { return d.fat; }));
  color_v.domain([0, data.length]);
  color_h.domain(color_v.domain());

  var bars_cnt = 5;
  var bars_data = d3.range(bars_cnt).map(function(i) {
      var val_x = i * (x.domain()[1] - x.domain()[0])/bars_cnt + x.domain()[0];
      var val_y = i * (y.domain()[1] - y.domain()[0])/bars_cnt + y.domain()[0];
      val_y = y.domain()[1];
      var color = i%2 ? "papayawhip" : "mediumvioletred";
      return [val_x, val_y, color]
  });
  var bars = svg.selectAll(".bar").data(bars_data).enter()
      .append("g")
      .attr("transform", "skewX(-45)")
      .attr("class", "bar");
  bars.append("rect")
      .attr("x", function(d) { return x(d[0]); })
      .attr("y", function(d) { return y(d[1]); })
      .attr("width", w/bars_cnt)
      .attr("height", h)
      .attr("fill-opacity", 3e-2)
      .attr("fill", function(d) {return d[2]; });

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Fat (%)");

  data.sort(function(a, b) { return a.date.getTime()-b.date.getTime(); });
  render(data);
};

var last_fat = 0;
var last_weight = 0;

function type(d) {
  d.date = formatDate.parse(d.Date);
  d.weight = +d['Weight (kg)'];
  if (d.weight <= 0) d.weight = last_weight;
  d.fat = +d['Fat mass (%)'];
  if (d.fat <= 0) d.fat = last_fat;

  last_fat = d.fat;
  last_weight = d.weight;

  return d;
}

<commit_msg>Trasition dependency fix<commit_after>handle_file = function() {
    var input = d3.select(this).remove();
    var files = this.files; // FileList
    var l_dbg = d3.select('#list');
    for (var i=0, fmeta; fmeta=files[i]; i++) {
        l_dbg.append('li').text(fmeta.name + ' ' + fmeta.size + ' ' + fmeta.type);
        // fmeta.size; // bytes
        // fmeta.type; // mime
        if (!fmeta.type.match('text/.*')) { // probably text/csv would be enough
            continue;
        };
        var reader = new FileReader();
        reader.onload = function(e) {
            var csv_string = e.target.result;
            l_dbg.append('li').text('read '+ csv_string.length/1024.0 + 'kB');
            process_csv_array(d3.csv.parse(csv_string, type));
            l_dbg.append('li').text('parsed');
        };

        reader.readAsText(fmeta);
    };
};
d3.select('input[name=file]').on('change', handle_file);

// *********

var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0) * 0.8;
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0) * 0.8;

var margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = w - margin.left - margin.right,
    height = h - margin.top - margin.bottom;

var formatDate = d3.time.format("%Y-%m-%d %I:%M %p");

var x = d3.scale.linear()
    .range([0, width]);

var y = d3.scale.linear()
    .range([height, 0]);

var color_v = d3.scale.linear()
    .range([0.5, 1]);
var color_h = d3.scale.linear()
    .range([0, 360]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

var line = d3.svg.line()
    .x(function(d) { return x(d.weight); })
    .y(function(d) { return y(d.fat); });

var title = d3.select("body").append("h2")
    .text("Chart");

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var path = svg.append("path")
    .datum([])
    .attr("class", "line")
    .attr("d", line);
var dot = svg.append("circle")
    .attr("r", "10")
    .attr("cx", 30)
    .attr("cy", 30)
    .style("stroke", "black")
    .style("stroke-width", 3)
    .style("fill", "green");
var pathlines = [];
var pathlines_to_close = [];
var pathlines_closing = false;

var step_axis = d3.svg.axis().orient("top").ticks(4);
var slider_step = d3.select("#slider_step").call(d3.slider().value(100).min(1).max(500).step(1).axis(step_axis).on("slide", function(e, v) {
    d3.select(".slider_step_value").text(v);
}));
var slider_length = d3.select("#slider_length").call(d3.slider().value(7).min(1).max(7).step(1).axis(true).on("slide", function(e, v) {
    d3.select(".slider_length_value").text(v);
}));

var render = function(data) {
    /*
    var last_transition = path.transition()
      .delay(10)
      .duration(160)
      .ease("linear");
    */
    var last_transition = dot.transition();
    var p_transition;

    var first_idx = 0;
    var previous_idx = first_idx;
    var render_tick = function() {
        // render7
        var length = +d3.select(".slider_length_value").text();
        var max_previous_day = d3.time.day.offset(data[first_idx].date, length*-1);
        var make_transition = function(current_idx) {
            var current_data = data.map(function(d, idx) {
              if (idx < previous_idx) return data[previous_idx];
              if (idx > current_idx) return data[current_idx];
              return d;
            });
            last_transition = last_transition.transition()
                .duration(duration)
                .attr("d", line(current_data))
            return last_transition;
        };
        var make_transition_line = function(current_idx) {
            if (current_idx < 1) return last_transition; // no previous point
            current_data = data.filter(function(d, idx) {
              if (idx > current_idx) return false;
              return (current_idx - idx) <= 1;
            });
            time_delta = data[current_idx].date.getTime() - data[current_idx-1].date.getTime();
            var t_duration = transition_duration(time_delta);
            var color = d3.hsl(color_h(current_idx), 0.51, color_v(current_idx));
            var pathline =  svg.append("path")
                .datum([])
                .attr("class", "pathline")
                .attr("d", line([current_data[0], current_data[0]]));
            p_transition = pathline.transition()
                .duration(t_duration)
                .attr('d', line(current_data))
                .style('stroke', color.toString());
            pathlines.push([data[current_idx].date, pathline, line([current_data[1], current_data[1]]), time_delta]);
            while (pathlines.length && pathlines[0][0].getTime() < max_previous_day.getTime())
                pathlines_to_close.push(pathlines.shift());
            last_transition = last_transition.transition()
                .duration(t_duration/2)
                .style("opacity", 0.2)
                .transition()
                .style("opacity", 1);
            return p_transition;
        };
        /*
        while ((first_idx - previous_idx > 3) && (previous_idx < first_idx) && (data[previous_idx].date.getTime() < max_previous_day.getTime())) {
            // catch up with head
            previous_idx++;
            last_transition = make_transition(first_idx);
        };
        last_transition = make_transition(first_idx);
        */
        make_transition_line(first_idx);
        // eo render7

        first_idx++
        if (first_idx < data.length) last_transition.each("end", function() {
            d3.select('#list').append('li').text("last transition ends <" + previous_idx + "," + first_idx + ">");
            render_tick();
            close_pathline();
        });
    };

    var transition_duration = function(time_delta) {
        var duration = +d3.select(".slider_step_value").text();
        return (time_delta*0.0023) * duration / 3600
    };

    var close_pathline = function() {
        if (pathlines_closing) return;
        pathlines_closing = true;
        var elem = pathlines_to_close.shift();
        if (elem === undefined) {
            pathlines_closing = false;
            return; // empty
        }
        try {
            elem[1].transition()
                .duration(transition_duration(elem[3])/4)
                .attr("d", elem[2])
                .each("end", function() {
                    d3.select(this).remove();
                    pathlines_closing = false;
                    close_pathline();
                });
        } catch(e) {
            console.error("error in transition close: %o", e);
            pathlines_closing = false;
        }
    }
    render_tick();
};

var process_csv_array = function(data) {
  x.domain(d3.extent(data, function(d) { return d.weight; }));
  y.domain(d3.extent(data, function(d) { return d.fat; }));
  color_v.domain([0, data.length]);
  color_h.domain(color_v.domain());

  var bars_cnt = 5;
  var bars_data = d3.range(bars_cnt).map(function(i) {
      var val_x = i * (x.domain()[1] - x.domain()[0])/bars_cnt + x.domain()[0];
      var val_y = i * (y.domain()[1] - y.domain()[0])/bars_cnt + y.domain()[0];
      val_y = y.domain()[1];
      var color = i%2 ? "papayawhip" : "mediumvioletred";
      return [val_x, val_y, color]
  });
  var bars = svg.selectAll(".bar").data(bars_data).enter()
      .append("g")
      .attr("transform", "skewX(-45)")
      .attr("class", "bar");
  bars.append("rect")
      .attr("x", function(d) { return x(d[0]); })
      .attr("y", function(d) { return y(d[1]); })
      .attr("width", w/bars_cnt)
      .attr("height", h)
      .attr("fill-opacity", 3e-2)
      .attr("fill", function(d) {return d[2]; });

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Fat (%)");

  data.sort(function(a, b) { return a.date.getTime()-b.date.getTime(); });
  render(data);
};

var last_fat = 0;
var last_weight = 0;

function type(d) {
  d.date = formatDate.parse(d.Date);
  d.weight = +d['Weight (kg)'];
  if (d.weight <= 0) d.weight = last_weight;
  d.fat = +d['Fat mass (%)'];
  if (d.fat <= 0) d.fat = last_fat;

  last_fat = d.fat;
  last_weight = d.weight;

  return d;
}

<|endoftext|>


<commit_before>/**
 * breeze.js
 *
 * The purpose of this file is to handle all the client side code, the ajax call for the status, comments and other stuff
 * @package Breeze mod
 * @version 1.0 Beta 3
 * @author Jessica Gonzlez <suki@missallsunday.com>
 * @copyright Copyright (c) 2013 Jessica Gonzlez
 * @license http://www.mozilla.org/MPL/MPL-1.1.html
 */

/*
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is http://missallsunday.com code.
 *
 * The Initial Developer of the Original Code is
 * Jessica Gonzlez.
 * Portions created by the Initial Developer are Copyright (c) 2012, 2013
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 */

// Some re-usable vars
var breeze = {};

breeze.loadImage = '';

// Helper function to show a notification instance
breeze.noti = function(params)
{
	noty({
		text: params.message,
		timeout: 3500, //@todo set this to a user setting
		type: params.type,
	});
}

jQuery(document).ready(function(){

	// Posting a new status
	jQuery('#form_status').submit(function(event){

		var status = {};

		// Get the profile owner
		status.Owner = window.breeze_profileOwner;

		// Get all the values we need
		jQuery('#form_status :input').each(function(){
			var input = jQuery(this);
			status[input.attr('name').replace('status', '')] = input.val();
		});

		// You need to type something...
		if(status.Content=='')
		{
			alert(breeze_empty_message); // @todo, perhaps fire a nice noty message instead of a nasty alert?
			return false;
		}

		else
		{
			// Shh!
			if (status.Content == 'about:Suki')
			{
				alert('Y es que tengo un coraz\xF3n t\xE1n necio \n que no comprende que no entiende \n que le hace da\xF1o amarte tanto \n no comprende que lo haz olvidado \n sigue aferrado a tu recuerdo y a tu amor \n Y es que tengo un coraz\xF3n t\xE1n necio \n que vive preso a las caricias de tus lindas manos \n al dulce beso de tus labios \n y aunque le hace da\xF1o \n te sigue amando igual o mucho m\xE1s que ayer \n mucho m\xE1s que ayer... \n');
				return false;
			}

			// Show a nice loading image so people can think we are actually doing some work...
			jQuery('#breeze_load_image').fadeIn('slow').html(breeze.loadImage);

			// The long, long ajax call...
			jQuery.ajax({
				type: 'GET',
				url: smf_scripturl + '?action=breezeajax;sa=post;js=1' + window.breeze_session_var + '=' + window.breeze_session_id + ';rf=' + window.breeze_commingFrom,
				data: status,
				cache: false,
				dataType: 'json',
				success: function(html)
				{
					jQuery('#breeze_load_image').fadeOut('slow', 'linear', function(){
						// Enable the button again...
						jQuery('.status_button').removeAttr('disabled');

						// Set the notification
						breeze.noti(html);

						// Do some after work...
						if (html.type == 'success')
						{
							jQuery('#statusContent').text('').focus();
							jQuery('#breeze_display_status').prepend(html.data).fadeIn('slow', 'linear', function(){})
						}
					});
				},
				error: function (html)
				{
					// Enable the button again...
					jQuery('.status_button').removeAttr('disabled');

					jQuery('#breeze_load_image').slideUp('slow', 'linear', function(){
						noty({
							text: html.message,
							timeout: 3500, type: html.type,
						});
					});
				},
			});
		}

		// Prevent normal behaviour
		return false;
	});

	// Post a new comment
	jQuery(document).on('submit', '.form_comment', function(event){

		// The most important thing is... the ID
		var StatusID = parseInt(jQuery(this).attr('id').replace('form_comment_', ''));

		// Gather all the data we need
		var comment = {
			'Status' : StatusID,
			'Owner' : jQuery('#commentOwner_' + StatusID).val(),
			'Poster' : jQuery('#commentPoster_' + StatusID).val(),
			'StatusPoster' : jQuery('#commentStatusPoster_' + StatusID).val(),
			'Content' : jQuery('#commentContent_' + StatusID).val(),
		};

		// Don't be silly...
		if(comment.Content=='')
		{
			alert(breeze_empty_message); // @todo, perhaps fire a nice noty message instead of a nasty alert?
			return false;
		}

		else
		{
			// Disable the button
			jQuery('#commentSubmit_' + StatusID).attr('disabled', 'disabled');

			// The usual loading image...
			jQuery('#breeze_load_image_comment_'+ StatusID).fadeIn('slow').html(breeze.loadImage);

			jQuery.ajax({
				type: 'GET',
				url: smf_scripturl + '?action=breezeajax;sa=postcomment;js=1' + window.breeze_session_var + '=' + window.breeze_session_id + ';rf=' + window.breeze_commingFrom,
				data: comment,
				cache: false,
				dataType: 'json',
				success: function(html){

					jQuery('#breeze_load_image_comment_'+ StatusID).fadeOut('slow', 'linear', function(){

						// Send the notification
						breeze.noti(html);

						// Everything went better than expected :)
						jQuery('#comment_loadplace_'+ StatusID).append(html.data).fadeIn('slow', 'linear', function(){});
					});

					// Enable the button again...
					jQuery('#commentSubmit_' + StatusID).removeAttr('disabled');
					jQuery('#commentContent_' + StatusID).val('').focus();

				},
				error: function (html)
				{
					jQuery('#breeze_load_image_comment_'+ StatusID).fadeOut('slow');
					breeze.noti(html);
					jQuery('#commentSubmit_' + StatusID).removeAttr('disabled');
					jQuery('#commentContent_' + StatusID).val('').focus();
				},
			});
		}

		// Prevent normal behaviour
		return false;
	});

	// Deleting a comment
	jQuery(document).on('click', '.breeze_delete_comment', function(event){

		// Get the ID
		commentID = parseInt(jQuery(this).attr('id').replace('deleteComment_', ''));
		commentUrl = jQuery(this).attr('href');

		// Show a confirmation message
		noty({
			text: breeze_confirm_delete,
			type: 'confirmation',
			dismissQueue: false,
			closeWith: ['button'],
			buttons: [{
				addClass: 'button_submit', text: breeze_confirm_yes, onClick: function($noty) {
					jQuery.ajax({
						type: 'GET',
						url: commentUrl + ';js=1' + window.breeze_session_var + '=' + window.breeze_session_id + ';rf=' + window.breeze_commingFrom,
						cache: false,
						dataType: 'json',
						success: function(html){
							$noty.close();

							switch(html.type)
							{
								case 'error':
									noty({
										text: html.message,
										timeout: 3500, type: html.type,
									});
								break;
								case 'success':
								jQuery('#comment_id_'+ commentID).fadeOut('slow');
								noty({
									text: html.message,
									timeout: 3500, type: html.type,
								});
								break;
							}
						},
						error: function (html){
							$noty.close();
							noty({
								text: html.message,
								timeout: 3500, type: html.error,
							});
						},
					});
				}
			},
				{addClass: 'button_submit', text: breeze_confirm_cancel, onClick: function($noty) {
					$noty.close();
				}}
			]
		});

		return false;
	});

	// Deleting a status, pretty much the same as deleting a comment :(
	jQuery(document).on('click', '.breeze_delete_status', function(event){

		var element = jQuery(this);
		var I = parseInt(element.attr('id').replace('deleteStatus_', ''));
		var typeMethod = 'status';
		var urlParam = element.attr('href');

		// Show a nice confirmation box
		noty({
			text: breeze_confirm_delete,
			type: 'confirmation',
			dismissQueue: false,
			closeWith: ['button'],
			buttons: [{
				addClass: 'button_submit', text: breeze_confirm_yes, onClick: function($noty) {
					jQuery.ajax({
						type: 'GET',
						url: urlParam + ';js=1' + window.breeze_session_var + '=' + window.breeze_session_id + ';rf=' + window.breeze_commingFrom,
						cache: false,
						dataType: 'json',
						success: function(html){
							$noty.close();
							switch(html.type)
							{
								case 'error':
									noty({
										text: html.message,
										timeout: 3500,
										type: html.type,
									});
								break;
								case 'success':
									jQuery('#status_id_'+I).fadeOut('slow');
									noty({
										text: html.message,
										timeout: 3500,
										type: html.type,
									});
								break;
							}
						},
						error: function (html){
							$noty.close();
							noty({
								text: html.message,
								timeout: 3500,
								type: html.type,
							});
						},
					});
				}
			},
				{addClass: 'button_submit', text: breeze_confirm_cancel, onClick: function($noty) {
					$noty.close();
				}}
			]
		});

		return false;
	});

	// Mentioning
	jQuery('textarea[rel*=atwhoMention]').bind("focus", function(event){
		jQuery.ajax({
			url: smf_scripturl + '?action=breezeajax;sa=usersmention;js=1' + window.breeze_session_var + '=' + window.breeze_session_id,
			type: "GET",
			dataType: "json",
			success: function(result)
			{
				jQuery('textarea[rel*=atwhoMention]').atwho('@', {
					search_key: "name",
					tpl: "
${name} ${id}
",
					data: result,
					limit: breeze_how_many_mentions_options,
					callback: {
						filter: function (query, data, search_key) {
							return jQuery.map(data, function(item, i) {
								return item[search_key].toLowerCase().indexOf(query) < 0 ? null : item
							})
						},
					}
				});
			},
		});
	});

	// Facebox
	jQuery('a[rel*=facebox]').livequery(function()
	{
		jQuery(this).facebox(
		{
			loadingImage : smf_images_url + '/breeze/loading.gif',
			closeImage   : smf_images_url + '/breeze/error_close.png'
		});
	});

});

<commit_msg>Don't focus() as it fires a pretty heavy DB query :(<commit_after>/**
 * breeze.js
 *
 * The purpose of this file is to handle all the client side code, the ajax call for the status, comments and other stuff
 * @package Breeze mod
 * @version 1.0 Beta 3
 * @author Jessica Gonzlez <suki@missallsunday.com>
 * @copyright Copyright (c) 2013 Jessica Gonzlez
 * @license http://www.mozilla.org/MPL/MPL-1.1.html
 */

/*
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is http://missallsunday.com code.
 *
 * The Initial Developer of the Original Code is
 * Jessica Gonzlez.
 * Portions created by the Initial Developer are Copyright (c) 2012, 2013
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 */

// Some re-usable vars
var breeze = {};

breeze.loadImage = '';

// Helper function to show a notification instance
breeze.noti = function(params)
{
	noty({
		text: params.message,
		timeout: 3500, //@todo set this to a user setting
		type: params.type,
	});
}

jQuery(document).ready(function(){

	// Posting a new status
	jQuery('#form_status').submit(function(event){

		var status = {};

		// Get the profile owner
		status.Owner = window.breeze_profileOwner;

		// Get all the values we need
		jQuery('#form_status :input').each(function(){
			var input = jQuery(this);
			status[input.attr('name').replace('status', '')] = input.val();
		});

		// You need to type something...
		if(status.Content=='')
		{
			alert(breeze_empty_message); // @todo, perhaps fire a nice noty message instead of a nasty alert?
			return false;
		}

		else
		{
			// Shh!
			if (status.Content == 'about:Suki')
			{
				alert('Y es que tengo un coraz\xF3n t\xE1n necio \n que no comprende que no entiende \n que le hace da\xF1o amarte tanto \n no comprende que lo haz olvidado \n sigue aferrado a tu recuerdo y a tu amor \n Y es que tengo un coraz\xF3n t\xE1n necio \n que vive preso a las caricias de tus lindas manos \n al dulce beso de tus labios \n y aunque le hace da\xF1o \n te sigue amando igual o mucho m\xE1s que ayer \n mucho m\xE1s que ayer... \n');
				return false;
			}

			// Show a nice loading image so people can think we are actually doing some work...
			jQuery('#breeze_load_image').fadeIn('slow').html(breeze.loadImage);

			// The long, long ajax call...
			jQuery.ajax({
				type: 'GET',
				url: smf_scripturl + '?action=breezeajax;sa=post;js=1' + window.breeze_session_var + '=' + window.breeze_session_id + ';rf=' + window.breeze_commingFrom,
				data: status,
				cache: false,
				dataType: 'json',
				success: function(html)
				{
					jQuery('#breeze_load_image').fadeOut('slow', 'linear', function(){
						// Enable the button again...
						jQuery('.status_button').removeAttr('disabled');

						// Set the notification
						breeze.noti(html);

						// Do some after work...
						if (html.type == 'success')
						{
							jQuery('#statusContent').val('');
							jQuery('#breeze_display_status').prepend(html.data).fadeIn('slow', 'linear', function(){})
						}
					});
				},
				error: function (html)
				{
					// Enable the button again...
					jQuery('.status_button').removeAttr('disabled');
					jQuery('#statusContent').val('');

					jQuery('#breeze_load_image').slideUp('slow', 'linear', function(){
						noty({
							text: html.message,
							timeout: 3500, type: html.type,
						});
					});
				},
			});
		}

		// Prevent normal behaviour
		return false;
	});

	// Post a new comment
	jQuery(document).on('submit', '.form_comment', function(event){

		// The most important thing is... the ID
		var StatusID = parseInt(jQuery(this).attr('id').replace('form_comment_', ''));

		// Gather all the data we need
		var comment = {
			'Status' : StatusID,
			'Owner' : jQuery('#commentOwner_' + StatusID).val(),
			'Poster' : jQuery('#commentPoster_' + StatusID).val(),
			'StatusPoster' : jQuery('#commentStatusPoster_' + StatusID).val(),
			'Content' : jQuery('#commentContent_' + StatusID).val(),
		};

		// Don't be silly...
		if(comment.Content=='')
		{
			alert(breeze_empty_message); // @todo, perhaps fire a nice noty message instead of a nasty alert?
			return false;
		}

		else
		{
			// Disable the button
			jQuery('#commentSubmit_' + StatusID).attr('disabled', 'disabled');

			// The usual loading image...
			jQuery('#breeze_load_image_comment_'+ StatusID).fadeIn('slow').html(breeze.loadImage);

			jQuery.ajax({
				type: 'GET',
				url: smf_scripturl + '?action=breezeajax;sa=postcomment;js=1' + window.breeze_session_var + '=' + window.breeze_session_id + ';rf=' + window.breeze_commingFrom,
				data: comment,
				cache: false,
				dataType: 'json',
				success: function(html){

					jQuery('#breeze_load_image_comment_'+ StatusID).fadeOut('slow', 'linear', function(){

						// Send the notification
						breeze.noti(html);

						// Everything went better than expected :)
						jQuery('#comment_loadplace_'+ StatusID).append(html.data).fadeIn('slow', 'linear', function(){});
					});

					// Enable the button again...
					jQuery('#commentSubmit_' + StatusID).removeAttr('disabled');
					jQuery('#commentContent_' + StatusID).val('');

				},
				error: function (html)
				{
					jQuery('#breeze_load_image_comment_'+ StatusID).fadeOut('slow');
					breeze.noti(html);
					jQuery('#commentSubmit_' + StatusID).removeAttr('disabled');
					jQuery('#commentContent_' + StatusID).val('');
				},
			});
		}

		// Prevent normal behaviour
		return false;
	});

	// Deleting a comment
	jQuery(document).on('click', '.breeze_delete_comment', function(event){

		// Get the ID
		commentID = parseInt(jQuery(this).attr('id').replace('deleteComment_', ''));
		commentUrl = jQuery(this).attr('href');

		// Show a confirmation message
		noty({
			text: breeze_confirm_delete,
			type: 'confirmation',
			dismissQueue: false,
			closeWith: ['button'],
			buttons: [{
				addClass: 'button_submit', text: breeze_confirm_yes, onClick: function($noty) {
					jQuery.ajax({
						type: 'GET',
						url: commentUrl + ';js=1' + window.breeze_session_var + '=' + window.breeze_session_id + ';rf=' + window.breeze_commingFrom,
						cache: false,
						dataType: 'json',
						success: function(html){
							$noty.close();

							switch(html.type)
							{
								case 'error':
									noty({
										text: html.message,
										timeout: 3500, type: html.type,
									});
								break;
								case 'success':
								jQuery('#comment_id_'+ commentID).fadeOut('slow');
								noty({
									text: html.message,
									timeout: 3500, type: html.type,
								});
								break;
							}
						},
						error: function (html){
							$noty.close();
							noty({
								text: html.message,
								timeout: 3500, type: html.error,
							});
						},
					});
				}
			},
				{addClass: 'button_submit', text: breeze_confirm_cancel, onClick: function($noty) {
					$noty.close();
				}}
			]
		});

		return false;
	});

	// Deleting a status, pretty much the same as deleting a comment :(
	jQuery(document).on('click', '.breeze_delete_status', function(event){

		var element = jQuery(this);
		var I = parseInt(element.attr('id').replace('deleteStatus_', ''));
		var typeMethod = 'status';
		var urlParam = element.attr('href');

		// Show a nice confirmation box
		noty({
			text: breeze_confirm_delete,
			type: 'confirmation',
			dismissQueue: false,
			closeWith: ['button'],
			buttons: [{
				addClass: 'button_submit', text: breeze_confirm_yes, onClick: function($noty) {
					jQuery.ajax({
						type: 'GET',
						url: urlParam + ';js=1' + window.breeze_session_var + '=' + window.breeze_session_id + ';rf=' + window.breeze_commingFrom,
						cache: false,
						dataType: 'json',
						success: function(html){
							$noty.close();
							switch(html.type)
							{
								case 'error':
									noty({
										text: html.message,
										timeout: 3500,
										type: html.type,
									});
								break;
								case 'success':
									jQuery('#status_id_'+I).fadeOut('slow');
									noty({
										text: html.message,
										timeout: 3500,
										type: html.type,
									});
								break;
							}
						},
						error: function (html){
							$noty.close();
							noty({
								text: html.message,
								timeout: 3500,
								type: html.type,
							});
						},
					});
				}
			},
				{addClass: 'button_submit', text: breeze_confirm_cancel, onClick: function($noty) {
					$noty.close();
				}}
			]
		});

		return false;
	});

	// Mentioning
	jQuery('textarea[rel*=atwhoMention]').bind("focus", function(event){
		jQuery.ajax({
			url: smf_scripturl + '?action=breezeajax;sa=usersmention;js=1' + window.breeze_session_var + '=' + window.breeze_session_id,
			type: "GET",
			dataType: "json",
			success: function(result)
			{
				jQuery('textarea[rel*=atwhoMention]').atwho('@', {
					search_key: "name",
					tpl: "
${name} ${id}
",
					data: result,
					limit: breeze_how_many_mentions_options,
					callback: {
						filter: function (query, data, search_key) {
							return jQuery.map(data, function(item, i) {
								return item[search_key].toLowerCase().indexOf(query) < 0 ? null : item
							})
						},
					}
				});
			},
		});
	});

	// Facebox
	jQuery('a[rel*=facebox]').livequery(function()
	{
		jQuery(this).facebox(
		{
			loadingImage : smf_images_url + '/breeze/loading.gif',
			closeImage   : smf_images_url + '/breeze/error_close.png'
		});
	});

});

<|endoftext|>