/* Minification failed. Returning unminified contents.
(3644,50-57): run-time error JS1137: 'default' is a new reserved word and should not be used as an identifier: default
(3664,50-57): run-time error JS1137: 'default' is a new reserved word and should not be used as an identifier: default
(3862,52-59): run-time error JS1137: 'default' is a new reserved word and should not be used as an identifier: default
(3875,62-69): run-time error JS1137: 'default' is a new reserved word and should not be used as an identifier: default
(3929,21-28): run-time error JS1137: 'default' is a new reserved word and should not be used as an identifier: default
 */
$(function ($) {
  $('.primary-menu-select select').on('change', function () {
    if (this.value !== '') { document.location.href = this.value }
  });

  $('.primary-menu-select select')[0].selectedIndex = 0;
});;
/*
    json2.js
    2013-05-26

    Public Domain.

    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

    See http://www.JSON.org/js.html


    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html

    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.


    This file creates a global JSON object containing two methods: stringify
    and parse.

        JSON.stringify(value, replacer, space)
            value       any JavaScript value, usually an object or array.

            replacer    an optional parameter that determines how object
                        values are stringified for objects. It can be a
                        function or an array of strings.

            space       an optional parameter that specifies the indentation
                        of nested structures. If it is omitted, the text will
                        be packed without extra whitespace. If it is a number,
                        it will specify the number of spaces to indent at each
                        level. If it is a string (such as '\t' or '&nbsp;'),
                        it contains the characters used to indent at each level.

            This method produces a JSON text from a JavaScript value.

            When an object value is found, if the object contains a toJSON
            method, its toJSON method will be called and the result will be
            stringified. A toJSON method does not serialize: it returns the
            value represented by the name/value pair that should be serialized,
            or undefined if nothing should be serialized. The toJSON method
            will be passed the key associated with the value, and this will be
            bound to the value

            For example, this would serialize Dates as ISO strings.

                Date.prototype.toJSON = function (key) {
                    function f(n) {
                        // Format integers to have at least two digits.
                        return n < 10 ? '0' + n : n;
                    }

                    return this.getUTCFullYear()   + '-' +
                         f(this.getUTCMonth() + 1) + '-' +
                         f(this.getUTCDate())      + 'T' +
                         f(this.getUTCHours())     + ':' +
                         f(this.getUTCMinutes())   + ':' +
                         f(this.getUTCSeconds())   + 'Z';
                };

            You can provide an optional replacer method. It will be passed the
            key and value of each member, with this bound to the containing
            object. The value that is returned from your method will be
            serialized. If your method returns undefined, then the member will
            be excluded from the serialization.

            If the replacer parameter is an array of strings, then it will be
            used to select the members to be serialized. It filters the results
            such that only members with keys listed in the replacer array are
            stringified.

            Values that do not have JSON representations, such as undefined or
            functions, will not be serialized. Such values in objects will be
            dropped; in arrays they will be replaced with null. You can use
            a replacer function to replace those with JSON values.
            JSON.stringify(undefined) returns undefined.

            The optional space parameter produces a stringification of the
            value that is filled with line breaks and indentation to make it
            easier to read.

            If the space parameter is a non-empty string, then that string will
            be used for indentation. If the space parameter is a number, then
            the indentation will be that many spaces.

            Example:

            text = JSON.stringify(['e', {pluribus: 'unum'}]);
            // text is '["e",{"pluribus":"unum"}]'


            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'

            text = JSON.stringify([new Date()], function (key, value) {
                return this[key] instanceof Date ?
                    'Date(' + this[key] + ')' : value;
            });
            // text is '["Date(---current time---)"]'


        JSON.parse(text, reviver)
            This method parses a JSON text to produce an object or array.
            It can throw a SyntaxError exception.

            The optional reviver parameter is a function that can filter and
            transform the results. It receives each of the keys and values,
            and its return value is used instead of the original value.
            If it returns what it received, then the structure is not modified.
            If it returns undefined then the member is deleted.

            Example:

            // Parse the text. Values that look like ISO date strings will
            // be converted to Date objects.

            myData = JSON.parse(text, function (key, value) {
                var a;
                if (typeof value === 'string') {
                    a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
                    if (a) {
                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                            +a[5], +a[6]));
                    }
                }
                return value;
            });

            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
                var d;
                if (typeof value === 'string' &&
                        value.slice(0, 5) === 'Date(' &&
                        value.slice(-1) === ')') {
                    d = new Date(value.slice(5, -1));
                    if (d) {
                        return d;
                    }
                }
                return value;
            });


    This is a reference implementation. You are free to copy, modify, or
    redistribute.
*/

/*jslint evil: true, regexp: true */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/


// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (typeof JSON !== 'object') {
  JSON = {};
}

(function () {
  'use strict';

  function f(n) {
    // Format integers to have at least two digits.
    return n < 10 ? '0' + n : n;
  }

  if (typeof Date.prototype.toJSON !== 'function') {

    Date.prototype.toJSON = function () {

      return isFinite(this.valueOf())
          ? this.getUTCFullYear() + '-' +
              f(this.getUTCMonth() + 1) + '-' +
              f(this.getUTCDate()) + 'T' +
              f(this.getUTCHours()) + ':' +
              f(this.getUTCMinutes()) + ':' +
              f(this.getUTCSeconds()) + 'Z'
          : null;
    };

    String.prototype.toJSON =
        Number.prototype.toJSON =
        Boolean.prototype.toJSON = function () {
          return this.valueOf();
        };
  }

  var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
      escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
      gap,
      indent,
      meta = {    // table of character substitutions
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"': '\\"',
        '\\': '\\\\'
      },
      rep;


  function quote(string) {

    // If the string contains no control characters, no quote characters, and no
    // backslash characters, then we can safely slap some quotes around it.
    // Otherwise we must also replace the offending characters with safe escape
    // sequences.

    escapable.lastIndex = 0;
    return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
      var c = meta[a];
      return typeof c === 'string'
          ? c
          : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
    }) + '"' : '"' + string + '"';
  }


  function str(key, holder) {

    // Produce a string from holder[key].

    var i,          // The loop counter.
        k,          // The member key.
        v,          // The member value.
        length,
        mind = gap,
        partial,
        value = holder[key];

    // If the value has a toJSON method, call it to obtain a replacement value.

    if (value && typeof value === 'object' &&
            typeof value.toJSON === 'function') {
      value = value.toJSON(key);
    }

    // If we were called with a replacer function, then call the replacer to
    // obtain a replacement value.

    if (typeof rep === 'function') {
      value = rep.call(holder, key, value);
    }

    // What happens next depends on the value's type.

    switch (typeof value) {
      case 'string':
        return quote(value);

      case 'number':

        // JSON numbers must be finite. Encode non-finite numbers as null.

        return isFinite(value) ? String(value) : 'null';

      case 'boolean':
      case 'null':

        // If the value is a boolean or null, convert it to a string. Note:
        // typeof null does not produce 'null'. The case is included here in
        // the remote chance that this gets fixed someday.

        return String(value);

        // If the type is 'object', we might be dealing with an object or an array or
        // null.

      case 'object':

        // Due to a specification blunder in ECMAScript, typeof null is 'object',
        // so watch out for that case.

        if (!value) {
          return 'null';
        }

        // Make an array to hold the partial results of stringifying this object value.

        gap += indent;
        partial = [];

        // Is the value an array?

        if (Object.prototype.toString.apply(value) === '[object Array]') {

          // The value is an array. Stringify every element. Use null as a placeholder
          // for non-JSON values.

          length = value.length;
          for (i = 0; i < length; i += 1) {
            partial[i] = str(i, value) || 'null';
          }

          // Join all of the elements together, separated with commas, and wrap them in
          // brackets.

          v = partial.length === 0
              ? '[]'
              : gap
              ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
              : '[' + partial.join(',') + ']';
          gap = mind;
          return v;
        }

        // If the replacer is an array, use it to select the members to be stringified.

        if (rep && typeof rep === 'object') {
          length = rep.length;
          for (i = 0; i < length; i += 1) {
            if (typeof rep[i] === 'string') {
              k = rep[i];
              v = str(k, value);
              if (v) {
                partial.push(quote(k) + (gap ? ': ' : ':') + v);
              }
            }
          }
        } else {

          // Otherwise, iterate through all of the keys in the object.

          for (k in value) {
            if (Object.prototype.hasOwnProperty.call(value, k)) {
              v = str(k, value);
              if (v) {
                partial.push(quote(k) + (gap ? ': ' : ':') + v);
              }
            }
          }
        }

        // Join all of the member texts together, separated with commas,
        // and wrap them in braces.

        v = partial.length === 0
            ? '{}'
            : gap
            ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
            : '{' + partial.join(',') + '}';
        gap = mind;
        return v;
    }
  }

  // If the JSON object does not yet have a stringify method, give it one.

  if (typeof JSON.stringify !== 'function') {
    JSON.stringify = function (value, replacer, space) {

      // The stringify method takes a value and an optional replacer, and an optional
      // space parameter, and returns a JSON text. The replacer can be a function
      // that can replace values, or an array of strings that will select the keys.
      // A default replacer method can be provided. Use of the space parameter can
      // produce text that is more easily readable.

      var i;
      gap = '';
      indent = '';

      // If the space parameter is a number, make an indent string containing that
      // many spaces.

      if (typeof space === 'number') {
        for (i = 0; i < space; i += 1) {
          indent += ' ';
        }

        // If the space parameter is a string, it will be used as the indent string.

      } else if (typeof space === 'string') {
        indent = space;
      }

      // If there is a replacer, it must be a function or an array.
      // Otherwise, throw an error.

      rep = replacer;
      if (replacer && typeof replacer !== 'function' &&
              (typeof replacer !== 'object' ||
              typeof replacer.length !== 'number')) {
        throw new Error('JSON.stringify');
      }

      // Make a fake root object containing our value under the key of ''.
      // Return the result of stringifying the value.

      return str('', { '': value });
    };
  }


  // If the JSON object does not yet have a parse method, give it one.

  if (typeof JSON.parse !== 'function') {
    JSON.parse = function (text, reviver) {

      // The parse method takes a text and an optional reviver function, and returns
      // a JavaScript value if the text is a valid JSON text.

      var j;

      function walk(holder, key) {

        // The walk method is used to recursively walk the resulting structure so
        // that modifications can be made.

        var k, v, value = holder[key];
        if (value && typeof value === 'object') {
          for (k in value) {
            if (Object.prototype.hasOwnProperty.call(value, k)) {
              v = walk(value, k);
              if (v !== undefined) {
                value[k] = v;
              } else {
                delete value[k];
              }
            }
          }
        }
        return reviver.call(holder, key, value);
      }


      // Parsing happens in four stages. In the first stage, we replace certain
      // Unicode characters with escape sequences. JavaScript handles many characters
      // incorrectly, either silently deleting them, or treating them as line endings.

      text = String(text);
      cx.lastIndex = 0;
      if (cx.test(text)) {
        text = text.replace(cx, function (a) {
          return '\\u' +
              ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        });
      }

      // In the second stage, we run the text against regular expressions that look
      // for non-JSON patterns. We are especially concerned with '()' and 'new'
      // because they can cause invocation, and '=' because it can cause mutation.
      // But just to be safe, we want to reject all unexpected forms.

      // We split the second stage into 4 regexp operations in order to work around
      // crippling inefficiencies in IE's and Safari's regexp engines. First we
      // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
      // replace all simple value tokens with ']' characters. Third, we delete all
      // open brackets that follow a colon or comma or that begin the text. Finally,
      // we look to see that the remaining characters are only whitespace or ']' or
      // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

      if (/^[\],:{}\s]*$/
              .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
                  .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
                  .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

        // In the third stage we use the eval function to compile the text into a
        // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
        // in JavaScript: it can begin a block or an object literal. We wrap the text
        // in parens to eliminate the ambiguity.

        j = eval('(' + text + ')');

        // In the optional fourth stage, we recursively walk the new structure, passing
        // each name/value pair to a reviver function for possible transformation.

        return typeof reviver === 'function'
            ? walk({ '': j }, '')
            : j;
      }

      // If the text is not JSON parseable, then a SyntaxError is thrown.

      throw new SyntaxError('JSON.parse');
    };
  }
}());
;
(function (tecit, $) {

  tecit.log = function (args) {
    if (typeof console !== 'undefined' && typeof console.log !== 'undefined') {
      console.log(args);
    }
  };

  tecit.error = function (args) {
    if (typeof console !== 'undefined' && typeof console.error !== 'undefined') {
      console.error(args);
    }
  };

  tecit.ParseDynamicValidation = function (element) {
    // reparse jQuery page validation for dynamic content
    try {
      $.validator.unobtrusive.parseDynamicContent(element);
    } catch (e) {
      tecit.log('Error parsing dynamic validation content.\n' + e);
    }
  };
  
  function buildFunction(widget, options) {
    var context = options[widget],
        fn;

    if (!context) {
      tecit.log('Attempted to create a helper for ' + widget + ' but the widget was not found in the options.');
      return;
    }

    fn = context[widget];
    return function () {
      var result = fn.apply(context, arguments);
      return result;
    };
  }

  // The preferred means of invoking public methods on a widget stored in options 
  // results in the awkward syntax: this.options.widget.widget('methodToInvoke')
  // Here we setup a set of helper methods to make the meaning of the code more
  // clear in general. Additionally, all of the complexity of invoking the widget
  // methods is located here, so there is less chance of errors at the site
  // where we consume this generated api.
  // The new syntax is: this._widget('methodToInvoke')
  tecit.setupWidgetInvocationMethods = function (host, options, widgetNames) {
    var i,
        widgetName;

    for (i = widgetNames.length - 1; i >= 0; i -= 1) {
      widgetName = widgetNames[i];
      host["_" + widgetName] = buildFunction(widgetName, options);
    }
  };


  tecit.getAttributes = function (element, startsWith){
    var i, aLength, attributes, map;
  
    map = {};
    attributes = element[0].attributes;
    aLength = attributes.length;
    for (i = 0; i < aLength; i++) {
      if (attributes[i].name.startsWith (startsWith))
        map[attributes[i].name.replace(startsWith, '')] = attributes[i].value;
    }
    return map;
  };

  String.prototype.startsWith = function (prefix) {
    return this.indexOf(prefix) === 0;
  };

  String.prototype.endsWith = function (suffix) {
    return this.match(suffix + "$") == suffix;
  };

  jQuery.fn.insertAt = function (index, parent) {
    var lastIndex = parent.children().length - 1;
    if (index < 0) {
      index = Math.max(0, lastIndex + 1 + index);
    }
    this.appendTo(parent);
    if (index < lastIndex) {
      parent.children().eq(index).before(parent.children().last());
    }
    return this;
  };

  // ----------------------------------------------
  // Scroll container to display this element
  // ----------------------------------------------
  $.fn.makeVisible = function (options) {

    if (this.length) {

      // element is document
      if (this.is(document))
        return this;

      // element is hidden
      if (!this.is(':visible'))
        return this;

      //set default options
      if (options === undefined)
        options = { animation: { 'duration': 400, 'easing': 'linear' }, offset: 0 };

      var container = this.scrollParent();  // element container to scroll

      if (!container.length)
        return this;


      // element position vars
      var nodeTop = this.offset().top;  // element top position relative to documnet
      var nodeHeight = this.height();   // element height

      // container position vars
      var containerTop = 0, containerHeight = 0, containerScroll = 0;
      var hidden = false;
      var scrollTo = 0;

      // scrollWindow if scrollParent is document
      if (container.is(document)) {
        // use body as container to allow scroll
        container = $('html, body');
        hidden = hidden | !isScrolledIntoView(this)
        scrollTo = nodeTop + options.offset;
      }
      else if (container.offset()) {
        //ensure container is visible
        //container.makeVisible();
        // get container position values
        containerTop = container.offset().top;    // distance to document top
        containerHeight = container.height();     // container height
        containerScroll = container.scrollTop();  // current scroll position

        hidden = hidden | (nodeTop < containerTop); // above viewport
        hidden = hidden | ((nodeTop + nodeHeight) > (containerTop + containerHeight)); // below viewport

        scrollTo = nodeTop - containerTop + containerScroll + options.offset;
      }
      else
        return this; // ?? no sense ??

      if (hidden) {
        container.animate({ scrollTop: scrollTo }, options.animation);
      }

    }
    return this;
  };

  // ----------------------------------------------
  // Checks if the elment is visible in the viewport
  // ----------------------------------------------
  function isScrolledIntoView(elem) {
    var $elem = $(elem);
    var $window = $(window);

    var docViewTop = $window.scrollTop();
    var docViewBottom = docViewTop + $window.height();

    var elemTop = $elem.offset().top;
    var elemBottom = elemTop + $elem.height();

    //return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); // any part visible
    return ((docViewTop < elemTop) && (docViewBottom > elemBottom)); // entirely visible
  }

  // ----------------------------------------------
  // adds js tooltips using title attributes of elements with the add-tooltip class
  // ----------------------------------------------
  tecit.tooltips_init = function () {
    var tt_id = 1;
    jQuery('.add-tooltip').each(function () {
      var title = jQuery(this).attr('title');
      if (typeof (title) == 'undefined')
        return;
      jQuery(this).data('tooltip_id', tt_id);

      jQuery(this).mouseenter(function () {
        jQuery(this).attr('title', '');
        var id = jQuery(this).data('tooltip_id');
        var $tt = jQuery('#tooltip_' + id).stop();
        if (!$tt.length) {
          var tipstyle = jQuery(this).attr('tipstyle');
          if (typeof (tipstyle) != 'undefined') {
            tipstyle = ' style="' + tipstyle + '" ';
          }
          var tipclass = jQuery(this).attr('tipclass');
          var pos = jQuery(this).offset();
          $tt = jQuery('<div class="tooltip ' + tipclass + '" id="tooltip_' + id + '"' + tipstyle + '>' + title + '</div>');
          $tt.appendTo('body');
          var left = pos.left + Math.round(jQuery(this).outerWidth() / 2);
          if ((left + $tt.innerWidth()) > window.innerWidth)
            left = window.innerWidth - $tt.innerWidth();
            
          $tt.css('left', left);
          $tt.css('top', pos.top - $tt.outerHeight());
        }
        $tt.show();
        $tt.animate({ opacity: 1, marginTop: '-6px' }, 200);
      });

      jQuery(this).mouseleave(function () {
        jQuery(this).attr('title', title);
        var id = jQuery(this).data('tooltip_id');
        jQuery('#tooltip_' + id).stop().animate({ opacity: 0, marginTop: '-15px' }, 200, function () {
          jQuery(this).remove();
        });
      });

      tt_id++;
    });
  }

}(this.tecit = this.tecit || {}, jQuery));;
(function ($) {

  // Singleton used for settings used accross all instances
  function Timepicker() {
    this.regional = [];
    this.regional[''] = {
      cancelCaption: 'Cancel',
      nowCaption: 'Now',
      doneCaption: 'Set',
      headerCaption: 'Pick a Time',
      hoursCaption: 'Hours',
      minutesCaption: 'Minutes',
      secondsCaption: 'Seconds'
    };
    this._defaults = {};
    
    this.setDefaults = function(settings) {
  		$.extend(this._defaults, settings || {});
  		return this;
  	}
    
    this.setDefaults(this.regional['']);
  }
  
  $.timepicker = new Timepicker(); // singleton instance

  // create timepicker widget 
  $.widget("tecit.timepicker", {
    options: {
      inlineClassName: "tecit-timepicker-inline",
      field: null,
      hideAfterDone: false,
      hideAfterNow: false,
      culture: null
    },

    wrapper: null,
    hourSpinner: null,
    minuteSpinner: null,
    secondSpinner: null,

    // called on creation of widget
    _create: function () {
      var that = this;

      var buttonPane = $('<div class="buttonPane"><div></div></div>');
      $('<a class="tpCancelButton grayButton" title="' + this._getRegional().cancelCaption + '">' + this._getRegional().cancelCaption + '</a>').on('click', function () {
        that.element.hide();
      }).appendTo(buttonPane);
      $('<a class="tpNowButton redButton" title="' + this._getRegional().nowCaption + '">' + this._getRegional().nowCaption + '</a>').on('click', function () {
        that.setTimeNow();
        //check if the picker should be hidden after clicking Now
        if (that.options.hideAfterNow)
        {
          that.transferToField();
          that.element.hide();
        }
      }).appendTo(buttonPane.find('> div'));
      $('<a class="tpDoneButton redButton" title="' + this._getRegional().doneCaption + '">' + this._getRegional().doneCaption + '</a>').on('click', function () {
        that.transferToField();
        //check if the picker should be hidden after clicking Done
        if (that.options.hideAfterDone)
          that.element.hide();
      }).appendTo(buttonPane.find('> div'));

      this.wrapper = $('<div class="' + this.options.inlineClassName + '"></div>')
        .append('<h3 class="caption">' + this._getRegional().headerCaption + '</h3>')
        .append('<label for="pickerHours">' + this._getRegional().hoursCaption + '</label>')
        .append('<input id="pickerHours" type="text" class="hours" />')
        .append('<label for="pickerMinutes">' + this._getRegional().minutesCaption + '</label>')
        .append('<input id="pickerMinutes" type="text" class="minutes" />')
        .append('<label for="pickerSeconds">' + this._getRegional().secondsCaption + '</label>')
        .append('<input id="pickerSeconds" type="text" class="seconds" />')
        .append(buttonPane)
        .appendTo(this.element);
      
      // initialize spinner controls
      this.hourSpinner = this.element.find('input.hours').spinner({
        numberFormat: 'd2',
        spin: this._hourOverflowSpin,
        change: this._sanitizeInput
      });
      this.minuteSpinner = this.element.find('input.minutes').spinner({
        numberFormat: 'd2',
        spin: this._minuteSecondOverflowSpin,
        change: this._sanitizeInput
      });
      this.secondSpinner = this.element.find('input.seconds').spinner({
        numberFormat: 'd2',
        spin: this._minuteSecondOverflowSpin,
        change: this._sanitizeInput
      });

      // replace default spinner icons with "+" and "-"
      this.element.find('.ui-spinner-up > span > span').removeClass('ui-icon').html('+');
      this.element.find('.ui-spinner-down > span > span').removeClass('ui-icon').html('-');

      // fix generated html of the spinners to help with css positioning
      this.element.find('.ui-spinner').addClass('clearfix').removeAttr('style');
      this.element.find('.ui-spinner-button').addClass('grayButton');
      this.element.find('.ui-spinner input').wrap('<div class="inputWrap"></div>');
    },

    setTime: function (time) {
      var splits = time.split(':');

      this.hourSpinner.spinner('value', splits[0]);
      this.minuteSpinner.spinner('value', splits[1]);
      this.secondSpinner.spinner('value', splits[2]);
    },

    setTimeNow: function () {
      var time = new Date();
      this.setTime(time.getHours() + ':' + time.getMinutes() + ':' + time.getSeconds());
    },

    getTime: function () {
      return this.hourSpinner.val() + ':' + this.minuteSpinner.val() + ':' + this.secondSpinner.val();
    },

    transferToField: function () {
      if (this.options.field !== null) {
        $(this.options.field).val(this.getTime()).change();
      }      
    },

    setCaption: function (text) {
      this.element.find('.caption').html(text);
    },

    // private functions

    _sanitizeInput: function () {
      var value = $(this).spinner('value');

      if (!$.isNumeric(value) || value < 0)
        $(this).spinner('value', 0);

      if ($(this).hasClass('hours') && value > 23)
        $(this).spinner('value', 23);

      if ($(this).is('.minutes, .seconds') && value > 59)
        $(this).spinner('value', 59);
    },
    
    // called automatically when unloading
    _destroy: function () {
      this.hourSpinner.spinner("destroy");
      this.minuteSpinner.spinner("destroy");
      this.secondSpinner.spinner("destroy");

      this.wrapper.remove();
    },

    _hourOverflowSpin: function (event, ui) {
      if (ui.value > 23) {
        $(this).spinner("value", 0);
        return false;
      } else if (ui.value < 0) {
        $(this).spinner("value", 23);
        return false;
      }
    },

    _minuteSecondOverflowSpin: function (event, ui) {
      if (ui.value > 59) {
        $(this).spinner("value", 0);
        return false;
      } else if (ui.value < 0) {
        $(this).spinner("value", 59);
        return false;
      }
    },
    
    // returns regional settings based on culture option, defaulting if nothing found
    _getRegional: function () {
      return $.timepicker.regional[this.options.culture] !== undefined ?
         $.timepicker.regional[this.options.culture] : $.timepicker._defaults;
    }
  });
}(jQuery));;
(function (tecit, $) {

  // create widget named barcode
  $.widget('tecit.barcode', {

    options: {
      // url to the barcode mvc app
      baseUrl: null,
      raiseError: function (message) {
        tecit.error('Error in barcode widget:\n' + message);
      },
      barcodeUpdated: null,
      loadDataOnStartup: false
    },

    qrCode: {
      data: {
        // default values
        //datatype: 'Raw'
      },
      settings: {},
      output: {
        method: 'Base64'
      }
    },

    // called on creation of widget
    _create: function () {
      // create the barcode image tag
      if (this.element.find('img').length > 0)
        this.imageElement = this.element.find('img');
      else {
        this.imageElement = $('<img />');
        this.imageElement.appendTo(this.element);
      }

      if (this.options.loadDataOnStartup) {
        this._initData();
        this._initSettings();

        this.updateBarcode();
      }
    },

    // gets internal qrCode object
    getQRCode: function () {
      return this.qrCode;
    },

    // sets the settings of the internal qrCode object and updates the barcode
    setQRCodeSettings: function (settings, updateBarcode) {
      if (settings !== undefined) {
        $.extend(this.qrCode.settings, settings);

        if (updateBarcode || updateBarcode === undefined)
          this.updateBarcode();
      }
    },

    // sets the data of the internal qrCode object and updates the barcode
    setQRCodeData: function (data, updateBarcode) {
      if (data !== undefined) {
        $.extend(this.qrCode.data, data);

        if (updateBarcode || updateBarcode === undefined)
          this.updateBarcode();
      }
    },

    // private method to initialize barcode data from html data- attributes
    _initData: function () {
      // read complete json object from data-data and override with explicit set attributes
      $.extend(this.qrCode.data, this.element.data('data'));
      $.extend(this.qrCode.data, tecit.getAttributes(this.element, 'data-data-'));
    },

    // private method to initialize barcode settings from html data- attributes
    _initSettings: function () {
      // read complete json object from data-settings and override with explicit set attributes
      $.extend(this.qrCode.settings, this.element.data('settings'));
      $.extend(this.qrCode.settings, tecit.getAttributes(this.element, 'data-settings-'));
    },

    // called automatically when unloading
    _destroy: function () {
      // remove image tag created in _create()
      this.imageElement.remove();
    },

    // called when changing anything in this.options
    _setOption: function (key) {
      $.Widget.prototype._setOption.apply(this, arguments);

      if (key === 'baseUrl')
        this.updateBarcode();
    },

    updateBarcode: function () {
      var that = this;
      
      $.ajax({
        url: this.options.baseUrl,
        type: 'POST',
        data: this.buildQueryParameters() + '&base64=true',
        //contentType: 'application/json',
        success: function (data, status, response) {
          var mime = response.getResponseHeader('X-Mime-Type');
          that.imageElement.attr('src', 'data:' + mime + ';base64,' + data);
          that._trigger('barcodeUpdated', null,
            {
              imageUrl: that.options.baseUrl + '?' + that.buildQueryParameters(),
              pageUrl: that.element[0].baseURI + '/' + that.qrCode.data.datatype + '?' + that.buildQueryPageParameters()
            });
        },
        error: function (response, status, error) {
          try {
            var responseJson = JSON.parse(response.responseText);

            if (responseJson.ExceptionMessage !== undefined)
              that.options.raiseError(responseJson.ExceptionMessage);
            else if (responseJson.Message !== undefined)
              that.options.raiseError(responseJson.Message);
            else
              that.options.raiseError('get from ' + that.options.baseUrl + ' failed');
          }
          catch (error) {
            that.options.raiseError('get from ' + that.options.baseUrl + ' failed');
          }
        }
      });
    },

    downloadBarcode: function () {
      var that = this;
      var responseType = 'blob';

      if (that.isDownloadTypeTextBased())
        responseType = 'text';

      $.ajax({
        url: this.options.baseUrl,
        type: 'POST',
        data: this.buildQueryParameters() + '&download=true',
        xhrFields: {
          // this need to be set to blob for binary image formats, otherwise the arriving bytes will be string encoded and garbled
          responseType: responseType
        },
        success: function (response, status, xhr) {
          if (that.isDownloadTypeTextBased())
            response = xhr.responseText;

          var filename = "";
          var disposition = xhr.getResponseHeader('Content-Disposition');
          if (disposition && disposition.indexOf('attachment') !== -1) {
            var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
            var matches = filenameRegex.exec(disposition);
            if (matches !== null && matches[1]) filename = matches[1].replace(/['"]/g, '');
          }
          var type = xhr.getResponseHeader('Content-Type');

          var blob;
          if (typeof File === 'function') {
            try {
              blob = new File([response], filename, { type: type });
            } catch (e) { /* Edge */ }
          }
          if (typeof blob === 'undefined') {
            blob = new Blob([response], { type: type });
          }

          if (typeof window.navigator.msSaveBlob !== 'undefined') {
            // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
            window.navigator.msSaveBlob(blob, filename);
          } else {
            var URL = window.URL || window.webkitURL;
            var downloadUrl = URL.createObjectURL(blob);

            if (filename) {
              // use HTML5 a[download] attribute to specify filename
              var a = document.createElement("a");
              // safari doesn't support this yet
              if (typeof a.download === 'undefined') {
                window.location = downloadUrl;
              } else {
                a.href = downloadUrl;
                a.download = filename;
                a.click();
              }
            } else {
              window.location = downloadUrl;
            }

            setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
          }
        },
        error: function (response, status, error) {
          try {
            var responseJson = JSON.parse(response.responseText);

            if (responseJson.ExceptionMessage !== undefined)
              that.options.raiseError(responseJson.ExceptionMessage);
            else if (responseJson.Message !== undefined)
              that.options.raiseError(responseJson.Message);
            else
              that.options.raiseError('get from ' + that.options.baseUrl + ' failed');
          }
          catch (error) {
            that.options.raiseError('get from ' + that.options.baseUrl + ' failed');
          }
        }
      });
    },

    buildQueryParameters: function () {
      var params = $.param(this.qrCode.data) + '&' + $.param(this.qrCode.settings);

      params = params.replace('datatype=', 'code=').replace('NaN', '').replace('Degree', '');

      return params;
    },

    buildQueryPageParameters: function () {

      var pageData = {
        data: this.qrCode.data.data,
        multiplebarcodes: this.qrCode.data.multiplebarcodes,
        'translate-esc': this.qrCode.data["translate-esc"]
      };

      var params = $.param(pageData) + '&' + $.param(this.qrCode.settings);

      params = params.replace('NaN', '').replace('Degree', '');

      return params;
    },

    isDownloadTypeTextBased: function () {
      // multiplebarcodes always generates a zip file
      if (this.qrCode.data.multiplebarcodes)
        return false;

       // if we include more text based image types add them here as well
     return this.qrCode.settings.imagetype === 'Svg';
    }

  });
}(this.tecit = this.tecit || {}, jQuery));;
(function (tecit, $) {

  // create widget named barcodeSettings
  $.widget("tecit.barcodeSettings", {
    options: {
      // base url of the generator web service
      baseUrl: null,
      // callback that is triggered after anything has changed in the form
      settingsChanged: function (settings) {
        tecit.log("No handler for settingsChanged set!");
      },
      // settings to be selected on the first load
      defaultSettings: null,
      // prefix to be filtered out of child input names
      idPrefix: null,
      // callback that is triggered after the form was successfully requested from the server
      formChanged: null,
      // triggers creaton of show/hideable wrapper div
      hideable: false,
      // event that is triggered after the widget was created; provides settingsObject as data
      widgetCreated: null
    },

    // called on creation of widget
    _create: function () {
      var that = this;

      if (this.options.hideable) {
        var wrapper = this.element.children().filter(':not(.head)').wrapAll('<div class="wrapper" />').parent().hide();
        var toggle = this.element.find('.head').addClass('toggle');
        if (!toggle.length)
          toggle = $('<div class="toggle"></div>');

        toggle.prependTo(this.element).on('click', function (e) {
          e.preventDefault();
          wrapper.toggle('slide');
          $(this).toggleClass('open');
        });
      }

      // fill with default values
      if (this.options.defaultSettings !== null)
        this.setSettingsObject(this.options.defaultSettings);

      if ($.trim(this.element.html()) === '')
        this.updateForm();

      this._bindChangeEvent();

      this._trigger('widgetCreated', null, this.getSettingsObject());
    },

    // builds a settings object from all input fields in the settings div
    getSettingsObject: function () {
      var that = this;
      var settings = {};

      this.element.find(":input[name]:not(.nonData):enabled").each(function () {
        var element = $(this);
        var settingName = element.attr("name").replace(that.options.idPrefix, "").toLowerCase();

        if (!(settingName in settings)) {
          if (element.is(':checkbox'))
            settings[settingName] = element.prop('checked');
          else if (element.is('[type="datetime"]')) {
            // parse the entered date with the current culture and format it for the server
            if (typeof (Globalize) === 'function'
              && typeof (Globalize.parseDate) === 'function'
              && typeof (Globalize.format) === 'function')
              settings[settingName] = Globalize.format(Globalize.parseDate(element.val()), 'MM.dd.yyyy HH:mm:ss');
            else
              settings[settingName] = element.val();
          }
          else if (element.is('[data-val-number]')) {
            if (typeof (Globalize) === 'function'
              && typeof (Globalize.parseFloat) === 'function')
              settings[settingName] = Globalize.parseFloat(element.val());
            else
              settings[settingName] = element.val();
          }
          else
            settings[settingName] = element.val();
        }
      });

      return settings;
    },

    // builds a settings object from all input fields in the settings div
    setSettingsObject: function (settings) {
      var that = this;

      $.each(settings, function (key, value) {
        var element = that.element.find(':input').filter(function () {
          return this.id.toLowerCase().endsWith(key);
        });

        if (element.is(':checkbox'))
          element.prop('checked', value);
        else
          element.val(value);
      });
    },

    updateForm: function (parameter, complete) {
      if (this.options.baseUrl === null) {
        tecit.log('No baseUrl to retrieve settingsForm from specified');
        return;
      }

      var that = this;
      var url = this.options.baseUrl;

      if (parameter !== undefined)
        url += '/' + parameter;

      $.get(url, null, function (data) {
        that.element.html(data);

        // reparse jQuery page validation for dynamic content
        tecit.ParseDynamicValidation(that.element);

        that._trigger('formChanged');
        that.options.settingsChanged(that.getSettingsObject());

        // execute callback
        if (complete && typeof (complete) === 'function') {
          complete();
        }
      });
    },

    triggerSettingsChanged: function () {
      var that = this;
      that.options.settingsChanged(that.getSettingsObject());
    },

    // called when changing anything in this.options
    _setOption: function () {
      $.Widget.prototype._setOption.apply(this, arguments);
    },

    // called automatically when unloading
    _destroy: function () {
      this.element.off(".barcodeSettings");
    },

    _bindChangeEvent: function () {
      var that = this;

      this.element.on("change.barcodeSettings", ":input[name]:not(:hidden):not(.nonData)", function () {
        that.options.settingsChanged(that.getSettingsObject());
      });
    }
  });
}(this.tecit = this.tecit || {}, jQuery));;
(function (tecit, $) {

  // create widget named barcodeSettings
  $.widget("tecit.barcodeSettingsOverride", $.tecit.barcodeSettings, {

    // builds a settings object from all input fields in the settings div
    getSettingsObject: function () {
      var that = this;
      // call base function
      var settings = this._super();

      if (settings.datatype.endsWith("_Events"))
        settings.data = this._getEventData(settings);
      else if (settings.datatype.endsWith("_Wifi"))
        settings.data = this._getWifiData(settings);
      else if (settings.datatype.endsWith("_vCard"))
        settings.data = this._getVCardData(settings);
      else if (settings.datatype.endsWith("_meCard"))
        settings.data = this._getMeCardData(settings);
      else if (settings.datatype === "EPCQRCode")
        settings.data = this._getSepaData(settings);
      else if (settings.datatype.startsWith("SwissQRCodeV2"))
        settings.data = this._getSwissQRCodeData(settings);
      else if (settings.datatype.startsWith("GS1DigitalLink"))
        settings.data = this._getGS1DigitalLinkData(settings);
      return settings;
    },

    // builds a settings object from all input fields in the settings div
    setSettingsObject: function (settings) {
      var that = this;
      // call base function
      this._super(settings);
    },

    _getEventData: function (settings) {
      var datastring = '';
      var fieldSeparator = '\x0a';

      var summary = settings.summary;
      var location = settings.location;
      var description = settings.description;
      var startdate = Globalize.format(Globalize.parseDate(settings.datestart, 'MM.dd.yyyy HH:mm:ss'), 'yyyyMMdd');
      var starttime = settings.timestart ? settings.timestart : '';
      var enddate = Globalize.format(Globalize.parseDate(settings.dateend, 'MM.dd.yyyy HH:mm:ss'), 'yyyyMMdd');
      var endtime = settings.timeend ? settings.timeend : '';

      datastring = 'BEGIN:VEVENT' + fieldSeparator;

      if (summary)
        datastring += 'SUMMARY:' + summary + fieldSeparator;
      if (location)
        datastring += 'LOCATION:' + location + fieldSeparator;
      if (description)
        datastring += 'DESCRIPTION:' + description + fieldSeparator;
      if (startdate) {
        if (starttime)
          starttime = starttime.replace(/:/g, ''); // remove colons
        else
          starttime = '000000';
        datastring += 'DTSTART:' + startdate + 'T' + starttime + fieldSeparator;
      }
      if (enddate) {
        if (endtime)
          endtime = endtime.replace(/:/g, ''); // remove colons
        else
          endtime = '000000';
        datastring += 'DTEND:' + enddate + 'T' + endtime + fieldSeparator;
      }

      datastring += 'END:VEVENT';

      //remove the used properties
      delete settings.summary;
      delete settings.location;
      delete settings.description;
      delete settings.datestart;
      delete settings.timestart;
      delete settings.dateend;
      delete settings.timeend;

      return datastring;
    },

    _getWifiData: function (settings) {

      var datastring = 'WIFI:';
      datastring += 'T:' + settings.authentication + ';';
      datastring += 'S:' + settings.ssid + ';';
      datastring += 'P:' + settings.password + ';';
      datastring += ';';

      //remove the used properties
      delete settings.authentication;
      delete settings.ssid;
      delete settings.password;

      return datastring;
    },

    _getVCardData: function (settings) {
      var datastring = '';
  
      var fieldSeparator = '\x0d\x0a';

      datastring = 'BEGIN:VCARD' + fieldSeparator;
      datastring += 'VERSION:3.0' + fieldSeparator;

      if (settings.name)
        datastring += 'N:' + settings.name + fieldSeparator;
      if (settings.phonenumber)
        datastring += 'TEL;TYPE=HOME,VOICE:' + settings.phonenumber + fieldSeparator;
      if (settings.phonenumberwork)
        datastring += 'TEL;TYPE=WORK,VOICE:' + settings.phonenumberwork + fieldSeparator;
      if (settings.email)
        datastring += 'EMAIL:' + settings.email + fieldSeparator;
      if (settings.organisation)
        datastring += 'ORG:' + settings.organisation + fieldSeparator;
      if (settings.title)
        datastring += 'TITLE:' + settings.title + fieldSeparator;
      if (settings.birthday)
        datastring += 'BDAY:' + Globalize.format(Globalize.parseDate(settings.birthday, 'MM.dd.yyyy HH:mm:ss'), 'yyyyMMdd') + fieldSeparator; /// TODO formatting yyyyMMdd
      if (settings.address)
        datastring += 'ADR:' + settings.address + fieldSeparator;
      if (settings.url)
        datastring += 'URL:' + settings.url + fieldSeparator;

      datastring += 'END:VCARD';

      //remove the used properties
      delete settings.name;
      delete settings.phonenumber;
      delete settings.phonenumberwork;
      delete settings.email;
      delete settings.organisation;
      delete settings.title;
      delete settings.birthday;
      delete settings.address;
      delete settings.url;

      return datastring;
    },

    _getMeCardData: function (settings) {
      var datastring = '';

      var fieldSeparator = ';';

      datastring = 'MECARD:';

      if (settings.memo)
        datastring += 'NOTE:' + settings.memo + fieldSeparator;
      if (settings.phonenumber)
        datastring += 'TEL:' + settings.phonenumber + fieldSeparator;
      if (settings.email)
        datastring += 'EMAIL:' + settings.email + fieldSeparator;
      if (settings.url)
        datastring += 'URL:' + settings.url + fieldSeparator;

      //if (firstName != '' && lastName != '')
      //  datastring += 'N:' + lastName + ',' + firstName + fieldSeparator;
      //else if (lastName != '')
      //  datastring += 'N:' + lastName + fieldSeparator;
      //else if (firstName != '')
      //  datastring += 'N:' + firstName + fieldSeparator;

      if (settings.name)
        datastring += 'N:' + settings.name + fieldSeparator;
      if (settings.nickname)
        datastring += 'NICKNAME:' + settings.nickname + fieldSeparator;
      if (settings.reading)
        datastring += 'SOUND:' + settings.reading + fieldSeparator;
      if (settings.birthday)
        datastring += 'BDAY:' + Globalize.format(Globalize.parseDate(settings.birthday, 'MM.dd.yyyy HH:mm:ss'), 'yyyyMMdd') + fieldSeparator; /// TODO formatting yyyyMMdd

      //if (address != '' || city != '' || zip != '' || country != '')
      //  datastring += 'ADR:' + address + ',' + city + ',' + zip + ',' + country + fieldSeparator;

      if (settings.address)
        datastring += 'ADR:' + settings.address + fieldSeparator;

      //remove the used properties
      delete settings.memo;
      delete settings.phonenumber;
      delete settings.email;
      delete settings.url;
      delete settings.name;
      delete settings.nickname;
      delete settings.reading;
      delete settings.birthday;
      delete settings.address;

      return datastring;
    },

    _getSepaData: function (settings) {
      var datastring = '';

      var fieldSeparator = '\x0A';

      datastring = 'BCD' + fieldSeparator + '002' + fieldSeparator + '1' + fieldSeparator + 'SCT' + fieldSeparator;

      datastring += settings.bic + fieldSeparator;
      datastring += settings.receiver + fieldSeparator;
      datastring += settings.iban + fieldSeparator;
      if (settings.amount) {
        var _amount = parseFloat(Math.round(settings.amount.replace(',', '.') * 100) / 100);
        if (_amount > 0)
          datastring += 'EUR' + _amount.toString() + fieldSeparator;
        else
          datastring += fieldSeparator;
      }
      else
        datastring += fieldSeparator;
      datastring += settings.usage + fieldSeparator;
      datastring += settings.reference + fieldSeparator;
      datastring += settings.information + fieldSeparator;
      datastring += settings.userhint;

      //datastring += '.';

      //remove the used properties
      delete settings.bic;
      delete settings.receiver;
      delete settings.iban;
      delete settings.amount;
      delete settings.usage;
      delete settings.reference;
      delete settings.information;
      delete settings.userhint;

      return datastring;
    },

    _getSwissQRCodeData: function (settings) {
      var datastring = '';

      var fieldSeparator = '\x0A';

      var referenceTypes = { NON: "NON", SCOR: "SCOR", QRR: "QRR" };

      datastring = 'SPC' + fieldSeparator + '0200' + fieldSeparator + '1' + fieldSeparator;

      //IBAN or QRIban
      if(settings.referencetype === referenceTypes.QRR)
        datastring += settings.qriban + fieldSeparator;
      else
        datastring += settings.creditoriban + fieldSeparator;

      //creditor
      datastring += 'K' + fieldSeparator + settings.creditorname + fieldSeparator;
      datastring += settings.creditoraddress1 + fieldSeparator;
      datastring += settings.creditoraddress2 + fieldSeparator + fieldSeparator + fieldSeparator;
      datastring += settings.creditorcountry + fieldSeparator;

      //ultimate creditor (not in use)
      datastring += fieldSeparator + fieldSeparator + fieldSeparator + fieldSeparator + fieldSeparator + fieldSeparator + fieldSeparator;

      //amount
      if (settings.swissamount)
        datastring += parseFloat(Math.round(settings.swissamount.replace(',', '.') * 100) / 100).toFixed(2) + fieldSeparator + settings.currency + fieldSeparator;
      else
        datastring += fieldSeparator + settings.currency + fieldSeparator;

      //debtor
      if (settings.debtorname + settings.debtoraddress1 + settings.debtoraddress2 + settings.debtorcountry === '')
        datastring += fieldSeparator + fieldSeparator + fieldSeparator + fieldSeparator + fieldSeparator + fieldSeparator + fieldSeparator;
      else {
        datastring += 'K' + fieldSeparator;
        datastring += settings.debtorname + fieldSeparator;
        datastring += settings.debtoraddress1 + fieldSeparator;
        datastring += settings.debtoraddress2 + fieldSeparator;
        datastring += fieldSeparator + fieldSeparator;
        datastring += settings.debtorcountry + fieldSeparator;
      }

      //reference
      datastring += settings.referencetype + fieldSeparator;
      if (settings.referencetype === referenceTypes.QRR)
        datastring += settings.qrreference + fieldSeparator;
      else if (settings.referencetype === referenceTypes.SCOR)
        datastring += settings.creditorreference + fieldSeparator;
      else
        datastring += fieldSeparator;

      //aditional data
      datastring += settings.message + fieldSeparator;
      datastring += 'EPD' + fieldSeparator;
      datastring += settings.billinfo + fieldSeparator;

      //parameters
      datastring += settings.parameter1 + fieldSeparator;
      datastring += settings.parameter2;

      //remove the used properties
      delete settings.referencetype;
      delete settings.qriban;
      delete settings.creditoriban;
      delete settings.creditorname;
      delete settings.creditoraddress1;
      delete settings.creditoraddress2;
      delete settings.creditorcountry;
      delete settings.swissamount;
      delete settings.currency;
      delete settings.debtorname;
      delete settings.debtoraddress1;
      delete settings.debtoraddress2;
      delete settings.debtorcountry;
      delete settings.qrreference;
      delete settings.creditorreference;
      delete settings.message;
      delete settings.billinfo;
      delete settings.parameter1;
      delete settings.parameter2;

      return datastring;
    },

    _getGS1DigitalLinkData: function (settings) {
      var datastring = '';

      if (settings.gs1resolver.startsWith('http'))
        datastring += settings.gs1resolver;
      else
        datastring += 'https://' + settings.gs1resolver;

      datastring += '/' + settings.primarykeyenum.substring(1) + '/' + settings.primarykeyvalue;

      if (settings.keyqualifier22)
        datastring += '/22/' + settings.keyqualifier22;
      if (settings.keyqualifier10)
        datastring += '/10/' + settings.keyqualifier10;
      if (settings.keyqualifier21)
        datastring += '/21/' + settings.keyqualifier21;
      if (settings.keyqualifier254)
        datastring += '/254/' + settings.keyqualifier254;
      if (settings.keyqualifier8011)
        datastring += '/8011/' + settings.keyqualifier8011;
      if (settings.keyqualifier8019)
        datastring += '/8019/' + settings.keyqualifier8019;

      
      var dataquery = "";
      for (var x = 1; x <= $('input[name^="DataAttributeKey"]').length; x++) {
        if (settings["dataattributekey_" + x]) {
          dataquery += settings["dataattributekey_" + x] + '=' + settings["dataattributeval_" + x] + '&';
          delete settings["dataattributekey_" + x];
          delete settings["dataattributeval_" + x];
        }
      }

      if (dataquery) {
        datastring += '?' + dataquery.substring(0, dataquery.length - 1);
      }

      $('input[name="DigitalLink"]').val(datastring);

      //remove the used properties
      delete settings.gs1resolver;
      delete settings.primarykeyenum;
      delete settings.primarykeyvalue;
      delete settings.keyqualifier10;
      delete settings.keyqualifier21;
      delete settings.keyqualifier22;
      delete settings.keyqualifier254;
      delete settings.keyqualifier8011;
      delete settings.keyqualifier8019;

      return datastring;
    }


  });
}(this.tecit = this.tecit || {}, jQuery));;
(function (tecit, $) {

  // create widget named barcodeType
  $.widget("tecit.barcodeType", {

    options: {
      baseUrl: null,
      typeChanged: function (type) {
        tecit.log("No handler for typeChanged set!");
      }
    },

    // called on creation of widget
    _create: function () {
      if ($.trim(this.element.html()) === '')
        this.updateForm();

      this._bindClickEvents();
    },

    updateForm: function () {
      if (this.options.baseUrl === null) {
        tecit.log('No baseUrl to retrieve form from specified');
        return;
      }

      var that = this;

      $.get(this.options.baseUrl, null, function (data) {
        that.element.html(data);

        // reparse jQuery page validation for dynamic content
        tecit.ParseDynamicValidation(that.element);

        that.options.typeChanged($(that).data('value'));
      });
    },

    // called automatically when unloading
    _destroy: function () {
      this.element.off(".barcodeType");
    },

    // called when changing anything in this.options
    _setOption: function () {
      $.Widget.prototype._setOption.apply(this, arguments);
    },

    _bindClickEvents: function () {
      var that = this;

      this.element.on('click.barcodeType', 'ul li a', function (e) {
        e.preventDefault();

        // add "selected" class to this element only
        that.element.find('li').removeClass('selected');
        $(this).parent().addClass('selected');

        that.options.typeChanged($(this).data('value'));
      });

      this.element.on('change.barcodeType', 'select', function (e) {
        e.preventDefault();
        that.options.typeChanged($(this).val());
      });
    }

  });
}(this.tecit = this.tecit || {}, jQuery));;
$(function () {

  $.widget("tecit.barcodeGenerator", {

    options: {
      // url to the barcode mvc app
      baseUrl: null
    },

    form: null,
    barcodeWidget: null,
    settingsWidget: null,
    dataWidget: null,
    typeWidget: null,

    // called on creation of widget
    _create: function () {
      var that = this;

      this._initBaseUrl();

      this.form = this.element.find('form');
      if (this.form.length === 0) {
        this.form = $('<form id="barcodeGeneratorForm" />').appendTo(this.element);
      }
      else {
        this.form.attr('id', 'barcodeGeneratorForm');
      }

      // restore hidden panes on window resize
      $(window).resize(function () {
        if (window.innerWidth >= 768) {
          if ($('.tecit-info').is(':hidden')) {
            $('#barcodeGenerator .block-h-3:hidden:not(.tecit-info)').show();
          }
          else {
            $('#barcodeGenerator .block-h-3:hidden:not(.tecit-info):not(#infoTarget)').show();
          }
        }
      });

      //add type widget
      this._getContainerWithClass('barcodeType').selection({
        selectionChanged: function (element) {
          var value = element.data("value");
          var name = element.find('span').html();

          //hide/show HideHRT dropdown for lineal barcodes
          var groupClass = element.closest('ul.styled-list').parent().attr('class');
          var isLineal = groupClass.startsWith('BCGroup_1D');
          var $settingsHideHRT = $('#Settings_HideHRT');
          $settingsHideHRT.prop('disabled', !isLineal);

          if (isLineal)
          {
            $settingsHideHRT.parent().parent().slideDown();
            // make sure to reparse the settings to include eclevel
            that.settingsWidget.barcodeSettings('triggerSettingsChanged');
          }
          else {
            $settingsHideHRT.find('option:selected').removeAttr('selected');
            $settingsHideHRT.find('option[value="False"]').attr('selected', 'selected');
            $settingsHideHRT.val('False');
            $settingsHideHRT.parent().parent().slideUp();
          }

          // hide/show EcLevel for QrCodes
          var isQrcode = value.match(/QRCode|MobileQR/gi);
          var isEPCQRCode = value === "EPCQRCode";
          var $settingsEcLevel = $("#Settings_EcLevel");
          $settingsEcLevel.prop("disabled", !isQrcode);

          if (isQrcode) {
            $settingsEcLevel.parent().parent().slideDown();

            var isBankingCode = element.closest('.BCGroup_Banking').length === 1;

            // disable/enable 'Low' option
            $settingsEcLevel.find("option[value='L']").attr('disabled', isBankingCode);
            // disable/enable 'Q','H' option for EPC codes
            $settingsEcLevel.find("option[value='Q']").attr('disabled', isEPCQRCode);
            $settingsEcLevel.find("option[value='H']").attr('disabled', isEPCQRCode);

            // set ecLevel value to 'Medium' for Banking codes when 'Low' option is selected
            if (isBankingCode) {
              $settingsEcLevel.find("option[value='L']").removeAttr("selected");
              $settingsEcLevel.find("option[value='M']").attr("selected", "selected");
              $settingsEcLevel.val("M");
            }

            // make sure to reparse the settings to include eclevel
            that.settingsWidget.barcodeSettings('triggerSettingsChanged');
          }
          else {
            $settingsEcLevel.parent().parent().slideUp();
          }

          // hide/show DmSize for Datamatrix
          var isDataMatrix = value.match(/DataMatrix|MobileSema/gi);
          $("#Settings_DmSize").prop("disabled", !isDataMatrix);

          if (isDataMatrix) {
            $("#Settings_DmSize").parent().parent().slideDown();
            // make sure to reparse the settings to include dmsize
            that.settingsWidget.barcodeSettings('triggerSettingsChanged');
          }
          else {
            $("#Settings_DmSize").parent().parent().slideUp();
          }

          that.dataWidget.barcodeSettingsOverride('updateForm', value);

          var width = jQuery(window).width();

          if (width < 768) {
            $('#barcodeGenerator .mobile-title')[1].click(); // open data panel
            $('.selectedBarcode span').html(element.parent().parent().siblings('a').find('span').html() + '&nbsp;&nbsp;&nbsp;&nbsp;>&nbsp;&nbsp;&nbsp;&nbsp;' + element.find('span').html()); // copy selected barcode name 
          }
          // ensure sequenceWrapper is hiden
          $('.sequenceWrapper').hide();

          // set document title and description according to selected code
          document.title = application.templates.title.replace(/%0/, name);
          $('meta[name=DESCRIPTION]').attr('content', application.templates.description.replace(/%0/, name));
          $('meta[name=KEYWORDS]').attr('content', application.templates.keywords.replace(/%0/g, name));
        },
        nodeChanged: function (node) {
          node.parent().makeVisible();
        },
        animation: {
          effect: 'blind'
        }
      });

      // add barcode widget
      this.barcodeWidget = this._getContainerWithClass('barcode').barcode({
        baseUrl: that._getNonLocalizedBaseUrl() + 'barcode.ashx',
        barcodeUpdated: function (event, urls) {
          $('.downloadButton').attr('href', urls.imageUrl + '&download=true').removeClass('disabled').removeClass('animated');

          $('.copyBarcodeImageUrl').val(urls.imageUrl);
          $('.copyBarcodeUrl').val(urls.pageUrl);

          // todo update only the first line for multiplebarcodes
          var htmlMarkup = $('#embedMarkup').data('template').replace('{0}', urls.imageUrl);

          $('#embedMarkup').html(htmlMarkup);
          $('.barcodeError').html('').hide();
        },
        raiseError: function (error) {
          $('.barcodeError').html(error).show();
          $('.downloadButton').removeAttr('href').addClass('disabled');
        }
      });

      // add data widget
      this.dataWidget = this._getContainerWithClass('barcodeData').barcodeSettingsOverride({
        baseUrl: this.options.baseUrl + '/GetDataForm',
        // override callback
        settingsChanged: function (data) {
          if (that.form.valid())
            that.barcodeWidget.barcode('setQRCodeData', data);

          // save the current url in the browser history
          if (typeof history.replaceState === "function") {
            var url = $("base").attr("href");
            //disable url replacement for barcodes where the data string could exceed max url length
            if (data.datatype.match(/(_meCard|_vCard|_Events|_Wifi|EPCQRCode)$|SwissQRCodeV2|GS1DigitalLink/g) || data.multiplebarcodes)
              url += "/" + encodeURIComponent(data.datatype);
            else
              url += "/" + encodeURIComponent(data.datatype) + "?data=" + encodeURIComponent(data.data);
            history.replaceState(data, "", url);
          }

          $('.copyBarcodeUrl').val(document.location.href);
        },
        defaultSettings: this.barcodeWidget.barcode('getQRCode').data,
        idPrefix: 'Data.',
        formChanged: that._initDateTime,
        widgetCreated: function (event, data) {
          that.barcodeWidget.barcode('setQRCodeData', data, false);
        }
      });

      // add settings widget
      this.settingsWidget = this._getContainerWithClass('barcodeSettings').barcodeSettings({
        baseUrl: this.options.baseUrl + '/GetSettingsForm',
        // override callback
        settingsChanged: function (settings) {
          if (that.form.valid())
            that.barcodeWidget.barcode('setQRCodeSettings', settings);
        },
        defaultSettings: this.barcodeWidget.barcode('getQRCode').settings,
        idPrefix: 'Settings.',
        formChanged: function () {

        },
        widgetCreated: function (event, settings) {
          that.barcodeWidget.barcode('setQRCodeSettings', settings, false);
        }
      }).hide();

      // add info widget
      if ($.info) {
        this.infoWidget = $('<div class="block-h-3" />').info({
          targetElement: $('#infoTarget'),
          chance: application.appSettings.infoChance,
          sourceHost: application.appSettings.infoSourceHost
        });
      }
      else {
        this.infoWidget = {};
        this.infoWidget.info = function () { }; // create a dummy function to prevent errors
      }

      // bind to change event to enable/disable background color input
      $('#Settings_IsTransparent').on('change', function (e) {
        $('#Settings_BackColor').prop('disabled', $(this).val() == 'true').css('color', '#929292');
      });

      // add toggle to switch between barcode and settings
      $('.barcodeSettingsToggle, .barcodeSettings .okButton').on('click', function () {
        that.settingsWidget.toggle();
        that.barcodeWidget.toggle();

        if (!$(this).is('.okButton')) // prevent showing when closing the settings
          that.infoWidget.info('show');
      });

      // add toggle to switch between barcode and copy
      $('.copyToggle, .copyWrapper .okButton').on('click', function () {
        $(".copyWrapper").toggle();
        that.barcodeWidget.toggle();

        if (!$(this).is('.okButton')) // prevent showing when closing the copyWrapper
          that.infoWidget.info('show');
      });

      // dropdown menu implementation -- maybe move this into a widget later
      $('.barcodeSettings .dropdownMenu > a').on('click', function () {
        $(this).toggleClass("noHover");
        $('.barcodeSettings .dropdownMenu > ul').toggle();
      });

      $('#generalSettingsToggle').on('click', function () {
        var list = $(this).parent().parent();
        // remove css classes
        list.siblings('a').removeClass("noHover");
        list.find('>li').removeClass('selected-list');
        // add selected class
        $(this).parent().addClass('selected-list');
        // set caption text
        list.siblings('a').find('.dropdownText').html($(this).html());

        $('.barcodeSettings .generalSettings').show();
        $('.barcodeSettings .colorSettings').hide();
        $('.barcodeSettings .advancedSettings').hide();
        list.hide();
      });

      $('#colorSettingsToggle').on('click', function () {
        var list = $(this).parent().parent();
        // remove css classes
        list.siblings('a').removeClass("noHover");
        list.find('>li').removeClass('selected-list');
        // add selected class
        $(this).parent().addClass('selected-list');
        // set caption text
        list.siblings('a').find('.dropdownText').html($(this).html());

        $('.barcodeSettings .generalSettings').hide();
        $('.barcodeSettings .colorSettings').show();
        $('.barcodeSettings .advancedSettings').hide();
        list.hide();
      });

      $('#advancedSettingsToggle').on('click', function () {
        var list = $(this).parent().parent();
        // remove css classes
        list.siblings('a').removeClass("noHover");
        list.find('>li').removeClass('selected-list');
        // add selected class
        $(this).parent().addClass('selected-list');
        // set caption text
        list.siblings('a').find('.dropdownText').html($(this).html());

        $('.barcodeSettings .generalSettings').hide();
        $('.barcodeSettings .colorSettings').hide();
        $('.barcodeSettings .advancedSettings').show();
        list.hide();
      });

      // prevent default form submit
      $('.barcodeGenerate :submit').on('click', function (e) {
        e.preventDefault();

        that.barcodeWidget.barcode('updateBarcode');
      });

      // event when navigating back/forward on the site 
      // for the time being we are not using this to restore state
      window.onpopstate = function (event) {
        //var state = event.state;

        //if (state)
        //  that.dataWidget.barcodeSettingsOverride("setSettingsObject", state);
      };

      this._initDatepicker();

      this._initTimepicker();

      this._initDateTime();

      this._initModuleWidthSettings();

      this._initMobileTitleHeaders();

      this._initClipboard();

      $('.showBarcodeButton').click(function (e) {
        e.preventDefault();

        $('#barcodeGenerator .mobile-title')[2].click(); // open download barcode panel
      });

      // decimal parsing for barcode data
      $('.barcodeData').on('change', '.decimal', function () {
        var parsedValue = Globalize.parseFloat($(this).val());
        if (parsedValue)
          $(this).val(Globalize.format(parsedValue, 'n2'));
      });

      // generate button is not needed if js is available
      $('.barcodeGenerate').hide();

      $('#barcodeGenerator').on('click', '.barcodeRefresh a', function (e) {
        e.preventDefault();
        that.dataWidget.barcodeSettingsOverride("triggerSettingsChanged");
      });

      // sequenceToggle
      $('#barcodeGenerator').on('click', 'a.sequenceToggle', function (e) {
        e.preventDefault();
        $('.dataWrapper').toggle();
        $('.checkboxWrapper').toggle();
        if (!$('.mobile-title').is(':visible'))
          $('.barcodeRefresh ').toggle();
        $('.sequenceWrapper').toggle();
        var sequenceVisible = $('.sequenceWrapper').is(':visible');
        var mobileVisible = $('.mobile-title').is(':visible');
        if (sequenceVisible) {
          this.text = this.dataset.textvisible;
          $('.barcodeRefresh ').hide();
        }
        else {
          this.text = this.dataset.texthidden;
          if (!mobileVisible)
            $('.barcodeRefresh ').show();
        }
      });

      // create the sequence
      $('#barcodeGenerator').on('click', '.sequenceWrapper a.generateSequence', function (e) {
        e.preventDefault();

        // check form is valid
        if (!that.form.valid()) {
          $('.input-validation-error').focus();
          return;
        }

        // close dataSequence
        $('#barcodeGenerator a.sequenceToggle').click();

        if ($('#Data').length === 1) {
          var i;
          var start = parseInt($('#SequenceStart').val());
          var end = parseInt($('#SequenceEnd').val());
          var increment = parseInt($('#SequenceIncrement').val());
          var newVal = "";
          //use MultipleBarcodesMax to limit the sequence
          var maxLoop = parseInt($('#MultipleBarcodesMax').val());
          var loop = 0;
          // create the sequence
          for (i = start; i <= end; i += increment) {
            if (loop >= maxLoop)
              break;
            loop++;
            newVal += $('#SequencePrefix').val() + "" + that._getMaskedNumber(i, $('#SequenceMask').val()) + "" + $('#SequenceSufix').val() + "\n";
          }

          // set Data value
          if (newVal !== "") {
            $('#Data').val(newVal.replace(/\n$/, ""));
            // check the multipleBarcodes checkbox
            $('#multipleBarcodes').prop('checked', true);
            // update the barcode
            $('.barcodeRefresh a').click();
          }
        }
      });

      // make sure downloading waits for ajax calls to finish
      $('.downloadButton').on('click', function (e) {

        var $this = $(this);
        e.preventDefault();

        if (!$this.hasClass('disabled')) {
          if (typeof gtag === 'function') {
            gtag('event', 'click', {
              'event_category': 'button',
              'event_label': 'Barcode_Generator_Download'
            });
          }

          // disable the downloadButton and start the animation
          $this.addClass('disabled').addClass('animated');

          // check for runnning ajax calls
          if ($.active > 0) {
            $(document).one('ajaxStop', function () {
              that.infoWidget.info('show');
              that.barcodeWidget.barcode('downloadBarcode');
              // enable the donwloadButton and stop the animation
              $(document).one('ajaxComplete', function () {
                $this.removeClass('disabled').removeClass('animated');
              });
            });
          }
          else {
            that.infoWidget.info('show');
            that.barcodeWidget.barcode('downloadBarcode');
            // enable the donwloadButton and stop the animation
            $(document).one('ajaxComplete', function () {
              $this.removeClass('disabled').removeClass('animated');
            });
          }
        }
      });

      // used to trim every input in the barcode data form
      $('.barcodeData').on('click', '.trim a', function (e) {
        e.preventDefault();
        var changed = false;
        $('.barcodeData input, .barcodeData textarea').val(function (_, value) {
          var newVal = $.trim(value);
          if (newVal !== value)
            changed = true;

          return newVal;
        });
        // update barcode if data was changed
        if (changed)
          that.dataWidget.barcodeSettingsOverride("triggerSettingsChanged");

        $('.barcodeData .trim').hide();
      });

      $('.barcodeData').on('keyup', 'input, textarea', function () {
        var showButton = false;
        $('.barcodeData input, .barcodeData textarea').each(function (_, element) {
          showButton = showButton || (element.value.match(/^\s+/) !== null || element.value.match(/\s+$/) !== null)
        });
        $('.barcodeData .trim').toggle(showButton);
      });

      // login handling
      $('.loginLink').on('click', function (e) {
        e.preventDefault();

        $('#barcodeGenerator').hide();
        $('div.login').show();
      });

      $('.login .backButton').on('click', function (e) {
        e.preventDefault();

        $('#barcodeGenerator').show();
        $('div.login').hide();
      });

      // validate all fields in the form (remove ":hidden")
      this.form.data("validator").settings.ignore = "";
      var formvalid = this.form.valid();
    },

    // called automatically when unloading
    _destroy: function () {
    },

    // called when changing anything in this.options
    _setOption: function () {
      $.Widget.prototype._setOption.apply(this, arguments);
    },

    _getContainerWithClass: function (className) {
      var container = this.form.find('.' + className);

      if (!container.length) {
        container = $('<div class="' + className + '" />').appendTo(this.form);
      }

      return container;
    },

    _initBaseUrl: function () {
      // read basurl from html
      if (this.options.baseUrl === null || this.options.baseUrl === undefined)
        this.options.baseUrl = $("base").attr("href");
      if (this.options.baseUrl === null || this.options.baseUrl === undefined)
        this.options.baseUrl = this.element.data('baseurl');

      if (this.options.baseUrl === null || this.options.baseUrl === undefined)
        this.options.baseUrl = '';
    },

    _initDateTime: function () {
      $('input[type="datetime"]').wrap('<div class="styled-date" />');
      $('<div class="toggleCal" />').appendTo($('.styled-date')).on('click', function () {
        var date = $(this).siblings('input').val();
        $('.datepicker').datepicker('option', 'altField', '#' + $(this).siblings('input').attr('id'));
        $('.datepicker').datepicker('setDate', date);
        $('.datepicker').show();
      });

      $('input.time').wrap('<div class="styled-time" />');
      $('<div class="toggleTime" />').appendTo($('.styled-time')).on('click', function () {
        var inputId = $(this).siblings('input').attr('id');
        var time = $(this).siblings('input').val();
        $('.timepicker').timepicker('option', 'field', '#' + inputId);
        $('.timepicker').timepicker('setTime', time);
        $('.timepicker').timepicker('setCaption', $('label[for=' + inputId + ']').html());
        $('.timepicker').show();
      });
    },

    _initDatepicker: function () {
      // initiate datepicker used for whole page
      $('.datepicker').datepicker({
        showButtonPanel: false,
        onSelect: function () {
          $($(this).datepicker('option', 'altField')).change();
          $('.datepicker').hide()
        },
        changeYear: true
      });

      $('.dpDoneButton').on('click', function () {
        $('.datepicker').hide();
      });

      $('.dpClearButton').on('click', function () {
        $($('.datepicker').datepicker('option', 'altField')).val('').change();
        $('.datepicker').hide();
      });

      $('.dpTodayButton').on('click', function () {
        $('.datepicker').datepicker("setDate", new Date());
        $($('.datepicker').datepicker('option', 'altField')).change();
        $('.datepicker').hide();
      });
    },

    _initTimepicker: function () {
      $('.timepicker').timepicker({
        hideAfterDone: true,
        hideAfterNow: true
      });
    },

    _initMobileTitleHeaders: function () {
      $('#barcodeGenerator').find('.mobile-title').click(function () {

        var $that = $(this);

        $that.next().slideToggle(); //expand or collapse this panel

        var $panelsToHide = $('#barcodeGenerator .block-3:not(.selectedBarcode)').not($that.next()); //get other panels

        if ($that.is(':first-child:not(.selected)'))
          $panelsToHide = $panelsToHide.add('.selectedBarcode'); //exclude the selected barcode type div
        else
          $('.selectedBarcode').slideDown();

        $panelsToHide.slideUp(); // hide other panels

        //set proper selected class
        $that.toggleClass('selected');
        $('#barcodeGenerator .mobile-title').not($that).removeClass('selected');

        $(':animated').promise().done(function () {
          $that.next().makeVisible({ animation: { duration: 400, easing: 'linear' }, offset: -$that.height() });
        });
      });

      $('.selectedBarcode').click(function () {
        $('#barcodeGenerator .mobile-title')[0].click(); // open barcode type selection panel
      });
    },

    // initialize clipboard functionality
    _initClipboard: function () {
      new Clipboard(".clipboard");
    },

    _getNonLocalizedBaseUrl: function () {
      return this.options.baseUrl.replace(/\/.{2}$/, '/');
    },

    _initModuleWidthSettings: function () {
      var that = this;

      var $moduleWidth = $('#Settings_ModuleWidth');
      if ($moduleWidth.val().length === 0)
        $moduleWidth.val('auto');

      this.element.on('change.moduleWidthUnit', 'select#Settings_Unit', function (e) {
        e.preventDefault();
        e.stopPropagation();

        var moduleWidth = that.BCCalculatePixelAlignedModuleWidth(0.254, $('#Settings_Dpi').val());

        var $this = $(this);
        switch ($this.val()) {
          case 'Mm':
            moduleWidth = Math.ceil(10000 * moduleWidth) / 10000;
            $moduleWidth.prop('disabled', false).val(Globalize.format(moduleWidth, 'n3'));
            break;
          case 'Mils':
            moduleWidth = Math.ceil(1000 * moduleWidth / 0.0254) / 1000;
            $moduleWidth.prop('disabled', false).val(Globalize.format(moduleWidth, 'n3'));
            break;
          case 'Px':
            moduleWidth = $('#Settings_Dpi').val() * moduleWidth / 25.4;
            $moduleWidth.prop('disabled', false).val(Globalize.format(moduleWidth, 'n0'));
            break;
          case 'Fit':
          case 'Min':
          default:
            $moduleWidth.prop('disabled', true).val('auto');
            break;
        }

        $moduleWidth.change();
      });
    },

    _getMaskedNumber: function (number, mask) {
      number = number.toString();
      var indexNumber = number.length;
      var indexMask = mask.length;
      var maskChar = "";
      var maskedNumber = "";

      //read all number positions (from last to first index)
      while (indexNumber > 0) {
        // get the next maskChar (from last to first index)
        if (indexMask >= 0) {
          indexMask--;
          maskChar = mask.substring(indexMask, indexMask + 1);
        }
        // evaluate maskChar
        switch (maskChar) {
          case "":
          case "#":
          case "$":
          case "*":
            // print digit 
            indexNumber--;
            maskedNumber = number.substring(indexNumber, indexNumber + 1) + maskedNumber;
            break;
          default:
            // print mask
            maskedNumber = maskChar + maskedNumber;
            break;
        }
        // empty the maskChar
        maskChar = "";
      }

      //read the remaining mask chars
      while (indexMask > 0) {
        indexMask--;
        maskChar = mask.substring(indexMask, indexMask + 1);
        switch (maskChar) {
          case "#":
            // print space
            maskedNumber = " " + maskedNumber;
            break;
          case "$":
            // print 0
            maskedNumber = "0" + maskedNumber;
            break;
          case "*":
            // print *
            maskedNumber = "*" + maskedNumber;
            break;
          default:
            // print mask
            maskedNumber = maskChar + maskedNumber;
            break;
        }
        // empty the maskChar
        maskChar = "";
      }

      return maskedNumber;
    },

    // ----------------------------------------------
    // calculate a Pixel raster aligned module width close to 0.254 mm
    // ----------------------------------------------
    BCCalculatePixelAlignedModuleWidth: function (moduleWidth, dpi) {
      moduleWidth = 25.4 / dpi * Math.ceil(moduleWidth / (25.4 / dpi));
      return moduleWidth;
    }

  });
});;
$(function ($) {
  $('#barcodeGenerator').barcodeGenerator();

  tecit.tooltips_init();

});;
// Value is the element to be validated, params is the array of name/value pairs of the parameters extracted from the HTML, element is the HTML element that the validator is attached to
$.validator.addMethod('aivalidation', function (value, element, params) {

  var result = true;

  //// validate if the field is not empty
  //if (value === '') {
  //  // check if one of the other fields was filled
  //  if (params.otherproperties && params.otherproperties.length > 0) {
  //    params.otherproperties.forEach(function (property) {
  //      if ($('#' + property).val() !== '')
  //        result = false;
  //    });
  //  }


  // validate reg
  if (value !== '') {
    if (params) {
      var ai = $(params).val();
      //check ai ....
      var pattern;
      switch (ai) {
        // 18 dígitos
        case "_00":
        case "_8017":
        case "_8018":
          pattern = new RegExp("^(\\d{18})$");
          break;
        // 8,12,13 0 14 dígitos
        case "_01":
          pattern = new RegExp("^(\\d{8}|\\d{12}|\\d{13}|\\d{14})$");
          break;
        case "_253":
          pattern = new RegExp("^(\\d{13})([\\x21-\\x22\\x25-\\x2F\\x30-\\x39\\x3A-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,17})$");
          break;
        case "_255":
          pattern = new RegExp("^(\\d{13})(\\d{0,12})$");
          break;
        case "_401":
          pattern = new RegExp("^([\\x21-\\x22\\x25-\\x2F\\x30-\\x39\\x3A-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,30})$");
          break;
        // 17 dígitos
        case "_402":
          pattern = new RegExp("^(\\d{17})$");
          break;
        // 13 dígitos
        case "_410":
        case "_411":
        case "_412":
        case "_413":
        case "_414":
        case "_415":
        case "_416":
        case "_417":
          pattern = new RegExp("^(\\d{13})$");
          break;
        case "_8003":
          pattern = new RegExp("^(\\d{14})([\\x21-\\x22\\x25-\\x2F\\x30-\\x39\\x3A-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,16})$");
          break;
        case "_8004":
        case "_8013":
          pattern = new RegExp("^([\\x21-\\x22\\x25-\\x2F\\x30-\\x39\\x3A-\\x3F\\x41-\\x5A\\x5F\\x61-\\x7A]{0,30})$");
          break;
        case "_8006":
          pattern = new RegExp("^(\\d{14})(\\d{2})(\\d{2})$");
          break;
        case "_8010":
          pattern = new RegExp("^([\\x23\\x2D\\x2F\\x30-\\x39\\x41-\\x5A]{0,30})$");
          break;
        default:
          break;
      }
      if (pattern)
        result = pattern.test(value);

      return result;
    }
  }

  return result;
});

/* The adapter signature:
adapterName is the name of the adapter, and matches the name of the rule in the HTML element.
 
params is an array of parameter names that you're expecting in the HTML attributes, and is optional. If it is not provided,
then it is presumed that the validator has no parameters.
 
fn is a function which is called to adapt the HTML attribute values into jQuery Validate rules and messages.
 
The function will receive a single parameter which is an options object with the following values in it:
element
The HTML element that the validator is attached to
 
form
The HTML form element
 
message
The message string extract from the HTML attribute
 
params
The array of name/value pairs of the parameters extracted from the HTML attributes
 
rules
The jQuery rules array for this HTML element. The adapter is expected to add item(s) to this rules array for the specific jQuery Validate validators
that it wants to attach. The name is the name of the jQuery Validate rule, and the value is the parameter values for the jQuery Validate rule.
 
messages
The jQuery messages array for this HTML element. The adapter is expected to add item(s) to this messages array for the specific jQuery Validate validators that it wants to attach, if it wants a custom error message for this rule. The name is the name of the jQuery Validate rule, and the value is the custom message to be displayed when the rule is violated.
*/
$.validator.unobtrusive.adapters.add('aivalidation', ['otherpropertyname'], function (options) {
  //options.rules['aivalidation'] = { otherproperties: options.params.otherproperties.split(',') };
  options.rules['aivalidation'] = '#' + options.params.otherpropertyname;
  options.messages['aivalidation'] = options.message;
});
;
/// <reference path="jquery-1.4.4.js" />
/// <reference path="jquery.validate.js" />
/// <reference path="jquery.validate.unobtrusive.js" />

(function ($) {
  $.validator.unobtrusive.parseDynamicContent = function (selector) {
    //use the normal unobstrusive.parse method
    $.validator.unobtrusive.parse(selector);

    //get the relevant form
    var form = $(selector).first().closest('form');

    //get the collections of unobstrusive validators, and jquery validators
    //and compare the two
    var unobtrusiveValidation = form.data('unobtrusiveValidation');
    var validator = form.validate();

    $.each(unobtrusiveValidation.options.rules, function (elname, elrules) {
      if (validator.settings.rules[elname] == undefined) {
        var args = {};
        $.extend(args, elrules);
        args.messages = unobtrusiveValidation.options.messages[elname];
        //edit:use quoted strings for the name selector
        $("[name='" + elname + "']").rules("add", args);
      } else {
        $.each(elrules, function (rulename, data) {
          if (validator.settings.rules[elname][rulename] == undefined) {
            var args = {};
            args[rulename] = data;
            args.messages = unobtrusiveValidation.options.messages[elname][rulename];
            //edit:use quoted strings for the name selector
            $("[name='" + elname + "']").rules("add", args);
          }
        });
      }
    });
  }
})($);;
// Value is the element to be validated, params is the array of name/value pairs of the parameters extracted from the HTML, element is the HTML element that the validator is attached to
$.validator.addMethod('greaterthan', function (value, element, params) {

  // validate if the field value is greater than the other field
  //return value === '' || $(params).val() === '' || parseInt($(params).val()) < parseInt(value);
  return value === '' || parseInt($(params).val()) < parseInt(value);
});

/* The adapter signature:
adapterName is the name of the adapter, and matches the name of the rule in the HTML element.
 
params is an array of parameter names that you're expecting in the HTML attributes, and is optional. If it is not provided,
then it is presumed that the validator has no parameters.
 
fn is a function which is called to adapt the HTML attribute values into jQuery Validate rules and messages.
 
The function will receive a single parameter which is an options object with the following values in it:
element
The HTML element that the validator is attached to
 
form
The HTML form element
 
message
The message string extract from the HTML attribute
 
params
The array of name/value pairs of the parameters extracted from the HTML attributes
 
rules
The jQuery rules array for this HTML element. The adapter is expected to add item(s) to this rules array for the specific jQuery Validate validators
that it wants to attach. The name is the name of the jQuery Validate rule, and the value is the parameter values for the jQuery Validate rule.
 
messages
The jQuery messages array for this HTML element. The adapter is expected to add item(s) to this messages array for the specific jQuery Validate validators that it wants to attach, if it wants a custom error message for this rule. The name is the name of the jQuery Validate rule, and the value is the custom message to be displayed when the rule is violated.
*/
$.validator.unobtrusive.adapters.add('greaterthan', ['otherpropertyname'], function (options) {
  options.rules['greaterthan'] = '#' + options.params.otherpropertyname;
  options.messages['greaterthan'] = options.message;
});

;
// Value is the element to be validated, params is the array of name/value pairs of the parameters extracted from the HTML, element is the HTML element that the validator is attached to
$.validator.addMethod('mutuallyexclusive', function (value, element, params) {
  return value == '' || $(params).val() == '';
});

/* The adapter signature:
adapterName is the name of the adapter, and matches the name of the rule in the HTML element.
 
params is an array of parameter names that you're expecting in the HTML attributes, and is optional. If it is not provided,
then it is presumed that the validator has no parameters.
 
fn is a function which is called to adapt the HTML attribute values into jQuery Validate rules and messages.
 
The function will receive a single parameter which is an options object with the following values in it:
element
The HTML element that the validator is attached to
 
form
The HTML form element
 
message
The message string extract from the HTML attribute
 
params
The array of name/value pairs of the parameters extracted from the HTML attributes
 
rules
The jQuery rules array for this HTML element. The adapter is expected to add item(s) to this rules array for the specific jQuery Validate validators
that it wants to attach. The name is the name of the jQuery Validate rule, and the value is the parameter values for the jQuery Validate rule.
 
messages
The jQuery messages array for this HTML element. The adapter is expected to add item(s) to this messages array for the specific jQuery Validate validators that it wants to attach, if it wants a custom error message for this rule. The name is the name of the jQuery Validate rule, and the value is the custom message to be displayed when the rule is violated.
*/
$.validator.unobtrusive.adapters.add('mutuallyexclusive', ['otherpropertyname'], function (options) {
  options.rules['mutuallyexclusive'] = '#' + options.params.otherpropertyname;
  options.messages['mutuallyexclusive'] = options.message;
});;
// Value is the element to be validated, params is the array of name/value pairs of the parameters extracted from the HTML, element is the HTML element that the validator is attached to
$.validator.addMethod('qriban', function (value, element, params) {
  var isValidIBAN = value !== null && value.length === 21;
  // The QR-IBAN contains the QR-IID of the account-keeping financial institution for identification of the scheme.
  // The values 3000 to 3199 are exclusively reserved for the QR-IID.
  var isQRIban = value.substr(4, 2) === "30" || value.substr(4, 2) === "31";
  // read the parameter value
  var mustmatch = params.toUpperCase() === "TRUE";
  // compare
  return isValidIBAN && isQRIban === mustmatch;
});

/* The adapter signature:
adapterName is the name of the adapter, and matches the name of the rule in the HTML element.
 
params is an array of parameter names that you're expecting in the HTML attributes, and is optional. If it is not provided,
then it is presumed that the validator has no parameters.
 
fn is a function which is called to adapt the HTML attribute values into jQuery Validate rules and messages.
 
The function will receive a single parameter which is an options object with the following values in it:
element
The HTML element that the validator is attached to
 
form
The HTML form element
 
message
The message string extract from the HTML attribute
 
params
The array of name/value pairs of the parameters extracted from the HTML attributes
 
rules
The jQuery rules array for this HTML element. The adapter is expected to add item(s) to this rules array for the specific jQuery Validate validators
that it wants to attach. The name is the name of the jQuery Validate rule, and the value is the parameter values for the jQuery Validate rule.
 
messages
The jQuery messages array for this HTML element. The adapter is expected to add item(s) to this messages array for the specific jQuery Validate validators that it wants to attach, if it wants a custom error message for this rule. The name is the name of the jQuery Validate rule, and the value is the custom message to be displayed when the rule is violated.
*/
$.validator.unobtrusive.adapters.add('qriban', ['mustmatch'], function (options) {
  options.rules['qriban'] = options.params.mustmatch;
  options.messages['qriban'] = options.message;
});;
// Value is the element to be validated, params is the array of name/value pairs of the parameters extracted from the HTML, element is the HTML element that the validator is attached to
$.validator.addMethod('requiredallowwhitespace', function (value, element, params) {
  return value != '';
});

/* The adapter signature:
adapterName is the name of the adapter, and matches the name of the rule in the HTML element.
 
ruleName is the name of the jQuery Validate rule, and is optional. If it's not provided, then the adapterName is used. 
 
*/
$.validator.unobtrusive.adapters.addBool('requiredallowwhitespace');;
// Value is the element to be validated, params is the array of name/value pairs of the parameters extracted from the HTML, element is the HTML element that the validator is attached to
$.validator.addMethod('requiredif', function (value, element, params) {

  var allowEmptyString = params.allowemptystring;

  // validate if the field is not empty
  if (value === '') {

    var result = true;

    // check if one of the other fields was filled
    if (params.otherproperties && params.otherproperties.length > 0) {
      params.otherproperties.forEach(function (property) {
        if ($('#' + property).val() !== '')
          result = false;
      });
    }

    return result;
  }
  else if (!allowEmptyString && value !== '' && value.trim() === '') {
    //
    result = false;
    return result;
  }

  return true;
});

/* The adapter signature:
adapterName is the name of the adapter, and matches the name of the rule in the HTML element.
 
params is an array of parameter names that you're expecting in the HTML attributes, and is optional. If it is not provided,
then it is presumed that the validator has no parameters.
 
fn is a function which is called to adapt the HTML attribute values into jQuery Validate rules and messages.
 
The function will receive a single parameter which is an options object with the following values in it:
element
The HTML element that the validator is attached to
 
form
The HTML form element
 
message
The message string extract from the HTML attribute
 
params
The array of name/value pairs of the parameters extracted from the HTML attributes
 
rules
The jQuery rules array for this HTML element. The adapter is expected to add item(s) to this rules array for the specific jQuery Validate validators
that it wants to attach. The name is the name of the jQuery Validate rule, and the value is the parameter values for the jQuery Validate rule.
 
messages
The jQuery messages array for this HTML element. The adapter is expected to add item(s) to this messages array for the specific jQuery Validate validators that it wants to attach, if it wants a custom error message for this rule. The name is the name of the jQuery Validate rule, and the value is the custom message to be displayed when the rule is violated.
*/
$.validator.unobtrusive.adapters.add('requiredif', ['otherproperties','allowemptystring'], function (options) {
  options.rules['requiredif'] = {
    otherproperties: options.params.otherproperties.split(','),
    allowemptystring: options.params.allowemptystring === "True"
  };
  options.messages['requiredif'] = options.message;
});

;
// Value is the element to be validated, params is the array of name/value pairs of the parameters extracted from the HTML, element is the HTML element that the validator is attached to
$.validator.addMethod('uniquedatakey', function (value, element, params) {

  var result = true;
  
  //get elements with the same validation
  var allElements = $('*[data-val-uniquedatakey]');

  for (i = 0; i < allElements.length; i++) {
    // check if current value is duplicate in the other fields
    if (allElements[i].id !== element.id && allElements[i].value !== '' && allElements[i].value === value) {
      result = false;
      break;
    }
  }

  return result;
});

/* The adapter signature:
adapterName is the name of the adapter, and matches the name of the rule in the HTML element.
 
params is an array of parameter names that you're expecting in the HTML attributes, and is optional. If it is not provided,
then it is presumed that the validator has no parameters.
 
fn is a function which is called to adapt the HTML attribute values into jQuery Validate rules and messages.
 
The function will receive a single parameter which is an options object with the following values in it:
element
The HTML element that the validator is attached to
 
form
The HTML form element
 
message
The message string extract from the HTML attribute
 
params
The array of name/value pairs of the parameters extracted from the HTML attributes
 
rules
The jQuery rules array for this HTML element. The adapter is expected to add item(s) to this rules array for the specific jQuery Validate validators
that it wants to attach. The name is the name of the jQuery Validate rule, and the value is the parameter values for the jQuery Validate rule.
 
messages
The jQuery messages array for this HTML element. The adapter is expected to add item(s) to this messages array for the specific jQuery Validate validators that it wants to attach, if it wants a custom error message for this rule. The name is the name of the jQuery Validate rule, and the value is the custom message to be displayed when the rule is violated.
*/
$.validator.unobtrusive.adapters.add('uniquedatakey', ['propertyname'], function (options) {
  //options.rules['uniquedatakey'] = { otherproperties: options.params.otherproperties.split(',') };
  options.rules['uniquedatakey'] = options.params.propertyname;
  options.messages['uniquedatakey'] = options.message;
});
;
// Value is the element to be validated, params is the array of name/value pairs of the parameters extracted from the HTML, element is the HTML element that the validator is attached to
$.validator.addMethod('variablelength', function (value, element, params) {
  var length = value.length.toString();
  return $.inArray(length, params.validlengths) >= 0;
});

/* The adapter signature:
adapterName is the name of the adapter, and matches the name of the rule in the HTML element.
 
params is an array of parameter names that you're expecting in the HTML attributes, and is optional. If it is not provided,
then it is presumed that the validator has no parameters.
 
fn is a function which is called to adapt the HTML attribute values into jQuery Validate rules and messages.
 
The function will receive a single parameter which is an options object with the following values in it:
element
The HTML element that the validator is attached to
 
form
The HTML form element
 
message
The message string extract from the HTML attribute
 
params
The array of name/value pairs of the parameters extracted from the HTML attributes
 
rules
The jQuery rules array for this HTML element. The adapter is expected to add item(s) to this rules array for the specific jQuery Validate validators
that it wants to attach. The name is the name of the jQuery Validate rule, and the value is the parameter values for the jQuery Validate rule.
 
messages
The jQuery messages array for this HTML element. The adapter is expected to add item(s) to this messages array for the specific jQuery Validate validators that it wants to attach, if it wants a custom error message for this rule. The name is the name of the jQuery Validate rule, and the value is the custom message to be displayed when the rule is violated.
*/

$.validator.unobtrusive.adapters.add('variablelength', ['validlengths'], function (options) {
  options.rules['variablelength'] = { validlengths: options.params.validlengths.split(',') };
  options.messages['variablelength'] = options.message;
});;
(function (tecit, $) {

  // override default _gotoToday to actually select today (default: only switches to current month)
  $.datepicker._gotoToday = function (id) {
    var target = $(id);
    var inst = this._getInst(target[0]);
    if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
      inst.selectedDay = inst.currentDay;
      inst.drawMonth = inst.selectedMonth = inst.currentMonth;
      inst.drawYear = inst.selectedYear = inst.currentYear;
    }
    else {
      var date = new Date();
      inst.selectedDay = date.getDate();
      inst.drawMonth = inst.selectedMonth = date.getMonth();
      inst.drawYear = inst.selectedYear = date.getFullYear();

      // set the current date to today
      this._setDateDatepicker(target, date);
      this._selectDate(id, this._getDateDatepicker(target));
    }
    this._notifyChange(inst);
    this._adjustDate(target);
  }
}(this.tecit = this.tecit || {}, jQuery));;
(function ($) {

  // create selection widget 
  // animation can be a string (eg.: 'blind') or a jqueryui animation options object (eg.: { effect: 'blind', duration: 400 })
  $.widget("tecit.selection", {
    options: {
      selectionChanged: function (clickedElement) {
        console.log("tecit.selection: No handler for selectionChanged set!");
      },
      nodeChanged: null,
      animation: null
    },

    // called on creation of widget
    _create: function () {
      this.element.addClass('tecit-selection');
      this.element.find('ul').addClass('styled-list');

      this._bindClickEvents();

      // hide all submenus
      //this.element.find('ul:not(:first)').hide();
    },

    // called automatically when unloading
    _destroy: function () {
      this.element.off(".selection");
    },

    _bindClickEvents: function () {
      var that = this;

      this.element.on('click.selection', 'ul li a', function (e) {
        var $this = $(this);
        e.preventDefault();

        // add "selected" class to current element and remove from others (except parents)
        $this.parent()
          .siblings()
            .find('ul')
              .hide(that.options.animation)
            .end()
            .removeClass('selected')
            .find('.selected')
              .removeClass('selected')
            .end()
          .end()
          .addClass('selected');

        var submenu = $this.siblings('ul');

        if (submenu.length) {
          submenu.toggle(that.options.animation)
            .promise()
            .done(function () {
              if (typeof (that.options.nodeChanged) == "function")
                that.options.nodeChanged($this);
            });
        }
        else
          //only raise the selectionchange event for items without submenus
          that.options.selectionChanged($this);

      });
    }

  });
}(jQuery));;
/*
adds a cookie consent header to the body

DEPENDENCIES: jquery 1.7+
USAGE: simply include the js file, all code is executed on load
  clicking the accept link sets the cookie "enableCookies" to true and runs every function in the cookiesAcceptedCallbacks array
  clicking the refuse link sets the cookie "enableCookies" to false and runs every function in the cookiesRefusedCallbacks array
  "enableCookies" cookie is saved for the entire domain

  to prevent cookie code to execute prior to consent use this
  if (document.cookie.indexOf('enableCookies=true') !== -1) {
    //code that uses cookies
  }

  if code needs to run after cookies were accepted create a cookiesAcceptedCallbacks array with every necessery function
  var cookiesAcceptedCallbacks = new Array();
  cookiesAcceptedCallbacks.push(callback);
*/

/* static functions */

function setCookieConsent(value) {
  var cookie = 'enableCookies=' + value + '; expires=Thu, 31 Dec 2099 23:59:59 UTC; path=/';
  if (location.hostname.match(/tec-it\.com$/i))
    cookie = cookie + ';domain=tec-it.com';
  document.cookie = cookie;
}

function hasAcceptedCookieConsent() {
  return document.cookie.indexOf('enableCookies=true') !== -1;
}

function getCookieConsentLanguage() {
  var currentLang = $('html').attr('lang');
  if (currentLang === undefined || currentLang === null)
    currentLang = 'en';
  else
    currentLang = currentLang.substring(0, 2); // zh-cn => zh
  return currentLang;
}

/* dynamic / onload functions */

$(function () {
  if (document.cookie.indexOf('enableCookies=true') === -1) {
    var cookieConsentContent = [];

    cookieConsentContent['en'] = {
      text: 'This website uses cookies to ensure website functionality and, with your permission, personalize content, provide social media features and analyze traffic. By clicking the “Accept” button, you consent to the use of all cookies, including third-party services. In doing so, information about your use of this website will be shared with our social media and analytics partners. To find out more, read our <a href="https://www.tec-it.com/en/website/legalconditions/Default.aspx#Privacy" target="_blank" class="cookieMore" title="Pricacy Policy">Privacy Policy</a>.',
      videoHint: 'Accept to watch YouTube videos!',
      accept: 'Accept',
      refuse: 'Refuse'
    }
    cookieConsentContent['de'] = {
      text: 'Diese Website verwendet Cookies, um die Funktionalität zu gewähr&shy;leisten und (wenn Sie zustimmen) Inhalte zu persona&shy;lisieren, Beiträge in sozialen Medien zu unter&shy;stützen und den Besucher&shy;verkehr zu analysieren. Mit dem Anklicken der Schalt&shy;fläche “Akzeptieren” erklären Sie sich mit der Verwendung aller Cookies, einschließlich der Dienste Dritter einverstanden. Hierbei werden Informa&shy;tionen zu Ihrem Gebrauch dieser Website mit unseren sozialen Netz&shy;werken und Analysepartnern geteilt. Die Details finden Sie in unserer <a href="https://www.tec-it.com/de/website/legalconditions/Default.aspx#Privacy" target="_blank" class="cookieMore" title="Datenschutzerklärung">Datenschutzerklärung</a>.',
      videoHint: 'Akzeptieren, um YouTube Videos anzusehen!',
      accept: 'Akzeptieren',
      refuse: 'Ablehnen'
    }
    cookieConsentContent['es'] = {
      text: 'Este sitio web utiliza cookies para garantizar la funcionalidad del sitio web y, con su permiso, personalizar el contenido, proporcionar funciones de redes sociales y analizar el tráfico. Al hacer clic en “Aceptar”, usted acepta el uso de todas las cookies, incluidos los servicios de terceros. Al hacerlo, la información sobre el uso de este sitio web se compartirá con nuestros socios de análisis y redes sociales. Para más información, lea nuestro <a href="https://www.tec-it.com/es/website/legalconditions/Default.aspx#Privacy" target="_blank" class="cookieMore" title="Política de privacidad">Política de privacidad</a>.',
      videoHint: 'Acepte, para ver videos YouTube!',
      accept: 'Aceptar',
      refuse: 'Rechazar'
    }
    cookieConsentContent['it'] = {
      text: 'Questo sito Web utilizza i cookie per garantire la funzionalità del sito Web e, con il tuo permesso, personalizzare i contenuti, fornire funzionalità dei social media e analizzare il traffico. Cliccando sul pulsante “Accetta” acconsenti all\'uso di tutti i cookie, compresi i servizi di terze parti. In tal modo, le informazioni sull\'utilizzo di questo sito Web verranno condivise con i nostri partner di social media e analisi. Per saperne di più, leggi la nostra  <a href="https://www.tec-it.com/it/website/legalconditions/Default.aspx#Privacy" target="_blank" class="cookieMore" title="Politica sulla privacy">Politica sulla privacy</a>',
      videoHint: 'Accetta di guardare i video di YouTube!',
      accept: 'Accetta',
      refuse: 'Rifiuta'
    }
    cookieConsentContent['ru'] = {
      text: 'Данный сайт использует файлы cookie для обеспе&shy;че&shy;ния функциональности веб-сайта и, при Вашем согласии, для пер&shy;сонализации контента, предостав&shy;ле&shy;ния функций социальных сетей и анализа трафика. Нажимая кнопку «Принять», Вы соглаша&shy;етесь с исполь&shy;зованием всех файлов cookie, включая сторонние службы. При этом инфор&shy;ма&shy;ция об исполь&shy;зовании Вами данного сайта будет переда&shy;вать&shy;ся нашим партнерам по социаль&shy;ным сетям и анали&shy;тике. Подробнее в нашей <a href="https://www.tec-it.com/ru/website/legalconditions/Default.aspx#Privacy" target="_blank" class="cookieMore" title="Политика конфиденциальности">Политика конфиденциальности</a>',
      videoHint: 'Принять для просмотра видео с YouTube!',
      accept: 'Принять',
      refuse: 'Отказаться'
    }
    cookieConsentContent['fr'] = {
      text: 'En utilisant ce site, vous acceptez l\'utilisation de cookies pour personnaliser le contenu, soutenir les publications dans les médias sociaux et analyser le trafic des visiteurs. Les informations relatives à votre utilisation de ce site sont partagées avec nos réseaux sociaux et nos partenaires d’analyse. <a href="https://www.tec-it.com/fr/website/legalconditions/Default.aspx#Privacy" target="_blank" class="cookieMore" title="Privacy and Terms...">Plus d\'informations</a>',
      videoHint: 'Veuillez accepter pour regarder des vidéos sur YouTube!',
      accept: 'Accepter',
      refuse: 'Refuser'
    }
    cookieConsentContent['zh'] = {
      text: '本网站使用Cookie来确保网站功能，并在您允许的情况下个性化内容，提供社交媒体功能并分析流量。点击“接受”按钮，即表示您同意使用所有Cookie，包括第三方服务。这样，有关您使用本网站的信息将与我们的社交媒体和分析合作伙伴共享。要了解更多信息，请阅读我们的 <a href="https://www.tec-it.com/zh-cn/website/legalconditions/Default.aspx#Privacy" target="_blank" class="cookieMore" title="隐私政策">隐私政策</a>',
      videoHint: '请接受观看 YouTube 视频!',
      accept: '接受',
      refuse: '拒绝'
    }

    function getConsentContent(language) {
      return cookieConsentContent[language] !== undefined ?
         cookieConsentContent[language] : cookieConsentContent['en'];
    }

    var currentLang = getCookieConsentLanguage();
    var consentContent = getConsentContent(currentLang);

    var accepted = hasAcceptedCookieConsent();

    // 1) execute init callbacks

    if (typeof (cookieConsentInitCallbacks) !== 'undefined') {
      cookieConsentInitCallbacks.forEach(function (callback) {
        if (typeof (callback) === 'function')
          callback(accepted, consentContent.text, consentContent.videoHint, consentContent.accept, consentContent.refuse);
      });
    }

    // 2) add header

    $('<div class="cookieConsent" />').append(
      $('<div class="cookieConsentContent" />')
        .append('<span class="cookieConsentText">' + consentContent.text + '</span>')
        .append($('<span class="cookieConsentButtons" />')
          .append('<a class="cookieAccept">' + consentContent.accept + '</a>')
          .append('<a class="cookieRefuse">' + consentContent.refuse + '</a>')
        )
      )
      .prependTo('body').slideDown(500);
      //.appendTo('body').slideDown(500);

    // 3) add click handlers to all(!) page elements

    $('.cookieAccept').click(function () {
      setCookieConsent('true');
      removeConsentHint();

      //cookies accepted - execute all callbacks
      if (typeof (cookiesAcceptedCallbacks) !== 'undefined') {
        cookiesAcceptedCallbacks.forEach(function (callback) {
          if (typeof (callback) === 'function')
            callback();
        });
      }
    });

    $('.cookieRefuse').click(function () {
      setCookieConsent('false');
      removeConsentHint();

      //cookies refused - execute all callbacks
      if (typeof (cookiesRefusedCallbacks) !== 'undefined') {
        cookiesRefusedCallbacks.forEach(function (callback) {
          if (typeof (callback) === 'function')
            callback();
        });
      }
    });

    $('.cookieClose').click(function () {
      removeConsentHint();
    });

    function removeConsentHint() {
      $('.cookieConsent').slideUp(400, function () {
        $(this).remove();
      })
    }
  }
});

;
/*!
 * clipboard.js v1.6.0
 * https://zenorocha.github.io/clipboard.js
 *
 * Licensed MIT © Zeno Rocha
 */
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Clipboard = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var DOCUMENT_NODE_TYPE = 9;

/**
 * A polyfill for Element.matches()
 */
if (Element && !Element.prototype.matches) {
    var proto = Element.prototype;

    proto.matches = proto.matchesSelector ||
                    proto.mozMatchesSelector ||
                    proto.msMatchesSelector ||
                    proto.oMatchesSelector ||
                    proto.webkitMatchesSelector;
}

/**
 * Finds the closest parent that matches a selector.
 *
 * @param {Element} element
 * @param {String} selector
 * @return {Function}
 */
function closest (element, selector) {
    while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {
        if (element.matches(selector)) return element;
        element = element.parentNode;
    }
}

module.exports = closest;

},{}],2:[function(require,module,exports){
var closest = require('./closest');

/**
 * Delegates event to a selector.
 *
 * @param {Element} element
 * @param {String} selector
 * @param {String} type
 * @param {Function} callback
 * @param {Boolean} useCapture
 * @return {Object}
 */
function delegate(element, selector, type, callback, useCapture) {
    var listenerFn = listener.apply(this, arguments);

    element.addEventListener(type, listenerFn, useCapture);

    return {
        destroy: function() {
            element.removeEventListener(type, listenerFn, useCapture);
        }
    }
}

/**
 * Finds closest match and invokes callback.
 *
 * @param {Element} element
 * @param {String} selector
 * @param {String} type
 * @param {Function} callback
 * @return {Function}
 */
function listener(element, selector, type, callback) {
    return function(e) {
        e.delegateTarget = closest(e.target, selector);

        if (e.delegateTarget) {
            callback.call(element, e);
        }
    }
}

module.exports = delegate;

},{"./closest":1}],3:[function(require,module,exports){
/**
 * Check if argument is a HTML element.
 *
 * @param {Object} value
 * @return {Boolean}
 */
exports.node = function(value) {
    return value !== undefined
        && value instanceof HTMLElement
        && value.nodeType === 1;
};

/**
 * Check if argument is a list of HTML elements.
 *
 * @param {Object} value
 * @return {Boolean}
 */
exports.nodeList = function(value) {
    var type = Object.prototype.toString.call(value);

    return value !== undefined
        && (type === '[object NodeList]' || type === '[object HTMLCollection]')
        && ('length' in value)
        && (value.length === 0 || exports.node(value[0]));
};

/**
 * Check if argument is a string.
 *
 * @param {Object} value
 * @return {Boolean}
 */
exports.string = function(value) {
    return typeof value === 'string'
        || value instanceof String;
};

/**
 * Check if argument is a function.
 *
 * @param {Object} value
 * @return {Boolean}
 */
exports.fn = function(value) {
    var type = Object.prototype.toString.call(value);

    return type === '[object Function]';
};

},{}],4:[function(require,module,exports){
var is = require('./is');
var delegate = require('delegate');

/**
 * Validates all params and calls the right
 * listener function based on its target type.
 *
 * @param {String|HTMLElement|HTMLCollection|NodeList} target
 * @param {String} type
 * @param {Function} callback
 * @return {Object}
 */
function listen(target, type, callback) {
    if (!target && !type && !callback) {
        throw new Error('Missing required arguments');
    }

    if (!is.string(type)) {
        throw new TypeError('Second argument must be a String');
    }

    if (!is.fn(callback)) {
        throw new TypeError('Third argument must be a Function');
    }

    if (is.node(target)) {
        return listenNode(target, type, callback);
    }
    else if (is.nodeList(target)) {
        return listenNodeList(target, type, callback);
    }
    else if (is.string(target)) {
        return listenSelector(target, type, callback);
    }
    else {
        throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');
    }
}

/**
 * Adds an event listener to a HTML element
 * and returns a remove listener function.
 *
 * @param {HTMLElement} node
 * @param {String} type
 * @param {Function} callback
 * @return {Object}
 */
function listenNode(node, type, callback) {
    node.addEventListener(type, callback);

    return {
        destroy: function() {
            node.removeEventListener(type, callback);
        }
    }
}

/**
 * Add an event listener to a list of HTML elements
 * and returns a remove listener function.
 *
 * @param {NodeList|HTMLCollection} nodeList
 * @param {String} type
 * @param {Function} callback
 * @return {Object}
 */
function listenNodeList(nodeList, type, callback) {
    Array.prototype.forEach.call(nodeList, function(node) {
        node.addEventListener(type, callback);
    });

    return {
        destroy: function() {
            Array.prototype.forEach.call(nodeList, function(node) {
                node.removeEventListener(type, callback);
            });
        }
    }
}

/**
 * Add an event listener to a selector
 * and returns a remove listener function.
 *
 * @param {String} selector
 * @param {String} type
 * @param {Function} callback
 * @return {Object}
 */
function listenSelector(selector, type, callback) {
    return delegate(document.body, selector, type, callback);
}

module.exports = listen;

},{"./is":3,"delegate":2}],5:[function(require,module,exports){
function select(element) {
    var selectedText;

    if (element.nodeName === 'SELECT') {
        element.focus();

        selectedText = element.value;
    }
    else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
        var isReadOnly = element.hasAttribute('readonly');

        if (!isReadOnly) {
            element.setAttribute('readonly', '');
        }

        element.select();
        element.setSelectionRange(0, element.value.length);

        if (!isReadOnly) {
            element.removeAttribute('readonly');
        }

        selectedText = element.value;
    }
    else {
        if (element.hasAttribute('contenteditable')) {
            element.focus();
        }

        var selection = window.getSelection();
        var range = document.createRange();

        range.selectNodeContents(element);
        selection.removeAllRanges();
        selection.addRange(range);

        selectedText = selection.toString();
    }

    return selectedText;
}

module.exports = select;

},{}],6:[function(require,module,exports){
function E () {
  // Keep this empty so it's easier to inherit from
  // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
}

E.prototype = {
  on: function (name, callback, ctx) {
    var e = this.e || (this.e = {});

    (e[name] || (e[name] = [])).push({
      fn: callback,
      ctx: ctx
    });

    return this;
  },

  once: function (name, callback, ctx) {
    var self = this;
    function listener () {
      self.off(name, listener);
      callback.apply(ctx, arguments);
    };

    listener._ = callback
    return this.on(name, listener, ctx);
  },

  emit: function (name) {
    var data = [].slice.call(arguments, 1);
    var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
    var i = 0;
    var len = evtArr.length;

    for (i; i < len; i++) {
      evtArr[i].fn.apply(evtArr[i].ctx, data);
    }

    return this;
  },

  off: function (name, callback) {
    var e = this.e || (this.e = {});
    var evts = e[name];
    var liveEvents = [];

    if (evts && callback) {
      for (var i = 0, len = evts.length; i < len; i++) {
        if (evts[i].fn !== callback && evts[i].fn._ !== callback)
          liveEvents.push(evts[i]);
      }
    }

    // Remove event from queue to prevent memory leak
    // Suggested by https://github.com/lazd
    // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910

    (liveEvents.length)
      ? e[name] = liveEvents
      : delete e[name];

    return this;
  }
};

module.exports = E;

},{}],7:[function(require,module,exports){
(function (global, factory) {
    if (typeof define === "function" && define.amd) {
        define(['module', 'select'], factory);
    } else if (typeof exports !== "undefined") {
        factory(module, require('select'));
    } else {
        var mod = {
            exports: {}
        };
        factory(mod, global.select);
        global.clipboardAction = mod.exports;
    }
})(this, function (module, _select) {
    'use strict';

    var _select2 = _interopRequireDefault(_select);

    function _interopRequireDefault(obj) {
        return obj && obj.__esModule ? obj : {
            default: obj
        };
    }

    var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
        return typeof obj;
    } : function (obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
    };

    function _classCallCheck(instance, Constructor) {
        if (!(instance instanceof Constructor)) {
            throw new TypeError("Cannot call a class as a function");
        }
    }

    var _createClass = function () {
        function defineProperties(target, props) {
            for (var i = 0; i < props.length; i++) {
                var descriptor = props[i];
                descriptor.enumerable = descriptor.enumerable || false;
                descriptor.configurable = true;
                if ("value" in descriptor) descriptor.writable = true;
                Object.defineProperty(target, descriptor.key, descriptor);
            }
        }

        return function (Constructor, protoProps, staticProps) {
            if (protoProps) defineProperties(Constructor.prototype, protoProps);
            if (staticProps) defineProperties(Constructor, staticProps);
            return Constructor;
        };
    }();

    var ClipboardAction = function () {
        /**
         * @param {Object} options
         */
        function ClipboardAction(options) {
            _classCallCheck(this, ClipboardAction);

            this.resolveOptions(options);
            this.initSelection();
        }

        /**
         * Defines base properties passed from constructor.
         * @param {Object} options
         */


        _createClass(ClipboardAction, [{
            key: 'resolveOptions',
            value: function resolveOptions() {
                var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

                this.action = options.action;
                this.emitter = options.emitter;
                this.target = options.target;
                this.text = options.text;
                this.trigger = options.trigger;

                this.selectedText = '';
            }
        }, {
            key: 'initSelection',
            value: function initSelection() {
                if (this.text) {
                    this.selectFake();
                } else if (this.target) {
                    this.selectTarget();
                }
            }
        }, {
            key: 'selectFake',
            value: function selectFake() {
                var _this = this;

                var isRTL = document.documentElement.getAttribute('dir') == 'rtl';

                this.removeFake();

                this.fakeHandlerCallback = function () {
                    return _this.removeFake();
                };
                this.fakeHandler = document.body.addEventListener('click', this.fakeHandlerCallback) || true;

                this.fakeElem = document.createElement('textarea');
                // Prevent zooming on iOS
                this.fakeElem.style.fontSize = '12pt';
                // Reset box model
                this.fakeElem.style.border = '0';
                this.fakeElem.style.padding = '0';
                this.fakeElem.style.margin = '0';
                // Move element out of screen horizontally
                this.fakeElem.style.position = 'absolute';
                this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';
                // Move element to the same position vertically
                var yPosition = window.pageYOffset || document.documentElement.scrollTop;
                this.fakeElem.style.top = yPosition + 'px';

                this.fakeElem.setAttribute('readonly', '');
                this.fakeElem.value = this.text;

                document.body.appendChild(this.fakeElem);

                this.selectedText = (0, _select2.default)(this.fakeElem);
                this.copyText();
            }
        }, {
            key: 'removeFake',
            value: function removeFake() {
                if (this.fakeHandler) {
                    document.body.removeEventListener('click', this.fakeHandlerCallback);
                    this.fakeHandler = null;
                    this.fakeHandlerCallback = null;
                }

                if (this.fakeElem) {
                    document.body.removeChild(this.fakeElem);
                    this.fakeElem = null;
                }
            }
        }, {
            key: 'selectTarget',
            value: function selectTarget() {
                this.selectedText = (0, _select2.default)(this.target);
                this.copyText();
            }
        }, {
            key: 'copyText',
            value: function copyText() {
                var succeeded = void 0;

                try {
                    succeeded = document.execCommand(this.action);
                } catch (err) {
                    succeeded = false;
                }

                this.handleResult(succeeded);
            }
        }, {
            key: 'handleResult',
            value: function handleResult(succeeded) {
                this.emitter.emit(succeeded ? 'success' : 'error', {
                    action: this.action,
                    text: this.selectedText,
                    trigger: this.trigger,
                    clearSelection: this.clearSelection.bind(this)
                });
            }
        }, {
            key: 'clearSelection',
            value: function clearSelection() {
                if (this.target) {
                    this.target.blur();
                }

                window.getSelection().removeAllRanges();
            }
        }, {
            key: 'destroy',
            value: function destroy() {
                this.removeFake();
            }
        }, {
            key: 'action',
            set: function set() {
                var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'copy';

                this._action = action;

                if (this._action !== 'copy' && this._action !== 'cut') {
                    throw new Error('Invalid "action" value, use either "copy" or "cut"');
                }
            },
            get: function get() {
                return this._action;
            }
        }, {
            key: 'target',
            set: function set(target) {
                if (target !== undefined) {
                    if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) {
                        if (this.action === 'copy' && target.hasAttribute('disabled')) {
                            throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');
                        }

                        if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {
                            throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');
                        }

                        this._target = target;
                    } else {
                        throw new Error('Invalid "target" value, use a valid Element');
                    }
                }
            },
            get: function get() {
                return this._target;
            }
        }]);

        return ClipboardAction;
    }();

    module.exports = ClipboardAction;
});

},{"select":5}],8:[function(require,module,exports){
(function (global, factory) {
    if (typeof define === "function" && define.amd) {
        define(['module', './clipboard-action', 'tiny-emitter', 'good-listener'], factory);
    } else if (typeof exports !== "undefined") {
        factory(module, require('./clipboard-action'), require('tiny-emitter'), require('good-listener'));
    } else {
        var mod = {
            exports: {}
        };
        factory(mod, global.clipboardAction, global.tinyEmitter, global.goodListener);
        global.clipboard = mod.exports;
    }
})(this, function (module, _clipboardAction, _tinyEmitter, _goodListener) {
    'use strict';

    var _clipboardAction2 = _interopRequireDefault(_clipboardAction);

    var _tinyEmitter2 = _interopRequireDefault(_tinyEmitter);

    var _goodListener2 = _interopRequireDefault(_goodListener);

    function _interopRequireDefault(obj) {
        return obj && obj.__esModule ? obj : {
            default: obj
        };
    }

    function _classCallCheck(instance, Constructor) {
        if (!(instance instanceof Constructor)) {
            throw new TypeError("Cannot call a class as a function");
        }
    }

    var _createClass = function () {
        function defineProperties(target, props) {
            for (var i = 0; i < props.length; i++) {
                var descriptor = props[i];
                descriptor.enumerable = descriptor.enumerable || false;
                descriptor.configurable = true;
                if ("value" in descriptor) descriptor.writable = true;
                Object.defineProperty(target, descriptor.key, descriptor);
            }
        }

        return function (Constructor, protoProps, staticProps) {
            if (protoProps) defineProperties(Constructor.prototype, protoProps);
            if (staticProps) defineProperties(Constructor, staticProps);
            return Constructor;
        };
    }();

    function _possibleConstructorReturn(self, call) {
        if (!self) {
            throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
        }

        return call && (typeof call === "object" || typeof call === "function") ? call : self;
    }

    function _inherits(subClass, superClass) {
        if (typeof superClass !== "function" && superClass !== null) {
            throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
        }

        subClass.prototype = Object.create(superClass && superClass.prototype, {
            constructor: {
                value: subClass,
                enumerable: false,
                writable: true,
                configurable: true
            }
        });
        if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
    }

    var Clipboard = function (_Emitter) {
        _inherits(Clipboard, _Emitter);

        /**
         * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
         * @param {Object} options
         */
        function Clipboard(trigger, options) {
            _classCallCheck(this, Clipboard);

            var _this = _possibleConstructorReturn(this, (Clipboard.__proto__ || Object.getPrototypeOf(Clipboard)).call(this));

            _this.resolveOptions(options);
            _this.listenClick(trigger);
            return _this;
        }

        /**
         * Defines if attributes would be resolved using internal setter functions
         * or custom functions that were passed in the constructor.
         * @param {Object} options
         */


        _createClass(Clipboard, [{
            key: 'resolveOptions',
            value: function resolveOptions() {
                var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};

                this.action = typeof options.action === 'function' ? options.action : this.defaultAction;
                this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;
                this.text = typeof options.text === 'function' ? options.text : this.defaultText;
            }
        }, {
            key: 'listenClick',
            value: function listenClick(trigger) {
                var _this2 = this;

                this.listener = (0, _goodListener2.default)(trigger, 'click', function (e) {
                    return _this2.onClick(e);
                });
            }
        }, {
            key: 'onClick',
            value: function onClick(e) {
                var trigger = e.delegateTarget || e.currentTarget;

                if (this.clipboardAction) {
                    this.clipboardAction = null;
                }

                this.clipboardAction = new _clipboardAction2.default({
                    action: this.action(trigger),
                    target: this.target(trigger),
                    text: this.text(trigger),
                    trigger: trigger,
                    emitter: this
                });
            }
        }, {
            key: 'defaultAction',
            value: function defaultAction(trigger) {
                return getAttributeValue('action', trigger);
            }
        }, {
            key: 'defaultTarget',
            value: function defaultTarget(trigger) {
                var selector = getAttributeValue('target', trigger);

                if (selector) {
                    return document.querySelector(selector);
                }
            }
        }, {
            key: 'defaultText',
            value: function defaultText(trigger) {
                return getAttributeValue('text', trigger);
            }
        }, {
            key: 'destroy',
            value: function destroy() {
                this.listener.destroy();

                if (this.clipboardAction) {
                    this.clipboardAction.destroy();
                    this.clipboardAction = null;
                }
            }
        }], [{
            key: 'isSupported',
            value: function isSupported() {
                var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];

                var actions = typeof action === 'string' ? [action] : action;
                var support = !!document.queryCommandSupported;

                actions.forEach(function (action) {
                    support = support && !!document.queryCommandSupported(action);
                });

                return support;
            }
        }]);

        return Clipboard;
    }(_tinyEmitter2.default);

    /**
     * Helper function to retrieve attribute value.
     * @param {String} suffix
     * @param {Element} element
     */
    function getAttributeValue(suffix, element) {
        var attribute = 'data-clipboard-' + suffix;

        if (!element.hasAttribute(attribute)) {
            return;
        }

        return element.getAttribute(attribute);
    }

    module.exports = Clipboard;
});

},{"./clipboard-action":7,"good-listener":4,"tiny-emitter":6}]},{},[8])(8)
});;
