/// <reference path="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.4.4-vsdoc.js" />
/*global $bf: true, blogfrog: true, log: true, $: false, jQuery: false */

// Setup older blogfrog namespaces
if (typeof (window.blogfrog) === 'undefined') { window.blogfrog = {}; }
if (typeof (window.blogfrog.controls) === 'undefined') { window.blogfrog.controls = {}; }

/* ==========================================================================================
    blogfrog.template Module
========================================================================================== */
if (typeof (blogfrog.template) === 'undefined' || blogfrog.template.version < 1.97) {
    blogfrog.template = blogfrog.template || function (undefined) {
        
        // Regex's
        var blockEndRegex = /\{\{\{[ ]*end[ ]*\}\}\}/i;
        var forInBlockRegex = /[ ]*for ([^ ]+) in ([^ ]+)[ ]*/i;
        var simpleIfBlockRegex = /[ ]*if ((!)?[^ ]+)[ ]*/i;

        var trim = function (s) {
            return s.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
        };

        var ltrim = function (s) {
            return s.replace(/^\s\s*/, '');
        };

        var warn = function (s) {
            if (typeof (console) !== 'undefined' && typeof (console.warn) !== 'undefined') {
                console.warn('blogfrog.template: ' + s);
            }
        };

        var getProp = function (prop, values, callback) {
            // Trap emtpy prop values
            if (prop === undefined || values === undefined) { return ''; }
            // Check next if we need to recursivley fetch a nested value
            var dot = prop.indexOf('.');
            if (dot > -1) {
                var parent = prop.substr(0, dot);
                var child = prop.substr(dot + 1);
                return getProp(child, values[parent], callback);
            }
            // If value isn't nested...
            else {
                var pc, filter;

                // ...check for filters
                // Syntax: {{prop:filter}}
                if (prop.indexOf(':') > -1) {
                    pc = prop.split(':');
                    filter = pc[1];
                    prop = pc[0];
                }
                var val = values[prop];

                if (typeof (callback) === 'function' && typeof (filter) !== 'undefined') {
                    var callbackVal = callback(filter, val);
                    val = (callbackVal !== undefined) ? callbackVal : val;
                }

                // Error if property isn't found
                if (typeof (val) === 'underfined' || val === undefined) {
                    throw ("Prop not found");
                }

                return val;
            }
        };

        var renderValues = function (template, values, callback) {
            var out = template;
            var offset = 0;
            var index = out.indexOf('{{', offset);
            var cache = {};

            while (index > -1) {
                var end = out.indexOf('}}', index + 1);
                var prop = trim(out.substr(index + 2, end - index - 2));

                // Resolve the value from the given data context (values)
                var val = '';
                if (prop in cache) {
                    val = cache[prop];
                } else {
                    try {
                        val = getProp(prop, values, callback).toString();
                    } catch (ex) {
                        if (ex === 'Prop not found') {
                            warn("Template variable '" + prop + "' not found for template '" + template.substr(0, 30) + "...'");
                        } else { warn(ex); }
                        val = '';
                    }
                    cache[prop] = val;
                }

                // Replace braces with HTML encoding
                if (val.indexOf('{') > -1 || val.indexOf('}') > -1) {
                    val = val.replace(/\{/g, '&#123;').replace(/\}/g, '&#125;');
                }

                // Get sides then concat
                var left = out.substr(0, index);
                var right = out.substr(end + 2);
                out = left + val + right;

                // Update for next pass
                offset = left.length + val.length;
                index = out.indexOf('{{', offset);
            }
            return out;
        };

        var forInBlock = function (forVar, forList, blockTemplate, values, callback) {
            var out = '';
            var list = [];

            // Resolve for value into actual iterable
            try {
                list = getProp(forList, values, callback);
            } catch (ex) {
                if (ex === 'Prop not found') {
                    warn("Template context variable '" + forList + "' not found for template:\n" + blockTemplate);
                } else {
                    warn(ex);
                }
            }

            // Check that the forList actually exists
            if (typeof (list) === 'undefined') {
                warn("List '" + forList + "' not found in template context for block {{{ for " + forVar + " in " + forList + " }}}");
                return '';
            }

            for (var v in list) {
                if (list.hasOwnProperty(v)) {
                    values[forVar] = list[v];
                    if (values[forVar]) {
                        out += blogfrog.template.render(blockTemplate, values, callback);
                    }
                }
            }
            delete values[forVar];
            return out;
        };

        var simpleIfBlock = function (conditionVar, blockTemplate, values, callback) {
            var out = '';

            // Check for "not"
            var not = false;
            var cv = conditionVar;
            if (conditionVar.substr(0, 1) === '!') {
                not = true;
                cv = conditionVar.substr(1);
            }

            // Render
            var v = false;
            try { v = getProp(cv, values, callback); } catch (ex) { }

            // Handle special cases
            if (v) {
                switch (typeof (v)) {
                    case "object":
                        if (v.constructor.toString().indexOf("Array") !== -1) {
                            v = v.length > 0;
                        }
                        break;
                }
            }

            if ((v && !not) || (!v && not)) {
                return blogfrog.template.render(blockTemplate, values, callback);
            } else {
                return '';
            }
        };

        var renderBlock = function (directive, blockTemplate, values, callback) {
            // Match {{{ for [var] in [list] }}}
            var m = forInBlockRegex.exec(directive);
            if (m) { return forInBlock(m[1], m[2], blockTemplate, values, callback); }
            // Match {{{ if [var] }}}
            m = simpleIfBlockRegex.exec(directive);
            if (m) { return simpleIfBlock(m[1], blockTemplate, values, callback); }
            // Else
            warn('Unknown block directive: "' + directive + '"');
        };

        var parseBlock = function (blockMatch, template, values, callback) {
            var out = template;
            var firstHalf = out.substr(0, blockMatch.index);
            var blockStartRegex = new RegExp('{{{[ ]*([^}]+)[ ]*}}}', 'gi');

            // Build a list of all blocks leading up to the parent of the current {{{ end }}}
            var blocks = [];
            var priorBlock = blockStartRegex.exec(firstHalf);
            while (priorBlock) {
                blocks.push({ start: priorBlock });
                priorBlock = blockStartRegex.exec(firstHalf);
            }

            var blockTemplate, blockDirective, rendered;

            if (blocks.length === 1) {
                // If there aren't any parents to this block, parse as is
                var b = blocks[0].start;
                blockTemplate = firstHalf.substr(b.index + b[0].length);
                blockDirective = trim(b[1]);
                // Render block
                rendered = renderBlock(blockDirective, trim(blockTemplate), values, callback);
                out = out.substr(0, b.index) + rendered + out.substr(blockMatch.index + blockMatch[0].length);
            } else {
                // If there are parents, find their end points...
                var indexOffset = blockMatch.index + blockMatch[0].length;
                var backHalf = out.substr(indexOffset);
                var blockStartOrEndGRegex = new RegExp('(?:{{{[ ]*([^}]+)[ ]*}}})|(?:{{{[ ]*(end)[ ]*}}})', 'gi');
                var nextBlock;
                var count = blocks.length - 2;
                var skipEnd = 0; // Used to keep track of when we find another nested block when to skip for the actual closing end
                do {
                    nextBlock = blockStartOrEndGRegex.exec(backHalf);
                    if (trim(nextBlock[1].toLowerCase()) === 'end') {
                        if (skipEnd <= 0) {
                            blocks[count].end = nextBlock;
                            count--;
                        } else {
                            skipEnd--;
                        }
                    } else {
                        skipEnd++;
                    }
                } while (nextBlock && count > -1);

                // ...then parse from the outside in
                var parent = blocks[0];
                var len = (parent.end.index + indexOffset) - parent.start.index - parent.start[0].length;
                blockTemplate = out.substr(parent.start.index + parent.start[0].length, len);
                blockDirective = trim(parent.start[1]);
                rendered = renderBlock(blockDirective, trim(blockTemplate), values, callback);
                out = out.substr(0, parent.start.index) + rendered + out.substr(parent.end.index + indexOffset + parent.end[0].length);
            }
            return out;
        };

        return {
            // Render a template where values is a dict or object.  Encase replacements in {{ }}'s
            render: function (template, values, callback) {
                var out = template;
                // Extract blocks
                var blockMatch = blockEndRegex.exec(out);
                while (blockMatch) {
                    out = parseBlock(blockMatch, out, values, callback);
                    blockMatch = blockEndRegex.exec(out);
                }
                // Render remaining values
                out = renderValues(out, values, callback);
                return out;
            }
        };
    } ();

    blogfrog.template.type = 'template';
    blogfrog.template.description = 'Blogfrog Widget Template Engine';
    blogfrog.template.version = 1.97;
}

/* ==========================================================================================
    $bf Module
========================================================================================== */
if (typeof (window.$bf) === 'undefined') { window.$bf = {}; }
if (typeof (window.$bf.globals) === 'undefined') { window.$bf.globals = {}; }

if (typeof (window.$bf.v2) === 'undefined' || typeof(window.$bf.v2.fn) === 'undefined') {

    // Init
    (function () {
        
        // Die if a higher version is present
        var version = 2.0;
        if (typeof (window.$bf.v2) !== 'undefined' && typeof (window.$bf.v2.version) !== 'undefined' && window.$bf.v2.version > version) { return false; }

        // Store previous version of $bf if one was already there
        var oldBf = null;
        var extend = function (orig, fresh, opt) {
            orig = orig || {};
            opt = opt || {};

            for (var key in fresh) {
                if (fresh.hasOwnProperty(key)) {
                    // Recurse for hashes (TODO: fix this for arrays)
                    if (typeof (fresh[key]) === 'object' && !opt.flat) {
                        orig[key] = extend(orig[key], fresh[key]);
                    } else {
                        orig[key] = fresh[key];
                    }
                }
            }
            return orig;
        };
        if (typeof (window.$bf.v2) !== 'undefined') { oldBf = window.$bf.v2; }

        // Otherwise overwrite/setup $bf and $bf.fn
        window.$bf.v2 = function (widget) { var w = new window.$bf.v2.fn(); w.widget = widget; return w; };
        if (oldBf !== null) { extend(window.$bf.v2, oldBf, { flat: true }); }

        // Carry over attributes to new $bf
        window.$bf.v2.version = version;

        // extend
        window.$bf.v2.extend = function (orig, fresh, opt) {
            return extend(orig, fresh, opt);
        };
    })();

    (function ($bf, GLOBALS) {

        $bf.fn = function () { };
        if (typeof ($bf.widgets) === 'undefined') { $bf.widgets = {}; }
        if (typeof ($bf.controls) === 'undefined') { $bf.controls = {}; }

        // Init counters
        if (typeof (GLOBALS.widgetCounter) === 'undefined') { GLOBALS.widgetCounter = 0; }
        if (typeof (GLOBALS.uniqueCounter) === 'undefined') { GLOBALS.uniqueCounter = 0; }

        // Safe console logging (from HTML5 boilerplate)
        window.log = function () { log.history = log.history || []; log.history.push(arguments); if (this.console) { console.log(Array.prototype.slice.call(arguments)); } };

        // Function.bind (from Prototype.js)
        Function.prototype.sbind = function () { var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); return function () { return fn.apply(object, args.concat(Array.prototype.slice.call(arguments))); }; };

        /* ==========================================================================================
        Global Library Methods
        ========================================================================================== */

        // buildUrl
        $bf.buildUrl = function (_url, _params) {
            var qs = '';
            for (var key in _params) {
                if (_params.hasOwnProperty(key)) {
                    qs += '&' + escape(key) + '=' + escape(_params[key]);
                }
            }

            if (_url.indexOf('?') > -1) {
                return _url + qs;
            }
            else {
                qs = qs.substr(1);      // Trim leading &
                return _url + '?' + qs;
            }
        };

        // get -- returns a property from a given object (can be specified as nested)
        $bf.get = function (obj, prop, defaultVal) {
            var val;
            if (prop.indexOf('.') > -1) {
                val = obj;
                var props = prop.split('.');
                for (var i = 0; i < props.length; i++) {
                    val = val[props[i]];
                }
            } else {
                val = obj[val];
            }
            // Return value or default value
            if (val) { return val; }
            else { return defaultVal; }
        };

        // getScript -- based on $script loader
        $bf.getScript = function (src, callback, async) {
            if (typeof (async) === 'undefined') { async = true; }
            if (typeof (src) === 'string' && src.length > 0) {
                var s = document.createElement("script");
                var loaded = false;
                s.onload = s.onreadystatechange = function () {
                    if ((s.readyState && s.readyState !== "complete" && s.readyState !== "loaded") || loaded) {
                        return false;
                    }
                    s.onload = s.onreadystatechange = null;
                    loaded = true;
                    if (typeof (callback) === 'function') { callback(src); }
                };
                s.async = async;
                s.type = 'text/javascript';
                s.src = src;
                var head = document.getElementsByTagName('head')[0];
                head.insertBefore(s, head.firstChild);
            }
        };

        // insertLink <link>
        $bf.insertLink = function (href) {
            if (typeof (href) === 'string' && href.length > 0) {
                var link = document.createElement('link');
                link.type = 'text/css';
                link.rel = 'stylesheet';
                link.href = href;
                var head = document.getElementsByTagName('head')[0];
                head.insertBefore(link, head.firstChild);
            }
        };

        // insertStyle <style>
        $bf.insertStyle = function (css) {
            if (typeof (css) === 'string' && css.length > 0) {
                var style = document.createElement('style');
                style.type = 'text/css';

                if (style.styleSheet) {     // IE
                    style.styleSheet.cssText = css;
                } else {                    // Everyone else
                    style.appendChild(document.createTextNode(css));
                }

                // Insert into head
                var head = document.getElementsByTagName('head')[0];
                head.insertBefore(style, head.firstChild);
            }
        };

        // jqueryAvailable
        $bf.jQueryAvailable = function () {
            var jq = GLOBALS.__sharejQuery ? window.jQuery : $bf.jQuery;
            return (
                typeof (jq) === 'function' &&                // jQuery Loaded
                Number(jq.fn.jquery.split('.')[1]) >= 4      // jQuery at least verison 1.4
            );
        };

        // onjQueryDomReady
        $bf.onjQueryDomReady = function (callback) {    // callback = f(jQuery)
            $bf.onjQueryReady(function ($) {
                $(function () {
                    if (typeof (callback) === 'function') { callback($); }
                });
            });
        };

        // onjQueryReady
        $bf.onjQueryReady = function (callback) {   // callback = f(jQuery)
            // Check if we have our pointer to a copy of jQuery
            if (typeof (GLOBALS.jQuery) !== 'function') {
                // If not check if jQuery has been loaded by something else
                if ($bf.jQueryAvailable()) {
                    GLOBALS.jQuery = window.jQuery;
                    $bf.jQuery = GLOBALS.jQuery;        // Developer shorthand
                    if (typeof (callback) === 'function') { callback(GLOBALS.jQuery); }
                } else {
                    // If not present, load it ourself
                    if (typeof ($bf.onjQueryReady.funcs) === 'undefined') { $bf.onjQueryReady.funcs = []; }
                    $bf.onjQueryReady.funcs.push(callback);
                    if (!$bf.onjQueryReady.loading) {
                        $bf.onjQueryReady.loading = true;
                        // Inject async script tag then wait for load
                        $bf.getScript('http://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js', function () {
                            $bf.onjQueryReady.loading = false;
                            GLOBALS.jQuery = window.jQuery;
                            $bf.jQuery = GLOBALS.jQuery;        // Developer shorthand
                            if (!GLOBALS.__sharejQuery) { window.jQuery.noConflict(true); }
                            // Fire stored callbacks
                            for (var i = 0; i < $bf.onjQueryReady.funcs.length; i++) {
                                var f = $bf.onjQueryReady.funcs[i];
                                if (typeof (f) === 'function') { f(GLOBALS.jQuery); }
                            }
                            $bf.onjQueryReady.funcs = null;
                        });
                    }
                }
            } else {
                $bf.jQuery = GLOBALS.jQuery;        // Developer shorthand
                if (typeof (callback) === 'function') { callback(GLOBALS.jQuery); }
            }
        };

        // parseUrl
        $bf.parseUrl = function (_url) {
            $bf.parseUrl.__cache = $bf.parseUrl.__cache || {};
            if (typeof ($bf.parseUrl.__cache[_url]) !== 'undefined') { return $bf.parseUrl.__cache[_url]; }

            _url = _url || window.location.href;
            var url = {};

            var pattern = new RegExp('(http[s]?):\/\/([^/?]+)([^\?]*)?(\\?[a-z0-9=&%]+)?', 'i');
            var match = pattern.exec(_url);
            url.protocol = match[1];
            url.host = match[2];
            url.path = match[3] || '';
            url.rawPath = url.path;
            url.segments = [];
            url.querystrings = {};
            url.hash = '';

            // Check for hash (remove early if so)
            if (url.path.indexOf('#') > -1) {
                var s = url.path.split('#');
                url.path = s[0];
                url.hash = s[1];
            } else if (_url.indexOf('#') > -1) {
                url.hash = _url.split('#')[1];
            }

            // Parse segments
            if (url.path.length > 0) {
                url.segments = url.path.substr(1).split('/');
                // Remove trailing querystring or hash if present
                var l = url.segments.length - 1;
                var last = url.segments[l];
                if (last.indexOf('?')) {
                    url.segments[l] = last.split('?')[0];
                }
            }

            // Parse querystrings
            if (match[4]) {
                var qs = match[4].substr(1).split('&');
                for (var i = 0; i < qs.length; i++) {
                    var param = qs[i].split('=');
                    url.querystrings[param[0]] = param[1];
                }
            }

            $bf.parseUrl.__cache[_url] = url;
            return url;
        };

        // sanitize
        $bf.sanitize = function (_o) {
            for (var key in _o) {
                if (!_o.hasOwnProperty(key)) {
                    delete _o[key];
                }
            }
            return _o;
        };

        // setLocationHash
        $bf.setLocationHash = function (_hash) {
            var href = window.location.href;
            if (href.indexOf('#') > -1) {
                href = href.split('#')[0];
            }
            window.location.href = href + '#' + _hash;
        };

        // stripHtml
        $bf.stripHtml = function (html) {
            return html.replace(/<[^>]+>/g, '');
        };

        // supportsXDocMessaging
        $bf.supportsXDocMessaging = function () {
            if (typeof ($bf.__supportsXDocMessaging) === 'undefined') {
                $bf.__supportsXDocMessaging = (typeof (window.postMessage) === 'function');
            }
            return $bf.__supportsXDocMessaging;
        };

        // trim
        $bf.trim = function (_s) {
            return _s.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
        };

        // warn
        $bf.warn = function (_s) {
            if (typeof (console) !== 'undefined' && typeof (console.warn) !== 'undefined') {
                console.warn('$bf: ' + _s);
            }
        };

        /* ==========================================================================================
        Pub/Sub
        ========================================================================================== */
        $bf.pubsub = {};
        $bf.pubsub.__subs = [];

        // pub
        $bf.pubsub.publish = function () {
            /* INPUT:
            function(realm, widget-id, event, data)
            function('pub string', data)
            function({ pub: values }, data) */

            // Build pubstring to match off of
            var pubString = '',
            dict,
            data;
            if (arguments.length <= 2) {
                var val = arguments[0];
                data = arguments[1];
                if (typeof (val) === 'string') {
                    pubString = val;
                } else if (typeof (val) === 'object') {
                    dict = $bf.extend({ realm: 'widget', type: 'generic-widget', id: '', message: '' }, val);
                }
            } else {
                dict = { realm: arguments[0], type: arguments[1], id: arguments[2], message: arguments[3] };
                data = arguments[4];
            }
            if (dict) {
                pubString = dict.realm + '|' + dict.type + '|' + dict.id + '|' + dict.message;
            }

            // Iterate subscriptions and call
            for (var i = 0; i < $bf.pubsub.__subs.length; i++) {
                var sub = $bf.pubsub.__subs[i];
                if (sub.compiledSub.test(pubString)) {
                    sub.callback(data, pubString);
                }
            }
        };

        // subscribe
        $bf.pubsub.subscribe = function () {
            /* INPUT:
            function(realm, widget-id, event, callback)
            function('pub string', callback)
            function({ realm, type, id, message }, callback) */

            // Build pubstring to match off of
            var subString = '',
            dict,
            callback;
            if (arguments.length <= 2) {
                var val = arguments[0];
                callback = arguments[1];
                if (typeof (val) === 'string') {
                    subString = val;
                } else if (typeof (val) === 'object') {
                    dict = val;
                }
            } else {
                dict = { realm: arguments[0], type: arguments[1], id: arguments[2], message: arguments[3] };
                callback = arguments[4];
            }
            if (dict) {
                if (dict.realm) { subString += dict.realm; }
                else { subString += '[^|]+' }
                subString += '\\|';
                if (dict.type) { subString += '[^|]*' + dict.type + '[^|]*'; }
                else { subString += '[^|]+' }
                subString += '\\|';
                if (dict.id) { subString += dict.id; }
                else { subString += '[^|]+' }
                subString += '\\|';
                if (dict.id) { subString += dict.message; }
                else { subString += '[^|]+' }
            }

            $bf.pubsub.__subs.push({
                subString: subString,
                compiledSub: new RegExp(subString),
                callback: callback
            });

            return $bf.pubsub.__subs.length - 1;
        };

        // unsubscribe
        $bf.pubsub.unsubscribe = function (_id) {
            // TODO:
            // delete $bf.pubsub.__subs[_id];
        };


        /* ==========================================================================================
        Widget Instance Functions, available on the wrapped widget "$bf(widget)"
        ========================================================================================== */

        // bind
        $bf.fn.prototype.bind = function (elem) {
            $bf.onjQueryReady((function ($) {

                // Bind cross-domain messages if widget has recipient functions
                // onPostMessage = f(message, data, raw)
                if (typeof (this.widget.onPostMessage) === 'function' || typeof (this.widget.onPostLegacyMessage) === 'function') {
                    var messageHandler = function (e) {
                        var data = e.data;
                        if (e.origin.indexOf('theblogfrog.com') < 0)
                            return;

                        var widgetId = data.substr(0, data.indexOf(':'));
                        data = data.substr(widgetId.length + 1);

                        // Catch legacy messages (sent mainly from bf-iframe.js)
                        // This isn't a very strong way to do this, but it works...
                        if (data.substr(0, 3) !== 'bf-' && typeof (this.widget.onPostLegacyMessage) === 'function') {
                            this.widget.onPostLegacyMessage(widgetId, data, e);
                        }

                        // Otherwise send a message as it's supposed to be
                        if (this.widget.config.elemId == widgetId || widgetId === 'bf-widget') {
                            var msg = data.substr(0, data.indexOf(':'));
                            data = data.substr(msg.length + 1);
                            this.widget.onPostMessage(msg, data, e);
                        }
                    };

                    if (typeof window.addEventListener !== 'undefined') { window.addEventListener('message', messageHandler.sbind(this), false); }
                    else if (typeof window.attachEvent !== 'undefined') { window.attachEvent('onmessage', messageHandler.sbind(this)); }
                }

                // Redefine element (if specified) and clear any loading CSS
                if (typeof (elem) !== 'undefined') { this.widget.baseTag = $(elem); }
                this.widget.baseTag.removeClass('bf-widget-loading');

                // Call widget's bind
                $bf(this.widget).invoke('bind', [elem]);

            }).sbind(this));
        };

        // callApi
        $bf.fn.prototype.callApi = function (_url, _params, _success, _fail) {    // callback = f(data)
            _params = _params || {};

            // Error handling for JSONP
            var response = false;
            var timeout = setTimeout((function () {
                if (!response && typeof (_fail) === 'function') {
                    _fail.call(this.widget);
                }
            }).sbind(this), 5000);   // 5 second timeout on api calls

            // Cleanup url (if necessary)
            if (_url.indexOf('http') > -1) {
                // Remove host
                _url = _url.replace(/http[s]?:\/\//i, '');
                var i = _url.indexOf('/');
                _url = _url.substr(i);
            }
            // Remove callback
            if (_url.indexOf('callback=') > -1) {
                _url = _url.replace(/[?|&]callback=[^?&]+/i, '');
            }

            // Setup callback
            GLOBALS.uniqueCounter += 1;
            _params.callback = '__BFApiCallback' + GLOBALS.uniqueCounter;
            window[_params.callback] = (function (json) {

                // Update state
                clearTimeout(timeout);
                response = true;
                this.widget.isLoading = false;

                // Pass JSON back to callback
                json = $bf.sanitize(json);
                _success.apply(this.widget, [json]);

            }).sbind(this);

            // Inject script into <head>
            var url = $bf.buildUrl(this.widget.config.apiHost + _url, _params);
            $bf.getScript(url);
            this.widget.isLoading = true;
        };

        // disableLoading
        $bf.fn.prototype.disableLoading = function (_b) {
            if (typeof (_b) === 'undefined') { _b = true; }
            this.widget.__enableLoading = !_b;
        };

        // doneLoading
        $bf.fn.prototype.doneLoading = function () {
            if (typeof (this.widget.config.onLoaded) === 'function') {
                this.widget.config.onLoaded(this.widget, this.widget.config.elemId);
            }
            $bf(this.widget).publish('loaded');
        };

        // init
        $bf.fn.prototype.init = function (_userConfig, _defaultConfig) {
            _defaultConfig = _defaultConfig || {};

            // Setup internal "magic" properties
            this.widget.__enableLoading = true;
            this.widget.__types = [];
            // $bf.__widgets.push(this.widget);

            this.widget.type = 'generic-widget';
            this.widget.description = 'Widget';
            this.widget.version = 1;
            this.widget.state = {};

            // Increment widget counter
            GLOBALS.widgetCounter += 1;

            var generic = {
                apiHost: window.BlogfrogApiHost || 'http://api.theblogfrog.com',
                customCSS: '',
                customCSSFile: '',
                elemId: 'bf-widget' + GLOBALS.widgetCounter,
                faceboxPath: '/widgets/v2/lib/facebox-min.js',
                iframeHost: window.BlogfrogIframeHost || 'http://iframe.theblogfrog.com',
                onLoaded: null,
                onDataReceived: null,
                linkBase: window.BlogfrogLinkBase || 'http://theblogfrog.com',
                staticHost: window.BlogfrogStaticHost || 'http://static.theblogfrog.com',
                widgetHost: window.BlogfrogWidgetHost || 'http://widget.theblogfrog.com',
                url: '',
                userId: -1
            };

            // Merge config
            if (typeof (_defaultConfig) === 'object') {
                generic = $bf.extend(generic, _defaultConfig);
                this.widget.config = $bf.extend(generic, _userConfig);
            } else {
                this.widget.config = $bf.extend(generic, _userConfig);
            }

            // Check for "publisher override" values (delivered by BF ad network)
            if (typeof (window.BlogFrogUserID) !== 'undefined') {
                this.widget.config.userId = Number(window.BlogFrogUserID);
            }

            $bf(this.widget).invoke('init', [_userConfig]);

            // Define templates
            if (typeof (this.widget.config.templates) === 'object') {
                this.widget.templates = $bf.extend({}, this.widget.config.templates);
            } else {
                this.widget.templates = {};
            }
            $bf(this.widget).invoke('defineTemplates');

            return this;
        };

        // includeFacebox
        $bf.fn.prototype.includeFacebox = function (_override) {
            // _override will cause facebox to get re-included if it's already loaded

            var initFacebox = function () {
                $bf.jQuery.facebox.settings.opacity = 0.35;
            };

            $bf.onjQueryReady((function () {
                if (typeof ($bf.jQuery.facebox) === 'undefined' || _override) {
                    $bf.getScript(this.widget.config.staticHost + this.widget.config.faceboxPath, initFacebox.sbind(this), true);
                } else if (!$bf._initFacebox) {
                    initFacebox.call(this);
                    $bf._initFacebox = true;
                }
            }).sbind(this));
        };

        // insertLink
        $bf.fn.prototype.insertLink = function (_href) {
            $bf.insertLink(_href);
            return this;
        };

        // insertStyle
        $bf.fn.prototype.insertStyle = function (_css) {
            if (typeof (_css) === 'string' && _css.length > 0) {
                _css = blogfrog.template.render(_css, this.widget);
                $bf.insertStyle(_css);
            }
            return this;
        };

        // invoke
        $bf.fn.prototype.invoke = function (_f, args) {
            if (typeof (this.widget[_f]) === 'function') {
                if (typeof (args) !== 'undefined') {
                    this.widget[_f].apply(this.widget, args);
                } else {
                    this.widget[_f].call(this.widget);
                }
            }
            return this;
        };

        // load
        $bf.fn.prototype.load = function () {
            // Write generic "Loading" markup
            if (this.widget.__enableLoading) {
                document.write(blogfrog.template.render(' \
                <div id="{{ config.elemId }}" class="bf-widget bf-widget-loading bf-{{ type }}"> \
                    <img src="{{ config.staticHost }}/widgets/v2/ajax-loader.gif" /> \
                    <span>Loading {{ description }}...</span> \
                </div>', this.widget));
            } else {
                document.write(blogfrog.template.render('<div id="{{ config.elemId }}" class="bf-widget bf-{{ type }}"></div>', this.widget));
            }

            $bf(this.widget).invoke('load');
            return this;
        };

        // onjQueryDomReady
        $bf.fn.prototype.onjQueryDomReady = function (callback) {
            $bf.onjQueryDomReady((function ($) {
                if (typeof (callback) === 'function') { callback.apply(this.widget, [$]); }
            }).sbind(this));
        };

        // onjQueryReady
        $bf.fn.prototype.onjQueryReady = function (callback) {
            $bf.onjQueryReady((function ($) {
                if (typeof (callback) === 'function') { callback.apply(this.widget, [$]); }
            }).sbind(this));
        };

        $bf.fn.prototype.postMessage = function (message, data, targetElem) {
            if (typeof (data) === 'undefined') { data = ''; }

            if ($bf.supportsXDocMessaging()) {
                // Get target
                var target = null;
                if (typeof (targetElem) === 'object') { // typeof == jQuery
                    target = targetElem.get(0);
                } else if (typeof (targetElem) === 'string') {
                    target = $(targetElem).get(0);
                } else {
                    target = document.getElementById(this.widget.config.elemId);
                }
                target.contentWindow.postMessage(message + ':' + data, '*');
            };
        };

        // run
        $bf.fn.prototype.run = function (_config) {
            var baseConfig = this.widget.baseConfig || {};
            $bf(this.widget).init(_config, baseConfig);
            $bf(this.widget).load();
            return this;
        };

        // publish
        $bf.fn.prototype.publish = function (_message, _data) {
            // Build list of types
            var types = '';
            // (backwards compatibility)
            if (this.widget.__types.length === 0) { types = this.widget.type; }
            else {
                for (var i = 0; i < this.widget.__types.length; i++) {
                    types += this.widget.__types + ',';
                }
                types = types.substr(0, types.length - 1);
            }

            // Prep data
            _data = _data || {};
            _data = $bf.extend({
                id: this.widget.config.elemId,
                message: _message
            }, _data, { flat: true });
            _data.widget = this.widget;

            // Publish
            $bf.pubsub.publish({ realm: 'widget', type: types, id: this.widget.config.elemId, message: _message }, _data);
        };

        // setWidgetType
        $bf.fn.prototype.setWidgetType = function (_type) {
            this.widget.__types.push(_type);
            this.widget.type = _type;
        };

        /* ==========================================================================================
        Load shared resources
        ========================================================================================== */

        // Quancast tracking
        $bf.insertQuantcast = function () {
            window._qoptions = { qacct: "p-0dDgbcU3aTMWc" };
            $bf.getScript('http://edge.quantserve.com/quant.js', undefined, false);
            GLOBALS.__quantcastAdded = true;
        };
        if (!GLOBALS.__quantcastAdded) { $bf.insertQuantcast(); }

        // Load CSS needed by all widgets (bf-widget-loading and bf-no-script)
        $bf.insertStyle(' \
            div.bf-widget-loading { -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; border: solid 1px #ccc; padding: 20px; text-align: center; background-image: none !important; background-color: #fff !important; } \
            div.bf-widget-loading img { margin-right: 5px; vertical-align: middle; } \
            div.bf-no-script { display: none; position: absolute; top: -9999px; left: -9999px; } \
        ');

    })(window.$bf.v2, window.$bf.globals);
}
/*
 * Facebox (for jQuery)
 * version: 1.2 (05/05/2008)
 *
 * Licensed under the MIT:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 * Copyright 2007, 2008 Chris Wanstrath [ chris@ozmm.org ]
 */

 (function($bf) {

    $bf.onjQueryReady(function (jQuery) {
        // Faecbox original source
        (function (f) { f.facebox = function (m, l) { f.facebox.loading(); if (m.ajax) { g(m.ajax) } else { if (m.image) { c(m.image) } else { if (m.div) { j(m.div) } else { if (f.isFunction(m)) { m.call(f) } else { f.facebox.reveal(m, l) } } } } }; f.extend(f.facebox, { settings: { opacity: 0, overlay: true, loadingImage: "http://theblogfrog.com/facebox/loading.gif", closeImage: "http://theblogfrog.com/facebox/closelabel.gif", imageTypes: ["png", "jpg", "jpeg", "gif"], faceboxHtml: '    <div id="facebox" style="display:none;">       <div class="popup">         <table>           <tbody>             <tr>               <td class="tl"/><td class="b"/><td class="tr"/>             </tr>             <tr>               <td class="b"/>               <td class="body">                 <div class="content">                 </div>                 <div class="footer" id="faceboxfooter" style="display:block">                   <a href="#" class="close">                     <img src="http://theblogfrog.com/facebox/closelabel.gif" title="close" class="close_image" />                   </a>                 </div>               </td>               <td class="b"/>             </tr>             <tr>               <td class="bl"/><td class="b"/><td class="br"/>             </tr>           </tbody>         </table>       </div>     </div>' }, loading: function () { k(); if (f("#facebox .loading").length == 1) { return true } e(); f("#facebox .content").empty(); f("#facebox .body").children().hide().end().append('<div class="loading"><img src="' + f.facebox.settings.loadingImage + '"/></div>'); f("#facebox").css({ top: h()[1] + (i() / 10), left: 385.5 }).show(); f(document).bind("keydown.facebox", function (l) { if (l.keyCode == 27) { f.facebox.close() } return true }); f(document).trigger("loading.facebox") }, reveal: function (m, l) { f(document).trigger("beforeReveal.facebox"); if (l) { f("#facebox .content").addClass(l) } f("#facebox .content").append(m); f("#facebox .loading").remove(); f("#facebox .body").children().fadeIn("normal"); f("#facebox").css("left", f(window).width() / 2 - (f("#facebox table").width() / 2)); f(document).trigger("reveal.facebox").trigger("afterReveal.facebox") }, close: function () { f(document).trigger("close.facebox"); return false } }); f.fn.facebox = function (l) { k(l); function m() { f.facebox.loading(true); var n = this.rel.match(/facebox\[?\.(\w+)\]?/); if (n) { n = n[1] } j(this.href, n); return false } return this.click(m) }; function k(n) { if (f.facebox.settings.inited) { return true } else { f.facebox.settings.inited = true } f(document).trigger("init.facebox"); d(); var l = f.facebox.settings.imageTypes.join("|"); f.facebox.settings.imageTypesRegexp = new RegExp("." + l + "$", "i"); if (n) { f.extend(f.facebox.settings, n) } f("body").append(f.facebox.settings.faceboxHtml); var m = [new Image(), new Image()]; m[0].src = f.facebox.settings.closeImage; m[1].src = f.facebox.settings.loadingImage; f("#facebox").find(".b:first, .bl, .br, .tl, .tr").each(function () { m.push(new Image()); m.slice(-1).src = f(this).css("background-image").replace(/url\((.+)\)/, "$1") }); f("#facebox .close").click(f.facebox.close); f("#facebox .close_image").attr("src", f.facebox.settings.closeImage) } function h() { var m, l; if (self.pageYOffset) { l = self.pageYOffset; m = self.pageXOffset } else { if (document.documentElement && document.documentElement.scrollTop) { l = document.documentElement.scrollTop; m = document.documentElement.scrollLeft } else { if (document.body) { l = document.body.scrollTop; m = document.body.scrollLeft } } } return new Array(m, l) } function i() { var l; if (self.innerHeight) { l = self.innerHeight } else { if (document.documentElement && document.documentElement.clientHeight) { l = document.documentElement.clientHeight } else { if (document.body) { l = document.body.clientHeight } } } return l } function d() { var l = f.facebox.settings; l.loadingImage = l.loading_image || l.loadingImage; l.closeImage = l.close_image || l.closeImage; l.imageTypes = l.image_types || l.imageTypes; l.faceboxHtml = l.facebox_html || l.faceboxHtml } function j(m, l) { if (m.match(/#/)) { var n = window.location.href.split("#")[0]; var o = m.replace(n, ""); f.facebox.reveal(f(o).clone().show(), l) } else { if (m.match(f.facebox.settings.imageTypesRegexp)) { c(m, l) } else { g(m, l) } } } function c(m, l) { var n = new Image(); n.onload = function () { f.facebox.reveal('<div class="image"><img src="' + n.src + '" /></div>', l) }; n.src = m } function g(m, l) { f.get(m, function (n) { f.facebox.reveal(n, l) }) } function b() { return f.facebox.settings.overlay == false || f.facebox.settings.opacity === null } function e() { if (b()) { return } if (f("facebox_overlay").length == 0) { f("body").append('<div id="facebox_overlay" class="facebox_hide"></div>') } f("#facebox_overlay").hide().addClass("facebox_overlayBG").css("opacity", f.facebox.settings.opacity).click(function () { f(document).trigger("close.facebox") }).fadeIn(200); return false } function a() { if (b()) { return } f("#facebox_overlay").fadeOut(200, function () { f("#facebox_overlay").removeClass("facebox_overlayBG"); f("#facebox_overlay").addClass("facebox_hide"); f("#facebox_overlay").remove() }); return false } f(document).bind("close.facebox", function () { f(document).unbind("keydown.facebox"); f("#facebox").fadeOut(function () { f("#facebox .content").removeClass().addClass("content"); a(); f("#facebox .loading").remove() }) }) })(jQuery);
        // Insert required CSS
        var faceBoxCss = "#facebox a.close { margin-right: 8px; margin-bottom: 5px; } #facebox tr { border: 0 none !important; } #facebox td { border: 0 none !important; padding: 0 !important; } #facebox table { background: Transparent none !important; } #facebox .content {padding:0 !important; margin:0 !important; width:auto !important; float:none !important;} #facebox .b{background:url(http://static.theblogfrog.com/facebox/b.png);} #facebox .tl{background:url(http://static.theblogfrog.com/facebox/tl.png);} #facebox .tr{background:url(http://static.theblogfrog.com/facebox/tr.png);} #facebox .bl{background:url(http://static.theblogfrog.com/facebox/bl.png);} #facebox .br{background:url(http://static.theblogfrog.com/facebox/br.png);} #facebox{position:absolute;top:0;left:0;z-index:1001;text-align:left;} #facebox .popup{position:relative;} #facebox table{border-collapse:collapse;} #facebox td{border-bottom:0;padding:0;} #facebox .body{padding:10px;background:#fff;width:370px;} #facebox .loading{text-align:center;} #facebox .image{text-align:center;} #facebox img{border:0;margin:0;} #facebox .footer{border-top:1px solid #DDD;padding-top:5px;padding-bottom:5px;margin-top:10px;text-align:right;} #facebox .tl,#facebox .tr,#facebox .bl,#facebox .br{height:10px;width:10px;overflow:hidden;padding:0;}#facebox_overlay{position:fixed;top:0;left:0;height:100%;width:100%;}.facebox_hide{z-index:-100;}.facebox_overlayBG{background-color:#000;z-index:1000;}* html #facebox_overlay{position:absolute;height:expression(document.body.scrollHeight>document.body.offsetHeight ? document.body.scrollHeight:document.body.offsetHeight+'px');}";
        var style = document.createElement('style');
        style.type = 'text/css';
        if (style.styleSheet) {     // IE
            style.styleSheet.cssText = faceBoxCss;
        } else {                    // Everyone else
            style.appendChild(document.createTextNode(faceBoxCss));
        }
        // Insert into head
        var head = document.getElementsByTagName('head')[0];
        head.insertBefore(style, head.firstChild);
    });

})(window.$bf.v2);
/*  ============================================================
CollapseExpand plugin
============================================================ */

(function($bf) {

    $bf.controls.CollapseExpand = function () { };
    (function(control) {
        control.version = 1.2;

        // init
        control.init = function (_settings, _elem) {
            // Setup config
            this.config = $bf.extend({
                linesToShow: 3,
                expandText: '+ Show More',
                collapseText: '- Show Less'
            }, _settings);
            this.state = { };

            $bf.onjQueryDomReady((function($) {
                // Setup element dimensions
                this.baseTag = $(_elem)
                    .css('height', 'auto');
                this.state.originalHeight = this.baseTag.height();

                // Set a callback to set the proper height if there are images in the content
                // Note this technically should use jQuery 1.5's new async "promise" system to
                // trap the loading of all images within the content area, not just the first one.
                // For now the first one at least fixes the sharing problem
                var imgs = this.baseTag.find('img').first();
                if (imgs.length > 0) {
                    imgs.load((function() {
                        this.state.originalHeight = this.baseTag.height();
                    }).sbind(this));
                }

                // Calculate new dimensions
                var lineHeight = Number(this.baseTag.css('line-height').replace('px', ''));
                if (!lineHeight || lineHeight == 1) {
                    lineHeight = Number(this.baseTag.css('font-size').replace('px', '')) + 3;
                }
                this.state.maxHeight = (this.config.linesToShow * lineHeight) - 0;

                // Check if we need to expand/collapse at all
                if (this.state.originalHeight > this.state.maxHeight && (this.state.originalHeight - 5) > (this.state.maxHeight + lineHeight)) {
                    // Prep children
                    this.baseTag.children().each(function () {
                        $(this).css({ 'padding-left': 0, 'padding-top': 0, 'margin-left': 0, 'margin-top': 0 });
                    });
                    // Create expand-o container around children
                    this.content = $('<div />')
                        .addClass('shrunk-content')
                        .css('overflow', 'hidden')
                        .html(this.baseTag.html());
                    this.container = $('<div />')
                        .addClass('bf-collapse-expand')
                        .append(this.content)
                        .append($('<a />')
                            .addClass('expand')
                            .attr('href', '#Expand')
                            .html(this.config.expandText)
                            .click(this.onClick.sbind(this))
                        );
                    this.baseTag.html(this.container);
                    // Start it
                    this.collapse();
                }
            }).sbind(this));
        };

        // onClick
        control.onClick = function (e) {
            var $ = $bf.jQuery;
            var target = $(e.currentTarget);

            target.blur(); // De-focus link
            this.state.collapsed ? this.expand() : this.collapse();
            return false;
        };

        // expand
        control.expand = function () {        
            this.state.collapsed = false;
            this.content
                .css('overflow', 'visible')
                .animate({ height: this.state.originalHeight }, 250, (function () {
                    this.container.find('a.expand').html(this.config.collapseText)
                }).sbind(this));
        };

        // collapse
        control.collapse = function (skipAnimation) {
            var postAnimation = function() {
                this.container.find('a.expand').html(this.config.expandText)
            };
        
            this.state.collapsed = true;
            this.content.css({ 
                overflow: 'hidden',
                position: 'relative'    
            });
      
            if (!skipAnimation) {
                this.content.animate({ height: this.state.maxHeight }, 250, postAnimation.sbind(this));
            } else {
                this.content.css('height', this.state.maxHeight + 'px');
                postAnimation.call(this);
            }
        };
    }($bf.controls.CollapseExpand.prototype));

})(window.$bf.v2);
/// <reference path="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.4.4-vsdoc.js" />
/// <reference path="/widgets/v2/widget-core.js" />
/*global $bf: true, blogfrog: true, log: true, $: false, jQuery: false */

(function ($bf) {

    $bf.widgets.EmbeddedDiscussion = function () { };
    (function (widget) {

        widget.baseConfig = {
            allowAttachments: false,
            bodyFormat: 'html',         // html or plain
            editUrl: '/community/discussion-edit.aspx',
            iframeUrl: '{{ config.iframeHost }}/{{ discussion.communityid }}/embedded-reply?threadid={{ discussion.id }}&iframe-height=400&buttonfontfamily={{ config.buttonFontFamily:escape }}&widgethost={{ config.widgetHost:escape }}&unitname={{ config.unitName:escape }}&widgetid={{ config.elemId:escape }}&allowAttachments={{ config.allowAttachments }}&twitterhash={{ config.twitterHash:escape }}',
            linesToShow: 3,
            profileUrl: 'http://theblogfrog.com/Users/Profile/UserProfile.aspx?back=0',
            onRepliesAdded: function (replies, rendered) { },
            replies: 8,
            replyShareUrl: '{{ config.linkBase }}/jump.aspx?replyid={{ reply.id }}',
            sortBy: 'id',               // id
            sortOrder: 'asc',           // asc, desc
            showDiscussionLink: true,
            showReplyBox: true,
            showReplySharing: false,
            showThread: true,
            threadId: 0,
            twitterHash: '@theBlogFrog',
            unitName: 'Response',
            unitNamePlural: 'Responses',
            url: '/v1/discussion/{{ config.threadId }}/replies'
        };

        // init
        widget.init = function (_config) {
            this.type = 'embedded-discussion';
            this.description = 'Conversation';

            // Requirements:
            // Facebox (loaded via ASPX loader)
            // Collapse/Expand (loaded via ASPX loader)
        };

        // load
        widget.load = function () {
            // Start loading of jQuery
            $bf.onjQueryReady();
            $bf(this).includeFacebox();

            // Inject CSS
            $bf(this).insertStyle(this.templates.requiredCSS);
            $bf(this).insertStyle(this.config.customCSS);
            $bf(this).insertLink(this.config.customCSSFile);
            $bf(this).onjQueryReady(function ($) {
                if ($.browser.msie && Number($.browser.version) <= 7) {
                    $bf(this).insertStyle(this.templates.IE7CSS);
                }
            });

            // Hit API
            this.config.url = blogfrog.template.render(this.config.url, { config: this.config });
            $bf(this).callApi(this.config.url, this.getInitialApiParams(), this.render, this.onInitialLoadError);
        };

        // render
        widget.render = function (data) {
            // Grab values from API response to setup widget state
            this.state.data = data;
            this.state.nextUrl = data.meta.next;
            this.state.userCommentCount = 0;
            this.state.repliesShown = 0;
            if (typeof (data.replies) !== 'undefined' && data.replies.length > 0) {
                this.state.lastReplyId = data.replies[data.replies.length - 1].id;
            }

            // Prep data before render
            data.url = this.config.linkBase + data.url;
            data['config'] = this.config;

            // Render thread body if enabled
            if (this.config.showThread) {
                data['threadbody'] = blogfrog.template.render(this.templates.thread, data);
            }

            // Render widget base and replies
            var html = blogfrog.template.render(this.templates.widgetBase, data, function (filter, value) {
                if (filter == 'requirehttp') {
                    if (value && value.length > 4 && value.substr(0, 4) !== 'http') {
                        return 'http://' + value;
                    }
                    return value;
                } else if (filter === 'noiframe') {
                    if (value.indexOf('iframe.theblogfrog') > -1) {
                        return value.replace(/iframe.theblogfrog/i, 'theblogfrog');
                    }
                }
            });

            // Inject HTML into DOM
            var b = document.getElementById(this.config.elemId);
            // Weird fix code 1-16-2012
            if (b) {
                b.innerHTML = html;
            } else {
                setTimeout(function () {
                    b = document.getElementById(this.config.elemId);
                    log('id', this.config.elemId, 'b', b);
                    b.innerHTML = html;
                } .sbind(this), 0);
            }

            $bf(this).onjQueryReady(function ($) {
                this.baseTag = $('#' + this.config.elemId);
                this.bindPopupProfileClicks(this.baseTag);

                // Setup reply iframe (if enabled)
                if (this.config.showReplyBox) {
                    // Pass correct font to iframe
                    data.config['buttonFontFamily'] = this.baseTag.find('a.more-replies').css('font-family');
                    var iframeUrl = blogfrog.template.render(this.config.iframeUrl, data, function (filter, value) {
                        if (filter == 'escape') {
                            return escape(value);
                        }
                    });
                    // Stick the URL on the iframe's SRC attribute
                    this.baseTag.find('iframe[data-function="reply-iframe"]', '#' + this.config.elemId).attr('src', iframeUrl);
                }

                // Render replies
                this.appendReplies(data.replies, false);

                // Bind markup to events
                $bf(this).bind();
                $bf(this).doneLoading();
            });
        };

        /* ========================================================================================== */

        // appendReplies
        widget.appendReplies = function (replies, slideDown) {
            if (typeof (slideDown) === 'undefined') { slideDown = true };

            var $ = $bf.jQuery;
            var showMore = this.baseTag.find('a.more-replies');

            showMore.hide();

            if (replies.length > 0) {
                replies = $bf.sanitize(replies);
                this.state.repliesShown += replies.length;

                // Prep data before render
                for (var i = 0; i < replies.length; i++) {
                    var reply = replies[i]

                    // Manually check if the reply is by the current user & update data
                    //if ($bf.currentUser.id === reply.poster.id) { reply.isuser = true; }
                    //else { reply.isuser = false; }
                    // TODO: Temporary fix
                    reply.isuser = false;

                    // Clean out empty <p> tags from CKEditor
                    if (typeof (reply.body) !== 'undefined') {
                        reply.body = reply.body.replace(/<p>[\s]*&nbsp;[\s]*<\/p>/gi, '');
                    }
                }

                // Render to HTML + append to current widget
                var config = this.config;
                var state = this.state;
                var context = {
                    state: state.data,
                    replies: replies,
                    config: config
                };
                var html = blogfrog.template.render(this.templates.replies, context, function (filter, value) {
                    if (filter == 'maxlen50') {
                        if (value.length > 50) { return value.substr(0, 50) + '...'; }
                        return value;
                    }
                    else if (filter == 'shareurl') {
                        var context = {
                            state: state,
                            replies: replies,
                            reply: { id: value },
                            config: config
                        };
                        var url = config.replyShareUrl;
                        if (url.length === 0) { $bf.warn('replyShareUrl is blank (likely not configured).'); }
                        url = blogfrog.template.render(config.replyShareUrl, context);
                        return url;
                    }
                    else if (filter == 'escapedshareurl') {
                        var context = {
                            state: state,
                            replies: replies,
                            reply: { id: value },
                            config: config
                        };
                        var url = config.replyShareUrl;
                        if (url.length === 0) { $bf.warn('replyShareUrl is blank (likely not configured).'); }
                        url = escape(blogfrog.template.render(config.replyShareUrl, context));
                        return url;
                    }
                    else if (filter == 'sharetext') {
                        value = $bf.stripHtml(value);
                        value = value.replace(/\r|\n/, '');
                        value = $bf.trim(value);
                        if (value.length > 100) { value = value.substr(0, 100) + '...' }
                        return escape(value);
                    }
                    else if (filter === 'escape') {
                        return escape(value);
                    }
                });
                var rendered = $('<div />').html(html).hide();

                this.baseTag.find('.bf-replies').append(rendered);
                if (slideDown) { rendered.slideDown(); }
                else { rendered.show(); }

                // Setup collapse/expand on user text
                var expandText = '+ Show Full ' + this.config.unitName;
                var config = this.config;
                rendered.find('.usergenerated').each(function () {
                    new $bf.controls.CollapseExpand().init({ linesToShow: config.linesToShow, expandText: expandText }, $(this));
                });

                // Update the visibility of the "show more" button
                if (this.state.repliesShown < this.state.data.discussion.replycount) {
                    showMore.show();

                    // Render proper button text
                    if (this.state.repliesShown <= 0) {
                        // "Show Responses"
                        showMore.html('Show ' + this.config.unitNamePlural + ' &#9662;<em></em>');
                    } else {
                        var next = this.config.replies;
                        var left = this.state.data.discussion.replycount - this.state.repliesShown;
                        if (left < next) {
                            showMore.html('Show Last ' + left + ' &#9662;<em></em>');
                        } else {
                            showMore.html('Show Next ' + next + ' &#9662;<em></em>');
                        }
                    }
                } else {
                    showMore.hide();
                }

                // Update the "show count" displayed on the UI
                this.updateUICounts();

                // Bind hover for sharing links
                if (this.config.showReplySharing) {
                    rendered.find('.bf-reply').hover(
                        function () { $(this).find('.bf-reply-sharing').show(); },
                        function () { $(this).find('.bf-reply-sharing').hide(); }
                    );
                }

                // Bind "Show More" click
                if (showMore.is(':visible')) {
                    showMore.unbind('click').click(this.onShowMoreClick.sbind(this));
                }

                // Bind profile popup clicks
                this.bindPopupProfileClicks(rendered);

                // Bind edit links
                rendered.find('a[rel=edit]').click(this.onEditClick.sbind(this));

                // Bind attached image clicks
                rendered.find('img.bf-attached-image, img.uploadedimage:first-child').unbind('click').click(this.onAttachedImageClick.sbind(this));

                // Update state for next pass
                if (this.config.sortBy === 'id' && this.config.sortOrder === 'desc') { this.state.lastReplyId = replies[replies.length - 1].id; }

                // Fire event
                if (typeof (this.config.onRepliesAdded) === 'function') {
                    this.config.onRepliesAdded.apply(this, [replies, rendered]);
                }
            }
        };

        // updateUICounts
        widget.updateUICounts = function () {
            var total = this.state.data.discussion.replycount + this.state.userCommentCount;

            if (total > 0) {
                var remaining = this.state.data.discussion.replycount - this.state.repliesShown;
                var end = this.state.repliesShown + this.state.userCommentCount;

                // Update "upper" count
                this.baseTag.find('.bf-count').html(blogfrog.template.render('Showing 1 to {{ end }} of {{ total }}', { end: end, total: total }));

                // Update "lower" count
                if (remaining > 0) {
                    this.baseTag.find('.bf-count-lower').html(blogfrog.template.render('{{ remaining }} more {{ unitnameplural }} to see!', {
                        unitnameplural: this.config.unitNamePlural,
                        remaining: remaining
                    }));
                } else {
                    this.baseTag.find('.bf-count-lower').html('');
                }
            } else {
                this.baseTag.find('.bf-count').html('');
                this.baseTag.find('.bf-count-lower').html('');
            }

        };

        // bindPopupProfileClicks
        widget.bindPopupProfileClicks = function (parent) {
            var $ = $bf.jQuery;
            $(parent).find('a[rel=popupprofile]').click((function (e) {
                var target = $(e.currentTarget);
                var url = this.config.profileUrl + '&id=' + target.attr('userid');

                if (typeof (this.state.data) !== 'undefined') {
                    url += '&cid=' + this.state.data.discussion.communityid;
                }

                $.facebox('<iframe src="' + url + '" width="800" height="600" frameborder="0" />');
                return false;
            }).sbind(this));
        };

        // getInitialApiParams
        widget.getInitialApiParams = function () {
            var base = {
                details: true,
                count: this.config.replies,
                sortorder: this.config.sortOrder,
                sortby: this.config.sortBy
            };
            if (this.config.format === 'html') { base['bodyplain'] = 'true'; }
            return base;
        };

        // loadAdditionalReplies
        widget.loadAdditionalReplies = function () {
            var success = function (json) {
                this.state.nextUrl = json.meta.next;
                this.appendReplies(json.replies);
            };
            var error = function () { };
            $bf(this).callApi(this.state.nextUrl, {}, success, error);
        };

        // showPostedResponse
        widget.showPostedResponse = function (response) {
            var replies = this.baseTag.find('.bf-replies');
            replies.append(response);
            response.slideDown();
        };

        /* ==========================================================================================
        Event Handlers
        ========================================================================================== */

        widget.onEditClick = function (e) {
            var $ = $bf.jQuery;
            var target = $(e.currentTarget);
            var edited = target.data('edited') || false;

            if (!edited) {
                var html = blogfrog.template.render('<iframe src="{{ host }}{{ path }}?replyid={{ replyid }}&cid={{ communityid }}&embedded=true" width="520" height="515" frameborder="0" />', {
                    host: this.config.iframeHost,
                    path: this.config.editUrl,
                    replyid: target.attr('data-reply-id'),
                    communityid: this.state.data.discussion.communityid
                });
                $.facebox(html);
                target.text('refresh page to see edits').data('edited', true);
            } else {
                window.location.reload();
            }
            return false;
        };

        // onInitialLoadError
        widget.onInitialLoadError = function () {
            // Smart error handling here
            $bf(this).onjQueryReady(function ($) {
                if (typeof (this.baseTag) === 'undefined') {
                    this.baseTag = $('#' + this.config.elemId);
                }
                this.baseTag.html('<p>The embedded widget has loaded properly, but your conversation is not available. (JSON Error)</p>');
            });
        };

        // onPostMesage
        widget.onPostMessage = function (msg, data, e) {
            var $ = $bf.jQuery;

            if (msg == 'bf-facebox-close') {
                $(document).trigger('close.facebox');
            } else if (msg == 'bf-response-posted') {
                // Clean newlines off of JSON
                data = data.replace(/\r\n|\r|\n/g, ' ');
                this.onResponsePosted($.parseJSON(data));
            }
        };

        // onResponsePosted
        widget.onResponsePosted = function (json) {
            var $ = $bf.jQuery;

            // Inject the response into the page
            var response = $(blogfrog.template.render(this.templates.replies, {
                replies: [{
                    id: json.replyid,
                    body: json.input,
                    isuser: true,
                    poster: {
                        id: json.userid,
                        name: json.userfirst,
                        blogurl: json.blogurl,
                        blogtitle: json.blogtitle,
                        image: json.userimg
                    }
                }]
            }));

            response.hide().addClass('bf-new-reply');
            this.showPostedResponse(response);

            // Update counts
            this.state.userCommentCount += 1;
            this.updateUICounts();

            // Bind edit links
            response.find('a[rel=edit]').click(this.onEditClick.sbind(this));

            // Bind attached image clicks
            response.find('img.bf-attached-image, img.uploadedimage:first-child').unbind('click').click(this.onAttachedImageClick.sbind(this));

            // Drop new highlight after 15 seconds
            setTimeout(function () {
                response.removeClass('bf-new-reply');
            }, 15000);
        }

        // onShowMoreClick
        widget.onShowMoreClick = function (e) {
            var $ = $bf.jQuery;
            var target = $(e.currentTarget);

            // Temporarily commented out, IE dies on this line
            // if (!this.isLoading) {
            // TODO: this.showActionAjax(target);
            target.html('Loading... <em></em>');
            this.loadAdditionalReplies();
            //}
            return false;
        };

        // onAttachedImageClick
        widget.onAttachedImageClick = function (e) {
            var $ = $bf.jQuery;
            var target = $(e.currentTarget);

            var maxH = $(window).height() - 150;
            var maxW = $(window).width() - 50;

            var img = $('<img style="max-height: ' + maxH + 'px; max-width: ' + maxW + 'px;" src="' + target.attr('src') + '" />');
            $.facebox(img);
        };

        /* ==========================================================================================
        Templates
        ========================================================================================== */
        widget.defineTemplates = function () {

            this.templates.widgetBase = ' \
                {{{ if threadbody }}} \
                    <div class="bf-thread-container" data-bf-type="threadbody">{{ threadbody }}</div> \
                {{{ end }}} \
                <div class="bf-info"> \
                    <a id="bf-powered-by" href="http://theblogfrog.com?utm_source=blog&utm_medium=embedded_discussion" title="Powered by BlogFrog: We turn blogs into communities">Powered by</a> \
                    <span class="bf-count"></span> \
                </div> \
                <div class="bf-replies"></div> \
                <div class="bf-widget-footer" style="margin:10px 0; line-height: 35px;"> \
                    <div class="bf-continue"> \
                        <a class="bf-button more-replies" href="#ShowMoreReplies">Show More &#9662;<em></em></a> \
                        {{{ if config.showDiscussionLink }}} \
                            <a class="community bf-button" href="{{ config.linkBase:noiframe }}{{ discussion.url }}?utm_medium=embedded_discussion&utm_content=reply">See Conversation in the Community &#9656;<em></em></a> \
                        {{{ end }}} \
                    </div> \
                    <div> \
                        <span class="bf-count-lower"></span> \
                    </div> \
                    {{{ if config.showReplyBox }}} \
                        <div class="bf-action bf-reply-action" style="margin-top:25px;"> \
                            <h3>Reply to Conversation</h3> \
                            <iframe data-function="reply-iframe" scrolling="no" frameborder="0"></iframe> \
                        </div> \
                    {{{ end }}} \
                    {{{ if !config.showReplyBox }}} \
                        <a class="minor-action reply" style="width:190px;" href="{{ config.linkBase }}{{ thread.url }}?utm_medium=embedded_discussion&utm_content=reply">Reply to Conversation &#8594; <em></em></a> \
                    {{{ end }}} \
                </div>';

            this.templates.thread = ' \
                <div class="bf-thread clearfix" style="min-height:68px;"> \
                    <div class="bf-post-meta"> \
                        <div class="bf-person-box"> \
                            <a href="#ViewProfile" userid="{{ discussion.poster.id }}" rel="popupprofile"><img style="width:65px;height:65px;" src="{{ discussion.poster.image }}" alt="{{ discussion.poster.name }}" /></a> \
                        </div> \
                        <span style="display:block; margin-bottom:1px;"> \
                            By <strong>{{ discussion.poster.name }}</strong> \
                            {{{ if discussion.poster.blogtitle }}} \
                                <br/>author of \
                                <a href="http://{{ discussion.poster.blogurl }}" title="Click to visit {{ discussion.poster.name }}' + "'" + 's blog, {{ discussion.poster.blogtitle }}" target="_blank">{{ discussion.poster.blogtitle }}</a> \
                            {{{ end }}} \
                        </span> \
                    </div> \
                    {{{ if discussion.bodyplain }}} \
                        {{ discussion.bodyplain }} \
                    {{{ end }}} \
                    {{{ if !discussion.bodyplain }}} \
                        {{ discussion.body }} \
                    {{{ end }}} \
                </div>';

            this.templates.replies = ' \
                {{{ for reply in replies }}} \
                    <div data-reply-id="{{ reply.id }}" class="bf-reply" data-user-id="{{ reply.poster.id }}"> \
                        <div class="bf-person-box"> \
                            <a href="#ViewProfile" userid="{{ reply.poster.id }}" rel="popupprofile"><img src="{{ reply.poster.image }}" alt="{{ reply.poster.name }}" /></a> \
                            <div class="bf-edit"> \
                                {{{ if reply.isuser }}} \
                                    <a href="http://theblogfrog.com/users/editprofile.aspx" target="_blank">edit profile &#9656;</a> \
                                    <a href="#EditPost" rel="edit" data-reply-id="{{ reply.id }}">edit post</a> \
                                {{{ end }}} \
                            </div> \
                        </div> \
                        <div class="bf-thread-content"> \
                            <div class="bf-post-meta" style="margin-bottom:10px; font-size:75%"> \
                                {{{ if reply.poster.blogtitle }}} \
                                    <span> \
                                        author of <a href="{{ reply.poster.blogurl }}" title="Click to visit {{ reply.poster.name }}' + "'" + 's blog, {{ reply.poster.blogtitle }}" target="_blank">{{ reply.poster.blogtitle:maxlen50 }}</a> \
                                    </span> \
                                {{{ end }}} \
                                <h4> \
                                    {{ reply.poster.name }} \
                                </h4> \
                            </div> \
                            <div class="usergenerated"> \
                                {{{ if reply.bodyplain }}} \
                                    {{ reply.bodyplain }} \
                                {{{ end }}} \
                                {{{ if !reply.bodyplain }}} \
                                    {{ reply.body }} \
                                {{{ end }}} \
                            </div> \
                        </div> \
                        {{{ if config.showReplySharing }}} \
                            <div class="bf-reply-sharing" style="display:none;"> \
                                <span>share</span> \
                                <sup class="facebook"> \
                                    <a href="http://facebook.com/share.php?u={{ reply.id:shareurl }}" target="_blank" title="Share this response on Facebook">Facebook</a> \
                                </sup> \
                                <sup class="twitter"> \
                                    {{{ if reply.bodyplain }}} \
                                        <a href="http://twitter.com/share?url={{ reply.id:shareurl }}&text={{ reply.bodyplain:sharetext }}...%22+{{ config.twitterHash:escape }}" target="_blank" title="Share this response on Twitter">Twitter</a> \
                                    {{{ end }}} \
                                    {{{ if !reply.bodyplain }}} \
                                        <a href="http://twitter.com/share?url={{ reply.id:shareurl }}&text={{ reply.body:sharetext }}...%22+{{ config.twitterHash:escape }}" target="_blank" title="Share this response on Twitter">Twitter</a> \
                                    {{{ end }}} \
                                </sup> \
                            </div> \
                        {{{ end }}} \
                    </div> \
                {{{ end }}}';

            this.templates.requiredCSS = ' \
                #{{ config.elemId }} h3 { margin-top: 15px !important; margin-bottom: 5px !important; font-size: 20px; padding: 0; clear: none; } \
                #{{ config.elemId }} .bf-embedded-discussion { position: relative; } \
                #{{ config.elemId }} .bf-extra-msg { margin-top: 0px; margin-bottom: 15px; font-size: 12px; padding: 0; } \
                #{{ config.elemId }} .bf-reply { min-height: 93px; margin-bottom: 20px; position: relative; border: solid 1px #ddd; padding: 10px; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; background: transparent url({{ config.staticHost }}/images/design2011/embed/embedded-backgrounds.png) repeat-x 0 -42px; } \
                #{{ config.elemId }} .bf-new-reply { border: solid 1px #aaa; -moz-box-shadow: 2px 2px 6px rgba(255,204,0,0.5); -webkit-box-shadow: 2px 2px 6px rgba(255,204,0,0.5); box-shadow: 2px 2px 6px rgba(255,204,0,0.5); } \
                #{{ config.elemId }} .bf-brand { float: right; margin-top: -15px; margin-right: 10px; text-align: center; margin-left: 10px; margin-bottom: 10px; } \
                #{{ config.elemId }} .bf-brand img { max-width: 120px; max-height: 60px; border: none; } \
                #{{ config.elemId }} .bf-person-box { width: 80px; float: left; } \
                #{{ config.elemId }} .bf-person-box a img { height: 65px; width: 65px; border: solid 1px #ccc; -moz-border-radius: 4px; margin: 0; padding: 0; } \
                #{{ config.elemId }} .bf-thread-container { border: solid 1px #ddd; padding: 15px; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; margin-bottom: 20px; } \
                #{{ config.elemId }} .bf-thread { min-height: 65px; } \
                #{{ config.elemId }} .bf-thread .bf-post-meta { margin-bottom: 10px; font-size: 75%; min-height: 65px; width: 40%; float: right; text-align: right; } \
                #{{ config.elemId }} .bf-thread .bf-person-box { width: 65px; float: right; margin-left: 7px; } \
                #{{ config.elemId }} .bf-thread-content { padding-left: 80px; font-size: 13px; min-height: 90px; margin-bottom: 10px; } \
                #{{ config.elemId }} .bf-edit { font-size: 11px; font-weight: normal; line-height: 12px; } \
                #{{ config.elemId }} .bf-edit a { text-decoration: none; display: block; } \
                #{{ config.elemId }} .bf-edit a:hover { text-decoration: underline; } \
                #{{ config.elemId }} .bf-post-meta { padding: 0; margin-bottom: 5px; text-align: left; } \
                #{{ config.elemId }} .bf-post-meta h4 { font-size: 13px; margin: 0 0 3px 0; display: inline; } \
                #{{ config.elemId }} .bf-post-meta span { font-size: 11px; float: right; } \
                #{{ config.elemId }} .bf-thread .bf-post-meta span { width: 60%; } \
                #{{ config.elemId }} .bf-reply-sharing { position: absolute; bottom: 2px; right: 7px; font-size: 12px; width: 182px; text-align: right; padding: 4px 3px 1px 3px; } \
                #{{ config.elemId }} .bf-reply-sharing a { text-decoration: none; font-size: 11px; } \
                #{{ config.elemId }} .bf-reply-sharing a:hover { text-decoration: underline; } \
                #{{ config.elemId }} .bf-reply-sharing > span { font-weight: bold; margin-right: 1px; font-size: 11.5px; } \
                #{{ config.elemId }} .bf-reply-sharing sup { vertical-align: baseline; padding: 3px 0 3px 20px; display: inline; line-height: 16px; margin-left: 8px; background: transparent url({{ config.staticHost }}/images/design2011/embed/embedded-buttons.png) no-repeat; } \
                #{{ config.elemId }} .bf-reply-sharing sup.facebook { background-position: -118px -71px; } \
                #{{ config.elemId }} .bf-reply-sharing sup.twitter { background-position: -118px -91px; } \
                #{{ config.elemId }} .bf-action { border: solid 1px #ddd; padding: 0 15px; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; margin-bottom: 20px; background: transparent url({{ config.staticHost }}/images/design2011/embed/embedded-backgrounds.png) repeat-x 0 -42px; } \
                #{{ config.elemId }} .bf-action iframe { border: none; width: 100%; height: 176px; margin-left: auto; margin-right: auto; background-color: transparent; } \
                #{{ config.elemId }} .bf-action small { font-size: 11px; display: block; margin-top: -8px; z-index: 2; line-height: 13px; font-weight: normal; text-transform: none; padding-bottom: 10px; color: #848484; } \
                #{{ config.elemId }} .bf-info { margin-bottom: 7px; min-height: 18px; } \
                #{{ config.elemId }} .bf-count { font-size: 12px; font-weight: bold; } \
                #{{ config.elemId }} .bf-count-lower { font-size: 11px; font-weight: bold; } \
                #{{ config.elemId }} p { margin: 0 0 8px 0; } \
                #{{ config.elemId }} div.bf-quoted { width:85%; min-height:40px; padding-left:50px } \
                #{{ config.elemId }} .bf-quotedarea { position:relative; padding-top:7px; padding-bottom:7px; padding-right:15px; margin-bottom:15px; margin-top:10px } \
                #{{ config.elemId }} .bf-quotedarea div.icon { width:37px; height:37px; overflow:hidden; float:left } \
                #{{ config.elemId }} .bf-quotedarea div.icon img { width:100% } \
                #{{ config.elemId }} .bf-quotedarea div.comment { margin-left:45px; z-index:2 } \
                #{{ config.elemId }} .bf-quotedarea ol, .bf-quotedarea ul { width: 250px } \
                #{{ config.elemId }} span.quotemark { font-size:50px; font-style: italic } \
                #{{ config.elemId }} span.lquote { position:absolute; top:0; left:0 } \
                #{{ config.elemId }} span.rquote { font-size:80px; z-index:0; position:absolute; bottom:10px; right:20px; height:15px } \
                #{{ config.elemId }} .bf-continue { text-align: left; } \
                #{{ config.elemId }} .bf-widget-footer a { margin-right: 10px; } \
                #{{ config.elemId }} #bf-powered-by { display: block; width: 104px; height: 15px; background: Transparent url({{ config.staticHost }}/images/design2011/embed/embedded-buttons.png) no-repeat -8px -72px; float: right; text-indent: -9999px; } \
                #{{ config.elemId }} a.expand { font-size: 11px; } \
                #{{ config.elemId }} a.minor-action { font-weight: bold; font-size: 95%; } \
                #{{ config.elemId }} a.edit { position: absolute; top: 0; right: 0; font-size: 12px; } \
                #{{ config.elemId }} a.bf-button { display: inline-block; position: relative; padding: 5px 15px 5px 20px; height: 24px; background: url("{{ config.staticHost }}/images/design2011/button-sprite.png") no-repeat left -66px; cursor: pointer; text-align: center; color: #777 !important; font-weight: bold; font-size: 13px; line-height: 25px; text-decoration: none !important; text-shadow: 1px 1px 2px #fff; } \
                #{{ config.elemId }} a.bf-button:hover { background-position: left -99px; } \
                #{{ config.elemId }} a.bf-button > em { display: block; position: absolute; width: 5px; height: 100%; top: 0; right: 0; margin-right: -5px; background: url("{{ config.staticHost }}/images/design2011/button-sprite.png") no-repeat right -66px; } \
                #{{ config.elemId }} a.bf-button > span { margin-top: 3px; display: inline-block; line-height: normal; } \
                #{{ config.elemId }} a.bf-button:hover > em { background-position: right -99px; } \
                #{{ config.elemId }} a.bf-button sup { margin-right: 5px; line-height: 16px; } \
                #{{ config.elemId }} a.bf-button sup.text { margin-top: 4px; font-size: 14px; font-weight: bold; } \
                #{{ config.elemId }} img.bf-attached-image, #{{ config.elemId }} img.uploadedimage:first-child { float: right; margin-left: 10px !important; display: block; max-height: 55px; max-width: 100px; cursor: pointer; } \
                #{{ config.elemId }} .usergenerated { overflow: hidden; text-align: left; } \
                #{{ config.elemId }} .clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } \
                #{{ config.elemId }} .clearfix { display: inline-block; } \
                #{{ config.elemId }} * html .clearfix { height: 1%; } \
                #{{ config.elemId }} .clearfix { display: block; } \
                ';

            // THIS DOESNT SEEM TO BE WORKING RIGHT?
            this.templates.IE7CSS = ' \
                #{{ config.elemId }} .bf-action small { margin-top: 0 !important; } \
                #{{ config.elemId }} .bf-thread-content { padding-left: 0px !important; } \
                ';

        };

    } ($bf.widgets.EmbeddedDiscussion.prototype));

})(window.$bf.v2);
/// <reference path="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.4.4-vsdoc.js" />
/// <reference path="/widgets/v2/widget-core.js" />
/*global $bf: true, blogfrog: true, log: true, $: false, jQuery: false */

(function($bf) {

    $bf.widgets.EmbeddedConversation = function () { };
    $bf.widgets.EmbeddedConversation.prototype = new $bf.widgets.EmbeddedDiscussion();
    $bf.widgets.EmbeddedConversation.prototype.constructor = $bf.widgets.EmbeddedConversation;

    (function (widget, parent) {

        // init
        widget.init = function(_config) {
        
            // Setup sponcon defaults
            _config = $bf.extend({
                extraActionMsg: '',
                newestFirst: true,
                replyShareUrl: '{{ state.data.sponsored.hubpageurl }}?replyid={{ reply.id }}',
                sortBy: 'id',
                sortOrder: 'desc',
                showThread: false,
                showReplyBox: true,
                showReplySharing: true,
                successPopup: '',
                successPopupBtn: '',
                iframeUrl: '{{ config.iframeHost }}/{{ discussion.communityid }}/embedded-reply?threadid={{ discussion.id }}&inviteid={{ config.inviteId }}&iframe-height=400&buttonfontfamily={{ config.buttonFontFamily:escape }}&widgethost={{ config.widgetHost:escape }}&unitname={{ config.unitName:escape }}&widgetid={{ config.elemId }}&popup={{ config.successPopup:escape }}&popupbtn={{ config.successPopupBtn:escape }}&allowAttachments={{ config.allowAttachments }}&twitterhash={{ config.twitterHash:escape }}',
                url: '/v1/discussion/sponsored/{{ config.inviteId }}/replies'
            },_config);

            // Merge back with widget config
            this.config = $bf.extend(this.config, _config);

            // Invoke base
            parent.init.apply(this, [_config]);

            // Update differences
            this.description = 'Conversation';
        };
    
        // render
        widget.render = function(data) {
        
            // Check for conversation-specific error messages
            if (!data.sponsored.found) { 
                // Conversation not found
                this.renderError('The embedded widget has loaded properly, but the sponsored conversation was not found.');
                return;
            } else if (!data.sponsored.invitation.ispublished && !data.sponsoredinvite.isscheduled) {
                // Not yet scheduled
                this.renderError('The embedded widget has loaded properly, but the conversation for this blog is not available.');
                return;
            } else if (!data.sponsored.invitation.ispublished) {
                // Not yet published
                var date = new Date(parseInt(data.sponsored.invitation.scheduleddate.substr(6)));
                this.renderError('This conversation is scheduled to post on ' + date.toLocaleDateString() + ' at ' + date.toLocaleTimeString() + '.');
                return;
            }

            // If no errors pass control back to the base method
            parent.render.apply(this, [data]);
        };

        // showPostedResponse
        widget.showPostedResponse = function(response) {
            var replies = this.baseTag.find('.bf-replies');
            replies.prepend(response);
            response.slideDown();
        };

        // renderError
        widget.renderError = function(text) {
            $bf(this).onjQueryDomReady(function($) {
                var html = '<p>' + text + '</p>';
                this.baseTag = $('#' + this.config.elemId);
                this.baseTag.html(html);
            });
        };

        // onResponsePosted
        widget.onResponsePosted = function(json) {
            var $ = $bf.jQuery;

            // Invoke normal code path
            parent.onResponsePosted.apply(this, [json]);

            // Then show the facebox of the popup
            if (typeof(this.config.successPopup) !== 'undefined' && this.config.successPopup.length > 0) {
                $bf(this).onjQueryReady(function($) {
                    var popup = this.config.successPopup;
                    if (popup.indexOf('<') > -1) {
                        $.facebox('<div style="height: 425px; width: 550px;">' + popup + '</div>');
                    } else {
                        $.facebox('<iframe src="' + popup + '" width="550" height="425" frameborder="0" />');
                    }
                });
            }
        };

        // defineTemplates
        widget.defineTemplates = function() {
            parent.defineTemplates.call(this);

            this.templates.widgetBase = ' \
                {{{ if threadbody }}} \
                    <div class="bf-thread-container" data-bf-type="threadbody">{{ threadbody }}</div> \
                {{{ end }}} \
                {{{ if config.showReplyBox }}} \
                    <div class="bf-action bf-reply-action" style="margin-top:25px;"> \
                        <div class="bf-brand"> \
                            <a title="Sponsored by {{ sponsored.companyname }}" href="{{ sponsored.hubpageurl }}"> \
                                <img src="{{ sponsored.companyimage }}" /> \
                            </a> \
                        </div> \
                        <h3>{{ config.callToAction }}</h3> \
                        {{{ if config.extraActionMsg }}} \
                            <div class="bf-extra-msg"> \
                                {{ config.extraActionMsg }} \
                            </div> \
                        {{{ end }}} \
                        <iframe data-function="reply-iframe" scrolling="no" frameborder="0"></iframe> \
                        <small>{{ sponsored.replydisclaimer }}</small> \
                    </div> \
                {{{ end }}} \
                <div class="bf-info"> \
                    <a id="bf-powered-by" href="http://theblogfrog.com?utm_source=blog&utm_medium=embedded_discussion" title="Powered by BlogFrog: We turn blogs into communities">Powered by</a> \
                    <span class="bf-count"></span> \
                </div> \
                <div class="bf-replies"></div> \
                <div class="bf-widget-footer" style="margin: 10px 0; line-height: 35px;"> \
                    <div class="bf-continue"> \
                        <a class="bf-button more-replies" href="#ShowMoreReplies">Show More &#9662;</a> \
                        {{{ if config.showDiscussionLink }}} \
                            <a class="bf-button hubpage" href="{{ sponsored.hubpageurl:requirehttp }}?utm_medium=embedded_discussion&utm_content=hubpage">See {{ config.unitNamePlural }} from Other Blogs &#9656;<em></em></a> \
                        {{{ end }}} \
                    </div> \
                    <div> \
                        <span class="bf-count-lower"></span> \
                    </div> \
                    {{{ if !config.showReplyBox }}} \
                        <a class="minor-action reply" style="width:190px;" href="{{ thread.url }}?utm_medium=embedded_discussion&utm_content=reply">Reply to Conversation &#8594; <em></em></a> \
                    {{{ end }}} \
                </div>';

            this.templates.requiredCSS += ' \
                #{{ config.elemId }} .bf-brand { padding: 2px 6px; border: solid 1px #eee; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; background-color: #fff; } \
            ';
        };

    }($bf.widgets.EmbeddedConversation.prototype, $bf.widgets.EmbeddedDiscussion.prototype));

})(window.$bf.v2);

(function($bf) {
    $bf(new $bf.widgets.EmbeddedConversation()).run({
        callToAction: "What advice do you have for moms prepping for pre-school?",
        extraActionMsg: 'The random winner has been selected, but feel free to keep sharing your advice for prepping for preschool!',
        inviteId: 753,
        linkBase: 'http://theblogfrog.com/1505348',
        replies: 10,
        unitName: 'Response',
        unitNamePlural: 'Responses',
        customCSS: ''
    });
})(window.$bf.v2 || window.$bf);