﻿//
// EasyPreview.class.js
//
// Yvan Rodrigues, Mabel's Labels Inc. http://www.mabel.ca
//
// This javascript class encapsulates the logic required to track a preview
// and instruct it to update itself at will.
//

// Constructor:
// id = the id attribute of the image element i.e. <img id="kitty" src="http://cats.com"/>
//      or an Image object.
function EasyPreview(ImageId, InitialImageUrl)
{
    // The update delay in milliseconds
    this.UpdateDelay = 1000;

    // This array stores an associate array of properties, such as colour, font etc.
    this.Properties = new Array();

    // A map of properties to controls
    this.Controls = new Array();

    // An initial image to display before the first update. This may be a static image
    // to save bandwidth, or possible an image with instructions, etc.
    this.initialImage = InitialImageUrl;

    // The image DOM element
    if (typeof ImageId == 'string')
        this.image = $("#" + ImageId);
    else
        this.image = $(ImageId);
    this.ImageId = this.image.attr('id');

    // Put the preview in a container
    this.Container = $("<div></div>");
    this.image.wrap(this.Container);
    this.image.css('zIndex', 1);
    //this.image.css('position', 'absolute');

    // Insert the Loading... box
    this.Loading = $('<div id="LoadingText" style="position:absolute; color:black; font-weight:bold; background-color:white; z-index:5000"><img src="/images/ajax_loading.gif" alt="Loading"/><br/>Preview loading...</div>');
    this.Loading.hide();
    this.Container.prepend(this.Loading);

    var me = this;
    this.image.load(function() { me.EndLoading(); });

    // The timer object
    this.timer = null;

    // Get the properties from the supplied url
    // url = url to use as a template
    try
    {
        // the part of the url up to the question mark
        var url = this.image.attr('src') == undefined ? this.initialImage : this.image.attr('src');
        var stubRegex = /^(.+)?\?/;
        var stubs = stubRegex.exec(url);
        this.url = stubs[0];

        // the parts after
        var props1Regex = /\?(.*)$/;
        var props2Regex = /([^=]+)=([^=]*)/;
        var props1 = props1Regex.exec(url);
        var props2 = props1[1].split('&');
        for (a in props2)
        {
            props3 = props2Regex.exec(props2[a]);
            this.Properties[props3[1]] = decodeURIComponent(props3[2]);
        }
    }
    catch (e) { }
    
    // Use the URL if provided
    if (this.initialImage != undefined)
        this.image.attr('src', this.initialImage);

    // Associate a control with this preview
    EasyPreview.prototype.Associate = function(Control, Token) {
        var ControlId;
        if(typeof Control == 'string')
            ControlId = Control;
        else if(Control.jquery != undefined)
            ControlId = $(Control).attr('id');
        else
            ControlId = Control.id;

        if (Token === undefined) {
            var regex = /[0-9]{1,}_([^_]+)$/;
            Token = regex.exec(ControlId)[1];
        }
        this.Controls[Token] = ControlId;
    }

    // Update after specified amount of time.
    // Control (optional) = The control requesting the update
    // Token (optional) = Forces the specified token to be passed
    //   to the preview engine instead of the control's property.
    //   e.g. t0 instead of t13
    EasyPreview.prototype.Update = function(Control, Token) {
        this.StartLoading();

        // associate the control's property with the control
        if (Control != undefined) {
            if (typeof Control == 'string')
                Control = $('#' + Control);
            else
                Control = $(Control);
            var ControlId = Control.attr('id');
            if (Token === undefined) {
                var regex = /[0-9]{1,}_([^_]+)$/;
                Token = regex.exec(ControlId)[1];
            }
            this.Controls[Token] = ControlId;
        }

        // restart the timer 
        if (this.timer != null)
            clearTimeout(this.timer);
        // set the timer
        var me = this;
        this.timer = setTimeout(function() { me.UpdateNow(); }, this.UpdateDelay);
    }

    // Update the image NOW
    EasyPreview.prototype.UpdateNow = function() {
        // update properties from all known controls
        for (a in this.Controls)
            if (this.Controls[a] != null)
            this.Properties[a] = $('#' + this.Controls[a]).val();

        // build new url
        var url = this.url;

        for (a in this.Properties)
            url += '&' + a + '=' + encodeURIComponent(this.Properties[a]);
        // change the image
        if (url != this.image.src) {
            var me = this;
            this.image.attr('src', url);
        }
    }

    EasyPreview.prototype.StartLoading = function() {
        this.Loading.fadeTo('normal', 0.7);
        this.Loading.show();
    }

    EasyPreview.prototype.EndLoading = function() {
        this.image.show();
        // get image size
        var height = this.image.height();
        var width = this.image.width();
        // force it to that size with css
//        this.image.css('height', height);
//        this.image.css('width', width);
        // and the loading...
//        this.Loading.css('height', width);
//        this.Loading.css('height', height);
        // and the container...
//        this.Container.css('height', height);
//        this.Container.css('height', width);
        // position the loading...
        var pos = this.image.position();
//        this.Loading.css('left', pos.left);
//        this.Loading.css('top', pos.top);
        // position the loading... text
        var lt = $('#LoadingText');
        lt.css('top', height / 2 - lt.height() / 2);
        lt.css('left', width / 2 - lt.width() / 2);
        this.Loading.hide();
    }


    // URI encodes a string.
    // Unlike the built-in javascript functions, this encodes ALL characters.
    EasyPreview.prototype.Encode = function (Value) {
        var work = '';
        for (a = 0; a < Value.length; a++)
            work += '%' + Value.charCodeAt(a).toString(16);
        return work;
    }

    EasyPreview.prototype.DisassociateAll = function() {
        this.Controls.length = 0;
    }
}

