
// dependency.. http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js

var Snapper = (function(){
  
  // alert(location.href);
  if(location.href.indexOf('file:\/\/')==0){
    alert("Warning: Due to flash security restrictions snapper cannot load when accessed via file: protocol. Please test using a web server.");
    return; 
  }
  
  // -----------------------------------------------
  
  // helper funcs ( collection of hacks to make plain old js less painful )
  var noop = function(){};
  var console = window['console'] || {log: noop, debug: noop, info: noop, warn: noop, error: function(args){alert(args);}};
  
  // dom stuff
  var loadScriptTag = function(src, loaded, callback) {
    if(loaded()){
      callback();
      return;
    }
    console.log("Loading missing javascript.", "swfobject", src);
    var scriptTag=document.createElement('scr'+'ipt');
    scriptTag.type = 'text/javascript';
    scriptTag.src=src;
    var head = document.getElementsByTagName("head")[0];
    head.appendChild(scriptTag);
    function check(){
      if(loaded()){
        callback();
      } else {
        setTimeout(check, 50);
      }
    };
    check(); 
  };
  var loadLinkTag = function(src){
    var link = document.createElement("link");
    link.setAttribute('rel','stylesheet');
    link.setAttribute('type','text/css');
    link.setAttribute('media', 'screen');
    link.setAttribute('charset', 'utf-8');
    link.setAttribute('href',src);
    document.getElementsByTagName("head")[0].appendChild(link);
    // <link rel="stylesheet" href="snapbox.css" type="text/css" media="screen" title="snapbox" charset="utf-8" />
  }
  var loadStyleTag = function(content){
    var style = document.createElement('style');
    style.setAttribute("type", "text/css");
    if (style.styleSheet) { // IE
        style.styleSheet.cssText = content;
    } else {                // the world
        var textNode = document.createTextNode(content);
        style.appendChild(textNode);
    }
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(style);
  }
  var hasClassName = function(element, className) {
    var elementClassName = element.className;
    return (elementClassName.length > 0 && (elementClassName == className ||
      new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
  };
  var addClassName = function(element, className) {
    if (!hasClassName(element, className))
      element.className += (element.className ? ' ' : '') + className;
    return element;
  };
  var removeClassName = function(element, className) {
    element.className = element.className.replace(
      new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ');
    return element;
  };
  
  if(!document.getElementsByClassName){
    document.getElementsByClassName = function(className) {
      var docList = this.all || this.getElementsByTagName('*');
      var matchArray = new Array();
      /*Create a regular expression object for class*/
      var re = new RegExp("(?:^|\\s)"+className+"(?:\\s|$)");
      for (var i = 0; i < docList.length; i++) {
          if (re.test(docList[i].className) ) {
              matchArray[matchArray.length] = docList[i];
          }
      }
      return matchArray;
    };
  }
  
  // basic stuff
  var lower = function(obj){
    return obj.toString().toLowerCase();
  };
  var collect = function(list,func){
    var x = [];
    for(var i=0; i<list.length; i++){
      if(func(list[i])){
        x.push(list[i]);
      }
    }
    return x;
  }
  var each = function(list,func){
    var x = [];
    for(var i=0; i<list.length; i++){
      x.push(func(list[i]));
    }
    return x;
  }
  var first = function(list,func){
    var x;
    for(var i=0; i<list.length; i++){
      x = func(list[i]);
      if(x){
        return list[i];
      }
    }
  }
  var merge = function(a,b){
    obj = {};
    for(prop in a){
      obj[prop] = a[prop];
    }
    for(prop in b){
      obj[prop] = b[prop];
    }
    return obj;
  }
  
  var setData = function(obj, data){
    for(var prop in data){
      obj.setAttribute('data-'+prop, data[prop]);
    }
  };
  var getData = function(obj){
    var data = {};
    for(var i=0; i<obj.attributes.length; i++){
      if(obj.attributes[i].nodeName.indexOf('data-')==0){
        data[obj.attributes[i].nodeName.split("data-")[1]] = obj.attributes[i].nodeValue;
      }
    }
    return data;
  };
  var randId = function(){
    return "rand_"+Math.random().toString().replace('.','');
  };
  var validElementId = function(element){
    if(element.id){
      return element.id;
    } else {
      element.id = randId();
      return element.id;
    }
  };
  
  // positioning 
  var getScrollerWidth = function(){
      var scr = null;
      var inn = null;
      var wNoScroll = 0;
      var wScroll = 0;

      // Outer scrolling div
      scr = document.createElement('div');
      scr.style.position = 'absolute';
      scr.style.top = '-1000px';
      scr.style.left = '-1000px';
      scr.style.width = '100px';
      scr.style.height = '50px';
      // Start with no scrollbar
      scr.style.overflow = 'hidden';

      // Inner content div
      inn = document.createElement('div');
      //inn.style.width = '100%';
      inn.style.height = '200px';

      // Put the inner div in the scrolling div
      scr.appendChild(inn);
      // Append the scrolling div to the doc
      document.body.appendChild(scr);

      // Width of the inner div sans scrollbar
      wNoScroll = inn.offsetWidth;
      // Add the scrollbar
      scr.style.overflow = 'auto';
      // Width of the inner div width scrollbar
      wScroll = inn.offsetWidth;

      // Remove the scrolling div from the doc
      document.body.removeChild(
          document.body.lastChild);

      // Pixel width of the scroller
      return (wNoScroll - wScroll);
  };
  var getStyle = function(obj, styleProp){
    if (obj.currentStyle)
      return obj.currentStyle[styleProp];
    else if (window.getComputedStyle)
      return document.defaultView.getComputedStyle(obj,null).getPropertyValue(styleProp);
  };
  var getScrollPos = function(){
    var docElem = document.documentElement;
    return {
      scrollX: document.body.scrollLeft || window.pageXOffset || (docElem && docElem.scrollLeft),
      scrollY: document.body.scrollTop || window.pageYOffset || (docElem && docElem.scrollTop)
    };
  };
  var getPageSize = function(){
    return {
      width: window.innerWidth || (document.documentElement && document.documentElement.clientWidth) || document.body.clientWidth,
      height: window.innerHeight || (document.documentElement && document.documentElement.clientHeight) || document.body.clientHeight
    };
  };
  var getElementSize = function(obj){
    return {
      width: obj.offsetWidth || obj.style.pixelWidth,
      height: obj.offsetHeight || obj.style.pixelHeight
    };
  };
  
  // animation 
  var setOpacity = function(e, obj, value){
    obj.style.opacity = value/100;
    obj.style.filter = 'alpha(opacity=' + value + ')';
  };
  var fadeIn = function(obj, level, speed, callback){
    if (level === undefined) var level = 100;
    if (speed === undefined) var speed = 70;
    if (!speed)
    {
      setOpacity(null, obj, level*10);
      if (callback) callback();
      return;
    }
    setOpacity(null, obj, 0);
    for (var i=0; i<=level; i++){
      setTimeout(bind(setOpacity, obj, i*10), speed*i);
    }
    if (callback) setTimeout(callback, speed*(i+1));
  };
  var fadeOut = function(){}; // todo 
  var center = function(obj){
    var pageSize = getPageSize();
    var scrollPos = getScrollPos();
    var emSize = getElementSize(obj);
    var x = Math.round((pageSize.width - emSize.width) / 2 + scrollPos.scrollX);
    var y = Math.round((pageSize.height - emSize.height) / 2 + scrollPos.scrollY);
    obj.style.left = x + 'px';
    obj.style.top = y + 'px';
  };
  
  // events
  // var events = {};
  // var addEventListener = function(name, callback){
  //   if (!events[name]) events[name] = new Array();
  //   events[name].push(callback);
  // };
  // var fireEvent = function(name){
  //   if (events[name] && events[name].length){
  //     for (var i=0; i<events[name].length; i++){
  //       var args = [];
  //       for (var n=1; n<arguments.length; n++) {
  //         args.push(arguments[n]);
  //       }
  //       if (events[name][i](args) === false) {
  //         break;
  //       }
  //     }
  //   }
  // };
  var dispatchEvent = function(obj, type, bubble, canCancel){
    if(bubble == undefined){
      bubble = true;
    }
    if(canCancel == undefined){
      canCancel = true;
    }
    if(document.createEvent){
      var e = document.createEvent('HTMLEvents');
      if(e.initEvent){
        e.initEvent(type, bubble, canCancel);
      }
      if(obj.dispatchEvent){
        obj.dispatchEvent(e);
      }
    } else if(obj.fireEvent){
      obj.fireEvent('on'+type);
    }
  };
  var deferUntilReady = function(callback){
    var readyRun = false;
    var ready = function(){
      if(readyRun){
        return;
      }
      readyRun = true;
      callback();
    }
    var domReady = null;
    if ( document.addEventListener ) {
      domReady = function() {
        document.removeEventListener( "DOMContentLoaded", domReady, false );
        ready();
      };
    } else if ( document.attachEvent ) {
      domReady = function() {
        if ( document.readyState === "complete" ) {
          document.detachEvent( "onreadystatechange", domReady );
          ready();
        }
      };
    }
    var bindRun = false;
    var bind = function() {
      if(bindRun) {
        return;
      }
      bindRun = true;
      if ( document.readyState === "complete" ) {
        return ready();
      }
      if ( document.addEventListener ) {
        document.addEventListener( "DOMContentLoaded", domReady, false );
        window.addEventListener( "load", ready, false );
      } else if ( document.attachEvent ) {
        document.attachEvent("onreadystatechange", domReady);
        window.attachEvent( "onload", ready );
      }
    };
    bind();
  }
  var bindEvent = function(el, event, callback){
    if ( document.addEventListener ) {
      el.addEventListener(event, callback, false );
    } else if ( document.attachEvent ) {
      el.attachEvent( "on"+event, callback );
    }
  }
  
  var isIE6 = false; // todo fix!
  
  // -----------------------------------------------
  var assetRoot = "http://code.webcamsnapper.com.s3.amazonaws.com/";
  var asset = function(path){
    return assetRoot + path;
  }
  
  // -----------------------------------------------
  var docReady = false;
  var deferred = [];
  var snapperIdx = 0;
  
  // -----------------------------------------------
  
  var cssRules = function(){
    
    var overlayImageBase64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAMAAABFaP0WAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRF////////VXz1bAAAAAJ0Uk5T/wDltzBKAAAAD0lEQVR42mJgYARCgAADAAAMAAMrbpwTAAAAAElFTkSuQmCC"; 
    var overlayImageURL = asset('images/overlay.png');
    
    var closeImageBase64 = "data:image/png;base64,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%3D";
    var closeImageURL = asset('images/close.png');
  
    var css = "\
    #snapbox {z-index:1000000; position:fixed;top:0;left:0;right:0;bottom:0;display:block;}\
    #snapbox_overlay\ {position:fixed;top:0;left:0;right:0;bottom:0;display:block;opacity:1;background-image:url('"+overlayImageBase64+"');z-index:1000000;}\
    #snapbox_wrapper {position:absolute;top:50%;left:50%;margin:-200px 0 0 -200px;display:block;padding:0;opacity:1;z-index:1000001;}\
    #snapbox_content {position:relative;display:block;overflow:visible;text-align:left;z-index:1000002;}\
    #snapbox_content object {display:block;}\
    #snapbox_content .snapbox_image {width:100%;height:100%;margin:0;padding:0;border:0;display:block;}\
    #snapbox_head a#snapbox_close\ {width:30px;height:30px;position:absolute;top:-10px;right:-10px;margin:0;padding:0;outline:0;border:none;text-indent:-9999999px;z-index:100000000;background-image:url('"+closeImageBase64+"');}\
    #snapbox_overlay {\
      *background-image:url('"+overlayImageURL+"');\
      _background-image:url('"+overlayImageURL+"');\
    }\
    #snapbox_head a#snapbox_close {\
      *background-image:url('"+closeImageURL+"');\
      _background-image:url('"+closeImageURL+"');\
    }\
    .webcam .webcam_thumb, .webcam .webcam_thumb img{width: 240px; }\
    .webcam.active .webcam_button  {display:none;}\
    .webcam.active .webcam_target {display:block;} \
    .webcam.active .webcam_thumb {display:none;}\
    .webcam.inactive .webcam_thumb {display:none;} \
    .webcam.inactive .webcam_target {display:none;} \
    .webcam.inactive.thumb_set .webcam_thumb {display:block;}\
    .webcam.inactive .webcam_button {display:block;}\
    body.flash_bug_fix_odd_width #snapbox_wrapper {padding-left: 0.5px; padding-right: -0.5px;}\
    body.flash_bug_fix_odd_height #snapbox_wrapper {padding-top: 0.5px; padding-bottom: -0.5px;}\
    ";
    
    return css;
  }

  var defaultSettings = function(){
    var settings = {
      // target: 'snapper',
      swf: asset('snapper.swf'),
      width: 480, height: 360,
      frame: 'default',
      wmode: 'transparent',
      shadow: true,
      sizes: {
        tiny : [320,240],
        small : [400,300],
        standard : [480,360],
        medium : [560,420],
        large : [640,480],
        huge : [800,600]
      }
    };
    return settings;
  };
  var defaultVars = function(){
    var vars = {  
      save_mode: 'post_base64', // 'js_base64',
      frame_path: "",
      init_frame_id: "", 
      init_effect_id: "", 
      upload_url: "http://www.webcamsnapper.com/snapload", 
      // upload_url: "http://localhost:8080/snapload", 
      output_format: "jpg",     
      cam_full_width: 640, // 800,
      cam_full_height: 480, //600,
      show_confirm_screen: 1,
      output_width: 640,
      output_height: 480, 
      mirror_mode: 1, 
      video_border_size: 1, 
      video_border_color: '999999',
      preview_mode_divider: 1, 
      show_setting_on_start: 0,
      hide_frame_btn : 1, 
      hide_effect_btn : 0, 
      hide_321_btn : 0,
      // raw_post : 1, // base64
      watermark_off : 1, // lets flip this round. watermark
      jpg_quality : 80,  
      camera_security_type: "1",
      auto_save : 0,
      custom_hex_color : "FFFFFF",  
      splash_logo_path : "", // its backed in now isnt it, will this override.
      padding_space : "20,20,5,20", //"0,0,3,0",// "9,9,0,9", 
      hide_credit_menu : 1, // lets review this menu
      quick_snap: 1, 
      on_click_save_js: "", 
      export_complete_js: "",
      denied_webcam_js: "",
      custom_fix_color: "",  
      faq_xml_path: "", 
      faq_css_path: "", 
      faq_video_path : asset('flv/demo.flv'), 
      faq_video_thumb_path : asset('flv/demo.jpg'),
      license_domain : "",
      license_key : "",
      init_picture_path : "",
      // load_completed_js: "",
      stop_after_loaded: 0,
      help_support_path: "http://www.webcamsnapper.com/help",
      license_agreement_path: "http://www.webcamsnapper.com/license",
      purchase_path: "http://www.webcamsnapper.com/pricing",
      background_type: "bgRoundWithShadow" // bgRectNoShadow (default), bgRectWithShadow, bgRoundNoShadow, bgRoundWithShadow
      // init_picture_path
      };
    return vars;
  };
  var globalSettings;
  
  var firefoxPixelFlashBugByClass = function(){
    var ua = navigator.userAgent.toLowerCase();
    if(ua.indexOf('firefox') && ua.indexOf('mac os x')){
      removeClassName(document.body, 'flash_bug_fix_odd_width');
      removeClassName(document.body, 'flash_bug_fix_even_width');
      removeClassName(document.body, 'flash_bug_fix_odd_height');
      removeClassName(document.body, 'flash_bug_fix_even_height');
      var w = document.documentElement.clientWidth;
      var h = document.documentElement.clientHeight;
      addClassName(document.body, 'flash_bug_fix_'+( (w % 2 == 0) ? 'even' : 'odd' )+'_width');
      addClassName(document.body, 'flash_bug_fix_'+( (h % 2 == 0) ? 'even' : 'odd' )+'_height');
    }
  };
  
  bindEvent(window, 'resize', firefoxPixelFlashBugByClass);
  // firefoxPixelFlashBugByClass();
  
  var firefoxPixelFlashBugFixByResizeWindow = function(){
    var ua = navigator.userAgent.toLowerCase();
    if(ua.indexOf('firefox') && ua.indexOf('mac os x')){
      var rx = document.documentElement.clientWidth % 2 == 1 ? -1 : 0; 
      var ry = document.documentElement.clientHeight % 2 == 1 ? -1 : 0;
      if(rx != 0 || ry != 0){
        window.resizeBy(rx, ry); // note this gives warning for some users. ugly!
      }
    }
  };
  
  var SnapBox = (function(){
    
    var box;
    var wrapper;
    var content;
    var overlay;
    var close;
    var overflow = 'auto';
    
    var showing = false;
    var close;
    
    var hide = function(){
      if(box.style.display=='none'){
        return;
      }
      box.style.display = 'none';
      content.innerHTML = '';
      showing = false;
      if(closeCallback){
        closeCallback();
      }
    };
    
    var insert = function(){
      box = document.getElementById('snapbox');
      if(box){
        return;
      }
      box = document.createElement('div');
      box.setAttribute('id', 'snapbox');
      box.innerHTML = '\
        <div id="snapbox_overlay"></div>\
        <div id="snapbox_wrapper">\
          <div id="snapbox_head"><a id="snapbox_close" href="javascript:void(0)">close</a></div>\
          <div id="snapbox_content"></div>\
        </div>';
      box.style.display = 'none';
      document.body.appendChild(box);
      overlay = document.getElementById('snapbox_overlay');
      wrapper = document.getElementById('snapbox_wrapper');
      content = document.getElementById('snapbox_content');
      close = document.getElementById('snapbox_close');
      // bindEvent(window, 'scroll', reposition);
      // bindEvent(window, 'resize', reposition);
      bindEvent(close, 'click', hide);
      bindEvent(window, 'keypress', function(e){ if (e.keyCode == (window.event ? 27 : e.DOM_VK_ESCAPE)) { hide() }});
    };
    
    var show = function(html, width, height, callback){ 
      showing = true;
      closeCallback = callback;
      insert();
      content.style.width = ''+width+'px';
      content.style.height = ''+height+'px';
      content.innerHTML = html;
      wrapper.style.margin = '-'+(height/2)+'px 0px 0px -'+(width/2)+'px';
      box.style.display = 'block';
      firefoxPixelFlashBugByClass();
    };
    
    return {
      show : show, 
      hide : hide
    };
    
  })();

  
  function findPos(obj) {
  	var curleft = curtop = 0;
  	if (obj.offsetParent) {
  		curleft = obj.offsetLeft
  		curtop = obj.offsetTop
  		while (obj = obj.offsetParent) {
  			curleft += obj.offsetLeft
  			curtop += obj.offsetTop
  		}
  	}
  	return [curleft,curtop];
  }
  
  var initFlash = function(swf, target, width, height, settings, vars){
    var version = '9.0.0';
    var expressInstall = '';
    var params = {"allowScriptAccess":"always", "wmode": settings['wmode'] || 'normal'}; // "bgcolor": "000000"
    var attrs = {id:"snapper"+snapperIdx, name: "snapper"+snapperIdx};
    snapperIdx++;
    loadScriptTag(
      'http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js', 
      function(){return window['swfobject'];}, 
      function(){
        swfobject.embedSWF(swf, target, width.toString(), height.toString(), version, expressInstall, vars, params, attrs);         
      }
    );
  };
  
  // callbacks
  var globalCallback = function(callback){
    var handlerName = 'handler_'+randId();
    window[handlerName] = callback;
    console.log(window[handlerName]);
    return handlerName;
  }
  
  var display = function(mode, args){
  
    // settings
    var settings = {};
    if(lower(typeof(args))=='function'){
      settings = {'complete': args};
    } else if(lower(typeof(args))=='string'){
      var id = args;
      var callback = function(snap){
        var element = document.getElementById(id);
        element.value = snap; 
        dispatchEvent(element, 'change');
      }
      settings = {'complete': callback };
    } else {
      settings = args || {}; 
    }
    
    console.debug(globalSettings);
    
    settings = merge(globalSettings, settings);
    
    // vars
    var vars = defaultVars();
    
    // size 
    if(settings['snapper_size']){
      var dims = settings['sizes'][settings['snapper_size']] || settings['sizes']['standard'];
      settings['width'] = dims[0];
      settings['height'] = dims[1];
    }
    
    if(settings['snapper_border']){
      settings['background_type'] = "bg";
      settings['background_type'] += (settings['snapper_border'].indexOf('round') != -1) ? 'Round' : 'Rect';
      settings['background_type'] += (settings['snapper_border'].indexOf('shadow') != -1) ? 'WithShadow' : 'WithoutShadow';
    }
    
    if(settings['image_size']){
      // should really check the format here.
      var dims = settings['image_size'].split("x");
      if(dims.length == 1){ dims[1] = Math.round(parseInt(dims[0]) / 4 * 3); }
      settings['cam_full_width'] = dims[0];
      settings['cam_full_height'] = dims[1];
      settings['output_width'] = dims[0];
      settings['output_height'] = dims[1];
    }
    
    if(settings['save_method']){
      settings['save_mode'] = (settings['save_method'].toLowerCase() == 'base64') ? 'js_base64' : 'post_base64';
    }
    
    if(settings['camera_security_type'] != undefined){
      if(settings['camera_security_type']=='remember'){
        settings['camera_security_type'] = 1;
      } else {
        settings['camera_security_type'] = 0;
      }
    }
    
    for(prop in vars){
      if(settings[prop]){
        vars[prop] = settings[prop];
      }
    }
    
    var complete = settings['complete']; 
    
    vars['export_complete_js'] = globalCallback(function(data){
      setTimeout(function(){complete(data);}, 100);
      SnapBox.hide();
    });
    
    vars['denied_webcam_js'] = globalCallback(function(){
      closeBoxIfOpen();
    });
    
    var load_complete = settings['load_complete'] || noop;
    vars['load_completed_js'] = globalCallback(function(){
      window.setTimeout(load_complete, 100);
    });
    
    
    
    
    var width = (settings['width']) ? parseInt(settings['width']) : 480;
    var height = (settings['height']) ? parseInt(settings['height']) : 360;
    var padding = each(vars['padding_space'].split(","),function(x){return parseInt(x);});
    var border_size = parseInt(vars['video_border_size']); 
    
    width+=padding[1] + padding[3];
    height+=padding[0] + (padding[2]*2);
    
    //width+=border_size*2;
    //height+=border_size*2;

    height += 56; // 46 + 10;
    
    var swf = settings['swf'];
  
    if(mode == 'show'){
      vars['show_confirm_screen'] = false;
      SnapBox.show('<div id="snapbox_target"></div>', width, height, settings['close']);
      window.setTimeout(function(){
        
        initFlash(swf, 'snapbox_target', width, height, settings, vars);
      }, 100); 
    } else {
      var target = settings['target'];
      if(typeof(target) != 'string'){
        target = validElementId(target);
      }
      // document.getElementById(target).innerHTML = '<div id="'+frame_target+'"></div>'; // frame_html;
      console.debug(settings, vars);
      
      initFlash(swf,target, width, height, settings, vars);
    }
    
  }

  // -----------------------------------------------

  var replaceInputTypeWebcam = function(){
    var embed = function(input){
      var frag = document.createDocumentFragment();
      var div = document.createElement("div");
      var thumb = document.createElement("div");
      var img = document.createElement("img");
      var hidden = document.createElement("input");
      var button = document.createElement("input");
      if(input.id){
        div.id = input.id;
      }
      var data = getData(input);
      //console.log(data);
      data['embed'] = data['embed'] || 'popup'; 
      data['take-label'] = data['take-label'] || 'Take Photo';
      data['change-label'] = data['change-label'] || 'Change Photo';
      data['src'] = data['src'] || input.getAttribute('value') || "";
      setData(div, data);
      div.className = 'webcam snapper-input-type-webcam '+input.className;
      hidden.setAttribute('name', input.name);
      hidden.setAttribute('type', 'hidden');
      if(input.onchange){
        hidden.onchange = input.onchange;
      }
      if(input.onclick){
        button.onclick = input.onclick;
      }
      button.setAttribute('type', 'button');
      button.setAttribute('value', data['start-label']);
      button.className = "webcam_button";
      thumb.className = 'webcam_thumb';
      thumb.appendChild(img);
      
      div.appendChild(thumb);
      div.appendChild(hidden);
      div.appendChild(button);
      var target = document.createElement("div");
      target.className = 'webcam_target';
      div.appendChild(target);
      frag.appendChild(div);
      input.parentNode.replaceChild(frag, input);
      return div;
    }
    
    var connect = function(div){
      
      var data = getData(div);
      var thumb = first(div.childNodes, function(x){ return lower(x.tagName) == 'div' && hasClassName(x,'webcam_thumb');});
      var img = first(thumb.childNodes, function(x){ return lower(x.tagName) == 'img';});
      if(!img){
        var img = document.createElement('img');
        thumb.appendChild(img);
      };
      var hidden = first(div.childNodes, function(x){ return lower(x.tagName) == 'input' && x.getAttribute('type') == 'hidden';});
      var button = first(div.childNodes, function(x){ return lower(x.tagName) == 'input' && hasClassName(x, "webcam_button");});
      var target = first(div.childNodes, function(x){ return lower(x.tagName) == 'div' && hasClassName(x,'webcam_target');});
      
      data['start-label'] = data['start-label'] || "Take Photo";
      data['change-label'] = data['change-label'] || "Change Photo";
      
      button.value = data['start-label']
      
      if(data['src'] && data['src'] != ""){
        // alert(data['src']);
        img.setAttribute('src', data['src']);
        button.value = data['change-label'];
        addClassName(div, 'thumb_set'); 
      } else {
        removeClassName(div, 'thumb_set'); 
      }
      
      
      addClassName(div, 'inactive');
      
      // if(!img.getAttribute('src')){
      //   thumb.style.display = 'none';
      // }
      
      var complete = function(image){
        img.src = image;
        button.value = data['change-label'];
        hidden.value = image;
        dispatchEvent(hidden, 'change');
        addClassName(div, 'thumb_set');
        removeClassName(div, 'active');
        addClassName(div, 'inactive');
      }
      
      // var close = function(){
      //   removeClassName(div, 'active');
      // }
      
      var settings = {};
      
      if(data['settings']){ // correct 
        settings = JSON.parse(data['settings']);
      } else if(data['config']){ // mistake in docs
        settings = JSON.parse(data['config']);
      }
      
      if(data['type']){
        data['type'] = lower(data['type']);
        if(data['type'].split("/")[0] == 'image'){
          var image_format = data['type'].split('/')[1];
          if(image_format =='jpeg'){
            image_format = 'jpg';
          }
          settings['image_format'] = image_format;
        }
      }
      
      if(data['quality']){
        settings['jpg_quality'] = data['quality'];
      }
      
      if(data['size']){
        settings['size'] = data['size'];
      }
      
      if(data['embed']=='onclick' || data['embed']=='onload'){
        button.onclick = function(){
          addClassName(div, 'active');
          removeClassName(div, 'inactive');
          var target_id = randId();
          target.innerHTML = '<div id="'+target_id+'"></div>';
          Snapper.embed(merge({
              'complete':complete, 
              'target': target_id
          }, settings));
        };
        if(data['embed'] == 'onload'){
          dispatchEvent(button,"click");
        }
      } else {
        button.onclick = function(){
          addClassName(div, 'active');
          removeClassName(div, 'inactive');
          console.debug(merge(data, {'complete':complete}));
          Snapper.show(merge({
              'complete':complete,
              'close': function(){removeClassName(div, 'active');}
          }, settings));
        };
      }
    }
    var typeWebcam = function(x){ return x.getAttribute('type') == 'webcam'; };
    var inputs = document.getElementsByTagName("input");
    each(collect(inputs, typeWebcam), function(x){ embed(x); });
    each(document.getElementsByClassName('snapper-input-type-webcam'), function(x){ connect(x); });
  };
  
  // wait until the page has loaded.
  deferUntilReady(function(){
    docReady = true;
    // alert("settings");
    // alert(assetRoot);
    globalSettings = merge(defaultSettings(),globalSettings || {});
    replaceInputTypeWebcam();
    each(deferred, function(x){x();});
    // stylesheet. 
    if(globalSettings['style']==undefined){
      globalSettings['style'] = cssRules();
    };
    if(globalSettings['style'].indexOf('http')==0){
      loadLinkTag(globalSettings['style']);
    } else {
      loadStyleTag(globalSettings['style']);
    }
    firefoxPixelFlashBugByClass();
  });

  // -----------------------------------------------

  // public
  var configure = function(settings){
    var updateConfig = function(){
      if(settings['asset_root']){
        assetRoot = settings['asset_root']; 
      }
      globalSettings = merge(globalSettings, settings);
    }
    if(!docReady){
      deferred.push(updateConfig);
      return; 
    }
    return updateConfig();
  };
  var show = function(args){
    if(!docReady){
      deferred.push(function(){display('show', args);});
      return; 
    }
    return display('show', args);
  };
  var embed = function(args){
    if(!docReady){
      if(typeof(args)=='function'){
        var target = randId();
        document.write('<div id="'+target+'" class="snapper"></div>');
        args = {target:target, complete:args};
      }
      deferred.push(function(){display('embed', args);});
      return; 
    }
    return display('embed', args);
  };
  
  var version = "1.0"; 
  
  return {
    version : version,  
    configure : configure,
    embed : embed,
    show : show, 
    assetRoot : assetRoot,
    setAssetRoot : function(x){assetRoot=x;}
  };
  
})();

Snapper.setAssetRoot('http://www.webcamsnapper.com/release/20110720/');

if(location.href.indexOf("http://localhost:8081")==0){
  Snapper.setAssetRoot('http://localhost:8081/latest/');
}

