
var Lib = new function(){

	var Gr0wl = {};
	
	Gr0wl.Base = new Class({
		
		options: {
		    image: 'growl.jpg',
		    title: 'Window.Growl by Daniel Mota',
		    text: 'http://icebeat.bitacoras.com',
		    duration: 2
		},
	
		initialize: function(image) {
		    this.image = new Asset.image(image, { onload: this.create.bind(this) });
		    return this.show.bind(this);
		},
		
		create: function(styles) {
		    this.image.setStyles('position:absolute;display:none').setOpacity(0).injectInside(document.body);
		    this.block = new Element('div').setStyles('position:absolute;display:none;z-index:999;color:#000;font: 12px/14px "Lucida Grande", Arial, Helvetica, Verdana, sans-serif;'+styles.div).setOpacity(0).injectInside(document.body);
		    new Element('img').setStyles(styles.img).injectInside(this.block);
		    new Element('h3').setStyles(styles.h3).injectInside(this.block);
		    new Element('p').setStyles(styles.p).injectInside(this.block);
		},
		
		show: function(options) {
		    options = $merge(this.options, options);
		    var elements = [this.image.clone(), this.block.clone()];
		    elements.each(function(e, i) {
			    e.injectInside(document.body);
			    e.setStyles(options.position);
			    if(i) e.getFirst().setProperty('src', options.image).getNext().setHTML(options.title).getNext().setHTML(options.text);
			});
		    new Fx.Elements(elements, {duration:400}).start({
			    '0': { 'opacity': 0.75 }, '1': { 'opacity': 1 }
		    });
		    var that = this;
		    return function(){ that.hide.delay(options.duration*1000, that, [elements]);};
		},
		
		hide: function(elements, effect) {
		    var effects = new Fx.Elements(elements, {duration:400, onComplete: function() {
				this.elements[0].remove();
				this.elements[1].empty().remove();
			    }}).start({'0': effect, '1': effect });
		}
	    });


	Gr0wl.Smoke = Gr0wl.Base.extend({
		create: function() {
		    this.queue = [];
		    this.parent({
			    div: 'width:200px; margin: 0px; padding: 5px; border: 1px solid black;',
				img: 'float:left;margin:10px;',
				h3: 'margin:0;padding:5px;font-size:13px;',
				p: 'margin:0px;font-size:12px;'
				});
		},
		show: function(options) {
		    var last = this.queue.getLast();
		    var delta = window.getScrollTop()+10+(last*83);
		    options.position = {'top':delta+'px', 'right':'10px', 'display':'block'};
		    this.queue.push(last+1);
		    return this.parent(options);
		},
		hide: function(elements) {
		    this.queue.shift();
		    this.parent(elements,{ 'opacity': 0 });
		}
	    });

	Gr0wl.Bezel = Gr0wl.Base.extend({
		create: function() {
		    this.i=0;
		    this.parent({
			    div: 'width:211px;height:206px;text-align:center;',
				img: 'margin-top:25px;',
				h3: 'margin:0;padding:0px;padding-top:22px;font-size:14px;',
				p: 'margin:15px;font-size:12px;'
				});
		},
		show: function(options) {
		    var top = window.getScrollTop()+(window.getHeight()/2)-105;
		    var left = window.getScrollLeft()+(window.getWidth()/2)-103;
		    options.position = {'top':top+'px', 'left':left+'px', 'display':'block'};
		    this.i++;
		    this.chain(this.parent.pass(options,this));
		    if(this.i==1) this.callChain();
		},
		hide: function(elements) {
		    this.queue.delay(400,this);
		    this.parent(elements, { 'opacity': 0, 'margin-top': [0,50] });
		},
		queue: function() {
		    this.i--;
		    this.callChain();
		}
	    });

	Gr0wl.Bezel.implement(new Chain);
	
	var Growl = function(options) {
	    if(Growl[options.type]) Growl[options.type].call(options);
	    else Growl.Smoke(options);
	};

	window.addEvent('domready',function() {
		Growl.Bezel = new Gr0wl.Bezel('/img/indicator.gif');
		Growl.Smoke = new Gr0wl.Smoke('/img/indicator.gif');
	    });

	var HumanizedMessage = new new Class({            
		
		initialize: function() {
		    // privates
		    var messageWidth = 560,
		    attachEventsHnd,
		    hideHnd,
		    container = new Element('div', { 
			    style: 'position: absolute; z-index: 999; width: ' + messageWidth + 'px; height: 80px; top: 200px; background-color: black; ',
			    opacity: 0
			}),
		    message = new Element('div', {
			    style: 'color: white; margin: 20px auto; padding: 0px 20px; text-align: center; font: 16px "Lucida Grande", Arial, Helvetica, Verdana, sans-serif;',
			    opacity: 0 
			}).inject(container),
                // create fx
		    fx = new Fx.Elements([container, message], {
			    duration: 400,
			    link: 'cancel',
			    onComplete: function() { container.style.top = '200px'; }});
		    fx.set({0: {opacity: 0}, 1: {opacity: 0}});
		    
		    function show(text) {    
			container.setStyle('left', (window.getWidth() / 2) - (messageWidth / 2));
			message.innerHTML = text;        
			fx.start({ 0: { opacity: [0, 0.8] }, 1: { opacity: [0, 1] } });		
			$clear(attachEventsHnd);
			$clear(hideHnd);
			attachEventsHnd = attachEvents.delay(700);
			hideHnd = hide.delay(5000);
		    }
 
		    function attachEvents(){
			document.addListener('mousemove', hide);
			document.addListener('click', hide);
			document.addListener('keypress', hide);        
		    };
		    
		    function hide() {
			// Remove message if mouse is moved or key is pressed
			document.removeListener('mousemove', hide);
			document.removeListener('click', hide);
			document.removeListener('keypress', hide);                		        		
			fx.start({'0': {'opacity': [0], 'top': [300] }, '1': {'opacity': [0] }});		                    
		    };
 
		    window.addEvent('domready', function() {
			    container.inject($(document.body));
			});
		    
		    // public api
		    this.show = show;
		}
	    });


var ProgressBar=new Class({
	initialize:function(value,parameters){
		var vals={
			'id':'progressbar_'+(ProgressBars++),
			'value':$pick(value,0),
			'width':0,
			'height':0,
			'darkbg':'#000',
			'darkfg':'#fff',
			'lightbg':'#fff',
			'lightfg':'#000'
		};
		if(parameters && $type(parameters)=='object')$extend(vals,parameters);
		if(vals.height<12)vals.height=12;
		var obj=new Element('div',{
			'id':vals.id,
			'class':'progressbar_wrapper',
			'styles':{
				'border':'1px solid #000',
				'width':vals.width,
				'height':vals.height,
				'position':'relative'
			}
		});
		obj.vals=vals;
		obj.vals.dark=new Element('div',{
			'id':vals.id+'_dark',
			'class':'progressbar_dark',
			'styles':{
				'width':vals.width,
				'height':vals.height,
				'background':vals.darkbg,
				'color':vals.darkfg,
				'position':'absolute',
				'text-align':'center',
				'left':0,
				'top':0,
				'line-height':vals.height-2
			}
		});
		obj.vals.light=new Element('div',{
			'id':vals.id+'_light',
			'class':'progressbar_light',
			'styles':{
				'width':vals.width,
				'height':vals.height,
				'background':vals.lightbg,
				'color':vals.lightfg,
				'position':'absolute',
				'text-align':'center',
				'left':0,
				'top':0,
				'line-height':vals.height-2
			}
		});
		obj.appendChild(obj.vals.dark);
		obj.appendChild(obj.vals.light);
		obj.setValue=ProgressBar_setValue;
		if(vals.width)obj.setValue(vals.value);
		else setTimeout('ProgressBar_checkForParent("'+obj.id+'")',1);
		return obj;
	}
});
function ProgressBar_setValue(value){
	value=parseFloat(value);
	if(isNaN(value))value=0;
	if(value>100)value=100;
	if(value<0)value=0;
	this.vals.value=value;
	this.vals.dark.empty();
	this.vals.light.empty();
	this.vals.dark.appendText(parseInt(value)+'%');
	this.vals.light.appendText(parseInt(value)+'%');
	var r=parseInt(this.vals.width*(value/100));
	this.vals.dark.setStyle('clip','rect(0,'+r+'px,'+this.vals.height+'px,0)');
	this.vals.light.setStyle('clip','rect(0,'+this.vals.width+'px,'+this.vals.height+'px,'+r+'px)');
}
function ProgressBar_checkForParent(id){
	var obj=$(id);
	if(!obj)return;
	if(!obj.parentNode)return setTimeout('ProgressBar_checkForParent("'+id+'")',1);
	obj.setStyle('width','100%');
	var w=obj.offsetWidth;
	obj.vals.dark.setStyle('width',w);
	obj.vals.light.setStyle('width',w);
	obj.vals.width=w;
	obj.setValue(obj.vals.value);
}
var ProgressBars=0;


	var lispylogs = new function(){
		// Convert logs from raw to readable
		var loglen = cfg.loglen || 150;
		var len = 0;
		var buffer = '';
		var indent_unit = '&nbsp;&nbsp;&nbsp;&nbsp;';
		var indent = 0;
		var delimiter = '<br/>';
		var parseString = function(_message_){
		    var delimiter = '<br/>';
		    if(!_message_) return;
		    var message = _message_;
		    var ind = message.indexOf(':');
		    var typ = null;
		    if (ind){
			typ = message.substring(0,ind);
		    }
		    else {
			typ = 'info';
		    }
		    var rest = message.substring(ind+1);
		    ind = rest.indexOf(':');
		    var kind = null;
		    if (ind){
			kind = rest.substring(0,ind);
		    }
		    else {
			kind = 'unknown';
		    }
		    rest = rest.substring(ind+1);
		    
		    typ = typ.toLowerCase();
		    kind = kind.toLowerCase();
		    var startline = "";
		    var endline = "";
		    var sep = "";
		    var indent_ = "";
		    var left = "";
		    var right = "";
		    message = "";
	    
		    switch(typ){
		    case "open-state":
			if (kind != "document"){
			    startline = delimiter; 
			    indent += 1;
			}
			left = "(";  
			for(var i=0;i<indent;i++){
			    indent_+=indent_unit;
			}
			message = rest;
			sep = "&nbsp;";
			break;
		    case "close-state":
			indent -= 1;
			if (kind == "document"){
			    endline = delimiter;
			}
			right = ")";
			break;
		    case "event": 
			left = '[';
			switch (kind){
			case 'table':
			    message ='T';
			    break;
			case 'footnote':
			    message ='Fn';
			    break;
			case 'float':
			    message = 'Fl';
			    break;
			case 'absolute-container':
			    message ='Ca';
			    break;
			case 'fixed-container':
			    message ='Cf';
			    break;
			default:
			    message = rest;
			}
			right = ']';
			break;
		    case 'error':
		    case 'warning':
		    case 'info':
			for(var i=0;i<indent;i++){
			    indent_+=indent_unit;
			}
			startline = delimiter;
			message = rest;
			switch (typ){
			case 'error':
			    left = '!';
			    break;
			case 'warning':
			    left = '?';
			    break;
			case 'info':
			    left = '&nbsp;';
			    break;
			}
			break;
		    };
		    //_indent_ = indent;
		    if ((startline+indent_+left+message+sep+right+endline).length == 0){
			len = 0;
			return _message_+delimiter;
		    }
		    var answer = startline+indent_+left+message+sep+right+endline;
		    if (answer.lastIndexOf(delimiter) > -1)
			len = answer.length - answer.lastIndexOf(delimiter);
		    else
			if (len + answer.length > loglen){
			    var ind = '';
			    for(var i=0;i<indent;i++)
				ind+=indent_unit;
			    len = answer.length + ind.length + 2;
			    answer = delimiter + ind + '&nbsp;&nbsp;' + answer;
			}
			else {
			    len += answer.length;
			}
		    return answer;
		};
		
		this.parse = function(message, _delimiter, _prefix){
		    if(_delimiter) delimiter = _delimiter;
		    var prefix = _prefix || '';
		    message = buffer+message;
		    buffer = message.slice(message.lastIndexOf(delimiter)+delimiter.length);
		    message = message.slice(0, message.lastIndexOf(delimiter));
		    var strings = message.split(delimiter);
		    var answer = '';
		    for(var i=0; i< strings.length; i++){
			if (strings[i].slice(0, prefix.length) == prefix)
			    answer+=parseString(strings[i].slice(prefix.length));
			else if (strings[i] && strings[i].length)
			    answer+=strings[i]+'<br/>';
		    }
		    return answer || '';
		};
		var parse = this.parse;
		this.reparse = function(message, _delimiter){
		    buffer = '';
		    indent = 0;
		    return parse(message,_delimiter);
		};
		this.parseStr = parseString;
	    };


	var ajax = new function(){
		var last = null; // Time of last request
		var timeout = cfg.timeout || 3000;
		
		var send = function(suffix, data, fn){
		    if(!last) last = new Date().getTime();
		    var time = new Date().getTime() - last;
		    if (time > timeout){
			last += time;
			var request = new Json.Remote(cfg.root+suffix+'/json/', { onComplete : fn });
			request.send(data);
		    }
		    else {
			setTimeout(function(){send(suffix,data,fn)},timeout-time);
		    };
		};
		this.send = send;

		this.state = function(lst, fn){
		    send('state',lst,fn);
		};

		this.action = function(type, dict, fn){
		    function process(obj){
			if (obj.process){
			    fn({'msg':'ok'});
			}
			else if ($defined(obj.process)){
			    setTimeout(function(){send('process',[], process)}, 500);
			}
			else {
			    fn({'msg':'ok'});
			}
		    };
		    send(type,dict,function(obj){
			    
			    if (obj.msg == 'ok'){
				setTimeout(function(){send('process',[], process)}, 500);
			    }
			    else
				fn(obj);
			});
		};
	    };

	var submit = new function(){
		var handler = null;
		var iframe = null;
		
		this.setHandler = function(fn){
		    handler = function(obj){ return fn(obj)};
		};
		this.send = function(form, _iframe, fn, _action, _submit){
		    handler = function(obj){ return fn(obj)};
		    iframe = _iframe;
		    var action = _action || 'upload';
		    var old_action = form.getAttribute('action');
		    var old_target = form.getAttribute('target');
		    var old_enctype = form.getAttribute('enctype');
		    form.setAttribute('action',cfg.root+action+'/html');
		    form.setAttribute('target', iframe.getAttribute('name'));
		    form.setAttribute('enctype','multipart/form-data');
		    form.submit();
		    form.setAttribute('action',old_action);
		    form.setAttribute('target',old_target);
		    form.setAttribute('enctype',old_enctype);
		    return true;
		};

		this.handleResponse = function(obj){
		    
		    function process(obj){
			if (obj.process){
			    handler({'msg':'ok'});
			}
			else if ($defined(obj.process)){
			    setTimeout(function(){ajax.send('process',[], process)}, 500);
			}
			else {
			    handler({'msg':'ok'});
			};
		    };
		    
		    if(iframe)
			iframe.src = '';
		    if (obj.msg=='ok') 
			setTimeout(function(){ajax.send('process',[], process)}, 500);
		    else
			handler({error:"cannot start"});
		};
	    };

	function download(form, _params, _action, _json){
    
	    //  Download formatting result
	    var params = Json.toString(_params || {});
	    var action = (_action || 'download') + '/pdf/';
	    var json = $(_json || 'json');
	    
	    var old_action = form.getAttribute('action');
	    var old_enctype = form.getAttribute('enctype');
	    if (params && json) json.value = params;
	    form.setAttribute('action',cfg.root+action);
	    form.setAttribute('enctype','multipart/form-data');
	    form.submit();
	    form.setAttribute('action',old_action);
	    form.setAttribute('enctype',old_enctype);
	    return true;
	};

	function browser(){
	    return [[window.ie, 'ie'],
	     [window.ie6, 'ie6'],
	     [window.ie7, 'ie7'],
	     [window.gecko, 'gecko'],
	     [window.webkit, 'webkit'],
	     [window.webkit419, 'webkit419'],
	     [window.webkit420, 'webkit420'],
		    [window.opera, 'opera']].filter(function(item){return item[0]}).map(function(item){return item[1];});
	};

	var errorHandler = function(msg, url, line){
	    // report error to the server
	    
	    try {
		ajax.send('error', {'msg':msg, 'url':url, 'info':l, 'browser': browser()}, function(){});
	    }
	    catch(e){
		alert('There was an error on page, please send Javascript Error Console log to support@blogpaper.com');
	    };
	    return false;
	};

	var eventwrapper = function(fn){
	    return function(evt){
		function clean(st){
		    return escape(escape((st || '')));
		};
		var res = null;
		try {
		    res = fn(evt);
		}
		catch (e){
		    errorHandler(clean(e.name+': '+e.message), clean(fn.name), clean(fn.toString()));
		    throw(e);
		};
		return res;
	    }
	};
	var feedback = new function(){
		// feedback support
		this.init = function(giveUsFeedback, send, cancel, textarea, div){
		    giveUsFeedback.addEvent('click',function(e){
			    div.className = 'feedback';
			    var evt = new Event(e)
			    evt.stop();
			    try {
				textarea.focus();
			    }
			    catch(e){
			    };
			});
		    cancel.addEvent('click', function(e){
			    div.className = 'hidden';
			});
		    send.addEvent('click', function(e){
			    var growl = Growl.Smoke({duration: 0, text: '', title: 'Sending Feedback...'});
			    ajax.send('feedback',{'text':escape(escape(textarea.value)),
					'browser': browser(),'cookie':escape(escape(document.cookie))}, function(obj){
				    growl();
				    obj.msg ?HumanizedMessage.show(obj.msg) : err('unknown answer from server');});
			    div.className = 'hidden';
			    textarea.value = '';
			});
		};
	    };
	
	var progressMeter = function(animate, total, width, points, weights, _finish, logspans, logspansdiv, logdiv, _minchunk, _maxchunk, velo){
	    var current = 0;
	    var next = 0;
	    var startTime = null;
	    var minchunk = _minchunk || 100;
	    var maxchunk = _maxchunk || 2000;
	    var sum = 0;
	    var nexttime = 0;
	    var adjusting = false;
	    var velocity = velo || 10;
	    var mutex = true;
	    var end = false;
	    var obj;
	    var events = [];
	    var nextevent = 0;
	    var buffer = '';
	    function max(a,b){
		return a > b ? a : b;
	    };
	    
	    function min(a,b){
		return a < b ? a : b;
	    };
	    
	    function reduce(fn,data,st){
		var res = null;
		if (st==0 || st) res = st;
		for(var i=0;i<data.length;i++){
		    res = fn(res,data[i]);
		};
		return res;
	    };

	    function finish(){
		if (mutex) {
		    logspansdiv.className = 'hidden';
		    events.map(function(event){$(logdiv).innerHTML += lispylogs.parse(event[2], '\n', 'LOG:');});
		    _finish(obj);
		}
		mutex = false;
	    };
	    
	    function adjust(val){
		function w(fn){
		    return function(){return fn(val);}
		};
		if (events.length){
		    if (current > nextevent){
			var event = events.shift();
			nextevent = current + (next - current)/events.length;
			    if (event[0]) logspans[0].setHTML(event[0]);
			    if (event[1]) logspans[1].setHTML(event[1]);
			    $(logdiv).innerHTML += lispylogs.parse(event[2], '\n', 'LOG:');
		    };
		};

		if (next >= width && current < next){
		    nextevent = current;
		    current += velocity;
		    animate(current);
		    setTimeout(w(adjust), minchunk);
		    return null;
		}
		else if(current < next){
		    current += 1;
		    animate(current);
		    var now = new Date().getTime()-startTime;
		    setTimeout(w(adjust), min(maxchunk,max(minchunk,(nexttime-now)/velocity/(next-current))));
		}
		else {
		    adjusting = false;
		}
		
		if ((current >= width) && end){
		    setTimeout(w(finish), minchunk);
		};
		return null;
	    };

	    function analyze(log){
		var logs = log.split('\n');
		for(var i=0; i< logs.length; i++){
		    var loginfo = logs[i].split(':');
		    var msgtype = loginfo[1];
		    var msg = loginfo[2];
		    var msginfo = loginfo[3];
		    var evtype = null;
		    var ev = null;
		    if (loginfo[1] == 'read') loginfo[1] = 'Reading';
		    switch(msg){
		    case 'url':
			evtype = 'Reading';
			ev = msginfo +':'+loginfo[4];
			loginfo = ['Reading', ev];
			break;
		    case 'document':
			if(msgtype == 'open-state'){evtype = 'Preparing'; ev = '...'};
			break;
		    case 'system-id':
			loginfo[4] = 'your file';
			break;
		    case 'transform':
			msgtype == 'open-state' ? (evtype = 'Transforming', ev = '...') : (ev = 'done'); 
			break;
		    case 'transformation':
			ev = msginfo;
			break;
		    case 'validate':
			if (msgtype == 'open-state') {evtype = 'Validating'; ev = '...';}; 
			break;
		    case 'validation':
			ev = msginfo;
			break;
		    case 'compile':
			msgtype == 'open-state' ? (evtype = 'Compiling', ev = '...') : (ev = 'done'); 
		        break;
		    case 'masters':
			msgtype == 'open-state' ? (ev = 'templates') : (ev = '...'); 
		        break;
		    case 'format':
			msgtype == 'open-state' ? (evtype = 'Formatting', ev = '...') : (ev = 'done'); 
		        break;
		    case 'postprocess':
			msgtype == 'open-state' ? (evtype = 'Postprocessing', ev='...') : (ev = 'done'); 
		        break;
		    case 'generate':
			msgtype == 'open-state' ? (evtype = 'Generating', ev='...') : (ev = 'done'); 
			break;
		    case 'bookmark-tree':
			ev = 'bookmarks';
			break;
		    case 'page-number':
			ev = 'page ' + msginfo;
			break;
		    case 'output-format':
			msginfo == 'XEPOUT' ? evtype = 'Generating xepout' : 'Generating ps';
			ev = '...';
			break;
		    case 'associated-stylesheet':
			ev = msginfo;
			break;
		    };
		    buffer += loginfo.join(':') + '\n';
		    if (events.length == 0 && !(evtype || ev)){
			$(logdiv).innerHTML += lispylogs.parse(buffer, '\n', 'LOG:');
			buffer = '';
		    }
		    else {
			if (evtype || ev){
			    events.push([evtype, ev, buffer]);
			    buffer = '';
			};
		    };
		};
	    };
    
	    function add(log){
		analyze(log);
		var j=null;
		for(var i=0;i<points.length;i++){
		    if (log.match(points[i])){
			j = i;
		    };
		};
		if(j==0 || j){
		    var curweight = reduce(function(x,y){return x+y;},weights.slice(0,j),0);
		    var now = new Date().getTime() - startTime;
		    if(now/total != current/width && current) total = (3*total + now*width/current)/4;
		    nexttime = total/sum*curweight;
		    next = width/sum*curweight;
		    if(!adjusting){
			adjusting = true;
			setTimeout(adjust,minchunk);
		    };
		};
	    };
	    
	    this.add = add;
	    this.start = function(log){
		startTime = new Date().getTime();
		end = false;
		sum = reduce(function(x,y){return x+y;}, weights, 0);
		add(log);
	    };
	    this.finish = function(_obj,now){
		obj = _obj;
		end = true;
		if (now) { finish(obj);}
		else {
		    next=width;
		    adjust(obj);
		};
	    };
	};
	
	function format(args, flag, finargs, callback, get_ready, _err, form, _iframe,  _progressdiv, _log, statusdiv, _action, _downloader, _points, _weights, _image, _logspans, _logspansdiv, _showlog){
	    var action = _action || 'format';
	    var status = function(){};
	    if (statusdiv || $('status'))
		status = function(msg){ $(statusdiv || 'status').setText(msg);};
	    var iframe = _iframe || $('iframe');
	    var points = [/open-state:transform/, /close-state:transform/,
			  /open-state:validate/, /close-state:validate/,
			  /open-state:simplify/, /close-state:simplify/,
			  /open-state:compile:compile|open-state:masters:masters|event:master:FirstPage|event:table:table:/,
			  /close-state:flow:flow|close-state:sequence:sequence|close-state:compile:compile/,
			  /open-state:format:format|open-state:sequence:sequence/, /close-state:format:format/,
			  /event:output-format:XEPOUT/,/close-state:generate:generate/,
			  /event:output-format:PostScript/,/close-state:generate:generate/,
			  /event:output-format:PDF/,/close-state:generate:generate/];
	    
	    var weights = [3,1,10,1,1,1,2,1,10,1,3,1,3,1,10,1];
	    var err = _err || function (msg){
		HumanizedMessage.show('Error: ' + msg);
	    };
	    var progressdiv = _progressdiv || 'progress';
	    var logdiv = _log || 'log';
	    var downloader = _downloader || 'downloader';
	    var image = _image || 'image';
	    var showlog = _showlog || 'showlog';
	    $(showlog).className = 'hidden';
	    $(showlog).innerHTML = '[+]';
	    function fin(obj){
		logspans.map(function(item){$(item).setHTML('')});
		logspansdiv.className = 'hidden';
		msg = callback(obj);
		if (msg){
		    err(msg);
		}
		else
		    download($(downloader));

		$(progressdiv).removeChild(progress);
		get_ready();
	    };

	    var logspans = _logspans && _logspans.length && _logspans.map($) || [$('logstatus'), $('logstatus-msg')];
	    var logspansdiv = _logspansdiv && $(_logspansdiv) || $('info');
	    var progress = new ProgressBar(0, {'width': 300, 'height': 30});
	    var meter = new progressMeter(function(i){return progress.setValue(i/3);}, 90000, 300, points, weights, fin, logspans, logspansdiv, logdiv);
	    
	    $(progressdiv).appendChild(progress);
	    $(logdiv).setHTML('');
	    var j = 0;
	    function logger(obj){
		if($defined(obj.log)){
		    if(!j++){
			meter.start(obj.log);
			logspans.map(function(item){$(item).setHTML('')});
			logspansdiv.className = 'status-log';
			$(showlog).className = 'showlog';
			$(showlog).innerHTML = '[+]';
			lispylogs.reparse('');
			progress.setValue(0);
			$(logdiv).className = 'hidden';
			$(image).className = 'hidden';
			$(progressdiv).className = 'progress';
			status('Formatting...');
		    }
		    else {
			meter.add(obj.log);
		    };
		}
		else {
		    err(obj.msg || obj.error);
		}
	    };

	    function log(obj){
		if (obj[flag]){
		    status('Formatting...');
		    logger(obj);
		    ajax.send('log', [flag], log); 
		}
		else {
		    logger(obj);
		    ajax.state(finargs, function(obj){
			    meter.finish(obj);
			})}};
	    
	    function start(obj){
		status('Loading...');
		ajax.send('log', [flag], log); 
	    };
	    status('Connecting...');
	    if (form){
		submit.setHandler(start);
	    }
	    else
		ajax.action('format', args, start);
	};

	try {
	    window.onerror = function(msg,url,l){
		try {
		    ajax.action('error', {'msg':msg, 'url':url, 'info':l, 'browser': browser()}, function(){});
		}
		catch(e){
		    alert('There was an error on page, please send Javascript Error Console log to support@blogpaper.com');
		};
		return false;
	    };
	    window.error = window.onerror;
	}
	catch(e){
	};

	this.ajax = ajax;
	this.submit = submit;
	this.errorHandler = errorHandler;
	this.download = download;
	this.lispylogs = lispylogs;
	this.format = format;
	this.feedback = feedback;
	this.eventwrapper = eventwrapper;
	this.HumanizedMessage = HumanizedMessage;
    };

