swf-debug.js revision fc2967b5bbf7bb08d68bd05189ba521717c31749
b32d148b0052e1f874e9bc9803bef729bf859d97Luke SmithYUI.add('swf', function(Y) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith/**
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * Embed a Flash applications in a standard manner and communicate with it
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * via External Interface.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @module swf
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith */
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith var Event = Y.Event,
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith SWFDetect = Y.SWFDetect,
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith Lang = Y.Lang,
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith uA = Y.UA,
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith Node = Y.Node,
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith // private
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith FLASH_CID = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000",
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith FLASH_TYPE = "application/x-shockwave-flash",
d463aba91a07cde67f9ec9382bce464db5bcc9d3Luke Smith FLASH_VER = "10.0.22",
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith EXPRESS_INSTALL_URL = "http://fpdownload.macromedia.com/pub/flashplayer/update/current/swf/autoUpdater.swf?" + Math.random(),
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith EVENT_HANDLER = "SWF.eventHandler",
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith possibleAttributes = {align:"", allowFullScreen:"", allowNetworking:"", allowScriptAccess:"", base:"", bgcolor:"", menu:"", name:"", quality:"", salign:"", scale:"", tabindex:"", wmode:""};
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith /**
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith * The SWF utility is a tool for embedding Flash applications in HTMl pages.
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith * @module swf
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith * @title SWF Utility
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith * @requires yahoo, dom, event
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @namespace YAHOO.widget
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith */
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith /**
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith * Creates the SWF instance and keeps the configuration data
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith *
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith * @class SWF
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith * @augments Y.Event.Target
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith * @constructor
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @param {String|HTMLElement} id The id of the element, or the element itself that the SWF will be inserted into.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * The width and height of the SWF will be set to the width and height of this container element.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @param {String} swfURL The URL of the SWF to be embedded into the page.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @param {Object} p_oAttributes (optional) Configuration parameters for the Flash application and values for Flashvars
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith * to be passed to the SWF.
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith */
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smithfunction SWF (p_oElement /*:String*/, swfURL /*:String*/, p_oAttributes /*:Object*/ ) {
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith this._id = Y.guid("yuiswf");
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith var _id = this._id;
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith var oElement = Node.one(p_oElement);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith var flashVersion = p_oAttributes["version"] || FLASH_VER;
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith var flashVersionSplit = (flashVersion + '').split(".");
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith var isFlashVersionRight = SWFDetect.isFlashVersionAtLeast(parseInt(flashVersionSplit[0]), parseInt(flashVersionSplit[1]), parseInt(flashVersionSplit[2]));
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith var canExpressInstall = (SWFDetect.isFlashVersionAtLeast(8,0,0));
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith var shouldExpressInstall = canExpressInstall && !isFlashVersionRight && p_oAttributes["useExpressInstall"];
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith var flashURL = (shouldExpressInstall)?EXPRESS_INSTALL_URL:swfURL;
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith var objstring = '<object ';
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith var w, h;
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith var flashvarstring = "yId=" + Y.id + "&YUISwfId=" + _id + "&YUIBridgeCallback=" + EVENT_HANDLER;
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith Y.SWF._instances[_id] = this;
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith if (oElement && (isFlashVersionRight || shouldExpressInstall) && flashURL) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith objstring += 'id="' + _id + '" ';
9327ef7ad1fee11b0e494b97cc07386565326c03Luke Smith if (uA.ie) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith objstring += 'classid="' + FLASH_CID + '" ';
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith else {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith objstring += 'type="' + FLASH_TYPE + '" data="' + flashURL + '" ';
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith w = "100%";
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith h = "100%";
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith objstring += 'width="' + w + '" height="' + h + '">';
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (uA.ie) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith objstring += '<param name="movie" value="' + flashURL + '"/>';
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith for (var attribute in p_oAttributes.fixedAttributes) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (possibleAttributes.hasOwnProperty(attribute)) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith objstring += '<param name="' + attribute + '" value="' + p_oAttributes.fixedAttributes[attribute] + '"/>';
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith for (var flashvar in p_oAttributes.flashVars) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith var fvar = p_oAttributes.flashVars[flashvar];
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (Lang.isString(fvar)) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith flashvarstring += "&" + flashvar + "=" + encodeURIComponent(fvar);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (flashvarstring) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith objstring += '<param name="flashVars" value="' + flashvarstring + '"/>';
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith objstring += "</object>";
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith oElement.setContent(objstring);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
8652e2d20f8ea9c9bfe21217ba427cf0d85ada9aLuke Smith this._swf = Node.one("#" + _id);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith};
8652e2d20f8ea9c9bfe21217ba427cf0d85ada9aLuke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith/**
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * The static collection of all instances of the SWFs on the page.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @property _instances
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @private
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @type Object
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith */
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
8652e2d20f8ea9c9bfe21217ba427cf0d85ada9aLuke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke SmithSWF._instances = SWF._instances || {};
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
8652e2d20f8ea9c9bfe21217ba427cf0d85ada9aLuke Smith/**
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * Handles an event coming from within the SWF and delegate it
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * to a specific instance of SWF.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @method eventHandler
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @param swfid {String} the id of the SWF dispatching the event
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @param event {Object} the event being transmitted.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @private
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith */
8652e2d20f8ea9c9bfe21217ba427cf0d85ada9aLuke SmithSWF.eventHandler = function (swfid, event) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith SWF._instances[swfid]._eventHandler(event);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith};
8652e2d20f8ea9c9bfe21217ba427cf0d85ada9aLuke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke SmithSWF.prototype =
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith{
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith /**
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @private
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * Propagates a specific event from Flash to JS.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @method _eventHandler
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @param event {Object} The event to be propagated from Flash.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith */
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith _eventHandler: function(event)
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (event.type == "swfReady")
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith this.publish("swfReady", {fireOnce:true});
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith this.fire("swfReady", event);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith else if(event.type == "log")
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith Y.log(event.message, event.category, this.toString());
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith else
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith this.fire(event.type, event);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith },
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith /**
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * Calls a specific function exposed by the SWF's
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * ExternalInterface.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @method callSWF
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @param func {String} the name of the function to call
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @param args {Object} the set of arguments to pass to the function.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith */
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith callSWF: function (func, args)
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (!args) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith args= [];
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith };
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (this._swf._node[func]) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith return(this._swf._node[func].apply(this._swf._node, args));
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith } else {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith return null;
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith },
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith createInstance: function (instanceId, className, args) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (!args) {args = []};
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (this._swf._node["createInstance"]) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith this._swf._node.createInstance(instanceId, className, args);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith },
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith applyMethod: function (instanceId, methodName, args) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (!args) {args = []};
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (this._swf._node["applyMethod"]) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith this._swf._node.applyMethod(instanceId, methodName, args);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith },
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith exposeMethod: function (instanceId, methodName, exposedName) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (this._swf._node["exposeMethod"]) {
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith this._swf._node.exposeMethod(instanceId, methodName, exposedName);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith },
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith getProperty: function (instanceId, propertyName) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (this._swf._node["getProperty"]) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith this._swf._node.getProperty(instanceId, propertyName);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith },
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith setProperty: function (instanceId, propertyName, propertyValue) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if (this._swf._node["setProperty"]) {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith this._swf._node.setProperty(instanceId, propertyName, propertyValue);
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith },
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith onFlash: function(type, instance)
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith var id = instance.get("id");
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith if(!SWF._instances.hasOwnProperty(id))
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith SWF._instances[id] = instance;
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith if(this._swf._node["subscribe"])
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith {
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith this._swf._node.subscribe(type, id);
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith }
ed51daad3a3ab15255ca10edef69d5f703d69adbLuke Smith },
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith /**
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * Public accessor to the unique name of the SWF instance.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith *
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @method toString
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith * @return {String} Unique name of the SWF instance.
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith */
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith toString: function()
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith {
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith return "SWF " + this._id;
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith }
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith};
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith//
b32d148b0052e1f874e9bc9803bef729bf859d97Luke SmithY.augment(SWF, Y.EventTarget);
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke SmithY.SWF = SWF;
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith}, '@VERSION@' );
b32d148b0052e1f874e9bc9803bef729bf859d97Luke Smith