<commit_before>$(document).ready(function() {
    $("#file").change(function() {
        $("#fileName").text(new Option($('input[type=file]')[0].files[0].name).innerHTML);
    });

    $('.table').bootstrapTable({
      onClickRow: function (row, $element) {
        window.location.href = "../application_state?applicationId=" + row.id;
      }
  });
});

function CandidateCreateModel(){
    var self = this;

    ko.bindingHandlers.valueWithInit = {
        init: function(element, valueAccessor, allBindingsAccessor, data) {
            var property = valueAccessor(),
                value = element.value;

            //create the observable, if it doesn't exist
            if (!ko.isWriteableObservable(data[property])) {
                data[property] = ko.observable();
            }

            data[property](value);

            ko.applyBindingsToNode(element, { value: data[property] });
        }
    };

    ko.bindingHandlers.initDisplay = {
        init: function(element, valueAccessor, allBindingsAccessor, data) {
            self.modify(true);
        }
    };

    function sendCandidateWithAjax(url, method) {
        return $.ajax({
                   url: url,
                   method: method,
                   contentType: 'application/json',
                   dataType: "json",
                   data: JSON.stringify({
                       id: self.id(),
                       name: self.name(),
                       referer: self.referer(),
                       email: self.email(),
                       languageSkill: self.languageSkill(),
                       phone: self.phone(),
                       description: self.description(),
                       cvFilename: self.cvFilename()
                   })
               });
    }

    function sendFileWithAjax(url, formData) {
        return $.ajax({
                   url: url,
                   data: formData,
                   type: 'POST',
                   contentType: false,
                   processData: false,
               });
    }

    self.ajaxCall = function() {
        var candidateValidationUrl = '/atsy/secure/candidate/validate';
        var candidateUrl = '/atsy/secure/candidate';
        var fileValidationUrl = '/atsy/secure/fileUpload/validate';
        var fileUploadUrl = '/atsy/secure/fileUpload/candidate/';

        var form = $("#candidate-create-form");
        var formData = new FormData();

        if(($('input[type=file]'))[0] != undefined) {
            formData.append('file', $('input[type=file]')[0].files[0]);
        }

        // Send candidate to validate
        sendCandidateWithAjax(candidateValidationUrl, form.attr('method')).done(function (xhr) {
            // If candidate is valid, then hide the error msg
            self.showError(false);
            if (($('input[type=file]')[0] === undefined) || ($('input[type=file]').val() === '')) {
                // Send candidate to save
                sendCandidateWithAjax(candidateUrl, form.attr('method')).done(function (xhr) {
                    // If there is no error with candidate, then hide the error msg
                    self.showError(false);
                    window.location = form.attr('action')+ '/' + xhr.id;
                    // If there is error with candidate, then show the error msg
                }).error(function (xhr) {
                    self.candidateErrorResponse(xhr.responseJSON);
                    self.showError(true);
                });
             // If the file exists
            } else {
                // If file exists, then send file to validate
                sendFileWithAjax(fileValidationUrl, formData).done(function (xhr) {
                    // If file is valid, then hide the error msg
                    self.showFileError(false);
                    // Send candidate to save or update
                    sendCandidateWithAjax(candidateUrl, form.attr('method')).done(function (xhr) {
                        // If there is no error with candidate, then hide the error msg
                        self.showError(false);
                        // Send file to save
                        sendFileWithAjax(fileUploadUrl + xhr.id, formData).done(function (xhr) {
                            // If there is no error with file, then hide error msg
                            self.showFileError(false);
                            // If candidate and file are corrects
                            window.location = form.attr('action')+ '/' + xhr.id;
                        }).error(function (xhr) {
                            // If there is error with file, then show the error msg
                            self.fileErrorResponse(xhr.responseJSON);
                            self.showFileError(true);
                        });
                    // If there is error with candidate, then show the error msg
                    }).error(function (xhr) {
                        self.candidateErrorResponse(xhr.responseJSON);
                        self.showError(true);
                    });
                // If file is not valid, then show the error msg
                }).error(function (xhr) {
                    self.fileErrorResponse(xhr.responseJSON);
                    self.showFileError(true);
                });
            }
        // If candidate is not valid, then show error msg
        }).error(function (xhr) {
            self.candidateErrorResponse(xhr.responseJSON);
            self.showError(true);
            // If the file exists
            if (($('input[type=file]')[0] != undefined) && ($('input[type=file]').val() != '')) {
                // Send file to save
                sendFileWithAjax(fileValidationUrl, formData).done(function (xhr) {
                    // If there is no error with file, then hide the error msg
                    self.showFileError(false);
                // If file is not valid, then show the error msg
                }).error(function (xhr) {
                    self.fileErrorResponse(xhr.responseJSON);
                    self.showFileError(true);
                });
            }
        });
    }

    self.candidateErrorResponse = ko.observable(null);
    self.fileErrorResponse = ko.observable(null);
    self.showError = ko.observable(false);
    self.showFileError = ko.observable(false);

    self.errorMessage = ko.pureComputed(function() {
      if (self.candidateErrorResponse() === null) {
        return ""
      }

      return self.candidateErrorResponse().errorMessage;
    });

    self.fileErrorMessage = ko.pureComputed(function() {
        if (self.fileErrorResponse() === null) {
            return "";
        }

        return self.fileErrorResponse().errorMessage;
    });

    self.fieldMessages = ko.pureComputed(function() {
        if (self.candidateErrorResponse() === null) {
          return [];
        }

        return Object.keys(self.candidateErrorResponse().fields).map(function(key) {
            return self.candidateErrorResponse().fields[key];
        });
    });

    self.modify = ko.observable(false);

    self.modify_display_true = function() {
        self.modify(true);
        self.showError(false);
        self.showFileError(false);
        $("#candidate-create-form").validator('destroy');
        candidateModel.id(savedModel.id);
        candidateModel.name(savedModel.name);
        candidateModel.referer(savedModel.referer);
        candidateModel.email(savedModel.email);
        candidateModel.languageSkill(savedModel.languageSkill);
        candidateModel.phone(savedModel.phone);
        $("#fileName").text('');
    };

    self.modify_display_false = function() {
        self.modify(false);
        savedModel = ko.toJS(candidateModel);
    };

     $("#downloadLink").on('click', function (event) {
         var url = $(this).data('file');

         event.preventDefault();
         event.stopPropagation();

         $.ajax({
             url: url,
             type: 'GET'
         }).done(function (xhr) {
            var downloadUrl = "/atsy/secure/fileDownload/" + xhr.id;
            window.location = downloadUrl;
         }).error(function (xhr) {
             self.fileErrorResponse(xhr.responseJSON);
             self.showFileError(true);
         });
     });
}

var savedModel;

var candidateModel = new CandidateCreateModel();

$('#candidate-create-form').validator().on('submit', function (e) {
  if (e.isDefaultPrevented()) {
    // handle the invalid form...
  } else {
    candidateModel.ajaxCall();
    return false;
  }
});

ko.applyBindings(candidateModel);

function creationDateFormatter(value, row, index) {
    var dateTime = new Date(row.creationDate);
    return dateTimeFormatter(dateTime);
}

function modificationDateFormatter(value, row, index) {
    var dateTime = new Date(row.modificationDate);
    return dateTimeFormatter(dateTime);
}

function dateTimeFormatter(dateTime) {
    var options = {year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric'};
    return dateTime.toLocaleDateString('hu-HU', options);
}

function actionFormatter(value, row, index) {
    return [
        '',
        '',
        '',
    ].join('');
}

window.channelsEvents = {
    'click .remove': function (e, value, row) {
         var container = $('#applications_table').parent();
         var options = getOptions('question.delete.application.js', 'selected.element.not.found', row, container, '../../applications');
         e.stopImmediatePropagation();
         bootbox.dialog(options);
    }
};
<commit_msg>Fixed opening of application state page.<commit_after>$('.table#applications_table').bootstrapTable({
  onClickRow: function (row, $element) {
    window.location.href = "../../application_state?applicationId=" + row.id;
  }
});

$(document).ready(function() {
    $("#file").change(function() {
        $("#fileName").text(new Option($('input[type=file]')[0].files[0].name).innerHTML);
    });

});

function CandidateCreateModel(){
    var self = this;

    ko.bindingHandlers.valueWithInit = {
        init: function(element, valueAccessor, allBindingsAccessor, data) {
            var property = valueAccessor(),
                value = element.value;

            //create the observable, if it doesn't exist
            if (!ko.isWriteableObservable(data[property])) {
                data[property] = ko.observable();
            }

            data[property](value);

            ko.applyBindingsToNode(element, { value: data[property] });
        }
    };

    ko.bindingHandlers.initDisplay = {
        init: function(element, valueAccessor, allBindingsAccessor, data) {
            self.modify(true);
        }
    };

    function sendCandidateWithAjax(url, method) {
        return $.ajax({
                   url: url,
                   method: method,
                   contentType: 'application/json',
                   dataType: "json",
                   data: JSON.stringify({
                       id: self.id(),
                       name: self.name(),
                       referer: self.referer(),
                       email: self.email(),
                       languageSkill: self.languageSkill(),
                       phone: self.phone(),
                       description: self.description(),
                       cvFilename: self.cvFilename()
                   })
               });
    }

    function sendFileWithAjax(url, formData) {
        return $.ajax({
                   url: url,
                   data: formData,
                   type: 'POST',
                   contentType: false,
                   processData: false,
               });
    }

    self.ajaxCall = function() {
        var candidateValidationUrl = '/atsy/secure/candidate/validate';
        var candidateUrl = '/atsy/secure/candidate';
        var fileValidationUrl = '/atsy/secure/fileUpload/validate';
        var fileUploadUrl = '/atsy/secure/fileUpload/candidate/';

        var form = $("#candidate-create-form");
        var formData = new FormData();

        if(($('input[type=file]'))[0] != undefined) {
            formData.append('file', $('input[type=file]')[0].files[0]);
        }

        // Send candidate to validate
        sendCandidateWithAjax(candidateValidationUrl, form.attr('method')).done(function (xhr) {
            // If candidate is valid, then hide the error msg
            self.showError(false);
            if (($('input[type=file]')[0] === undefined) || ($('input[type=file]').val() === '')) {
                // Send candidate to save
                sendCandidateWithAjax(candidateUrl, form.attr('method')).done(function (xhr) {
                    // If there is no error with candidate, then hide the error msg
                    self.showError(false);
                    window.location = form.attr('action')+ '/' + xhr.id;
                    // If there is error with candidate, then show the error msg
                }).error(function (xhr) {
                    self.candidateErrorResponse(xhr.responseJSON);
                    self.showError(true);
                });
             // If the file exists
            } else {
                // If file exists, then send file to validate
                sendFileWithAjax(fileValidationUrl, formData).done(function (xhr) {
                    // If file is valid, then hide the error msg
                    self.showFileError(false);
                    // Send candidate to save or update
                    sendCandidateWithAjax(candidateUrl, form.attr('method')).done(function (xhr) {
                        // If there is no error with candidate, then hide the error msg
                        self.showError(false);
                        // Send file to save
                        sendFileWithAjax(fileUploadUrl + xhr.id, formData).done(function (xhr) {
                            // If there is no error with file, then hide error msg
                            self.showFileError(false);
                            // If candidate and file are corrects
                            window.location = form.attr('action')+ '/' + xhr.id;
                        }).error(function (xhr) {
                            // If there is error with file, then show the error msg
                            self.fileErrorResponse(xhr.responseJSON);
                            self.showFileError(true);
                        });
                    // If there is error with candidate, then show the error msg
                    }).error(function (xhr) {
                        self.candidateErrorResponse(xhr.responseJSON);
                        self.showError(true);
                    });
                // If file is not valid, then show the error msg
                }).error(function (xhr) {
                    self.fileErrorResponse(xhr.responseJSON);
                    self.showFileError(true);
                });
            }
        // If candidate is not valid, then show error msg
        }).error(function (xhr) {
            self.candidateErrorResponse(xhr.responseJSON);
            self.showError(true);
            // If the file exists
            if (($('input[type=file]')[0] != undefined) && ($('input[type=file]').val() != '')) {
                // Send file to save
                sendFileWithAjax(fileValidationUrl, formData).done(function (xhr) {
                    // If there is no error with file, then hide the error msg
                    self.showFileError(false);
                // If file is not valid, then show the error msg
                }).error(function (xhr) {
                    self.fileErrorResponse(xhr.responseJSON);
                    self.showFileError(true);
                });
            }
        });
    }

    self.candidateErrorResponse = ko.observable(null);
    self.fileErrorResponse = ko.observable(null);
    self.showError = ko.observable(false);
    self.showFileError = ko.observable(false);

    self.errorMessage = ko.pureComputed(function() {
      if (self.candidateErrorResponse() === null) {
        return ""
      }

      return self.candidateErrorResponse().errorMessage;
    });

    self.fileErrorMessage = ko.pureComputed(function() {
        if (self.fileErrorResponse() === null) {
            return "";
        }

        return self.fileErrorResponse().errorMessage;
    });

    self.fieldMessages = ko.pureComputed(function() {
        if (self.candidateErrorResponse() === null) {
          return [];
        }

        return Object.keys(self.candidateErrorResponse().fields).map(function(key) {
            return self.candidateErrorResponse().fields[key];
        });
    });

    self.modify = ko.observable(false);

    self.modify_display_true = function() {
        self.modify(true);
        self.showError(false);
        self.showFileError(false);
        $("#candidate-create-form").validator('destroy');
        candidateModel.id(savedModel.id);
        candidateModel.name(savedModel.name);
        candidateModel.referer(savedModel.referer);
        candidateModel.email(savedModel.email);
        candidateModel.languageSkill(savedModel.languageSkill);
        candidateModel.phone(savedModel.phone);
        $("#fileName").text('');
    };

    self.modify_display_false = function() {
        self.modify(false);
        savedModel = ko.toJS(candidateModel);
    };

     $("#downloadLink").on('click', function (event) {
         var url = $(this).data('file');

         event.preventDefault();
         event.stopPropagation();

         $.ajax({
             url: url,
             type: 'GET'
         }).done(function (xhr) {
            var downloadUrl = "/atsy/secure/fileDownload/" + xhr.id;
            window.location = downloadUrl;
         }).error(function (xhr) {
             self.fileErrorResponse(xhr.responseJSON);
             self.showFileError(true);
         });
     });
}

var savedModel;

var candidateModel = new CandidateCreateModel();

$('#candidate-create-form').validator().on('submit', function (e) {
  if (e.isDefaultPrevented()) {
    // handle the invalid form...
  } else {
    candidateModel.ajaxCall();
    return false;
  }
});

ko.applyBindings(candidateModel);

function creationDateFormatter(value, row, index) {
    var dateTime = new Date(row.creationDate);
    return dateTimeFormatter(dateTime);
}

function modificationDateFormatter(value, row, index) {
    var dateTime = new Date(row.modificationDate);
    return dateTimeFormatter(dateTime);
}

function dateTimeFormatter(dateTime) {
    var options = {year: 'numeric', month: 'numeric', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric'};
    return dateTime.toLocaleDateString('hu-HU', options);
}

function actionFormatter(value, row, index) {
    return [
        '',
        '',
        '',
    ].join('');
}

window.channelsEvents = {
    'click .remove': function (e, value, row) {
         var container = $('#applications_table').parent();
         var options = getOptions('question.delete.application.js', 'selected.element.not.found', row, container, '../../applications');
         e.stopImmediatePropagation();
         bootbox.dialog(options);
    }
};
<|endoftext|>


<commit_before>import { Component, EventEmitter } from '@angular/core';
import { COMMON_DIRECTIVES, NgModel } from '@angular/common';

import { BaseInput } from './../FormExtras';
import { NOVO_PICKER_ELEMENTS } from './../../../picker';
import { NovoLabelService } from './../../../../novo-elements';

@Component({
    selector: 'picker-input',
    inputs: [
        'name',
        'placeholder',
        'options',
        'required'
    ],
    outputs: ['inputState'],
    directives: [COMMON_DIRECTIVES, NOVO_PICKER_ELEMENTS, NgModel],
    template: `

        <novo-picker [config]="options" [(ngModel)]="value" [placeholder]="placeholder" (select)="onSelect($event)" (blur)="toggleInactive($event)" (focus)="toggleInactive($event)"></novo-picker>

        {{labels.required}}
    `
})
export class PickerInput extends BaseInput {
    inactive:Boolean = false;
    inputState:EventEmitter = new EventEmitter();

    constructor(labels:NovoLabelService) {
        super();
        this.labels = labels;
    }

    ngOnInit() {
        super.ngOnInit();
        if (this.value && this.value instanceof Object) {
            this.value = this.value.label || this.value.name || this.value.title || this.value.id;
        }
        this.control.updateValue(this.value);
        setTimeout(() => {
            this.toggleInactive(null);
        }, 10);
    }

    onSelect(value) {
        this.update.emit(value);
        this.control.updateValue(value);
        this.toggleInactive(value);
    }

    toggleInactive(ev) {
        setTimeout(() => {
            if (ev) {
                if (ev.type === 'focus' || this.value || this.placeholder) this.inactive = false;
                else this.inactive = true;
            } else {
                if (this.value || this.placeholder) this.inactive = false;
                else this.inactive = true;
            }

            this.inputState.emit({
                value: this.inactive
            });
        });
    }
}
<commit_msg>refactor(Picker): Added the ability to filter out events (#136)<commit_after>import { Component, EventEmitter } from '@angular/core';
import { COMMON_DIRECTIVES, NgModel } from '@angular/common';

import { BaseInput } from './../FormExtras';
import { NOVO_PICKER_ELEMENTS } from './../../../picker';
import { NovoLabelService } from './../../../../novo-elements';

@Component({
    selector: 'picker-input',
    inputs: [
        'name',
        'placeholder',
        'options',
        'required'
    ],
    outputs: ['inputState'],
    directives: [COMMON_DIRECTIVES, NOVO_PICKER_ELEMENTS, NgModel],
    template: `

        <novo-picker [config]="options" [(ngModel)]="value" [placeholder]="placeholder" (select)="onSelect($event)" (blur)="toggleInactive($event)" (focus)="toggleInactive($event)"></novo-picker>

        {{labels.required}}
    `
})
export class PickerInput extends BaseInput {
    inactive:Boolean = false;
    inputState:EventEmitter = new EventEmitter();

    constructor(labels:NovoLabelService) {
        super();
        this.labels = labels;
    }

    ngOnInit() {
        super.ngOnInit();
        if (this.value && this.value instanceof Object) {
            this.value = this.value.label || this.value.name || this.value.title || this.value.id;
        }
        this.control.updateValue(this.value);
        setTimeout(() => {
            this.toggleInactive(null);
        }, 10);
    }

    onSelect(value) {
        if (value instanceof Event) {
            this.update.emit(null);
            this.control.updateValue(null);
            this.toggleInactive(null);
        } else {
            this.update.emit(value);
            this.control.updateValue(value);
            this.toggleInactive(value);
        }
    }

    toggleInactive(ev) {
        setTimeout(() => {
            if (ev) {
                if (ev.type === 'focus' || this.value || this.placeholder) this.inactive = false;
                else this.inactive = true;
            } else {
                if (this.value || this.placeholder) this.inactive = false;
                else this.inactive = true;
            }

            this.inputState.emit({
                value: this.inactive
            });
        });
    }
}
<|endoftext|>


<commit_before>function DateTimeInput(input) {
    this.input = input;
    this.cursor_pos = function(evt) {
        var input = this.input;
        if (!this.x_pos) this.x_pos = $(input).offset().left;
        var input_style;
        try {
            input_style = getComputedStyle(input, '');
        } catch(e) {
            input_style = input.currentStyle;
        }
        if (input_style == undefined) input_style = {};

        var padding = input_style.paddingLeft;
        if (/^(\d+)(?:px)?$/.test(padding)) padding = new Number(RegExp.$1);
        else padding = 0;
        var border = input_style.borderLeftWidth;
        if (/^(\d+)(?:px)?$/.test(border )) border  = new Number(RegExp.$1);
        else border = 0;

        var x = evt.clientX - this.x_pos - padding - border;

        var $tempspan = $('#datetime-temp');
        if ($tempspan.length == 0) $tempspan = $('').css({
            position: 'absolute',
            top: '-100px'
        });
        for (var property in input_style) {
            if (property.substr(0, 4) == 'font') {
                $tempspan.css(property, input_style[property]);
            }
        }
        $tempspan.insertAfter($(input));

        $tempspan.text('m');
        var dotwidth = -$tempspan.width();
        $tempspan.text('m.');
        dotwidth += $tempspan.width();
        $tempspan.text( $(input).val() + '.' );

        var text, last = '';
        while ($tempspan.width() - dotwidth >= x) {
            text = $tempspan.text();
            if (text == '.') break;
            text = text.substr(0,text.length-1);
            last = text.substr(text.length-1);
            $tempspan.text(
                text.substr(0, text.length-1) + '.'
            );
        }
        text = $tempspan.text();
        text = text.substr(0, text.length-1) + last;
        return text.length;
    };
    this.set_date = function(d, preserve) {
        var fields = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})/.exec( $(this.input).val() );
        var year, month, day, hour, minute, dow;
        if (!fields) preserve = {};
        else {
            year   = fields[1];
            month  = fields[2];
            day    = fields[3];
            hour   = fields[4];
            minute = fields[5];
            month = new Number(month) - 1;
        }
        if (!preserve) preserve = { };

        if (preserve.year  ) d.setFullYear(year  );
        if (preserve.month ) d.setMonth   (month );
        if (preserve.day   ) d.setDate    (day   );
        if (preserve.hour  ) d.setHours   (hour  );
        if (preserve.minute) d.setMinutes (minute);

        year = d.getFullYear();
        month = new Number(d.getMonth()) + 1;
        day = d.getDate();
        hour = d.getHours();
        minute = d.getMinutes();
        dow = ([
            gettext('Su'), gettext('Mo'), gettext('Tu'), gettext('We'), gettext('Th'), gettext('Fr'), gettext('Sa')
        ])[ d.getDay() ];

        function pad(str,n) {
            var s = new String(str);
            while (s.length < n) s = '0'+s;
            return s;
        }

        var nval = ''
        + pad(  year,4) + '-'
        + pad( month,2) + '-'
        + pad(   day,2) + ' '
        + pad(  hour,2) + ':'
        + pad(minute,2) + ' '
        + dow;
        $(this.input).val( nval ).change();
    };
    this.scroll = function(pos, delta) {
        var input = this.input;
        var fields = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})/.exec( $(input).val() );
        if (!fields) {
            carp('Invalid date:', $(input).val());
            return;
        }

        var i = ([
            undefined,
            1,1,1,1,
            undefined,
            2,2,
            undefined,
            3,3,
            undefined,
            4,4,
            undefined,
            5,5,
            undefined,
            3,3
        ])[pos];
        if (i == undefined) return;
        fields[i] = new Number(fields[i]) + delta;

        var year   = fields[1];
        var month  = fields[2];
        var day    = fields[3];
        var hour   = fields[4];
        var minute = fields[5];
        month = new Number(month) - 1;

        var d = new Date();
        d.setFullYear(year);
        d.setMonth(month);
        d.setDate(day);
        d.setHours(hour);
        d.setMinutes(minute);
        d.setSeconds(0);
        d.setMilliseconds(0);

        this.set_date(d);

        input.selectionStart = input.selectionEnd = pos;
    };
}

function DateInput(input) {
    this.input = input;
    this.cursor_pos = function(evt) {
        var input = this.input;
        if (!this.x_pos) this.x_pos = $(input).offset().left;
        var input_style;
        try {
            input_style = getComputedStyle(input, '');
        } catch(e) {
            input_style = input.currentStyle;
        }
        if (input_style == undefined) input_style = {};

        var padding = input_style.paddingLeft;
        if (/^(\d+)(?:px)?$/.test(padding)) padding = new Number(RegExp.$1);
        else padding = 0;
        var border = input_style.borderLeftWidth;
        if (/^(\d+)(?:px)?$/.test(border )) border  = new Number(RegExp.$1);
        else border = 0;

        var x = evt.clientX - this.x_pos - padding - border;

        var $tempspan = $('#datetime-temp');
        if ($tempspan.length == 0) $tempspan = $('').css({
            position: 'absolute',
            top: '-100px'
        });
        for (var property in input_style) {
            if (property.substr(0, 4) == 'font') {
                $tempspan.css(property, input_style[property]);
            }
        }
        $tempspan.insertAfter($(input));

        $tempspan.text('m');
        var dotwidth = -$tempspan.width();
        $tempspan.text('m.');
        dotwidth += $tempspan.width();
        $tempspan.text( $(input).val() + '.' );

        var text, last = '';
        while ($tempspan.width() - dotwidth >= x) {
            text = $tempspan.text();
            if (text == '.') break;
            text = text.substr(0,text.length-1);
            last = text.substr(text.length-1);
            $tempspan.text(
                text.substr(0, text.length-1) + '.'
            );
        }
        text = $tempspan.text();
        text = text.substr(0, text.length-1) + last;
        return text.length;
    };
    this.set_date = function(d, preserve) {
        var fields = /^(\d{4})-(\d{2})-(\d{2})/.exec( $(this.input).val() );
        var year, month, day,  dow;
        if (!fields) preserve = {};
        else {
            year   = fields[1];
            month  = fields[2];
            day    = fields[3];
            month = new Number(month) - 1;
        }
        if (!preserve) preserve = { };

        if (preserve.year ) d.setFullYear(year );
        if (preserve.month) d.setMonth   (month);
        if (preserve.day  ) d.setDate    (day  );

        year = d.getFullYear();
        month = new Number(d.getMonth()) + 1;
        day = d.getDate();
        dow = ([
            gettext('Su'), gettext('Mo'), gettext('Tu'), gettext('We'), gettext('Th'), gettext('Fr'), gettext('Sa')
        ])[ d.getDay() ];

        function pad(str,n) {
            var s = new String(str);
            while (s.length < n) s = '0'+s;
            return s;
        }

        var nval = ''
        + pad(  year,4) + '-'
        + pad( month,2) + '-'
        + pad(   day,2) + ' '
        + dow;
        $(this.input).val( nval ).change();
    };
    this.scroll = function(pos, delta) {
        var input = this.input;
        var fields = /^(\d{4})-(\d{2})-(\d{2})/.exec( $(input).val() );
        if (!fields) {
            carp('Invalid date:', $(input).val());
            return;
        }

        var i = ([
            undefined,
            1,1,1,1,
            undefined,
            2,2,
            undefined,
            3,3,
            undefined,
            3,3
        ])[pos];
        if (i == undefined) return;
        fields[i] = new Number(fields[i]) + delta;

        var year   = fields[1];
        var month  = fields[2];
        var day    = fields[3];
        month = new Number(month) - 1;

        var d = new Date();
        d.setFullYear(year);
        d.setMonth(month);
        d.setDate(day);
        d.setHours(0);
        d.setMinutes(0);
        d.setSeconds(0);
        d.setMilliseconds(0);

        this.set_date(d);

        input.selectionStart = input.selectionEnd = pos;
    };
}

(function($) {
    $('span.dtpicker-trigger').live('click', function() {
        var $dtp = $('.datetimepicker');
        var x = $(this).offset().left + $(this).width();
        var y = $(this).offset().top;
        var $input = $(this).data('input');

        // check if Y doesn't reach below the current screen height
        var d = y + $dtp.outerHeight()  -  $('body').outerHeight();
        if (d > 0) y -= d;
        if (y < 0) y = 0;   // But rather reach below bottom than above top

        $('.datetimepicker').css({
            top : y + 'px',
            left: x + 'px'
        }).toggle().data( 'input', $input );
    });

    function datetime_init() {
        $('.vDateTimeInput,.vDateInput').each( function() {
            var $input = $(this);
            var is_datetime = $input.hasClass('vDateTimeInput');
            if (! $input.data('dti')) {
                if (is_datetime) {
                    $input.data('dti', new DateTimeInput(this));
                }
                else {
                    $input.data('dti', new DateInput(this));
                }

                $(  ''
                )
                .data('input', $input)
                .insertAfter(this);

                $input.keydown(function(evt) {
                    var delta = 0;
                    if (evt.keyCode == 38) delta =  1;
                    if (evt.keyCode == 40) delta = -1;
                    if (!delta) return true;
                    var pos = this.selectionEnd;
                    $input.data('dti').scroll(pos, delta);
                    evt.preventDefault();
                });
            }
        });
    }
    datetime_init();

    var timepicker_html;
    function media_dependent_datetime_init(evt) {

        if ( ! timepicker_html ) {
            var args = arguments; args._this = this;
            get_html_chunk('timepicker', function(data) {
                timepicker_html = data;
                args.callee.apply( args._this, args );
            });
            return;
        }

        // create the datetimepicker div
        if ($('.datetimepicker').length) { }    // but only if there is none yet
        else if (
               evt.type == 'content_added'  // and we added something that uses a datepicker
            && $(evt.target).find('.dtpicker-trigger').length == 0    // if anything
        ) { }
        else {
            // Container creation
            var $dtpicker = $('
');

            // Date picker
            var $datepicker = $('
');
            $datepicker.datepicker(new DATEPICKER_OPTIONS({
                onSelect: function(dtext, dpick) {
                    var $dtpicker = $(this).closest('.datetimepicker');
                    var dti = $( $dtpicker.data('input') ).data('dti');
                    var d = new Date();
                    d.setFullYear(dpick.selectedYear);
                    d.setMonth(dpick.selectedMonth);
                    d.setDate(dpick.selectedDay);
                    d.setHours(0);
                    d.setMinutes(0);
                    d.setSeconds(0);
                    d.setMilliseconds(0);
                    dti.set_date(d, {/*preserve*/hour:true,minute:true});
                },
                onClose: function() {
                    $(this).closest('.datetimepicker').hide();
                }
            }));
            $datepicker.appendTo($dtpicker);

            // Time picker
            var $timepicker = $('
')
            .html(timepicker_html).appendTo($dtpicker);

            // Container placement
            $dtpicker.appendTo(
                   $('.change-form').get(0)
                || $('#content').get(0)
                || $('body').get(0)
            );
        }

        // mousewheel datetime scrolling
        function mousewheel_handler(evt, delta) {
            var dti = $(this).data('dti');
            var pos = dti.cursor_pos(evt);
            dti.scroll(pos, delta / Math.abs(delta||1));
            evt.preventDefault();
        };
        if (DEBUG)  // FIXME: mousewheel scrolling broken!
        $('.vDateTimeInput,.vDateInput').not('.mwheel-enhanced').focus( function() {
            $(this)  .bind('mousewheel', mousewheel_handler);
        }).blur( function() {
            $(this).unbind('mousewheel', mousewheel_handler);
        }).addClass('mwheel-enhanced');
    }

    $('.js-dtpicker-close').live('click', function(evt) {
        if (evt.button != 0) return;
        $(this).closest('.datetimepicker').hide();
    });
    $('.js-timepick').live('click', function(evt) {
        if (evt.button != 0) return;
        var dti = $( $(this).closest('.datetimepicker').data('input') ).data('dti');
        var selected_time = /js-time-(\d\d)(\d\d)/.exec(this.className);
        var d = new Date();
        d.setSeconds(0);
        d.setMilliseconds(0);
        if ( ! selected_time ) {
            if ( ! $(this).hasClass('js-time-now') ) return;
        }
        else {
            var selected_hours   = selected_time[1];
            var selected_minutes = selected_time[2];
            d.setHours  (selected_hours  );
            d.setMinutes(selected_minutes);
            // let default date be the following 24 hours
            if (d.getTime() < new Date().getTime()) {
                d.setDate( d.getDate() + 1 );
            }
        }
        dti.set_date(d, {/*preserve*/year:true,month:true,day:true});
    });

    $( document ).bind('content_added', datetime_init);
    $( document ).bind('content_added', media_dependent_datetime_init);
    $( document ).one ('media_loaded' , media_dependent_datetime_init);

    // Close the datetimepicker when something else is clicked
    $('body').live('click', function(evt) {
        // ignore clicking on the datepicker triggering icon
        if ($(evt.target).closest('.dtpicker-trigger').length) return true;
        // ignore clicking on the datepicker itself
        if ($(evt.target).closest('.datetimepicker').length)   return true;
        // if there's no datepicker shown, don't attempt to hide it
        if ($('.datetimepicker').not(':hidden').length == 0)   return true;
        // all else failed, hide all present datepickers
        $('.datetimepicker').hide();
        // and let the click be processed as usual
        return true;
    });

})(jQuery);
<commit_msg>Date[Time]Input mousewheel scrolling works in Chrome. Refs #2776.<commit_after>function DateTimeInput(input) {
    this.input = input;
    this.cursor_pos = function(evt) {
        var input = this.input;
        if (!this.x_pos) this.x_pos = $(input).offset().left;
        var input_style;
        try {
            input_style = getComputedStyle(input, '');
        } catch(e) {
            input_style = input.currentStyle;
        }
        if (input_style == undefined) input_style = {};

        var padding = input_style.paddingLeft || input_style['padding-left'];
        if (/^(\d+)(?:px)?$/.test(padding)) padding = new Number(RegExp.$1);
        else padding = 0;
        var border = input_style.borderLeftWidth || input_style['border-left-width'];
        if (/^(\d+)(?:px)?$/.test(border )) border  = new Number(RegExp.$1);
        else border = 0;

        var x = evt.clientX - this.x_pos - padding - border;

        var $tempspan = $('#datetime-temp');
        if ($tempspan.length == 0) $tempspan = $('').css({
            position: 'absolute',
            top: '-100px'
        });
        for (var property in input_style) {

            if (property >= 0) property = input_style[ property ];  // XXX nasty Chrome hack

            if (property.substr(0, 4) == 'font') {
                $tempspan.css(property, input_style[property]);
            }
        }
        $tempspan.insertAfter($(input));

        $tempspan.text('m');
        var dotwidth = -$tempspan.width();
        $tempspan.text('m.');
        dotwidth += $tempspan.width();
        $tempspan.text( $(input).val() + '.' );

        var text, last = '';
        while ($tempspan.width() - dotwidth >= x) {
            text = $tempspan.text();
            if (text == '.') break;
            text = text.substr(0,text.length-1);
            last = text.substr(text.length-1);
            $tempspan.text(
                text.substr(0, text.length-1) + '.'
            );
        }
        text = $tempspan.text();
        text = text.substr(0, text.length-1) + last;
        return text.length;
    };
    this.set_date = function(d, preserve) {
        var fields = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})/.exec( $(this.input).val() );
        var year, month, day, hour, minute, dow;
        if (!fields) preserve = {};
        else {
            year   = fields[1];
            month  = fields[2];
            day    = fields[3];
            hour   = fields[4];
            minute = fields[5];
            month = new Number(month) - 1;
        }
        if (!preserve) preserve = { };

        if (preserve.year  ) d.setFullYear(year  );
        if (preserve.month ) d.setMonth   (month );
        if (preserve.day   ) d.setDate    (day   );
        if (preserve.hour  ) d.setHours   (hour  );
        if (preserve.minute) d.setMinutes (minute);

        year = d.getFullYear();
        month = new Number(d.getMonth()) + 1;
        day = d.getDate();
        hour = d.getHours();
        minute = d.getMinutes();
        dow = ([
            gettext('Su'), gettext('Mo'), gettext('Tu'), gettext('We'), gettext('Th'), gettext('Fr'), gettext('Sa')
        ])[ d.getDay() ];

        function pad(str,n) {
            var s = new String(str);
            while (s.length < n) s = '0'+s;
            return s;
        }

        var nval = ''
        + pad(  year,4) + '-'
        + pad( month,2) + '-'
        + pad(   day,2) + ' '
        + pad(  hour,2) + ':'
        + pad(minute,2) + ' '
        + dow;
        $(this.input).val( nval ).change();
    };
    this.scroll = function(pos, delta) {
        var input = this.input;
        var fields = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})/.exec( $(input).val() );
        if (!fields) {
            carp('Invalid date:', $(input).val());
            return;
        }

        var i = ([
            undefined,
            1,1,1,1,
            undefined,
            2,2,
            undefined,
            3,3,
            undefined,
            4,4,
            undefined,
            5,5,
            undefined,
            3,3
        ])[pos];
        if (i == undefined) return;
        fields[i] = new Number(fields[i]) + delta;

        var year   = fields[1];
        var month  = fields[2];
        var day    = fields[3];
        var hour   = fields[4];
        var minute = fields[5];
        month = new Number(month) - 1;

        var d = new Date();
        d.setFullYear(year);
        d.setMonth(month);
        d.setDate(day);
        d.setHours(hour);
        d.setMinutes(minute);
        d.setSeconds(0);
        d.setMilliseconds(0);

        this.set_date(d);

        input.selectionStart = input.selectionEnd = pos;
    };
}

function DateInput(input) {
    this.input = input;
    this.cursor_pos = function(evt) {
        var input = this.input;
        if (!this.x_pos) this.x_pos = $(input).offset().left;
        var input_style;
        try {
            input_style = getComputedStyle(input, '');
        } catch(e) {
            input_style = input.currentStyle;
        }
        if (input_style == undefined) input_style = {};

        var padding = input_style.paddingLeft || input_style['padding-left'];
        if (/^(\d+)(?:px)?$/.test(padding)) padding = new Number(RegExp.$1);
        else padding = 0;
        var border = input_style.borderLeftWidth || input_style['border-left-width'];
        if (/^(\d+)(?:px)?$/.test(border )) border  = new Number(RegExp.$1);
        else border = 0;

        var x = evt.clientX - this.x_pos - padding - border;

        var $tempspan = $('#datetime-temp');
        if ($tempspan.length == 0) $tempspan = $('').css({
            position: 'absolute',
            top: '-100px'
        });
        for (var property in input_style) {

            if (property >= 0) property = input_style[ property ];  // XXX nasty Chrome hack

            if (property.substr(0, 4) == 'font') {
                $tempspan.css(property, input_style[property]);
            }
        }
        $tempspan.insertAfter($(input));

        $tempspan.text('m');
        var dotwidth = -$tempspan.width();
        $tempspan.text('m.');
        dotwidth += $tempspan.width();
        $tempspan.text( $(input).val() + '.' );

        var text, last = '';
        while ($tempspan.width() - dotwidth >= x) {
            text = $tempspan.text();
            if (text == '.') break;
            text = text.substr(0,text.length-1);
            last = text.substr(text.length-1);
            $tempspan.text(
                text.substr(0, text.length-1) + '.'
            );
        }
        text = $tempspan.text();
        text = text.substr(0, text.length-1) + last;
        return text.length;
    };
    this.set_date = function(d, preserve) {
        var fields = /^(\d{4})-(\d{2})-(\d{2})/.exec( $(this.input).val() );
        var year, month, day,  dow;
        if (!fields) preserve = {};
        else {
            year   = fields[1];
            month  = fields[2];
            day    = fields[3];
            month = new Number(month) - 1;
        }
        if (!preserve) preserve = { };

        if (preserve.year ) d.setFullYear(year );
        if (preserve.month) d.setMonth   (month);
        if (preserve.day  ) d.setDate    (day  );

        year = d.getFullYear();
        month = new Number(d.getMonth()) + 1;
        day = d.getDate();
        dow = ([
            gettext('Su'), gettext('Mo'), gettext('Tu'), gettext('We'), gettext('Th'), gettext('Fr'), gettext('Sa')
        ])[ d.getDay() ];

        function pad(str,n) {
            var s = new String(str);
            while (s.length < n) s = '0'+s;
            return s;
        }

        var nval = ''
        + pad(  year,4) + '-'
        + pad( month,2) + '-'
        + pad(   day,2) + ' '
        + dow;
        $(this.input).val( nval ).change();
    };
    this.scroll = function(pos, delta) {
        var input = this.input;
        var fields = /^(\d{4})-(\d{2})-(\d{2})/.exec( $(input).val() );
        if (!fields) {
            carp('Invalid date:', $(input).val());
            return;
        }

        var i = ([
            undefined,
            1,1,1,1,
            undefined,
            2,2,
            undefined,
            3,3,
            undefined,
            3,3
        ])[pos];
        if (i == undefined) return;
        fields[i] = new Number(fields[i]) + delta;

        var year   = fields[1];
        var month  = fields[2];
        var day    = fields[3];
        month = new Number(month) - 1;

        var d = new Date();
        d.setFullYear(year);
        d.setMonth(month);
        d.setDate(day);
        d.setHours(0);
        d.setMinutes(0);
        d.setSeconds(0);
        d.setMilliseconds(0);

        this.set_date(d);

        input.selectionStart = input.selectionEnd = pos;
    };
}

(function($) {
    $('span.dtpicker-trigger').live('click', function() {
        var $dtp = $('.datetimepicker');
        var x = $(this).offset().left + $(this).width();
        var y = $(this).offset().top;
        var $input = $(this).data('input');

        // check if Y doesn't reach below the current screen height
        var d = y + $dtp.outerHeight()  -  $('body').outerHeight();
        if (d > 0) y -= d;
        if (y < 0) y = 0;   // But rather reach below bottom than above top

        $('.datetimepicker').css({
            top : y + 'px',
            left: x + 'px'
        }).toggle().data( 'input', $input );
    });

    function datetime_init() {
        $('.vDateTimeInput,.vDateInput').each( function() {
            var $input = $(this);
            var is_datetime = $input.hasClass('vDateTimeInput');
            if (! $input.data('dti')) {
                if (is_datetime) {
                    $input.data('dti', new DateTimeInput(this));
                }
                else {
                    $input.data('dti', new DateInput(this));
                }

                $(  ''
                )
                .data('input', $input)
                .insertAfter(this);

                $input.keydown(function(evt) {
                    var delta = 0;
                    if (evt.keyCode == 38) delta =  1;
                    if (evt.keyCode == 40) delta = -1;
                    if (!delta) return true;
                    var pos = this.selectionEnd;
                    $input.data('dti').scroll(pos, delta);
                    evt.preventDefault();
                });
            }
        });
    }
    datetime_init();

    var timepicker_html;
    function media_dependent_datetime_init(evt) {

        if ( ! timepicker_html ) {
            var args = arguments; args._this = this;
            get_html_chunk('timepicker', function(data) {
                timepicker_html = data;
                args.callee.apply( args._this, args );
            });
            return;
        }

        // create the datetimepicker div
        if ($('.datetimepicker').length) { }    // but only if there is none yet
        else if (
               evt.type == 'content_added'  // and we added something that uses a datepicker
            && $(evt.target).find('.dtpicker-trigger').length == 0    // if anything
        ) { }
        else {
            // Container creation
            var $dtpicker = $('
');

            // Date picker
            var $datepicker = $('
');
            $datepicker.datepicker(new DATEPICKER_OPTIONS({
                onSelect: function(dtext, dpick) {
                    var $dtpicker = $(this).closest('.datetimepicker');
                    var dti = $( $dtpicker.data('input') ).data('dti');
                    var d = new Date();
                    d.setFullYear(dpick.selectedYear);
                    d.setMonth(dpick.selectedMonth);
                    d.setDate(dpick.selectedDay);
                    d.setHours(0);
                    d.setMinutes(0);
                    d.setSeconds(0);
                    d.setMilliseconds(0);
                    dti.set_date(d, {/*preserve*/hour:true,minute:true});
                },
                onClose: function() {
                    $(this).closest('.datetimepicker').hide();
                }
            }));
            $datepicker.appendTo($dtpicker);

            // Time picker
            var $timepicker = $('
')
            .html(timepicker_html).appendTo($dtpicker);

            // Container placement
            $dtpicker.appendTo(
                   $('.change-form').get(0)
                || $('#content').get(0)
                || $('body').get(0)
            );
        }

        // mousewheel datetime scrolling
        function mousewheel_handler(evt, delta) {
            var dti = $(this).data('dti');
            var pos = dti.cursor_pos(evt);
            dti.scroll(pos, delta / Math.abs(delta||1));
            evt.preventDefault();
        };
        if (DEBUG)  // FIXME: mousewheel scrolling broken!
        $('.vDateTimeInput,.vDateInput').not('.mwheel-enhanced').focus( function() {
            $(this)  .bind('mousewheel', mousewheel_handler);
        }).blur( function() {
            $(this).unbind('mousewheel', mousewheel_handler);
        }).addClass('mwheel-enhanced');
    }

    $('.js-dtpicker-close').live('click', function(evt) {
        if (evt.button != 0) return;
        $(this).closest('.datetimepicker').hide();
    });
    $('.js-timepick').live('click', function(evt) {
        if (evt.button != 0) return;
        var dti = $( $(this).closest('.datetimepicker').data('input') ).data('dti');
        var selected_time = /js-time-(\d\d)(\d\d)/.exec(this.className);
        var d = new Date();
        d.setSeconds(0);
        d.setMilliseconds(0);
        if ( ! selected_time ) {
            if ( ! $(this).hasClass('js-time-now') ) return;
        }
        else {
            var selected_hours   = selected_time[1];
            var selected_minutes = selected_time[2];
            d.setHours  (selected_hours  );
            d.setMinutes(selected_minutes);
            // let default date be the following 24 hours
            if (d.getTime() < new Date().getTime()) {
                d.setDate( d.getDate() + 1 );
            }
        }
        dti.set_date(d, {/*preserve*/year:true,month:true,day:true});
    });

    $( document ).bind('content_added', datetime_init);
    $( document ).bind('content_added', media_dependent_datetime_init);
    $( document ).one ('media_loaded' , media_dependent_datetime_init);

    // Close the datetimepicker when something else is clicked
    $('body').live('click', function(evt) {
        // ignore clicking on the datepicker triggering icon
        if ($(evt.target).closest('.dtpicker-trigger').length) return true;
        // ignore clicking on the datepicker itself
        if ($(evt.target).closest('.datetimepicker').length)   return true;
        // if there's no datepicker shown, don't attempt to hide it
        if ($('.datetimepicker').not(':hidden').length == 0)   return true;
        // all else failed, hide all present datepickers
        $('.datetimepicker').hide();
        // and let the click be processed as usual
        return true;
    });

})(jQuery);
<|endoftext|>


<commit_before>/*
	Note:
		Whenever we support a new PB adapter, we need to check if it needs actual sizes to be passed,
			if so we will need to add special handling
		PreBid does not do mandatory parameters checking
*/
var CONFIG = require("../config.js");
var CONSTANTS = require("../constants.js");
var BID = require("../bid.js");
var util = require("../util.js");
var bidManager = require("../bidManager.js");
var adapterManager = require("../adapterManager.js");
var CONF = require("../conf.js");

var parentAdapterID = CONSTANTS.COMMON.PARENT_ADAPTER_PREBID;

var pbNameSpace = "pbjs";
var pbNameSpaceVersion = 0;

/* start-test-block */
exports.parentAdapterID = parentAdapterID;
/* end-test-block */
var kgpvMap = {};

/* start-test-block */
exports.kgpvMap = kgpvMap;
/* end-test-block */

var refThis = this;

//todo: unit-test-case pending
function transformPBBidToBid(bid, kgpv){
	var theBid = BID.createBid(bid.bidderCode, kgpv);
	theBid.setGrossEcpm(bid.cpm);
	theBid.setDealID(bid.dealId);
	theBid.setDealChannel(bid.dealChannel);
	theBid.setAdHtml(bid.ad || "");
	theBid.setAdUrl(bid.adUrl || "");
	theBid.setWidth(bid.width);
	theBid.setHeight(bid.height);
	theBid.setReceivedTime(bid.responseTimestamp);

	util.forEachOnObject(bid.adserverTargeting, function(key, value){
		theBid.setKeyValuePair(key, value);
	});
	return theBid;
}

//todo: unit-test-case pending
function pbBidStreamHandler(pbBid){
	var responseID = pbBid.adUnitCode || "";
	if(util.isOwnProperty(refThis.kgpvMap, responseID)){
		if(pbBid.bidderCode){
			bidManager.setBidFromBidder(
				refThis.kgpvMap[responseID].divID,
				transformPBBidToBid(pbBid, refThis.kgpvMap[responseID].kgpv)
			);
		}
	}
}

function handleBidResponses(bidResponses){
	for(var responseID in bidResponses){
		/* istanbul ignore else */
		if(util.isOwnProperty(bidResponses, responseID) && util.isOwnProperty(refThis.kgpvMap, responseID)){
			var bidObject = bidResponses[responseID];
			var bids = bidObject.bids || [];

			for(var i = 0; i<bids.length; i++){
				var bid = bids[i];
				/* istanbul ignore else */
				if(bid.bidderCode){
					bidManager.setBidFromBidder(refThis.kgpvMap[responseID].divID, transformPBBidToBid(bid, refThis.kgpvMap[responseID].kgpv));
				}
			}
		}
	}
}

/* start-test-block */
exports.handleBidResponses = handleBidResponses;
/* end-test-block */

function generatedKeyCallback(adapterID, adUnits, adapterConfig, impressionID, generatedKey, kgpConsistsWidthAndHeight, currentSlot, keyConfig, currentWidth, currentHeight){

	var code, sizes, divID = currentSlot.getDivID();

	if(kgpConsistsWidthAndHeight){
		code = divID + "@" + adapterID + "@" + currentWidth + "X" + currentHeight;
		sizes = [[currentWidth, currentHeight]];
	}else{
		code = divID + "@" + adapterID;
		sizes = currentSlot.getSizes();
	}

	refThis.kgpvMap [ code ] = {
		kgpv: generatedKey,
		divID: divID
	};

	/* istanbul ignore else */
	if(!util.isOwnProperty(adUnits, code)){
		adUnits[code] = {
			code: code,
			sizes: sizes,
			bids: []
		};
	}

	var slotParams = {};
	util.forEachOnObject(keyConfig, function(key, value){
		/* istanbul ignore next */
		slotParams[key] = value;
	});

	// processing for each partner
	switch(adapterID){
		case "pubmatic":
			slotParams["publisherId"] = adapterConfig["publisherId"];
			slotParams["adSlot"] = generatedKey;
			slotParams["wiid"] = impressionID;
			slotParams["profId"] = CONFIG.getProfileID();
			/* istanbul ignore else*/
			if(window.PWT.udpv){
				slotParams["verId"] = CONFIG.getProfileDisplayVersionID();
			}
			adUnits[ code ].bids.push({	bidder: adapterID, params: slotParams });
			break;

		case "pulsepoint":
			util.forEachOnArray(sizes, function(index, size){
				slotParams["cf"] = size[0] + "x" + size[1];
				adUnits[ code ].bids.push({	bidder: adapterID, params: slotParams });
			});
			break;

		default:
			adUnits[code].bids.push({ bidder: adapterID, params: slotParams });
			break;
	}
};

/* start-test-block */
exports.generatedKeyCallback = generatedKeyCallback;
/* end-test-block */

function generatePbConf(adapterID, adapterConfig, activeSlots, adUnits, impressionID){
	util.log(adapterID+CONSTANTS.MESSAGES.M1);

	if(!adapterConfig){
		return;
	}

	util.forEachGeneratedKey(
		adapterID,
		adUnits,
		adapterConfig,
		impressionID,
		[],
		activeSlots,
		adapterConfig[CONSTANTS.CONFIG.KEY_GENERATION_PATTERN],
		adapterConfig[CONSTANTS.CONFIG.KEY_LOOKUP_MAP] || null,
		refThis.generatedKeyCallback,
		true
	);
}

/* start-test-block */
exports.generatePbConf = generatePbConf;
/* end-test-block */

function fetchBids(activeSlots, impressionID){

	var newPBNameSpace = pbNameSpace + pbNameSpaceVersion++;
	pwtCreatePrebidNamespace(newPBNameSpace);

	if(! window[newPBNameSpace]){ // todo: move this code to initial state of adhooks
		util.log("PreBid js is not loaded");
		return;
	}

	if(util.isFunction(window[newPBNameSpace].onEvent)){
		window[newPBNameSpace].onEvent('bidResponse', pbBidStreamHandler);
	}

	var adUnits = {};// create ad-units for prebid
	var randomNumberBelow100 = adapterManager.getRandomNumberBelow100();
	CONFIG.forEachAdapter(function(adapterID, adapterConfig){
		// Assumption: all partners are running through PreBid,
		//				if we add any new parent-adapter, then code changes will be required
		/* istanbul ignore else */
		if(adapterID !== refThis.parentAdapterID){
			/* istanbul ignore if */
			if(adapterManager.throttleAdapter(randomNumberBelow100, adapterID) == false){
				adapterManager.setInitTimeForSlotsForAdapter(activeSlots, adapterID);
				refThis.generatePbConf(adapterID, adapterConfig, activeSlots, adUnits, impressionID);
			}else{
				util.log(adapterID+CONSTANTS.MESSAGES.M2);
			}
		}
	});

	// adUnits is object create array from it
	var adUnitsArray = [];
	for(var code in adUnits){
		/* istanbul ignore else */
		if(util.isOwnProperty(adUnits, code)){
			adUnitsArray.push(adUnits[code]);
		}
	}

	/* istanbul ignore else */
	if(adUnitsArray.length > 0 && window[newPBNameSpace]){

		try{
			/* istanbul ignore else */
			if(util.isFunction(window[newPBNameSpace].setBidderSequence)){
				window[newPBNameSpace].setBidderSequence("random");
			}
			/* istanbul ignore else */
			if(util.isFunction(window[newPBNameSpace].requestBids)){
				window[newPBNameSpace].logging = false;//todo: enable optionally
				window[newPBNameSpace].requestBids({
					adUnits: adUnitsArray,
					bidsBackHandler: function(bidResponses) {
						//refThis.handleBidResponses(bidResponses);
					},
					timeout: CONFIG.getTimeout()-50 //todo is it higher ?: major pre and post processing time and then
				});
			}
		} catch (e) {
			util.log('Error occured in calling PreBid.');
			util.log(e);
		}
	}
}

/* start-test-block */
exports.fetchBids = fetchBids;
/* end-test-block */

function getParenteAdapterID() {
	return refThis.parentAdapterID;
}

/* start-test-block */
exports.getParenteAdapterID = getParenteAdapterID;
/* end-test-block */

exports.register = function(){
	return {
		fB: refThis.fetchBids,
		ID: refThis.getParenteAdapterID
	};
};<commit_msg>enable PreBid logs optionally<commit_after>/*
	Note:
		Whenever we support a new PB adapter, we need to check if it needs actual sizes to be passed,
			if so we will need to add special handling
		PreBid does not do mandatory parameters checking
*/
var CONFIG = require("../config.js");
var CONSTANTS = require("../constants.js");
var BID = require("../bid.js");
var util = require("../util.js");
var bidManager = require("../bidManager.js");
var adapterManager = require("../adapterManager.js");
var CONF = require("../conf.js");

var parentAdapterID = CONSTANTS.COMMON.PARENT_ADAPTER_PREBID;

var pbNameSpace = "pbjs";
var pbNameSpaceVersion = 0;

/* start-test-block */
exports.parentAdapterID = parentAdapterID;
/* end-test-block */
var kgpvMap = {};

/* start-test-block */
exports.kgpvMap = kgpvMap;
/* end-test-block */

var refThis = this;

//todo: unit-test-case pending
function transformPBBidToBid(bid, kgpv){
	var theBid = BID.createBid(bid.bidderCode, kgpv);
	theBid.setGrossEcpm(bid.cpm);
	theBid.setDealID(bid.dealId);
	theBid.setDealChannel(bid.dealChannel);
	theBid.setAdHtml(bid.ad || "");
	theBid.setAdUrl(bid.adUrl || "");
	theBid.setWidth(bid.width);
	theBid.setHeight(bid.height);
	theBid.setReceivedTime(bid.responseTimestamp);

	util.forEachOnObject(bid.adserverTargeting, function(key, value){
		theBid.setKeyValuePair(key, value);
	});
	return theBid;
}

//todo: unit-test-case pending
function pbBidStreamHandler(pbBid){
	var responseID = pbBid.adUnitCode || "";
	if(util.isOwnProperty(refThis.kgpvMap, responseID)){
		if(pbBid.bidderCode){
			bidManager.setBidFromBidder(
				refThis.kgpvMap[responseID].divID,
				transformPBBidToBid(pbBid, refThis.kgpvMap[responseID].kgpv)
			);
		}
	}
}

function handleBidResponses(bidResponses){
	for(var responseID in bidResponses){
		/* istanbul ignore else */
		if(util.isOwnProperty(bidResponses, responseID) && util.isOwnProperty(refThis.kgpvMap, responseID)){
			var bidObject = bidResponses[responseID];
			var bids = bidObject.bids || [];

			for(var i = 0; i<bids.length; i++){
				var bid = bids[i];
				/* istanbul ignore else */
				if(bid.bidderCode){
					bidManager.setBidFromBidder(refThis.kgpvMap[responseID].divID, transformPBBidToBid(bid, refThis.kgpvMap[responseID].kgpv));
				}
			}
		}
	}
}

/* start-test-block */
exports.handleBidResponses = handleBidResponses;
/* end-test-block */

function generatedKeyCallback(adapterID, adUnits, adapterConfig, impressionID, generatedKey, kgpConsistsWidthAndHeight, currentSlot, keyConfig, currentWidth, currentHeight){

	var code, sizes, divID = currentSlot.getDivID();

	if(kgpConsistsWidthAndHeight){
		code = divID + "@" + adapterID + "@" + currentWidth + "X" + currentHeight;
		sizes = [[currentWidth, currentHeight]];
	}else{
		code = divID + "@" + adapterID;
		sizes = currentSlot.getSizes();
	}

	refThis.kgpvMap [ code ] = {
		kgpv: generatedKey,
		divID: divID
	};

	/* istanbul ignore else */
	if(!util.isOwnProperty(adUnits, code)){
		adUnits[code] = {
			code: code,
			sizes: sizes,
			bids: []
		};
	}

	var slotParams = {};
	util.forEachOnObject(keyConfig, function(key, value){
		/* istanbul ignore next */
		slotParams[key] = value;
	});

	// processing for each partner
	switch(adapterID){
		case "pubmatic":
			slotParams["publisherId"] = adapterConfig["publisherId"];
			slotParams["adSlot"] = generatedKey;
			slotParams["wiid"] = impressionID;
			slotParams["profId"] = CONFIG.getProfileID();
			/* istanbul ignore else*/
			if(window.PWT.udpv){
				slotParams["verId"] = CONFIG.getProfileDisplayVersionID();
			}
			adUnits[ code ].bids.push({	bidder: adapterID, params: slotParams });
			break;

		case "pulsepoint":
			util.forEachOnArray(sizes, function(index, size){
				slotParams["cf"] = size[0] + "x" + size[1];
				adUnits[ code ].bids.push({	bidder: adapterID, params: slotParams });
			});
			break;

		default:
			adUnits[code].bids.push({ bidder: adapterID, params: slotParams });
			break;
	}
};

/* start-test-block */
exports.generatedKeyCallback = generatedKeyCallback;
/* end-test-block */

function generatePbConf(adapterID, adapterConfig, activeSlots, adUnits, impressionID){
	util.log(adapterID+CONSTANTS.MESSAGES.M1);

	if(!adapterConfig){
		return;
	}

	util.forEachGeneratedKey(
		adapterID,
		adUnits,
		adapterConfig,
		impressionID,
		[],
		activeSlots,
		adapterConfig[CONSTANTS.CONFIG.KEY_GENERATION_PATTERN],
		adapterConfig[CONSTANTS.CONFIG.KEY_LOOKUP_MAP] || null,
		refThis.generatedKeyCallback,
		true
	);
}

/* start-test-block */
exports.generatePbConf = generatePbConf;
/* end-test-block */

function fetchBids(activeSlots, impressionID){

	var newPBNameSpace = pbNameSpace + pbNameSpaceVersion++;
	pwtCreatePrebidNamespace(newPBNameSpace);

	if(! window[newPBNameSpace]){ // todo: move this code to initial state of adhooks
		util.log("PreBid js is not loaded");
		return;
	}

	if(util.isFunction(window[newPBNameSpace].onEvent)){
		window[newPBNameSpace].onEvent('bidResponse', pbBidStreamHandler);
	}

	var adUnits = {};// create ad-units for prebid
	var randomNumberBelow100 = adapterManager.getRandomNumberBelow100();
	CONFIG.forEachAdapter(function(adapterID, adapterConfig){
		// Assumption: all partners are running through PreBid,
		//				if we add any new parent-adapter, then code changes will be required
		/* istanbul ignore else */
		if(adapterID !== refThis.parentAdapterID){
			/* istanbul ignore if */
			if(adapterManager.throttleAdapter(randomNumberBelow100, adapterID) == false){
				adapterManager.setInitTimeForSlotsForAdapter(activeSlots, adapterID);
				refThis.generatePbConf(adapterID, adapterConfig, activeSlots, adUnits, impressionID);
			}else{
				util.log(adapterID+CONSTANTS.MESSAGES.M2);
			}
		}
	});

	// adUnits is object create array from it
	var adUnitsArray = [];
	for(var code in adUnits){
		/* istanbul ignore else */
		if(util.isOwnProperty(adUnits, code)){
			adUnitsArray.push(adUnits[code]);
		}
	}

	/* istanbul ignore else */
	if(adUnitsArray.length > 0 && window[newPBNameSpace]){

		try{
			/* istanbul ignore else */
			if(util.isFunction(window[newPBNameSpace].setBidderSequence)){
				window[newPBNameSpace].setBidderSequence("random");
			}
			/* istanbul ignore else */
			if(util.isFunction(window[newPBNameSpace].requestBids)){
				window[newPBNameSpace].logging = util.debugLogIsEnabled;
				window[newPBNameSpace].requestBids({
					adUnits: adUnitsArray,
					bidsBackHandler: function(bidResponses) {
						//refThis.handleBidResponses(bidResponses);
					},
					timeout: CONFIG.getTimeout()-50 //todo is it higher ?: major pre and post processing time and then
				});
			}
		} catch (e) {
			util.log('Error occured in calling PreBid.');
			util.log(e);
		}
	}
}

/* start-test-block */
exports.fetchBids = fetchBids;
/* end-test-block */

function getParenteAdapterID() {
	return refThis.parentAdapterID;
}

/* start-test-block */
exports.getParenteAdapterID = getParenteAdapterID;
/* end-test-block */

exports.register = function(){
	return {
		fB: refThis.fetchBids,
		ID: refThis.getParenteAdapterID
	};
};<|endoftext|>


<commit_before>import React, { PureComponent } from 'react'

import ReactHighCharts from './ReactHighCharts.js'

import byDepartment from './data/summary-by-department.json'

const piechartColors = (function () {
  const colors = []
  const base = ReactHighCharts.Highcharts.getOptions().colors[0]

  for (let i = -5; i < 5; i += 1) {
    let color = ReactHighCharts.Highcharts.Color(base).brighten(i / 10).get()
    colors.push(color)
  }

  return colors
}())

export default class IncomeLevelPieCharts extends PureComponent {
  constructor (props) {
    super(props)
    this.byDepartment = byDepartment
  }

  render () {
    if (!this.props.department || !this.props.metric) {
      return null
    }

    const graphData = []
    const incomeLevels = this.byDepartment[this.props.department][this.props.metric]
    for (let level in incomeLevels) {
      const levelGraph = {
        level: level,
        data: [],
        type: 'pie'
      }

      let metrics = incomeLevels[level]
      for (let m in metrics) {
        levelGraph.data.push([m, metrics[m]])
      }

      graphData.push(levelGraph)
    }

    const pieCharts = graphData.map((graph, ix) => {
      const config = {
        chart: {
          plotBackgroundColor: null,
          plotBorderWidth: null,
          plotShadow: true
        },
        exporting: {
          enabled: false
        },
        title: {
          text: graph.level
        },
        tooltip: {
          pointFormat: '{name}: {point.percentage:.1f}%'
        },
        legend: {
          enabled: true,
          labelFormat: '{name}: {y:.1f}   ({percentage:.1f}%)'
        },
        plotOptions: {
          pie: {
            allowPointSelect: true,
            colors: piechartColors,
            cursor: 'pointer',
            dataLabels: {
              enabled: false
            },
            showInLegend: true
          }
        },
        series: [graph]
      }

      return <ReactHighCharts key={ix} config={config} />
    })

    return (

        {pieCharts}

    )
  }
}
<commit_msg>Use preset colors for piecharts<commit_after>import React, { PureComponent } from 'react'

import ReactHighCharts from './ReactHighCharts.js'

import byDepartment from './data/summary-by-department.json'

// Adapted from a set of "Fall" colors
// http://duoparadigms.com/2013/10/11/10-color-palettes-perfect-autumnfall-season/
const piechartColors = [
  '#6D7696',
  '#59484F',
  '#455C4F',
  '#CC5543',
  '#EDB579',
  '#DBE6AF',
  '#694364',
  '#94353C'
]

export default class IncomeLevelPieCharts extends PureComponent {
  constructor (props) {
    super(props)
    this.byDepartment = byDepartment
  }

  render () {
    if (!this.props.department || !this.props.metric) {
      return null
    }

    const graphData = []
    const incomeLevels = this.byDepartment[this.props.department][this.props.metric]
    for (let level in incomeLevels) {
      const levelGraph = {
        level: level,
        data: [],
        type: 'pie'
      }

      let metrics = incomeLevels[level]
      for (let m in metrics) {
        levelGraph.data.push([m, metrics[m]])
      }

      graphData.push(levelGraph)
    }

    const pieCharts = graphData.map((graph, ix) => {
      const config = {
        chart: {
          plotBackgroundColor: null,
          plotBorderWidth: null,
          plotShadow: true
        },
        exporting: {
          enabled: false
        },
        title: {
          text: graph.level
        },
        tooltip: {
          pointFormat: '{name}: {point.percentage:.1f}%'
        },
        legend: {
          enabled: true,
          labelFormat: '{name}: {y:.1f}   ({percentage:.1f}%)'
        },
        plotOptions: {
          pie: {
            allowPointSelect: true,
            colors: piechartColors,
            cursor: 'pointer',
            dataLabels: {
              enabled: false
            },
            showInLegend: true
          }
        },
        series: [graph]
      }

      return <ReactHighCharts key={ix} config={config} />
    })

    return (

        {pieCharts}

    )
  }
}
<|endoftext|>


<commit_before>import EVENTS from './../events.js';
import triggerEvent from './../util/triggerEvent.js';
import getToolForElement from './getToolForElement.js';
import { state } from './../store/index.js';

/**
 * Sets a tool's state, with the provided toolName and element, to 'active'. Active tools are rendered,
 * respond to user input, and can create new data.
 *
 * @export @public @method
 * @name setToolActiveForElement
 * @example
Setting a tool 'active' for a specific interaction type.

 * // Sets length tool to Active
 * setToolActiveForElement(element, 'Length', {
 *   mouseButtonMask: 1
 * }, ['Mouse'])
 * @example
Setting a tool 'active' for all interaction types.

 * // Sets length tool to Active
 * setToolActiveForElement(element, 'Length', {
 *   mouseButtonMask: 1
 * })
 * @param {HTMLElement} element
 * @param {string} toolName
 * @param {(Object|string[]|number)} options
 * @param {(string[])} interactionTypes
 * @returns {undefined}
 */
const setToolActiveForElement = function (
  element,
  toolName,
  options,
  interactionTypes
) {
  // If interactionTypes was passed in via options
  if (interactionTypes === undefined && Array.isArray(options)) {
    interactionTypes = options;
    options = null;
  }

  const tool = getToolForElement(element, toolName);

  if (tool) {
    _resolveInputConflicts(element, tool, options, interactionTypes);

    // Iterate over specific interaction types and set active
    // This is used as a secondary check on active tools to find the active "parts" of the tool
    tool.supportedInteractionTypes.forEach((interactionType) => {
      if (
        interactionTypes === undefined ||
        interactionTypes.includes(interactionType)
      ) {
        options[`is${interactionType}Active`] = true;
      } else {
        options[`is${interactionType}Active`] = false;
      }
    });
  }

  // Resume normal behavior
  setToolModeForElement('active', null, element, toolName, options);
};

/**
 * Sets all tool's state, with the provided toolName, to 'active'. Active tools are rendered,
 * respond to user input, and can create new data.
 * @export @public @method
 * @name setToolActive
 * @param {string} toolName
 * @param {(Object|string[]|number)} options
 * @param {(string[])} interactionTypes
 * @returns {undefined}
 */
const setToolActive = function (toolName, options, interactionTypes) {
  state.enabledElements.forEach((element) => {
    setToolActiveForElement(element, toolName, options, interactionTypes);
  });
};

/**
 * Sets a tool's state, with the provided toolName and element, to 'disabled'. Disabled tools are not rendered,
 * and do not respond to user input
 * @export @public @method
 * @param {HTMLElement} element
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolDisabledForElement = setToolModeForElement.bind(
  null,
  'disabled',
  null
);

/**
 * Sets all tool's state, with the provided toolName, to 'disabled'. Disabled tools are not rendered,
 * and do not respond to user input
 * @export @public @method
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolDisabled = setToolMode.bind(null, 'disabled', null);

/**
 * Sets a tool's state, with the provided toolName and element, to 'enabled'. Enabled tools are rendered,
 * but do not respond to user input
 * @export @public @method
 * @param {HTMLElement} element
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolEnabledForElement = setToolModeForElement.bind(
  null,
  'enabled',
  null
);

/**
 * Sets all tool's state, with the provided toolName, to 'enabled'. Enabled tools are rendered,
 * but do not respond to user input
 * @export @public @method
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolEnabled = setToolMode.bind(null, 'enabled', null);

/**
 * Sets a tool's state, with the provided toolName and element, to 'passive'. Passive tools are rendered and respond to user input,
 * but do not create new measurements or annotations.
 * @export @public @method
 * @param {HTMLElement} element
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolPassiveForElement = setToolModeForElement.bind(
  null,
  'passive',
  EVENTS.TOOL_DEACTIVATED
);

/**
 * Sets all tool's state, with the provided toolName, to 'passive'. Passive tools are rendered and respond to user input,
 * but do not create new measurements or annotations.
 * @export @public @method
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolPassive = setToolMode.bind(
  null,
  'passive',
  EVENTS.TOOL_DEACTIVATED
);

/**
 * An internal method that helps make sure we change tool mode in a consistent
 * way
 * @private @method
 * @param {string} mode
 * @param {string} changeEvent
 * @param {HTMLElement} element
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
function setToolModeForElement (mode, changeEvent, element, toolName, options) {
  const tool = getToolForElement(element, toolName);

  if (!tool) {
    console.warn(`Unable to find tool '${toolName}' for enabledElement`);

    return;
  }

  // MouseButtonMask
  if (typeof options === 'number') {
    options = {
      mouseButtonMask: options
    };
  } else {
    options = options || {};
  }

  // Set mode & options
  tool.mode = mode;
  tool.mergeOptions(options);

  // Call tool's hook for this event, if one exists
  if (tool[`${mode}Callback`]) {
    tool[`${mode}Callback`](element, options);
  }

  // Emit event indicating tool state change
  if (changeEvent) {
    const statusChangeEventData = {
      options,
      toolName,
      type: changeEvent
    };

    triggerEvent(element, changeEvent, statusChangeEventData);
  }

  // Trigger Update
  // Todo: don't error out if image hasn't been loaded...
  // Cornerstone.updateImage(element);
}

/**
 * A helper/quick way to set a tool's mode for all canvases
 *
 * @private @method
 * @param {string} mode
 * @param {string} changeEvent
 * @param {string} toolName
 * @param {(object|number)} options
 * @returns {undefined}
 */
function setToolMode (mode, changeEvent, toolName, options) {
  state.enabledElements.forEach((element) => {
    setToolModeForElement(mode, changeEvent, element, toolName, options);
  });
}

/**
 * Find tool's that conflict with the incoming tool's mouse/touch bindings and
 * resolve those conflicts.
 *
 * @private @method
 * @param {HTMLElement} element
 * @param {Object} tool
 * @param {(Object|number)} options
 * @param {(Array)} interactionTypes
 * @returns {undefined}
 */
function _resolveInputConflicts (element, tool, options, interactionTypes) {
  // Iterate over the interaction types our tool supports.
  // For each one we intend to activate, check for potential conflicts
  // And resolve them
  tool.supportedInteractionTypes.forEach((interactionType) => {
    if (
      interactionTypes === undefined ||
      interactionTypes.includes(interactionType)
    ) {
      const inputResolver = _inputResolvers[interactionType];

      if (inputResolver) {
        inputResolver(tool, element, options);
      } else {
        console.warn(
          `Unable to resolve input conflicts for type ${interactionType}`
        );
      }
    }
  });
}

/**
 * Resolves conflicting active tools when activating a tool for mouse interaction
 * @private @method
 * @param {Object} tool
 * @param {HTMLElement} element
 * @param {(Object|number)} options
 * @returns {undefined}
 */
function _resolveMouseInputConflicts (tool, element, options) {
  const mouseButtonMask =
    typeof options === 'number' ? options : options.mouseButtonMask;
  const hasMouseButtonMask =
    mouseButtonMask !== undefined && mouseButtonMask > 0;

  const activeToolWithMatchingMouseButtonMask = state.tools.find(
    (t) =>
      t.element === element &&
      t.mode === 'active' &&
      t.options.isMouseActive === true &&
      t.options.mouseButtonMask === mouseButtonMask
  );

  if (hasMouseButtonMask && activeToolWithMatchingMouseButtonMask) {
    console.info(
      `Setting tool ${
        activeToolWithMatchingMouseButtonMask.name
      }'s isMouseActive to false`
    );
    activeToolWithMatchingMouseButtonMask.options.isMouseActive = false;
  }
}

/**
 * Resolves conflicting active tools when activating a tool for touch interaction
 * @private @method
 * @param {Object} tool
 * @param {HTMLElement} element
 * @param {Object} options
 * @returns {undefined}
 */
function _resolveTouchInputConflicts (tool, element, options) {
  const activeTouchTool = state.tools.find(
    (t) =>
      t.element === element &&
      t.mode === 'active' &&
      t.options.isTouchActive === true
  );

  const activeMultiTouchToolWithOneTouchPointer = state.tools.find(
    (t) =>
      t.element === element &&
      t.mode === 'active' &&
      t.options.isMultiTouchActive === true &&
      t.configuration.touchPointers === 1
  );

  if (activeTouchTool) {
    console.info(
      `Setting tool ${activeTouchTool.name}'s isTouchActive to false`
    );
    activeTouchTool.options.isTouchActive = false;
  }
  if (activeMultiTouchToolWithOneTouchPointer) {
    console.info(
      `Setting tool ${
        activeMultiTouchToolWithOneTouchPointer.name
      }'s isTouchActive to false`
    );
    activeMultiTouchToolWithOneTouchPointer.options.isMultiTouchActive = false;
  }
}

/**
 * Resolves conflicting active tools when activating a tool for MultiTouch interaction
 * @private @method
 * @param {Object} tool
 * @param {HTMLElement} element
 * @param {Object} options
 * @returns {undefined}
 */
function _resolveMultiTouchInputConflicts (tool, element, options) {
  const activeMultiTouchTool = state.tools.find(
    (t) =>
      t.element === element &&
      t.mode === 'active' &&
      t.options.isMultiTouchActive === true &&
      t.configuration.touchPointers === tool.configuration.touchPointers
  );

  let activeTouchTool;

  if (tool.configuration.touchPointers === 1) {
    activeTouchTool = state.tools.find(
      (t) =>
        t.element === element &&
        t.mode === 'active' &&
        t.options.isTouchActive === true
    );
  }

  if (activeMultiTouchTool) {
    console.info(
      `Setting tool ${activeMultiTouchTool.name}'s isMultiTouchActive to false`
    );
    activeMultiTouchTool.options.isMultiTouchActive = false;
  }

  if (activeTouchTool) {
    console.info(
      `Setting tool ${activeTouchTool.name}'s isTouchActive to false`
    );
    activeTouchTool.options.isTouchActive = false;
  }
}

/**
 * If the incoming tool isTouchActive, find any conflicting tools
 * and set their isTouchActive to false to avoid conflicts.
 *
 * @private @method
 * @param {string} interactionType
 * @param {Object} tool
 * @param {HTMLElement} element
 * @param {(Object|number)} options
 * @returns {undefined}
 */
function _resolveGenericInputConflicts (
  interactionType,
  tool,
  element,
  options
) {
  const activeToolWithActiveInteractionType = state.tools.find(
    (t) =>
      t.element === element &&
      t.mode === 'active' &&
      t.options[`is${interactionType}Active`] === true
  );

  if (activeToolWithActiveInteractionType) {
    console.info(
      `Setting tool ${
        activeToolWithActiveInteractionType.name
      }'s is${interactionType}Active to false`
    );
    activeToolWithActiveInteractionType.options[
      `is${interactionType}Active`
    ] = false;
  }
}

const _inputResolvers = {
  Mouse: _resolveMouseInputConflicts,
  MouseWheel: _resolveGenericInputConflicts.bind(this, 'MouseWheel'),
  Touch: _resolveTouchInputConflicts,
  TouchPinch: _resolveGenericInputConflicts.bind(this, 'TouchPinch'),
  TouchRotate: _resolveGenericInputConflicts.bind(this, 'TouchRotate'),
  DoubleTap: _resolveGenericInputConflicts.bind(this, 'DoubleTap'),
  MultiTouch: _resolveMultiTouchInputConflicts
};

export {
  setToolActive,
  setToolActiveForElement,
  setToolDisabled,
  setToolDisabledForElement,
  setToolEnabled,
  setToolEnabledForElement,
  setToolPassive,
  setToolPassiveForElement
};
<commit_msg>If our tool has no `active` interactionTypes, set it to `passive`<commit_after>import EVENTS from './../events.js';
import triggerEvent from './../util/triggerEvent.js';
import getToolForElement from './getToolForElement.js';
import { state } from './../store/index.js';

/**
 * Sets a tool's state, with the provided toolName and element, to 'active'. Active tools are rendered,
 * respond to user input, and can create new data.
 *
 * @export @public @method
 * @name setToolActiveForElement
 * @example
Setting a tool 'active' for a specific interaction type.

 * // Sets length tool to Active
 * setToolActiveForElement(element, 'Length', {
 *   mouseButtonMask: 1
 * }, ['Mouse'])
 * @example
Setting a tool 'active' for all interaction types.

 * // Sets length tool to Active
 * setToolActiveForElement(element, 'Length', {
 *   mouseButtonMask: 1
 * })
 * @param {HTMLElement} element
 * @param {string} toolName
 * @param {(Object|string[]|number)} options
 * @param {(string[])} interactionTypes
 * @returns {undefined}
 */
const setToolActiveForElement = function (
  element,
  toolName,
  options,
  interactionTypes
) {
  // If interactionTypes was passed in via options
  if (interactionTypes === undefined && Array.isArray(options)) {
    interactionTypes = options;
    options = null;
  }

  const tool = getToolForElement(element, toolName);

  if (tool) {
    _resolveInputConflicts(element, tool, options, interactionTypes);

    // Iterate over specific interaction types and set active
    // This is used as a secondary check on active tools to find the active "parts" of the tool
    tool.supportedInteractionTypes.forEach((interactionType) => {
      if (
        interactionTypes === undefined ||
        interactionTypes.includes(interactionType)
      ) {
        options[`is${interactionType}Active`] = true;
      } else {
        options[`is${interactionType}Active`] = false;
      }
    });
  }

  // Resume normal behavior
  setToolModeForElement('active', null, element, toolName, options);
};

/**
 * Sets all tool's state, with the provided toolName, to 'active'. Active tools are rendered,
 * respond to user input, and can create new data.
 * @export @public @method
 * @name setToolActive
 * @param {string} toolName
 * @param {(Object|string[]|number)} options
 * @param {(string[])} interactionTypes
 * @returns {undefined}
 */
const setToolActive = function (toolName, options, interactionTypes) {
  state.enabledElements.forEach((element) => {
    setToolActiveForElement(element, toolName, options, interactionTypes);
  });
};

/**
 * Sets a tool's state, with the provided toolName and element, to 'disabled'. Disabled tools are not rendered,
 * and do not respond to user input
 * @export @public @method
 * @param {HTMLElement} element
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolDisabledForElement = setToolModeForElement.bind(
  null,
  'disabled',
  null
);

/**
 * Sets all tool's state, with the provided toolName, to 'disabled'. Disabled tools are not rendered,
 * and do not respond to user input
 * @export @public @method
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolDisabled = setToolMode.bind(null, 'disabled', null);

/**
 * Sets a tool's state, with the provided toolName and element, to 'enabled'. Enabled tools are rendered,
 * but do not respond to user input
 * @export @public @method
 * @param {HTMLElement} element
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolEnabledForElement = setToolModeForElement.bind(
  null,
  'enabled',
  null
);

/**
 * Sets all tool's state, with the provided toolName, to 'enabled'. Enabled tools are rendered,
 * but do not respond to user input
 * @export @public @method
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolEnabled = setToolMode.bind(null, 'enabled', null);

/**
 * Sets a tool's state, with the provided toolName and element, to 'passive'. Passive tools are rendered and respond to user input,
 * but do not create new measurements or annotations.
 * @export @public @method
 * @param {HTMLElement} element
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolPassiveForElement = setToolModeForElement.bind(
  null,
  'passive',
  EVENTS.TOOL_DEACTIVATED
);

/**
 * Sets all tool's state, with the provided toolName, to 'passive'. Passive tools are rendered and respond to user input,
 * but do not create new measurements or annotations.
 * @export @public @method
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
const setToolPassive = setToolMode.bind(
  null,
  'passive',
  EVENTS.TOOL_DEACTIVATED
);

/**
 * An internal method that helps make sure we change tool mode in a consistent
 * way
 * @private @method
 * @param {string} mode
 * @param {string} changeEvent
 * @param {HTMLElement} element
 * @param {string} toolName
 * @param {(Object|number)} options
 * @returns {undefined}
 */
function setToolModeForElement (mode, changeEvent, element, toolName, options) {
  const tool = getToolForElement(element, toolName);

  if (!tool) {
    console.warn(`Unable to find tool '${toolName}' for enabledElement`);

    return;
  }

  // MouseButtonMask
  if (typeof options === 'number') {
    options = {
      mouseButtonMask: options
    };
  } else {
    options = options || {};
  }

  // Set mode & options
  tool.mode = mode;
  tool.mergeOptions(options);

  // Call tool's hook for this event, if one exists
  if (tool[`${mode}Callback`]) {
    tool[`${mode}Callback`](element, options);
  }

  // Emit event indicating tool state change
  if (changeEvent) {
    const statusChangeEventData = {
      options,
      toolName,
      type: changeEvent
    };

    triggerEvent(element, changeEvent, statusChangeEventData);
  }

  // Trigger Update
  // Todo: don't error out if image hasn't been loaded...
  // Cornerstone.updateImage(element);
}

/**
 * A helper/quick way to set a tool's mode for all canvases
 *
 * @private @method
 * @param {string} mode
 * @param {string} changeEvent
 * @param {string} toolName
 * @param {(object|number)} options
 * @returns {undefined}
 */
function setToolMode (mode, changeEvent, toolName, options) {
  state.enabledElements.forEach((element) => {
    setToolModeForElement(mode, changeEvent, element, toolName, options);
  });
}

/**
 * Find tool's that conflict with the incoming tool's mouse/touch bindings and
 * resolve those conflicts.
 *
 * @private @method
 * @param {HTMLElement} element
 * @param {Object} tool
 * @param {(Object|number)} options
 * @param {(Array)} interactionTypes
 * @returns {undefined}
 */
function _resolveInputConflicts (element, tool, options, interactionTypes) {
  // Iterate over the interaction types our tool supports.
  // For each one we intend to activate, check for potential conflicts
  // And resolve them
  tool.supportedInteractionTypes.forEach((interactionType) => {
    if (
      interactionTypes === undefined ||
      interactionTypes.includes(interactionType)
    ) {
      const inputResolver = _inputResolvers[interactionType];

      if (inputResolver) {
        inputResolver(tool, element, options);
      } else {
        console.warn(
          `Unable to resolve input conflicts for type ${interactionType}`
        );
      }
    }
  });

  const activeToolsForElement = state.tools.filter(
    (t) =>
      t.element === element &&
      t.mode === 'active' &&
      t.supportedInteractionTypes.length > 0
  );

  activeToolsForElement.forEach((t) => {
    let toolHasAnyActiveInteractionType = false;

    t.supportedInteractionTypes.forEach((interactionType) => {
      if (tool.options[`is${interactionType}Active`]) {
        toolHasAnyActiveInteractionType = true;
      }
    });

    if (!toolHasAnyActiveInteractionType) {
      console.info(`Setting tool ${tool.name}'s to PASSIVE`);
      setToolPassiveForElement(element, tool.name);
    }
  });
}

/**
 * Resolves conflicting active tools when activating a tool for mouse interaction
 * @private @method
 * @param {Object} tool
 * @param {HTMLElement} element
 * @param {(Object|number)} options
 * @returns {undefined}
 */
function _resolveMouseInputConflicts (tool, element, options) {
  const mouseButtonMask =
    typeof options === 'number' ? options : options.mouseButtonMask;
  const hasMouseButtonMask =
    mouseButtonMask !== undefined && mouseButtonMask > 0;

  const activeToolWithMatchingMouseButtonMask = state.tools.find(
    (t) =>
      t.element === element &&
      t.mode === 'active' &&
      t.options.isMouseActive === true &&
      t.options.mouseButtonMask === mouseButtonMask
  );

  if (hasMouseButtonMask && activeToolWithMatchingMouseButtonMask) {
    console.info(
      `Setting tool ${
        activeToolWithMatchingMouseButtonMask.name
      }'s isMouseActive to false`
    );
    activeToolWithMatchingMouseButtonMask.options.isMouseActive = false;
  }
}

/**
 * Resolves conflicting active tools when activating a tool for touch interaction
 * @private @method
 * @param {Object} tool
 * @param {HTMLElement} element
 * @param {Object} options
 * @returns {undefined}
 */
function _resolveTouchInputConflicts (tool, element, options) {
  const activeTouchTool = state.tools.find(
    (t) =>
      t.element === element &&
      t.mode === 'active' &&
      t.options.isTouchActive === true
  );

  const activeMultiTouchToolWithOneTouchPointer = state.tools.find(
    (t) =>
      t.element === element &&
      t.mode === 'active' &&
      t.options.isMultiTouchActive === true &&
      t.configuration.touchPointers === 1
  );

  if (activeTouchTool) {
    console.info(
      `Setting tool ${activeTouchTool.name}'s isTouchActive to false`
    );
    activeTouchTool.options.isTouchActive = false;
  }
  if (activeMultiTouchToolWithOneTouchPointer) {
    console.info(
      `Setting tool ${
        activeMultiTouchToolWithOneTouchPointer.name
      }'s isTouchActive to false`
    );
    activeMultiTouchToolWithOneTouchPointer.options.isMultiTouchActive = false;
  }
}

/**
 * Resolves conflicting active tools when activating a tool for MultiTouch interaction
 * @private @method
 * @param {Object} tool
 * @param {HTMLElement} element
 * @param {Object} options
 * @returns {undefined}
 */
function _resolveMultiTouchInputConflicts (tool, element, options) {
  const activeMultiTouchTool = state.tools.find(
    (t) =>
      t.element === element &&
      t.mode === 'active' &&
      t.options.isMultiTouchActive === true &&
      t.configuration.touchPointers === tool.configuration.touchPointers
  );

  let activeTouchTool;

  if (tool.configuration.touchPointers === 1) {
    activeTouchTool = state.tools.find(
      (t) =>
        t.element === element &&
        t.mode === 'active' &&
        t.options.isTouchActive === true
    );
  }

  if (activeMultiTouchTool) {
    console.info(
      `Setting tool ${activeMultiTouchTool.name}'s isMultiTouchActive to false`
    );
    activeMultiTouchTool.options.isMultiTouchActive = false;
  }

  if (activeTouchTool) {
    console.info(
      `Setting tool ${activeTouchTool.name}'s isTouchActive to false`
    );
    activeTouchTool.options.isTouchActive = false;
  }
}

/**
 * If the incoming tool isTouchActive, find any conflicting tools
 * and set their isTouchActive to false to avoid conflicts.
 *
 * @private @method
 * @param {string} interactionType
 * @param {Object} tool
 * @param {HTMLElement} element
 * @param {(Object|number)} options
 * @returns {undefined}
 */
function _resolveGenericInputConflicts (
  interactionType,
  tool,
  element,
  options
) {
  const activeToolWithActiveInteractionType = state.tools.find(
    (t) =>
      t.element === element &&
      t.mode === 'active' &&
      t.options[`is${interactionType}Active`] === true
  );

  if (activeToolWithActiveInteractionType) {
    console.info(
      `Setting tool ${
        activeToolWithActiveInteractionType.name
      }'s is${interactionType}Active to false`
    );
    activeToolWithActiveInteractionType.options[
      `is${interactionType}Active`
    ] = false;
  }
}

const _inputResolvers = {
  Mouse: _resolveMouseInputConflicts,
  MouseWheel: _resolveGenericInputConflicts.bind(this, 'MouseWheel'),
  Touch: _resolveTouchInputConflicts,
  TouchPinch: _resolveGenericInputConflicts.bind(this, 'TouchPinch'),
  TouchRotate: _resolveGenericInputConflicts.bind(this, 'TouchRotate'),
  DoubleTap: _resolveGenericInputConflicts.bind(this, 'DoubleTap'),
  MultiTouch: _resolveMultiTouchInputConflicts
};

export {
  setToolActive,
  setToolActiveForElement,
  setToolDisabled,
  setToolDisabledForElement,
  setToolEnabled,
  setToolEnabledForElement,
  setToolPassive,
  setToolPassiveForElement
};
<|endoftext|>