'use strict';
var animationPosition = false;
var qrModusAn = false;
var defaultViewport = '';
var videoTrack;
var backgroundsrc = '';					   
var nocam = false;
var hgrAusBeimVerlassen = true;
var customimagehtml = '<div class="background-controls"><label class="upload bgs">Eigenes Ambiente<input type="file" id="getval" name="background-image" accept="image/png, image/jpeg" onchange="readURL()"></label><input type="radio" name="background-size" value="cover" id="bgs1" style="display: none;" checked=""><label for="bgs1" class="bgs needspic">f i t</label><input type="radio" name="background-size" value="contain" id="bgs3" style="display: none;"><label for="bgs3" class="bgs needspic">1 : 1</label><span class="bgs needspic" onclick="createCustom();" id="customdownload">download</span></div><div><canvas id="zielbild" style="display:none;"></canvas></div>';
window.addEventListener("load", function(event) {
	/*
	jQuery('#modellbild_steuerung_ar').unbind('click').click(function(){
		var test = new AR3D('ansicht3D');
	});*/
	
});
function openMainStoffwahl() {
	
	var aktStoff = 0;
	if (oKonfiguration.grundform == 7) aktStoff = jQuery('#aktStoff').val()*1;
	openWindowDesigns(aktStoff);
	
}
function handleCustomAmbiente(blob) {
	if (typeof blob === 'string' && blob != '') {
			ansicht3D.gemueseWeg();
			document.getElementById('ansicht3D').style.backgroundImage = "url(" + blob + ")";
			backgroundsrc = blob;
			jQuery('#ansicht3D').addClass('hasCustomImage');
			eigenesAmbienteAn = true;
	}
	else {
			removeCustomBG();
	}
}
function removeCustomBG() {
		jQuery('#ansicht3D').removeClass('hasCustomImage');
		//jQuery('.uploadremove, .bgs.needspic').hide();
		document.getElementById('ansicht3D').style.backgroundImage = "";
    document.getElementById('ansicht3D').style.backgroundSize = "";
		eigenesAmbienteAn = false;
		ansicht3D.gemueseBack();
		ansicht3D.startAnsicht();
}													 
function readURL(){
        var filesrc = document.getElementById("getval");
        if (filesrc.type !== 'file') return;
		var file = filesrc.files[0];
		var reader = new FileReader();
		reader.onloadend = function() {
			ansicht3D.gemueseWeg();
			jQuery('#modellbild_steuerung > *').removeClass('active')
			document.getElementById('ansicht3D').style.backgroundImage = "url(" + reader.result + ")";
			backgroundsrc = reader.result;
            //gkhead.src = reader.result;
			jQuery('#ansicht3D').addClass('hasCustomImage');
			eigenesAmbienteAn = true;
			if (isTouch === true && typeof expirimental !== 'undefined') {
				//jQuery('#canvasBG').show().css('z-index', 9999999);
				//jQuery('#ansicht3D').css('background-image', '');
				/*
				var gesturableImg = new ImgTouchCanvas({
					canvas: document.getElementById('canvasBG'),
					path: backgroundsrc,
					//desktop: true
				});*/
				//var pinchZoom = new PinchZoomCanvas({
				//	canvas: document.getElementById('canvasBG'),
				//	path: backgroundsrc,
				//	momentum: false,
				//	zoomMax: 2,
				//	doubletap: true,
/*					onZoomEnd: function (zoom, zoomed) {
						console.log("---> is zoomed: %s", zoomed);
						console.log("---> zoom end at %s", zoom);
					},
					onZoom: function (zoom) {
						console.log("---> zoom is %s", zoom);
					}*/
				//});
			}
			//jQuery('.uploadremove, .bgs').css('display', 'inline-block');
            if (reader.result != '') {
                    var sendit = {};
                    var uri ='/_save_img.php';
                    sendit.modellbild = reader.result;
                    sendit.coding='dataUri';
                    sendit.id = 'wf_userbild_' + (Date.now().toString());
        //            sendit.fileExtension = 'png';

                    //alert(uri)
/*
                    jQuery.ajax({
                      url: uri,
                      method:'POST',
                      data:sendit,
                      dataType: "json"
                    })*/
            }
			

		}
		if(file) {
			reader.readAsDataURL(file);
            
		}
		document.getElementById("getval").type='';
		document.getElementById("getval").value='';
		document.getElementById("getval").type='file';
}
function coverImg (ctx, img, ch, cw,  type) {
	if (typeof type === 'undefined') type = 'cover';
  const imgRatio = img.height / img.width
  const winRatio = ch / cw
  if ((imgRatio < winRatio && type === 'contain') || (imgRatio > winRatio && type === 'cover')) {
    const h = cw * imgRatio
    ctx.drawImage(img, 0, (ch - h) / 2, cw, h)
  }
  if ((imgRatio > winRatio && type === 'contain') || (imgRatio < winRatio && type === 'cover')) {
    const w = cw * winRatio / imgRatio
    ctx.drawImage(img, (cw - w) / 2, 0, w, ch)
  }
}
function inIframe () {
    try {
        return window.self !== window.top;
    } catch (e) {
        return true;
    }
}

function ARshare(shareButton) {
	const title = document.title;
	var url = getUrlCurrentConfiguration();
	var blabla = document.querySelector('meta[name="description"]').content;
	var sharedata = {
		title: title,
		url: url,
		text: blabla
	};
	if (!url.match('\\?')) url += '?';

	if (navigator.canShare(sharedata) && !inIframe()) {
		navigator.share(sharedata).catch(console.error);
	} else {
				//shareDialog.classList.add('is-open');
				//shareButton.addEventListener('click', function() {
				//var mailuri = url.replace(':', '%3A');
				//mailuri = mailuri.replace('/', '%2F');
				//mailuri = mailuri.replace('\\?', '%3F');
				//mailuri = mailuri.replace('\\&', '%26');
				//jQuery('.resp-sharing-button__link').attr('href', 'mailto:?subject='+title+'&body='+(mailuri)).show();
				shareButton.style.display = 'none';
				 //jQuery('#linkSharing').click();
	}
}
function toggleFullScreen(forceShutdown) {
  if (typeof forceShutdown === 'undefined') forceShutdown = false;
  var doc = window.document;
  var docEl = doc.documentElement;

  var requestFullScreen = docEl.requestFullscreen || docEl.mozRequestFullScreen || docEl.webkitRequestFullScreen || docEl.msRequestFullscreen;
  var cancelFullScreen = doc.exitFullscreen || doc.mozCancelFullScreen || doc.webkitExitFullscreen || doc.msExitFullscreen;
  if(!doc.fullscreenElement && !doc.mozFullScreenElement && !doc.webkitFullscreenElement && !doc.msFullscreenElement && forceShutdown === false) {
    requestFullScreen.call(docEl);
  }
  else {
    cancelFullScreen.call(doc);
  }
} 
function createCustom() {
	var can = document.getElementById('zielbild');
	var ctx = can.getContext("2d");
	can.height = document.getElementById('ansicht3DCanvas').height;
	can.width = document.getElementById('ansicht3DCanvas').width;
	var image = new Image();
	image.onload = function() {
		var wrh = image.width / image.height;
		var newWidth = can.width;
		var newHeight = newWidth / wrh;
		if (newHeight > can.height) {
			newHeight = can.height;
			newWidth = newHeight * wrh;
		}
		var xOffset = newWidth < can.width ? ((can.width - newWidth) / 2) : 0;
		var yOffset = newHeight < can.height ? ((can.height - newHeight) / 2) : 0;
		coverImg(ctx, image, can.height, can.width, jQuery('input[name="background-size"]:checked').val());

	};
	var image2 = new Image();
	image2.onload = function() {
		ctx.drawImage(image2, 0, 0);
		ctx.restore();
		downloadCustom();
	};
	image.src = backgroundsrc;
	ctx.globalAlpha = 1;
	var config =	{
	  'width':document.getElementById('ansicht3DCanvas').width,
	  'height':document.getElementById('ansicht3DCanvas').height,
	  'format':'png',
	  'quality':'0.6',
	  'noevents': true,
	  'bg_clear': true
	}
	var konfibild = ansicht3D.getPicture(config);
	image2.src = konfibild;
}

function downloadCustom() {
	var format = 'jpeg';
	var quality = .9;
	var bes = document.getElementById('zielbild').toDataURL("image/" + format, quality)
	var a = document.createElement("a"); //Create <a>
	a.href = bes;
	var pname = 'wf_rollo_' + (Date.now().toString())
	a.download = pname + "." + format.replace('jpeg', 'jpg'); //File name Here
	a.click(); //Downloaded file
}

function stopStreamedVideo(videoElem) {
  const stream = videoElem.srcObject;
  const tracks = stream.getTracks();

  tracks.forEach(function(track) {
    track.stop();
  });

  videoElem.srcObject = null;
}
function rolloani() {
  bildgrShow('ansicht3D');
/*	
  var anipos = ansicht3D.rollo.hauptRollo.getOpenState();
  //alert('ansicht3D.rollo.hauptRollo.getOpenState() liefert immer null')
  console.log('anipos: ' + anipos);
  if (anipos != 1) {
    ansicht3D.rollo.stoffRunter();
  } else {
    ansicht3D.rollo.stoffHoch();
  }
*/
	jQuery('#modellbild_steuerung_aufzu').click()
}
var varraints;

var ausgangsposition = {};
var cont3Dheight = 0;

var ScriptPath = (function() {
		  var scripts = document.getElementsByTagName('script'), script = scripts[scripts.length - 1];
		  var path = '';
		  if (script.getAttribute.length !== undefined) {
			path = script.getAttribute('src');
		  } else {
			path = script.getAttribute('src', 2);
		  }
		  if (path) {
			path = path.substr(0,path.lastIndexOf('/')+1);
		  }
		  return path;
	}());
var videoSelect;
var container3d = null;
var container_fehler = '<p id="qr-code">INFO_TEXT</p>';

function iOS() {
  return [
    'iPad Simulator',
    'iPhone Simulator',
    'iPod Simulator',
    'iPad',
    'iPhone',
    'iPod'
  ].includes(navigator.platform)
  || (navigator.userAgent.includes("Mac") && "ontouchend" in document && window.safari !== undefined)

}
function onZoomIn() {

	ansicht3D.orbit.zoomIn();

}

function onZoomOut() {

	ansicht3D.orbit.zoomOut();

}
function ARzoom (step) {
				ansicht3D.camera.position.z += step;
				ansicht3D.renderer.render(ansicht3D.scene,ansicht3D.camera);
}
function ARmove (axis, step) {
				ansicht3D.camera.position[axis] -= step
				ansicht3D.orbit.target[axis] -= step
				ansicht3D.orbit.update()
}
function ARmoveTo (axis, val) {
                ansicht3D.camera.position[axis] = val
                ansicht3D.orbit.target[axis] = val
                ansicht3D.orbit.update()
}
var video = document.getElementById("videoAR");
			var canvas = document.getElementById('canvasAR');

			let streamStarted = false;

			var pause = document.getElementById('pauseAR');
			var screenshot = document.getElementById("screenshot");


			var display = document.querySelector('#display');
			var zurueck = document.querySelector('#zurueck');

function handleError(error) {
    console.log('navigator.getUserMedia error: ', error);
	if (error.name == 'NotFoundError') {
		console.log('kein Gerät da');
		AR3D.cleanup();
		//ansicht3D.quitAR(true);
		return AR3D.addQRCode(0);
	}
	else if (error.name == 'NotReadableError') {
		//alert('Bitte prüfen Sie ob ein anderer Browser (oder Tab) die Kamera verwendet.\nDas Skript kann nicht auf die Kamera zugreifen.. :(');
		alert('Please check if another browser (or tab) uses your camera.\nThe app cannot access your camera.. :(');
	}
	else if (error.name === 'PermissionDeniedError') {
			//alert('Bitte prüfen Sie ob ein anderer Browser (oder Tab) die Kamera verwendet.\nDas Skript kann nicht auf die Kamera zugreifen.. :(');
			alert('Please check if another browser (or tab) uses your camera.\nThe app cannot access your camera.. :(');
	}
	if (error.name === 'NotAllowedError') {
			//alert('Ihr Browser lässt die Verwendung Ihrer Kamera nicht zu :(');
			nocam = true;
			jQuery('#pmodus2').attr('checked', true);
			//jQuery('#getval').click();
	}
}
function GetDevice(tra) {
	var id = tra.getSettings().deviceId;
	while (videoSelect.firstChild) {
			videoSelect.removeChild(videoSelect.firstChild);
	}
	navigator.mediaDevices.enumerateDevices()
	  .then(function(devices) {
		var anz = 0;
		devices.forEach(function(device) {

			if(device.deviceId == id){
				console.log(device.kind + ": " + device.label != undefined ? device.label : 'Default');

			}

			const option = document.createElement('option');
			option.value = device.deviceId;
			if (device.kind === 'audioinput') {
			} else if (device.kind === 'videoinput') {
				option.text = device.label || 'Kamera ' + (videoSelect.length + 1);
				videoSelect.appendChild(option);
				anz++;

			} else {
                //wir freuen uns weil es uns titte ist.. console.log('Some other kind of source/device: ', device.kind);
			}
			if (anz == 1) {

					jQuery(container3d).addClass('hasDeviceInfo');
 			}
			else {
					jQuery(container3d).removeClass('hasDeviceInfo');


			}
			//alert(anz);
		});
	})
	.catch(function(err) {
		console.log(err.name + ": " + err.message);
		//console.log('hier kommt der fallback für keine kamera rein');
	});
}
function toastitbaby() {
    if (ansicht3D.orbit.enabled === false) {
        //e.preventDefault();
        
        jQuery.toast({
            heading: 'Information - ' + translationGet('3d-ar-hint-heading-touch-enabled'),
            text: translationGet('3d-ar-hint-text-touch-enabled'),
            showHideTransition: 'slide',
            icon: 'success'
        });
        ansicht3D.orbit.enabled = true;
        return;
        //alert('touch-a, touch-a, touch-a, touch me...');
    }
    else if (ansicht3D.orbit.enabled === true) {
        //e.preventDefault();
       
        //alert('scheiss iphone!');
       jQuery.toast({
            heading: 'Information - ' + translationGet('3d-ar-hint-heading-touch-disabled'),
            text: translationGet('3d-ar-hint-text-touch-disabled'),
            showHideTransition: 'slide',
            icon: 'warning'
        });
        ansicht3D.orbit.enabled = false;
        //return;
        //alert('finger weg von der muschi...');
    }
}
function showInfos (e) {
					//e.cancelable = false;
					e.preventDefault();

                    toastitbaby();
}
function waehleStoff() {
	jQuery('.twoFabrics').hide();
	if (oKonfiguration.grundform == 7) {
		//alert('selection for day and night coming soon');
		jQuery('.twoFabrics').show();
	}
	else {
		jQuery('.twoFabrics').hide();
		openWindowDesigns(0);
	}
}
function gotStream(stream) {
    window.stream = stream; // make stream available to console

    document.getElementById('videoAR').srcObject = stream;

//return navigator.mediaDevices.enumerateDevices();
}
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a 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); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

var AR3D = /*#__PURE__*/function () {
  function AR3D(container) {
    _classCallCheck(this, AR3D);

    if (typeof QRCodeModel !== 'undefined') {
      console.log('alles fein: QRCodeModel ist ' + (typeof QRCodeModel === "undefined" ? "undefined" : _typeof(QRCodeModel)));
    } else {
      var script = document.createElement('script');
      var url = '/rollos/konfigurator/frameworks/qrcodeSVG.js';
      script.src = url;
      script.className = 'ar-zeugs';
      document.head.appendChild(script);
    }

    if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
      console.log("enumerateDevices() not supported.");
      AR3D.cleanup(true);
      AR3D.addQRCode(0);
    }

    ansicht3D.orbit.enabled = false;
    this._container = document.getElementById(container);
    container3d = this._container;
    cont3Dheight = jQuery(container3d).height();
    ausgangsposition = ansicht3D.rollo.hauptRollo.position;
    AR3D.addCustomStyle();
    AR3D.loadStyle('3d_ar.css', AR3D.init);
  }

  _createClass(AR3D, [{
    key: "ScriptPath",
    value: function ScriptPath() {
      var scripts = document.getElementsByTagName('script'),
          script = scripts[scripts.length - 1];
      var path = '';

      if (script.getAttribute.length !== undefined) {
        path = script.getAttribute('src');
      } else {
        path = script.getAttribute('src', 2);
      }

      if (path) {
        path = path.substr(0, path.lastIndexOf('/') + 1);
      }

      return path;
    }
  }], [{
    key: "addCustomStyle",
    value: function addCustomStyle() {
      var css = ':root { --movehint: "' + translationGet('3d-ar-label-mobil-move') + '";' + "\n" + ' --zoomhint: "' + translationGet('3d-ar-label-mobil-zoom') + '";' + "\n" + ' --infohint: "' + translationGet('3d-ar-label-mobil-info') + '";' + "\n" + '}',
          head = document.head || document.getElementsByTagName('head')[0],
          style = document.createElement('style');
      style.className = 'ar-zeugs';
      head.appendChild(style);
      style.type = 'text/css';

      if (style.styleSheet) {
        style.styleSheet.cssText = css;
      } else {
        style.appendChild(document.createTextNode(css));
      }
    }
  }, {
    key: "loadStyle",
    value: function loadStyle(href, callback) {
      for (var i = 0; i < document.styleSheets.length; i++) {
        if (document.styleSheets[i].href == href) {
          return;
        }
      }

      var head = document.getElementsByTagName('head')[0];
      var link = document.createElement('link');
      link.rel = 'stylesheet';
      link.type = 'text/css';
      link.className = 'ar-zeugs';
      link.href = ScriptPath + href + '?cache=' + Date.now().toString();

      if (callback) {
        link.onload = function () {
          callback();
        };
      }

      head.appendChild(link);
    }
  }, {
    key: "cleanup",
    value: function cleanup(quitMode) {
      if (typeof quitMode === 'undefined') quitMode = true;
      jQuery('body, html').removeClass('ARModus, ausgezoomed');
      var viewport = document.querySelector("meta[name=viewport]");
      viewport.setAttribute('content', defaultViewport);
      jQuery('.ar-zeugs').remove();
      jQuery(container3d).removeClass('hasCustomImage');
      jQuery(container3d).removeClass('infobereich');
      jQuery(container3d).removeClass('AR-info-active');
      jQuery(container3d).removeClass('hasDeviceInfo');
      jQuery(container3d).removeClass('minimalControls');
      jQuery(container3d).removeClass('hiddenControl');
      jQuery.toast().reset('all');
      container3d.style.backgroundImage = "";
      container3d.removeEventListener('langermousedown', showInfos);

      if (quitMode === true) {
        jQuery(container3d).height(cont3Dheight);

		var doc = window.document;
		if(doc.fullscreenElement || doc.mozFullScreenElement || doc.webkitFullscreenElement || doc.msFullscreenElement) toggleFullScreen(true);																																															 
        if (ansicht3D.orbit.enabled === false) {
          jQuery('.orbitAn').show();
        } else {
          jQuery('.orbitAus').show();
        }
		ansicht3D.orbit.enabled = true;
		ansicht3D.gemueseBack();
		ansicht3D.resize();
        ansicht3D.quitAR();
		
      }
    }
  }, {
    key: "initMenu",
    value: function initMenu() {
      jQuery('.dreiD-und-Ar-Bedieninfo-toggler').unbind('click').click(function () {
        jQuery(container3d).toggleClass('AR-info-active');
      });
      jQuery('.Info-Bedienung section').unbind('click').click(function () {
        jQuery('.Info-Bedienung section').removeClass('AR-active');
        jQuery(this).addClass('AR-active');
      });
      jQuery(container3d).addClass('minimalControls');
      var mycontainerwidth = jQuery(container3d).width();
      console.log(mycontainerwidth);
      jQuery('.AR-Steuerung.AR-Zoom-it-neu, .AR-Steuerung.AR-Move').removeClass('aktiveControl');
      jQuery('.arsticky').removeClass('aktiveControl');
      jQuery('.AR-Steuerung, #screenshot').removeClass('verschwindibus');
      jQuery('.AR-Move .action-info, .AR-Zoom-it-neu .action-info').unbind('click');

      if (mycontainerwidth >= 740) {
        jQuery('.AR-Steuerung.AR-Zoom-it-neu, .AR-Steuerung.AR-Move').addClass('aktiveControl');
        jQuery('.arsticky').addClass('aktiveControl');
      } else {
        jQuery('.AR-Move .action-info, .AR-Zoom-it-neu .action-info').unbind('click').click(function () {
          if (jQuery(this).parent('div').hasClass('aktiveControl')) {
            jQuery('.AR-Steuerung, #screenshot').removeClass('verschwindibus');
            jQuery(this).parent('div').removeClass('aktiveControl');
          } else {
            jQuery(this).parent('div').addClass('aktiveControl');
            jQuery('.AR-Steuerung, #screenshot').not(jQuery(this).parent('div')).addClass('verschwindibus');
          }

          jQuery('.arsticky, #screenshot').removeClass('verschwindibus');
          jQuery('.arsticky').not(jQuery(this).parent('div')).removeClass('aktiveControl');
        });
      }
				var goFS = document.getElementById("goFS");
				if ('fullscreenEnabled' in document && document.fullscreenEnabled === true) {
						jQuery('#goFS').show();
						goFS.addEventListener("click", function() {
								toggleFullScreen();
						}, false);
				}
				else {
						jQuery('#goFS').remove();
				}
				if ('canShare' in navigator && typeof navigator.canShare === 'function' && !inIframe()) {
				  jQuery('#ARsharebutton').show();
				}
				else {
				  jQuery('#ARsharebutton').hide();
				}
    }
  }, {
    key: "addQRCode",
    value: function addQRCode(statusnr, callback, quitAR) {
      if (typeof quitAR === 'undefined') quitAR = false;
      jQuery('#qr-code').remove();
      var infotext_nodevice = translationGet('ar-infohtml-nodevice'); //'Sie haben keine Kamera oder der Zugriff ist nicht möglich. Für den AR-Modus wird empfohlen ein mobiles Gerät (Tablet oder Handy) zu verwenden.<br>Scannen Sie den angezeigten QR-Code und rufen Sie die dort hinterlegte Seite auf.';

      var infotext_onedevice = translationGet('ar-infohtml-onedevice'); //'Sie haben nur eine Kamera. Für den AR-Modus wird empfohlen ein mobiles Gerät (Tablet oder Handy) zu verwenden.<br>Scannen Sie den angezeigten QR-Code und rufen Sie die dort hinterlegte Seite auf.<br>Wenn Sie hier klicken können Sie mit dem aktuellen Gerät fortfahren.';
      //qrModusAn = true;

      var info = statusnr == 1 ? infotext_onedevice : infotext_nodevice;
      jQuery('#ansicht3D').prepend(container_fehler.replace('INFO_TEXT', info));
      var url = getUrlCurrentConfiguration();
      var qrcode = new QRCode({
        content: url,
        padding: 4,
        width: 256,
        height: 256,
        color: "#000000",
        background: "#ffffff",
        ecl: "M"
      });
      jQuery('#ansicht3DCanvas').hide();
      jQuery('#qr-code').append('<p>' + qrcode.svg() + '</p>').click(function () {
        jQuery(this).remove();
        jQuery('#ansicht3DCanvas').show();
		//alert('email to timm');
		if (typeof callback === 'function') callback();
        if (quitAR === true) ansicht3D.quitAR(true);
      });
    }
  }, {
    key: "gibfeuer",
    value: function gibfeuer(el, etype) {
      if (el.fireEvent) {
        el.fireEvent('on' + etype);
      } else {
        var evObj = document.createEvent('Events');
        evObj.initEvent(etype, true, false);
        el.dispatchEvent(evObj);
      }
    }
  }, {
    key: "init",
    value: function init(resizeAnsicht) {
      jQuery('body, html').addClass('ARModus');
      jQuery('.orbitAn, .orbitAus,.dreiDhinweis').hide();
      var myc = container3d;
	  jQuery(container3d).append(customimagehtml);

		
		if (typeof aConfig !== 'undefined' && aConfig.hasOwnProperty('zeichnungHatDownloadButton') && aConfig.zeichnungHatDownloadButton === true) {
			jQuery(container3d).addClass('downloadEnabled');
		}
		if (typeof aConfig !== 'undefined' && aConfig.hasOwnProperty('zeichnungHatGroessenwahl') && aConfig.zeichnungHatGroessenwahl === true) {
			jQuery(container3d).addClass('bgsizeEnabled');
		}
      jQuery(myc).data('langermousedown-delay', 150).unbind('langermousedown');
      myc.addEventListener('langermousedown', showInfos);
      var viewport = document.querySelector("meta[name=viewport]");
      defaultViewport = viewport.getAttribute('content');
      viewport.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no');
      var topmenuhtml = '<div class="dreiD-und-Ar-Interface pos-top ar-zeugs"><div class="Ar-toggler Ar-only" id="zurueck"></div><div class="AR-Important-Notice" onclick="AR3D.addQRCode(1, false)"><span>i</span></div><div class="dreiD-und-Ar-Bedieninfo-toggler Ar-toggler"><span>i</span> info</div><div onclick="ARshare(this)" id="ARsharebutton" style="display:none;"></div><div id="goFS">FS</div></div><div class="Ar-Info ar-zeugs"></div><div class="ar-zeugs"><div class="Info-Bedienung"><div class="AR-overlay"><section class="arinfo AR-active"><p>%TEXT_INFO_TRANSLATE%</p></section><section class="armove"><p>%TEXT_MOVE_TRANSLATE%</p></section><section class="arzoom"><p>%TEXT_ZOOM_TRANSLATE%</p></section></div></div></div></div></div>';
      topmenuhtml = topmenuhtml.replace('%AN%', translationGet('ar-mode-on'));
	  topmenuhtml = topmenuhtml.replace('%AUS%', translationGet('ar-mode-off'));
      topmenuhtml = topmenuhtml.replace('%TEXT_INFO_TRANSLATE%', translationGet('3d-ar-infotext-mobil-info'));
      topmenuhtml = topmenuhtml.replace('%TEXT_MOVE_TRANSLATE%', translationGet('3d-ar-infotext-mobil-move'));
      topmenuhtml = topmenuhtml.replace('%TEXT_ZOOM_TRANSLATE%', translationGet('3d-ar-infotext-mobil-zoom'));
      var bottommenuhtml = '<div class="AR-Steuerung AR-Stoff ar-zeugs"><span class="twoFabrics" style="display:none;"><span onclick="openWindowDesigns(0);jQuery(\'.twoFabrics\').hide();">%Stoffe% 1</span><span onclick="openWindowDesigns(1);jQuery(\'.twoFabrics\').hide();">%Stoffe% 2</span></span><span onclick="waehleStoff();">%Stoffe%</span></div><div class="AR-Steuerung AR-Ani ar-zeugs" onclick="rolloani();"><span>Animate</span></div><div class="AR-Steuerung AR-Zoom-it-neu ar-zeugs arsticky"><div class="AR-leer action-info"></div><div class="AR-zoomout" id="zoom-out"></div><div class="AR-zoomslide"><input type="range" min="0.1" max="3" step=".01" id="ARzoomslider" class="slider" value="1.2" oninput="ansicht3D.camera.position.z = this.value;ansicht3D.renderer.render(ansicht3D.scene,ansicht3D.camera);"></div><div class="AR-zoomin" id="zoom-in"></div></div><div class="AR-Steuerung AR-Move ar-zeugs arsticky"><div class="AR-Moveleft" onclick="ARmove(\'x\', +.01);"></div><div class="AR-Moveup" onclick="ARmove(\'y\', .03);"></div><div class="AR-Movedown" onclick="ARmove(\'y\', -.03);"></div><div class="AR-Moveright" onclick="ARmove(\'x\', -.01);"></div><div class="AR-leer action-info"></div></div><div class="ar-zeugs"><div id="AR-confirm-shutdown-overlay" class="AR-overlay"><p>Wir hoffen, unser AR-Modus hat Ihnen gefallen.</p><div class="butt">' + translationGet('ar-mode-exit') + '</div><p>&copy; 2020 window-fashion AG<br><img src="https://window-fashion.ag/assets/img/windowfashion-logo-2020.svg" alt="window-fashion AG" style="height:70px;display:block;"><span class="small">So long .. and thanks for all the fish.. ;-)</span></p></div></div>';
      bottommenuhtml = bottommenuhtml.replaceAll('%Stoffe%', translationGet('Stoff'));
      var needed_html = '<div id="videoContainer" class="ar-zeugs"><video id="videoAR" class="ardisplay ar-zeugs" autoplay muted playsinline style="pointer-events: none;"></video></div><canvas id="canvasAR" class="d-none ar-zeugs" style="width:100%;"></canvas><div class="video-options ar-zeugs"><select name="cam_select" id="videoSource" class="custom-select"></select></div><input type="range" class="slider ar-zeugs" name="zoomlevel" id="zoomlevel_" style="z-index:9999;position:absolute;bottom:1em;left:1em;display:none;"><input type="radio" name="pmodus" id="pmodus1" class="ar-zeugs" style="display:none;" checked><input type="radio" name="pmodus" id="pmodus2" class="ar-zeugs" style="display:none;"><span id="screenshot" title="ScreenShot" class="ar-zeugs"></span><span id="picturezoomtoggler" class="ar-zeugs" onclick="jQuery(\'body\').toggleClass(\'ausgezoomed\');"></span>';
      jQuery(container3d).prepend(needed_html);
      if (typeof resizeAnsicht === 'undefined') resizeAnsicht = true;
      var anzDevices = 0;
      var onlyDevice = '0';
      var cwidth = 1920;
      var videoSource = undefined;
      var aspRatio = 1;
      videoSelect = document.querySelector('select#videoSource');
      varraints = {
        audio: false,
        video: {
          deviceId: videoSource ? {
            exact: videoSource
          } : undefined,
          facingMode: {
            ideal: "environment"
          },
          width: {
            ideal: cwidth
          },
          aspectRatio: {
            ideal: aspRatio
          }
        }
      };

      if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
        console.log("enumerateDevices() not supported.");
        nocam = true;
      } 
	  else {
		  //if (1 == 1) {
        var doScreenshot = function doScreenshot() {
          if (jQuery(container3d).hasClass('hasCustomImage')) {
            container3d.style.backgroundImage = '';
            jQuery(container3d).removeClass('AR-info-active');
            jQuery(container3d).removeClass('hasCustomImage');
			backgroundsrc = '';
            if (nocam === false) {
              var tracks = window.stream.getTracks();

              for (var i = 0; i < tracks.length; i++) {
                tracks[i].enabled = true;
              }
            }
          } else {
            if (jQuery('#pmodus1').is(':checked')) {
              var screenshot = document.getElementById('screenshot');
              document.getElementById('canvasAR').width = document.getElementById('videoAR').videoWidth;
              document.getElementById('canvasAR').height = document.getElementById('videoAR').videoHeight;
              document.getElementById('canvasAR').getContext('2d').drawImage(document.getElementById('videoAR'), 0, 0);
              var bg = 'url("' + document.getElementById('canvasAR').toDataURL('image/webp') + '")';
              container3d.style.backgroundImage = bg;
			  backgroundsrc = document.getElementById('canvasAR').toDataURL('image/webp');
              container3d.classList.add('hasCustomImage');
            } else {
              jQuery('#getval').click();
            }
          }
        };

        var screenshot = document.getElementById('screenshot');
        screenshot.onclick = doScreenshot;
        var devicetext = '';
        var actId = null;
        navigator.mediaDevices.enumerateDevices().then(function (devices) {
          devices.forEach(function (device) {
            devicetext += device.kind + ": " + device.label + " id = " + device.deviceId + '\n';

            if (device.kind == 'videoinput') {
              console.log(device.kind + ": " + device.label + " id = " + device.deviceId);
              anzDevices++;
              var option = document.createElement('option');
              option.value = device.deviceId;
              option.text = device.label || 'Kamera ' + (videoSelect.length + 1);
              videoSelect.appendChild(option);
              actId = device.deviceId;
            }
          });
          console.log(devicetext);
          console.log(anzDevices + ' Kamera(s) gefunden');

          if (anzDevices == 1) {
            jQuery(container3d).addClass('hasDeviceInfo');
          } else {
            jQuery(container3d).removeClass('hasDeviceInfo');
          }
        }).catch(function (err) {
          console.log(err.name + ": " + err.message);
         AR3D.cleanup();
          return AR3D.addQRCode(0);
        }).then(function () {
		//if (typeof navigator.mediaDevices !== 'undefined') {
          navigator.mediaDevices.getUserMedia(varraints).then(gotStream).then(function () {
            var tracks = window.stream.getTracks();

            for (var i = 0; i < tracks.length; i++) {
              GetDevice(tracks[i]);
            }
          }).catch(handleError);
		//}
          jQuery(container3d).prepend(topmenuhtml);
          jQuery(container3d).prepend(bottommenuhtml);
		  jQuery('input[name="background-size"]').change(function() {
			  jQuery('#ansicht3D').css('background-size', jQuery(this).val() );
													   
			});
          jQuery('#AR-confirm-shutdown-overlay').click(function () {
            AR3D.cleanup();
          });
          document.getElementById('zurueck').addEventListener("click", function () {
			  /*
            jQuery('#AR-confirm-shutdown-overlay').css({
              'display': 'flex',
              'opacity': 1
            }).fadeIn(3000);*/
			AR3D.cleanup();
            jQuery('#qr-code').remove();
          });
          var zoomIn = document.getElementById('zoom-in');
          var zoomOut = document.getElementById('zoom-out');
          zoomIn.addEventListener('click', onZoomIn, false);
          zoomOut.addEventListener('click', onZoomOut, false);
          AR3D.initMenu();
          ansicht3D.resize();
          window.addEventListener("orientationchange", function (event) {
            jQuery('body').removeClass('ausgezoomed');
            ansicht3D.resize();
            AR3D.initMenu();
          });
          window.addEventListener("resize", function (event) {
            ansicht3D.resize();
            AR3D.initMenu();
          });
		  ansicht3D.orbit.enabled=true;
          ansicht3D.fitCameraToObjectStocki(null, 1.2, 0.00);
          ARmove('y', .2);
          ansicht3D.orbit.update();
          ansicht3D.renderer.render(ansicht3D.scene, ansicht3D.camera);
          //toastitbaby();
			
        }).catch(function (err) {
          //console.log(err.name + ": " + err.message);
          //return AR3D.addQRCode(0);
        });
      }
    }
  }]);

  return AR3D;
}();

(function (window, document) {

    'use strict';

    // local timer object based on rAF
    var timer = null;

    // check if we're using a touch screen
    var isTouchMe = (('ontouchstart' in window) || (navigator.MaxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0));
//works and is true in chrome since v70 too
    // switch to touch events if using a touch screen
    var mouseDown = isTouchMe ? 'touchstart' : 'mousedown';
    var mouseUp = isTouchMe ? 'touchend' : 'mouseup';
    var mouseMove = isTouchMe ? 'touchmove' : 'mousemove';

    // track number of pixels the mouse moves during long press
    var startX = 0; // mouse x position when timer started
    var startY = 0; // mouse y position when timer started
    var maxDiffX = 50; // max number of X pixels the mouse can move during long press before it is canceled
    var maxDiffY = 50; // max number of Y pixels the mouse can move during long press before it is canceled

    // patch CustomEvent to allow constructor creation (IE/Chrome)
    if (typeof window.CustomEvent !== 'function') {

        window.CustomEvent = function(event, params) {

            params = params || { bubbles: false, cancelable: false, detail: undefined };

            var evt = document.createEvent('CustomEvent');
            evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
            return evt;
        };

        window.CustomEvent.prototype = window.Event.prototype;
    }

    // requestAnimationFrame() shim by Paul Irish
    window.requestAnimFrame = (function() {
        return window.requestAnimationFrame ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame ||
            window.oRequestAnimationFrame ||
            window.msRequestAnimationFrame || function(callback) {
                window.setTimeout(callback, 1000 / 60);
            };
    })();

    /**
     * Behaves the same as setTimeout except uses requestAnimationFrame() where possible for better performance
     * @param {function} fn The callback function
     * @param {int} delay The delay in milliseconds
     * @returns {object} handle to the timeout object
     */
    function requestTimeout(fn, delay) {

        if (!window.requestAnimationFrame && !window.webkitRequestAnimationFrame &&
            !(window.mozRequestAnimationFrame && window.mozCancelRequestAnimationFrame) && // Firefox 5 ships without cancel support
            !window.oRequestAnimationFrame && !window.msRequestAnimationFrame) return window.setTimeout(fn, delay);

        var start = new Date().getTime();
        var handle = {};

        var loop = function() {
            var current = new Date().getTime();
            var delta = current - start;

            if (delta >= delay) {
                fn.call();
            }
            else {
                handle.value = requestAnimFrame(loop);
            }
        };

        handle.value = requestAnimFrame(loop);

        return handle;
    }

    /**
     * Behaves the same as clearTimeout except uses cancelRequestAnimationFrame() where possible for better performance
     * @param {object} handle The callback function
     * @returns {void}
     */
    function clearRequestTimeout(handle) {
        if (handle) {
            window.cancelAnimationFrame ? window.cancelAnimationFrame(handle.value) :
            window.webkitCancelAnimationFrame ? window.webkitCancelAnimationFrame(handle.value) :
            window.webkitCancelRequestAnimationFrame ? window.webkitCancelRequestAnimationFrame(handle.value) : /* Support for legacy API */
            window.mozCancelRequestAnimationFrame ? window.mozCancelRequestAnimationFrame(handle.value) :
            window.oCancelRequestAnimationFrame    ? window.oCancelRequestAnimationFrame(handle.value) :
            window.msCancelRequestAnimationFrame ? window.msCancelRequestAnimationFrame(handle.value) :
            clearTimeout(handle);
        }
    }

    /**
     * Fires the 'langermousedown' event on element
     * @param {MouseEvent|TouchEvent} originalEvent The original event being fired
     * @returns {void}
     */
    function fireLongPressEvent(originalEvent) {

        clearLongPressTimer();

        var clientX = isTouchMe ? originalEvent.touches[0].clientX : originalEvent.clientX,
            clientY = isTouchMe ? originalEvent.touches[0].clientY : originalEvent.clientY;

        // fire the langermousedown event
        var suppressClickEvent = this.dispatchEvent(new CustomEvent('langermousedown', { bubbles: true, cancelable: true, detail: { clientX: clientX, clientY: clientY } }));

        if (suppressClickEvent) {

            // temporarily intercept and clear the next click
            document.addEventListener(mouseUp, function clearMouseUp(e) {
                document.removeEventListener(mouseUp, clearMouseUp, true);
                cancelEvent(e);
            }, true);
        }
    }

    /**
     * method responsible for starting the long press timer
     * @param {event} e - event object
     * @returns {void}
     */
    function startLongPressTimer(e) {

        clearLongPressTimer(e);

        var el = e.target;

        // get delay from html attribute if it exists, otherwise default to 1500
        var longPressDelayInMs = parseInt(el.getAttribute('data-langermousedown-delay') || '400', 10);

        // start the timer
        timer = requestTimeout(fireLongPressEvent.bind(el, e), longPressDelayInMs);
    }

    /**
     * method responsible for clearing a pending long press timer
     * @param {event} e - event object
     * @returns {void}
     */
    function clearLongPressTimer(e) {
        clearRequestTimeout(timer);
        timer = null;
    }

    /**
    * Cancels the current event
    * @param {object} e - browser event object
    * @returns {void}
    */
    function cancelEvent(e) {
        e.stopImmediatePropagation();
        e.preventDefault();
        e.stopPropagation();
    }

    /**
     * Starts the timer on mouse down and logs current position
     * @param {object} e - browser event object
     * @returns {void}
     */
    function mouseDownHandler(e) {
        startX = e.clientX;
        startY = e.clientY;
        startLongPressTimer(e);
    }

    /**
     * If the mouse moves n pixels during langermousedown, cancel the timer
     * @param {object} e - browser event object
     * @returns {void}
     */
    function mouseMoveHandler(e) {

        // calculate total number of pixels the pointer has moved
        var diffX = Math.abs(startX - e.clientX);
        var diffY = Math.abs(startY - e.clientY);

        // if pointer has moved more than allowed, cancel the langermousedown timer and therefore the event
        //if (diffX >= maxDiffX || diffY >= maxDiffY) {
            clearLongPressTimer(e);
        //}
    }

    // hook events that clear a pending long press event
    document.addEventListener(mouseUp, clearLongPressTimer, true);
    document.addEventListener(mouseMove, mouseMoveHandler, true);
    document.addEventListener('wheel', clearLongPressTimer, true);
    document.addEventListener('scroll', clearLongPressTimer, true);

    // hook events that can trigger a long press event
    document.addEventListener(mouseDown, mouseDownHandler, true); // <- start

}(window, document));

// jQuery toast plugin created by Kamran Ahmed copyright MIT license 2015
if ( typeof Object.create !== 'function' ) {
    Object.create = function( obj ) {
        function F() {}
        F.prototype = obj;
        return new F();
    };
}

(function( $, window, document, undefined ) {

    "use strict";
    
    var Toast = {

        _positionClasses : ['bottom-left', 'bottom-right', 'top-right', 'top-left', 'bottom-center', 'top-center', 'mid-center'],
        _defaultIcons : ['success', 'error', 'info', 'warning'],

        init: function (options, elem) {
            this.prepareOptions(options, $.toast.options);
            this.process();
        },

        prepareOptions: function(options, options_to_extend) {
            var _options = {};
            if ( ( typeof options === 'string' ) || ( options instanceof Array ) ) {
                _options.text = options;
            } else {
                _options = options;
            }
            this.options = $.extend( {}, options_to_extend, _options );
        },

        process: function () {
            this.setup();
            this.addToDom();
            this.position();
            this.bindToast();
            this.animate();
        },

        setup: function () {
            
            var _toastContent = '';
            
            this._toastEl = this._toastEl || $('<div></div>', {
                class : 'jq-toast-single'
            });

            // For the loader on top
            _toastContent += '<span class="jq-toast-loader"></span>';

            if ( this.options.allowToastClose ) {
                _toastContent += '<span class="close-jq-toast-single">&times;</span>';
            };

            if ( this.options.text instanceof Array ) {

                if ( this.options.heading ) {
                    _toastContent +='<h2 class="jq-toast-heading">' + this.options.heading + '</h2>';
                };

                _toastContent += '<ul class="jq-toast-ul">';
                for (var i = 0; i < this.options.text.length; i++) {
                    _toastContent += '<li class="jq-toast-li" id="jq-toast-item-' + i + '">' + this.options.text[i] + '</li>';
                }
                _toastContent += '</ul>';

            } else {
                if ( this.options.heading ) {
                    _toastContent +='<h2 class="jq-toast-heading">' + this.options.heading + '</h2>';
                };
                _toastContent += this.options.text;
            }

            this._toastEl.html( _toastContent );

            if ( this.options.bgColor !== false ) {
                this._toastEl.css("background-color", this.options.bgColor);
            };

            if ( this.options.textColor !== false ) {
                this._toastEl.css("color", this.options.textColor);
            };

            if ( this.options.textAlign ) {
                this._toastEl.css('text-align', this.options.textAlign);
            }

            if ( this.options.icon !== false ) {
                this._toastEl.addClass('jq-has-icon');

                if ( $.inArray(this.options.icon, this._defaultIcons) !== -1 ) {
                    this._toastEl.addClass('jq-icon-' + this.options.icon);
                };
            };

            if ( this.options.class !== false ){
                this._toastEl.addClass(this.options.class)
            }
        },

        position: function () {
            if ( ( typeof this.options.position === 'string' ) && ( $.inArray( this.options.position, this._positionClasses) !== -1 ) ) {

                if ( this.options.position === 'bottom-center' ) {
                    this._container.css({
                        left: ( $(window).outerWidth() / 2 ) - this._container.outerWidth()/2,
                        bottom: 20
                    });
                } else if ( this.options.position === 'top-center' ) {
                    this._container.css({
                        left: ( $(window).outerWidth() / 2 ) - this._container.outerWidth()/2,
                        top: 20
                    });
                } else if ( this.options.position === 'mid-center' ) {
                    this._container.css({
                        left: ( $(window).outerWidth() / 2 ) - this._container.outerWidth()/2,
                        top: ( $(window).outerHeight() / 2 ) - this._container.outerHeight()/2
                    });
                } else {
                    this._container.addClass( this.options.position );
                }

            } else if ( typeof this.options.position === 'object' ) {
                this._container.css({
                    top : this.options.position.top ? this.options.position.top : 'auto',
                    bottom : this.options.position.bottom ? this.options.position.bottom : 'auto',
                    left : this.options.position.left ? this.options.position.left : 'auto',
                    right : this.options.position.right ? this.options.position.right : 'auto'
                });
            } else {
                this._container.addClass( 'bottom-left' );
            }
        },

        bindToast: function () {

            var that = this;

            this._toastEl.on('afterShown', function () {
                that.processLoader();
            });

            this._toastEl.find('.close-jq-toast-single').on('click', function ( e ) {

                e.preventDefault();

                if( that.options.showHideTransition === 'fade') {
                    that._toastEl.trigger('beforeHide');
                    that._toastEl.fadeOut(function () {
                        that._toastEl.trigger('afterHidden');
                    });
                } else if ( that.options.showHideTransition === 'slide' ) {
                    that._toastEl.trigger('beforeHide');
                    that._toastEl.slideUp(function () {
                        that._toastEl.trigger('afterHidden');
                    });
                } else {
                    that._toastEl.trigger('beforeHide');
                    that._toastEl.hide(function () {
                        that._toastEl.trigger('afterHidden');
                    });
                }
            });

            if ( typeof this.options.beforeShow == 'function' ) {
                this._toastEl.on('beforeShow', function () {
                    that.options.beforeShow(that._toastEl);
                });
            };

            if ( typeof this.options.afterShown == 'function' ) {
                this._toastEl.on('afterShown', function () {
                    that.options.afterShown(that._toastEl);
                });
            };

            if ( typeof this.options.beforeHide == 'function' ) {
                this._toastEl.on('beforeHide', function () {
                    that.options.beforeHide(that._toastEl);
                });
            };

            if ( typeof this.options.afterHidden == 'function' ) {
                this._toastEl.on('afterHidden', function () {
                    that.options.afterHidden(that._toastEl);
                });
            };

            if ( typeof this.options.onClick == 'function' ) {
                this._toastEl.on('click', function () {
                    that.options.onClick(that._toastEl);
                });
            };
        },

        addToDom: function () {

             var _container = $('.jq-toast-wrap');
             
             if ( _container.length === 0 ) {
                
                _container = $('<div></div>',{
                    class: "jq-toast-wrap",
                    role: "alert",
                    "aria-live": "polite"
                });

                $('body').append( _container );

             } else if ( !this.options.stack || isNaN( parseInt(this.options.stack, 10) ) ) {
                _container.empty();
             }

             _container.find('.jq-toast-single:hidden').remove();

             _container.append( this._toastEl );

            if ( this.options.stack && !isNaN( parseInt( this.options.stack ), 10 ) ) {
                
                var _prevToastCount = _container.find('.jq-toast-single').length,
                    _extToastCount = _prevToastCount - this.options.stack;

                if ( _extToastCount > 0 ) {
                    $('.jq-toast-wrap').find('.jq-toast-single').slice(0, _extToastCount).remove();
                };

            }

            this._container = _container;
        },

        canAutoHide: function () {
            return ( this.options.hideAfter !== false ) && !isNaN( parseInt( this.options.hideAfter, 10 ) );
        },

        processLoader: function () {
            // Show the loader only, if auto-hide is on and loader is demanded
            if (!this.canAutoHide() || this.options.loader === false) {
                return false;
            }

            var loader = this._toastEl.find('.jq-toast-loader');

            // 400 is the default time that jquery uses for fade/slide
            // Divide by 1000 for milliseconds to seconds conversion
            var transitionTime = (this.options.hideAfter - 400) / 1000 + 's';
            var loaderBg = this.options.loaderBg;

            var style = loader.attr('style') || '';
            style = style.substring(0, style.indexOf('-webkit-transition')); // Remove the last transition definition

            style += '-webkit-transition: width ' + transitionTime + ' ease-in; \
                      -o-transition: width ' + transitionTime + ' ease-in; \
                      transition: width ' + transitionTime + ' ease-in; \
                      background-color: ' + loaderBg + ';';


            loader.attr('style', style).addClass('jq-toast-loaded');
        },

        animate: function () {

            var that = this;

            this._toastEl.hide();

            this._toastEl.trigger('beforeShow');

            if ( this.options.showHideTransition.toLowerCase() === 'fade' ) {
                this._toastEl.fadeIn(function ( ){
                    that._toastEl.trigger('afterShown');
                });
            } else if ( this.options.showHideTransition.toLowerCase() === 'slide' ) {
                this._toastEl.slideDown(function ( ){
                    that._toastEl.trigger('afterShown');
                });
            } else {
                this._toastEl.show(function ( ){
                    that._toastEl.trigger('afterShown');
                });
            }

            if (this.canAutoHide()) {

                var that = this;

                window.setTimeout(function(){
                    
                    if ( that.options.showHideTransition.toLowerCase() === 'fade' ) {
                        that._toastEl.trigger('beforeHide');
                        that._toastEl.fadeOut(function () {
                            that._toastEl.trigger('afterHidden');
                        });
                    } else if ( that.options.showHideTransition.toLowerCase() === 'slide' ) {
                        that._toastEl.trigger('beforeHide');
                        that._toastEl.slideUp(function () {
                            that._toastEl.trigger('afterHidden');
                        });
                    } else {
                        that._toastEl.trigger('beforeHide');
                        that._toastEl.hide(function () {
                            that._toastEl.trigger('afterHidden');
                        });
                    }

                }, this.options.hideAfter);
            };
        },

        reset: function ( resetWhat ) {

            if ( resetWhat === 'all' ) {
                $('.jq-toast-wrap').remove();
            } else {
                this._toastEl.remove();
            }

        },

        update: function(options) {
            this.prepareOptions(options, this.options);
            this.setup();
            this.bindToast();
        },
        
        close: function() {
            this._toastEl.find('.close-jq-toast-single').click();
        }
    };
    
    $.toast = function(options) {
        var toast = Object.create(Toast);
        toast.init(options, this);

        return {
            
            reset: function ( what ) {
                toast.reset( what );
            },

            update: function( options ) {
                toast.update( options );
            },
            
            close: function( ) {
                toast.close( );
            }
        }
    };

    $.toast.options = {
        text: '',
        heading: '',
        showHideTransition: 'fade',
        allowToastClose: true,
        hideAfter: 4000,
        loader: false,
        loaderBg: '#9EC600',
        stack: 5,
        position: {},//'bottom-left',
        bgColor: false,
        textColor: false,
        textAlign: 'left',
        icon: false,
        beforeShow: function () {},
        afterShown: function () {},
        beforeHide: function () {},
        afterHidden: function () {},
        onClick: function () {}
    };

})( jQuery, window, document );

function QR8bitByte(data) {
  this.mode = QRMode.MODE_8BIT_BYTE;
  this.data = data;
  this.parsedData = [];

  // Added to support UTF-8 Characters
  for (var i = 0, l = this.data.length; i < l; i++) {
    var byteArray = [];
    var code = this.data.charCodeAt(i);

    if (code > 0x10000) {
      byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18);
      byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12);
      byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6);
      byteArray[3] = 0x80 | (code & 0x3F);
    } else if (code > 0x800) {
      byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12);
      byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6);
      byteArray[2] = 0x80 | (code & 0x3F);
    } else if (code > 0x80) {
      byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6);
      byteArray[1] = 0x80 | (code & 0x3F);
    } else {
      byteArray[0] = code;
    }

    this.parsedData.push(byteArray);
  }

  this.parsedData = Array.prototype.concat.apply([], this.parsedData);

  if (this.parsedData.length != this.data.length) {
    this.parsedData.unshift(191);
    this.parsedData.unshift(187);
    this.parsedData.unshift(239);
  }
}

QR8bitByte.prototype = {
  getLength: function (buffer) {
    return this.parsedData.length;
  },
  write: function (buffer) {
    for (var i = 0, l = this.parsedData.length; i < l; i++) {
      buffer.put(this.parsedData[i], 8);
    }
  }
};

function QRCodeModel(typeNumber, errorCorrectLevel) {
  this.typeNumber = typeNumber;
  this.errorCorrectLevel = errorCorrectLevel;
  this.modules = null;
  this.moduleCount = 0;
  this.dataCache = null;
  this.dataList = [];
}

QRCodeModel.prototype={addData:function(data){var newData=new QR8bitByte(data);this.dataList.push(newData);this.dataCache=null;},isDark:function(row,col){if(row<0||this.moduleCount<=row||col<0||this.moduleCount<=col){throw new Error(row+","+col);}
return this.modules[row][col];},getModuleCount:function(){return this.moduleCount;},make:function(){this.makeImpl(false,this.getBestMaskPattern());},makeImpl:function(test,maskPattern){this.moduleCount=this.typeNumber*4+17;this.modules=new Array(this.moduleCount);for(var row=0;row<this.moduleCount;row++){this.modules[row]=new Array(this.moduleCount);for(var col=0;col<this.moduleCount;col++){this.modules[row][col]=null;}}
this.setupPositionProbePattern(0,0);this.setupPositionProbePattern(this.moduleCount-7,0);this.setupPositionProbePattern(0,this.moduleCount-7);this.setupPositionAdjustPattern();this.setupTimingPattern();this.setupTypeInfo(test,maskPattern);if(this.typeNumber>=7){this.setupTypeNumber(test);}
if(this.dataCache==null){this.dataCache=QRCodeModel.createData(this.typeNumber,this.errorCorrectLevel,this.dataList);}
this.mapData(this.dataCache,maskPattern);},setupPositionProbePattern:function(row,col){for(var r=-1;r<=7;r++){if(row+r<=-1||this.moduleCount<=row+r)continue;for(var c=-1;c<=7;c++){if(col+c<=-1||this.moduleCount<=col+c)continue;if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}},getBestMaskPattern:function(){var minLostPoint=0;var pattern=0;for(var i=0;i<8;i++){this.makeImpl(true,i);var lostPoint=QRUtil.getLostPoint(this);if(i==0||minLostPoint>lostPoint){minLostPoint=lostPoint;pattern=i;}}
return pattern;},createMovieClip:function(target_mc,instance_name,depth){var qr_mc=target_mc.createEmptyMovieClip(instance_name,depth);var cs=1;this.make();for(var row=0;row<this.modules.length;row++){var y=row*cs;for(var col=0;col<this.modules[row].length;col++){var x=col*cs;var dark=this.modules[row][col];if(dark){qr_mc.beginFill(0,100);qr_mc.moveTo(x,y);qr_mc.lineTo(x+cs,y);qr_mc.lineTo(x+cs,y+cs);qr_mc.lineTo(x,y+cs);qr_mc.endFill();}}}
return qr_mc;},setupTimingPattern:function(){for(var r=8;r<this.moduleCount-8;r++){if(this.modules[r][6]!=null){continue;}
this.modules[r][6]=(r%2==0);}
for(var c=8;c<this.moduleCount-8;c++){if(this.modules[6][c]!=null){continue;}
this.modules[6][c]=(c%2==0);}},setupPositionAdjustPattern:function(){var pos=QRUtil.getPatternPosition(this.typeNumber);for(var i=0;i<pos.length;i++){for(var j=0;j<pos.length;j++){var row=pos[i];var col=pos[j];if(this.modules[row][col]!=null){continue;}
for(var r=-2;r<=2;r++){for(var c=-2;c<=2;c++){if(r==-2||r==2||c==-2||c==2||(r==0&&c==0)){this.modules[row+r][col+c]=true;}else{this.modules[row+r][col+c]=false;}}}}}},setupTypeNumber:function(test){var bits=QRUtil.getBCHTypeNumber(this.typeNumber);for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[Math.floor(i/3)][i%3+this.moduleCount-8-3]=mod;}
for(var i=0;i<18;i++){var mod=(!test&&((bits>>i)&1)==1);this.modules[i%3+this.moduleCount-8-3][Math.floor(i/3)]=mod;}},setupTypeInfo:function(test,maskPattern){var data=(this.errorCorrectLevel<<3)|maskPattern;var bits=QRUtil.getBCHTypeInfo(data);for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<6){this.modules[i][8]=mod;}else if(i<8){this.modules[i+1][8]=mod;}else{this.modules[this.moduleCount-15+i][8]=mod;}}
for(var i=0;i<15;i++){var mod=(!test&&((bits>>i)&1)==1);if(i<8){this.modules[8][this.moduleCount-i-1]=mod;}else if(i<9){this.modules[8][15-i-1+1]=mod;}else{this.modules[8][15-i-1]=mod;}}
this.modules[this.moduleCount-8][8]=(!test);},mapData:function(data,maskPattern){var inc=-1;var row=this.moduleCount-1;var bitIndex=7;var byteIndex=0;for(var col=this.moduleCount-1;col>0;col-=2){if(col==6)col--;while(true){for(var c=0;c<2;c++){if(this.modules[row][col-c]==null){var dark=false;if(byteIndex<data.length){dark=(((data[byteIndex]>>>bitIndex)&1)==1);}
var mask=QRUtil.getMask(maskPattern,row,col-c);if(mask){dark=!dark;}
this.modules[row][col-c]=dark;bitIndex--;if(bitIndex==-1){byteIndex++;bitIndex=7;}}}
row+=inc;if(row<0||this.moduleCount<=row){row-=inc;inc=-inc;break;}}}}};QRCodeModel.PAD0=0xEC;QRCodeModel.PAD1=0x11;QRCodeModel.createData=function(typeNumber,errorCorrectLevel,dataList){var rsBlocks=QRRSBlock.getRSBlocks(typeNumber,errorCorrectLevel);var buffer=new QRBitBuffer();for(var i=0;i<dataList.length;i++){var data=dataList[i];buffer.put(data.mode,4);buffer.put(data.getLength(),QRUtil.getLengthInBits(data.mode,typeNumber));data.write(buffer);}
var totalDataCount=0;for(var i=0;i<rsBlocks.length;i++){totalDataCount+=rsBlocks[i].dataCount;}
if(buffer.getLengthInBits()>totalDataCount*8){throw new Error("code length overflow. ("
+buffer.getLengthInBits()
+">"
+totalDataCount*8
+")");}
if(buffer.getLengthInBits()+4<=totalDataCount*8){buffer.put(0,4);}
while(buffer.getLengthInBits()%8!=0){buffer.putBit(false);}
while(true){if(buffer.getLengthInBits()>=totalDataCount*8){break;}
buffer.put(QRCodeModel.PAD0,8);if(buffer.getLengthInBits()>=totalDataCount*8){break;}
buffer.put(QRCodeModel.PAD1,8);}
return QRCodeModel.createBytes(buffer,rsBlocks);};QRCodeModel.createBytes=function(buffer,rsBlocks){var offset=0;var maxDcCount=0;var maxEcCount=0;var dcdata=new Array(rsBlocks.length);var ecdata=new Array(rsBlocks.length);for(var r=0;r<rsBlocks.length;r++){var dcCount=rsBlocks[r].dataCount;var ecCount=rsBlocks[r].totalCount-dcCount;maxDcCount=Math.max(maxDcCount,dcCount);maxEcCount=Math.max(maxEcCount,ecCount);dcdata[r]=new Array(dcCount);for(var i=0;i<dcdata[r].length;i++){dcdata[r][i]=0xff&buffer.buffer[i+offset];}
offset+=dcCount;var rsPoly=QRUtil.getErrorCorrectPolynomial(ecCount);var rawPoly=new QRPolynomial(dcdata[r],rsPoly.getLength()-1);var modPoly=rawPoly.mod(rsPoly);ecdata[r]=new Array(rsPoly.getLength()-1);for(var i=0;i<ecdata[r].length;i++){var modIndex=i+modPoly.getLength()-ecdata[r].length;ecdata[r][i]=(modIndex>=0)?modPoly.get(modIndex):0;}}
var totalCodeCount=0;for(var i=0;i<rsBlocks.length;i++){totalCodeCount+=rsBlocks[i].totalCount;}
var data=new Array(totalCodeCount);var index=0;for(var i=0;i<maxDcCount;i++){for(var r=0;r<rsBlocks.length;r++){if(i<dcdata[r].length){data[index++]=dcdata[r][i];}}}
for(var i=0;i<maxEcCount;i++){for(var r=0;r<rsBlocks.length;r++){if(i<ecdata[r].length){data[index++]=ecdata[r][i];}}}
return data;};var QRMode={MODE_NUMBER:1<<0,MODE_ALPHA_NUM:1<<1,MODE_8BIT_BYTE:1<<2,MODE_KANJI:1<<3};var QRErrorCorrectLevel={L:1,M:0,Q:3,H:2};var QRMaskPattern={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var QRUtil={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:(1<<10)|(1<<8)|(1<<5)|(1<<4)|(1<<2)|(1<<1)|(1<<0),G18:(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<5)|(1<<2)|(1<<0),G15_MASK:(1<<14)|(1<<12)|(1<<10)|(1<<4)|(1<<1),getBCHTypeInfo:function(data){var d=data<<10;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)>=0){d^=(QRUtil.G15<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G15)));}
return((data<<10)|d)^QRUtil.G15_MASK;},getBCHTypeNumber:function(data){var d=data<<12;while(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)>=0){d^=(QRUtil.G18<<(QRUtil.getBCHDigit(d)-QRUtil.getBCHDigit(QRUtil.G18)));}
return(data<<12)|d;},getBCHDigit:function(data){var digit=0;while(data!=0){digit++;data>>>=1;}
return digit;},getPatternPosition:function(typeNumber){return QRUtil.PATTERN_POSITION_TABLE[typeNumber-1];},getMask:function(maskPattern,i,j){switch(maskPattern){case QRMaskPattern.PATTERN000:return(i+j)%2==0;case QRMaskPattern.PATTERN001:return i%2==0;case QRMaskPattern.PATTERN010:return j%3==0;case QRMaskPattern.PATTERN011:return(i+j)%3==0;case QRMaskPattern.PATTERN100:return(Math.floor(i/2)+Math.floor(j/3))%2==0;case QRMaskPattern.PATTERN101:return(i*j)%2+(i*j)%3==0;case QRMaskPattern.PATTERN110:return((i*j)%2+(i*j)%3)%2==0;case QRMaskPattern.PATTERN111:return((i*j)%3+(i+j)%2)%2==0;default:throw new Error("bad maskPattern:"+maskPattern);}},getErrorCorrectPolynomial:function(errorCorrectLength){var a=new QRPolynomial([1],0);for(var i=0;i<errorCorrectLength;i++){a=a.multiply(new QRPolynomial([1,QRMath.gexp(i)],0));}
return a;},getLengthInBits:function(mode,type){if(1<=type&&type<10){switch(mode){case QRMode.MODE_NUMBER:return 10;case QRMode.MODE_ALPHA_NUM:return 9;case QRMode.MODE_8BIT_BYTE:return 8;case QRMode.MODE_KANJI:return 8;default:throw new Error("mode:"+mode);}}else if(type<27){switch(mode){case QRMode.MODE_NUMBER:return 12;case QRMode.MODE_ALPHA_NUM:return 11;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 10;default:throw new Error("mode:"+mode);}}else if(type<41){switch(mode){case QRMode.MODE_NUMBER:return 14;case QRMode.MODE_ALPHA_NUM:return 13;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 12;default:throw new Error("mode:"+mode);}}else{throw new Error("type:"+type);}},getLostPoint:function(qrCode){var moduleCount=qrCode.getModuleCount();var lostPoint=0;for(var row=0;row<moduleCount;row++){for(var col=0;col<moduleCount;col++){var sameCount=0;var dark=qrCode.isDark(row,col);for(var r=-1;r<=1;r++){if(row+r<0||moduleCount<=row+r){continue;}
for(var c=-1;c<=1;c++){if(col+c<0||moduleCount<=col+c){continue;}
if(r==0&&c==0){continue;}
if(dark==qrCode.isDark(row+r,col+c)){sameCount++;}}}
if(sameCount>5){lostPoint+=(3+sameCount-5);}}}
for(var row=0;row<moduleCount-1;row++){for(var col=0;col<moduleCount-1;col++){var count=0;if(qrCode.isDark(row,col))count++;if(qrCode.isDark(row+1,col))count++;if(qrCode.isDark(row,col+1))count++;if(qrCode.isDark(row+1,col+1))count++;if(count==0||count==4){lostPoint+=3;}}}
for(var row=0;row<moduleCount;row++){for(var col=0;col<moduleCount-6;col++){if(qrCode.isDark(row,col)&&!qrCode.isDark(row,col+1)&&qrCode.isDark(row,col+2)&&qrCode.isDark(row,col+3)&&qrCode.isDark(row,col+4)&&!qrCode.isDark(row,col+5)&&qrCode.isDark(row,col+6)){lostPoint+=40;}}}
for(var col=0;col<moduleCount;col++){for(var row=0;row<moduleCount-6;row++){if(qrCode.isDark(row,col)&&!qrCode.isDark(row+1,col)&&qrCode.isDark(row+2,col)&&qrCode.isDark(row+3,col)&&qrCode.isDark(row+4,col)&&!qrCode.isDark(row+5,col)&&qrCode.isDark(row+6,col)){lostPoint+=40;}}}
var darkCount=0;for(var col=0;col<moduleCount;col++){for(var row=0;row<moduleCount;row++){if(qrCode.isDark(row,col)){darkCount++;}}}
var ratio=Math.abs(100*darkCount/moduleCount/moduleCount-50)/5;lostPoint+=ratio*10;return lostPoint;}};var QRMath={glog:function(n){if(n<1){throw new Error("glog("+n+")");}
return QRMath.LOG_TABLE[n];},gexp:function(n){while(n<0){n+=255;}
while(n>=256){n-=255;}
return QRMath.EXP_TABLE[n];},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)};for(var i=0;i<8;i++){QRMath.EXP_TABLE[i]=1<<i;}
for(var i=8;i<256;i++){QRMath.EXP_TABLE[i]=QRMath.EXP_TABLE[i-4]^QRMath.EXP_TABLE[i-5]^QRMath.EXP_TABLE[i-6]^QRMath.EXP_TABLE[i-8];}
for(var i=0;i<255;i++){QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]]=i;}
function QRPolynomial(num,shift){if(num.length==undefined){throw new Error(num.length+"/"+shift);}
var offset=0;while(offset<num.length&&num[offset]==0){offset++;}
this.num=new Array(num.length-offset+shift);for(var i=0;i<num.length-offset;i++){this.num[i]=num[i+offset];}}
QRPolynomial.prototype={get:function(index){return this.num[index];},getLength:function(){return this.num.length;},multiply:function(e){var num=new Array(this.getLength()+e.getLength()-1);for(var i=0;i<this.getLength();i++){for(var j=0;j<e.getLength();j++){num[i+j]^=QRMath.gexp(QRMath.glog(this.get(i))+QRMath.glog(e.get(j)));}}
return new QRPolynomial(num,0);},mod:function(e){if(this.getLength()-e.getLength()<0){return this;}
var ratio=QRMath.glog(this.get(0))-QRMath.glog(e.get(0));var num=new Array(this.getLength());for(var i=0;i<this.getLength();i++){num[i]=this.get(i);}
for(var i=0;i<e.getLength();i++){num[i]^=QRMath.gexp(QRMath.glog(e.get(i))+ratio);}
return new QRPolynomial(num,0).mod(e);}};function QRRSBlock(totalCount,dataCount){this.totalCount=totalCount;this.dataCount=dataCount;}
QRRSBlock.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]];QRRSBlock.getRSBlocks=function(typeNumber,errorCorrectLevel){var rsBlock=QRRSBlock.getRsBlockTable(typeNumber,errorCorrectLevel);if(rsBlock==undefined){throw new Error("bad rs block @ typeNumber:"+typeNumber+"/errorCorrectLevel:"+errorCorrectLevel);}
var length=rsBlock.length/3;var list=[];for(var i=0;i<length;i++){var count=rsBlock[i*3+0];var totalCount=rsBlock[i*3+1];var dataCount=rsBlock[i*3+2];for(var j=0;j<count;j++){list.push(new QRRSBlock(totalCount,dataCount));}}
return list;};QRRSBlock.getRsBlockTable=function(typeNumber,errorCorrectLevel){switch(errorCorrectLevel){case QRErrorCorrectLevel.L:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+0];case QRErrorCorrectLevel.M:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+1];case QRErrorCorrectLevel.Q:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+2];case QRErrorCorrectLevel.H:return QRRSBlock.RS_BLOCK_TABLE[(typeNumber-1)*4+3];default:return undefined;}};function QRBitBuffer(){this.buffer=[];this.length=0;}
QRBitBuffer.prototype={get:function(index){var bufIndex=Math.floor(index/8);return((this.buffer[bufIndex]>>>(7-index%8))&1)==1;},put:function(num,length){for(var i=0;i<length;i++){this.putBit(((num>>>(length-i-1))&1)==1);}},getLengthInBits:function(){return this.length;},putBit:function(bit){var bufIndex=Math.floor(this.length/8);if(this.buffer.length<=bufIndex){this.buffer.push(0);}
if(bit){this.buffer[bufIndex]|=(0x80>>>(this.length%8));}
this.length++;}};var QRCodeLimitLength=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]];


/** Constructor */
function QRCode(options) {
  var instance = this;
  
  //Default options
  this.options = {
    padding: 4,
    width: 256, 
    height: 256,
    typeNumber: 4,
    color: "#000000",
    background: "#ffffff",
    ecl: "M"
  };
  
  //In case the options is string
  if (typeof options === 'string') {
    options = {
      content: options
    };
  }
  
  //Merge options
  if (options) {
    for (var i in options) {
      this.options[i] = options[i];
    }
  }
  
  if (typeof this.options.content !== 'string') {
    throw new Error("Expected 'content' as string!");
  }
  
  if (this.options.content.length === 0 /* || this.options.content.length > 7089 */) {
    throw new Error("Expected 'content' to be non-empty!");
  }
  
  if (!(this.options.padding >= 0)) {
    throw new Error("Expected 'padding' value to be non-negative!");
  }
  
  if (!(this.options.width > 0) || !(this.options.height > 0)) {
    throw new Error("Expected 'width' or 'height' value to be higher than zero!");
  }
  
  //Gets the error correction level
  function _getErrorCorrectLevel(ecl) {
    switch (ecl) {
        case "L":
          return QRErrorCorrectLevel.L;
          
        case "M":
          return QRErrorCorrectLevel.M;
          
        case "Q":
          return QRErrorCorrectLevel.Q;
          
        case "H":
          return QRErrorCorrectLevel.H;
          
        default:
          throw new Error("Unknwon error correction level: " + ecl);
      }
  }
  
  //Get type number
  function _getTypeNumber(content, ecl) {      
    var length = _getUTF8Length(content);
    
    var type = 1;
    var limit = 0;
    for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
      var table = QRCodeLimitLength[i];
      if (!table) {
        throw new Error("Content too long: expected " + limit + " but got " + length);
      }
      
      switch (ecl) {
        case "L":
          limit = table[0];
          break;
          
        case "M":
          limit = table[1];
          break;
          
        case "Q":
          limit = table[2];
          break;
          
        case "H":
          limit = table[3];
          break;
          
        default:
          throw new Error("Unknwon error correction level: " + ecl);
      }
      
      if (length <= limit) {
        break;
      }
      
      type++;
    }
    
    if (type > QRCodeLimitLength.length) {
      throw new Error("Content too long");
    }
    
    return type;
  }

  //Gets text length
  function _getUTF8Length(content) {
    var result = encodeURI(content).toString().replace(/\%[0-9a-fA-F]{2}/g, 'a');
    return result.length + (result.length != content ? 3 : 0);
  }
  
  //Generate QR Code matrix
  var content = this.options.content;
  var type = _getTypeNumber(content, this.options.ecl);
  var ecl = _getErrorCorrectLevel(this.options.ecl);
  this.qrcode = new QRCodeModel(type, ecl);
  this.qrcode.addData(content);
  this.qrcode.make();
}

/** Generates QR Code as SVG image */
QRCode.prototype.svg = function(opt) {
  var options = this.options || { };
  var modules = this.qrcode.modules;
  
  if (typeof opt == "undefined") {
    opt = { container: options.container || "svg" };
  }
  
  //Apply new lines and indents in SVG?
  var pretty = typeof options.pretty != "undefined" ? !!options.pretty : true;
  
  var indent = pretty ? '  ' : '';
  var EOL = pretty ? '\r\n' : '';
  var width = options.width;
  var height = options.height;
  var length = modules.length;
  var xsize = width / (length + 2 * options.padding);
  var ysize = height / (length + 2 * options.padding);
  
  //Join (union, merge) rectangles into one shape?
  var join = typeof options.join != "undefined" ? !!options.join : false;
  
  //Swap the X and Y modules, pull request #2
  var swap = typeof options.swap != "undefined" ? !!options.swap : false;
  
  //Apply <?xml...?> declaration in SVG?
  var xmlDeclaration = typeof options.xmlDeclaration != "undefined" ? !!options.xmlDeclaration : true;
  
  //Populate with predefined shape instead of "rect" elements, thanks to @kkocdko
  var predefined = typeof options.predefined != "undefined" ? !!options.predefined : false;
  var defs = predefined ? indent + '<defs><path id="qrmodule" d="M0 0 h' + ysize + ' v' + xsize + ' H0 z" style="fill:' + options.color + ';shape-rendering:crispEdges;" /></defs>' + EOL : '';
  
  //Background rectangle
  var bgrect = indent + '<rect x="0" y="0" width="' + width + '" height="' + height + '" style="fill:' + options.background + ';shape-rendering:crispEdges;"/>' + EOL;
  
  //Rectangles representing modules
  var modrect = '';
  var pathdata = '';

  for (var y = 0; y < length; y++) {
    for (var x = 0; x < length; x++) {
      var module = modules[x][y];
      if (module) {
        
        var px = (x * xsize + options.padding * xsize);
        var py = (y * ysize + options.padding * ysize);
        
        //Some users have had issues with the QR Code, thanks to @danioso for the solution
        if (swap) {
          var t = px;
          px = py;
          py = t;
        }
        
        if (join) {
          //Module as a part of svg path data, thanks to @danioso
          var w = xsize + px
          var h = ysize + py

          px = (Number.isInteger(px))? Number(px): px.toFixed(2);
          py = (Number.isInteger(py))? Number(py): py.toFixed(2);
          w = (Number.isInteger(w))? Number(w): w.toFixed(2);
          h = (Number.isInteger(h))? Number(h): h.toFixed(2);

          pathdata += ('M' + px + ',' + py + ' V' + h + ' H' + w + ' V' + py + ' H' + px + ' Z ');
        }
        else if (predefined) {
          //Module as a predefined shape, thanks to @kkocdko
          modrect += indent + '<use x="' + px.toString() + '" y="' + py.toString() + '" href="#qrmodule" />' + EOL;
        }
        else {
          //Module as rectangle element
          modrect += indent + '<rect x="' + px.toString() + '" y="' + py.toString() + '" width="' + xsize + '" height="' + ysize + '" style="fill:' + options.color + ';shape-rendering:crispEdges;"/>' + EOL;
        }
      }
    }
  }
  
  if (join) {
    modrect = indent + '<path x="0" y="0" style="fill:' + options.color + ';shape-rendering:crispEdges;" d="' + pathdata + '" />';
  }

  var svg = "";
  switch (opt.container) {
    //Wrapped in SVG document
    case "svg":
      if (xmlDeclaration) {
        svg += '<?xml version="1.0" standalone="yes"?>' + EOL;
      }
      svg += '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="' + width + '" height="' + height + '">' + EOL;
      svg += defs + bgrect + modrect;
      svg += '</svg>';
      break;
      
    //Viewbox for responsive use in a browser, thanks to @danioso
    case "svg-viewbox":
      if (xmlDeclaration) {
        svg += '<?xml version="1.0" standalone="yes"?>' + EOL;
      }
      svg += '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 ' + width + ' ' + height + '">' + EOL;
      svg += defs + bgrect + modrect;
      svg += '</svg>';
      break;
      
    
    //Wrapped in group element    
    case "g":
      svg += '<g width="' + width + '" height="' + height + '">' + EOL;
      svg += defs + bgrect + modrect;
      svg += '</g>';
      break;
      
    //Without a container
    default:
      svg += (defs + bgrect + modrect).replace(/^\s+/, ""); //Clear indents on each line
      break;
  }
  
  return svg;
};

/** Writes QR Code image to a file */
QRCode.prototype.save = function(file, callback) {
  var data = this.svg();
  if (typeof callback != "function") {
    callback = function(error, result) { };
  }
  try {
    //Package 'fs' is available in node.js but not in a web browser
    var fs = require('fs');
    fs.writeFile(file, data, callback);
  }
  catch (e) {
    //Sorry, 'fs' is not available
    callback(e);
  }
};

if (typeof module != "undefined") {
  module.exports = QRCode;
}
