Skip to content

Instantly share code, notes, and snippets.

@draeton
Created April 12, 2013 18:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save draeton/4285da1f539cc00d7eed to your computer and use it in GitHub Desktop.
Save draeton/4285da1f539cc00d7eed to your computer and use it in GitHub Desktop.
Ford » My Saved Items code sample
/*global jQuery,ngbs,NextGen,MySavedItems*/
/**
* MySavedItems.Data
*
* Copyright (c) 2012, Team Detroit
* All rights reserved
*
* @desc Retrieves and process the My Saved Items data
* @dependencies jQuery + .views, .render, .observable
*/
(function (window, $, ngbs, NextGen, MySavedItems) {
"use strict";
var console = window.console || {
log: function () {}
};
$.extend(MySavedItems.Events, {
"DATA_REQUEST_START": "DATA_REQUEST_START",
"DATA_AXZ_ERROR": "DATA_AXZ_ERROR"
});
var NAMESPACE = ".MSIDATA";
/* shortcuts */
var $MSI = $(MySavedItems);
var E = MySavedItems.Events;
var P = MySavedItems.Page;
var NG = NextGen;
var $NG = $(NG);
var NGAW = NG.AuthenticationWidget;
var NGSAPI = NG.SaveAPI;
/**
* MySavedItems Data module
*/
var D = MySavedItems.Data = (function () {
/* public interface */
return {
/**
* init
*
* Sets up the element for rendering
*
* @param {jQuery} selector References the element where view is created
*/
init: function ($element, options) {
var $widget = $("#nextgen_auth_save_widget_container");
var baseURL = $widget.data("baseUrl");
var make = $widget.data("make");
NextGen.init({
baseURL: baseURL,
make: make
});
/* bind handlers */
D._unbindHandlers();
D._bindHandlers();
/* trigger data retrieval */
D._requestSavedItems();
},
/**
* _unbindHandlers
*/
_unbindHandlers: function () {
$MSI.unbind(NAMESPACE);
$NG.unbind(NAMESPACE);
},
/**
* _bindHandlers
*
* Bind handlers to msi data events
*/
_bindHandlers: function () {
$MSI.bind(E.DATA_REQUEST_START + NAMESPACE, D._requestSavedItems);
$MSI.bind(E.DATA_AXZ_ERROR + NAMESPACE, P._axzAuthFlip);
$NG.bind(NG.events.AUTHENTICATION_COMPLETE_EVENT + NAMESPACE, D._requestSavedItems);
$NG.bind(NG.events.AUTHENTICATION_LOGOUT_EVENT + NAMESPACE, D._requestSavedItems);
},
/**
* _requestSavedItems
*
* Request data from API
*
* @param {Object} e jQuery event
*/
_requestSavedItems: function (e) {
var success = D._requestSavedItemsSuccess;
var error = D._requestSavedItemsError;
MySavedItems.init();
$MSI.trigger(E.PAGE_RENDER_RESET);
if (NGAW.userId !== null) {
NGSAPI.getSavedItems(success, error);
} else {
D._requestSavedItemsError();
}
},
/**
* _requestSavedItemsSuccess
*
* Handles the JSON response data
*
* @param {Object} data
*/
_requestSavedItemsSuccess: function (data, status, jqXHR) {
var response = data.Response;
if (response && response.status === "OK") {
D._processSavedItems(response.SavedItems);
} else {
$MSI.trigger(E.PAGE_RENDER_START);
}
},
/**
* _requestSavedItemsError
*
* Handles AJAX error
*/
_requestSavedItemsError: function () {
D.__processed = {
total: 0,
userID: NGAW.userId,
provider: NGAW.provider
};
$MSI.trigger(E.PAGE_RENDER_START, D.__processed);
},
/**
* _processSavedItems
*
* Pre-process saved items JSON in preparation for templates
* @param {Object} data API JSON data
*/
_processSavedItems: function (data) {
/* set up buckets */
D.__items = [];
D.__models = {};
D.__vehicles = [];
D.__vehiclesUpdates = [];
D.__vehiclesUpdatesArray = [];
D.__technology = [];
D.__recent = null;
D.__totalVehicles = 0;
/* set axz plan type before processing */
D.planType = D._getPlanType();
/* parse out the data nodes into lists by data type */
D.__lists = {
cpo: data.CPOVehicles && data.CPOVehicles.CPOVehicle,
config: data.ConfigVehicles && data.ConfigVehicles.ConfigVehicle,
inventory: data.InventoryVehicles && data.InventoryVehicles.InventoryVehicle,
compare: data.VehicleCompareItems && data.VehicleCompareItems.VehicleCompare,
gallery: data.BrandContents && data.BrandContents.BrandContent
};
/* begin processing */
$.each(D.__lists, D._sortDataTypeListsIntoItems);
$.each(D.__items, D._formatDate);
/* sort and set recent */
D.__items = D.__items.sort(function (a, b) {
return a.CreationDateFull === b.CreationDateFull ? 0 : a.CreationDateFull > b.CreationDateFull ? -1 : 1;
});
D.__recent = D.__items[0];
/* continue processing */
$.each(D.__items, D._setItemDisplayPricing);
/* processing data for Get Updates Flip */
D.__vehiclesUpdates = D.__items.sort(function (a, b) {
return a.Year === b.Year ? 0 : a.Year > b.Year ? -1 : 1;
});
$.each(D.__vehiclesUpdates, D._sortModelsIntoArrayForUpdates);
$.each(D.__items, D._sortItemsIntoArraysByModel);
/* if there are no vehicles, create an empty vehicle */
if (!D.__totalVehicles) {
D.__models.empty = {
cpo: [],
config: [],
inventory: [],
compare: [],
gallery: []
};
}
$.each(D.__models, D._sortModelsIntoArraysByVehicle);
/* alpha sort vehicles for display */
D.__vehicles = D.__vehicles.sort(function (a, b) {
return a.model === b.model ? 0 : a.model < b.model ? -1 : 1;
});
/* returned object */
D.__processed = {
recent: D.__recent,
vehicles: D.__vehicles,
technology: D.__technology,
firstVehicle: D.__vehicles[0],
totalVehicles: D.__totalVehicles,
total: D.__items.length,
userID: NGAW.userId,
provider: NGAW.provider
};
/* trigger rendering */
$MSI.trigger(E.PAGE_RENDER_START, D.__processed);
},
/**
* _sortDataTypeListsIntoItems
*
* Push items into a single items array while adding properties
*/
_sortDataTypeListsIntoItems: function (dataType, list) {
/* convert single objects to an array */
list = $.isPlainObject(list) ? [list] : list;
$.each(list, function (index, item) {
item.dataType = dataType;
/* skip these keys when decoding */
var skip = ["Pricing", "CreationDate", "PivotVehicle", "CompetitorVehicles"];
/* decode values */
$.each(item, function (key, value) {
if ($.inArray(key, skip) === -1) {
item[key] = decodeURIComponent(value);
}
});
/* remove old title from description */
if (item.Description) {
/*jslint regexp:true*/
/*item.Description = item.Description.replace(/^.+\|\|/, "");*/
item.Description = item.Description.split("||");
item.OriginalTitle = item.Description[0];
item.Description = item.Description[1];
}
/* add to items array */
D.__items.push(item);
});
},
/**
* _formatDate
*/
_formatDate: (function () {
var dateRegex = /(\d{4})-(\d{1,2})-(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2}) (\w{2})/;
var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
var formatDate = function (d) {
return months[d.getMonth()] + " " + d.getDate() + ", " + d.getFullYear();
};
// e.g. 2012-2-23 5:2 AM
return function (index, item) {
var parts;
var meridian;
var dateTime;
if (!item.CreationDateFull) {
parts = item.CreationDate.match(dateRegex);
meridian = parts[7];
if (meridian === "PM") {
parts[4] = +parts[4] + 12;
}
dateTime = new Date(parts[1], parts[2] - 1, parts[3], parts[4], parts[5], parts[6]);
item.CreationDate = formatDate(dateTime);
item.CreationDateFull = dateTime;
}
};
}()),
/**
* _setItemDisplayPricing
*
* Select the correct pricing to display based on plan type
*/
_setItemDisplayPricing: (function () {
/* see: http://stackoverflow.com/a/149099 */
var formatMoney = function (n, c, d, t) {
var s, i, j;
c = Math.abs(c);
c = isNaN(c) ? 2 : c;
d = typeof d === "undefined" ? "." : d;
t = typeof t === "undefined" ? "," : t;
s = n < 0 ? "-" : "";
n = Math.abs(+n || 0).toFixed(c);
i = parseInt(n, 10).toString();
j = i.length;
j = (j) > 3 ? j % 3 : 0;
return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};
return function (index, item) {
var flagged = false;
if (item.Pricing) {
/* format prices as currency */
$.each(item.Pricing, function (index, price) {
item.Pricing[index] = formatMoney(price, 0);
});
/* set default plan type */
if (!item.PlanType) {
item.PlanType = "MSRP";
}
/* AXZ: check that user can view data */
if (item.PlanType !== "MSRP") {
if (D.planType === "MSRP") {
flagged = true;
} else {
if (D.planType !== item.PlanType) {
flagged = true;
}
}
}
/* AXZ: user is only shown MSRP with an option to login */
if (flagged) {
$MSI.trigger(E.DATA_AXZ_ERROR, item.PlanType);
item.PlanType = "MSRP";
}
/* AXZ: choose display pricing */
switch (item.PlanType) {
case "MSRP":
item.DisplayPricing = {
BasePrice: item.Pricing.BaseMSRP,
Options: item.Pricing.Options,
Destination: item.Pricing.DestinationDeliveryCharge,
Incentives: item.Pricing.MSRPDiscount,
NetPrice: item.Pricing.MSRP
};
break;
case "AZ":
item.DisplayPricing = {
BasePrice: item.Pricing.BaseAZPlan,
Options: item.Pricing.OptionsAZPlan,
Destination: item.Pricing.DestinationDeliveryCharge,
Incentives: item.Pricing.AZPlanDiscount,
NetPrice: item.Pricing.AZPlan
};
break;
case "X":
item.DisplayPricing = {
BasePrice: item.Pricing.BaseXPlan,
Options: item.Pricing.OptionsXPlan,
Destination: item.Pricing.DestinationDeliveryCharge,
Incentives: item.Pricing.XPlanDiscount,
NetPrice: item.Pricing.XPlan
};
break;
}
}
};
}()),
/**
* _getPlanType
*
* Get AXZ Auth status
*/
_getPlanType: function () {
var axz = NGAW.planType;
var type;
switch (axz) {
case "A/Z Plan":
type = "AZ";
break;
case "X Plan":
type = "X";
break;
default:
type = "MSRP";
break;
}
return type;
},
/**
* _sortItemsIntoArraysByModel
*
* Pull each node out of the data objects and place them into
* arrays oraganized by model and data type. Also, set the
* `recent` item
*/
_sortItemsIntoArraysByModel: function (index, item) {
var name = item.Model;
if (name && item.ItemType !== "technology") {
D.__models[name] = D.__models[name] || {
cpo: [],
config: [],
inventory: [],
compare: [],
gallery: []
};
}
/* push item into the appropriate bucket */
switch (item.ItemType) {
case "technology":
item.dataType = "technology";
D.__technology.push(item);
break;
default:
D.__models[name][item.dataType].push(item);
D.__totalVehicles++;
break;
}
},
/**
* _sortModelsIntoArraysByVehicle
*
* Place models into the vehicles array
*/
_sortModelsIntoArraysByVehicle: function (name, model) {
/* get first visible category */
// var firstCategory = model.config.length ? "config" : model.inventory.length ? "inventory" : model.cpo.length ? "cpo" : model.gallery.length ? "gallery" : "config";
var firstCategory = "config";
/* add string form of length for templating */
model.config.count = String(model.config.length);
model.inventory.count = String(model.inventory.length);
model.compare.count = String(model.compare.length);
model.cpo.count = String(model.cpo.length);
model.gallery.count = String(model.gallery.length);
/* add onto vehicles array */
D.__vehicles.push({
model: name,
modelID: name.match(/[a-z0-9]/gi).join("").toLowerCase(),
items: model,
firstCategory: firstCategory
});
},
/**
* _sortModelsIntoArrayForUpdates
*
* Creates array of model names to pass into MySavedItems.Page._getUpdatesHandler
*/
_sortModelsIntoArrayForUpdates: function (key, item) {
var model = item.Model;
var exists = $.inArray(model, D.__vehiclesUpdatesArray);
/*only want to add particular ngpID once */
if (exists !== -1 || model === "") {
return;
}
model = model.replace(/%20/g, " ");
D.__vehiclesUpdatesArray.push(model);
}
};
}());
}(window, jQuery, ngbs, NextGen, MySavedItems));
/*global jQuery,ngbs,NextGen,MySavedItems,s, __params */
/**
* MySavedItems.Page
*
* Copyright (c) 2012, Team Detroit
* All rights reserved
*
* @desc Renders and manages the My Saved Items page
* @dependencies jQuery + .views, .render, .observable
*/
(function (window, $, ngbs, NextGen, MySavedItems) {
"use strict";
var document = window.document;
var console = window.console || {
log: function () {}
};
$.extend(MySavedItems.Events, {
"PAGE_RENDER_RESET": "PAGE_RENDER_RESET",
"PAGE_RENDER_START": "PAGE_RENDER_START"
});
var RESPONDERS = {
"config": true,
"cpo": true,
"inventory_bp": true,
"inventory_si": true
};
var NAMESPACE = ".MSIPAGE";
/* shortcuts */
var $MSI = $(MySavedItems);
var E = MySavedItems.Events;
var D = MySavedItems.Data;
var NG = NextGen;
var NGAW = NG.AuthenticationWidget;
var NGSAPI = NG.SaveAPI;
var message_bus = ngbs._message_bus;
var $dealerName;
/**
* MySavedItems Page module
*/
var P = MySavedItems.Page = (function () {
/* public interface */
return {
/**
* init
*
* Sets up the element for rendering
*
* @param {jQuery} selector References the element where view is created
*/
init: function ($element, options) {
/* set wrapper element */
P.$body = $(document.body);
P.$element = $element;
P.$element.initHTML = $element.html();
P.$flip = $("#msi-flip");
P.$flipContent = $("#msi-flip-conent");
P.$flipBackground = $("#msi-flip-background");
P.$defaultInput = 22 + "px";
/*metrics*/
P.vehicle = "";
P.tabname = "";
P.tabtype = "";
P.category = "";
P.prop5 = "";
/* move flip to child of body */
P.$flip.detach().appendTo(P.$body);
/* bind handlers */
P._unbindHandlers();
P._bindHandlers();
/* routing */
P._addRoutes();
/* metrics*/
P._configMetrics();
/* disclosures */
P._getDisclosures();
},
/**
* _unbindHandlers
*/
_unbindHandlers: function () {
$MSI.unbind(NAMESPACE);
P.$body.undelegate(NAMESPACE);
},
/**
* _bindHandlers
*
* Bind handlers to msi content events
*/
_bindHandlers: function () {
$MSI.bind(E.PAGE_RENDER_RESET + NAMESPACE, P._renderReset);
$MSI.bind(E.PAGE_RENDER_START + NAMESPACE, P._renderAll);
P.$body.delegate(".msi-link", "click" + NAMESPACE, P._linkHandler);
P.$body.delegate(".msi-sign-out", "click" + NAMESPACE, P._signoutHandler);
P.$body.delegate(".msi-sign-in", "click" + NAMESPACE, P._signinHandler);
P.$body.delegate(".msi-upgrade-user", "click" + NAMESPACE, P._upgradeHandler);
P.$body.delegate(".msi-delete-all", "click" + NAMESPACE, P._deleteAllHandler);
P.$body.delegate(".btn-remove", "click" + NAMESPACE, P._deleteHandler);
P.$body.delegate(".msi-flip-close", "click" + NAMESPACE, P._hideFlip);
P.$body.delegate(".msi-flip-background", "click" + NAMESPACE, P._hideFlip);
P.$body.delegate(".axz-exit", "click" + NAMESPACE, P._axzExit);
P.$body.delegate(".msi-btn-disclosures", "click" + NAMESPACE, P._disclosuresHandler);
P.$body.delegate(".msi-note-field", "keyup" + NAMESPACE, P._textareaChangeHandler);
P.$body.delegate(".msi-note-field", "focusin" + NAMESPACE, P._textareaFocusHandler);
P.$body.delegate(".msi-note-field", "focusout" + NAMESPACE, P._textareaFocusHandler);
P.$body.delegate(".msi-btn-note-submit", "click" + NAMESPACE, P._updateItemHandler);
P.$body.delegate(".msi-get-updates", "click" + NAMESPACE, P._getUpdatesHandler);
P.$body.delegate('.item-offerstext', 'click' + NAMESPACE, P._showOffersHandler);
/* tooltip */
P.$body.delegate(".item-price-info", "mouseenter mouseleave touchstart touchend" + NAMESPACE, P._tooltipHandler);
/* hide flip on esc key */
$(document).keyup(function (e) {
if (e.keyCode === 27) {
P._hideFlip();
}
});
/* hide flip on clicking back button */
window.onhashchange = function () {
P._hideFlip();
};
},
/**
* _addRoutes
*
* Add deeplinking routes
* Fire page metrics
* data.tabname = config || gallery || cpo...etc
* data.category = recent || technology OR data.vehicle = vehicle
*/
_addRoutes: function () {
// nav
var lcswitch = $("#concierge-switch").data('lcswitch');
var make = __params.make.toLowerCase();
P.deeplink = ngbs.u.deeplink({
"default": function (hash) {
var tabname;
var vehicle;
if (MySavedItems.SavedItems.total === 0) {
P.vehicle = "";
P.category = "empty";
P.tabname = "bp";
P.prop5 = "myfolder: empty queue";
P._navigateToContent("msi-vehicle", "empty", "config");
} else {
tabname = MySavedItems.SavedItems.recent.dataType;
if (tabname === "config") {
tabname = "bp";
}
vehicle = MySavedItems.SavedItems.recent.Model.toLowerCase() || "";
P.vehicle = vehicle;
P.tabtype = "recent";
P.tabname = tabname;
P.category = "recent save";
P.prop5 = "";
P._navigateToContent("msi-recent");
}
if (NGAW.provider !== "ANONYMOUS" && make === "lincoln" && lcswitch === "on") {
P._pageMetrics("msi-concierge-page");
} else {
P._pageMetrics("msi-page");
}
P._matchCompareColumnsHeight();
},
"/recent": function (hash) {
var tabname;
var vehicle;
// mysaveditems page without #nav displays either empty config or recent item
// Pass appropriate value to page-load metrics.
if (MySavedItems.SavedItems.total === 0) {
P.vehicle = "";
P.category = "empty";
P.tabname = "";
} else {
tabname = MySavedItems.SavedItems.recent.dataType.toLowerCase();
vehicle = MySavedItems.SavedItems.recent.Model.toLowerCase() || "";
if (tabname === "config") {
tabname = "bp";
}
P.vehicle = vehicle;
P.category = "recent save";
P.tabtype = "recent";
P.tabname = tabname;
}
P._navigateToContent("msi-recent");
if (NGAW.provider !== "ANONYMOUS" && make === "lincoln" && lcswitch === "on") {
P._pageMetrics("msi-concierge-page");
} else {
P._pageMetrics("msi-page");
}
P._matchCompareColumnsHeight();
},
"/vehicle": function (hash) {
P.vehicle = "";
P.tabname = "empty";
P.tabtype = "";
P.category = "vehicles";
P._navigateToContent("msi-vehicle");
if (NGAW.provider !== "ANONYMOUS" && make === "lincoln" && lcswitch === "on") {
P._pageMetrics("msi-concierge-page");
} else {
P._pageMetrics("msi-page");
}
},
"/vehicle/:vehicle/:tab": function (hash, vehicle, tab) {
var tabname = tab;
if (tabname === "config") {
tabname = "bp";
}
P.vehicle = vehicle;
P.tabname = tabname;
P.tabtype = "";
P.category = "vehicles";
P._navigateToContent("msi-vehicle", vehicle, tab);
if (NGAW.provider !== "ANONYMOUS" && make === "lincoln" && lcswitch === "on") {
P._pageMetrics("msi-concierge-page");
} else {
P._pageMetrics("msi-page");
}
if (tab === 'compare') {
P._matchCompareColumnsHeight();
}
},
"/technology": function (hash) {
P.vehicle = "";
P.tabname = "technology";
P.tabtype = "";
P.category = "technology";
P._navigateToContent("msi-technology");
if (NGAW.provider !== "ANONYMOUS" && make === "lincoln" && lcswitch === "on") {
P._pageMetrics("msi-concierge-page");
} else {
P._pageMetrics("msi-page");
}
}
});
},
/**
* _goHome
*/
_goHome: function () {
P.deeplink.gotoRoute();
},
/**
* _navigateToContent
*
* Show some content
*
* @param {String} id
* @param {String} vehicle
* @param {String} tab
*/
_navigateToContent: function (id, vehicle, tab) {
var contentID = "#" + id;
var $content = $(contentID);
var $vehicle;
var $tab;
if (!$content.length) {
P._goHome();
return;
}
P._showElementHideSiblings($content);
if (id === "msi-vehicle") {
$vehicle = $(contentID + "-" + vehicle);
$tab = $(contentID + "-" + vehicle + "-" + tab);
if (!$vehicle.length && !$tab.length) {
P._goHome();
return;
}
P._showElementHideSiblings($vehicle);
P._showElementHideSiblings($tab);
P._textareaFormatHandler($tab);
} else {
P._textareaFormatHandler(contentID);
}
P._updateNav(id, vehicle, tab);
},
/**
* _updateNav
*
* Update the current class in the nav
*
* @param {String} id
* @param {String} vehicle
* @param {String} tab
*/
_updateNav: function (id, vehicle, tab) {
// highlight main nav
P._showElementHideSiblings($("a.nav-" + id).parent());
// if vehicle, highlight vehicle nav
P._showElementHideSiblings($("a.nav-" + id + "-" + vehicle).parent());
// if tab, highlight tab nav
P._showElementHideSiblings($("a.nav-" + id + "-" + vehicle + "-" + tab).parent());
},
/**
* _showElementHideSiblings
*
* Show an element and hide its siblings
*
* @param {jQuery} $element
*/
_showElementHideSiblings: function ($element) {
$element.addClass("current").siblings().removeClass("current");
},
/**
* _gotoURL
*
* Navigate to an external URL after checking if content exists
*
* {String} itemType
* {String} id
* {String} url
* {String} model optional
* {Boolean} newWin
*/
_gotoURL: function (itemType, id, url, model, newWin) {
P._processingFlip();
var success = function (data, isSuccessful) {
var response = data && data.response;
var redirect;
if (data === true || response.success) {
P._hideFlip();
if (newWin) {
window.open(url);
return false;
}
window.location.href = url;
} else {
redirect = response.redirect;
P._responderFlip(itemType, id, redirect, model);
}
};
var error = function () {
P._hideFlip();
if (newWin) {
window.open(url);
return false;
}
window.location.href = url;
};
var responder = RESPONDERS[itemType];
var anchor;
var responderDomain;
var responderPath;
var responderURL;
var responderProtocol;
// make an ajax call to the responder for the url
if (responder) {
anchor = ngbs.u.anchor(url);
responderProtocol = anchor.protocol();
responderDomain = anchor.host();
responderPath = "/saveandshare/checkurl?url=" + encodeURIComponent(url);
responderURL = responderProtocol + "//" + responderDomain + responderPath;
$.ajax(responderURL, {
dataType: "jsonp",
cache: true,
timeout: 8000
}).done(success).fail(error);
} else {
success(true);
}
},
/**
* _renderReset
*
* Initialize the my saved items canvas
*/
_renderReset: function () {
P.$element.html(P.$element.initHTML);
},
/**
* _renderAll
*
* Render the data as html using the template indicated
*
* @param {Object} e jQuery event
* @param {Object} data Processed saved items data
*/
_renderAll: function (e, data) {
MySavedItems.SavedItems = data || MySavedItems.SavedItems;
P.$element.link(MySavedItems.SavedItems, "#msi-template");
/* start deeplinking */
P.deeplink.start();
/* init sharev2 buttons */
jQuery('.ngbssharev2pagelevel').each(function (index, element) {
ngbs.widgetv2.bootstrap.register(element);
});
P.$body.ready(function () {
$dealerName = $('.bp-saved-dealer-names');
var dealercode;
$dealerName.each(function () {
dealercode = $dealerName.attr('data-pacode');
jQuery.getJSON('/services/dealer/Details.json?make=Lincoln&dealerPACode=' + dealercode, function (response) {
$dealerName.html(response.Response.Dealer.Name);
}).fail(function (response) {
$dealerName.html('the Dealer');
});
});
});
},
_matchCompareColumnsHeight: function () {
var compareItems = jQuery('.msi-content-holder .msi-compare, #msi-recent .msi-compare');
// reset height
compareItems.find('.item-sec').css('height', 'auto');
compareItems.each(function () {
var tallest = 0,
cols = jQuery(this).find('.item-sec'),
btnRow = jQuery(this).find('.item-btnrow');
cols.each(function () {
var thisHeight = jQuery(this).height();
if (thisHeight > tallest) {
tallest = thisHeight;
}
});
cols.height(tallest);
btnRow.css('top', tallest + 77);
});
},
/**
* _tooltipHandler
*
* Hover for tooltip
*
* @param {Object} e jQuery event
*/
_tooltipHandler: function (e) {
var $this = $(this);
var $tooltip = $this.find(".msi-tooltip");
if (e.type === "mouseenter" || e.type === "touchstart") {
$tooltip.show();
} else {
$tooltip.hide();
}
},
/**
* _textareaResizeHandler
*
* Finds and resizes all textarea fields to fit populated text, styles populated text fields appropriately.
*
*/
_textareaFormatHandler: function (element) {
var inputFields = $(element).find("textarea.msi-note-field");
if (inputFields.length > 0) {
$.each(inputFields, function (index, input) {
var populated = $(input).val();
if (populated) {
var submitBtn = $(this).parent().find(".msi-btn-note-submit");
var padding = parseFloat($(input).css("padding-top")) + parseFloat($(input).css("padding-bottom"));
var height = input.scrollHeight - padding;
$(submitBtn).addClass("populated").text("Edit");
$(input).addClass("populated");
$(input).height(height);
if (submitBtn.hasClass("updated")) {
$(submitBtn).text("Submit");
}
}
});
}
},
/**
* _textareaFocusHandler
*
* Handle series of display changes when user focuses on notes field
*
* @param {Event} e
*/
_textareaFocusHandler: function (e) {
if (e.type === "focusin") {
$(this).addClass("selected");
} else {
$(this).removeClass("selected");
}
},
/**
* _textareaChangeHandler
*
* Handle series of behaviors to occur when user changes value of input.
*
* @param {Event} e
*/
_textareaChangeHandler: function (e) {
var $this = $(this);
var $submitBtn = $this.parent().find(".msi-btn-note-submit");
$submitBtn.addClass("updated").text("Submit");
$this.addClass("updated");
while ($this.outerHeight() < this.scrollHeight + parseFloat($this.css("borderTopWidth")) + parseFloat($this.css("borderBottomWidth"))) {
$this.height($this.height() + 1);
}
},
/**
* _linkHandler
*
* Handle outgoing links
*
* @param {Event} e
*/
_linkHandler: function (e) {
e.preventDefault();
var $this = $(this);
var $item = $this.parents(".msi-item");
var url = $this.attr("href");
var data = $item.readDataAttr();
var itemType = data.itemType;
var id = data.id;
var model = data.model;
var newWin = $this.hasClass('msi-newwin');
P._gotoURL(itemType, id, url, model, newWin);
},
/**
* _showOffersHandler
*
* Handle view offers click event
*
* @param {Event} e
*/
_showOffersHandler: function (e) {
var $flip = jQuery('.msi-incentives-flip-content'),
$flipHolder = $flip.find('.msi-incentives-holder'),
$target = jQuery(e.target),
vehicleData = $target.closest('.msi-item').data(),
zipcode = vehicleData.zipcode,
year = vehicleData.year,
make = vehicleData.make,
ngpID = vehicleData.model,
url = 'https://www.ford-incentives.com/Flip/',
iframe = document.createElement('iframe');
if (make === 'lincoln') {
url = "https://www.lincoln-incentives.com/Flip/";
}
var params = [
'zipcode=' + zipcode,
'year=' + year,
'make=' + make,
'model=' + ngpID,
'app_context=ngbs_sploffr'
];
url += '?' + params.join('&');
$flipHolder.html('');
iframe.src = url;
iframe.id = 'incentives-flip-iframe';
iframe.height = "580";
iframe.width = '950';
iframe.frameBorder = 0;
$flipHolder.append(iframe);
P._showFlip("msi-incentives-flip");
},
/**
* _signinHandler
*
* @param {Event} e
*/
_signinHandler: function (e) {
if (!window.ThirdPartyAuthenticator) {
return;
}
NGAW.validateUser(NG.widgets.MY_SAVED_ITEM_WIDGET_NAME);
},
/**
* _upgradeHandler
*
* @param {Event} e
*/
_upgradeHandler: function (e) {
NGAW.upgradeUser();
},
/**
* _signoutHandler
*
* @param {Event} e
*/
_signoutHandler: function (e) {
NGAW.logoutUser();
var eVar11 = s.eVar11;
var channel = s.channel;
var hier1 = s.hier1;
var metricsData = {
eVar11: eVar11,
channel: channel,
hier1: hier1
};
ngbs.metrics.constructor();
P._clickMetrics("logout", metricsData);
P._confirmFlip("msi-logout-complete");
},
/**
* _deleteAllHandler
*
* @param {Event} e
*/
_deleteAllHandler: function (e) {
var callbacks = {
"ok": function () {
NGSAPI.deleteSavedItems(function () {
$MSI.trigger(E.DATA_REQUEST_START);
P._confirmFlip("msi-delete-all-complete");
});
}
};
P._showFlip("msi-delete-all", callbacks);
},
/**
* _deleteHandler
*
* @param {Event} e
*/
_deleteHandler: function (e) {
var $this = $(this);
var $item = $this.parents(".msi-item");
var data = $item.readDataAttr();
var id = data.id;
var itemType = data.itemType;
var callbacks = {
"ok": function () {
NGSAPI.deleteItem(itemType, id, function () {
$MSI.trigger(E.DATA_REQUEST_START);
P._confirmFlip("msi-delete-complete");
});
}
};
P._showFlip("msi-delete", callbacks);
},
/**
* _updateItemHandler
*
* @param {Event} e
*/
_updateItemHandler: function (e) {
var $element = $(this);
var isUpdated = $element.hasClass("updated");
if (!isUpdated) {
return;
}
NextGen.DataCollectionWidget.formObjectAndUpdateItem($element);
P._clickMetrics("notes");
},
/**
* _responderDeleteHandler
*
* @param {Event} id
*/
_responderDeleteHandler: function (id, itemType, redirectCallback) {
NGSAPI.deleteItem(itemType, id, function () {
if (redirectCallback) {
redirectCallback();
} else {
$MSI.trigger(E.DATA_REQUEST_START);
P._confirmFlip("msi-delete-complete");
}
});
},
/**
* _disclosuresHandler
*
* @param {Event} e
*/
_disclosuresHandler: function (e) {
P._showFlip("msi-disclosures");
},
/**
* _getUpdatesHandler
*
* @param {Event} e
*/
_getUpdatesHandler: function (e) {
var $getupdates = $('.ng-widget.getupdates');
var make = __params.make.toLowerCase();
var qaCodes = "313167";
if (make === "lincoln") {
qaCodes = "321017";
}
ngbs._message_bus.send($getupdates, 'getupdates.open', {
type: 'updates',
vehicles: MySavedItems.Data.__vehiclesUpdatesArray,
qacodes: qaCodes
});
},
/**
* _getDisclosures
*/
_getDisclosures: function () {
var urls = {
ford: "/services/attributes/Attributes.json?make=Ford&model=Focus&year=2012&returnAttributes=ShoppingTools_Shared_Disclaimer_Text_.*",
lincoln: "/services/attributes/Attributes.json?make=Lincoln&model=MKX&year=2012&returnAttributes=ShoppingTools_Shared_Disclaimer_Text_.*"
};
var make = __params.make.toLowerCase();
var url = urls[make];
if (url) {
$.get(url).success(P._renderDisclosures);
}
},
/**
* _renderDisclosures
*/
_renderDisclosures: function (data) {
var $disclosuresHolder = $(".msi-disclosures-holder");
var sections;
var text = "";
if (data.Response && data.Response.Attribute) {
sections = data.Response.Attribute;
$.each(sections, function (index, section) {
text += section.Value;
});
$disclosuresHolder.append(text);
}
},
/**
* _showFlip
*
* Fires _toggleFlipContents. Appends css to display flip
*
* @param {String} id Required string content identifier
* @param {Object} callbacks Map of callback functions to classes
*/
_showFlip: function (id, callbacks) {
callbacks = callbacks || {};
/* check for cancel */
callbacks.cancel = callbacks.cancel || function () {
P._hideFlip();
};
/* bind callbacks to buttons in flip */
P.$flip.undelegate();
$.each(callbacks, function (i, callback) {
P.$flip.delegate(".msi-" + i, "click", callback);
});
/* change flip contents and show */
P._toggleFlipContents(id);
P.$flip.show();
},
/**
* _hideFlip
*
* Hides flip
*/
_hideFlip: function () {
P.$flip.hide();
},
/**
* _confirmFlip
*
* @param {String} id Required id of content flip minus "-content"
*/
_confirmFlip: function (id) {
var callbacks = {
"confirm": function () {
P._hideFlip();
}
};
P._showFlip(id, callbacks);
},
/**
* _toggleFlipContents
*
* Hides and shows flip content
*
* @param {Object} id Item clicked to trigger event
*/
_toggleFlipContents: function (id) {
var $flipContent = $("." + id + "-content");
$flipContent.show();
$flipContent.siblings().hide();
},
/**
* _axzAuthFlip
*
* @param {Event} e
* @param {String} planType
*/
_axzAuthFlip: (function () {
var shownOnce = false;
/*retrieving location from url for metrics*/
var url = window.location.href;
var section = url.split("/");
section = (section[section.length - 1]);
if (section === "config") {
section = "bp";
}
switch (section) {
case "bp":
case "cpo":
case "inventory":
case "gallery":
case "technology":
break;
default:
section = "recent";
break;
}
var metricsData = {
tabname: section
};
return function (e, planType) {
if (!shownOnce) {
if (planType === "AZ") {
P._showFlip("msi-az-authentication");
P._pageMetrics("axz-flip", metricsData);
} else if (planType === "X") {
P._showFlip("msi-x-authentication");
P._pageMetrics("axz-flip", metricsData);
}
shownOnce = true;
}
};
}()),
/**
* _axzExit
* Fires metrics for AXZ exit link
*/
_axzExit: function () {
var eVar11 = s.eVar11;
var metricsData = {
eVar11 : eVar11
};
P._clickMetrics("axz-exit", metricsData);
},
/**
* _responderFlip
*
* @param {String} itemType
* @param {String} id
* @param {String} url
* @param {String} model optional
*/
_responderFlip: function (itemType, id, url, model) {
var callbacks = {
"similar": function () {
var input = $(this).parent().parent().find("input");
P._hideFlip();
if (input.attr("checked")) {
P._responderDeleteHandler(id, itemType, function () {
window.location.href = url;
});
}
window.location.href = url;
},
"cancel": function () {
var input = $(this).parent().parent().find("input");
P._hideFlip();
if (input.attr("checked")) {
P._responderDeleteHandler(id, itemType);
}
}
};
switch (itemType) {
case "cpo":
P._showFlip("msi-responder-cpo", callbacks);
break;
case "inventory_bp":
case "inventory_si":
P._showFlip("msi-responder-inventory", callbacks);
break;
case "config":
P._showFlip("msi-responder-config", callbacks);
break;
default:
break;
}
var metricsItemType;
/*metrics requires more generalized values for itemType
* while services require full values. Ex: inventory_si VS inventory.
*/
if (itemType === "inventory_si" || itemType === "inventory_bp") {
metricsItemType = "inventory";
} else if (itemType === "config") {
metricsItemType = "bp";
} else {
metricsItemType = itemType;
}
var metricsData = {
tabName: metricsItemType,
vehicle: model
};
P._pageMetrics("obsolete-item", metricsData);
},
/**
* _processingFlip
*
* Show a loading image while processing is being done
*/
_processingFlip: function () {
P._showFlip("msi-processing");
},
/**
* _configMetrics
*
* Initial setup of metrics
*/
_configMetrics: function () {
var base;
var make = __params.make.toLowerCase();
if (make === "ford") {
base = "fv: myfolder: ";
} else {
base = "ln: myfolder: ";
}
var getPageName = function () {
var details;
if (P.vehicle !== "empty" && P.vehicle !== "") {
details = ": " + make + " " + P.vehicle;
} else {
details = ": " + P.category;
}
return base + "saved items: " + P.tabname + details;
};
var getProp16 = function () {
var prop;
if (P.vehicle !== "empty" && P.vehicle !== "") {
prop = make + " " + P.vehicle;
} else {
prop = "";
}
return prop.toLowerCase();
};
ngbs.metrics.config({
click: {
'logout': {
pe: "o",
pev2: base + "signout",
channel: function (data) {
return data.channel;
},
hier1: function (data) {
return data.hier1;
},
prop5: "",
prop11: function (data) {
return data.eVar11;
},
eVar11: function (data) {
return data.eVar11;
},
prop16: getProp16,
eVar16: getProp16,
prop42: "logged out"
},
'notes': {
pe: "o",
pev2: base + "notes",
channel: function (data) {
return data.channel;
},
hier1: function (data) {
return data.hier1;
},
prop5: "",
prop11: function (data) {
return data.eVar11;
},
eVar11: function (data) {
return data.eVar11;
},
prop16: getProp16,
eVar16: getProp16
},
'axz-exit': {
pe: "e",
pev2: "referral: exit",
channel: "myfolder",
prop5: "referral: axzplan: login",
hier1: "shopping tools:myfolder",
prop6: "axzplan: login",
eVar6: "axzplan: login",
prop11: function (data) {
return data.eVar11;
},
eVar11: function (data) {
return data.eVar11;
},
prop16: getProp16,
eVar16: getProp16
}
},
page: {
'msi-page': {
pageName: getPageName,
channel: "myfolder",
prop5: function () {
return P.prop5;
},
hier1: function () {
return "shopping tools:myfolder:" + P.tabname;
},
prop11: function () {
if (P.tabtype === "recent") {
return base + "saved items: " + P.tabtype;
}
return base + "saved items: " + P.tabname;
},
eVar11: function () {
if (P.tabtype === "recent") {
return base + "saved items: " + P.tabtype;
}
return base + "saved items: " + P.tabname;
},
prop16: getProp16,
eVar16: getProp16,
prop39: "",
events: [""]
},
'msi-concierge-page': {
pageName: function () {
if (P.tabtype === "recent") {
return "ln:concierge:saved items:" + P.tabtype;
}
return "ln:concierge:saved items:" + P.tabname;
},
channel: "concierge",
hier1: "shopping tools:concierge:my saved items",
prop11: function () {
if (P.tabtype === "recent") {
return "ln:concierge:my saved items:" + P.tabtype;
}
return "ln:concierge:my saved items:" + P.tabname;
},
eVar11: function () {
if (P.tabtype === "recent") {
return "ln:concierge:my saved items:" + P.tabtype;
}
return "ln:concierge:my saved items:" + P.tabname;
},
prop39: "",
events: [""]
},
'axz-flip': {
prop39: "",
pageName: base + "axz flip",
channel: "myfolder",
hier1: "shopping tools:myfolder",
prop5: base + "axz flip",
prop11: function (data) {
return base + "saved items: " + data.tabname;
},
eVar11: function (data) {
return base + "saved items: " + data.tabname;
},
eVar16: getProp16,
prop16: getProp16,
events: [""]
},
'obsolete-item': {
pageName: function () {
return base + "item not available: " + P.tabname;
},
channel: "myfolder",
prop5: function () {
return "myfolder:item not available: " + P.tabname;
},
hier1: "shopping tools:myfolder",
prop11: function () {
return base + "item not available:" + P.tabname;
},
eVar11: function () {
return base + "item not available: " + P.tabname;
},
prop16: getProp16,
eVar16: getProp16,
prop39: "",
events: [""]
}
}
});
},
/**
* _clickMetrics
*
* Fires click metrics
*
* @param {String} clickName
* @param {Object} data
*/
_clickMetrics: function (clickName, data) {
ngbs.metrics.click(clickName, data);
},
/**
* _pageMetrics
*
* Fires page level metrics
*
* @param {String} pageName
* @param {Object} data
*/
_pageMetrics: function (pageName, data) {
ngbs.metrics.page(pageName, data);
}
};
}());
}(window, jQuery, ngbs, NextGen, MySavedItems));
/*global jQuery,ThirdPartyAuthenticator,AXZAuthenticator,s, ngbs, MySavedItems, Concierge, shopOpenScheduleDealer, _lc_params */
/**
* NextGen.SaveAPI
*
* Copyright (c) 2012, Team Detroit
* All rights reserved
*
* @desc Manages interaction with the Save API
*
*
* @fileoverview <h1>SAVE - Authentication Widget Library</h1>
* <p>This is a library meant to Authenticate the User with 4 different
* Social Media Sites. "Facebook", "Google", "LinkedIn","Twitter"
* widget. The Save Widget will access the ng_authentication_window
* internally. While MSI will access it using the validateUser() function</p>
*
* <strong>Version History:</strong>
* <ul>
* <li>1.0: Initial creation of script</li>
* <li>1.1: Removal of global . Optimizations of Code. Adding into the NGBS Library</li>
* </ul>
*
* @version 1.1
*
*
* @fileoverview <h1>SAVE - SAVE Widget Library</h1>
* <p>This is a library meant to SAVE the required data
* passed from VIEW / Web Pages to Save Widget. Based on
* Authentication Status, save flow will perform desire
* funcationality
*
* <strong>Version History:</strong>
* <ul>
* <li>1.0: Initial creation of script</li>
* <li>1.1: Removal of global . Optimizations of Code. Adding into the NGBS Library</li>
* </ul>
*
* @version 1.1
*/
(function (window, $, ngbs) {
"use strict";
var document = window.document;
var location = window.location;
var console = window.console || {
log: function () {}
};
var NextGen = window.NextGen = window.NextGen || {};
var $NextGen = $(NextGen);
NextGen.baseURL = null;
NextGen.ready = false;
NextGen.events = {
"AUTHENTICATION_COMPLETE_EVENT": "AUTHENTICATION_COMPLETE_EVENT",
"METRIC_TRACKER_EVENT": "METRIC_TRACKER_EVENT",
"AUTHENTICATION_STARTED": "AUTHENTICATION_STARTED",
"AUTHENTICATION_ENDED": "AUTHENTICATION_ENDED",
"AUTHENTICATION_LOGOUT_EVENT": "AUTHENTICATION_LOGOUT_EVENT",
"SAVE_STARTED": "SAVE_STARTED",
"SAVE_ENDED": "SAVE_ENDED"
};
NextGen.widgets = {
"MY_SAVED_ITEM_WIDGET_NAME": "MSI",
"UPGRADE_USER": "UPGRADE_USER",
"SAVE_WIDGET_NAME": "SAVE"
};
/**
* NextGen Save API module
*/
NextGen.SaveAPI = (function () {
/* begin module */
var NGSAPI = function () {};
/* add methods */
NGSAPI.prototype = {
/**
* init
* Set user-specific values
*/
init: function () {},
/**
* getBase
*/
getBase: function () {
return "/services/user/" + NextGen.AuthenticationWidget.userId + "/SavedItems";
},
/**
* getAccessToken
*/
getAccessToken: function () {
return NextGen.AuthenticationWidget.accessToken;
},
/**
* getBrandSite
*/
getBrandSite: function () {
return NextGen.make === "Ford" ? "www.ford.com" : "www.lincoln.com";
},
/**
* getParameters
*/
getParameters: function () {
return "accessToken=" + this.getAccessToken() + "&brandSite=" + this.getBrandSite();
},
/**
* makeRequest
*
* Makes all AJAX requests for this module
* @param {String} url The request URL
* @param {Object} props AJAX request properties
* @param {Function} success Callback
* @param {Function} error Callback
*/
makeRequest: function (url, props, success, error) {
if (typeof error === "undefined") {
error = this.defaultErrorHandler;
}
/* return a reference to the ajax promise */
return $.ajax(url, props).done(success).fail(error);
},
/**
* defaultErrorHandler
*
* Default error callback for AJAX requests
*/
defaultErrorHandler: function (jqxhr, type, status) {
throw new Error(status);
},
/**
* getSavedItems
*
* @param {Function} success Callback
* @param {Function} error Callback
* @return {Object} jqXHR deferred object
*/
getSavedItems: function (success, error) {
var cacheBuster = +new Date();
var url = this.getBase() + ".json" + "?" + this.getParameters() + "&t=" + cacheBuster;
var props = {
type: "GET"
};
return this.makeRequest(url, props, success, error);
},
/**
* deleteSavedItems
*
* @param {Function} success Callback
* @param {Function} error Callback
* @return {Object} jqXHR deferred object
*/
deleteSavedItems: function (success, error) {
var url = this.getBase() + "?" + this.getParameters();
var props = {
type: "DELETE"
};
return this.makeRequest(url, props, success, error);
},
/**
* createConfigVehicle
*
* @param {Object} config Parameters for the item to create
* @param {Function} success Callback
* @param {Function} error Callback
* @param {String} optional, itemID to update item (if id is present = item already exists)
* @return {Object} jqXHR deferred object
*/
createConfigVehicle: function (config, success, error, itemID) {
var url;
if (itemID) {
url = this.getBase() + "/ConfigVehicle/" + itemID + "?" + this.getParameters();
} else {
url = this.getBase() + "/ConfigVehicle/" + "?" + this.getParameters();
}
var props = {
type: "POST",
data: config
};
return this.makeRequest(url, props, success, error);
},
/**
* deleteConfigVehicle
*
* @param {String} id The id of the item to delete
* @param {Function} success Callback
* @param {Function} error Callback
* @return {Object} jqXHR deferred object
*/
deleteConfigVehicle: function (id, success, error) {
var url = this.getBase() + "/ConfigVehicle/" + id + "?" + this.getParameters();
var props = {
type: "DELETE"
};
return this.makeRequest(url, props, success, error);
},
/**
* createInventoryVehicle
*
* @param {Object} config Parameters for the item to create
* @param {Function} success Callback
* @param {Function} error Callback
* @param {String} optional, itemID to update item
* @return {Object} jqXHR deferred object
*/
createInventoryVehicle: function (config, success, error, itemID) {
var url;
if (itemID) {
url = this.getBase() + "/InventoryVehicle/" + itemID + "?" + this.getParameters();
} else {
url = this.getBase() + "/InventoryVehicle/" + "?" + this.getParameters();
}
var props = {
type: "POST",
data: config
};
return this.makeRequest(url, props, success, error);
},
/**
* deleteInventoryVehicle
*
* @param {String} id The id of the item to delete
* @param {Function} success Callback
* @param {Function} error Callback
* @return {Object} jqXHR deferred object
*/
deleteInventoryVehicle: function (id, success, error) {
var url = this.getBase() + "/InventoryVehicle/" + id + "?" + this.getParameters();
var props = {
type: "DELETE"
};
return this.makeRequest(url, props, success, error);
},
/**
* createCPOVehicle
*
* @param {Object} config Parameters for the item to create
* @param {Function} success Callback
* @param {Function} error Callback
* @param {String} optional, itemID to update item
* @return {Object} jqXHR deferred object
*/
createCPOVehicle: function (config, success, error, itemID) {
var url;
if (itemID) {
url = this.getBase() + "/CPOVehicle/" + itemID + "?" + this.getParameters();
} else {
url = this.getBase() + "/CPOVehicle/" + "?" + this.getParameters();
}
var props = {
type: "POST",
data: config
};
return this.makeRequest(url, props, success, error);
},
/**
* deleteCPOVehicle
*
* @param {String} id The id of the item to delete
* @param {Function} success Callback
* @param {Function} error Callback
* @return {Object} jqXHR deferred object
*/
deleteCPOVehicle: function (id, success, error) {
var url = this.getBase() + "/CPOVehicle/" + id + "?" + this.getParameters();
var props = {
type: "DELETE"
};
return this.makeRequest(url, props, success, error);
},
/**
* createBrandContent
*
* @param {Object} config Parameters for the item to create
* @param {Function} success Callback
* @param {Function} error Callback
* @param {String} optional, itemID to update item
* @return {Object} jqXHR deferred object
*/
createBrandContent: function (config, success, error, itemID) {
var url;
if (itemID) {
url = this.getBase() + "/BrandContent/" + itemID + "?" + this.getParameters();
} else {
url = this.getBase() + "/BrandContent/" + "?" + this.getParameters();
}
var props = {
type: "POST",
data: config
};
return this.makeRequest(url, props, success, error);
},
/**
* deleteBrandContent
*
* @param {String} id The id of the item to delete
* @param {Function} success Callback
* @param {Function} error Callback
* @return {Object} jqXHR deferred object
*/
deleteBrandContent: function (id, success, error) {
var url = this.getBase() + "/BrandContent/" + id + "?" + this.getParameters();
var props = {
type: "DELETE"
};
return this.makeRequest(url, props, success, error);
},
/**
* createCompareVehicle
*
* @param {Object} config Parameters for the item to create
* @param {Function} success Callback
* @param {Function} error Callback
* @param {String} optional, itemID to update item
* @return {Object} jqXHR deferred object
*/
createCompareVehicle: function (config, success, error, itemID) {
var url;
if (itemID) {
url = this.getBase() + "/VehicleCompare/" + itemID + "?" + this.getParameters();
} else {
url = this.getBase() + "/VehicleCompare/" + "?" + this.getParameters();
}
var props = {
type: "POST",
data: config
};
return this.makeRequest(url, props, success, error);
},
/**
* deleteCompareVehicle
*
* @param {String} id The id of the item to delete
* @param {Function} success Callback
* @param {Function} error Callback
* @return {Object} jqXHR deferred object
*/
deleteCompareVehicle: function (id, success, error) {
var url = this.getBase() + "/InventoryVehicle/" + id + "?" + this.getParameters();
var props = {
type: "DELETE"
};
return this.makeRequest(url, props, success, error);
},
/**
* deleteItem
*
* @param {String} itemType
* @param {String} id The id of the item to delete
* @param {Function} success Callback
* @param {Function} error Callback
* @return {Object} jqXHR deferred object
*/
deleteItem: function (itemType, id, success, error) {
var methodName;
switch (itemType) {
case "image":
case "video":
case "technology":
methodName = "deleteBrandContent";
break;
case "cpo":
methodName = "deleteCPOVehicle";
break;
case "inventory_bp":
case "inventory_si":
methodName = "deleteInventoryVehicle";
break;
case "config":
methodName = "deleteConfigVehicle";
break;
case "compare":
methodName = "deleteCompareVehicle";
break;
}
return NGSAPI[methodName].call(NGSAPI, id, success, error);
}
};
/* return public properties */
NGSAPI = new NGSAPI();
return NGSAPI;
}());
/**
* Base Class - Authentication Widget
* Core funcationality of User Authentication
* using the NextGen Services with Social Media Sites
*/
NextGen.AuthenticationWidget = (function () {
var NGPOP;
var NGSW;
var TPA;
var AXZ;
var NGFBW;
var PROVIDERS = {
"FACEBOOK": "/services/authentication/oauth/requesttoken/facebook?redirectUrl=",
"TWITTER": "/services/authentication/oauth/requesttoken/twitter?redirectUrl=",
"GOOGLE": "/services/authentication/openid/discovery/google?redirectUrl=",
"YAHOO": "/services/authentication/openid/discovery/yahoo?redirectUrl=",
"ANONYMOUS": "/services/authentication/aauth/requesttoken/anonymous?redirectUrl="
};
/* begin module */
var NGAW = function () {
this.userId = null;
this.accessToken = null;
this.provider = null;
this.planType = null;
this.authenticationWindow = null;
this.authenticationTimer = null;
this.contentAfterIcon = null;
this.divider = null;
this.mainContentDiv = null;
this.isUpgraded = false;
};
/* add methods */
NGAW.prototype = {
/**
* init
*/
init: function () {
NGPOP = NextGen.SavePopupWidget;
NGSW = NextGen.SaveWidget;
NGFBW = NextGen.FallbackWidget;
if (!window.ThirdPartyAuthenticator) {
return;
}
TPA = new window.ThirdPartyAuthenticator();
AXZ = new window.AXZAuthenticator();
NGAW.contentAfterIcon = $("#FNASW_content_after_icon");
NGAW.divider = $("#FNASW_divider");
NGAW.mainContentDiv = $("#main_content_div");
NGAW.bindHandlers();
NGAW.setProperties();
},
/**
* bindHandlers
*/
bindHandlers: function () {
$(document).delegate("a[rel='ng_auth_btn_']", "click", function () {
var provider = $(this).data("provider");
NGAW.authenticateWithNextGenService(provider);
});
},
/**
* getFallbackUrl
*/
getFallbackUrl: function () {
return NextGen.baseURL + "/save/fallback";
},
/**
* getProviderUrl
*/
getProviderUrl: function (name) {
var url = NextGen.baseURL + PROVIDERS[name];
if (url.indexOf("redirectUrl") > -1) {
url = url + NGAW.getFallbackUrl();
}
return url;
},
/**
* startPollingForUserID
*
* Start a timer to check for user id, if cookies are set
* call getAuthenticationStatus(true) and cancel timer
*/
startPollingForUserID: function () {
NGAW.authenticationTimer = window.setTimeout(function () {
var userId = TPA.getUserId();
var provider = TPA.getProvider() || "ANONYMOUS";
var model = NGSW.saveData ? NGSW.saveData.model : "";
if (NGAW.callerWidget === NextGen.widgets.UPGRADE_USER) {
if (userId && provider !== "ANONYMOUS") {
$NextGen.trigger(NextGen.events.METRIC_TRACKER_EVENT, [NextGen.events.AUTHENTICATION_ENDED, NGAW.provider, null, model]);
NGAW.getAuthenticationStatus(true);
return;
}
} else {
if (userId) {
$NextGen.trigger(NextGen.events.METRIC_TRACKER_EVENT, [NextGen.events.AUTHENTICATION_ENDED, NGAW.provider, null, model]);
NGAW.getAuthenticationStatus(true);
return;
}
}
NGAW.startPollingForUserID();
}, 250);
},
/**
* stopPollingForUserID
*
* Cancel the timer and close the auth popup window
*/
stopPollingForUserID: function () {
window.clearTimeout(NGAW.authenticationTimer);
},
/**
* authenticateWithNextGenService
*
* Authentication with NextGenServices consolidation
* If "Anonymous" then new Services need to "link-up" here
*/
authenticateWithNextGenService: function (provider) {
var url = NGAW.getProviderUrl(provider);
var title = "ngAuthWindow";
var props = "status=1,resizable=1,scrollbars=1,height=500,width=800";
if (url) {
NGAW.authenticationWindow = window.open(url, title, props);
NGAW.startPollingForUserID();
}
},
/**
* setProperties
*
* Set authentication user properties on NGAW object
*/
setProperties: function () {
NGAW.userId = TPA.getUserId();
NGAW.accessToken = TPA.getAccessToken();
NGAW.provider = TPA.getProvider() || "ANONYMOUS";
NGAW.planType = AXZ.getPlanTypeForDisplay();
if (NGAW.userId) {
NGAW.setRegisteredCookie();
}
},
/**
* logoutUser
*/
logoutUser: function () {
TPA.logoutUser();
NGAW.setProperties();
$NextGen.trigger(NextGen.events.AUTHENTICATION_LOGOUT_EVENT);
},
/**
* setRegisteredCookie
*/
setRegisteredCookie: function () {
var ONE_YEAR = 1000 * 60 * 60 * 24 * 365;
ngbs.u.cookie.set("save-registered", 1, {
domain: "." + NextGen.make.toLowerCase() + ".com",
expires: ONE_YEAR,
path: "/"
});
},
/**
* validateUser(caller)
*
* Entry point into Authnetication Widget.
* caller - Caller Widget e.g. MSI
*/
validateUser: function (caller, lc) {
var concierge = lc || false;
NGAW.setProperties();
NGAW.callerWidget = caller;
if (NGAW.isUpgraded) {
NGAW.updateAuthScreen(false);
}
var model = NGSW.saveData ? NGSW.saveData.model : "";
if (NGAW.userId) {
NGAW.setRegisteredCookie();
$NextGen.trigger(NextGen.events.AUTHENTICATION_COMPLETE_EVENT, [true, NGAW.userId, NGAW.accessToken, NGAW.provider, NGAW.callerWidget, concierge]);
} else {
NGPOP.open("Sign In", "#FNASW_authentication_content");
$NextGen.trigger(NextGen.events.METRIC_TRACKER_EVENT, [NextGen.events.AUTHENTICATION_STARTED, null, null, model]);
}
},
/**
* upgradeUser
*
* For upgrading anonymous user to a normal one
*/
upgradeUser: function () {
NGAW.updateAuthScreen(true);
NGAW.callerWidget = NextGen.widgets.UPGRADE_USER;
NGPOP.open("Sign In", "#FNASW_authentication_content");
},
/*Function added for updating the authentication screen elemensts while upgrade*/
updateAuthScreen: function (can_hide) {
if (can_hide) {
NGAW.contentAfterIcon.hide();
NGAW.divider.hide();
NGAW.isUpgraded = true;
} else {
NGAW.contentAfterIcon.show();
NGAW.divider.show();
NGAW.isUpgraded = false;
}
},
/**
* getAuthenticationStatus
*
* For upgrading anonymous user to a normal one
*/
getAuthenticationStatus: function (isAuthenticated) {
NGAW.setProperties();
NGAW.stopPollingForUserID();
if (isAuthenticated) {
NGPOP.close();
$NextGen.trigger(NextGen.events.AUTHENTICATION_COMPLETE_EVENT, [true, NGAW.userId, NGAW.accessToken, NGAW.provider, NGAW.callerWidget]);
}
}
};
/* return public properties */
NGAW = new NGAW();
return NGAW;
}());
/**
* Save Popup Window display
*/
NextGen.SavePopupWidget = (function () {
var TPA;
var NGDCW;
/* begin module */
var NGPOP = function () {
this.visible = false;
this.$container = null;
this.$background = null;
this.$screens = null;
this.$headingTitle = null;
};
/* add methods */
NGPOP.prototype = {
init: function () {
if (!window.ThirdPartyAuthenticator) {
return;
}
TPA = new window.ThirdPartyAuthenticator();
NGDCW = NextGen.DataCollectionWidget;
NGPOP.$container = $("#nextgen_auth_save_widget_container");
NGPOP.$background = $("#nextgen_auth_save_container_background");
NGPOP.$screens = NGPOP.$container.find(".changable_content");
NGPOP.$headingTitle = $("#FNASW_window_title");
NGPOP.bindHandlers();
},
/**
* bindHandlers
*/
bindHandlers: function () {
$(document).delegate("#ng_popup_close_btn", "click", NGPOP.close);
$(document).delegate("#nextgen_auth_save_container_background", "click", NGPOP.close);
},
setWindowHeading: function (headingText) {
NGPOP.$headingTitle.html(headingText);
},
hideAllWindows: function () {
NGPOP.$screens.hide();
},
open: function (title, contentId) {
NGPOP.setWindowHeading(title);
NGPOP.hideAllWindows();
NGPOP.$container.find(contentId).show();
if (!NGPOP.visible) {
NGPOP.$background.show();
NGPOP.$container.show();
NGPOP.visible = true;
}
},
close: function () {
if (NGPOP.visible) {
NGPOP.$background.hide();
NGPOP.$container.hide();
NGPOP.visible = false;
}
}
};
/* return public properties */
NGPOP = new NGPOP();
return NGPOP;
}());
/**
* Fallback display
*/
NextGen.FallbackWidget = (function () {
/* begin module */
var NGFBW = function () {};
if (!window.ThirdPartyAuthenticator) {
return;
}
var TPA = new window.ThirdPartyAuthenticator();
/* add methods */
NGFBW.prototype = {
init: function () {
window.resizeTo(800, 500);
NGFBW.bindHandlers();
},
hideConciergeButton: function () {
var prov = TPA.getProvider() || "ANONYMOUS";
var authenticatedDomain = ngbs.u.cookie.get('authenticatedDomain');
var fallbackPageDomain = $('#baseurl').data("baseurl");
if ((fallbackPageDomain.toLowerCase().indexOf(authenticatedDomain) < 0) || (prov === "ANONYMOUS")) {
$(document).find("#fallback_goto_concierge_btn").css('display', 'none');
$(document).find("#fallback_ok_btn").css('margin-left', '97px');
return false;
}
},
bindHandlers: function () {
$(document).delegate("#fallback_ok_btn", "click", NGFBW.closeWindow);
$(document).delegate("#fallback_goto_concierge_btn", "click", NGFBW.openconcierge);
},
openconcierge: function () {
window.opener.document.location.href = $('#baseurl').data("baseurl") + '/concierge';
window.close();
},
closeWindow: function () {
window.open("", "_self", "");
window.close();
}
};
/* return public properties */
NGFBW = new NGFBW();
return NGFBW;
}());
/**
* Base Class NextGenSaveWidget
* Core SAVE Widget starts
*/
NextGen.SaveWidget = (function () {
var NGAW;
var NGSAPI;
var NGPOP;
var NGDCW;
var AXZ;
var TPA;
var disclaimerRegex = /<sup\\?>(\d+|[\u2020\u2021]+|&dagger;)<\/sup\\?>/gi;
var htmlTagRegex = /<\/?\w+\s*\/?\\?>/gi;
var strip = function (str) {
if (str) {
str = str.replace(disclaimerRegex, ""); // disclaimers
str = str.replace(htmlTagRegex, ""); // html tags
return str;
}
};
var slashUnescape = function (str) {
if (str) {
str = str.replace(/\\/gi, "");
return str;
}
};
var ellipsis = "%E2%80%A6";
var ELLIPSIS_LENGTH = ellipsis.length;
var TITLE_MAX_LENGTH = 200 - ELLIPSIS_LENGTH;
var NOTE_MAX_LENGTH = 500 - ELLIPSIS_LENGTH;
var DESCRIPTION_MAX_LENGTH = 200 - ELLIPSIS_LENGTH;
var notesDefaultInput = "Add a note...";
var notesDefaultHeight = 22 + "px";
var encodeAndTruncate = function (str, maxLength) {
var lastIndex;
// encode only the necessary characters
/*jslint regexp:true*/
str = str.replace(/[^a-z0-9\s,\.\|]/gi, function (str) {
return encodeURIComponent(str);
});
// add ellipsis if more that max length
if (str.length > maxLength) {
str = str.slice(0, maxLength);
lastIndex = str.lastIndexOf(" ");
if (lastIndex > -1) {
str = str.slice(0, lastIndex);
}
str = str + ellipsis;
}
return str;
};
/* begin module */
var NGSW = function () {
this.saveData = null;
};
/* add methods */
NGSW.prototype = {
/**
* init
*/
init: function () {
if (!window.ThirdPartyAuthenticator) {
return;
}
NGAW = NextGen.AuthenticationWidget;
NGSAPI = NextGen.SaveAPI;
NGPOP = NextGen.SavePopupWidget;
NGDCW = NextGen.DataCollectionWidget;
AXZ = new window.AXZAuthenticator();
TPA = new window.ThirdPartyAuthenticator();
NGSW.planType = AXZ.getPlanTypeForServices();
NGSW.bindHandlers();
},
/**
* bindHandlers
*/
bindHandlers: function () {
$NextGen.bind(NextGen.events.AUTHENTICATION_COMPLETE_EVENT, NGSW.resumeSave);
$(document).delegate("#submit_btn", "click", NGSW.validate);
$(document).delegate("#continue_btn", "click", NGPOP.close);
$(document).delegate("#goto_save_btn", "click", NGSW.gotoMySavedItem);
$(document).delegate("#cancel_btn", "click", NGPOP.close);
$(document).delegate("#FNASW_ng_notes", "click", NGSW.clearTextInput);
$(document).delegate("#FNASW_ng_notes", "keyup", NGSW.expandTextArea);
$(document).delegate("#concierge_continue_btn", "click", NGPOP.close);
$(document).delegate("#schedule_dealer_btn", "click", NGSW.scheduleDealerFlip);
},
/**
* wrapper to call other vendor function
*/
scheduleDealerFlip: function () {
NGPOP.close();
shopOpenScheduleDealer();
},
/**
* validate
*/
validate: function () {
var saveTitle = $("#FNASW_ng_save_title").val();
var noteField = $("#FNASW_ng_notes").val();
if (noteField === notesDefaultInput) {
noteField = "";
}
if (saveTitle) {
NGSW.saveData.title = saveTitle.replace(/</gi, "").replace(/>/gi, "");
NGSW.saveData.notes = noteField;
NGSW.selectServiceAndCall(NGSW.saveData);
} else {
window.alert("Title field cannot be empty");
}
},
/**
* clearTextInput
* removes default value from input
*/
clearTextInput: function (e) {
var value = $(this).val();
if (value === notesDefaultInput) {
$(this).val("");
}
},
/**
* expandTextArea
* expands textarea box for user input
*/
expandTextArea: function (e) {
while ($(this).outerHeight() < this.scrollHeight + parseFloat($(this).css("borderTopWidth")) + parseFloat($(this).css("borderBottomWidth"))) {
if (parseInt($(this).height(), 10) >= 70) {
break;
} else {
$(this).height($(this).height() + 1);
}
}
},
/**
* gotoMySavedItem
*
* Invoke My Saved Items from save widget
*/
gotoMySavedItem: function () {
location.href = NextGen.baseURL + "/mysaveditems";
},
/**
* loadErrorScreen
*
* Function - Loads the ERROR Screen
*/
loadErrorScreen: function () {
NGPOP.open("Error", "#FNASW_save_auth_error_content");
},
/**
* loadMaxItemsReachedErrorScreen
*
* Loads the maximum saved item reached ERROR Screen
*/
loadMaxItemsReachedErrorScreen: function () {
var metricsData = {
channel: s.channel,
hier1: s.hier1,
evar11: s.eVar11
};
NGDCW.clickMetrics("max-saved-items", metricsData);
NGPOP.open("Maximum Saved Items", "#FNASW_save_max_item_error_content");
},
/**
* loadSuccessScreen
*
* Function - Loads the SUCCESS Screen
*/
loadSuccessScreen: function () {
var concierge = $('#FNASW_window_title').text();
if (concierge === 'Concierge') {
if (NGSW.saveData.thumbnailUrl !== "na") {
$("#FNASW_concierge_save_success_content #ng_save_item_image").attr("src", NGSW.saveData.thumbnailUrl);
}
$("#FNASW_concierge_save_success_content #FNASW_vehicle_info").html(NGSW.saveData.title);
if (NGSW.saveData.itemType === "config" || NGSW.saveData.itemType === "inventory_si" || NGSW.saveData.itemType === "inventory_bp") {
$("#FNASW_concierge_save_success_content #schedule_dealer_btn").css('display', 'block');
} else {
$("#FNASW_concierge_save_success_content #schedule_dealer_btn").css('display', 'none');
}
NGPOP.open("Concierge", "#FNASW_concierge_save_success_content");
} else {
if (NGSW.saveData.thumbnailUrl !== "na") {
$("#FNASW_save_success_content #ng_save_item_image").attr("src", NGSW.saveData.thumbnailUrl);
}
NGPOP.open("Save An Item", "#FNASW_save_success_content");
}
},
/**
* loadSaveScreen
*
* Function - Loads the SAVE Form
*/
loadSaveScreen: function (lc) {
var concierge = lc || false;
if (NGSW.saveData) {
$NextGen.trigger(NextGen.events.METRIC_TRACKER_EVENT, [NextGen.events.SAVE_STARTED, null, null, NGSW.saveData.model]);
if (NGSW.saveData.thumbnailUrl === "na") {
$("#ng_save_item_image").addClass("ng_save_item_hide_thumbnail");
} else {
$("#ng_save_item_image").attr("src", NGSW.saveData.thumbnailUrl);
}
$("#FNASW_ng_notes").val(notesDefaultInput).height(notesDefaultHeight);
//console.dir(NGSW.saveData);
$("#FNASW_ng_save_title").val(NGSW.saveData.title);
if (concierge) {
NGPOP.open("Concierge", "#FNASW_save_content");
} else {
NGPOP.open("Save An Item", "#FNASW_save_content");
}
}
},
/**
* selectServiceAndCall
*
* Selection of Respective SAVE "Services" & Invoke the "Service Caller Function"
*/
selectServiceAndCall: function (data) {
var itemType = data.itemType;
var itemID = data.id || "";
var method;
switch (itemType) {
case "config":
method = "createConfigVehicle";
break;
case "inventory_bp":
case "inventory_si":
method = "createInventoryVehicle";
break;
case "cpo":
method = "createCPOVehicle";
break;
case "image":
case "video":
case "technology":
method = "createBrandContent";
break;
case "compare":
method = "createCompareVehicle";
break;
default:
break;
}
if (!method) {
NGSW.loadErrorScreen();
return;
}
/* clone object before encoding */
data = $.extend(true, {}, data);
/* skip these keys when encoding */
var skip = ["configToken", "description", "title", "notes", "price", "competitorVehicleADescription", "competitorVehicleBDescription"];
$.each(data, function (key, value) {
if ($.inArray(key, skip) === -1) {
data[key] = encodeURIComponent(value);
}
});
if (data.title) {
data.title = encodeAndTruncate(data.title, TITLE_MAX_LENGTH);
}
if (data.notes) {
data.notes = encodeAndTruncate(data.notes, NOTE_MAX_LENGTH);
}
/* ajax callbacks */
var saveSuccess = function (data, status, jqXHR) {
var statusCode = jqXHR.status;
var model = NGSW.saveData ? NGSW.saveData.model : "";
NGSW.loadSuccessScreen();
$NextGen.trigger(NextGen.events.METRIC_TRACKER_EVENT, [NextGen.events.SAVE_ENDED, null, itemType, model]);
};
var updateSuccess = function () {
$(MySavedItems).trigger(MySavedItems.Events.DATA_REQUEST_START);
};
var saveError = function (jqXHR, type, status) {
var statusCode = jqXHR.status;
if (statusCode === 403) {
NGSW.loadMaxItemsReachedErrorScreen();
} else {
NGSW.loadErrorScreen();
}
};
var updateError = function () {
console.log("error");
};
/* call api method */
if (itemID) {
NGSAPI[method](data, updateSuccess, updateError, itemID);
} else {
NGSAPI[method](data, saveSuccess, saveError);
}
},
processData: function (data) {
/* strip html tags and disclaimers */
data.title = slashUnescape(strip(data.title));
data.description = slashUnescape(strip(data.description));
/* special encoding and truncate */
data.description = encodeAndTruncate(data.title + "||" + data.description, DESCRIPTION_MAX_LENGTH);
/* add postal code */
var zip = ngbs.u.cookie && ngbs.u.cookie.zip && ngbs.u.cookie.zip();
data.postalCode = zip || "00000";
/* add user plan type */
if (NGSW.planType) {
data.planType = NGSW.planType;
}
return data;
},
/**
* loadSaveWidget
*
* Load Save Widget and perform the Authentication internally
*/
loadSaveWidget: function (data, $target) {
var $conciergedata = $('#kill-switch-status');
var lcswitch = $conciergedata.data('status');
var make = $conciergedata.data('make').toLowerCase();
var userid = TPA.getUserId();
var provider = TPA.getProvider();
/* save reference and pass control to validation */
NGSW.saveData = NGSW.processData(data);
if (!window.ThirdPartyAuthenticator) {
return;
}
/* Integrate killswitch and swap flips for concierge */
if (lcswitch === "on" && make === 'lincoln') {
if (userid === null) {
if ($target && $target.length > 0 && $target.hasClass('lc-mobile-auth-trigger')) {
ngbs._message_bus.send(document.body, 'open-mobile-auth', {target: $target, saveData: NGSW.saveData});
} else {
Concierge.AuthWidget.openFlipForSave(NGSW.saveData);
}
} else {
if (provider === 'ANONYMOUS') {
NGAW.validateUser(NextGen.widgets.SAVE_WIDGET_NAME);
} else { // load concierge save flip
NGAW.validateUser(NextGen.widgets.SAVE_WIDGET_NAME, true);
}
}
} else {
NGAW.validateUser(NextGen.widgets.SAVE_WIDGET_NAME);
}
/* End of integration */
},
/**
* resumeSave
*
* Save Widget "Back to Action" after the Authentication completed
*/
resumeSave: function (event, isAuthenticated, userIdentity, accessCode, provider, callerWidget, lc) {
var concierge = lc || false;
if (isAuthenticated && callerWidget === NextGen.widgets.SAVE_WIDGET_NAME) {
NGSW.loadSaveScreen(concierge);
}
}
};
/* return public properties */
NGSW = new NGSW();
return NGSW;
}());
/**
* Data Collection Widget
* To Collect Data & Invoke SAVE Widget
* VIEW / Pages need to invoke and pass data here
* Works with HTML Page . FLASH / Flex web pages
* do not require it
*/
NextGen.DataCollectionWidget = (function () {
var NGAW;
var NGSW;
var NGPOP;
var TPA;
/* begin module */
var NGDCW = function () {};
/* add methods */
NGDCW.prototype = {
/**
* init
*/
init: function () {
if (!window.ThirdPartyAuthenticator) {
return;
}
TPA = new window.ThirdPartyAuthenticator();
NGAW = NextGen.AuthenticationWidget;
NGSW = NextGen.SaveWidget;
NGPOP = NextGen.SavePopupWidget;
NGDCW.bindHandlers();
NGDCW.show();
NGDCW.configMetrics();
},
/**
* show
*/
show: function () {
$(document.body).addClass("ng_save");
},
/**
* bindHandlers
*/
bindHandlers: function () {
$NextGen.bind(NextGen.events.METRIC_TRACKER_EVENT, NGDCW.metric_tracker_handler);
$NextGen.bind(NextGen.events.AUTHENTICATION_COMPLETE_EVENT, NGDCW.authenticationCompleteHandler);
$(document).delegate("a[rel=ng_save_bookmark]", "click", NGDCW.formObjectAndInvokeSave);
},
/**
* formObjectAndInvokeSave
*
* Collects Data from Anchor element & Formation of JSON Object based
* on SavedItemTypes = {"config","inventory_bp","inventory_si","cpo","image","video","technology"}
*/
formObjectAndInvokeSave: function (e) {
e.preventDefault();
var data = $(this).readDataAttr();
NGSW.loadSaveWidget(data, $(this));
},
/**
* formObjectAndUpdateItem
*
* Collects Data from MySavedItems.Page._updateItemHandler dom elements data attribute.
*/
formObjectAndUpdateItem: function (element) {
var data = $(element).parent().readDataAttr();
data.notes = $(element).parent().siblings(".msi-note-field").val();
NGSW.selectServiceAndCall(data);
},
/**
* authenticationCompleteHandler
*
* Authentication complete handler that is used only for MSI and upgrade user
* the provider value will be - GOOGLE, YAHOO, FACEBOOK, TWITTER or ANONYMOUS
*/
authenticationCompleteHandler: function (event, isAuthenticated, userIdentity, accessCode, provider, callerWidget) {
if (isAuthenticated && callerWidget === NextGen.widgets.MY_SAVED_ITEM_WIDGET_NAME) {
// my saved items auth complete
console.log(NextGen.widgets.MY_SAVED_ITEM_WIDGET_NAME);
} else if (isAuthenticated && callerWidget === NextGen.widgets.UPGRADE_USER) {
// upgrade user auth complete
console.log(NextGen.widgets.UPGRADE_USER);
}
},
/**
* metric_tracker_handler
*
* Sample event handler for metric tracker
* @params {event} the event name
* @params {event_name} type of metric event happened inside the widget
* Possible values AUTHENTICATION_STARTED, AUTHENTICATION_ENDED, SAVE_STARTED, SAVE_ENDED
* @params {provider} the provider of authentication. This value will be passed only from authentication event
* the provider value will be - GOOGLE, YAHOO, FACEBOOK, TWITTER or ANONYMOUS
* @params {itemType} related to saved item metrics - required to pass the type of item successfully saved.
* @params {model} The model
*/
metric_tracker_handler: function (event, event_name, provider, itemType, model) {
if (itemType === "config") {
itemType = "bp";
}
if (typeof model === "undefined") {
model = "";
} else if (model === "SuperDuty") { /*Fix for NG-28809, metrics model name for Super Duty*/
model = "Super Duty";
}
var metricsData = {
itemType: itemType,
channel: s.channel,
hier1: s.hier1,
evar11: s.eVar11,
evar16: model
};
switch (event_name) {
case NextGen.events.SAVE_STARTED:
NGDCW.clickMetrics("saveStarted", metricsData);
break;
case NextGen.events.SAVE_ENDED:
NGDCW.clickMetrics("saveEnded", metricsData);
break;
case NextGen.events.AUTHENTICATION_STARTED:
NGDCW.clickMetrics("authStarted", metricsData);
break;
case NextGen.events.AUTHENTICATION_ENDED:
ngbs.metrics.constructor();
var tpa = new ThirdPartyAuthenticator();
var userStat = tpa.getProfileStatus();
// This method tells, whether the profile requested or
// created already exists(-1) or succeeded(1) or failed(0).
if (userStat === "1") {
NGDCW.clickMetrics("regComplete", metricsData);
} else {
NGDCW.clickMetrics("authComplete", metricsData);
}
break;
default:
break;
}
},
/**
* configMetrics
*
* Fires click metrics
*
*/
configMetrics: function () {
var base;
var make = NextGen.make.toLowerCase();
if (make === "ford") {
base = "fv: myfolder: ";
} else {
base = "ln: myfolder: ";
}
var getItemType = function (data) {
return data.itemType;
};
var getChannel = function (data) {
return data.channel;
};
var getHier1 = function (data) {
return data.hier1;
};
var getEvar11 = function (data) {
return data.evar11;
};
var getEvar16 = function (data) {
if (data.evar16) {
return make + ' ' + data.evar16.toLowerCase();
}
return "";
};
ngbs.metrics.config({
click: {
"saveStarted": {
pe: "o",
prop5: "myfolder: start",
pev2: base + "save item: start",
channel: getChannel,
hier1: getHier1,
prop11: getEvar11,
eVar11: getEvar11,
eVar16: getEvar16,
prop16: getEvar16
},
"saveEnded": {
pe: "o",
prop5: "myfolder: complete",
pev2: base + "save item: complete",
channel: getChannel,
hier1: getHier1,
prop11: getEvar11,
eVar11: getEvar11,
eVar16: getEvar16,
prop16: getEvar16,
prop49: getItemType,
prop48: "event: save content",
eVar49: getItemType,
eVar48: "event: save content",
events: ["event43"]
},
"authStarted": {
pe: "o",
pev2: base + "login: start",
channel: getChannel,
hier1: getHier1,
prop11: getEvar11,
eVar11: getEvar11,
eVar16: getEvar16,
prop16: getEvar16,
prop42: "logged out",
eVar42: "logged out"
},
"regComplete": {
pe: "o",
pev2: base + "login: complete",
channel: getChannel,
hier1: getHier1,
prop11: getEvar11,
eVar11: getEvar11,
eVar16: getEvar16,
prop16: getEvar16,
events: ["event14", "event47"]
},
"authComplete": {
pe: "o",
pev2: base + "login: complete",
channel: getChannel,
hier1: getHier1,
prop11: getEvar11,
eVar11: getEvar11,
eVar16: getEvar16,
prop16: getEvar16,
events: ["event47"]
},
"max-saved-items": {
pe: "o",
pev2: base + "saves exceeded",
channel: getChannel,
hier1: getHier1,
prop11: getEvar11,
eVar11: getEvar11
}
}
});
},
/**
* clickMetrics
*
* Fires click metrics
*
* @param {String} clickName
* @param {Object} data
*/
clickMetrics: function (clickName, data) {
ngbs.metrics.click(clickName, data);
},
/**
* pageMetrics
*
* Fires page level metrics
*
* @param {String} pageName
* @param {Object} data
*/
pageMetrics: function (pageName, data) {
ngbs.metrics.page(pageName, data);
}
};
/* return public properties */
NGDCW = new NGDCW();
return NGDCW;
}());
/**
* NextGen.init
*
* Initialize the save and authentication widgets
* @param {Object} options Base URL and Make
*/
NextGen.init = function (options) {
if (NextGen.ready) {
return;
}
NextGen.ready = true;
NextGen.baseURL = options.baseURL;
NextGen.make = options.make;
NextGen.SaveAPI.init();
NextGen.AuthenticationWidget.init();
NextGen.SavePopupWidget.init();
NextGen.SaveWidget.init();
NextGen.DataCollectionWidget.init();
};
$(document).ready(function () {
var $widget = null;
var baseURL;
var make;
// check for auth widget until it is loaded
var interval = window.setInterval(function () {
$widget = $("#nextgen_auth_save_widget_container");
if ($widget.length) {
window.clearInterval(interval);
baseURL = $widget.data("baseUrl");
make = $widget.data("make");
NextGen.init({
baseURL: baseURL,
make: make
});
ngbs._message_bus.listen(document.body, 'lc-init', function () {
ngbs._message_bus.send(document.body, 'nextgen-loaded');
});
}
}, 100);
if ($("#fallback_ok_btn").length) {
NextGen.FallbackWidget.init();
NextGen.FallbackWidget.hideConciergeButton();
}
});
}(window, jQuery, ngbs));
/*global ngbs*/
(function (ngbs) {
'use strict';
if (!ngbs.u) {
return;
}
/**
* @class ngbs.u.anchor
* ngbs.u.anchor - A URL parsing utility
*
* @usage
* var a = ngbs.u.anchor("http://www.example.com?fruit=banana&pie=apple#page=1");
* a.href(); // "http://www.example.com?fruit=banana&pie=apple#page=1";
* a.search(); // "?fruit=banana&pie=apple"
* a.hash(); // "#page=1"
*
* a.getSearchVars(); // {"fruit": "banana", "pie": "apple"}
* a.getHashVars(); // {"page": "1"}
*
* a.setSearchVars({fruit: "pear", type: "test"});
* a.href(); // "http://www.example.com/?fruit=pear&pie=apple&type=test#page=1"
*
* a.setHashVars({page: 2});
* a.href(); // "http://www.example.com/?fruit=pear&pie=apple&type=test#page=2"
*
* a.setSearchVar("type", "live");
* a.href(); // "http://www.example.com/?fruit=pear&pie=apple&type=live#page=2"
*
* a.setHashVar("page", 3);
* a.href(); // "http://www.example.com/?fruit=pear&pie=apple&type=live#page=3"
*
* a.delSearchVar("type");
* a.href(); // "http://www.example.com/?fruit=pear&pie=apple#page=3"
*
* a.delHashVar("page");
* a.href(); // "http://www.example.com/?fruit=pear&pie=apple#"
*
* var q = ngbs.u.getQuery(); // Duplicates functionality of ngbs.u.getQuery
*/
ngbs.u.anchor = (function (window, document, location) {
/**
* isObject
* Type check
* @private
* @return {Boolean}
*/
var isObject = function (o) {
return typeof o === "object" && o !== null;
};
/**
* isArray
* Type check
* @private
* @return {Boolean}
*/
var isArray = function (o) {
return Object.prototype.toString.call(o) === "[object Array]";
};
/**
* extend
* Object extend
* @private
* @return {Object}
*/
var extend = function (o, o2) {
var args = Array.prototype.slice.call(arguments, 2),
i;
for (i in o2) {
if (o2.hasOwnProperty(i)) {
o[i] = o2[i];
}
}
if (args.length) {
args.unshift(o);
extend.apply(this, args);
}
return o;
};
/**
* append
* Append a key-value pair to an object
* @private
*/
var append = function (o, key, val) {
if (isObject(o) && o.hasOwnProperty(key)) {
if (isArray(o[key])) {
o[key].push(val);
} else {
o[key] = [o[key], val];
}
} else {
o[key] = val;
}
};
/**
* stringify
* Turn a key value pair into a string
* @private
* @return {String}
*/
var stringify = function (key, val, eq, sep) {
var i, l, s = "";
if (isArray(val)) {
for (i = 0, l = val.length; i < l; i++) {
s += sep + key + eq + val[i];
}
} else {
s += sep + key + eq + val;
}
return s;
};
/**
* update
* Update the value of a key
* @private
*/
var update = function (o, key, val) {
if (isObject(o)) {
if (typeof val === "undefined") {
delete o[key];
} else {
o[key] = val;
}
}
};
/**
* Private methods to add to the Anchor prototype
* @lends Anchor
* @private
*/
var privateMethods = {
/**
* toObject_
* Turn a search or hash into an object
* @private
* @param {String} type Either "search" or "hash"
* @return {Object}
*/
toObject_: function (type) {
var str, eq, sep, list, map, i, l, pair;
if (type === "search") {
str = this.anchor.search.replace(/^\?/, "");
eq = this.sass;
sep = this.ssep;
} else {
str = this.anchor.hash.replace(/^\#/, "");
eq = this.hass;
sep = this.hsep;
}
list = str.split(sep);
map = {};
for (i = 0, l = list.length; i < l; i++) {
pair = list[i].split(eq);
if (pair[0] !== "") {
append(map, pair[0], pair[1]);
}
}
return map;
},
/**
* toString_
* Turn an object into a str for search or hash
* @private
* @param {String} type Either "search" or "hash"
* @param {Object} map Key-value map of parameters
* @return {String}
*/
toString_: function (type, map) {
var str = "", eq, sep, i;
if (type === "search") {
eq = this.sass;
sep = this.ssep;
} else {
eq = this.hass;
sep = this.hsep;
}
for (i in map) {
if (map.hasOwnProperty(i)) {
str += stringify(i, map[i], eq, sep);
}
}
return str.replace(new RegExp("^\\" + sep), "");
},
/**
* getUrlVars_
* Get search and hash vars
* @private
* @param {String} type Either "search" or "hash"
* @return {Object}
*/
getUrlVars_: function (type) {
var vars;
vars = {
search: this.toObject_("search"),
hash: this.toObject_("hash")
};
return type ? vars[type] : vars;
},
/**
* setUrlVars_
* Set search and hash vars
* @private
* @param {String} type Either "search" or "hash"
* @param {Object} map Key-value map of parameters
* @return {Anchor}
*/
setUrlVars_: function (type, map) {
var vars = this.getUrlVars_(type),
i;
for (i in map) {
if (map.hasOwnProperty(i)) {
update(vars, i, map[i]);
}
}
return this.toString_(type, vars);
}
};
/**
* Public methods to add to the Anchor prototype
* @lends Anchor
* @ignore
*/
var publicMethods = {
/**
* getSearchVars
* Return a key-value object with the parameters in the URL search
* @return {Object}
*/
getSearchVars: function () {
return this.getUrlVars_("search");
},
/**
* getHashVars
* Return a key-value object with the parameters in the URL hash
* @return {Object}
*/
getHashVars: function () {
return this.getUrlVars_("hash");
},
/**
* getUrlVars
* Return combined url variables
* @return {Object}
*/
getUrlVars: function () {
var vars = this.getUrlVars_(),
search = vars.search,
hash = vars.hash,
combined = extend(search, hash);
return combined;
},
/**
* setSearchVars
* Sets parameters using a key-value object in the URL search; returns this
* @param {Object} map The key-value object
* @return {Anchor}
*/
setSearchVars: function (map) {
this.anchor.search = this.setUrlVars_("search", map);
return this;
},
/**
* setSearchVar
* Sets the key parameter to val in the URL search; returns this
* @param {String} key The name of the parameter
* @param {String} val The value of the parameter
* @return {Anchor}
*/
setSearchVar: function (key, val) {
var o = {};
o[key] = val;
return this.setSearchVars(o);
},
/**
* setHashVars
* Sets parameters using a key-value object in the URL hash; returns this
* @param {Object} map The key-value object
* @return {Anchor}
*/
setHashVars: function (map) {
this.anchor.hash = this.setUrlVars_("hash", map);
return this;
},
/**
* setHashVar
* Sets the key parameter to val in the URL hash; returns this
* @param {String} key The name of the parameter
* @param {String} val The value of the parameter
* @return {Anchor}
*/
setHashVar: function (key, val) {
var o = {};
o[key] = val;
return this.setHashVars(o);
},
/**
* delSearchVar
* Deletes the key parameter from the URL search; returns this
* @param {String} key The name of the parameter
* @return {Anchor}
*/
delSearchVar: function (key) {
return this.setSearchVar(key);
},
/**
* delHashVar
* Deletes the key parameter from the URL hash; returns this
* @param {String} key The name of the parameter
* @return {Anchor}
*/
delHashVar: function (key) {
return this.setHashVar(key);
},
/**
* toString
* Used for type coercion of Anchor instance to string
* @return {String}
*/
toString: function () {
return this.anchor.href;
}
};
/**
* nativeGetter
* Returns a get method that aliases a native anchor property
* @private
* @param {String} prop The property name
* @return {Function}
*/
var nativeGetter = function (prop) {
return function () {
return this.anchor[prop];
};
};
// Native get methods to add to the Anchor prototype
var nativeMethods = (function () {
var methods = {}, props, prop, i, l;
props = ["href", "protocol", "host", "hostname", "port", "pathname", "search", "hash"];
for (i = 0, l = props.length; i < l; i++) {
prop = props[i];
methods[prop] = nativeGetter(prop);
}
return methods;
}());
// regular expression URL test for protocol
var regexP = /^(http|https|ftp):/;
/**
* @class ngbs.u.anchor
* @constructor
* Constructor and prototype
* @param {String} href
* @param {String} [searchAss] Optional search assignment operator; default of "="
* @param {String} [searchSep] Optional search separator operator; default of "&"
* @param {String} [hashAss] Optional hash assignment operator; default of "="
* @param {String} [hashSep] Optional hash separator operator; default of "&"
* @return {Anchor}
*/
var Anchor = function (href, /* optional */ searchAss, searchSep, hashAss, hashSep) {
if (typeof href === "undefined" || href === "") {
throw new Error("The href argument must be defined and non-empty.");
}
this.anchor = this.a = document.createElement("a");
this.anchor.href = href;
// this forces the anchor to fill out the full path
if (!regexP.test(this.anchor.protocol)) {
this.anchor.protocol = location.protocol;
}
if (!this.anchor.hostname) {
this.anchor.hostname = location.hostname;
}
this.sass = searchAss || "=";
this.ssep = searchSep || "&";
this.hass = hashAss || "=";
this.hsep = hashSep || "&";
};
Anchor.prototype = extend({}, nativeMethods, privateMethods, publicMethods);
/**
* Anchor.factory
* Create an Anchor instance
* @return {Anchor}
*/
Anchor.factory = function (href, /* optional */ searchAss, searchSep, hashAss, hashSep) {
return new Anchor(href, searchAss, searchSep, hashAss, hashSep);
};
/**
* Anchor.getQuery
* Duplicates functionality of ngbs.u.getQuery
* @param {String|Array|Undefined} key The parameter name, or an array of names, or undefined for all values
* @return {String|Object|Boolean}
*/
Anchor.factory.getQuery = function (key) {
var href = location.href,
t = new Anchor(href),
vars = t.getUrlVars(),
result = {},
l;
if (typeof key === "string" && vars[key]) {
return vars[key];
}
if (isArray(key)) {
l = key.length;
while (l--) {
result[key[l]] = false;
if (vars[key[l]]) {
result[key[l]] = vars[key[l]];
}
}
return result;
}
if (typeof key === "undefined") {
return vars;
}
return false;
};
// return the factory method for ngbs.u.anchor
return Anchor.factory;
}(window, document, location));
ngbs.u.getQuery = function () {
if (window.console && window.console.warn) {
window.console.warn('ngbs.u.getQuery is deprecated, please use ngbs.u.anchor');
}
ngbs.u.anchor.getQuery.apply(null, arguments);
};
}(ngbs));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment