<commit_before>!function(e,t,n){"use strict";!function o(e,t,n){function a(s,l){if(!t[s]){if(!e[s]){var i="function"==typeof require&&require;if(!l&&i)return i(s,!0);if(r)return r(s,!0);var u=new Error("Cannot find module '"+s+"'");throw u.code="MODULE_NOT_FOUND",u}var c=t[s]={exports:{}};e[s][0].call(c.exports,function(t){var n=e[s][1][t];return a(n?n:t)},c,c.exports,o,e,t,n)}return t[s].exports}for(var r="function"==typeof require&&require,s=0;s<n.length;s++)a(n[s]);return a}({1:[function(o,a,r){var s=function(e){return e&&e.__esModule?e:{"default":e}};Object.defineProperty(r,"__esModule",{value:!0});var l,i,u,c,d=o("./modules/handle-dom"),f=o("./modules/utils"),p=o("./modules/handle-swal-dom"),m=o("./modules/handle-click"),v=o("./modules/handle-key"),y=s(v),h=o("./modules/default-params"),b=s(h),g=o("./modules/set-params"),w=s(g);r["default"]=u=c=function(){function o(e){var t=a;return t[e]===n?b["default"][e]:t[e]}var a=arguments[0];if(d.addClass(t.body,"stop-scrolling"),p.resetInput(),a===n)return f.logStr("SweetAlert expects at least 1 attribute!"),!1;var r=f.extend({},b["default"]);switch(typeof a){case"string":r.title=a,r.text=arguments[1]||"",r.type=arguments[2]||"";break;case"object":if(a.title===n)return f.logStr('Missing "title" argument!'),!1;r.title=a.title;for(var s in b["default"])r[s]=o(s);r.confirmButtonText=r.showCancelButton?"Confirm":b["default"].confirmButtonText,r.confirmButtonText=o("confirmButtonText"),r.doneFunction=arguments[1]||null;break;default:return f.logStr('Unexpected type of argument! Expected "string" or "object", got '+typeof a),!1}w["default"](r),p.fixVerticalPosition(),p.openModal(arguments[1]);for(var u=p.getModal(),v=u.querySelectorAll("button"),h=["onclick","onmouseover","onmouseout","onmousedown","onmouseup","onfocus"],g=function(e){return m.handleButton(e,r,u)},C=0;C<v.length;C++)for(var S=0;S<h.length;S++){var x=h[S];v[C][x]=g}p.getOverlay().onclick=g,l=e.onkeydown;var k=function(e){return y["default"](e,r,u)};e.onkeydown=k,e.onfocus=function(){setTimeout(function(){i!==n&&(i.focus(),i=n)},0)},c.enableButtons()},u.setDefaults=c.setDefaults=function(e){if(!e)throw new Error("userParams is required");if("object"!=typeof e)throw new Error("userParams has to be a object");f.extend(b["default"],e)},u.close=c.close=function(){var o=p.getModal();d.fadeOut(p.getOverlay(),5),d.fadeOut(o,5),d.removeClass(o,"showSweetAlert"),d.addClass(o,"hideSweetAlert"),d.removeClass(o,"visible");var a=o.querySelector(".sa-icon.sa-success");d.removeClass(a,"animate"),d.removeClass(a.querySelector(".sa-tip"),"animateSuccessTip"),d.removeClass(a.querySelector(".sa-long"),"animateSuccessLong");var r=o.querySelector(".sa-icon.sa-error");d.removeClass(r,"animateErrorIcon"),d.removeClass(r.querySelector(".sa-x-mark"),"animateXMark");var s=o.querySelector(".sa-icon.sa-warning");return d.removeClass(s,"pulseWarning"),d.removeClass(s.querySelector(".sa-body"),"pulseWarningIns"),d.removeClass(s.querySelector(".sa-dot"),"pulseWarningIns"),setTimeout(function(){var e=o.getAttribute("data-custom-class");d.removeClass(o,e)},300),d.removeClass(t.body,"stop-scrolling"),e.onkeydown=l,e.previousActiveElement&&e.previousActiveElement.focus(),i=n,clearTimeout(o.timeout),!0},u.showInputError=c.showInputError=function(e){var t=p.getModal(),n=t.querySelector(".sa-input-error");d.addClass(n,"show");var o=t.querySelector(".sa-error-container");d.addClass(o,"show"),o.querySelector("p").innerHTML=e,setTimeout(function(){u.enableButtons()},1),t.querySelector("input").focus()},u.resetInputError=c.resetInputError=function(e){if(e&&13===e.keyCode)return!1;var t=p.getModal(),n=t.querySelector(".sa-input-error");d.removeClass(n,"show");var o=t.querySelector(".sa-error-container");d.removeClass(o,"show")},u.disableButtons=c.disableButtons=function(){var e=p.getModal(),t=e.querySelector("button.confirm"),n=e.querySelector("button.cancel");t.disabled=!0,n.disabled=!0},u.enableButtons=c.enableButtons=function(){var e=p.getModal(),t=e.querySelector("button.confirm"),n=e.querySelector("button.cancel");t.disabled=!1,n.disabled=!1},"undefined"!=typeof e?e.sweetAlert=e.swal=u:f.logStr("SweetAlert is a frontend module!"),a.exports=r["default"]},{"./modules/default-params":2,"./modules/handle-click":3,"./modules/handle-dom":4,"./modules/handle-key":5,"./modules/handle-swal-dom":6,"./modules/set-params":8,"./modules/utils":9}],2:[function(e,t,n){Object.defineProperty(n,"__esModule",{value:!0});var o={title:"",text:"",type:null,allowOutsideClick:!1,showConfirmButton:!0,showCancelButton:!1,closeOnConfirm:!0,closeOnCancel:!0,confirmButtonText:"OK",confirmButtonColor:"#8CD4F5",cancelButtonText:"Cancel",imageUrl:null,imageSize:null,timer:null,customClass:"",html:!1,animation:!0,allowEscapeKey:!0,inputType:"text",inputPlaceholder:"",inputValue:"",showLoaderOnConfirm:!1};n["default"]=o,t.exports=n["default"]},{}],3:[function(t,n,o){Object.defineProperty(o,"__esModule",{value:!0});var a=t("./utils"),r=(t("./handle-swal-dom"),t("./handle-dom")),s=function(t,n,o){function s(e){m&&n.confirmButtonColor&&(p.style.backgroundColor=e)}var u,c,d,f=t||e.event,p=f.target||f.srcElement,m=-1!==p.className.indexOf("confirm"),v=-1!==p.className.indexOf("sweet-overlay"),y=r.hasClass(o,"visible"),h=n.doneFunction&&"true"===o.getAttribute("data-has-done-function");switch(m&&n.confirmButtonColor&&(u=n.confirmButtonColor,c=a.colorLuminance(u,-.04),d=a.colorLuminance(u,-.14)),f.type){case"mouseover":s(c);break;case"mouseout":s(u);break;case"mousedown":s(d);break;case"mouseup":s(c);break;case"focus":var b=o.querySelector("button.confirm"),g=o.querySelector("button.cancel");m?g.style.boxShadow="none":b.style.boxShadow="none";break;case"click":var w=o===p,C=r.isDescendant(o,p);if(!w&&!C&&y&&!n.allowOutsideClick)break;m&&h&&y?l(o,n):h&&y||v?i(o,n):r.isDescendant(o,p)&&"BUTTON"===p.tagName&&sweetAlert.close()}},l=function(e,t){var n=!0;r.hasClass(e,"show-input")&&(n=e.querySelector("input").value,n||(n="")),t.doneFunction(n),t.closeOnConfirm&&sweetAlert.close(),t.showLoaderOnConfirm&&sweetAlert.disableButtons()},i=function(e,t){var n=String(t.doneFunction).replace(/\s/g,""),o="function("===n.substring(0,9)&&")"!==n.substring(9,10);o&&t.doneFunction(!1),t.closeOnCancel&&sweetAlert.close()};o["default"]={handleButton:s,handleConfirm:l,handleCancel:i},n.exports=o["default"]},{"./handle-dom":4,"./handle-swal-dom":6,"./utils":9}],4:[function(n,o,a){Object.defineProperty(a,"__esModule",{value:!0});var r=function(e,t){return new RegExp(" "+t+" ").test(" "+e.className+" ")},s=function(e,t){r(e,t)||(e.className+=" "+t)},l=function(e,t){var n=" "+e.className.replace(/[\t\r\n]/g," ")+" ";if(r(e,t)){for(;n.indexOf(" "+t+" ")>=0;)n=n.replace(" "+t+" "," ");e.className=n.replace(/^\s+|\s+$/g,"")}},i=function(e){var n=t.createElement("div");return n.appendChild(t.createTextNode(e)),n.innerHTML},u=function(e){e.style.opacity="",e.style.display="block"},c=function(e){if(e&&!e.length)return u(e);for(var t=0;t<e.length;++t)u(e[t])},d=function(e){e.style.opacity="",e.style.display="none"},f=function(e){if(e&&!e.length)return d(e);for(var t=0;t<e.length;++t)d(e[t])},p=function(e,t){for(var n=t.parentNode;null!==n;){if(n===e)return!0;n=n.parentNode}return!1},m=function(e){e.style.left="-9999px",e.style.display="block";var t,n=e.clientHeight;return t="undefined"!=typeof getComputedStyle?parseInt(getComputedStyle(e).getPropertyValue("padding-top"),10):parseInt(e.currentStyle.padding),e.style.left="",e.style.display="none","-"+parseInt((n+t)/2)+"px"},v=function(e,t){if(+e.style.opacity<1){t=t||16,e.style.opacity=0,e.style.display="block";var n=+new Date,o=function(e){function t(){return e.apply(this,arguments)}return t.toString=function(){return e.toString()},t}(function(){e.style.opacity=+e.style.opacity+(new Date-n)/100,n=+new Date,+e.style.opacity<1&&setTimeout(o,t)});o()}e.style.display="block"},y=function(e,t){t=t||16,e.style.opacity=1;var n=+new Date,o=function(e){function t(){return e.apply(this,arguments)}return t.toString=function(){return e.toString()},t}(function(){e.style.opacity=+e.style.opacity-(new Date-n)/100,n=+new Date,+e.style.opacity>0?setTimeout(o,t):e.style.display="none"});o()},h=function(n){if("function"==typeof MouseEvent){var o=new MouseEvent("click",{view:e,bubbles:!1,cancelable:!0});n.dispatchEvent(o)}else if(t.createEvent){var a=t.createEvent("MouseEvents");a.initEvent("click",!1,!1),n.dispatchEvent(a)}else t.createEventObject?n.fireEvent("onclick"):"function"==typeof n.onclick&&n.onclick()},b=function(t){"function"==typeof t.stopPropagation?(t.stopPropagation(),t.preventDefault()):e.event&&e.event.hasOwnProperty("cancelBubble")&&(e.event.cancelBubble=!0)};a.hasClass=r,a.addClass=s,a.removeClass=l,a.escapeHtml=i,a._show=u,a.show=c,a._hide=d,a.hide=f,a.isDescendant=p,a.getTopMargin=m,a.fadeIn=v,a.fadeOut=y,a.fireClick=h,a.stopEventPropagation=b},{}],5:[function(t,o,a){Object.defineProperty(a,"__esModule",{value:!0});var r=t("./handle-dom"),s=t("./handle-swal-dom"),l=function(t,o,a){var l=t||e.event,i=l.keyCode||l.which,u=a.querySelector("button.confirm"),c=a.querySelector("button.cancel"),d=a.querySelectorAll("button[tabindex]");if(-1!==[9,13,32,27].indexOf(i)){for(var f=l.target||l.srcElement,p=-1,m=0;m<d.length;m++)if(f===d[m]){p=m;break}9===i?(f=-1===p?u:p===d.length-1?d[0]:d[p+1],r.stopEventPropagation(l),f.focus(),o.confirmButtonColor&&s.setFocusStyle(f,o.confirmButtonColor)):13===i?("INPUT"===f.tagName&&(f=u,u.focus()),f=-1===p?u:n):27===i&&o.allowEscapeKey===!0?(f=c,r.fireClick(f,l)):f=n}};a["default"]=l,o.exports=a["default"]},{"./handle-dom":4,"./handle-swal-dom":6}],6:[function(n,o,a){var r=function(e){return e&&e.__esModule?e:{"default":e}};Object.defineProperty(a,"__esModule",{value:!0});var s=n("./utils"),l=n("./handle-dom"),i=n("./default-params"),u=r(i),c=n("./injected-html"),d=r(c),f=".sweet-alert",p=".sweet-overlay",m=function(){var e=t.createElement("div");for(e.innerHTML=d["default"];e.firstChild;)t.body.appendChild(e.firstChild)},v=function(e){function t(){return e.apply(this,arguments)}return t.toString=function(){return e.toString()},t}(function(){var e=t.querySelector(f);return e||(m(),e=v()),e}),y=function(){var e=v();return e?e.querySelector("input"):void 0},h=function(){return t.querySelector(p)},b=function(e,t){var n=s.hexToRgb(t);e.style.boxShadow="0 0 2px rgba("+n+", 0.8), inset 0 0 0 1px rgba(0, 0, 0, 0.05)"},g=function(n){var o=v();l.fadeIn(h(),10),l.show(o),l.addClass(o,"showSweetAlert"),l.removeClass(o,"hideSweetAlert"),e.previousActiveElement=t.activeElement;var a=o.querySelector("button.confirm");a.focus(),setTimeout(function(){l.addClass(o,"visible")},500);var r=o.getAttribute("data-timer");if("null"!==r&&""!==r){var s=n;o.timeout=setTimeout(function(){var e=(s||null)&&"true"===o.getAttribute("data-has-done-function");e?s(null):sweetAlert.close()},r)}},w=function(){var e=v(),t=y();l.removeClass(e,"show-input"),t.value=u["default"].inputValue,t.setAttribute("type",u["default"].inputType),t.setAttribute("placeholder",u["default"].inputPlaceholder),C()},C=function(e){if(e&&13===e.keyCode)return!1;var t=v(),n=t.querySelector(".sa-input-error");l.removeClass(n,"show");var o=t.querySelector(".sa-error-container");l.removeClass(o,"show")},S=function(){var e=v();e.style.marginTop=l.getTopMargin(v())};a.sweetAlertInitialize=m,a.getModal=v,a.getOverlay=h,a.getInput=y,a.setFocusStyle=b,a.openModal=g,a.resetInput=w,a.resetInputError=C,a.fixVerticalPosition=S},{"./default-params":2,"./handle-dom":4,"./injected-html":7,"./utils":9}],7:[function(e,t,n){Object.defineProperty(n,"__esModule",{value:!0});var o='

\n      \n        \n        \n      \n

\n      \n      \n

\n      \n      \n\n

\n

\n

Title
\n
Text
\n    <fieldset>\n      <input type="text" tabIndex="3" />\n

\n    </fieldset>
\n
!
\n
Not valid!
\n

\n      <button class="cancel" tabIndex="2">Cancel</button>\n
\n        <button class="confirm" tabIndex="1">OK</button>
\n

\n

\n

\n
\n
\n

';n["default"]=o,t.exports=n["default"]},{}],8:[function(e,t,o){Object.defineProperty(o,"__esModule",{value:!0});var a=e("./utils"),r=e("./handle-swal-dom"),s=e("./handle-dom"),l=["error","warning","info","success","input","prompt"],i=function(e){var t=r.getModal(),o=t.querySelector("h2"),i=t.querySelector("p"),u=t.querySelector("button.cancel"),c=t.querySelector("button.confirm");if(o.innerHTML=e.html?e.title:s.escapeHtml(e.title).split("\n").join("
"),i.innerHTML=e.html?e.text:s.escapeHtml(e.text||"").split("\n").join("
"),e.text&&s.show(i),e.customClass)s.addClass(t,e.customClass),t.setAttribute("data-custom-class",e.customClass);else{var d=t.getAttribute("data-custom-class");s.removeClass(t,d),t.setAttribute("data-custom-class","")}if(s.hide(t.querySelectorAll(".sa-icon")),e.type&&!a.isIE8()){var f=function(){for(var o=!1,a=0;a<l.length;a++)if(e.type===l[a]){o=!0;break}if(!o)return logStr("Unknown alert type: "+e.type),{v:!1};var i=["success","error","warning","info"],u=n;-1!==i.indexOf(e.type)&&(u=t.querySelector(".sa-icon.sa-"+e.type),s.show(u));var c=r.getInput();switch(e.type){case"success":s.addClass(u,"animate"),s.addClass(u.querySelector(".sa-tip"),"animateSuccessTip"),s.addClass(u.querySelector(".sa-long"),"animateSuccessLong");break;case"error":s.addClass(u,"animateErrorIcon"),s.addClass(u.querySelector(".sa-x-mark"),"animateXMark");break;case"warning":s.addClass(u,"pulseWarning"),s.addClass(u.querySelector(".sa-body"),"pulseWarningIns"),s.addClass(u.querySelector(".sa-dot"),"pulseWarningIns");break;case"input":case"prompt":c.setAttribute("type",e.inputType),c.value=e.inputValue,c.setAttribute("placeholder",e.inputPlaceholder),s.addClass(t,"show-input"),setTimeout(function(){c.focus(),c.addEventListener("keyup",swal.resetInputError)},400)}}();if("object"==typeof f)return f.v}if(e.imageUrl){var p=t.querySelector(".sa-icon.sa-custom");p.style.backgroundImage="url("+e.imageUrl+")",s.show(p);var m=80,v=80;if(e.imageSize){var y=e.imageSize.toString().split("x"),h=y[0],b=y[1];h&&b?(m=h,v=b):logStr("Parameter imageSize expects value with format WIDTHxHEIGHT, got "+e.imageSize)}p.setAttribute("style",p.getAttribute("style")+"width:"+m+"px; height:"+v+"px")}t.setAttribute("data-has-cancel-button",e.showCancelButton),e.showCancelButton?u.style.display="inline-block":s.hide(u),t.setAttribute("data-has-confirm-button",e.showConfirmButton),e.showConfirmButton?c.style.display="inline-block":s.hide(c),e.cancelButtonText&&(u.innerHTML=s.escapeHtml(e.cancelButtonText)),e.confirmButtonText&&(c.innerHTML=s.escapeHtml(e.confirmButtonText)),e.confirmButtonColor&&(c.style.backgroundColor=e.confirmButtonColor,c.style.borderLeftColor=e.confirmLoadingButtonColor,c.style.borderRightColor=e.confirmLoadingButtonColor,r.setFocusStyle(c,e.confirmButtonColor)),t.setAttribute("data-allow-outside-click",e.allowOutsideClick);var g=e.doneFunction?!0:!1;t.setAttribute("data-has-done-function",g),e.animation?"string"==typeof e.animation?t.setAttribute("data-animation",e.animation):t.setAttribute("data-animation","pop"):t.setAttribute("data-animation","none"),t.setAttribute("data-timer",e.timer)};o["default"]=i,t.exports=o["default"]},{"./handle-dom":4,"./handle-swal-dom":6,"./utils":9}],9:[function(t,n,o){Object.defineProperty(o,"__esModule",{value:!0});var a=function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e},r=function(e){var t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return t?parseInt(t[1],16)+", "+parseInt(t[2],16)+", "+parseInt(t[3],16):null},s=function(){return e.attachEvent&&!e.addEventListener},l=function(t){e.console&&e.console.log("SweetAlert: "+t)},i=function(e,t){e=String(e).replace(/[^0-9a-f]/gi,""),e.length<6&&(e=e[0]+e[0]+e[1]+e[1]+e[2]+e[2]),t=t||0;var n,o,a="#";for(o=0;3>o;o++)n=parseInt(e.substr(2*o,2),16),n=Math.round(Math.min(Math.max(0,n+n*t),255)).toString(16),a+=("00"+n).substr(n.length);return a};o.extend=a,o.hexToRgb=r,o.isIE8=s,o.logStr=l,o.colorLuminance=i},{}]},{},[1]),"function"==typeof define&&define.amd?define(function(){return sweetAlert}):"undefined"!=typeof module&&module.exports&&(module.exports=sweetAlert)}(window,document);<commit_msg>Delete sweetalert.min.js<commit_after><|endoftext|>


<commit_before>/*global define*/
define(['jquery', 'underscore', 'oroui/js/tools'
    ], function ($, _, tools) {
    'use strict';

    /**
     * @export  oroform/js/select2-config
     * @class   oroform.Select2Config
     */
    var Select2Config = function (config, url, perPage, excluded) {
        this.config = config;
        this.url = url;
        this.perPage = perPage;
        this.excluded = excluded;
    };

    Select2Config.prototype = {
        getConfig: function () {
            var self = this;
            // create default AJAX object for AJAX based Select2
            // and if this object was not created in extra config block
            if (this.config.ajax === undefined && this.url) {
                this.config.ajax = {
                    url: this.url,
                    data: function (query, page) {
                        return {
                            page: page,
                            per_page: self.perPage,
                            query: query
                        };
                    },
                    results: function (data, page) {
                        return data;
                    }
                };
            }
            // configure AJAX object if it exists
            if (this.config.ajax !== undefined) {
                if (this.config.initSelection === undefined) {
                    this.config.initSelection = _.bind(this.initSelection, this);
                }
                var filterData = function(data) {
                    if (self.excluded) {
                        var forRemove = [];
                        var results = data.results;
                        for (var i = 0; i < results.length; i++) {
                            if (results[i].hasOwnProperty('id') && self.excluded.indexOf(results[i].id) > -1) {
                                forRemove.push(i);
                            }
                        }
                        for (i = 0; i < forRemove.length; i++) {
                            results.splice(forRemove[i], 1);
                        }
                        data.results = results;
                    }
                    return data;
                };
                var resultsMethod = this.config.ajax.results;
                this.config.ajax.results = function(data, page) {
                    return filterData(resultsMethod(data, page));
                };
                if (this.config.ajax.quietMillis === undefined) {
                    this.config.ajax.quietMillis = 700;
                }
            } else {
                // configure non AJAX based Select2
                if (this.config.minimumResultsForSearch === undefined) {
                    this.config.minimumResultsForSearch = 7;
                }
            }
            // set default values for other Select2 options
            if (this.config.formatResult === undefined) {
                this.config.formatResult = this.format(this.config.result_template || false);
            }
            if (this.config.formatSelection === undefined) {
                this.config.formatSelection = this.format(this.config.selection_template || false);
            }
            if (this.config.escapeMarkup === undefined) {
                this.config.escapeMarkup = function (m) { return m; };
            }
            if (this.config.dropdownAutoWidth === undefined) {
                this.config.dropdownAutoWidth = true;
            }
            if (this.config.openOnEnter === undefined) {
                this.config.openOnEnter = null;
            }
            return this.config;
        },

        format: function(jsTemplate) {
            var self = this;
            // pre-compile template if it exists
            if (jsTemplate) {
                jsTemplate = _.template(jsTemplate);
            }

            return function (object, container, query) {
                if ($.isEmptyObject(object)) {
                    return undefined;
                }
                var result = '',
                    highlight = function (str) {
                        return object.children ? str : self.highlightSelection(str, query);
                    };
                if (object._html !== undefined) {
                    result = _.escape(object._html);
                } else if (jsTemplate) {
                    object = _.clone(object);
                    object.highlight = highlight;
                    if (self.config.formatContext !== undefined) {
                        object.context = self.config.formatContext();
                    }
                    result = jsTemplate(object);
                } else {
                    result = highlight(_.escape(self.getTitle(object, self.config.properties)));
                }
                return result;
            };
        },

        initSelection: function(element, callback) {
            var self = this;

            var handleResults = function(data) {
                if (self.config.multiple === true) {
                    callback(data);
                } else {
                    callback(data.pop());
                }
            };

            var setSelect2ValueById = function(id) {
                if (_.isArray(id)) {
                    id = id.join(',');
                }
                var select2Obj = element.data('select2');
                var select2AjaxOptions = select2Obj.opts.ajax;
                var searchData = select2AjaxOptions.data(id, 1, true);
                var url = (typeof select2AjaxOptions.url === 'function')
                    ? select2AjaxOptions.url.call(select2Obj, id, 1)
                    : select2AjaxOptions.url;

                searchData.search_by_id = true;
                $.ajax({
                    url: url,
                    data: searchData,
                    success: function(response) {
                        if (typeof select2AjaxOptions.results == 'function') {
                            response = select2AjaxOptions.results.call(select2Obj, response, 1);
                        }
                        if (typeof response.results != 'undefined') {
                            handleResults(response.results);
                        }
                        element.trigger('select2-data-loaded');
                    }
                });
            };

            var currentValue = element.select2('val');
            if (!_.isArray(currentValue)) {
                currentValue = [currentValue];
            }

            // elementData must have name
            var elementData = _.filter(
                element.data('selected-data'),
                function (item) {
                    return item.name !== undefined && item.name !== null;
                }
            );

            if (_.isArray(elementData) && elementData.length > 0) {
                var dataIds = _.map(elementData, function(item) {
                    return item.id;
                });

                // handle case when creation of new item allowed and value should be restored (f.e. validation failed)
                dataIds = _.compact(dataIds);

                if (dataIds.length === 0 || dataIds.sort().join(',') === currentValue.sort().join(',')) {
                    handleResults(elementData);
                } else {
                    setSelect2ValueById(currentValue);
                }
            } else {
                setSelect2ValueById(currentValue);
            }
        },

        highlightSelection: function(str, selection) {
            return str && selection && selection.term ?
                str.replace(tools.safeRegExp(selection.term, 'ig'), '$&') : str;
        },

        getTitle: function(data, properties) {
            var title = '', result;
            if (data) {
                if (properties === undefined) {
                    if (data.text !== undefined) {
                        title = data.text;
                    }
                } else {
                    result = [];
                    _.each(properties, function(property) {
                        result.push(data[property]);
                    });
                    title = result.join(' ');
                }
            }
            return title;
        }
    };

    return Select2Config;
});
<commit_msg>BAP-7137 Issue when same value is selected in select2 control<commit_after>/*global define*/
define(['jquery', 'underscore', 'oroui/js/tools'
    ], function ($, _, tools) {
    'use strict';

    /**
     * @export  oroform/js/select2-config
     * @class   oroform.Select2Config
     */
    var Select2Config = function (config, url, perPage, excluded) {
        this.config = config;
        this.url = url;
        this.perPage = perPage;
        this.excluded = excluded;
    };

    Select2Config.prototype = {
        getConfig: function () {
            var self = this;
            // create default AJAX object for AJAX based Select2
            // and if this object was not created in extra config block
            if (this.config.ajax === undefined && this.url) {
                this.config.ajax = {
                    url: this.url,
                    data: function (query, page) {
                        return {
                            page: page,
                            per_page: self.perPage,
                            query: query
                        };
                    },
                    results: function (data, page) {
                        return data;
                    }
                };
            }
            // configure AJAX object if it exists
            if (this.config.ajax !== undefined) {
                if (this.config.initSelection === undefined) {
                    this.config.initSelection = _.bind(this.initSelection, this);
                }
                var filterData = function(data) {
                    if (self.excluded) {
                        var forRemove = [];
                        var results = data.results;
                        for (var i = 0; i < results.length; i++) {
                            if (results[i].hasOwnProperty('id') && self.excluded.indexOf(results[i].id) > -1) {
                                forRemove.push(i);
                            }
                        }
                        for (i = 0; i < forRemove.length; i++) {
                            results.splice(forRemove[i], 1);
                        }
                        data.results = results;
                    }
                    return data;
                };
                var resultsMethod = this.config.ajax.results;
                this.config.ajax.results = function(data, page) {
                    return filterData(resultsMethod(data, page));
                };
                if (this.config.ajax.quietMillis === undefined) {
                    this.config.ajax.quietMillis = 700;
                }
            } else {
                // configure non AJAX based Select2
                if (this.config.minimumResultsForSearch === undefined) {
                    this.config.minimumResultsForSearch = 7;
                }
            }
            // set default values for other Select2 options
            if (this.config.formatResult === undefined) {
                this.config.formatResult = this.format(this.config.result_template || false);
            }
            if (this.config.formatSelection === undefined) {
                this.config.formatSelection = this.format(this.config.selection_template || false);
            }
            if (this.config.escapeMarkup === undefined) {
                this.config.escapeMarkup = function (m) { return m; };
            }
            if (this.config.dropdownAutoWidth === undefined) {
                this.config.dropdownAutoWidth = true;
            }
            if (this.config.openOnEnter === undefined) {
                this.config.openOnEnter = null;
            }
            return this.config;
        },

        format: function(jsTemplate) {
            var self = this;
            // pre-compile template if it exists
            if (jsTemplate) {
                jsTemplate = _.template(jsTemplate);
            }

            return function (object, container, query) {
                if ($.isEmptyObject(object)) {
                    return undefined;
                }
                var result = '',
                    highlight = function (str) {
                        return object.children ? str : self.highlightSelection(str, query);
                    };
                if (object._html !== undefined) {
                    result = _.escape(object._html);
                } else if (jsTemplate) {
                    object = _.clone(object);
                    object.highlight = highlight;
                    if (self.config.formatContext !== undefined) {
                        object.context = self.config.formatContext();
                    }
                    result = jsTemplate(object);
                } else {
                    result = highlight(_.escape(self.getTitle(object, self.config.properties)));
                }
                return result;
            };
        },

        initSelection: function(element, callback) {
            var self = this;

            var handleResults = function(data) {
                if (self.config.multiple === true) {
                    callback(data);
                } else {
                    callback(data.pop());
                }
            };

            var setSelect2ValueById = function(id) {
                if (_.isArray(id)) {
                    id = id.join(',');
                }
                var select2Obj = element.data('select2');
                var select2AjaxOptions = select2Obj.opts.ajax;
                var searchData = select2AjaxOptions.data(id, 1, true);
                var url = (typeof select2AjaxOptions.url === 'function')
                    ? select2AjaxOptions.url.call(select2Obj, id, 1)
                    : select2AjaxOptions.url;

                searchData.search_by_id = true;
                $.ajax({
                    url: url,
                    data: searchData,
                    success: function(response) {
                        if (typeof select2AjaxOptions.results == 'function') {
                            response = select2AjaxOptions.results.call(select2Obj, response, 1);
                        }
                        if (typeof response.results != 'undefined') {
                            handleResults(response.results);
                        }
                        element.trigger('select2-data-loaded');
                    }
                });
            };

            var currentValue = element.select2('val');
            if (!_.isArray(currentValue)) {
                currentValue = [currentValue];
            }

            var selectedData = element.data('selected-data');
            if (!_.isArray(selectedData) && selectedData !== undefined) {
                selectedData = [selectedData];
            }

            // elementData must have name
            var elementData = _.filter(
                selectedData,
                function (item) {
                    return item.name !== undefined && item.name !== null;
                }
            );

            if (_.isArray(elementData) && elementData.length > 0) {
                var dataIds = _.map(elementData, function(item) {
                    return item.id;
                });

                // handle case when creation of new item allowed and value should be restored (f.e. validation failed)
                dataIds = _.compact(dataIds);

                if (dataIds.length === 0 || dataIds.sort().join(',') === currentValue.sort().join(',')) {
                    handleResults(elementData);
                } else {
                    setSelect2ValueById(currentValue);
                }
            } else {
                setSelect2ValueById(currentValue);
            }
        },

        highlightSelection: function(str, selection) {
            return str && selection && selection.term ?
                str.replace(tools.safeRegExp(selection.term, 'ig'), '$&') : str;
        },

        getTitle: function(data, properties) {
            var title = '', result;
            if (data) {
                if (properties === undefined) {
                    if (data.text !== undefined) {
                        title = data.text;
                    }
                } else {
                    result = [];
                    _.each(properties, function(property) {
                        result.push(data[property]);
                    });
                    title = result.join(' ');
                }
            }
            return title;
        }
    };

    return Select2Config;
});
<|endoftext|>


<commit_before>#     NoFlo - Flow-Based Programming for JavaScript
#     (c) 2014-2017 Flowhub UG
#     NoFlo may be freely distributed under the MIT license
{EventEmitter} = require 'events'

# ## NoFlo Port Base class
#
# Base port type used for options normalization. Both inports and outports extend this class.

# The list of valid datatypes for ports.
validTypes = [
  'all'
  'string'
  'number'
  'int'
  'object'
  'array'
  'boolean'
  'color'
  'date'
  'bang'
  'function'
  'buffer'
  'stream'
]

class BasePort extends EventEmitter
  constructor: (options) ->
    super()
    # Options holds all options of the current port
    @options = @handleOptions options
    # Sockets list contains all currently attached
    # connections to the port
    @sockets = []
    # Name of the graph node this port is in
    @node = null
    # Name of the port
    @name = null

  handleOptions: (options) ->
    options = {} unless options
    # We default to the `all` type if no explicit datatype
    # was provided
    options.datatype = 'all' unless options.datatype
    # By default ports are not required for graph execution
    options.required = false if options.required is undefined

    # Normalize the legacy `integer` type to `int`.
    options.datatype = 'int' if options.datatype is 'integer'

    # Ensure datatype defined for the port is valid
    if validTypes.indexOf(options.datatype) is -1
      throw new Error "Invalid port datatype '#{options.datatype}' specified, valid are #{validTypes.join(', ')}"

    # Ensure schema defined for the port is valid
    if options.type and not options.schema
      options.schema = options.type
      delete options.type
    if options.schema and options.schema.indexOf('/') is -1
      throw new Error "Invalid port schema '#{options.schema}' specified. Should be URL or MIME type"

    return options

  getId: ->
    unless @node and @name
      return 'Port'
    return "#{@node} #{@name.toUpperCase()}"

  getDataType: -> return @options.datatype
  getSchema: -> return @options.schema or null
  getDescription: -> return @options.description

  attach: (socket, index = null) ->
    if not @isAddressable() or index is null
      index = @sockets.length
    @sockets[index] = socket
    @attachSocket socket, index
    if @isAddressable()
      @emit 'attach', socket, index
      return
    @emit 'attach', socket
    return

  attachSocket: -> return

  detach: (socket) ->
    index = @sockets.indexOf socket
    if index is -1
      return
    @sockets[index] = undefined
    if @isAddressable()
      @emit 'detach', socket, index
      return
    @emit 'detach', socket
    return

  isAddressable: ->
    return true if @options.addressable
    return false

  isBuffered: ->
    return true if @options.buffered
    return false

  isRequired: ->
    return true if @options.required
    return false

  isAttached: (socketId = null) ->
    if @isAddressable() and socketId isnt null
      return true if @sockets[socketId]
      return false
    return true if @sockets.length
    return false

  listAttached: ->
    attached = []
    for socket, idx in @sockets
      continue unless socket
      attached.push idx
    return attached

  isConnected: (socketId = null) ->
    if @isAddressable()
      throw new Error "#{@getId()}: Socket ID required" if socketId is null
      throw new Error "#{@getId()}: Socket #{socketId} not available" unless @sockets[socketId]
      return @sockets[socketId].isConnected()

    connected = false
    @sockets.forEach (socket) ->
      return unless socket
      if socket.isConnected()
        connected = true
    return connected

  canAttach: -> return true

module.exports = BasePort
<commit_msg>decaffeinate: Convert BasePort.coffee to JS<commit_after>/*
 * decaffeinate suggestions:
 * DS102: Remove unnecessary code created because of implicit returns
 * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
 */
//     NoFlo - Flow-Based Programming for JavaScript
//     (c) 2014-2017 Flowhub UG
//     NoFlo may be freely distributed under the MIT license
const {EventEmitter} = require('events');

// ## NoFlo Port Base class
//
// Base port type used for options normalization. Both inports and outports extend this class.

// The list of valid datatypes for ports.
const validTypes = [
  'all',
  'string',
  'number',
  'int',
  'object',
  'array',
  'boolean',
  'color',
  'date',
  'bang',
  'function',
  'buffer',
  'stream'
];

class BasePort extends EventEmitter {
  constructor(options) {
    super();
    // Options holds all options of the current port
    this.options = this.handleOptions(options);
    // Sockets list contains all currently attached
    // connections to the port
    this.sockets = [];
    // Name of the graph node this port is in
    this.node = null;
    // Name of the port
    this.name = null;
  }

  handleOptions(options) {
    if (!options) { options = {}; }
    // We default to the `all` type if no explicit datatype
    // was provided
    if (!options.datatype) { options.datatype = 'all'; }
    // By default ports are not required for graph execution
    if (options.required === undefined) { options.required = false; }

    // Normalize the legacy `integer` type to `int`.
    if (options.datatype === 'integer') { options.datatype = 'int'; }

    // Ensure datatype defined for the port is valid
    if (validTypes.indexOf(options.datatype) === -1) {
      throw new Error(`Invalid port datatype '${options.datatype}' specified, valid are ${validTypes.join(', ')}`);
    }

    // Ensure schema defined for the port is valid
    if (options.type && !options.schema) {
      options.schema = options.type;
      delete options.type;
    }
    if (options.schema && (options.schema.indexOf('/') === -1)) {
      throw new Error(`Invalid port schema '${options.schema}' specified. Should be URL or MIME type`);
    }

    return options;
  }

  getId() {
    if (!this.node || !this.name) {
      return 'Port';
    }
    return `${this.node} ${this.name.toUpperCase()}`;
  }

  getDataType() { return this.options.datatype; }
  getSchema() { return this.options.schema || null; }
  getDescription() { return this.options.description; }

  attach(socket, index = null) {
    if (!this.isAddressable() || (index === null)) {
      index = this.sockets.length;
    }
    this.sockets[index] = socket;
    this.attachSocket(socket, index);
    if (this.isAddressable()) {
      this.emit('attach', socket, index);
      return;
    }
    this.emit('attach', socket);
  }

  attachSocket() {  }

  detach(socket) {
    const index = this.sockets.indexOf(socket);
    if (index === -1) {
      return;
    }
    this.sockets[index] = undefined;
    if (this.isAddressable()) {
      this.emit('detach', socket, index);
      return;
    }
    this.emit('detach', socket);
  }

  isAddressable() {
    if (this.options.addressable) { return true; }
    return false;
  }

  isBuffered() {
    if (this.options.buffered) { return true; }
    return false;
  }

  isRequired() {
    if (this.options.required) { return true; }
    return false;
  }

  isAttached(socketId = null) {
    if (this.isAddressable() && (socketId !== null)) {
      if (this.sockets[socketId]) { return true; }
      return false;
    }
    if (this.sockets.length) { return true; }
    return false;
  }

  listAttached() {
    const attached = [];
    for (let idx = 0; idx < this.sockets.length; idx++) {
      const socket = this.sockets[idx];
      if (!socket) { continue; }
      attached.push(idx);
    }
    return attached;
  }

  isConnected(socketId = null) {
    if (this.isAddressable()) {
      if (socketId === null) { throw new Error(`${this.getId()}: Socket ID required`); }
      if (!this.sockets[socketId]) { throw new Error(`${this.getId()}: Socket ${socketId} not available`); }
      return this.sockets[socketId].isConnected();
    }

    let connected = false;
    this.sockets.forEach(function(socket) {
      if (!socket) { return; }
      if (socket.isConnected()) {
        return connected = true;
      }
    });
    return connected;
  }

  canAttach() { return true; }
}

module.exports = BasePort;
<|endoftext|>


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

	KC3StrategyTabs.iconmaker = new KC3StrategyTab("iconmaker");

	KC3StrategyTabs.iconmaker.definition = {
		tabSelf: KC3StrategyTabs.iconmaker,

		/* INIT: mandatory
		Prepares initial static data needed.
		---------------------------------*/
		init: function() {
			this.iconSize = 70;
			this.croppieOptions = {
				boundary: { width: this.iconSize * 4, height: this.iconSize * 4 },
				viewport: { width: this.iconSize, height: this.iconSize, type: "circle" },
				showZoomer: false,
			};
			this.bgColors = ["#0070cc", "#8e0000"];
			this.shipId = 0;
			this.isDamaged = false;
			this.seasonalIdx = 0;
			this.imgUrl = "";
			this.isAbyssal = false;
			this.useOfficial = false;
			this.pointX = 0;
			this.pointY = 0;
			this.scale = 0.75;
			this.isLoading = false;
			this.serverIp = (new KC3Server()).setNum(PlayerManager.hq.server).ip;
		},

		/* RELOAD: optional
		Loads latest player or game data if needed.
		---------------------------------*/
		reload: function() {
		},

		/* EXECUTE: mandatory
		Places data onto the interface from scratch.
		---------------------------------*/
		execute: function() {
			// parameters intentionally not to be remembered
			this.imgUrl = "";
			this.isLoading = false;

			const updateParams = () => {
				$(".ship_id").val(this.shipId || "");
				$(".damaged").prop("checked", this.isDamaged);
				$(".abyssal").prop("checked", this.isAbyssal);
				$(".seasonal").val(this.seasonalIdx || "");
				$(".img_url").val(this.imgUrl);
			};
			updateParams();
			// event handlers binding
			this.croppie = $(".crop_container").croppie(this.croppieOptions);
			$(".ship_id").on("blur", e => {
				if(this.isLoading) {
					updateParams();
					return;
				}
				const newShipId = Number($(".ship_id").val());
				const damaged = !!$(".damaged").prop("checked");
				const newSeasonal = Number($(".seasonal").val()) || 0;
				const officialLink = !!$(".official").prop("checked");
				const isNewImage = newShipId !== this.shipId
					|| damaged !== this.isDamaged
					|| newSeasonal !== this.seasonalIdx
					|| officialLink !== this.useOfficial;
				if(!newShipId || !isNewImage) return;
				this.shipId = newShipId;
				this.isDamaged = damaged;
				this.seasonalIdx = newSeasonal;
				this.useOfficial = officialLink;
				const dbShip = WhoCallsTheFleetDb.db[`s${this.shipId}`];
				const illustId = this.seasonalIdx > 0 ? ((dbShip || {}).illust_extra || [])[this.seasonalIdx - 1] : this.shipId;
				const imgNo = 8 + (1 & this.isDamaged);
				const baseUrl = [
					"http://fleet.diablohu.com/!/pics-ships/",
					"http://fleet.diablohu.com/!/pics-ships-extra/",
					`http://${this.serverIp}/kcs2/resources`
				][this.useOfficial ? 2 : 1 & (this.seasonalIdx > 0)];
				this.imgUrl = this.useOfficial ?
					baseUrl + KC3Master.png_file(this.shipId, "full", "ship", this.isDamaged) :
					`${baseUrl}${illustId}/${imgNo}.png`;
				this.bindNewImage(isNewImage);
			});
			$(".damaged").on("change", e => {
				$(".ship_id").blur();
			});
			$(".seasonal").on("change", e => {
				$(".ship_id").blur();
			});
			$(".abyssal").on("change", e => {
				this.isAbyssal = !!$(".abyssal").prop("checked");
			});
			$(".official").on("change", e => {
				$(".ship_id").blur();
			});
			$(".img_url").on("blur", e => {
				if(this.isLoading) {
					$(".img_url").val(this.imgUrl);
					return;
				}
				const newUrl = $(".img_url").val();
				if(newUrl && newUrl !== this.imgUrl) {
					this.imgUrl = newUrl;
					this.bindNewImage(false);
				}
			});
			$(".crop_container").on("update.croppie", (e, data) => {
				$(".crop_info").text(JSON.stringify(data));
				[this.pointX, this.pointY] = data.points.map(v => Number(v));
				this.scale = data.zoom;
				$(".left").val(this.pointX);
				$(".top").val(this.pointY);
				// keep 3 decimals for zoom percent value
				$(".zoom").val(Math.floor(this.scale * 100000) / 1000);
			});
			$(".crop_info").text("{}");
			$(".point.left").on("blur", e => {
				const newLeft = Number($(".point.left").val()) || 0;
				if(newLeft !== this.pointX) {
					this.pointX = newLeft;
					this.bindNewImage(false);
				}
			}).val(this.pointX);
			$(".point.top").on("blur", e => {
				const newTop = Number($(".point.top").val()) || 0;
				if(newTop !== this.pointY) {
					this.pointY = newTop;
					this.bindNewImage(false);
				}
			}).val(this.pointY);
			$(".zoom").on("blur", e => {
				const newScale = (Number($(".zoom").val()) || 100) / 100;
				if(newScale !== this.scale) {
					this.scale = newScale;
					this.croppie.croppie("setZoom", this.scale);
				}
			}).val(this.scale * 100);
			$(".get_result").on("click", e => {
				this.croppie.croppie("result", {
					type: "canvas",
					format: "png",
					size: "viewport",
					circle: true,
					backgroundColor: this.bgColors[1 & this.isAbyssal],
				}).then(resp => {
					const imgElm = $('<img/>').addClass("cropped_icon")
						.attr("src", resp)
						.attr("alt", `${this.shipId}${this.isDamaged ? "_d" : ""}.png`);
					$(".cropped").append(imgElm);
					$(".cropped").show();
					$(".preview img").attr("src", resp);
					$(".preview").show();
				});
			});
			$(".cropped").on("click", ".cropped_icon,.existed_icon", e => {
				$(e.target).remove();
			});
		},

		/* UPDATE: optional
		Partially update elements of the interface,
			possibly without clearing all contents first.
		Be careful! Do not only update new data,
			but also handle the old states (do cleanup).
		Return `false` if updating all needed,
			EXECUTE will be invoked instead.
		---------------------------------*/
		update: function(pageParams) {
			// Use `pageParams` for latest page hash values,
			// KC3StrategyTabs.pageParams keeps the old values for states tracking

			// Returning `true` means updating has been handled.
			return false;
		},

		bindNewImage: function(addExistedRef = true) {
			this.isLoading = true;
			$(".loading").css("visibility", "visible");
			$(".img_url").removeClass("error").val(this.imgUrl);
			this.croppie.croppie("destroy");
			this.croppie = $(".crop_container").croppie(this.croppieOptions);
			this.croppie.croppie("bind", {
				url: this.imgUrl,
				zoom: this.scale,
				points: [this.pointX, this.pointY,
					this.pointX + this.iconSize / this.scale, this.pointY + this.iconSize / this.scale],
			}).then(img => {
				$(".cr-image").css("background", this.bgColors[1 & this.isAbyssal]);
				$(".loading").css("visibility", "hidden");
				this.isLoading = false;
				if(addExistedRef) {
					$(".cropped").append(" ").append(
					$("<img/>").addClass("existed_icon").attr("src",
						`/assets/img/${this.isAbyssal ? "abyss" : "ships"}/${this.shipId}${this.isDamaged ? "_d" : ""}.png`)
					);
					$(".cropped").show();
				}
			}).catch(e => {
				$(".loading").css("visibility", "hidden");
				this.isLoading = false;
				$(".img_url").addClass("error");
				// for http get exception, `e` will be a event instance instead of Error instance
				console.debug("Image loading failed", e);
				if(addExistedRef && this.isAbyssal) {
					$(".cropped").append(" ").append(
						$("<img/>").addClass("existed_icon")
							.attr("src", `/assets/img/abyss/${this.shipId}$.png`)
					);
					$(".cropped").show();
				}
			});
		},

	};
})();
<commit_msg>Fix iconmaker abyssal ref icon link<commit_after>(function(){
	"use strict";

	KC3StrategyTabs.iconmaker = new KC3StrategyTab("iconmaker");

	KC3StrategyTabs.iconmaker.definition = {
		tabSelf: KC3StrategyTabs.iconmaker,

		/* INIT: mandatory
		Prepares initial static data needed.
		---------------------------------*/
		init: function() {
			this.iconSize = 70;
			this.croppieOptions = {
				boundary: { width: this.iconSize * 4, height: this.iconSize * 4 },
				viewport: { width: this.iconSize, height: this.iconSize, type: "circle" },
				showZoomer: false,
			};
			this.bgColors = ["#0070cc", "#8e0000"];
			this.shipId = 0;
			this.isDamaged = false;
			this.seasonalIdx = 0;
			this.imgUrl = "";
			this.isAbyssal = false;
			this.useOfficial = false;
			this.pointX = 0;
			this.pointY = 0;
			this.scale = 0.75;
			this.isLoading = false;
			this.serverIp = (new KC3Server()).setNum(PlayerManager.hq.server).ip;
		},

		/* RELOAD: optional
		Loads latest player or game data if needed.
		---------------------------------*/
		reload: function() {
		},

		/* EXECUTE: mandatory
		Places data onto the interface from scratch.
		---------------------------------*/
		execute: function() {
			// parameters intentionally not to be remembered
			this.imgUrl = "";
			this.isLoading = false;

			const updateParams = () => {
				$(".ship_id").val(this.shipId || "");
				$(".damaged").prop("checked", this.isDamaged);
				$(".abyssal").prop("checked", this.isAbyssal);
				$(".seasonal").val(this.seasonalIdx || "");
				$(".img_url").val(this.imgUrl);
			};
			updateParams();
			// event handlers binding
			this.croppie = $(".crop_container").croppie(this.croppieOptions);
			$(".ship_id").on("blur", e => {
				if(this.isLoading) {
					updateParams();
					return;
				}
				const newShipId = Number($(".ship_id").val());
				const damaged = !!$(".damaged").prop("checked");
				const newSeasonal = Number($(".seasonal").val()) || 0;
				const officialLink = !!$(".official").prop("checked");
				const isNewImage = newShipId !== this.shipId
					|| damaged !== this.isDamaged
					|| newSeasonal !== this.seasonalIdx
					|| officialLink !== this.useOfficial;
				if(!newShipId || !isNewImage) return;
				this.shipId = newShipId;
				this.isDamaged = damaged;
				this.seasonalIdx = newSeasonal;
				this.useOfficial = officialLink;
				const dbShip = WhoCallsTheFleetDb.db[`s${this.shipId}`];
				const illustId = this.seasonalIdx > 0 ? ((dbShip || {}).illust_extra || [])[this.seasonalIdx - 1] : this.shipId;
				const imgNo = 8 + (1 & this.isDamaged);
				const baseUrl = [
					"http://fleet.diablohu.com/!/pics-ships/",
					"http://fleet.diablohu.com/!/pics-ships-extra/",
					`http://${this.serverIp}/kcs2/resources`
				][this.useOfficial ? 2 : 1 & (this.seasonalIdx > 0)];
				this.imgUrl = this.useOfficial ?
					baseUrl + KC3Master.png_file(this.shipId, "full", "ship", this.isDamaged) :
					`${baseUrl}${illustId}/${imgNo}.png`;
				this.bindNewImage(isNewImage);
			});
			$(".damaged").on("change", e => {
				$(".ship_id").blur();
			});
			$(".seasonal").on("change", e => {
				$(".ship_id").blur();
			});
			$(".abyssal").on("change", e => {
				this.isAbyssal = !!$(".abyssal").prop("checked");
			});
			$(".official").on("change", e => {
				$(".ship_id").blur();
			});
			$(".img_url").on("blur", e => {
				if(this.isLoading) {
					$(".img_url").val(this.imgUrl);
					return;
				}
				const newUrl = $(".img_url").val();
				if(newUrl && newUrl !== this.imgUrl) {
					this.imgUrl = newUrl;
					this.bindNewImage(false);
				}
			});
			$(".crop_container").on("update.croppie", (e, data) => {
				$(".crop_info").text(JSON.stringify(data));
				[this.pointX, this.pointY] = data.points.map(v => Number(v));
				this.scale = data.zoom;
				$(".left").val(this.pointX);
				$(".top").val(this.pointY);
				// keep 3 decimals for zoom percent value
				$(".zoom").val(Math.floor(this.scale * 100000) / 1000);
			});
			$(".crop_info").text("{}");
			$(".point.left").on("blur", e => {
				const newLeft = Number($(".point.left").val()) || 0;
				if(newLeft !== this.pointX) {
					this.pointX = newLeft;
					this.bindNewImage(false);
				}
			}).val(this.pointX);
			$(".point.top").on("blur", e => {
				const newTop = Number($(".point.top").val()) || 0;
				if(newTop !== this.pointY) {
					this.pointY = newTop;
					this.bindNewImage(false);
				}
			}).val(this.pointY);
			$(".zoom").on("blur", e => {
				const newScale = (Number($(".zoom").val()) || 100) / 100;
				if(newScale !== this.scale) {
					this.scale = newScale;
					this.croppie.croppie("setZoom", this.scale);
				}
			}).val(this.scale * 100);
			$(".get_result").on("click", e => {
				this.croppie.croppie("result", {
					type: "canvas",
					format: "png",
					size: "viewport",
					circle: true,
					backgroundColor: this.bgColors[1 & this.isAbyssal],
				}).then(resp => {
					const imgElm = $('<img/>').addClass("cropped_icon")
						.attr("src", resp)
						.attr("alt", `${this.shipId}${this.isDamaged ? "_d" : ""}.png`);
					$(".cropped").append(imgElm);
					$(".cropped").show();
					$(".preview img").attr("src", resp);
					$(".preview").show();
				});
			});
			$(".cropped").on("click", ".cropped_icon,.existed_icon", e => {
				$(e.target).remove();
			});
		},

		/* UPDATE: optional
		Partially update elements of the interface,
			possibly without clearing all contents first.
		Be careful! Do not only update new data,
			but also handle the old states (do cleanup).
		Return `false` if updating all needed,
			EXECUTE will be invoked instead.
		---------------------------------*/
		update: function(pageParams) {
			// Use `pageParams` for latest page hash values,
			// KC3StrategyTabs.pageParams keeps the old values for states tracking

			// Returning `true` means updating has been handled.
			return false;
		},

		bindNewImage: function(addExistedRef = true) {
			this.isLoading = true;
			$(".loading").css("visibility", "visible");
			$(".img_url").removeClass("error").val(this.imgUrl);
			this.croppie.croppie("destroy");
			this.croppie = $(".crop_container").croppie(this.croppieOptions);
			this.croppie.croppie("bind", {
				url: this.imgUrl,
				zoom: this.scale,
				points: [this.pointX, this.pointY,
					this.pointX + this.iconSize / this.scale, this.pointY + this.iconSize / this.scale],
			}).then(img => {
				$(".cr-image").css("background", this.bgColors[1 & this.isAbyssal]);
				$(".loading").css("visibility", "hidden");
				this.isLoading = false;
				if(addExistedRef) {
					const refId = this.isAbyssal ? this.shipId - 1000 : this.shipId;
					$(".cropped").append(" ").append(
					$("<img/>").addClass("existed_icon").attr("src",
						`/assets/img/${this.isAbyssal ? "abyss" : "ships"}/${refId}${this.isDamaged ? "_d" : ""}.png`)
					);
					$(".cropped").show();
				}
			}).catch(e => {
				$(".loading").css("visibility", "hidden");
				this.isLoading = false;
				$(".img_url").addClass("error");
				// for http get exception, `e` will be a event instance instead of Error instance
				console.debug("Image loading failed", e);
				if(addExistedRef && this.isAbyssal) {
					const refId = this.isAbyssal ? this.shipId - 1000 : this.shipId;
					$(".cropped").append(" ").append(
						$("<img/>").addClass("existed_icon")
							.attr("src", `/assets/img/abyss/${this.refId}$.png`)
					);
					$(".cropped").show();
				}
			});
		},

	};
})();
<|endoftext|>


<commit_before>/*
*
* Copyright (C) 2011, The Locker Project
* All rights reserved.
*
* Please see the LICENSE file for more information.
*
*/

/*
* Tests the acutal implementation of the lsyncmanager.
*/

require.paths.push(__dirname + "/../Common/node");
var vows = require("vows")
  , assert = require("assert")
  , lconfig = require("lconfig")
  , fs = require('fs')
  , mongo
  , request = require('request')
  , events = {}
  , eventCount = 0
  , events = []
  , dataSets = []
  , dataSets[0] = {"config" : { "ids" : { [1, 500]}},
                   "data": [ { "obj" : {"id" : 500, "someData":"BAM"}, "type" : "new", "timestamp" : 1312325283581 },
                             {"obj" : {"id" : 1, "someData":"datas"}, "type" : "new", "timestamp" : 1312325283582 }]}
  , dataSets[1] = {"config" : {}, "data" : {}};
  , dataSets[2] = {"config" : "ids" : {[1]}};
  , dataSets[3] = {"data": [ { "obj" : {"notId" : 1}, "timestamp" : 1312325283583 } ]};
  ;

lconfig.load("Config/config.json");

var pushManager = require("lpushmanager.js");
var lmongo = require('../Common/node/lmongo');

pushManager.eventEmitter.on('push/testing', function(event) {
    events.push(event);
    eventCount++;
});

vows.describe("Push Manager").addBatch({
    "has a map of the data sets" : function() {
        assert.include(pushManager, "datasets");
        assert.equal(pushManager, []);
    },
}).addBatch({
    "Data sets can be created by pushing arbitrary data in" : {
        topic:function() {
            events = {};
            request.post({uri : "http://localhost:8043/push/testing", json: dataSets[0]}, this.callback);
        },
        "which adds that set to the map" : function(err, status) {
            assert.isNull(err);
            assert.include(pushManager.datasets, "testing");
        },
        "and also" : {
            "generates events" : function() {
                assert.equal(eventCount, 2);
                assert.equal(events[1].type, 'new');
                assert.notEqual(events[0].data._id, undefined);
                assert.notEqual(events[1].data._id, undefined)
                assert.equal(events[0].data.id, 500);
                assert.equal(events[1].data.id, 1);
                events = [];
            },
            "and generates mongo data" : {
                topic: function() {
                    var self = this;
                    lmongo.init('push', ['testing'], function(theMongo, theColls) {
                        mongo = theMongo;
                        colls = theColls;
                        colls.testing.count(self.callback);
                    });
                },
                "successfully" : function(err, count) {
                    assert.equal(count, 1);
                }
            },
            "and writes out IJOD stuff" : {
                topic; function() {
                    fs.readFile(lconfig.me + "/push/testing.json", this.callback);
                },
                "successfully" : function(err, data) {
                    assert.equal(data.toString(), '{"timeStamp":1312325283581,"data":{"id":500,"someData":"BAM"}}\n{"timeStamp":1312325283582,"data":{"id":1,"someData":"datas"}}\n');
                }
            }
        }
    },
}).addBatch({
    "Querying the data API returns the data" : {
        topic: function() {
            request.get({uri : "http://localhost:8043/push/testing/getCurrent"}, this.callback)
        },
        "from testSync" : function(err, resp, body) {
            var data = JSON.parse(body);
            _id = data[0]._id;
            obj = data[0];
            assert.equal(data[0].id, 500);
            assert.equal(data[0].someData, 'BAM');
        }
    }
}).addBatch({
    "Querying for an ID returns the object": {
        topic: function() {
            request.get({uri : "http://localhost:8043/push/testing/" + _id}, this.callback);
        },
        "successfully" : function(err, resp, body) {
            var data = JSON.parse(body);
            assert.deepEqual(obj, data);
        }
    }
}).addBatch({
    "Pushing to that same API again" : {
        topic: function() {
            events = [];
            request.post({uri : "http://localhost:8043/push/testing", json: dataSets[1]}, this.callback);
        },
        "with no data will leave everything intact" : function(topic) {
            assert.equal(events.length, 0);
            assert.equal(events[0], undefined);
        }
    }
}).addBatch({
    "If the source doesn't return an ID" : {
        topic: function() {
            var self = this;
            events = [];
            request.post({uri : "http://localhost:8043/push/testing", json: dataSets[2]}, function() {
                 colls.testing.count(self.callback);
            });
        },
        "it will generate a delete event and remove the row from mongo" : function(err, count) {
            assert.equal(count, 1);
            assert.equal(events.length, 1);
            assert.equal(events[0].type, 'delete');
            assert.equal(events[0].data.id, 500);
        }
    }
}).addBatch({
    "Pushing invalid data" : {
        topic: function() {
            request.post({uri : "http://localhost:8043/push/testing", json: dataSets[3]}, this.callback);
        },
        "with no value for 'id' errors" : function(err, status, data) {
            assert.equal(err.message, 'no value for primary key');
        }
    }
}).addBatch({
    "an endpoint is available" : {
        topic: function() {
            request.get({uri : "http://localhost:8043/pushMap"}, this.callback);
        },
        "to query the map" : function(err, status, data) {
            assert.equal(data, ["testing"]);
        }
    }
}).export(module);

<commit_msg>tessssstsssss<commit_after>/*
*
* Copyright (C) 2011, The Locker Project
* All rights reserved.
*
* Please see the LICENSE file for more information.
*
*/

/*
* Tests the acutal implementation of the lsyncmanager.
*/

require.paths.push(__dirname + "/../Common/node");
var vows = require("vows")
  , assert = require("assert")
  , lconfig = require("lconfig")
  , fs = require('fs')
  , mongo
  , request = require('request')
  , events = {}
  , eventCount = 0
  , events = []
  , dataSets = []
  ;

dataSets[0] = {"config" : { "ids" : [1, 500] },
               "data": [ { "obj" : {"id" : 500, "someData":"BAM"}, "type" : "new", "timestamp" : 1312325283581 },
                         {"obj" : {"id" : 1, "someData":"datas"}, "type" : "new", "timestamp" : 1312325283582 }]}
dataSets[1] = {"config" : {}, "data" : {}};
dataSets[2] = {"config" : { "ids" : [1] } };
dataSets[3] = {"data": [ { "obj" : {"notId" : 1}, "timestamp" : 1312325283583 } ]};

lconfig.load("Config/config.json");

var pushManager = require(__dirname + "/../Common/node/lpushmanager.js");
var lmongo = require(__dirname + '/../Common/node/lmongo');

pushManager.eventEmitter.on('push/testing', function(event) {
    events.push(event);
    eventCount++;
});

vows.describe("Push Manager").addBatch({
    "has a map of the data sets" : function() {
        assert.include(pushManager, "datasets");
        assert.equal(pushManager, []);
    },
}).addBatch({
    "Data sets can be created by pushing arbitrary data in" : {
        topic:function() {
            events = {};
            request.post({uri : "http://localhost:8043/push/testing", json: dataSets[0]}, this.callback);
        },
        "which adds that set to the map" : function(err, status) {
            assert.isNull(err);
            assert.include(pushManager.datasets, "testing");
        },
        "and also" : {
            "generates events" : function() {
                assert.equal(eventCount, 2);
                assert.equal(events[1].type, 'new');
                assert.notEqual(events[0].data._id, undefined);
                assert.notEqual(events[1].data._id, undefined)
                assert.equal(events[0].data.id, 500);
                assert.equal(events[1].data.id, 1);
                events = [];
            },
            "and generates mongo data" : {
                topic: function() {
                    var self = this;
                    lmongo.init('push', ['testing'], function(theMongo, theColls) {
                        mongo = theMongo;
                        colls = theColls;
                        colls.testing.count(self.callback);
                    });
                },
                "successfully" : function(err, count) {
                    assert.equal(count, 1);
                }
            },
            "and writes out IJOD stuff" : {
                topic: function() {
                    fs.readFile(lconfig.me + "/push/testing.json", this.callback);
                },
                "successfully" : function(err, data) {
                    assert.equal(data.toString(), '{"timeStamp":1312325283581,"data":{"id":500,"someData":"BAM"}}\n{"timeStamp":1312325283582,"data":{"id":1,"someData":"datas"}}\n');
                }
            }
        }
    },
}).addBatch({
    "Querying the data API returns the data" : {
        topic: function() {
            request.get({uri : "http://localhost:8043/push/testing/getCurrent"}, this.callback)
        },
        "from testSync" : function(err, resp, body) {
            var data = JSON.parse(body);
            _id = data[0]._id;
            obj = data[0];
            assert.equal(data[0].id, 500);
            assert.equal(data[0].someData, 'BAM');
        }
    }
}).addBatch({
    "Querying for an ID returns the object": {
        topic: function() {
            request.get({uri : "http://localhost:8043/push/testing/" + _id}, this.callback);
        },
        "successfully" : function(err, resp, body) {
            var data = JSON.parse(body);
            assert.deepEqual(obj, data);
        }
    }
}).addBatch({
    "Pushing to that same API again" : {
        topic: function() {
            events = [];
            request.post({uri : "http://localhost:8043/push/testing", json: dataSets[1]}, this.callback);
        },
        "with no data will leave everything intact" : function(topic) {
            assert.equal(events.length, 0);
            assert.equal(events[0], undefined);
        }
    }
}).addBatch({
    "If the source doesn't return an ID" : {
        topic: function() {
            var self = this;
            events = [];
            request.post({uri : "http://localhost:8043/push/testing", json: dataSets[2]}, function() {
                 colls.testing.count(self.callback);
            });
        },
        "it will generate a delete event and remove the row from mongo" : function(err, count) {
            assert.equal(count, 1);
            assert.equal(events.length, 1);
            assert.equal(events[0].type, 'delete');
            assert.equal(events[0].data.id, 500);
        }
    }
}).addBatch({
    "Pushing invalid data" : {
        topic: function() {
            request.post({uri : "http://localhost:8043/push/testing", json: dataSets[3]}, this.callback);
        },
        "with no value for 'id' errors" : function(err, status, data) {
            assert.equal(err.message, 'no value for primary key');
        }
    }
}).addBatch({
    "an endpoint is available" : {
        topic: function() {
            request.get({uri : "http://localhost:8043/pushMap"}, this.callback);
        },
        "to query the map" : function(err, status, data) {
            assert.equal(data, ["testing"]);
        }
    }
}).addBatch({
    "can use the query API" : {
        topic: function() {
            request.get({uri : "http://localhost:8043/query/getPush?dataset=testing&limit=1"}, this.callback);
        },
        "to get at the data" : function(err, status, data) {
            assert.equal(data.length, 1);
        }
    }
}).export(module);

<|endoftext|>


<commit_before>function toggleQuickAddButton() {
  var fab = document.querySelector('.fab');
  fab.classList.toggle('collapsed');
  fab.classList.toggle('expanded');
}

function openQuickAddForm(startingStep) {
  Session.set('quickadd current step', startingStep || 0);
  $('.quickaddform').openModal();
  toggleQuickAddButton();
}

function closeQuickAddForm() {
  Session.set('quickadd current step', -1);
  $('.quickaddform').closeModal();
}

Template.fab.helpers({
  isQuickAdding: function() {
    return !Session.equals('quickadd current step', -1);
  },
  reportTypes: function() {
    return reportTypes.common;
  }
});

Template.fab.events({
  'click .btn-floating': function(evt) {
    evt.currentTarget.parentNode.classList.remove('no-anim');
    toggleQuickAddButton(evt.currentTarget.parentNode);
  },
  'click .dimmer': function() {
    toggleQuickAddButton();
  },
  'click .quick-report': function(evt) {
    var reportCategory = evt.currentTarget.dataset.reportCategory;
    var reportName = evt.currentTarget.dataset.reportName;
    if (reportCategory === 'other') {
      openQuickAddForm(0);
    } else {
      Session.set('quickadd choice 0', reportName);
      openQuickAddForm(1);
    }
  }
});

function getLines(type) {
  return lines.km.map(function(elem) { return elem.line; });
}

function getLines(type) {
  return lines.km.map(function(elem) { return elem.line; });
}

var transportTypes = {
  'Metro': 'metro',
  'WKD': 'wkd',
  'SKM': 'skm',
  'KM': 'km',
};

var quickSteps = [
  {
    name: 'Co się dzieje?',
    choices: function() {
      return allReportTypes.slice(0, -1);
    }
  },
  {
    name: 'Gdzie?',
    choices: function() {
      return Object.keys(transportTypes).map(function(elem) {
        return { name: elem };
      });
    }
  },
  {
    name: 'Na której linii?',
    choices: function() {
      var type = Session.get('quickadd choice 1');
      return lines[transportTypes[type]];
    },
  },
  {
    name: 'W którym kierunku?',
    choices: function() {
      var type = Session.get('quickadd choice 1');
      var line = Session.get('quickadd choice 2');
      return lines[transportTypes[type]].filter(function(elem) {
        return elem.name === line;
      })[0].directions;
    }
  }
];

Template.quickadd.helpers({
  isCurrentStep: function(stepIndex) {
    return Session.equals('quickadd current step', stepIndex);
  },
  isStepComplete: function(stepIndex) {
    return Session.get('quickadd current step') > stepIndex;
  },
  steps: quickSteps.map(function(step, i) {
    return { name: step.name, index: i };
  }),
  choices: function() {
    var stepIndex = Session.get('quickadd current step');
    if (quickSteps[stepIndex]) {
      return quickSteps[stepIndex].choices();
    }
  },
  stepChoice: function(stepIndex) {
    return Session.get('quickadd choice ' + stepIndex);
  }
});

Template.quickadd.events({
  'click .close': function() {
    closeQuickAddForm();
  },
  'click .collapsible-header.complete': function(evt) {
    var stepIndex = parseInt(evt.currentTarget.dataset.stepIndex);
    Session.set('quickadd current step', stepIndex);
  },
  'click .collection-item': function(evt) {
    var choice = evt.currentTarget.dataset.choice;
    var stepIndex = Session.get('quickadd current step');
    Session.set('quickadd choice ' + stepIndex, choice);
    Session.set('quickadd current step', stepIndex + 1);
  },
});

<commit_msg>icons for transport types<commit_after>function toggleQuickAddButton() {
  var fab = document.querySelector('.fab');
  fab.classList.toggle('collapsed');
  fab.classList.toggle('expanded');
}

function openQuickAddForm(startingStep) {
  Session.set('quickadd current step', startingStep || 0);
  $('.quickaddform').openModal();
  toggleQuickAddButton();
}

function closeQuickAddForm() {
  Session.set('quickadd current step', -1);
  $('.quickaddform').closeModal();
}

Template.fab.helpers({
  isQuickAdding: function() {
    return !Session.equals('quickadd current step', -1);
  },
  reportTypes: function() {
    return reportTypes.common;
  }
});

Template.fab.events({
  'click .btn-floating': function(evt) {
    evt.currentTarget.parentNode.classList.remove('no-anim');
    toggleQuickAddButton(evt.currentTarget.parentNode);
  },
  'click .dimmer': function() {
    toggleQuickAddButton();
  },
  'click .quick-report': function(evt) {
    var reportCategory = evt.currentTarget.dataset.reportCategory;
    var reportName = evt.currentTarget.dataset.reportName;
    if (reportCategory === 'other') {
      openQuickAddForm(0);
    } else {
      Session.set('quickadd choice 0', reportName);
      openQuickAddForm(1);
    }
  }
});

var transportTypes = {
  'Metro': { slug: 'metro', icon: 'mdi-maps-directions-subway' },
  'WKD': { slug: 'wkd', icon: 'mdi-maps-directions-train' },
  'SKM': { slug: 'skm', icon: 'mdi-maps-directions-train' },
  'KM': { slug: 'km', icon: 'mdi-maps-directions-train' },
};

var quickSteps = [
  {
    name: 'Co się dzieje?',
    choices: function() {
      return allReportTypes.slice(0, -1);
    }
  },
  {
    name: 'Gdzie?',
    choices: function() {
      return Object.keys(transportTypes).map(function(elem) {
        return { name: elem, icon: transportTypes[elem].icon };
      });
    }
  },
  {
    name: 'Na której linii?',
    choices: function() {
      var type = Session.get('quickadd choice 1');
      return lines[transportTypes[type].slug];
    },
  },
  {
    name: 'W którym kierunku?',
    choices: function() {
      var type = Session.get('quickadd choice 1');
      var line = Session.get('quickadd choice 2');
      return lines[transportTypes[type].slug].filter(function(elem) {
        return elem.name === line;
      })[0].directions;
    }
  }
];

Template.quickadd.helpers({
  isCurrentStep: function(stepIndex) {
    return Session.equals('quickadd current step', stepIndex);
  },
  isStepComplete: function(stepIndex) {
    return Session.get('quickadd current step') > stepIndex;
  },
  steps: quickSteps.map(function(step, i) {
    return { name: step.name, index: i };
  }),
  choices: function() {
    var stepIndex = Session.get('quickadd current step');
    if (quickSteps[stepIndex]) {
      return quickSteps[stepIndex].choices();
    }
  },
  stepChoice: function(stepIndex) {
    return Session.get('quickadd choice ' + stepIndex);
  }
});

Template.quickadd.events({
  'click .close': function() {
    closeQuickAddForm();
  },
  'click .collapsible-header.complete': function(evt) {
    var stepIndex = parseInt(evt.currentTarget.dataset.stepIndex);
    Session.set('quickadd current step', stepIndex);
  },
  'click .collection-item': function(evt) {
    var choice = evt.currentTarget.dataset.choice;
    var stepIndex = Session.get('quickadd current step');
    Session.set('quickadd choice ' + stepIndex, choice);
    Session.set('quickadd current step', stepIndex + 1);
  },
});

<|endoftext|>


<commit_before>const fs = require('fs');

/**
 * Replace any characters that can't be sent on with an underscore
 */
function sanitizeTags(value, telegraf) {
  const blacklist = telegraf ? /:|\|/g : /:|\||@|,/g;
  // Replace reserved chars with underscores.
  return String(value).replace(blacklist, '_');
}

/**
 * Format tags properly before sending on
 */
function formatTags(tags, telegraf) {
  if (Array.isArray(tags)) {
    return tags;

  } else {
    return Object.keys(tags).map(key => {
      return `${sanitizeTags(key, telegraf)}:${sanitizeTags(tags[key], telegraf)}`;
    });
  }
}

/**
 * Overrides tags in parent with tags from child with the same name (case sensitive) and return the result as new
 * array. parent and child are not mutated.
 */
function overrideTags (parent, child, telegraf) {
  const childCopy = {};
  const toAppend = [];
  formatTags(child, telegraf).forEach(tag => {
    const idx = typeof tag === 'string' ? tag.indexOf(':') : -1;
    if (idx < 1) { // Not found or first character
      toAppend.push(tag);
    } else {
      childCopy[tag.substring(0, idx)] = tag.substring(idx + 1);
    }
  });
  const result = parent.map(tag => {
    const idx = typeof tag === 'string' ? tag.indexOf(':') : -1;
    if (idx < 1) { // Not found or first character
      return tag;
    }
    const key = tag.substring(0, idx);
    if (childCopy.hasOwnProperty(key)) {
      const value = childCopy[key];
      delete childCopy[key];
      return `${key}:${value}`;
    }
    return tag;
  });
  Object.keys(childCopy).forEach(key => {
    result.push(`${key}:${childCopy[key]}`);
  });
  return result.concat(toAppend);
}

/**
 * Formats a date for use with DataDog
 */
function formatDate(date) {
  let timestamp;
  if (date instanceof Date) {
    // Datadog expects seconds.
    timestamp = Math.round(date.getTime() / 1000);
  } else if (date instanceof Number) {
    // Make sure it is an integer, not a float.
    timestamp = Math.round(date);
  }
  return timestamp;
}

/**
 * Converts int to a string IP
 */
function intToIP(int) {
  const part1 = int & 255;
  const part2 = ((int >> 8) & 255);
  const part3 = ((int >> 16) & 255);
  const part4 = ((int >> 24) & 255);

  return `${part4}.${part3}.${part2}.${part1}`;
}

/**
 * Returns the system default interface on Linux
 */
function getDefaultRoute() {
  try {
    const fileContents = fs.readFileSync('/proc/net/route', 'utf8'); // eslint-disable-line no-sync
    const routes = fileContents.split('\n');
    for (const routeIdx in routes) {
      const fields = routes[routeIdx].trim().split('\t');
      if (fields[1] === '00000000') {
        const address = fields[2];
        // Convert to little endian by splitting every 2 digits and reversing that list
        const littleEndianAddress = address.match(/.{2}/g).reverse().join('');
        return intToIP(parseInt(littleEndianAddress, 16));
      }
    }
  } catch (e) {
    console.error('Could not get default route from /proc/net/route');
  }
  return null;
}

module.exports = {
  formatTags: formatTags,
  overrideTags: overrideTags,
  formatDate: formatDate,
  getDefaultRoute: getDefaultRoute,
  sanitizeTags: sanitizeTags
};
<commit_msg>sanitize ',' characters in tags<commit_after>const fs = require('fs');

/**
 * Replace any characters that can't be sent on with an underscore
 */
function sanitizeTags(value, telegraf) {
  const blacklist = telegraf ? /:|\||,/g : /:|\||@|,/g;
  // Replace reserved chars with underscores.
  return String(value).replace(blacklist, '_');
}

/**
 * Format tags properly before sending on
 */
function formatTags(tags, telegraf) {
  if (Array.isArray(tags)) {
    return tags;

  } else {
    return Object.keys(tags).map(key => {
      return `${sanitizeTags(key, telegraf)}:${sanitizeTags(tags[key], telegraf)}`;
    });
  }
}

/**
 * Overrides tags in parent with tags from child with the same name (case sensitive) and return the result as new
 * array. parent and child are not mutated.
 */
function overrideTags (parent, child, telegraf) {
  const childCopy = {};
  const toAppend = [];
  formatTags(child, telegraf).forEach(tag => {
    const idx = typeof tag === 'string' ? tag.indexOf(':') : -1;
    if (idx < 1) { // Not found or first character
      toAppend.push(tag);
    } else {
      childCopy[tag.substring(0, idx)] = tag.substring(idx + 1);
    }
  });
  const result = parent.map(tag => {
    const idx = typeof tag === 'string' ? tag.indexOf(':') : -1;
    if (idx < 1) { // Not found or first character
      return tag;
    }
    const key = tag.substring(0, idx);
    if (childCopy.hasOwnProperty(key)) {
      const value = childCopy[key];
      delete childCopy[key];
      return `${key}:${value}`;
    }
    return tag;
  });
  Object.keys(childCopy).forEach(key => {
    result.push(`${key}:${childCopy[key]}`);
  });
  return result.concat(toAppend);
}

/**
 * Formats a date for use with DataDog
 */
function formatDate(date) {
  let timestamp;
  if (date instanceof Date) {
    // Datadog expects seconds.
    timestamp = Math.round(date.getTime() / 1000);
  } else if (date instanceof Number) {
    // Make sure it is an integer, not a float.
    timestamp = Math.round(date);
  }
  return timestamp;
}

/**
 * Converts int to a string IP
 */
function intToIP(int) {
  const part1 = int & 255;
  const part2 = ((int >> 8) & 255);
  const part3 = ((int >> 16) & 255);
  const part4 = ((int >> 24) & 255);

  return `${part4}.${part3}.${part2}.${part1}`;
}

/**
 * Returns the system default interface on Linux
 */
function getDefaultRoute() {
  try {
    const fileContents = fs.readFileSync('/proc/net/route', 'utf8'); // eslint-disable-line no-sync
    const routes = fileContents.split('\n');
    for (const routeIdx in routes) {
      const fields = routes[routeIdx].trim().split('\t');
      if (fields[1] === '00000000') {
        const address = fields[2];
        // Convert to little endian by splitting every 2 digits and reversing that list
        const littleEndianAddress = address.match(/.{2}/g).reverse().join('');
        return intToIP(parseInt(littleEndianAddress, 16));
      }
    }
  } catch (e) {
    console.error('Could not get default route from /proc/net/route');
  }
  return null;
}

module.exports = {
  formatTags: formatTags,
  overrideTags: overrideTags,
  formatDate: formatDate,
  getDefaultRoute: getDefaultRoute,
  sanitizeTags: sanitizeTags
};
<|endoftext|>


<commit_before>dc.ui.Scroll = dc.View.extend({

  OVERLAP_MARGIN : 50,

  SPEED: 500,

  className : 'scroll',

  callbacks : {
    '.scroll_up.click'    : 'scrollUp',
    '.scroll_down.click'  : 'scrollDown',
    'el.mousewheel'       : '_mouseScroll'
  },

  // Given a div with overflow:hidden, make the div scrollable by inserting
  // "page up" and "page down" divs at the top and bottom.
  constructor : function(el) {
    this.base();
    this.content    = $(el);
    this.upButton   = $.el('div', {'class' : 'scroll_up'});
    this.downButton = $.el('div', {'class' : 'scroll_down'});
  },

  render : function() {
    this.content.addClass('scroll_content');
    this.content.wrap(this.el);
    this.el = $(this.content).closest('.scroll')[0];
    this.content.before(this.upButton);
    this.content.after(this.downButton);
    $(window).resize(_.bind(this.check, this));
    this.setCallbacks();
    return this;
  },

  scrollUp : function() {
    var distance = this.content.innerHeight() - this.OVERLAP_MARGIN;
    var top = this.content[0].scrollTop - distance;
    this.content.animate({scrollTop : top}, this.SPEED, null, _.bind(this.setPosition, this, top));
  },

  scrollDown : function() {
    var distance = this.content.innerHeight() - this.OVERLAP_MARGIN;
    var top = this.content[0].scrollTop + distance;
    this.content.animate({scrollTop : top}, this.SPEED, null, _.bind(this.setPosition, this, top));
  },

  check : function() {
    var over = this.hasOverflow();
    if (over == this._overflow) return;
    this._overflow = over;
    this.setMode(over ? 'is' : 'not', 'active');
    this.setPosition(this.content[0].scrollTop);
  },

  hasOverflow : function() {
    return this.content.innerHeight() < this.content[0].scrollHeight;
  },

  setPosition : function(scrollTop) {
    var mode = scrollTop <= 0 ? 'top' :
      scrollTop + this.content.innerHeight() >= this.content[0].scrollHeight ? 'bottom' :
      'middle';
    if (this.modes.position == mode) return;
    this.setMode(mode, 'position');
  },

  _mouseScroll : function(e, distance) {
    if (this.modes.active == 'not' ||
       (distance >= 0 && this.modes.position == 'top') ||
       (distance <= 0 && this.modes.position == 'bottom')) return;
    var top = this.content[0].scrollTop - distance;
    this.content[0].scrollTop = top;
    this.setPosition(top);
    return false;
  }

});<commit_msg>stop trying to cache the overflow<commit_after>dc.ui.Scroll = dc.View.extend({

  OVERLAP_MARGIN : 50,

  SPEED: 500,

  className : 'scroll',

  callbacks : {
    '.scroll_up.click'    : 'scrollUp',
    '.scroll_down.click'  : 'scrollDown',
    'el.mousewheel'       : '_mouseScroll'
  },

  // Given a div with overflow:hidden, make the div scrollable by inserting
  // "page up" and "page down" divs at the top and bottom.
  constructor : function(el) {
    this.base();
    this.content    = $(el);
    this.upButton   = $.el('div', {'class' : 'scroll_up'});
    this.downButton = $.el('div', {'class' : 'scroll_down'});
  },

  render : function() {
    this.content.addClass('scroll_content');
    this.content.wrap(this.el);
    this.el = $(this.content).closest('.scroll')[0];
    this.content.before(this.upButton);
    this.content.after(this.downButton);
    $(window).resize(_.bind(this.check, this));
    this.setCallbacks();
    return this;
  },

  scrollUp : function() {
    var distance = this.content.innerHeight() - this.OVERLAP_MARGIN;
    var top = this.content[0].scrollTop - distance;
    this.content.animate({scrollTop : top}, this.SPEED, null, _.bind(this.setPosition, this, top));
  },

  scrollDown : function() {
    var distance = this.content.innerHeight() - this.OVERLAP_MARGIN;
    var top = this.content[0].scrollTop + distance;
    this.content.animate({scrollTop : top}, this.SPEED, null, _.bind(this.setPosition, this, top));
  },

  check : function() {
    var over = this.hasOverflow();
    this.setMode(over ? 'is' : 'not', 'active');
    this.setPosition(this.content[0].scrollTop);
  },

  hasOverflow : function() {
    return this.content.innerHeight() < this.content[0].scrollHeight;
  },

  setPosition : function(scrollTop) {
    var mode = scrollTop <= 0 ? 'top' :
      scrollTop + this.content.innerHeight() >= this.content[0].scrollHeight ? 'bottom' :
      'middle';
    if (this.modes.position == mode) return;
    this.setMode(mode, 'position');
  },

  _mouseScroll : function(e, distance) {
    if (this.modes.active == 'not' ||
       (distance >= 0 && this.modes.position == 'top') ||
       (distance <= 0 && this.modes.position == 'bottom')) return;
    var top = this.content[0].scrollTop - distance;
    this.content[0].scrollTop = top;
    this.setPosition(top);
    return false;
  }

});<|endoftext|>


<commit_before>import tldjs from 'tldjs'

import 'src/activity-logger/background'
import 'src/scheduled-tasks/background'
import 'src/blacklist/background'
import 'src/omnibar'
import { installTimeStorageKey } from 'src/imports/background'
import convertOldData from 'src/util/old-data-converter'
import fetchPageData from 'src/page-analysis/background/fetch-page-data'
import { findPagesByUrl } from 'src/search/find-pages'
import { transformToBookmarkDoc } from 'src/imports/background/imports-preparation'
import { dataURLToBlob } from 'blob-util'
import { generatePageDocId } from 'src/page-storage'
import db from 'src/pouchdb'

export const dataConvertTimeKey = 'data-conversion-timestamp'

export async function bookmarkStorageListener(id, bookmarkInfo) {
    const urlToFind = bookmarkInfo.url
    const samePageCandidates = (await findPagesByUrl({urlToFind})).rows.map(row => row.doc)
    if (samePageCandidates.length > 0) {
        let pageDoc = samePageCandidates[samePageCandidates.length - 1]
        const bookmarkDoc = await transformToBookmarkDoc(pageDoc)(bookmarkInfo)
        db.bulkDocs([bookmarkDoc, pageDoc])
        return
    }
    let pageDoc = {
        url: bookmarkInfo.url,
        title: bookmarkInfo.title,
        _id: generatePageDocId(bookmarkInfo.dateAdded, id),
    }
    try {
        console.log("Trying to get page data")
        let freezeDryFlag = false
        browser.storage.local.get('freeze-dry-bookmarks').then(result => {
            freezeDryFlag = result
        }).catch(error => {})
        let fetchPageDataOptions = {
            includePageContent: true,
            includeFavIcon: true,
            includeFreezeDry: freezeDryFlag,
        }
        const pageData = await fetchPageData({ url: bookmarkInfo.url, opts: fetchPageDataOptions })
        const favIconBlob = await dataURLToBlob(pageData.favIconURI)
        const freezeDryBlob = new Blob([pageData.freezeDryHTML], {type: 'text/html;charset=UTF-8'})
        pageDoc.content = pageData.content
        pageDoc._attachments = {
            'freeze-dry-blob': {
                content_type: freezeDryBlob.type,
                data: freezeDryBlob,
            },
            'fav-icon-blob': {
                content_type: favIconBlob.type,
                data: favIconBlob,
            },
        }
    } catch (err) {
        console.log("Error occurred while fetching page data: " + err.toString())
    } finally {
        const bookmarkDoc = await transformToBookmarkDoc(pageDoc)(bookmarkInfo)
        console.log(bookmarkDoc)
        db.bulkDocs([bookmarkDoc, pageDoc])
    }
}

async function openOverview() {
    const [ currentTab ] = await browser.tabs.query({ active: true })
    if (currentTab && currentTab.url) {
        const validUrl = tldjs.isValid(currentTab.url)
        if (validUrl) {
            return browser.tabs.create({
                url: '/overview/overview.html',
            })
        }
    }

    browser.tabs.update({
        url: '/overview/overview.html',
    })
}

// Open the overview when the extension's button is clicked
browser.browserAction.onClicked.addListener(() => {
    openOverview()
})

browser.bookmarks.onCreated.addListener(bookmarkStorageListener)

browser.commands.onCommand.addListener(command => {
    if (command === 'openOverview') {
        openOverview()
    }
})

browser.runtime.onInstalled.addListener(async details => {
    // Store the timestamp of when the extension was installed in local storage
    if (details.reason === 'install') {
        browser.storage.local.set({ [installTimeStorageKey]: Date.now() })
    }
    // Attempt convert of old extension data on extension update
    if (details.reason === 'update') {
        const storage = await browser.storage.local.get(dataConvertTimeKey)
        if (!storage[dataConvertTimeKey]) {
            await convertOldData({ setAsStubs: false, concurrency: 15 })
            await browser.storage.local.set({ [dataConvertTimeKey]: Date.now() })
        }
    }
})
<commit_msg>Fix up local storage access + conditional freeze-dry<commit_after>import tldjs from 'tldjs'
import { dataURLToBlob } from 'blob-util'

import 'src/activity-logger/background'
import 'src/scheduled-tasks/background'
import 'src/blacklist/background'
import 'src/omnibar'
import { installTimeStorageKey } from 'src/imports/background'
import convertOldData from 'src/util/old-data-converter'
import fetchPageData from 'src/page-analysis/background/fetch-page-data'
import { findPagesByUrl } from 'src/search/find-pages'
import { transformToBookmarkDoc } from 'src/imports/background/imports-preparation'
import { generatePageDocId } from 'src/page-storage'
import { FREEZE_DRY_BOOKMARKS_KEY } from 'src/options/preferences/constants'
import db from 'src/pouchdb'

export const dataConvertTimeKey = 'data-conversion-timestamp'

export async function bookmarkStorageListener(id, bookmarkInfo) {
    const getAttachments = async pageData => {
        const favIconBlob = await dataURLToBlob(pageData.favIconURI)

        let _attachments = {
            'fav-icon-blob': {
                content_type: favIconBlob.type,
                data: favIconBlob,
            },
        }

        if (pageData.freezeDryHTML) {
            const freezeDryBlob = new Blob([pageData.freezeDryHTML], {type: 'text/html;charset=UTF-8'})

            _attachments = {
                ..._attachments,
                'freeze-dry-blob': {
                    content_type: freezeDryBlob.type,
                    data: freezeDryBlob,
                },
            }
        }

        return _attachments
    }

    const samePageCandidates = (await findPagesByUrl({ url: bookmarkInfo.url })).rows.map(row => row.doc)

    if (samePageCandidates.length) {
        const pageDoc = samePageCandidates[samePageCandidates.length - 1]
        const bookmarkDoc = await transformToBookmarkDoc(pageDoc)(bookmarkInfo)
        return db.bulkDocs([bookmarkDoc, pageDoc])
    }

    let pageDoc = {
        url: bookmarkInfo.url,
        title: bookmarkInfo.title,
        _id: generatePageDocId(bookmarkInfo.dateAdded, id),
    }

    try {
        const { [FREEZE_DRY_BOOKMARKS_KEY]: includeFreezeDry = false } = await browser.storage.local.get(FREEZE_DRY_BOOKMARKS_KEY)

        const fetchPageDataOptions = {
            includePageContent: true,
            includeFavIcon: true,
            includeFreezeDry,
        }
        const pageData = await fetchPageData({ url: bookmarkInfo.url, opts: fetchPageDataOptions })
        pageDoc = {
            ...pageDoc,
            _attachments: await getAttachments(pageData),
            content: pageData.content,
        }
    } catch (err) {
        console.error("Error occurred while fetching page data: " + err.toString())
    } finally {
        const bookmarkDoc = await transformToBookmarkDoc(pageDoc)(bookmarkInfo)
        db.bulkDocs([bookmarkDoc, pageDoc])
    }
}

async function openOverview() {
    const [ currentTab ] = await browser.tabs.query({ active: true })
    if (currentTab && currentTab.url) {
        const validUrl = tldjs.isValid(currentTab.url)
        if (validUrl) {
            return browser.tabs.create({
                url: '/overview/overview.html',
            })
        }
    }

    browser.tabs.update({
        url: '/overview/overview.html',
    })
}

// Open the overview when the extension's button is clicked
browser.browserAction.onClicked.addListener(() => {
    openOverview()
})

browser.bookmarks.onCreated.addListener(bookmarkStorageListener)

browser.commands.onCommand.addListener(command => {
    if (command === 'openOverview') {
        openOverview()
    }
})

browser.runtime.onInstalled.addListener(async details => {
    // Store the timestamp of when the extension was installed in local storage
    if (details.reason === 'install') {
        browser.storage.local.set({ [installTimeStorageKey]: Date.now() })
    }
    // Attempt convert of old extension data on extension update
    if (details.reason === 'update') {
        const storage = await browser.storage.local.get(dataConvertTimeKey)
        if (!storage[dataConvertTimeKey]) {
            await convertOldData({ setAsStubs: false, concurrency: 15 })
            await browser.storage.local.set({ [dataConvertTimeKey]: Date.now() })
        }
    }
})
<|endoftext|>