<commit_before>import sourceAutocomplete   from './sourceAutocomplete'
import sourceOption   from './sourceOption'
import {
  abeExtend
  ,User
} from '../../../'

export function getAttributes(params) {
  var attributes = ''
  if(params.key != null) attributes += `id="${params.key}" data-id="${params.key}"`
  if(params.value != null) attributes += ` value="${params.value}"`
  if(params['max-length'] != null) attributes += ` data-maxlength="${params['max-length']}"`
  if(params.reload != null) attributes += ` reload="${params.reload}"`
  if(params.order != null) attributes += ` tabIndex="${params.order}"`
  if(params.required != null) attributes += ` data-required="${params.required}"`
  if(params.display != null) attributes += ` data-display="${params.display}"`
  if(params.visible != null) attributes += ` data-visible="${params.visible}"`
  if(params.autocomplete != null) attributes += ` data-autocomplete="${params.autocomplete}"`
  if(params.placeholder != null) attributes += ` placeholder="${params.placeholder}"`
  if(params.thumbs != null) attributes += ` data-size="${params.thumbs}"`
  if(params.toolbar != null) attributes += ` data-toolbar="${params.toolbar}"`
  if(params.multiple != null) attributes += ` ${params.multiple}`
  if(params.disabled != null) attributes += ` ${params.disabled}`
  return attributes
}

export function getLabel(params) {
  var desc = params.desc + ((params.required) ? ' *' : '')
  return `
            ${desc}
          `
}

export function hint(params) {
  if (params.hint) {
    return `

         ${params.hint}

`
  }

  return ''
}

export function createInputSource(attributes, inputClass, params) {
  var inputSource = `<div class="parent-${params.type} parent-${params.key}" data-parent="${params.key}">`
  var lastValues
  if(params.autocomplete != null && params.autocomplete === 'true') {
    if(params.sourceString.indexOf('http') === 0) lastValues = params.source
    else lastValues = JSON.stringify(params.source).replace(/\'/g, '&quote;')
    inputSource += `<div class="autocomplete-result-wrapper">`
    if(params.autocomplete != null && params.autocomplete === 'true' && params.prefill === 'true') {
      inputSource += `

`
    }
    Array.prototype.forEach.call(params.value, (val) => {
      inputSource += sourceAutocomplete(val, params)
    })
    inputSource += `</div><input value="" type="text" autocomplete="off" data-value='${lastValues}' ${attributes} class="${inputClass}" />`
  }
  else {
    lastValues = JSON.stringify(params.value).replace(/\'/g, '&quote;')
    inputSource += `<select ${attributes} class="${inputClass}" last-values='${lastValues}'>`

    // if (!params.required) inputSource += '<option value=\'\'></option>'
    var options = ''
    if(typeof params.source === 'object' && Object.prototype.toString.call(params.source) === '[object Array]') {
      Array.prototype.forEach.call(params.source, (val) => {
        options += sourceOption(val, params)
      })
    }else{
      options += sourceOption(params.source, params)
    }

    var defaultValueSelected = 'selected=selected'
    if (options.indexOf('selected') > -1) {
      defaultValueSelected = ''
    }
    if (params.required) inputSource += `<option value=\'\' value="" disabled ${defaultValueSelected}>Select ${params.desc.toLowerCase()}...</option>`
    if (!params.required) inputSource += `<option value=\'\' value="" ${defaultValueSelected}></option>`
    inputSource += options

    inputSource += '</select>'
  }
  inputSource += `${hint(params)}</div>`

  return inputSource
}

export function createInputRich(attributes, inputClass, params) {
  var buttons = [
    { icon: 'bold',                  title: 'Bold (Ctrl+B)',          action: 'bold',         param: '',         hotkey: 'b',     key:'b' },
    { icon: 'ti-Italic',             title: 'Italic (Ctrl+I)',        action: 'italic',       param: '',         hotkey: 'i' },
    { icon: 'ti-underline',          title: 'Underline (Ctrl+U)',     action: 'underline',    param: '',         hotkey: 'u' },
    { icon: 'strikethrough',         title: 'Strikethrough',          action: 'strikethrough',param: '' ,                         key:'s' },
    { icon: 'ti-paint-bucket',       title: 'Text color',             action: 'forecolor',    param: '',         popup: 'color' },
    { icon: 'ti-paint-bucket bg',    title: 'Background color',       action: 'highlight',    param: '',         popup: 'color' },
    { icon: 'ti-align-left',         title: 'Left',                   action: 'align',        param: 'left' },
    { icon: 'ti-align-center',       title: 'Center',                 action: 'align',        param: 'center' },
    { icon: 'ti-align-right',        title: 'Right',                  action: 'align',        param: 'right' },
    { icon: 'ti-align-justify',      title: 'Justify',                action: 'align',        param: 'justify' },
    { icon: 'ti-text ti-text-sub',   title: 'Subscript',              action: 'subscript',    param: '' },
    { icon: 'ti-text ti-text-sup',   title: 'Superscript',            action: 'superscript',  param: '' },
    { icon: 'ti-shift-right-alt',    title: 'Indent',                 action: 'indent',       param: '' },
    { icon: 'ti-shift-left-alt',     title: 'Outdent',                action: 'indent',       param: 'outdent' },
    { icon: 'ti-list',               title: 'Unordered list',         action: 'list',         param: '' },
    { icon: 'ti-list-ol',            title: 'Ordered list',           action: 'list',         param: 'ordered' },
    { icon: 'ti-eraser',             title: 'Remove format',          action: 'removeFormat', param: '' },
    { icon: 'ti-link',               title: 'Add link',               action: 'insertLink',   param: '',         popup: 'link' },
    { icon: 'console',               title: 'Code style',             action: 'code',         param: '',                          key:'{code}' },
    { icon: 'ti-image',              title: 'media',                  action: 'media',        param: '',         popup: 'image' },
    { icon: 'ti-face-smile',         title: 'smiley',                 action: 'smiley',       param: '',         popup: 'smiley' },
  ]
  if(params.toolbar !== '*') params.toolbar = params.toolbar.split(',')
  var inputRich = `

`

  buttons.forEach(function (button) {
    if(params.toolbar === '*' || params.toolbar.indexOf(button.action) > -1){
      var hotkey = (button.hotkey != null) ? `hotkey="${button.hotkey}"` : ''
      var popup = (button.popup != null) ? `data-popup="${button.popup}"` : ''
      if (button.popup === 'image') button.action = 'insertImage'
      if (button.action === 'list') button.action = 'insertList'
      inputRich += `
                      ${(button.key) ? button.key : ''}
                    `
    }
  })

  inputRich +=    `

                  <textarea class="${inputClass} form-rich" ${attributes} rows="4">${params.value}</textarea>

                ${hint(params)}

`

  return inputRich
}

export function createInputFile(attributes, inputClass, params) {

  return `

            <input type="text" ${attributes} class="${inputClass} file-input" />

              <input class="form-control" ${attributes} name="${params.key}" type="file" title="upload a file"/>

          ${hint(params)}

`
}

export function createInputTextarea(attributes, inputClass, params) {
  return `

          <textarea class="${inputClass}" ${attributes} rows="4">${params.value}</textarea>
            ${hint(params)}

`
}

export function createInputLink(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass}" />

          ${hint(params)}

`
}

export function createInputImage(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass} file-input" />

              <input class="form-control" ${attributes} name="${params.key}" type="file" title="upload an image"/>

        ${hint(params)}

`
}

export function createInputText(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass}" />

            ${hint(params)}

`
}

/**
 * Print form input based on input data type {Textarea | text | meta | link | image | ...}
 * && add appropriate attributs / data-attributs
 * @return {String|html} input / input group ...
 */
export function printInput (params, root) {
  params = abeExtend.hooks.instance.trigger('beforeEditorInput', params)
  var userWorkflow = (root.user != null) ? root.user.role.workflow : ''
  var res = `<div class="form-group" data-precontrib-templates="${params.precontribTemplate}">`
  var inputClass = 'form-control form-abe'
  res += getLabel(params)

  params.placeholder = params.placeholder || ''
  params.value = params.value || ''

  if(typeof params.value === 'string') params.value = params.value.replace(/\"/g, '"')
  if(!(params.toolbar != null)) params.toolbar = '*'

  params.disabled = ''
  if (params.tab !== 'slug' && !User.utils.isUserAllowedOnRoute(userWorkflow, `/abe/operations/edit/${params.status}`)) {
    params.disabled = 'disabled="disabled"'
  }
  var attributes = getAttributes(params)

  if(params.source != null) {
    params.multiple = ((params['max-length'] == null || params['max-length'] > 1) && params.source.length > 0) ? 'multiple' : ''
    params.disabled = (params.source.length <= 0) ? 'disabled' : ''
    res += createInputSource(getAttributes(params), inputClass, params)
  }
  else if (params.type.indexOf('rich') >= 0) res += createInputRich(attributes, inputClass, params)
  else if (params.type.indexOf('file') >= 0) res += createInputFile(attributes, inputClass, params)
  else if (params.type.indexOf('textarea') >= 0) res += createInputTextarea(attributes, inputClass, params)
  else if (params.type.indexOf('link') >= 0) res += createInputLink(attributes, inputClass, params)
  else if (params.type.indexOf('image') >= 0) res += createInputImage(attributes, inputClass, params)
  else res += createInputText(attributes, inputClass, params)

  res += '
'
  res = abeExtend.hooks.instance.trigger('afterEditorInput', res, params)

  return res
}<commit_msg>ic:fix linting<commit_after>import sourceAutocomplete   from './sourceAutocomplete'
import sourceOption   from './sourceOption'
import {
  abeExtend
  ,User
} from '../../../'

export function getAttributes(params) {
  var attributes = ''
  if(params.key != null) attributes += `id="${params.key}" data-id="${params.key}"`
  if(params.value != null) attributes += ` value="${params.value}"`
  if(params['max-length'] != null) attributes += ` data-maxlength="${params['max-length']}"`
  if(params.reload != null) attributes += ` reload="${params.reload}"`
  if(params.order != null) attributes += ` tabIndex="${params.order}"`
  if(params.required != null) attributes += ` data-required="${params.required}"`
  if(params.display != null) attributes += ` data-display="${params.display}"`
  if(params.visible != null) attributes += ` data-visible="${params.visible}"`
  if(params.autocomplete != null) attributes += ` data-autocomplete="${params.autocomplete}"`
  if(params.placeholder != null) attributes += ` placeholder="${params.placeholder}"`
  if(params.thumbs != null) attributes += ` data-size="${params.thumbs}"`
  if(params.toolbar != null) attributes += ` data-toolbar="${params.toolbar}"`
  if(params.multiple != null) attributes += ` ${params.multiple}`
  if(params.disabled != null) attributes += ` ${params.disabled}`
  return attributes
}

export function getLabel(params) {
  var desc = params.desc + ((params.required) ? ' *' : '')
  return `
            ${desc}
          `
}

export function hint(params) {
  if (params.hint) {
    return `

         ${params.hint}

`
  }

  return ''
}

export function createInputSource(attributes, inputClass, params) {
  var inputSource = `<div class="parent-${params.type} parent-${params.key}" data-parent="${params.key}">`
  var lastValues
  if(params.autocomplete != null && params.autocomplete === 'true') {
    if(params.sourceString.indexOf('http') === 0) lastValues = params.source
    else lastValues = JSON.stringify(params.source).replace(/\'/g, '&quote;')
    inputSource += '
'
    if(params.autocomplete != null && params.autocomplete === 'true' && params.prefill === 'true') {
      inputSource += `

`
    }
    Array.prototype.forEach.call(params.value, (val) => {
      inputSource += sourceAutocomplete(val, params)
    })
    inputSource += `</div><input value="" type="text" autocomplete="off" data-value='${lastValues}' ${attributes} class="${inputClass}" />`
  }
  else {
    lastValues = JSON.stringify(params.value).replace(/\'/g, '&quote;')
    inputSource += `<select ${attributes} class="${inputClass}" last-values='${lastValues}'>`

    // if (!params.required) inputSource += '<option value=\'\'></option>'
    var options = ''
    if(typeof params.source === 'object' && Object.prototype.toString.call(params.source) === '[object Array]') {
      Array.prototype.forEach.call(params.source, (val) => {
        options += sourceOption(val, params)
      })
    }else{
      options += sourceOption(params.source, params)
    }

    var defaultValueSelected = 'selected=selected'
    if (options.indexOf('selected') > -1) {
      defaultValueSelected = ''
    }
    if (params.required) inputSource += `<option value=\'\' value="" disabled ${defaultValueSelected}>Select ${params.desc.toLowerCase()}...</option>`
    if (!params.required) inputSource += `<option value=\'\' value="" ${defaultValueSelected}></option>`
    inputSource += options

    inputSource += '</select>'
  }
  inputSource += `${hint(params)}</div>`

  return inputSource
}

export function createInputRich(attributes, inputClass, params) {
  var buttons = [
    { icon: 'bold',                  title: 'Bold (Ctrl+B)',          action: 'bold',         param: '',         hotkey: 'b',     key:'b' },
    { icon: 'ti-Italic',             title: 'Italic (Ctrl+I)',        action: 'italic',       param: '',         hotkey: 'i' },
    { icon: 'ti-underline',          title: 'Underline (Ctrl+U)',     action: 'underline',    param: '',         hotkey: 'u' },
    { icon: 'strikethrough',         title: 'Strikethrough',          action: 'strikethrough',param: '' ,                         key:'s' },
    { icon: 'ti-paint-bucket',       title: 'Text color',             action: 'forecolor',    param: '',         popup: 'color' },
    { icon: 'ti-paint-bucket bg',    title: 'Background color',       action: 'highlight',    param: '',         popup: 'color' },
    { icon: 'ti-align-left',         title: 'Left',                   action: 'align',        param: 'left' },
    { icon: 'ti-align-center',       title: 'Center',                 action: 'align',        param: 'center' },
    { icon: 'ti-align-right',        title: 'Right',                  action: 'align',        param: 'right' },
    { icon: 'ti-align-justify',      title: 'Justify',                action: 'align',        param: 'justify' },
    { icon: 'ti-text ti-text-sub',   title: 'Subscript',              action: 'subscript',    param: '' },
    { icon: 'ti-text ti-text-sup',   title: 'Superscript',            action: 'superscript',  param: '' },
    { icon: 'ti-shift-right-alt',    title: 'Indent',                 action: 'indent',       param: '' },
    { icon: 'ti-shift-left-alt',     title: 'Outdent',                action: 'indent',       param: 'outdent' },
    { icon: 'ti-list',               title: 'Unordered list',         action: 'list',         param: '' },
    { icon: 'ti-list-ol',            title: 'Ordered list',           action: 'list',         param: 'ordered' },
    { icon: 'ti-eraser',             title: 'Remove format',          action: 'removeFormat', param: '' },
    { icon: 'ti-link',               title: 'Add link',               action: 'insertLink',   param: '',         popup: 'link' },
    { icon: 'console',               title: 'Code style',             action: 'code',         param: '',                          key:'{code}' },
    { icon: 'ti-image',              title: 'media',                  action: 'media',        param: '',         popup: 'image' },
    { icon: 'ti-face-smile',         title: 'smiley',                 action: 'smiley',       param: '',         popup: 'smiley' },
  ]
  if(params.toolbar !== '*') params.toolbar = params.toolbar.split(',')
  var inputRich = `

`

  buttons.forEach(function (button) {
    if(params.toolbar === '*' || params.toolbar.indexOf(button.action) > -1){
      var hotkey = (button.hotkey != null) ? `hotkey="${button.hotkey}"` : ''
      var popup = (button.popup != null) ? `data-popup="${button.popup}"` : ''
      if (button.popup === 'image') button.action = 'insertImage'
      if (button.action === 'list') button.action = 'insertList'
      inputRich += `
                      ${(button.key) ? button.key : ''}
                    `
    }
  })

  inputRich +=    `

                  <textarea class="${inputClass} form-rich" ${attributes} rows="4">${params.value}</textarea>

                ${hint(params)}

`

  return inputRich
}

export function createInputFile(attributes, inputClass, params) {

  return `

            <input type="text" ${attributes} class="${inputClass} file-input" />

              <input class="form-control" ${attributes} name="${params.key}" type="file" title="upload a file"/>

          ${hint(params)}

`
}

export function createInputTextarea(attributes, inputClass, params) {
  return `

          <textarea class="${inputClass}" ${attributes} rows="4">${params.value}</textarea>
            ${hint(params)}

`
}

export function createInputLink(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass}" />

          ${hint(params)}

`
}

export function createInputImage(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass} file-input" />

              <input class="form-control" ${attributes} name="${params.key}" type="file" title="upload an image"/>

        ${hint(params)}

`
}

export function createInputText(attributes, inputClass, params) {
  return `

            <input type="text" ${attributes} class="${inputClass}" />

            ${hint(params)}

`
}

/**
 * Print form input based on input data type {Textarea | text | meta | link | image | ...}
 * && add appropriate attributs / data-attributs
 * @return {String|html} input / input group ...
 */
export function printInput (params, root) {
  params = abeExtend.hooks.instance.trigger('beforeEditorInput', params)
  var userWorkflow = (root.user != null) ? root.user.role.workflow : ''
  var res = `<div class="form-group" data-precontrib-templates="${params.precontribTemplate}">`
  var inputClass = 'form-control form-abe'
  res += getLabel(params)

  params.placeholder = params.placeholder || ''
  params.value = params.value || ''

  if(typeof params.value === 'string') params.value = params.value.replace(/\"/g, '"')
  if(!(params.toolbar != null)) params.toolbar = '*'

  params.disabled = ''
  if (params.tab !== 'slug' && !User.utils.isUserAllowedOnRoute(userWorkflow, `/abe/operations/edit/${params.status}`)) {
    params.disabled = 'disabled="disabled"'
  }
  var attributes = getAttributes(params)

  if(params.source != null) {
    params.multiple = ((params['max-length'] == null || params['max-length'] > 1) && params.source.length > 0) ? 'multiple' : ''
    params.disabled = (params.source.length <= 0) ? 'disabled' : ''
    res += createInputSource(getAttributes(params), inputClass, params)
  }
  else if (params.type.indexOf('rich') >= 0) res += createInputRich(attributes, inputClass, params)
  else if (params.type.indexOf('file') >= 0) res += createInputFile(attributes, inputClass, params)
  else if (params.type.indexOf('textarea') >= 0) res += createInputTextarea(attributes, inputClass, params)
  else if (params.type.indexOf('link') >= 0) res += createInputLink(attributes, inputClass, params)
  else if (params.type.indexOf('image') >= 0) res += createInputImage(attributes, inputClass, params)
  else res += createInputText(attributes, inputClass, params)

  res += '
'
  res = abeExtend.hooks.instance.trigger('afterEditorInput', res, params)

  return res
}<|endoftext|>


<commit_before>define('yandex-map-markers', [
    'jquery',
    'underscore'
], function ($, _) {
    'use strict';

    var self;
    var map_options = {
        default_options: {
            center: [55.751574, 37.573856],
            zoom: 10,
            controls: []
        },

        markers_options: {
            iconImageHref: '../../images/marker.png'
        },

        controls_types: {
            zoomControl : { right: "8px", top: "125px" },
            fullscreenControl : { right: "8px", top: "15px" }
        }
    };

    var __balloon_template = function() {
        self.marker_balloon_layout = ymaps.templateLayoutFactory.createClass(
            '
' +
            '
$[properties.name]
' +
            '
$[properties.region], $[properties.city]
' +
            '
$[properties.address]
' +
            '
'
        );
        ymaps.layout.storage.add('map#marker_balloon_layout', self.marker_balloon_layout);
    };

    var __add_markers = function() {
        self.objectManager.add(self.markers_data);
    };

    function Map(map_id, options) {
        self = this;

        if(typeof ymaps == 'undefined') {
            return false;
        }

        $.ajax({
            url: '/json/data.json',
            data: {},
            success: function(data){
                console.log(data);

                self.markers_data = data;

                ymaps.ready(function() {
                    self.initialize(map_id, options);
                });
            },
            dataType: 'json'
        });
    }

    Map.prototype = {
        initialize: function(map_id, options) {
            self.init_map(map_id, options);
            self.init_ballon_template();
            self.init_map_controls();
            self.init_my_controls();
            self.init_object_manager();
            self.add_markers();
            self.getVisibleMarkers();
            //self.geolocation();
        },

        //Инициализация карты
        init_map: function(map_id, options) {
            var init_options = $.extend({}, map_options.default_options, options);
            self.map = new ymaps.Map(
                map_id,
                init_options
            );

            self.map.behaviors.disable('scrollZoom');
        },

        //Инициализация ObjectManager
        init_object_manager: function() {
            self.objectManager = new ymaps.ObjectManager({
                clusterize: true,
                geoObjectPreset: 'islands#greenDotIcon',
                geoObjectBalloonContentLayout: self.marker_balloon_layout,
                geoObjectBalloonMaxWidth: 505,
                geoObjectBalloonMaxHeight: 215,
                geoObjectHideIconOnBalloonOpen: false,
                geoObjectIconLayout: 'default#image',
                geoObjectIconImageHref: map_options.markers_options.iconImageHref,
                geoObjectIconImageSize: [36, 36],
                geoObjectIconImageOffset: [-18, -18],
                clusterBalloonContentLayout: 'cluster#balloonCarouselContent',
                clusterBalloonItemContentLayout: self.marker_balloon_layout,
                clusterballoonWidth: 505,
                clusterBalloonHeight: 215,
                clustergroupByCoordinates: false,
                clusterDisableClickZoom: false,
                clusterHideIconOnBalloonOpen: false
            });

            self.map.geoObjects.add(self.objectManager);
        },

        //Инициализация элементов урпавления для карты
        init_map_controls: function() {
            for (var control in map_options.controls_types) {
                self.map.controls.add(control, {
                    float: 'none',
                    position: map_options.controls_types[control]
                });
            }
        },

        //Инициализация дополнительных элементов управления
        init_my_controls: function() {
            self.map.events.add(['boundschange','datachange','objecttypeschange'], function(e){
                /* self.objectManager.objects.balloon.close();
                 self.objectManager.clusters.balloon.close();*/
                self.getVisibleMarkers();
            });

            $('body').on('click', '.js__show-all-addresses', _.bind(self.showAllAddresses, self));
            $('body').on('click', '.js__show-main-addresses', _.bind(self.showMainAddresses, self));
            $('body').on('click', '.js__select-address', _.bind(self.selectAddresses, self));
            $('body').on('click', '.js__select-optics', _.bind(self.selectOptics, self));
        },

        //Инициализация шаблона для балунов
        init_ballon_template: function() {
            __balloon_template();
        },

        //Добавление меток на карту
        add_markers: function() {
            __add_markers();
        },

        //Получит видимые метки
        getVisibleMarkers: function() {
            var result = ymaps.geoQuery(self.objectManager.objects).searchInside(self.map);
            result.then(function () {
                self.showOptics(result);
            });
        },

        //Центрирование по адресу
        setCenterByAddress: function(address) {
            ymaps.geocode(address, {
                results: 1
            }).then(function (res) {
                var firstGeoObject = res.geoObjects.get(0),
                    bounds = firstGeoObject.properties.get('boundedBy');

                self.map.setBounds(bounds, {
                    checkZoomRange: true
                });
            });
        },

        //Геолокация
        geolocation: function() {
            var geolocation = ymaps.geolocation;
            geolocation.get({
                provider: 'auto',
                autoReverseGeocode: true
            }).then(function (res) {
                var firstGeoObject = res.geoObjects.get(0),
                    bounds = firstGeoObject.properties.get('boundedBy');

                self.map.setBounds(bounds, {
                    checkZoomRange: true
                });
            });
        },

        //Показать оптику
        showOptics: function(optics) {
            var i = 1,
                templateOpticsItem = _.template($('#js__optics__item-template').html()),
                contentOptics = '';

            optics.each(function(optic) {
                var item = {
                    id: optic.properties.get('id'),
                    name: optic.properties.get('name'),
                    region: optic.properties.get('region'),
                    city: optic.properties.get('city'),
                    address: optic.properties.get('address'),
                    description: optic.properties.get('description'),
                    i: i
                };

                i++;
                contentOptics += templateOpticsItem(item);
            });

            $('.js__optics').html(contentOptics);
        },

        //Показать все адреса (города)
        showAllAddresses: function() {
            $('.js__all-addresses').css('display', 'block');
            $('.js__main-addresses').css('display', 'none');
            return false;
        },

        //Показать главные адреса (города)
        showMainAddresses: function() {
            $('.js__all-addresses').css('display', 'none');
            $('.js__main-addresses').css('display', 'block');
            return false;
        },

        //Выбрать адрес (город)
        selectAddresses: function(e) {
            var $el = $(e.currentTarget),
                $id = $el.attr('data-id'),
                templateSurroundingCitiesItem = _.template($('#js__surrounding-cities-item-template').html()),
                contentSurroundingCities = '',
                surrounding_cities = [];

            var finded = self.objectManager.objects.getById($id);

            var current_item = {
                id: finded.properties.id,
                region: finded.properties.region,
                city: finded.properties.city
            };

            self.objectManager.objects.each(function(object) {
                if(object.properties.region == current_item.region && object.properties.region != $id) {
                    surrounding_cities.push(object.properties);
                }
            });

            surrounding_cities = _.uniq(surrounding_cities, function(el) {
                return el.city;
            });

            _.each(surrounding_cities, function(item){
                contentSurroundingCities += templateSurroundingCitiesItem(item);
            });

            self.setCenterByAddress('Россия, ' + current_item.region + ', ' + current_item.city);

            $('.js__select-address').removeClass('active');
            $('.js__select-address[data-id= "'+ $id + '"]').addClass('active');
            $('.js__current_city').html(current_item.city);
            $('.js__surrounding_cities').html(contentSurroundingCities);
            return false;
        },

        //Выбрать оптику
        selectOptics: function(e) {
            var $el = $(e.currentTarget),
                $id = $el.attr('data-id');

            var finded = self.objectManager.objects.getById($id);
            var coord = finded.geometry.coordinates;

            self.map.setCenter(coord, 17)
                .then(function () {
                    setTimeout(function() {
                        var objectState = self.objectManager.getObjectState($id);
                        // Проверяем, находится ли объект в видимой области карты.
                        if (objectState.isShown) {
                            // Если объект попадает в кластер, открываем балун кластера с нужным выбранным объектом.
                            if (objectState.isClustered) {
                                self.objectManager.clusters.state.set('activeObject', finded);
                                self.objectManager.clusters.balloon.open(objectState.cluster.id);
                            } else {
                                // Если объект не попал в кластер, открываем его собственный балун.
                                self.objectManager.objects.balloon.open($id);
                            }
                        }
                    }, 300);
                });

            return false;
        }
    };

    return Map;
});
<commit_msg>Update yandex-map-markers.js<commit_after>define('yandex-map-markers', [
    'jquery',
    'underscore'
], function ($, _) {
    'use strict';

    var self;
    var map_options = {
        default_options: {
            center: [55.751574, 37.573856],
            zoom: 10,
            controls: []
        },

        markers_options: {
            iconImageHref: '../../images/marker.png'
        },

        controls_types: {
            zoomControl : { right: "8px", top: "125px" },
            fullscreenControl : { right: "8px", top: "15px" }
        }
    };

    var __balloon_template = function() {
        self.marker_balloon_layout = ymaps.templateLayoutFactory.createClass(
            '
' +
            '
$[properties.name]
' +
            '
$[properties.region], $[properties.city]
' +
            '
$[properties.address]
' +
            '
'
        );
        ymaps.layout.storage.add('map#marker_balloon_layout', self.marker_balloon_layout);
    };

    var __add_markers = function() {
        self.objectManager.add(self.markers_data);
    };

    function Map(map_id, options) {
        self = this;

        if(typeof ymaps == 'undefined') {
            return false;
        }

        $.ajax({
            url: '/json/data.json',
            data: {},
            success: function(data){
                console.log(data);

                self.markers_data = data;

                ymaps.ready(function() {
                    self.initialize(map_id, options);
                });
            },
            dataType: 'json'
        });
    }

    Map.prototype = {
        initialize: function(map_id, options) {
            self.init_map(map_id, options);
            self.init_ballon_template();
            self.init_map_controls();
            self.init_my_controls();
            self.init_object_manager();
            self.add_markers();
            self.getVisibleMarkers();
            //self.geolocation();
        },

        //Инициализация карты
        init_map: function(map_id, options) {
            var init_options = $.extend({}, map_options.default_options, options);
            self.map = new ymaps.Map(
                map_id,
                init_options
            );

            self.map.behaviors.disable('scrollZoom');
        },

        //Инициализация ObjectManager
        init_object_manager: function() {
            self.objectManager = new ymaps.ObjectManager({
                clusterize: true,
                geoObjectPreset: 'islands#greenDotIcon',
                geoObjectBalloonContentLayout: self.marker_balloon_layout,
                geoObjectBalloonMaxWidth: 505,
                geoObjectBalloonMaxHeight: 215,
                geoObjectHideIconOnBalloonOpen: false,
                geoObjectIconLayout: 'default#image',
                geoObjectIconImageHref: map_options.markers_options.iconImageHref,
                geoObjectIconImageSize: [36, 36],
                geoObjectIconImageOffset: [-18, -18],
                clusterBalloonContentLayout: 'cluster#balloonCarouselContent',
                clusterBalloonItemContentLayout: self.marker_balloon_layout,
                clusterballoonWidth: 505,
                clusterBalloonHeight: 215,
                clustergroupByCoordinates: false,
                clusterDisableClickZoom: false,
                clusterHideIconOnBalloonOpen: false
            });

            self.map.geoObjects.add(self.objectManager);
        },

        //Инициализация элементов урпавления для карты
        init_map_controls: function() {
            for (var control in map_options.controls_types) {
                self.map.controls.add(control, {
                    float: 'none',
                    position: map_options.controls_types[control]
                });
            }
        },

        //Инициализация дополнительных элементов управления
        init_my_controls: function() {
            self.map.events.add(['boundschange','datachange','objecttypeschange'], function(e){
                /* self.objectManager.objects.balloon.close();
                 self.objectManager.clusters.balloon.close();*/
                self.getVisibleMarkers();
            });

            $('body').on('click', '.js__show-all-addresses', _.bind(self.showAllAddresses, self));
            $('body').on('click', '.js__show-main-addresses', _.bind(self.showMainAddresses, self));
            $('body').on('click', '.js__select-address', _.bind(self.selectAddresses, self));
            $('body').on('click', '.js__select-optics', _.bind(self.selectOptics, self));
        },

        //Инициализация шаблона для балунов
        init_ballon_template: function() {
            __balloon_template();
        },

        //Добавление меток на карту
        add_markers: function() {
            __add_markers();
        },

        //Получит видимые метки
        getVisibleMarkers: function() {
            var result = ymaps.geoQuery(self.objectManager.objects).searchInside(self.map);
            result.then(function () {
                self.showOptics(result);
            });
        },

        //Центрирование по адресу
        setCenterByAddress: function(address) {
            ymaps.geocode(address, {
                results: 1
            }).then(function (res) {
                var firstGeoObject = res.geoObjects.get(0),
                    bounds = firstGeoObject.properties.get('boundedBy');

                self.map.setBounds(bounds, {
                    checkZoomRange: true
                });
            });
        },

        //Геолокация
        geolocation: function() {
            var geolocation = ymaps.geolocation;
            geolocation.get({
                provider: 'auto',
                autoReverseGeocode: true
            }).then(function (res) {
                var firstGeoObject = res.geoObjects.get(0),
                    bounds = firstGeoObject.properties.get('boundedBy');

                self.map.setBounds(bounds, {
                    checkZoomRange: true
                });
            });
        },

        //Показать оптику
        showOptics: function(optics) {
            var i = 1,
                templateOpticsItem = _.template($('#js__optics__item-template').html()),
                contentOptics = '';

            optics.each(function(optic) {
                var item = {
                    id: optic.properties.get('id'),
                    name: optic.properties.get('name'),
                    region: optic.properties.get('region'),
                    city: optic.properties.get('city'),
                    address: optic.properties.get('address'),
                    description: optic.properties.get('description'),
                    i: i
                };

                i++;
                contentOptics += templateOpticsItem(item);
            });

            $('.js__optics').html(contentOptics);
        },

        //Показать все адреса (города)
        showAllAddresses: function() {
            $('.js__all-addresses').css('display', 'block');
            $('.js__main-addresses').css('display', 'none');
            return false;
        },

        //Показать главные адреса (города)
        showMainAddresses: function() {
            $('.js__all-addresses').css('display', 'none');
            $('.js__main-addresses').css('display', 'block');
            return false;
        },

        //Выбрать адрес (город)
        selectAddresses: function(e) {
            var $el = $(e.currentTarget),
                $id = $el.attr('data-id'),
                templateSurroundingCitiesItem = _.template($('#js__surrounding-cities-item-template').html()),
                contentSurroundingCities = '',
                surrounding_cities = [];

            var finded = self.objectManager.objects.getById($id);

            var current_item = {
                id: finded.properties.id,
                region: finded.properties.region,
                city: finded.properties.city
            };

            self.objectManager.objects.each(function(object) {
                if(object.properties.region == current_item.region && object.properties.city != current_item.city) {
                    surrounding_cities.push(object.properties);
                }
            });

            surrounding_cities = _.uniq(surrounding_cities, function(el) {
                return el.city;
            });

            _.each(surrounding_cities, function(item){
                contentSurroundingCities += templateSurroundingCitiesItem(item);
            });

            self.setCenterByAddress(current_item.city);

            $('.js__select-address').removeClass('active');
            $('.js__select-address[data-id= "'+ $id + '"]').addClass('active');
            $('.js__current_city').html(current_item.city);
            $('.js__surrounding_cities').html(contentSurroundingCities);
            return false;
        },

        //Выбрать оптику
        selectOptics: function(e) {
            var $el = $(e.currentTarget),
                $id = $el.attr('data-id');

            var finded = self.objectManager.objects.getById($id);
            var coord = finded.geometry.coordinates;

            self.map.setCenter(coord, 17)
                .then(function () {
                    setTimeout(function() {
                        var objectState = self.objectManager.getObjectState($id);
                        // Проверяем, находится ли объект в видимой области карты.
                        if (objectState.isShown) {
                            // Если объект попадает в кластер, открываем балун кластера с нужным выбранным объектом.
                            if (objectState.isClustered) {
                                self.objectManager.clusters.state.set('activeObject', finded);
                                self.objectManager.clusters.balloon.open(objectState.cluster.id);
                            } else {
                                // Если объект не попал в кластер, открываем его собственный балун.
                                self.objectManager.objects.balloon.open($id);
                            }
                        }
                    }, 300);
                });

            return false;
        }
    };

    return Map;
});
<|endoftext|>


<commit_before>/**
 * Copyright 2014, 2015 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

RED.comms = (function() {

    var errornotification = null;
    var clearErrorTimer = null;

    var subscriptions = {};
    var ws;
    var pendingAuth = false;

    function connectWS() {
        var path = location.hostname;
        var port = location.port;
        if (port.length !== 0) {
            path = path+":"+port;
        }
        path = path+document.location.pathname;
        path = path+(path.slice(-1) == "/"?"":"/")+"comms";
        path = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path;

        var auth_tokens = RED.settings.get("auth-tokens");
        pendingAuth = (auth_tokens!=null);

        function completeConnection() {
            for (var t in subscriptions) {
                if (subscriptions.hasOwnProperty(t)) {
                    ws.send(JSON.stringify({subscribe:t}));
                }
            }
        }

        ws = new WebSocket(path);
        ws.onopen = function() {
            if (errornotification) {
                clearErrorTimer = setTimeout(function() {
                    errornotification.close();
                    errornotification = null;
                },1000);
            }
            if (pendingAuth) {
                ws.send(JSON.stringify({auth:auth_tokens.access_token}));
            } else {
                completeConnection();
            }
        }
        ws.onmessage = function(event) {
            var msg = JSON.parse(event.data);
            if (pendingAuth && msg.auth == "ok") {
                pendingAuth = false;
                completeConnection();
            } else if (msg.topic) {
                for (var t in subscriptions) {
                    if (subscriptions.hasOwnProperty(t)) {
                        var re = new RegExp("^"+t.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$");
                        if (re.test(msg.topic)) {
                            var subscribers = subscriptions[t];
                            if (subscribers) {
                                for (var i=0;i<subscribers.length;i++) {
                                    subscribers[i](msg.topic,msg.data);
                                }
                            }
                        }
                    }
                }
            }
        };
        ws.onclose = function() {
            if (errornotification == null) {
                errornotification = RED.notify(RED._("notification.error",{message:RED._("notification.errors.lostConnection")}),"error",true);
            } else if (clearErrorTimer) {
                clearTimeout(clearErrorTimer);
                clearErrorTimer = null;
            }
            setTimeout(connectWS,1000);
        }
    }

    function subscribe(topic,callback) {
        if (subscriptions[topic] == null) {
            subscriptions[topic] = [];
        }
        subscriptions[topic].push(callback);
        if (ws && ws.readyState == 1) {
            ws.send(JSON.stringify({subscribe:topic}));
        }
    }

    function unsubscribe(topic,callback) {
        if (subscriptions[topic]) {
            for (var i=0;i<subscriptions[topic].length;i++) {
                if (subscriptions[topic][i] === callback) {
                    subscriptions[topic].splice(i,1);
                    break;
                }
            }
            if (subscriptions[topic].length === 0) {
                delete subscriptions[topic];
            }
        }
    }

    return {
        connect: connectWS,
        subscribe: subscribe,
        unsubscribe:unsubscribe
    }
})();
<commit_msg>Make the comms link be more tolerant to temporarily blips<commit_after>/**
 * Copyright 2014, 2015 IBM Corp.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/

RED.comms = (function() {

    var errornotification = null;
    var clearErrorTimer = null;

    var subscriptions = {};
    var ws;
    var pendingAuth = false;
    var reconnectAttempts = 0;

    function connectWS() {
        var path = location.hostname;
        var port = location.port;
        if (port.length !== 0) {
            path = path+":"+port;
        }
        path = path+document.location.pathname;
        path = path+(path.slice(-1) == "/"?"":"/")+"comms";
        path = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path;

        var auth_tokens = RED.settings.get("auth-tokens");
        pendingAuth = (auth_tokens!=null);

        function completeConnection() {
            for (var t in subscriptions) {
                if (subscriptions.hasOwnProperty(t)) {
                    ws.send(JSON.stringify({subscribe:t}));
                }
            }
        }

        ws = new WebSocket(path);
        ws.onopen = function() {
            reconnectAttempts = 0;
            if (errornotification) {
                clearErrorTimer = setTimeout(function() {
                    errornotification.close();
                    errornotification = null;
                },1000);
            }
            if (pendingAuth) {
                ws.send(JSON.stringify({auth:auth_tokens.access_token}));
            } else {
                completeConnection();
            }
        }
        ws.onmessage = function(event) {
            var msg = JSON.parse(event.data);
            if (pendingAuth && msg.auth == "ok") {
                pendingAuth = false;
                completeConnection();
            } else if (msg.topic) {
                for (var t in subscriptions) {
                    if (subscriptions.hasOwnProperty(t)) {
                        var re = new RegExp("^"+t.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$");
                        if (re.test(msg.topic)) {
                            var subscribers = subscriptions[t];
                            if (subscribers) {
                                for (var i=0;i<subscribers.length;i++) {
                                    subscribers[i](msg.topic,msg.data);
                                }
                            }
                        }
                    }
                }
            }
        };
        ws.onclose = function() {
            if (reconnectAttempts > 5 && errornotification == null) {
                errornotification = RED.notify(RED._("notification.error",{message:RED._("notification.errors.lostConnection")}),"error",true);
            } else if (clearErrorTimer) {
                clearTimeout(clearErrorTimer);
                clearErrorTimer = null;
            }
            reconnectAttempts++;
            setTimeout(connectWS,1000);
        }
    }

    function subscribe(topic,callback) {
        if (subscriptions[topic] == null) {
            subscriptions[topic] = [];
        }
        subscriptions[topic].push(callback);
        if (ws && ws.readyState == 1) {
            ws.send(JSON.stringify({subscribe:topic}));
        }
    }

    function unsubscribe(topic,callback) {
        if (subscriptions[topic]) {
            for (var i=0;i<subscriptions[topic].length;i++) {
                if (subscriptions[topic][i] === callback) {
                    subscriptions[topic].splice(i,1);
                    break;
                }
            }
            if (subscriptions[topic].length === 0) {
                delete subscriptions[topic];
            }
        }
    }

    return {
        connect: connectWS,
        subscribe: subscribe,
        unsubscribe:unsubscribe
    }
})();
<|endoftext|>


<commit_before>define(["js/data/Entity", "sprd/entity/ShippingState", "sprd/entity/Country", "sprd/entity/Person", "js/data/validator/Validator", "underscore", "js/data/validator/RegExValidator"], function (Entity, ShippingState, Country, Person, Validator, _, RegExValidator) {

    var ADDRESS_TYPES = {
        PACKSTATION: "PACKSTATION",
        PRIVATE: "PRIVATE"
    };

    var MAX_LENGTH = {
        STREET: 50,
        ZIP_CODE: 10,
        CITY: 30,
        STREET_ANNEX: 50
    };

    var LengthValidator = Validator.inherit({
        defaults: {
            errorCode: 'maxLengthError',
            /**
             * The min length of the input
             *
             * @type number
             */
            minLength: 0,
            /**
             * The max length of the input
             * -1 is for unlimited
             *
             * @type number
             */
            maxLength: -1
        },
        _validate: function (entity, options) {
            var value = entity.get(this.$.field),
                schemaDefinition = entity.schema[this.$.field],
                required = schemaDefinition ? schemaDefinition.required : true;

            if (_.isString(value) && (required && value.length || !required)) {

                if (value.length < this.$.minLength || (this.$.maxLength > -1 && value.length > this.$.maxLength)) {
                    return this._createFieldError();
                }
            }
        }
    });

    var POSTNUMMER = "Postnummer ",
        PACKSTATION = "Packstation ";

    var Address = Entity.inherit("sprd.entity.Address", {

        defaults: {
            type: ADDRESS_TYPES.PRIVATE,
            company: null,
            person: Person,

            street: null,
            streetAnnex: null,
            houseNumber: '1',
            city: null,
            state: null,
            country: null,
            zipCode: null,
            email: null,
            phone: null,
            fax: null,
            packStationNr: "",
            postNr: "",

            root: null,
            shippingCountries: "{root.shippingCountries()}"
        },

        schema: {
            type: {
                type: String,
                required: true
            },
            company: {
                type: String,
                required: false
            },

            person: Person,

            street: {
                type: String,
                required: function () {
                    return this.get('type') == ADDRESS_TYPES.PRIVATE;
                }
            },

            streetAnnex: {
                type: String,
                required: false
            },
            city: String,
            houseNumber: String,
            state: {
                type: ShippingState,
                required: function () {
                    return this.isStateRequired();
                }
            },
            country: {
                type: Country,
                isReference: true
            },
            zipCode: {
                type: String,
                required: function () {
                    // not required for Ireland
                    return this.get('country.code') !== "IE";
                }
            },
            postNr: {
                type: String,
                required: function () {
                    return this.get('type') == ADDRESS_TYPES.PACKSTATION
                }
            },

            packStationNr: {
                type: String,
                required: function () {
                    return this.get('type') == ADDRESS_TYPES.PACKSTATION
                }
            },

            phone: {
                type: String,
                required: false
            },
            fax: {
                type: String,
                required: false
            }
        },

        validators: [
            new LengthValidator({
                field: "zipCode",
                maxLength: MAX_LENGTH.ZIP_CODE
            }),
            new LengthValidator({
                field: "city",
                maxLength: MAX_LENGTH.CITY
            }),
            new LengthValidator({
                field: "street",
                maxLength: MAX_LENGTH.STREET
            }),
            new LengthValidator({
                field: "streetAnnex",
                maxLength: MAX_LENGTH.STREET_ANNEX
            }),
            new RegExValidator({
                field: "street",
                regEx: /postfiliale/i,
                inverse: true,
                errorCode: "postfilialeNotSupported"
            }),
            new RegExValidator({
                field: "street",
                regEx: /packstation|postnummer/i,
                inverse: true,
                errorCode: "packstationError"
            })
        ],

        _commitChangedAttributes: function ($) {
            this.callBase();

            if ($.hasOwnProperty("country") && this.$.type === ADDRESS_TYPES.PACKSTATION) {
                if ($.country.get('code') != "DE") {
                    this.set('type', ADDRESS_TYPES.PRIVATE);
                }
            }
        },

        parse: function (data) {
            if (data.type === ADDRESS_TYPES.PACKSTATION) {
                data.packStationNr = data.street ? data.street.replace(PACKSTATION, "") : "";
                data.postNr = data.streetAnnex ? data.streetAnnex.replace(POSTNUMMER, "") : "";
                delete data.streetAnnex;
                delete data.street;
            }

            return this.callBase(data);
        },

        compose: function () {
            var data = this.callBase();

            if (this.get("country.code") !== "US") {
                delete data.state;
            }

            if (this.get('type') === ADDRESS_TYPES.PACKSTATION) {
                data.street = PACKSTATION + data.packStationNr;
                data.streetAnnex = POSTNUMMER + data.postNr;
            } else {
                delete data.packstationNr;
                delete data.postNr;
            }

            return data;
        },

        isPackStation: function () {
            return this.$.type == ADDRESS_TYPES.PACKSTATION;
        }.onChange('type'),

        supportsCounty: function () {
            var code = this.get('country.code');
            return  code === "GB" || code === "IE";
        }.onChange('country'),

        isStateRequired: function () {
            var code = this.get("country.code");
            return  code === "US" || code === "IE";
        }.onChange('country'),

        needsZipCode: function () {
            return this.get("country.code") !== "IE";
        }.onChange('country')
    });

    Address.ADDRESS_TYPES = ADDRESS_TYPES;
    Address.MAX_LENGTH = MAX_LENGTH;

    return Address;
});
<commit_msg>optimized required functions<commit_after>define(["js/data/Entity", "sprd/entity/ShippingState", "sprd/entity/Country", "sprd/entity/Person", "js/data/validator/Validator", "underscore", "js/data/validator/RegExValidator"], function (Entity, ShippingState, Country, Person, Validator, _, RegExValidator) {

    var ADDRESS_TYPES = {
        PACKSTATION: "PACKSTATION",
        PRIVATE: "PRIVATE"
    };

    var MAX_LENGTH = {
        STREET: 50,
        ZIP_CODE: 10,
        CITY: 30,
        STREET_ANNEX: 50
    };

    var LengthValidator = Validator.inherit({
        defaults: {
            errorCode: 'maxLengthError',
            /**
             * The min length of the input
             *
             * @type number
             */
            minLength: 0,
            /**
             * The max length of the input
             * -1 is for unlimited
             *
             * @type number
             */
            maxLength: -1
        },
        _validate: function (entity, options) {
            var value = entity.get(this.$.field),
                schemaDefinition = entity.schema[this.$.field],
                required = schemaDefinition ? schemaDefinition.required : true;

            if (_.isString(value) && (required && value.length || !required)) {

                if (value.length < this.$.minLength || (this.$.maxLength > -1 && value.length > this.$.maxLength)) {
                    return this._createFieldError();
                }
            }
        }
    });

    var POSTNUMMER = "Postnummer ",
        PACKSTATION = "Packstation ";

    var Address = Entity.inherit("sprd.entity.Address", {

        defaults: {
            type: ADDRESS_TYPES.PRIVATE,
            company: null,
            person: Person,

            street: null,
            streetAnnex: null,
            houseNumber: '1',
            city: null,
            state: null,
            country: null,
            zipCode: null,
            email: null,
            phone: null,
            fax: null,
            packStationNr: "",
            postNr: "",

            root: null,
            shippingCountries: "{root.shippingCountries()}"
        },

        schema: {
            type: {
                type: String,
                required: true
            },
            company: {
                type: String,
                required: false
            },

            person: Person,

            street: {
                type: String,
                required: function () {
                    return !this.isPackStation();
                }
            },

            streetAnnex: {
                type: String,
                required: false
            },
            city: String,
            houseNumber: String,
            state: {
                type: ShippingState,
                required: function () {
                    return this.isStateRequired();
                }
            },
            country: {
                type: Country,
                isReference: true
            },
            zipCode: {
                type: String,
                required: function () {
                    // not required for Ireland
                    return this.needsZipCode();
                }
            },
            postNr: {
                type: String,
                required: function () {
                    return this.isPackStation()
                }
            },

            packStationNr: {
                type: String,
                required: function () {
                    return this.isPackStation()
                }
            },

            phone: {
                type: String,
                required: false
            },
            fax: {
                type: String,
                required: false
            }
        },

        validators: [
            new LengthValidator({
                field: "zipCode",
                maxLength: MAX_LENGTH.ZIP_CODE
            }),
            new LengthValidator({
                field: "city",
                maxLength: MAX_LENGTH.CITY
            }),
            new LengthValidator({
                field: "street",
                maxLength: MAX_LENGTH.STREET
            }),
            new LengthValidator({
                field: "streetAnnex",
                maxLength: MAX_LENGTH.STREET_ANNEX
            }),
            new RegExValidator({
                field: "street",
                regEx: /postfiliale/i,
                inverse: true,
                errorCode: "postfilialeNotSupported"
            }),
            new RegExValidator({
                field: "street",
                regEx: /packstation|postnummer/i,
                inverse: true,
                errorCode: "packstationError"
            })
        ],

        _commitChangedAttributes: function ($) {
            this.callBase();

            if ($.hasOwnProperty("country") && this.$.type === ADDRESS_TYPES.PACKSTATION) {
                if ($.country.get('code') != "DE") {
                    this.set('type', ADDRESS_TYPES.PRIVATE);
                }
            }
        },

        parse: function (data) {
            if (data.type === ADDRESS_TYPES.PACKSTATION) {
                data.packStationNr = data.street ? data.street.replace(PACKSTATION, "") : "";
                data.postNr = data.streetAnnex ? data.streetAnnex.replace(POSTNUMMER, "") : "";
                delete data.streetAnnex;
                delete data.street;
            }

            return this.callBase(data);
        },

        compose: function () {
            var data = this.callBase();

            if (this.get("country.code") !== "US") {
                delete data.state;
            }

            if (this.get('type') === ADDRESS_TYPES.PACKSTATION) {
                data.street = PACKSTATION + data.packStationNr;
                data.streetAnnex = POSTNUMMER + data.postNr;
            } else {
                delete data.packstationNr;
                delete data.postNr;
            }

            return data;
        },

        isPackStation: function () {
            return this.$.type == ADDRESS_TYPES.PACKSTATION;
        }.onChange('type'),

        supportsCounty: function () {
            var code = this.get('country.code');
            return  code === "GB" || code === "IE";
        }.onChange('country'),

        isStateRequired: function () {
            var code = this.get("country.code");
            return  code === "US" || code === "IE";
        }.onChange('country'),

        needsZipCode: function () {
            return this.get("country.code") !== "IE";
        }.onChange('country')
    });

    Address.ADDRESS_TYPES = ADDRESS_TYPES;
    Address.MAX_LENGTH = MAX_LENGTH;

    return Address;
});
<|endoftext|>


<commit_before>/* ©Copyright Utrecht University (Department of Information and Computing Sciences) */

(function()
{
    "use strict";

    var itemProperties = [],
        propEditors =
        {
            fallback: '<input tabindex="1" type="text">',
            type: '<select tabindex="1" class="type">' +
                '<option value="player">' + i18next.t('draft:letter.player') + '</option>' +
                '<option value="computer">' + i18next.t('draft:letter.computer') + '</option>' +
                '<option value="situation">' + i18next.t('draft:letter.situation') + '</option>' +
                '</select>',
            statement: '<textarea tabindex="1"></textarea>'
        },
        editing = null,
        editingCol = -1,
        maxCols = 0;

    $(document).ready(function()
    {
        $('#draftScreen').html(Parts.getDraftScreenHTML());

        itemProperties = $('#draftTable').data("properties").split(',');
        maxCols = itemProperties.length - 1;

        styleTableSpacing();

        // Resizability for the table columns
        $('#draftTable').colResizable(
        {
            liveDrag: true
        });

        // Resizability for the whole panel
        $('#draftScreen').resizable(
        {
            containment: "parent",
            handles: "n",
            maxHeight: $('#content').height() / 2,
            minHeight: 100
        });

        // Click-to-edit functionality
        $('#draftTable').on("click",
            '.draftItem td:has(span.value):not(:has(:input:focus))',
            function()
            {
                var tr = $(this).closest('tr'),
                    value = $(this).find('.value'),
                    edit = $(this).find('.edit'),
                    editField = edit.children();

                if (!$(this).hasClass("disabled"))
                {
                    if (value.html() !== "")
                    {
                        editField.val(value.html());
                    }
                    value.hide();
                    edit.show();
                    editField.trigger("focus");

                    editing = tr;
                    editingCol = parseInt($(this).attr("class")
                        .split(" ")[1].substr(3), 10);
                }
            });

        // Save property value on blur
        $('#draftTable').on("blur", ':input:not(select)',
            function()
            {
                saveOnBlur($(this));
            });

        // Save select values on change
        $('#draftTable').on("change", 'select', function()
        {
            var tr = $(this).closest('tr'),
                item = tr.data('item'),
                property = $(this).parents('td').attr("class").split(" ")[0],
                value = $(this).val(),
                playerOnlyCols =
                [
                    itemProperties.indexOf("effect")
                ];

            item.properties[property] = value;

            // Disable / enable player-only properties
            if ($(this).hasClass("type"))
            {
                var playerOnlySel = '.col' + playerOnlyCols.join(", .col");
                var playerOnlyTds = tr.find(playerOnlySel);
                if (value === "computer")
                {
                    playerOnlyTds.addClass("disabled");
                    playerOnlyTds.append(
                        ''+i18next.t('draft:not_available')+''
                    );
                }
                if (value === "player")
                {
                    playerOnlyTds.removeClass("disabled");
                    playerOnlyTds.find('.disabled-text').remove();
                }
            }

            editing = null;
            editingCol = -1;
        });

        // for all nodes together
        // Drag & drop into main container
        $('#draftDragAll').on("mousedown", function(e)
        {
            // Make sure key shortcut events can be fired tp cancel the dragbox
            $("#main").focus();

            e.preventDefault(); // Prevent selecting text

            if (!Zoom.isZoomed())
            {
                DragBox.showError(e, i18next.t('draft:no_subject_open'));
                return;
            }

            if (allIsEmpty())
            {
                DragBox.showError(e, i18next.t('draft:no_filled_items'));
                return;
            }

            if (editing) editing.find(':input:focus').trigger("blur");

            var text = i18next.t('draft:all_items');
            DragBox.startDragging(e, text, function(pos)
            {
                var nodes = allItemsToNodes(),
                    main = $('#main').offset(),
                    min = main.top + 51;
                nodes.forEach( function(node)
                {
                    var xdif = -75 + 150 * Math.random(), ydif = -75 + 150 * Math.random();
                    var nodePos = {
                        left : Math.max(0,pos.left + xdif),
                        top : Math.max(pos.top + ydif, min)
                    };
                    $('#' + node.id).offset(nodePos);
                });
                return true;
            });
        });

        // for the single nodes:
        // Drag & drop into main container
        $('#draftTable').on("mousedown", 'td.dragHandle', function(e)
        {
            // Make sure key shortcut events can be fired tp cancel the dragbox
            $("#main").focus();

            e.preventDefault(); // Prevent selecting text

            if (!Zoom.isZoomed())
            {
                DragBox.showError(e, i18next.t('draft:no_subject_open'));
                return;
            }

            var tr = $(this).closest('tr');
            if (isItemEmpty(tr))
            {
                DragBox.showError(e, i18next.t('draft:empty_item'));
                return;
            }

            tr.find(':input:focus').trigger("blur");

            var stmt = tr.data('item').properties.statement.trimToLength(25);
            var index = $('#draftTable tr.draftItem').index(tr);
            var text = i18next.t('draft:item_number', { postProcess: 'sprintf', sprintf: [parseInt(index, 10) + 1]});
            if (stmt) text += ' ' + stmt;

            if (DragBox.isDroppable())
            {
                tr.find('td').addClass("disabled");
            }
            else
            {
                tr.find('td').removeClass("disabled");
            }
            DragBox.startDragging(e, text, function(pos)
            {
                var node = itemToNode(tr);
                $('#' + node.id).offset(pos);
                return true;
            });
        });

        // Keydown events
        $(document).keydown(function(e)
        {
            var tr = editing,
                col = editingCol;

            if (editing)
            {

                // ENTER
                if (e.which === 13)
                {

                    e.preventDefault();

                    tr.find('.col' + col + ' :input').trigger("blur");

                    // + CTRL
                    if (e.ctrlKey)
                    {
                        // + SHIFT
                        if (e.shiftKey)
                        {
                            // Make nodes of all items
                            allItemsToNodes();
                        }
                        else
                        {
                            // Makes node of current item
                            itemToNode(tr);
                        }
                    }
                    else if (!e.shiftKey)
                    {
                        // Next row
                        var next = tr.next();

                        if (next.length === 0)
                        {
                            createDraftItem();
                            next = tr.next();
                        }
                        col = 1;

                        next.find('.col' + col).trigger("click");
                    }
                }
                // CTRL + DELETE
                else if (e.ctrlKey && e.which === 46)
                {
                    // Removes current item

                    tr.prev().find('.col1').trigger("click");

                    removeItem(tr);
                }
                // TAB
                else if (e.which === 9)
                {
                    // Go to next/previous column
                    e.preventDefault();

                    tr.find('.col' + col + ' :input').trigger("blur");

                    // + SHIFT
                    var obj;
                    if (e.shiftKey)
                    {
                        // Previous
                        obj = prevCol({tr: tr, col: col});
                    }
                    else
                    {
                        // Next
                        obj = nextCol({tr: tr, col: col});
                    }
                    obj.tr.find('td.col' + obj.col).trigger("click");
                }
            }
        });

        // Item control functionality
        $('#addDraftItem').on("click", function(e)
        {
            e.preventDefault();
            createDraftItem();
        });
        $('#itemControls .clear').on("click", function(e)
        {
            e.preventDefault();
            clearTable();
        });

        // Button functionality
        $('#toggleDraftScreen').on("click", function()
        {
            $('#draftScreen').show();
            $('#validationReport').hide();
            $('#tabDock').show();
        });
    });

    // Utils

    // SHIFT + TAB function while editing draft
    function prevCol(obj)
    {
        obj.col -= 1;
        if (obj.col < 1)
        {
            var prev = obj.tr.prev();
            if (prev.length === 0)
            {
                obj.col = 1;
                return obj;
            }
            obj.tr = prev;
            obj.col = maxCols;
        }
        var field = obj.tr.find('.col' + obj.col);
        // recursion to skip cols that are disabled or contain a select element
        if (field.hasClass("disabled") || field.find("select").length > 0)
            obj = prevCol(obj);

        return obj;
    }

    // TAB function while editing draft
    function nextCol(obj)
    {
        obj.col += 1;
        if (obj.col > maxCols)
        {
            var next = obj.tr.next();
            if (next.length === 0)
            {
                obj.tr = createDraftItem();
            }
            else
            {
                obj.tr = next;
            }
            obj.col = 0;
        }
        var field = obj.tr.find('.col' + obj.col);
        // recursion to skip cols that are disabled or contain a select element
        if (field.hasClass("disabled") || field.find("select").length > 0)
            obj = nextCol(obj);

        return obj;
    }

    // String max length trimmer
    String.prototype.trimToLength = function(m)
    {
        if (this.length > m)
        {
            return jQuery.trim(this).substring(0, m)
                .split(" ").slice(0, -1).join(" ") + "...";
        }
        return this;
    };

    // Dynamically style the table depending on the amount of properties
    function styleTableSpacing()
    {
        var wt = $('#content').width(),
            w0 = 45 / wt * 100,
            wh = 35 / wt * 100,
            wp = w0 + wh,
            w = (100 - wp) / (itemProperties.length - 1),
            style = "#draftTable td,#draftTable th{width:" + w + "%}";
        style += " #draftTable td.col0,#draftTable th.col0{width:" + w0 +
            "%;} ";
        style +=
            " #draftTable td.dragHandle,#draftTable th.dragHandle{width:" +
            wh + "%;}";

        $('#draftStyle').append(style);
    }

    // Style the table rows with zebra striping
    // Avoiding CSS3 for the sake of compatibility
    function styleTableRows()
    {
        var i = 0;

        $('tr.draftItem').removeClass("odd").removeClass("even");
        $('tr.draftItem').each(function()
        {
            $(this).addClass(i % 2 === 1 ? "odd" : "even");
            i += 1;
        });
    }

    // Creating an empty draft item and adding it to the table
    // Returns the item as an object
    function createDraftItem(ignore)
    {
        var item = {
            properties: {},
            toHtml: function()
            {
                var i, p, e,
                    html = '
';
                html += '::::::	';

                for (i = 0; i < itemProperties.length; i += 1)
                {
                    p = itemProperties[i];
                    e = propEditors[p] === undefined ?
                        propEditors.fallback : propEditors[p];

                    if (e.indexOf('<select') !== -1)
                    {
                        html += '' + e + '	';
                    }
                    else
                    {
                        html += '' + this.properties[
                                p] + '';
                        html +=
                            '' +
                            e + '	';
                    }
                }

                return html + "
";
            }
        };

        itemProperties.forEach(function(p)
        {
            item.properties[p] = "";
        });

        item.properties.type = "player";

        var tr = $(item.toHtml());
        tr.data('item', item);
        $('#draftTable').append(tr);
        styleTableRows();

        if (!ignore)
        {
            tr.find('.col1').trigger("click");
        }

        return tr;
    }

    // Clear the table and remove all items
    function clearTable()
    {
        if (!confirm(i18next.t('draft:delete_all_confirm')))
        {
            return;
        }

        $('#draftTable tr.draftItem').remove();
        createDraftItem();
    }

    function saveOnBlur(input)
    {
        var tr = $(input).closest('tr'),
            item = tr.data('item'),
            property = input.parents('td').attr("class").split(" ")[0],
            value = input.val(),
            valueView = input.parent().siblings('.value');
        item.properties[property] = value;
        valueView.text(value);
        input.parent().hide();
        valueView.show();

        editing = null;
        editingCol = -1;
    }

    function removeItem(tr)
    {
        tr.remove();
        styleTableRows();

        if ($('#draftTable tr.draftItem').length === 0)
        {
            createDraftItem(true);
        }
    }

    function itemToNode(tr)
    {
        if (isItemEmpty(tr)) return;

        var props = tr.data('item').properties,
            node = Main.addNewNode(props.type);

        if (node === null)
        {
            // A tree container must be open.
            console.error("Item to node failed.");
            return;
        }
        // deselect the node before making changes in the object
        // (otherwise chages will be oversaved with empty values)
        Main.selectElement(null);
        node.text = props.statement;

        // make sure the starting input-text equals current saved node.text
        var nodeDiv = $("#"+node.id);
        var inputText = nodeDiv.find(".nodestatement");
        inputText.val(node.text);
        Main.changeNodeText(node.id);
        Main.selectElement(node.id);

        removeItem(tr);
        return node;
    }

    function allItemsToNodes()
    {
        var nodes = [];
        $('#draftTable .draftItem').each(function()
        {
            if (!isItemEmpty($(this)))
            {
                nodes.push(itemToNode($(this)));
            }
        });
        return nodes;
    }
    function allIsEmpty()
    {
        var allEmpty = true;
        $('#draftTable .draftItem').each(function()
        {
            allEmpty = allEmpty && isItemEmpty($(this));
        });
        return allEmpty;
    }

    function isItemEmpty(tr)
    {
        var props = tr.data('item').properties;
        for (var p in props)
        {
            if (props.hasOwnProperty(p) && p !== "type" && props[p] !== "")
            {
                return false;
            }
        }
        return true;
    }
}());
<commit_msg>Removed unused classes and related code<commit_after>/* ©Copyright Utrecht University (Department of Information and Computing Sciences) */

(function()
{
    "use strict";

    var itemProperties = [],
        propEditors =
        {
            fallback: '<input tabindex="1" type="text">',
            type: '<select tabindex="1" class="type">' +
                '<option value="player">' + i18next.t('draft:letter.player') + '</option>' +
                '<option value="computer">' + i18next.t('draft:letter.computer') + '</option>' +
                '<option value="situation">' + i18next.t('draft:letter.situation') + '</option>' +
                '</select>',
            statement: '<textarea tabindex="1"></textarea>'
        },
        editing = null,
        editingCol = -1,
        maxCols = 0;

    $(document).ready(function()
    {
        $('#draftScreen').html(Parts.getDraftScreenHTML());

        itemProperties = $('#draftTable').data("properties").split(',');
        maxCols = itemProperties.length - 1;

        styleTableSpacing();

        // Resizability for the table columns
        $('#draftTable').colResizable(
        {
            liveDrag: true
        });

        // Resizability for the whole panel
        $('#draftScreen').resizable(
        {
            containment: "parent",
            handles: "n",
            maxHeight: $('#content').height() / 2,
            minHeight: 100
        });

        // Click-to-edit functionality
        $('#draftTable').on("click",
            '.draftItem td:has(span.value):not(:has(:input:focus))',
            function()
            {
                var tr = $(this).closest('tr'),
                    value = $(this).find('.value'),
                    edit = $(this).find('.edit'),
                    editField = edit.children();

                if (!$(this).hasClass("disabled"))
                {
                    if (value.html() !== "")
                    {
                        editField.val(value.html());
                    }
                    value.hide();
                    edit.show();
                    editField.trigger("focus");

                    editing = tr;
                    editingCol = parseInt($(this).attr("class")
                        .split(" ")[1].substr(3), 10);
                }
            });

        // Save property value on blur
        $('#draftTable').on("blur", ':input:not(select)',
            function()
            {
                saveOnBlur($(this));
            });

        // Save select values on change
        $('#draftTable').on("change", 'select', function()
        {
            var tr = $(this).closest('tr'),
                item = tr.data('item'),
                property = $(this).parents('td').attr("class").split(" ")[0],
                value = $(this).val(),
                playerOnlyCols =
                [
                    itemProperties.indexOf("effect")
                ];

            item.properties[property] = value;

            // Disable / enable player-only properties
            if ($(this).hasClass("type"))
            {
                var playerOnlySel = '.col' + playerOnlyCols.join(", .col");
                var playerOnlyTds = tr.find(playerOnlySel);
                if (value === "computer")
                {
                    playerOnlyTds.addClass("disabled");
                    playerOnlyTds.append(
                        ''+i18next.t('draft:not_available')+''
                    );
                }
                if (value === "player")
                {
                    playerOnlyTds.removeClass("disabled");
                    playerOnlyTds.find('.disabled-text').remove();
                }
            }

            editing = null;
            editingCol = -1;
        });

        // for all nodes together
        // Drag & drop into main container
        $('#draftDragAll').on("mousedown", function(e)
        {
            // Make sure key shortcut events can be fired tp cancel the dragbox
            $("#main").focus();

            e.preventDefault(); // Prevent selecting text

            if (!Zoom.isZoomed())
            {
                DragBox.showError(e, i18next.t('draft:no_subject_open'));
                return;
            }

            if (allIsEmpty())
            {
                DragBox.showError(e, i18next.t('draft:no_filled_items'));
                return;
            }

            if (editing) editing.find(':input:focus').trigger("blur");

            var text = i18next.t('draft:all_items');
            DragBox.startDragging(e, text, function(pos)
            {
                var nodes = allItemsToNodes(),
                    main = $('#main').offset(),
                    min = main.top + 51;
                nodes.forEach( function(node)
                {
                    var xdif = -75 + 150 * Math.random(), ydif = -75 + 150 * Math.random();
                    var nodePos = {
                        left : Math.max(0,pos.left + xdif),
                        top : Math.max(pos.top + ydif, min)
                    };
                    $('#' + node.id).offset(nodePos);
                });
                return true;
            });
        });

        // for the single nodes:
        // Drag & drop into main container
        $('#draftTable').on("mousedown", 'td.dragHandle', function(e)
        {
            // Make sure key shortcut events can be fired tp cancel the dragbox
            $("#main").focus();

            e.preventDefault(); // Prevent selecting text

            if (!Zoom.isZoomed())
            {
                DragBox.showError(e, i18next.t('draft:no_subject_open'));
                return;
            }

            var tr = $(this).closest('tr');
            if (isItemEmpty(tr))
            {
                DragBox.showError(e, i18next.t('draft:empty_item'));
                return;
            }

            tr.find(':input:focus').trigger("blur");

            var stmt = tr.data('item').properties.statement.trimToLength(25);
            var index = $('#draftTable tr.draftItem').index(tr);
            var text = i18next.t('draft:item_number', { postProcess: 'sprintf', sprintf: [parseInt(index, 10) + 1]});
            if (stmt) text += ' ' + stmt;

            if (DragBox.isDroppable())
            {
                tr.find('td').addClass("disabled");
            }
            else
            {
                tr.find('td').removeClass("disabled");
            }
            DragBox.startDragging(e, text, function(pos)
            {
                var node = itemToNode(tr);
                $('#' + node.id).offset(pos);
                return true;
            });
        });

        // Keydown events
        $(document).keydown(function(e)
        {
            var tr = editing,
                col = editingCol;

            if (editing)
            {

                // ENTER
                if (e.which === 13)
                {

                    e.preventDefault();

                    tr.find('.col' + col + ' :input').trigger("blur");

                    // + CTRL
                    if (e.ctrlKey)
                    {
                        // + SHIFT
                        if (e.shiftKey)
                        {
                            // Make nodes of all items
                            allItemsToNodes();
                        }
                        else
                        {
                            // Makes node of current item
                            itemToNode(tr);
                        }
                    }
                    else if (!e.shiftKey)
                    {
                        // Next row
                        var next = tr.next();

                        if (next.length === 0)
                        {
                            createDraftItem();
                            next = tr.next();
                        }
                        col = 1;

                        next.find('.col' + col).trigger("click");
                    }
                }
                // CTRL + DELETE
                else if (e.ctrlKey && e.which === 46)
                {
                    // Removes current item

                    tr.prev().find('.col1').trigger("click");

                    removeItem(tr);
                }
                // TAB
                else if (e.which === 9)
                {
                    // Go to next/previous column
                    e.preventDefault();

                    tr.find('.col' + col + ' :input').trigger("blur");

                    // + SHIFT
                    var obj;
                    if (e.shiftKey)
                    {
                        // Previous
                        obj = prevCol({tr: tr, col: col});
                    }
                    else
                    {
                        // Next
                        obj = nextCol({tr: tr, col: col});
                    }
                    obj.tr.find('td.col' + obj.col).trigger("click");
                }
            }
        });

        // Item control functionality
        $('#addDraftItem').on("click", function(e)
        {
            e.preventDefault();
            createDraftItem();
        });
        $('#itemControls .clear').on("click", function(e)
        {
            e.preventDefault();
            clearTable();
        });

        // Button functionality
        $('#toggleDraftScreen').on("click", function()
        {
            $('#draftScreen').show();
            $('#validationReport').hide();
            $('#tabDock').show();
        });
    });

    // Utils

    // SHIFT + TAB function while editing draft
    function prevCol(obj)
    {
        obj.col -= 1;
        if (obj.col < 1)
        {
            var prev = obj.tr.prev();
            if (prev.length === 0)
            {
                obj.col = 1;
                return obj;
            }
            obj.tr = prev;
            obj.col = maxCols;
        }
        var field = obj.tr.find('.col' + obj.col);
        // recursion to skip cols that are disabled or contain a select element
        if (field.hasClass("disabled") || field.find("select").length > 0)
            obj = prevCol(obj);

        return obj;
    }

    // TAB function while editing draft
    function nextCol(obj)
    {
        obj.col += 1;
        if (obj.col > maxCols)
        {
            var next = obj.tr.next();
            if (next.length === 0)
            {
                obj.tr = createDraftItem();
            }
            else
            {
                obj.tr = next;
            }
            obj.col = 0;
        }
        var field = obj.tr.find('.col' + obj.col);
        // recursion to skip cols that are disabled or contain a select element
        if (field.hasClass("disabled") || field.find("select").length > 0)
            obj = nextCol(obj);

        return obj;
    }

    // String max length trimmer
    String.prototype.trimToLength = function(m)
    {
        if (this.length > m)
        {
            return jQuery.trim(this).substring(0, m)
                .split(" ").slice(0, -1).join(" ") + "...";
        }
        return this;
    };

    // Dynamically style the table depending on the amount of properties
    function styleTableSpacing()
    {
        var wt = $('#content').width(),
            w0 = 45 / wt * 100,
            wh = 35 / wt * 100,
            wp = w0 + wh,
            w = (100 - wp) / (itemProperties.length - 1),
            style = "#draftTable td,#draftTable th{width:" + w + "%}";
        style += " #draftTable td.col0,#draftTable th.col0{width:" + w0 +
            "%;} ";
        style +=
            " #draftTable td.dragHandle,#draftTable th.dragHandle{width:" +
            wh + "%;}";

        $('#draftStyle').append(style);
    }

    // Creating an empty draft item and adding it to the table
    // Returns the item as an object
    function createDraftItem(ignore)
    {
        var item = {
            properties: {},
            toHtml: function()
            {
                var i, p, e,
                    html = '
';
                html += '::::::	';

                for (i = 0; i < itemProperties.length; i += 1)
                {
                    p = itemProperties[i];
                    e = propEditors[p] === undefined ?
                        propEditors.fallback : propEditors[p];

                    if (e.indexOf('<select') !== -1)
                    {
                        html += '' + e + '	';
                    }
                    else
                    {
                        html += '' + this.properties[
                                p] + '';
                        html +=
                            '' +
                            e + '	';
                    }
                }

                return html + "
";
            }
        };

        itemProperties.forEach(function(p)
        {
            item.properties[p] = "";
        });

        item.properties.type = "player";

        var tr = $(item.toHtml());
        tr.data('item', item);
        $('#draftTable').append(tr);

        if (!ignore)
        {
            tr.find('.col1').trigger("click");
        }

        return tr;
    }

    // Clear the table and remove all items
    function clearTable()
    {
        if (!confirm(i18next.t('draft:delete_all_confirm')))
        {
            return;
        }

        $('#draftTable tr.draftItem').remove();
        createDraftItem();
    }

    function saveOnBlur(input)
    {
        var tr = $(input).closest('tr'),
            item = tr.data('item'),
            property = input.parents('td').attr("class").split(" ")[0],
            value = input.val(),
            valueView = input.parent().siblings('.value');
        item.properties[property] = value;
        valueView.text(value);
        input.parent().hide();
        valueView.show();

        editing = null;
        editingCol = -1;
    }

    function removeItem(tr)
    {
        tr.remove();

        if ($('#draftTable tr.draftItem').length === 0)
        {
            createDraftItem(true);
        }
    }

    function itemToNode(tr)
    {
        if (isItemEmpty(tr)) return;

        var props = tr.data('item').properties,
            node = Main.addNewNode(props.type);

        if (node === null)
        {
            // A tree container must be open.
            console.error("Item to node failed.");
            return;
        }
        // deselect the node before making changes in the object
        // (otherwise chages will be oversaved with empty values)
        Main.selectElement(null);
        node.text = props.statement;

        // make sure the starting input-text equals current saved node.text
        var nodeDiv = $("#"+node.id);
        var inputText = nodeDiv.find(".nodestatement");
        inputText.val(node.text);
        Main.changeNodeText(node.id);
        Main.selectElement(node.id);

        removeItem(tr);
        return node;
    }

    function allItemsToNodes()
    {
        var nodes = [];
        $('#draftTable .draftItem').each(function()
        {
            if (!isItemEmpty($(this)))
            {
                nodes.push(itemToNode($(this)));
            }
        });
        return nodes;
    }
    function allIsEmpty()
    {
        var allEmpty = true;
        $('#draftTable .draftItem').each(function()
        {
            allEmpty = allEmpty && isItemEmpty($(this));
        });
        return allEmpty;
    }

    function isItemEmpty(tr)
    {
        var props = tr.data('item').properties;
        for (var p in props)
        {
            if (props.hasOwnProperty(p) && p !== "type" && props[p] !== "")
            {
                return false;
            }
        }
        return true;
    }
}());
<|endoftext|>