var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; /// <reference path="../../util/BaseContext.ts"/> /// <reference path="../history/VisitorHistory.ts" /> /// <reference path="../../data.ts" /> /// <reference path="../../debug.ts" /> /// <reference path="IContextConfigOptions.ts" /> /// <reference path="IProductReferenceConfigOptions.ts" /> /// <reference path="ProductReference.ts" /> /// <reference path="CategoryReference.ts" /> var econda; (function (econda) { var recengine; (function (recengine) { var context; (function (context) { var CategoryReference = econda.recengine.context.CategoryReference; var ProductReference = econda.recengine.context.ProductReference; var VisitorHistory = econda.recengine.history.VisitorHistory; /** * Request context, e.g. the product we want to get recommendations for. * @class econda.recengine.context.Context * @extends econda.base.BaseClass * * <h3>Setting the Context of a Widget or Request</h3> * <p>Examples are <strong>incomplete</strong> and will not work without additional configuration. All the following examples are identical.</p> * * <h4>Just pass the context configuration to the widget</h4> * <p>This is the preferred way.</p> * var widget = new econda.recengine.Widget({ * ... * context: { * products: [{id: 'prodId1'}, {id: 'prodId2'}], * } * }); * * * <h4>Use context object in widget configuration</h4> * var widget = new econda.recengine.Widget({ * ... * context: new econda.recengine.Context({ * products: [{id: 'prodId1'}, {id: 'prodId2'}], * }) * }); * * <h4>Create context object first</h4> * var context = new econda.recengine.Context({ * products: {id: 'prodId1'} * }); * context.addProducts({id: 'prodId2'}); * var widget = new econda.recengine.Widget({ * context: context * }); * * <h3>Example Context Configurations</h3> * <p>Examples are <strong>incomplete</strong> and will not work without additional configuration.</p> * * <h4>Widget on Product Detail Pages: "other customers bought..."</h4> * var widget = new econda.recengine.Widget({ * ... * id: 6, * context: { * products: {id: 'article number of product'}, * } * }); * * <h4>Widget on Category Page: "top sellers in this category"</h4> * var widget = new econda.recengine.Widget({ * ... * id: 7, * context: { * categories: { * type: "productcategory", * path: "T-Shirts" * }, * } * }); * * <h4>Widget on Checkout Pages</h4> * var widget = new econda.recengine.Widget({ * ... * id: 8, * context: { * products: ['prodIdInCart1', 'prodIdInCart2', 'prodIdInCart3'], * } * }); */ var Context = (function (_super) { __extends(Context, _super); function Context(cfg) { _super.call(this); /** * List of product references in context * @cfg {econda.recengine.context.ProductReference[]} products * @accessor */ this.products = []; this.visitorHistory = null; /** * List of categories in context * @cfg {econda.recengine.context.CategoryReference[]} categories * @accessor */ this.categories = []; /** * Context attributes * var ctx = new econda.recengine.context.Context({ * attributes: { * myattribute: "myvalue" * } * }); * * @cfg {Object} attributes * @accessor */ this.attributes = {}; /** * @cfg {econda.recengine.context.ProductReference[]} productsExcluded * Products to exclude from response. This items will be passed to cross sell server. Limits will work correctly. */ this.productsExcluded = []; /** * True to auto append visitor data from current visitor profile * @cfg {Boolean} appendVisitorData */ this._appendVisitorData = null; var cfg = cfg || {}; if (cfg instanceof Context) { return cfg; } else { if (typeof cfg['appendVisitorData'] != 'undefined') { this._appendVisitorData = cfg['appendVisitorData'] === true; delete cfg['appendVisitorData']; } this.initConfig(cfg); } if (this._appendVisitorData === true || this._appendVisitorData === null && (typeof econdaConfig.crosssellAppendVisitorData === 'undefined' || econdaConfig.crosssellAppendVisitorData === true)) { this._doAppendVisitorData(); } } Context.prototype.getProducts = function () { return this.products; }; Context.prototype.setProducts = function (products) { this.products = []; this.addProducts(products); return this; }; /** * adds a list of products to context * @method * @param {Object[]/econda.recengine.context.ProductReference[]} products */ Context.prototype.addProducts = function (products) { return this.addArray('products', products, ProductReference, { itemFilter: this._productReferenceInputFilter }); }; /** * Adds a single product * @method * @param {Object} product * @chainable */ Context.prototype.addProduct = function (product) { return this.addProducts(product); }; Context.prototype.getVisitorHistory = function () { return this.visitorHistory; }; Context.prototype.setVisitorHistory = function (visitorHistory) { this.visitorHistory = new VisitorHistory(visitorHistory); }; Context.prototype.getCategories = function () { return this.categories; }; /** * Set multiple categories references * * // set one or multiple category references * context.setCategories([{ type: 'brand', path: 'econda' }, { type: 'productcategory', path: 'accessories'}]); * * @param {econda.recengine.context.CategoryReference[]} categories */ Context.prototype.setCategories = function (categories) { return this.setArray('categories', categories, CategoryReference); }; /** * Add multiple category references * * // add one or multiple category references * context.addCategories([{ type: 'brand', path: 'econda' }, { type: 'productcategory', path: 'accessories'}]); * * @param {econda.recengine.context.CategoryReference[]} categories */ Context.prototype.addCategories = function (categories) { return this.addArray('categories', categories, CategoryReference); }; /** * Adds a single category reference * * // add one category reference * context.addCategory({ type: 'brand', path: 'econda' }); * * @param {econda.recengine.context.CategoryReference} category */ Context.prototype.addCategory = function (category) { return this.addCategories(category); }; Context.prototype.getAttributes = function () { return this.attributes; }; Context.prototype.setAttributes = function (attributes, value) { if (value === void 0) { value = null; } this.attributes = {}; return this.addAttributes(attributes, value); }; /** * Add attributes to context * * // add one or multiple attributes * context.addAttributes({ myattr: "myvalue"}); * * // add single attribute * context.addAttributes('myattr', 'myvalue'); * * @param {String/Object} attributes * @param {String/Number} value */ Context.prototype.addAttributes = function (attributes, value) { if (value === void 0) { value = null; } if (typeof attributes == 'string') { this.attributes[attributes] = value; } else { for (var property in attributes) { this.attributes[property] = attributes[property]; } } return this; }; Context.prototype.getProductsExcluded = function () { return this.productsExcluded; }; Context.prototype.setProductsExcluded = function (products) { return this.setArray('productsExcluded', products, ProductReference, { itemFilter: this._productReferenceInputFilter }); }; Context.prototype.addProductsExcluded = function (products) { return this.addArray('productsExcluded', products, ProductReference, { itemFilter: this._productReferenceInputFilter }); }; Context.prototype._productReferenceInputFilter = function (product) { if (product instanceof ProductReference) { return product; } else { return { id: product.id || null, sku: product.sku || null }; } }; Context.prototype.addToRequest = function (params) { var categories = this.getCategories(); if (categories.length > 0) { for (var i = 0; i < categories.length; i++) { var cat = categories[i]; var prefix = 'ctxcat'; if (i > 0) { prefix = prefix + i; } var typeParam = prefix + '.ct'; params[typeParam] = cat.getType(); if (cat.getId()) { var byIdParam = prefix + '.cid'; params[byIdParam] = cat.getId(); } if (cat.getPath()) { var pathAsArrayParam = prefix + '.paa'; params[pathAsArrayParam] = cat.getPath(); } if (cat.getVariant()) { var variantParam = prefix + '.pv'; params[variantParam] = cat.getVariant(); } } } // handle custom attributes var attributes = this.getAttributes(); for (var name in attributes) { switch (attributes[name]) { case null: params['ctxcustom.' + name] = ''; break; default: params['ctxcustom.' + name] = '' + attributes[name]; } } _super.prototype.addToRequest.call(this, params); }; Context.prototype._doAppendVisitorData = function () { try { var visitorProfile = econda.data.visitor; this.setVisitorId(visitorProfile.getVisitorId()); this.setSessionId(visitorProfile.getSessionId()); this.setCustomerId(visitorProfile.getCustomerId()); this.setUserId(visitorProfile.getUserId()); this.setRecipientId(visitorProfile.getRecipientId()); this.setEmail(visitorProfile.getEmail()); this.setEmailHash(visitorProfile.getEmailHash()); this.setProfileProperties(visitorProfile.getProperties()); this.setVisitorHistory(visitorProfile.getHistory()); } catch (e) { econda.debug.error('Could not append visitor profile data to cross sell request due to an internal exception: ' + e); } }; return Context; }(econda.base.BaseContext)); context.Context = Context; // end of class })(context = recengine.context || (recengine.context = {})); })(recengine = econda.recengine || (econda.recengine = {})); })(econda || (econda = {})); // end of module