How can I delete Items from json string without using $.grep - javascript

I have a cart variable and I am storing the cart inside it like this.
[{"course_id":"24","doc_id":"211","doc_title":"PDF Notes","doc_price":"500"},{"course_id":"25","doc_id":"217","doc_title":"PDF Notes","doc_price":"500"},{"course_id":"25","doc_id":"218","doc_title":"PDF Solved Past Papers","doc_price":"500"},{"course_id":"26","doc_id":"224","doc_title":"PDF Solved Past Papers","doc_price":"595"}]
I created a RemoveFromCart function. It works in simple JQUERY But it is not working in Framework 7 because of $.grep. Is there any other way I can do it without using $.grep?
This is my Function
function removeFromCart(course_id, doc_id) {
var x = confirm("Are you sure you want to remove this item from your cart?");
if (x) {
$$('#cart_body').html('');
existing_cart = localStorage.getItem("cart");
if (existing_cart == '') {
existing_cart = [];
} else {
existing_cart = JSON.parse(existing_cart);
}
existing_cart = $.grep(existing_cart, function (data, index) {
return data.doc_id != doc_id
});
ex_cart = JSON.stringify(existing_cart);
localStorage.setItem('cart', ex_cart);
existing_cart = localStorage.getItem("cart");
if (existing_cart == '') {
existing_cart = [];
} else {
existing_cart = JSON.parse(existing_cart);
}
if (existing_cart !== null && existing_cart.length > 0) {
var total = '';
$$('#cart_div').show();
existing_cart.forEach(function (arrayItem) {
var text = '';
text = '<li class="item-content"><div class="item-inner"><div class="item-title">' + arrayItem.doc_title + '</div><div class="item-after">' + arrayItem.course_id + '</div><div class="item-after">' + arrayItem.doc_price + '</div><div class="item-after"><i class="icon icon-cross" onclick="removeFromCart(' + arrayItem.course_id + ',' + arrayItem.doc_id + ')"></i></div></div></li>';
total = Number(total) + Number(arrayItem.doc_price);
$$('#cart_body').append(text);
});
text = '<tr><td></td><td class="text-center"><b>Total: </b></td><td class="text-center">' + total + '</td><td></td></tr>';
$$('#cart_body').append(text);
} else {
$$('#cart_div').hide();
text = '<p>Your cart is empty.</p>';
$$('#cart_body').append(text);
}
} else {
return false;
}
}

Instead of:
$.grep(existing_cart, function ...
You can use:
existing_cart.filter(function ...

var new_courses = existing_cart.map( v=> {
if(v.doc_id != doc_id)
return v
}).filter( v=> {return v})
// new_courses does not contain the course with doc_id
map loops through each member of an array. filter removes members not returned in map.

Related

want to display duplicate ranks selected along with exactly which ranks are duplicated using javascript/ jquery

Here we added the logic to display which ranks are duplicated but I also want to display exactly which rank is duplicated. Ranks are from 0 to 18.
function validate(sdd_ejrp_form)
{
var duplicateRanksDetected = false;
var validate_rank_str = ",";
jq("\[data-dom-id=gsc-containers\]").find("\[data-dom-id=gsc-container\]").each(function (index)
{ var jqThis = jq(this);
var gsc_uri = jqThis.attr("data-gsc-data-gsc-uri");
var prof_lvl_rank = jqThis.find("select\[name='prof-lvl-rank'\]").val();
jqThis.find("\[data-dom-id=proficiency-level\]").each(function (index2)
{
var btn = jq(this);
if (btn.hasClass("active"))
{
if (validate_rank_str.indexOf("," + prof_lvl_rank + ",") != -1)
{
duplicateRanksDetected = true;
return false;
} else
{
validate_rank_str += prof_lvl_rank + ",";
}
}
});
});
if (duplicateRanksDetected == true)
{
// here I want to display exactly which rank is duplicated
alert("Duplicate ranks detected!");
return false;
}
}
}
It's easy as 3 modifications:
function validate(sdd_ejrp_form) {
var duplicateRanksDetected = []; //create an array here
var validate_rank_str = ",";
jq("\[data-dom-id=gsc-containers\]").find("\[data-dom-id=gsc-container\]").each(function(index) {
var jqThis = jq(this);
var gsc_uri = jqThis.attr("data-gsc-data-gsc-uri");
var prof_lvl_rank = jqThis.find("select\[name='prof-lvl-rank'\]").val();
jqThis.find("\[data-dom-id=proficiency-level\]").each(function(index2) {
var btn = jq(this);
if (btn.hasClass("active")) {
if (validate_rank_str.indexOf("," + prof_lvl_rank + ",") != -1) {
duplicateRanksDetected.push(prof_lvl_rank); // fill the array here
return false;
} else {
validate_rank_str += prof_lvl_rank + ",";
}
}
});
});
if (duplicateRanksDetected.length > 0) {
// here I want to display exactly which rank is duplicated
alert(
"Duplicate ranks detected: " +
duplicateRanksDetected.join(', ') // display the result here
);
return false;
}
}

element null in Magento

I upgrade magento from 1.8.1 to 1.9.0, and I have a problem with one js file:
TypeError: $(...) is null
$('product_addtocart_form').getElements().each(function(el) {
simple_product_pricing.js (line 1131, col 5)
I think this file is related to the Ayasoftware_SimpleProductPricing, maybe someone can help me to solve this. Before upgrade in 1.8.1 version everything was fine, in 1.9.0 version I have this error.
I will add here the entire js:
/*
Some of these override earlier varien/product.js methods, therefore
varien/product.js must have been included prior to this file.
some of these functions were initially written by Matt Dean ( http://organicinternet.co.uk/ )
*/
Product.Config.prototype.getMatchingSimpleProduct = function(){
var inScopeProductIds = this.getInScopeProductIds();
if ((typeof inScopeProductIds != 'undefined') && (inScopeProductIds.length == 1)) {
return inScopeProductIds[0];
}
return false;
};
/*
Find products which are within consideration based on user's selection of
config options so far
Returns a normal array containing product ids
allowedProducts is a normal numeric array containing product ids.
childProducts is a hash keyed on product id
optionalAllowedProducts lets you pass a set of products to restrict by,
in addition to just using the ones already selected by the user
*/
Product.Config.prototype.getInScopeProductIds = function(optionalAllowedProducts) {
var childProducts = this.config.childProducts;
var allowedProducts = [];
if ((typeof optionalAllowedProducts != 'undefined') && (optionalAllowedProducts.length > 0)) {
allowedProducts = optionalAllowedProducts;
}
for(var s=0, len=this.settings.length-1; s<=len; s++) {
if (this.settings[s].selectedIndex <= 0){
break;
}
var selected = this.settings[s].options[this.settings[s].selectedIndex];
if (s==0 && allowedProducts.length == 0){
allowedProducts = selected.config.allowedProducts;
} else {
allowedProducts = allowedProducts.intersect(selected.config.allowedProducts).uniq();
}
}
//If we can't find any products (because nothing's been selected most likely)
//then just use all product ids.
if ((typeof allowedProducts == 'undefined') || (allowedProducts.length == 0)) {
productIds = Object.keys(childProducts);
} else {
productIds = allowedProducts;
}
return productIds;
};
Product.Config.prototype.getProductIdOfCheapestProductInScope = function(priceType, optionalAllowedProducts) {
var childProducts = this.config.childProducts;
var productIds = this.getInScopeProductIds(optionalAllowedProducts);
var minPrice = Infinity;
var lowestPricedProdId = false;
//Get lowest price from product ids.
for (var x=0, len=productIds.length; x<len; ++x) {
var thisPrice = Number(childProducts[productIds[x]][priceType]);
if (thisPrice < minPrice) {
minPrice = thisPrice;
lowestPricedProdId = productIds[x];
}
}
return lowestPricedProdId;
};
Product.Config.prototype.getProductIdOfMostExpensiveProductInScope = function(priceType, optionalAllowedProducts) {
var childProducts = this.config.childProducts;
var productIds = this.getInScopeProductIds(optionalAllowedProducts);
var maxPrice = 0;
var highestPricedProdId = false;
//Get highest price from product ids.
for (var x=0, len=productIds.length; x<len; ++x) {
var thisPrice = Number(childProducts[productIds[x]][priceType]);
if (thisPrice >= maxPrice) {
maxPrice = thisPrice;
highestPricedProdId = productIds[x];
}
}
return highestPricedProdId;
};
Product.OptionsPrice.prototype.updateSpecialPriceDisplay = function(price, finalPrice) {
var prodForm = $('product_addtocart_form');
jQuery('p.msg').hide();
jQuery('div.price-box').show();
var specialPriceBox = prodForm.select('p.special-price');
var oldPricePriceBox = prodForm.select('p.old-price, p.was-old-price');
var magentopriceLabel = prodForm.select('span.price-label');
if (price == finalPrice) {
//specialPriceBox.each(function(x) {x.hide();});
magentopriceLabel.each(function(x) {x.hide();});
oldPricePriceBox.each(function(x) { x.hide();
// x.removeClassName('old-price');
// x.addClassName('was-old-price');
});
jQuery('.product-shop').removeClass('sale-product') ;
}else{
specialPriceBox.each(function(x) {x.show();});
magentopriceLabel.each(function(x) {x.show();});
oldPricePriceBox.each(function(x) { x.show();
x.removeClassName('was-old-price');
x.addClassName('old-price');
});
jQuery('.product-shop').addClass('sale-product') ;
}
};
//This triggers reload of price and other elements that can change
//once all options are selected
Product.Config.prototype.reloadPrice = function() {
var childProductId = this.getMatchingSimpleProduct();
var childProducts = this.config.childProducts;
var usingZoomer = false;
if(this.config.imageZoomer){
usingZoomer = true;
}
if(childProductId){
var price = childProducts[childProductId]["price"];
var finalPrice = childProducts[childProductId]["finalPrice"];
optionsPrice.productPrice = finalPrice;
optionsPrice.productOldPrice = price;
optionsPrice.reload();
optionsPrice.reloadPriceLabels(true);
optionsPrice.updateSpecialPriceDisplay(price, finalPrice);
if(this.config.updateShortDescription) {
this.updateProductShortDescription(childProductId);
}
if(this.config.updateDescription) {
this.updateProductDescription(childProductId);
}
if(this.config.updateProductName) {
this.updateProductName(childProductId);
}
if(this.config.customStockDisplay) {
this.updateProductAvailability(childProductId);
}
this.showTierPricingBlock(childProductId, this.config.productId);
if (usingZoomer) {
this.showFullImageDiv(childProductId, this.config.productId);
} else {
if(this.config.updateproductimage) {
this.updateProductImage(childProductId);
}
}
} else {
var cheapestPid = this.getProductIdOfCheapestProductInScope("finalPrice");
var price = childProducts[cheapestPid]["price"];
var finalPrice = childProducts[cheapestPid]["finalPrice"];
optionsPrice.productPrice = finalPrice;
optionsPrice.productOldPrice = price;
optionsPrice.reload();
optionsPrice.reloadPriceLabels(false);
if(this.config.updateProductName) {
this.updateProductName(false);
}
if(this.config.updateShortDescription) {
this.updateProductShortDescription(false);
}
if(this.config.updateDescription) {
this.updateProductDescription(false);
}
if(this.config.customStockDisplay) {
this.updateProductAvailability(false);
}
optionsPrice.updateSpecialPriceDisplay(price, finalPrice);
this.showTierPricingBlock(false);
this.showCustomOptionsBlock(false, false);
if (usingZoomer) {
this.showFullImageDiv(false, false);
} else {
if(this.config.updateproductimage) {
this.updateProductImage(false);
}
}
}
};
Product.Config.prototype.updateProductImage = function(productId) {
var imageUrl = this.config.imageUrl;
if(productId && this.config.childProducts[productId].imageUrl) {
imageUrl = this.config.childProducts[productId].imageUrl;
}
if (!imageUrl) {
return;
}
if($('image')) {
$('image').src = imageUrl;
} else {
$$('#product_addtocart_form p.product-image img').each(function(el) {
var dims = el.getDimensions();
el.src = imageUrl;
el.width = dims.width;
el.height = dims.height;
});
}
};
Product.Config.prototype.updateProductName = function(productId) {
var productName = this.config.productName;
if (productId && this.config.ProductNames[productId].ProductName) {
productName = this.config.ProductNames[productId].ProductName;
}
$$('#product_addtocart_form div.product-name h1').each(function(el) {
el.innerHTML = productName;
});
var productSku = this.config.sku ;
if (productId && this.config.childProducts[productId].sku) {
productSku = this.config.childProducts[productId].sku ;
}
jQuery('.sku span').text(productSku) ;
var productDelivery = this.config.delivery;
if (productId && this.config.childProducts[productId].delivery) {
productDelivery = this.config.childProducts[productId].delivery ;
}
jQuery('.delivery-info').html(productDelivery) ;
var productReturns = this.config.returns;
if (productId && this.config.childProducts[productId].returns) {
productReturns = this.config.childProducts[productId].returns ;
}
jQuery('.returns-info').html(productReturns) ;
var productDownloads = this.config.downloads;
if (productId && this.config.childProducts[productId].downloads) {
productDownloads = this.config.childProducts[productId].downloads;
}
if (productDownloads) jQuery('.downloads-info').html(productDownloads) ;
else jQuery('.downloads-info').html('There are no downloads for this product') ;
var productAttribs = this.config.attributesTable;
if (productId && this.config.childProducts[productId].attributesTable) {
productAttribs = this.config.childProducts[productId].attributesTable ;
}
jQuery('.attribs-info').html(productAttribs) ;
decorateTable('product-attribute-specs-table') ;
if (productId && this.config.childProducts[productId].isNew) {
jQuery('.product-image .new-label').show() ;
} else {
jQuery('.product-image .new-label').hide() ;
}
if (productId && this.config.childProducts[productId].isOnSale) {
jQuery('.product-image .sale-label').show() ;
} else {
jQuery('.product-image .sale-label').hide() ;
}
if (productId) jQuery('input[name="pid"]').val(productId) ;
};
Product.Config.prototype.updateProductAvailability = function(productId) {
var stockInfo = this.config.stockInfo;
var is_in_stock = false;
var stockLabel = '';
if (productId && stockInfo[productId]["stockLabel"]) {
stockLabel = stockInfo[productId]["stockLabel"];
stockQty = stockInfo[productId]["stockQty"];
is_in_stock = stockInfo[productId]["is_in_stock"];
}
$$('#product_addtocart_form p.availability span').each(function(el) {
if(is_in_stock) {
$$('#product_addtocart_form p.availability').each(function(es) {
es.removeClassName('availability out-of-stock');
es.addClassName('availability in-stock');
});
el.innerHTML = /*stockQty + ' ' + */stockLabel;
} else {
$$('#product_addtocart_form p.availability').each(function(ef) {
ef.removeClassName('availability in-stock');
ef.addClassName('availability out-of-stock');
});
el.innerHTML = stockLabel;
}
});
};
Product.Config.prototype.updateProductShortDescription = function(productId) {
var shortDescription = this.config.shortDescription;
if (productId && this.config.shortDescriptions[productId].shortDescription) {
shortDescription = this.config.shortDescriptions[productId].shortDescription;
}
$$('#product_addtocart_form div.short-description div.std').each(function(el) {
el.innerHTML = shortDescription;
});
};
Product.Config.prototype.updateProductDescription = function(productId) {
var description = this.config.description;
if (productId && this.config.Descriptions[productId].Description) {
description = this.config.Descriptions[productId].Description;
}
$$('#product_tabs_description_tabbed_contents div.std').each(function(el) {
el.innerHTML = description;
});
};
Product.Config.prototype.updateProductAttributes = function(productId) {
var productAttributes = this.config.productAttributes;
if (productId && this.config.childProducts[productId].productAttributes) {
productAttributes = this.config.childProducts[productId].productAttributes;
}
//If config product doesn't already have an additional information section,
//it won't be shown for associated product either. It's too hard to work out
//where to place it given that different themes use very different html here
console.log(productAttributes) ;
$$('div.product-collateral div.attribs-info').each(function(el) {
el.innerHTML = productAttributes;
decorateTable('product-attribute-specs-table');
});
};
Product.Config.prototype.showCustomOptionsBlock = function(productId, parentId) {
var coUrl = this.config.ajaxBaseUrl + "co/?id=" + productId + '&pid=' + parentId;
var prodForm = $('product_addtocart_form');
if ($('SCPcustomOptionsDiv')==null) {
return;
}
Effect.Fade('SCPcustomOptionsDiv', { duration: 0.5, from: 1, to: 0.5 });
if(productId) {
//Uncomment the line below if you want an ajax loader to appear while any custom
//options are being loaded.
//$$('span.scp-please-wait').each(function(el) {el.show()});
//prodForm.getElements().each(function(el) {el.disable()});
new Ajax.Updater('SCPcustomOptionsDiv', coUrl, {
method: 'get',
evalScripts: true,
onComplete: function() {
$$('span.scp-please-wait').each(function(el) {el.hide()});
Effect.Fade('SCPcustomOptionsDiv', { duration: 0.5, from: 0.5, to: 1 });
//prodForm.getElements().each(function(el) {el.enable()});
}
});
} else {
$('SCPcustomOptionsDiv').innerHTML = '';
try{window.opConfig = new Product.Options([]);} catch(e){}
}
};
Product.OptionsPrice.prototype.reloadPriceLabels = function(productPriceIsKnown) {
var priceFromLabel = '';
var prodForm = $('product_addtocart_form');
if (!productPriceIsKnown && typeof spConfig != "undefined") {
priceFromLabel = spConfig.config.priceFromLabel;
}
var priceSpanId = 'configurable-price-from-' + this.productId;
var duplicatePriceSpanId = priceSpanId + this.duplicateIdSuffix;
if($(priceSpanId) && $(priceSpanId).select('span.configurable-price-from-label'))
$(priceSpanId).select('span.configurable-price-from-label').each(function(label) {
label.innerHTML = priceFromLabel;
});
if ($(duplicatePriceSpanId) && $(duplicatePriceSpanId).select('span.configurable-price-from-label')) {
$(duplicatePriceSpanId).select('span.configurable-price-from-label').each(function(label) {
label.innerHTML = priceFromLabel;
});
}
};
//SCP: Forces the 'next' element to have it's optionLabels reloaded too
Product.Config.prototype.configureElement = function(element) {
this.reloadOptionLabels(element);
if(element.value){
this.state[element.config.id] = element.value;
if(element.nextSetting){
element.nextSetting.disabled = false;
this.fillSelect(element.nextSetting);
this.reloadOptionLabels(element.nextSetting);
this.resetChildren(element.nextSetting);
}
}
else {
this.resetChildren(element);
}
this.reloadPrice();
};
//SCP: Changed logic to use absolute price ranges rather than price differentials
Product.Config.prototype.reloadOptionLabels = function(element){
var selectedPrice;
var childProducts = this.config.childProducts;
var stockInfo = this.config.stockInfo;
//Don't update elements that have a selected option
if(element.options[element.selectedIndex].config){
return;
}
for(var i=0;i<element.options.length;i++){
if(element.options[i].config){
var cheapestPid = this.getProductIdOfCheapestProductInScope("finalPrice", element.options[i].config.allowedProducts);
var mostExpensivePid = this.getProductIdOfMostExpensiveProductInScope("finalPrice", element.options[i].config.allowedProducts);
var cheapestFinalPrice = childProducts[cheapestPid]["finalPrice"];
var mostExpensiveFinalPrice = childProducts[mostExpensivePid]["finalPrice"];
var stock = '';
if(cheapestPid == mostExpensivePid ){
if(stockInfo[cheapestPid]["stockLabel"] != '') {
stock = '( ' +stockInfo[cheapestPid]["stockLabel"] + ' )';
}
}
if (this.config.showOutOfStock){
if(this.config.disable_out_of_stock_option ) {
if(!stockInfo[cheapestPid]["is_in_stock"] ) {
if(cheapestPid == mostExpensivePid ){
element.options[i].disabled=true;
var stock = '( ' +stockInfo[cheapestPid]["stockLabel"] + ' )';
}
}
}
}
var tierpricing = childProducts[mostExpensivePid]["tierpricing"];
element.options[i].text = this.getOptionLabel(element.options[i].config, cheapestFinalPrice, mostExpensiveFinalPrice, stock , tierpricing);
}
}
};
Product.Config.prototype.showTierPricingBlock = function(productId, parentId) {
var coUrl = this.config.ajaxBaseUrl + "co/?id=" + productId + '&pid=' + parentId;
var prodForm = $('product_addtocart_form');
if(productId) {
new Ajax.Updater('sppTierPricingDiv', coUrl, {
method: 'get',
evalScripts: true,
onComplete: function() {
$$('span.scp-please-wait').each(function(el) {el.hide()});
}
});
} else {
$('sppTierPricingDiv').innerHTML = '';
}
};
//SCP: Changed label formatting to show absolute price ranges rather than price differentials
Product.Config.prototype.getOptionLabel = function(option, lowPrice, highPrice, stock, tierpricing){
var str = option.label;
if(tierpricing > 0 && tierpricing < lowPrice) {
var tierpricinglowestprice = ': As low as (' + this.formatPrice(tierpricing,false) + ')';
} else {
var tierpricinglowestprice = '';
}
if (!this.config.showPriceRangesInOptions) {
return str;
}
if (!this.config.showOutOfStock){
stock = '';
}
lowPrices = this.getTaxPrices(lowPrice);
highPrices = this.getTaxPrices(highPrice);
if (this.config.hideprices) {
if (this.config.showOutOfStock){
return str + ' ' + stock + ' ';
} else {
return str;
}
}
var to = ' ' + this.config.rangeToLabel + ' ';
var separator = ': ( ';
if(lowPrice && highPrice){
if (this.config.showfromprice) {
this.config.priceFromLabel = this.config.priceFromLabel; //'From: ';
}
if (lowPrice != highPrice) {
if (this.taxConfig.showBothPrices) {
str+= separator + this.formatPrice(lowPrices[2], false) + ' (' + this.formatPrice(lowPrices[1], false) + ' ' + this.taxConfig.inclTaxTitle.replace('Tax','VAT') + ')';
str+= to + this.formatPrice(highPrices[2], false) + ' (' + this.formatPrice(highPrices[1], false) + ' ' + this.taxConfig.inclTaxTitle.replace('Tax','VAT') + ')';
str += " ) ";
} else {
str+= separator + this.formatPrice(lowPrices[0], false);
str+= to + this.formatPrice(highPrices[0], false);
str += " ) ";
}
} else {
if (this.taxConfig.showBothPrices) {
str+= separator + this.formatPrice(lowPrices[2], false) + ' (' + this.formatPrice(lowPrices[1], false) + ' ' + this.taxConfig.inclTaxTitle.replace('Tax','VAT') + ')';
str += " ) ";
str += stock;
str += tierpricinglowestprice;
} else {
if(tierpricing == 0 ) {
str+= separator + this.formatPrice(lowPrices[0], false);
str += " ) ";
}
str += tierpricinglowestprice;
str += ' ' + stock;
}
}
}
return str;
};
//SCP: Refactored price calculations into separate function
Product.Config.prototype.getTaxPrices = function(price) {
var price = parseFloat(price);
if (this.taxConfig.includeTax) {
var tax = price / (100 + this.taxConfig.defaultTax) * this.taxConfig.defaultTax;
var excl = price - tax;
var incl = excl*(1+(this.taxConfig.currentTax/100));
} else {
var tax = price * (this.taxConfig.currentTax / 100);
var excl = price;
var incl = excl + tax;
}
if (this.taxConfig.showIncludeTax || this.taxConfig.showBothPrices) {
price = incl;
} else {
price = excl;
}
return [price, incl, excl];
};
//SCP: Forces price labels to be updated on load
//so that first select shows ranges from the start
document.observe("dom:loaded", function() {
//Really only needs to be the first element that has configureElement set on it,
//rather than all.
if (typeof opConfig != "undefined") {
spConfig.reloadPrice();
}
$('product_addtocart_form').getElements().each(function(el) {
if(el.type == 'select-one') {
if(el.options && (el.options.length > 1)) {
el.options[0].selected = true;
spConfig.reloadOptionLabels(el);
}
}
});
});
Thank you
The version 1.5.11 is not compatible w/ Magento 1.9 according to the extension version on Magento connect. Please obtain the newest version of the extension and/or ask the creator to give you support. As far as I can see 1.9 support is support with 1.11.6, released 11th March 2015. The infos on their homepage and Magento connect are different - not good. On the homepage it says Works with Magento 1.9.0.X . tested 15 May 2014.

Custom JQuery dynamic link creation

I'm pretty new to js and having a hard time figuring out the best way to generate a custom url depending on what links are selected. You can view what I have done here. http://jsfiddle.net/1fz50z1y/26/ I will also paste my info here.
var products = [];
var quantity = [];
qstring = '';
$('input.product-radio, select.products-howmany').change(function() {
var $this = $(this)
var $product = $(this).closest('.product-options-left');
var $radio = $product.find('input.product-radio');
var $select = $product.find('select.products-howmany')
var qid = $select.val();
var pid = $radio.val();
currentStatus = $radio.prop('checked'),
theString = '';
qString = '';
pString = '';
if (currentStatus) {
products.push(pid);
quantity.push(qid);
if ($product.find('div.quantity').removeClass('q-hidden')) {
//code
}
} else {
products.splice(products.indexOf(pid), 1);
quantity.splice(quantity.indexOf(qid), 1);
$product.find('div.quantity').addClass('q-hidden');
}
if ((products.length > -1) || (quantity.length > -1)) {
if ((products.length === 0) || (quantity.length === 0)) {
console.log("Q Length: " + quantity.length);
pString += products[0];
qString += quantity[0];
console.log("qString = " + quantity);
} else {
pString = products.join('-p');
qString = quantity.join('_q');
if (quantity.length > 1) {
qString = quantity.splice(quantity.indexOf(qid), 1);
pString = products.splice(products.indexOf(pid), 1);
}
console.log("+ Q Length: " + quantity.length);
console.log("ADDING " + "p" + pString + "_q" + qString);
}
if ((qString == 'undefined') || (pString == 'undefined')) {
$('a.options-cart').prop("href", "#");
} else {
//$('a.options-cart').prop("href", "/cart/add/p" + theString + "_q" + qstring + "?destination=/cart");
//$('a.options-cart').prop("href", "/cart/add/p" + theString + "?destination=/cart");
$('a.options-cart').prop("href", "/cart/add/p" + pString + "_q" + qString + "?destination=/cart");
}
}
});
$('a.options-cart').click(function() {
alert(qstring);
var $this = $(this);
href = $this.attr('href');
if (href == '#') {
alert("You must select a product.");
return false;
}
});
When you click on the add link icon it displays a drop down where you can select the quantity. So changing the quantity should also update the link and how it is created. I am trying to figure out how to create the link so the end result looks like so.
cart/add/p123_q1?destination=/cart this is how it would look with a single item. Where p = the product ID and q = the quantity. Unclicking the add to cart should remove those items and changing the drop down should update the quantity. If there is more than one item it should append to the link like so. cart/add/p123_q1-p234_q2-p232_q4?destination=/cart and then unclicking or changing quantity on any of those items should reflect the change in the link. I am not sure if I am going about this all wrong but I have been trying forever and many different routes to go about trying to achieve this effect. If anyone could please help me figure this out I would be greatly appreciated!
I was able to get this to work properly using this piece of code. Hope this maybe helps someone.
$('input.product-radio, select.products-howmany').change(function () {
var $product = $(this).closest('.product-options-left');
var $radio = $product.find('input.product-radio');
var $select = $product.find('select.products-howmany')
$product.find('div.quantity').toggleClass('q-hidden', !$radio.prop('checked'));
$product.find('label.quantity').toggleClass('q-hidden', !$radio.prop('checked'));
var string = $('.product-radio')
.filter(':checked')
.map(function(){
return $(this)
.closest('.product-options-left')
.find('.products-howmany')
.val();
})
.get()
.join('-');
$('a.options-cart').prop("href", "/cart/add/" + string + "?destination=/cart");
});
$('a.options-cart').click(function() {
alert(qstring);
var $this = $(this);
href = $this.attr('href');
if (href == '#') {
alert("You must select a product.");
return false;
}
});

Why does this loop seem convoluted and verbose? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
The loop below builds an HTML string using the object literal obj_fav, which holds a list of favorites.
Because the HTML string can be appended in multiple places, ns_tag namespaces the DOM ids to make sure they are unique.
This is somewhat besides the point. I feel the loop has poor logic. It works fine, but I find it hard to read and feel that is is poorly written. But I can't put my finger on why that is.
// $A.someIndex() implements array.prototype.some
// create favorite pane strings
$A.someIndex(obj_fav, function (val) {
previous_id = current_id;
current_id = this.A.ns_tag + selector + val.tag;
// new tag found, close previous and open new
if ((previous_id === undefined) || (previous_id !== current_id)) {
// populate tag array
this.A['tag_array' + selector].push(current_id);
tag_string = tag_string + this.composeTag(current_id, selector);
if (previous_id !== undefined) {
favorite_string += '</div>';
}
favorite_string = favorite_string +
'<div class="bookmark_page toggle_display_none" id = "' + current_id + '_page">';
}
// add set of favorites between page tags
favorite_string += this.composeFavorite(val, selector);
}, this);
this snippet is contained in this klass:
/*******************************************************************************
**SArcmarks
*/
var SArcmarks = $A.klass({
Name: 'SArcmarks',
// namespacing helps to prevent name clashes // base_location_id_subdivisions // there are 2 prefixes and one suffix
A: {
// namespace suffix base: 'udt' loc: null,
ns_tag: 'udt_',
ns_tag1: 'udt_1_',
tag_array: [],
tag_array1: [],
prev_page_el: null,
prev_tag_el: null,
but_text: null,
// toggles
toggle_display_none: 'toggle_display_none',
toggle_display_inline: 'toggle_display_inline',
toggle_tag_active: 'toggle_tag_active',
toggle_tag_lazy: 'toggle_tag_lazy',
// morphing
class_a: null
},
E: {
hold_arcmarks: '#hold_arcmarks',
hold_tags: '#hold_tags',
aba_but_del: '#aba_but_del',
bookmark_link: '#bookmark_link'
},
/******************************************************************************/
update: function (obj_fav, fav_el, tag_el) {
var favorite_string = '',
tag_string = '',
current_id,
previous_id,
selector;
if (fav_el) {
selector = 1;
} else {
selector = '';
}
// create favorite pane strings
$A.someIndex(obj_fav, function (val) {
previous_id = current_id;
current_id = this.A.ns_tag + selector + val.tag;
// new tag found, close previous and open new
if ((previous_id === undefined) || (previous_id !== current_id)) {
// populate tag array
this.A['tag_array' + selector].push(current_id);
tag_string = tag_string + this.composeTag(current_id, selector);
if (previous_id !== undefined) {
favorite_string += '</div>';
}
favorite_string = favorite_string +
'<div class="bookmark_page toggle_display_none" id = "' + current_id + '_page">';
}
// add set of favorites between page tags
favorite_string += this.composeFavorite(val, selector);
}, this);
// close last tag
favorite_string = favorite_string + '</div>';
// if atleast one favorite/tag
if (this.A['tag_array' + selector][0]) {
if (!fav_el) {
this.E.hold_arcmarks.innerHTML = favorite_string;
} else {
fav_el.innerHTML = favorite_string;
}
if (!tag_el) {
this.E.hold_tags.innerHTML = tag_string;
} else {
tag_el.innerHTML = tag_string;
}
this.initPane(selector);
this.flip($A.el('#' + this.A['tag_array' + selector][0]));
}
},
/******************************************************************************/
composeFavorite: function (val, selector) {
// add selector
if (val.favicon === null) {
val.favicon = 'arcmarks/images/image_null_50.png';
}
return '<div class = "am_hold" id = "' + val.id + selector + '">' +
'<img name="bo_im" id="' + $A.addU(val.id + selector, 'a') +
'" class="bookmark_image" src="' + val.favicon + '">' +
'<a target="_blank" name="bookmark_link" class="bookmark_link" href = "' +
val.url + '" id="' + $A.addU(val.id + selector, 'b') + '">' + val.title + '</a>' +
'</div>';
},
/******************************************************************************/
composeTag: function (current_id, selector) {
// selector
return '<p class="single_tag toggle_tag_lazy" id = "' + current_id + '">' +
current_id.slice(this.A['ns_tag' + selector].length) + '</p>';
},
/******************************************************************************/
// add listeners to tag(<p>) elements
initPane: function (selector) {
$A.someIndex(this.A['tag_array' + selector], function (val) {
var self = this;
$A.el('#' + val).addEventListener("click", function () {
self.flip(this);
});
}, this);
},
/******************************************************************************/
// flip page(<div>) | tag(<p>) given a tag
flip: function (tag_element) {
var page_element = $A.el('#' + tag_element.id + '_page');
$A.addClass(page_element, this.A.toggle_display_inline);
$A.addClass(tag_element, this.A.toggle_tag_active);
if (this.A.prev_page_el && (tag_element.id !== this.A.prev_tag_el.id)) {
$A.addClass(this.A.prev_page_el, this.A.toggle_display_none);
$A.addClass(this.A.prev_tag_el, this.A.toggle_tag_lazy);
}
this.A.prev_page_el = page_element;
this.A.prev_tag_el = tag_element;
$A.log(page_element);
},
// insert favorite(<div>) given user input
insertFavorite: function (obj_fav) {
var tag_id = this.A.ns_tag + obj_fav.tag,
div_el,
html_string = this.composeFavorite(obj_fav),
page_el = $A.el('#' + tag_id + '_page');
div_el = $A.HTMLToElement(html_string);
if (!page_el) {
page_el = this.insertTagAndPage(tag_id);
}
$A.eachChild(page_el, function (iter) {
if (iter === null) {
page_el.appendChild(div_el);
return true;
}
if (div_el.id < iter.id) {
page_el.insertBefore(div_el, iter);
return true;
}
if (iter === page_el.lastChild) {
page_el.appendChild(div_el);
return true;
}
});
this.flip($A.el('#' + tag_id));
return div_el;
},
/******************************************************************************/
// insert page(<div>) | tag(<p>) given a tag id
insertTagAndPage: function (tag) {
var par_el,
div_el,
hold_tags_el,
hold_arcmarks_el,
self = this;
hold_tags_el = this.E.hold_tags;
hold_arcmarks_el = this.E.hold_arcmarks;
par_el = $A.createElement('p');
par_el.innerHTML = tag.slice(this.A.ns_tag.length);
par_el.className = "single_tag";
par_el.id = tag;
// insert the tag(<p>)
$A.eachChild(hold_tags_el, function (iter) {
if (iter === null) {
hold_tags_el.appendChild(par_el);
return true;
}
if (par_el.id < iter.id) {
hold_tags_el.insertBefore(par_el, iter);
return true;
}
if (iter === hold_tags_el.lastChild) {
hold_tags_el.appendChild(par_el);
return true;
}
});
par_el.addEventListener("click", function () {
self.flip(this);
});
div_el = $A.createElement('div');
div_el.className = "bookmark_page";
div_el.id = tag + "_page";
div_el.style.display = "";
// insert the page(<div>);
$A.eachChild(hold_arcmarks_el, function (iter) {
if (iter === null) {
hold_arcmarks_el.appendChild(div_el);
return true;
}
if (div_el.id < iter.id) {
hold_arcmarks_el.insertBefore(div_el, iter);
return true;
}
if (iter === hold_arcmarks_el.lastChild) {
hold_arcmarks_el.appendChild(div_el);
return true;
}
});
return div_el;
},
/******************************************************************************/
// delete a favorite(<div>) given a link
deleteFavorite: function (link_el) {
var self = this,
div_el = link_el.parentNode;
$(div_el).toggle("explode", function () {
if (div_el.previousSibling === null &&
div_el.nextSibling === null) {
self.deleteTagAndPage(div_el);
}
$A.removeElement(div_el);
});
},
/******************************************************************************/
// delete tag(<p>) and page(<div>) given a favorite sub-element
deleteTagAndPage : function (div_el) {
var page_el = div_el.parentNode,
tag_el = $A.el('#' + page_el.id.slice(0, -5)),
hold_el = $A.el("#hold_tags");
$A.removeElement(tag_el);
$A.removeElement(page_el);
$A.eachChild(hold_el, function (iter_el) {
if (iter_el) {
this.flip(iter_el);
return true;
}
}, this);
},
/******************************************************************************/
morph: function (callback) {
var i = 0,
button = this.E.aba_but_del;
if (this.A.but_text === 'Done') {
this.A.but_text = 'Delete';
this.A.class_a = 'bookmark_link';
while (this.E.bookmark_link[i]) {
this.E.bookmark_link[i].removeEventListener("click", callback);
this.E.bookmark_link[i].className = this.A.class_a;
i += 1;
}
button.innerHTML = this.A.but_text;
} else {
this.A.but_text = 'Done';
this.A.class_a = 'bookmark_delete';
while (this.E.bookmark_link[i]) {
this.E.bookmark_link[i].addEventListener("click", callback);
this.E.bookmark_link[i].className = this.A.class_a;
i += 1;
}
button.innerHTML = this.A.but_text;
}
}
}, true);

Google Closure introducing errors

EDIT
The lesson, learned with the help of #Alex, is that you should never put function declarations in block scope. Not that I intended to do this, but if you slip up, it can cause big problems.
I have a script file that seems to be getting compressed via Google Closure incorrectly. When I run my app with the original code, all works fine. But when I try to compress it with Google Closure, some errors get introduced.
I am NOT using the advanced option; I'm using the basic, default mode
Obviously I can't expect anyone to debug the compressed file, but I'm hoping someone can look at the uncompressed code and let me know if I'm somehow doing something insanely stupid that would trick Closure.
Some notes on the minified code:
Closure is inlining BEFramework.prototype.hstreamLoad and BEFramework.prototype.hstreamEvalJson, and seems to be utterly removing the helper functions getDeleteValue, getValueToDisplay, getDisplayForLabel and likely others.
Uncompressed file is below.
This code can manually be compiled by closure here, which should reproduce the symptoms described above.
(function() {
var $ = jQuery;
// Load and display the messages ("healthstream") for a given module.
// This requires that the module's HTML have specific features, see
// dashboard.htm and contactsManager/details/default.htm for examples.
// This also requires that the `request` support `pageIndex` and `pageSize`,
// so we can handle paging.
//
// Args: `options` An options object with these keys:
// `channelId` The channel ID of the module (for transmitRequest)
// `translationId` Optional alternate ID for translation (if not given,
// `channelId` is used).
// `action` The action (for transmitRequest)
// - Must support `pageIndex` and `pageSize`
// `request` The request (for transmitRequest)
// - Must include `pageIndex` and `pageSize`
// `complete` Optional callback triggered when the load is complete.
// `showOptions` Optional callback if an options menu is supported
// by the calling module. Receives a raw event instance
// and the item on which the options were triggered:
// function showOptions(event, item)
// `context` Optional context (`this` value) for the call to
// `complete` and/or `showOptions`
BEFramework.prototype.hstreamLoad = hstreamLoad;
function hstreamLoad(options) {
var inst = this;
var channelId, translationId, action, request, complete, showOptions, context,
pageIndex, pageCount, pageSize, pageCount,
btnPrevious, btnNext,
dataShownFlags;
// Get our arguments (with defaults)
channelId = options.channelId;
translationId = options.translationId || options.channelId;
action = options.action;
request = $.extend({}, options.request); // Create a *copy*, because we modify it when doing paging
complete = options.complete;
if (typeof complete !== "function") {
complete = undefined;
}
showOptions = options.showOptions;
if (typeof showOptions !== "function") {
showOptions = undefined;
}
context = options.context; // (undefined will automatically become the global object)
// Grab the initial pageIndex and pageSize
pageIndex = request.pageIndex || 1;
pageSize = request.pageSize || 100;
// Disable the button and show "searching" label
$('#healthStreamSearchButton')
.button("disable")
.button("option", "label", BETranslate(translationId, 'HealthStreamSearching'));
// Hook up the buttons; be a bit paranoid that they've been hooked before and clear previous handlers
btnPrevious = $('#healthStreamPagePrevious');
btnNext = $('#healthStreamPageNext');
btnPrevious.hide().unbind("click.paging").bind("click.paging", goToPreviousPage);
btnNext.hide().unbind("click.paging").bind("click.paging", goToNextPage);
// Do it
doLoad();
// === Support functions
// Trigger a load request
function doLoad() {
request.pageIndex = pageIndex;
request.pageSize = pageSize;
inst._transport.transmitRequest(channelId, action, request, hstreamLoaded);
}
// Hndle the load response
function hstreamLoaded(objResponse) {
var healthStream = objResponse.items;
var total = objResponse.total;
var tbody = $('#healthStreamList');
// Need to make this update optional
$('#pageHeaderName').html(BETranslate(translationId, 'HeaderActivity') + ' (' + String(total) + ')');
$('#healthStreamSearchButton')
.button("enable")
.button("option", "label", BETranslate(translationId, 'HealthStreamSearch'));
tbody.empty();
btnPrevious.hide();
btnNext.hide();
if (healthStream.length > 0) {
pageCount = Math.ceil(total / pageSize);
if (pageCount > 1) {
if (pageIndex > 1) {
btnPrevious.show();
}
if (pageIndex < pageCount) {
btnNext.show();
}
}
var item;
var tr;
var tdMain;
var daysHash = {};
var creationDate;
var key;
var today = new Date();
var yesterday = new Date();
var msg;
yesterday.setDate(yesterday.getDate() - 1);
dataShownFlags = {};
for (var x = 0; x < healthStream.length; x++) {
item = healthStream[x];
msg = inst.hstreamEvalJson(item);
if (msg.length > 0) {
creationDate = new Date(item.CreationDate);
key = [creationDate.getYear(), creationDate.getMonth(), creationDate.getDate()].join('-');
if (!daysHash[key]) {
if (isDateEqual(creationDate, today)) {
addRowHeader(tbody, BETranslate(inst._channelId, 'HSToday'));
}
else if (isDateEqual(creationDate, yesterday)) {
addRowHeader(tbody, BETranslate(inst._channelId, 'HSYesterday'));
}
else {
addRowHeader(tbody, creationDate.toString('MM/dd/yyyy'));
}
daysHash[key] = true;
}
tr = $(
"<tr>" +
"<td class='date' style='white-space:nowrap;'>" + new Date(item.CreationDate).toString('h:mm tt') + "</td>" +
"<td class='main'><span class='name'>" + msg + "</span>" +
"</tr>"
);
tbody.append(tr);
if (showOptions) {
tr.find("td.main").prepend($("<em rel='opt'> </em>").click(makeShowOptionsHandler(item)));
}
}
}
// If any of the templates created links with a `data` attribute, hook them up
$('#healthStreamList a[data]').click(showTitle).each(function (index) {
this.id = 'data' + index;
});
}
else {
tbody.html('<tr><td colspan="2">' + BETranslate(inst._channelId, 'HSNoActivity') + '</td></tr>');
}
// Trigger completion callback
if (complete) {
complete.call(context, objResponse);
}
}
function makeShowOptionsHandler(item) {
// Our event comes to us from jQuery, but we pass on the raw
// event to the callback
return function (event) {
showOptions.call(context, event.originalEvent || event, item);
};
}
function addRowHeader(listRef, name) {
listRef.append(
"<tr>" +
"<td colspan='2' class='divider'>" + name + "</td>" +
"</tr>"
);
}
function showTitle(event) {
$.stopEvent(event);
var link = this;
var $link = $(this);
var href = $link.attr("href"); // We want the attribute, not the property (the property is usually expanded)
var hrefTitle = $link.attr('hreftitle') || BETranslate(inst._channelId, 'HSMoreInfo');
var data = $link.attr('data') || "";
var linkId = link.id;
if (!dataShownFlags[linkId]) {
dataShownFlags[linkId] = true;
if (data) {
var div = $(
"<div class='data'>" +
"<span data-linkId='" + linkId + "' class='close'>x</span>" +
"<table><thead></thead></table>" +
"</div>"
);
$link.parent().append(div);
var thead = div.find("thead");
var arr = data.split('~');
var splitEntry;
for (var x = 0; x < arr.length; x++) {
splitEntry = arr[x].split('|');
if (splitEntry[0] === 'Changed length') {
splitEntry[1] = splitEntry[1].replace(/\d+/g, BEFramework.prettyTime);
}
if (splitEntry.length > 1 && splitEntry[1].length > 0) {
thead.append(
"<tr>" +
"<td class='hslabel'>" + splitEntry[0] + ":</td>" +
"<td>" + splitEntry[1] + "</td>" +
"</tr>"
);
}
}
div.find("span:first").click(hideTitle);
if (href && href !== "#") {
$("<a target='_blank'>" + hrefTitle + "</a>").attr("href", href).appendTo(div);
}
}
}
}
function hideTitle(event) {
var $this = $(this),
linkId = $this.attr("data-linkId");
delete dataShownFlags[linkId];
$this.parent().remove();
return false;
}
function goToPreviousPage(event) {
--pageIndex;
doLoad();
return false;
}
function goToNextPage(event) {
++pageIndex;
doLoad();
return false;
}
}
var ___x = false;
var __i = 0;
BEFramework.prototype.hstreamEvalJson = hstreamEvalJson;
function hstreamEvalJson(item) {
var inst = this;
if (item.Action === 'saveinsurance' && !___x && __i != 0){
var start = +new Date();
__i = 1;
}
var userId = inst._BEUser ? inst._BEUser.getId() : -1;
var json = eval('(' + item.JSON + ')');
var key = 'HS' + item.Module + '_' + item.Action;
var msg = BETranslate(inst._channelId, key);
var fromIsMe = item.CreatedByContactId == userId;
var toIsMe = item.ContactId == userId;
var fromString = (fromIsMe) ? '<strong>' + BETranslate(inst._channelId, 'HSYou') + '</strong>' : '<a class="vcard" contactId="' + item.CreatedByContactId + '">' + item.CreatedByName + '</a>';
var toString = (toIsMe) ? '<strong>' + BETranslate(inst._channelId, 'HSYour') + '</strong>' : '<a class="vcard" contactId="' + item.ContactId + '">' + item.ContactName + '</a>';
var fromString2 = (fromIsMe) ? '<strong>' + BETranslate(inst._channelId, 'HSYour').toLowerCase() + '</strong>' : '<a class="vcard" contactId="' + item.CreatedByContactId + '">' + item.CreatedByName + '</a>';
var toString2 = (toIsMe) ? '<strong>' + BETranslate(inst._channelId, 'HSYou').toLowerCase() + '</strong>' : '<a class="vcard" contactId="' + item.ContactId + '">' + item.ContactName + '</a>';
var subFormat, subProps;
var configObject = (BEFramework.healthStreamConfig[item.Module] && BEFramework.healthStreamConfig[item.Module][item.Action]) || {};
var standardCase = configObject.standardCase;
var suppress = configObject.suppress || [];
var propertiesInOrder = configObject.displayOrder || [];
if (msg.indexOf('not found in module') != -1) {
try {
switch (item.Module) {
case 'contacts':
if (item.Action == 'setpermission' || item.Action == 'deleterelationship' || item.Action == 'addinvite') {
msg = BETranslate(inst._channelId, key + json.type.toString());
}
break;
case 'tasks':
if (item.Action == 'savetask') {
msg = BETranslate(inst._channelId, key + json.type.toString());
}
break;
default:
msg = '';
}
} catch (ex) {
msg = '';
}
}
for (var prop in json) {
if (typeof (json[prop]) == 'object') {
if (prop === 'changes' || prop === 'deleted'){
subProps = json[prop];
for (var propName in subProps) {
if (indexInArrayCI(propName, propertiesInOrder) === -1 && indexInArrayCI(propName, suppress) === -1){
propertiesInOrder.push(propName);
}
}
}
if (prop == 'changes') {
var changes = '';
var changeFrom = BETranslate(inst._channelId, 'HSChangedFrom');
var changeTo = BETranslate(inst._channelId, 'HSChangedTo');
for (var i = 0; i < propertiesInOrder.length; i++) {
var subprop = propertiesInOrder[i];
if (getObjectValCI(subProps, subprop) == null) continue;
var subSplit = stripHtml(getObjectValCI(subProps, subprop)).split('|');
if (subSplit.length === 1) {
subFormat = BETranslate(inst._channelId, 'HS' + item.Module + '_changes_' + subprop);
if (subFormat.indexOf('not found in module') < 0) {
changes += $.sandr(subFormat, '#{value}', subSplit[0]);
}
else {
changes += "*|" + subprop + " " + subSplit[0] + "~";
}
}
else {
var fromValue = stripHtml(subSplit[0]);
var toValue = stripHtml(subSplit[1]);
var packetInfo = processChangedValues(subprop, fromValue, toValue);
if (packetInfo.skip) continue;
changes = changes + changeFrom + packetInfo.display + '|' + packetInfo.fromValue + '<b>' + changeTo + '</b>' + packetInfo.toValue + '~';
}
}
msg = $.sandr(msg, '#{' + prop + '}', changes);
} else if (prop == 'deleted') {
var deleted = '';
for (var i = 0; i < propertiesInOrder.length; i++) {
var subprop = propertiesInOrder[i];
var currentValue = getObjectValCI(subProps, subprop);
if (currentValue == null || currentValue.toString().length === 0) continue;
deleted = deleted + getDisplayForLabel(subprop) + '|' + getDeleteValue(subprop, currentValue) + '~';
}
msg = $.sandr(msg, '#{' + prop + '}', deleted);
}
} else {
msg = $.sandr(msg, '#{' + prop + '}', $.sandr(json[prop], '"', ' '));
}
function processChangedValues(label, fromValue, toValue){
var typeFormat = (getObjectValCI(configObject, label) || {}).type;
var result = {};
if (typeFormat === 'date'){
var d1 = new Date(fromValue);
var d2 = new Date(toValue);
if (isDateEqual(d1, d2)) result.skip = true;
}
result.fromValue = getValueToDisplay(fromValue, typeFormat);
result.toValue = getValueToDisplay(toValue, typeFormat);
result.display = getDisplayForLabel(label)
return result;
}
function getDeleteValue(label, value){
var typeFormat = (getObjectValCI(configObject, label) || {}).type;
return getValueToDisplay(value, typeFormat);
}
function getValueToDisplay(rawValue, typeFormat){
if (typeFormat === 'date'){
var d = new Date(rawValue);
return isNaN(d.getTime()) ? rawValue : d.toString('MM/dd/yyyy');
} else if (typeof typeFormat === 'function') {
return typeFormat(rawValue)
} else {
return rawValue;
}
}
function getDisplayForLabel(label){
var fixCaseOfProperty = standardCase === '*' || indexInArrayCI(label, standardCase) > -1;
var rawConfigForLabel = getObjectValCI(configObject, label) || {};
return (rawConfigForLabel && rawConfigForLabel.display)
|| (fixCaseOfProperty ? fixCase(label) : null)
|| label;
}
}
msg = $.sandr(msg, '#{contactId}', item.ContactId);
msg = $.sandr(msg, '#{from}', fromString);
msg = $.sandr(msg, '#{to}', toString);
msg = $.sandr(msg, '#{from2}', fromString2);
msg = $.sandr(msg, '#{to2}', toString2);
msg = $.sandr(msg, '#{recordId}', item.RecordId);
msg = msg.replace(/#{[\S]*}/g, '');
if (item.Action === 'saveinsurance' && !___x && __i == 1){
var end = +new Date();
___x = true;
//alert(end - start);
}
if (item.Action === 'saveinsurance') __i++;
if (msg.indexOf('not found in module') == -1) {
return msg;
} else {
return '';
}
}
function stripHtml(html) {
var tmp = document.createElement('DIV');
tmp.innerHTML = html;
return tmp.textContent || tmp.innerText;
}
function isDateEqual(date1, date2) {
if (date1.getDate() === date2.getDate() &&
date1.getMonth() === date2.getMonth() &&
date1.getYear() === date2.getYear()) {
return true;
}
else {
return false;
}
}
function getObjectValCI(obj, key){
for (var k in obj){
if (k.toLowerCase() === key.toLowerCase()){
return obj[k];
}
}
}
function indexInArrayCI(item, arr){
if (!$.isArray(arr)) arr = [];
var target = item.toString().toLowerCase();
for (var i = 0; i < arr.length; i++){
if (target === arr[i].toLowerCase()) return i;
}
return -1;
}
function fixCase(str){
return str.replace(/[a-z][A-Z]/g, function(match) { return match.charAt(0) + ' ' + match.charAt(1).toLowerCase(); }).toLowerCase()
.replace(/\sid\s/g, ' ID ')
.replace(/\sid$/g, ' ID')
.replace(/^id$/g, 'ID');
}
})();
When you use closure compiler you're giving up some control over your code. It will do all sorts of tricks, and potentially remove unused code.
It appears as though your functions are not removed, but are renamed.
For example, your call to getDeleteValue...
getDeleteValue(subprop, currentValue)
is now...
l(g,r)
Because getDeleteValue was not exported, Closure renamed it.
Working with Closure Compiler takes a bit of finesse and quite a bit of documentation scouring until you're familiar with how it works.
Well, there are too many errors to think of. First of all, I don't understand if you want static reference or instantiated values. You are not using jsDoc tags or anything like that. The Compiler does it's best work only with the corresponding jsDoc tag. You're logic is very weird and ill formulated. Prototype alternations, etc, all happening in an IIFE(immediately invoked function expression). Are your functions static? Are they constructors? Are we human or are we dancer?
an IIFE executes before the DOMContentLoaded event is fired by the browser. The most you can do is a jQuery IIFE equivalent $(function() {})(); which binds that to the DOMReady or DOMContentLoaded callback. You are defining inline functions inside blocks, which is not even in the ECMA Language.
While most script engines support Function Declarations within blocks it is not part of ECMAScript (see ECMA-262, clause 13 and 14). Worse implementations are inconsistent with each other and with future EcmaScript proposals. ECMAScript only allows for Function Declarations in the root statement list of a script or function. Instead use a variable initialized with a Function Expression to define a function within a block.
var myFunctionName = function (params) {};
You are also missing loads of semi-colons. Automatic semi-colon insertion on interpretation of your JS is not exactly flawless, so make a habit out of it.
Relying on implicit insertion can cause subtle, hard to debug problems. Don't do it. You're better than that.
There are a couple places where missing semicolons are particularly dangerous:
// 1.
MyClass.prototype.myMethod = function() {
return 42;
} // No semicolon here.
(function() {
// Some initialization code wrapped in a function to create a scope for locals.
})();
var x = {
'i': 1,
'j': 2
} // No semicolon here.
// 2. Trying to do one thing on Internet Explorer and another on Firefox.
// I know you'd never write code like this, but throw me a bone.
[normalVersion, ffVersion][isFF]();
var THINGS_TO_EAT = [apples, oysters, sprayOnCheese] // No semicolon here.
// 3. conditional execution a la bash
-1 == resultOfOperation() || die();
So what happens?
JavaScript error - first the function returning 42 is called with the second function as a parameter, then the number 42 is "called" resulting in an error.
You will most likely get a 'no such property in undefined' error at runtime as it tries to call x[ffVersion][isIE]().
die is called unless resultOfOperation() is NaN and THINGS_TO_EAT gets assigned the result of die().
Why?
JavaScript requires statements to end with a semicolon, except when it thinks it can safely infer their existence. In each of these examples, a function declaration or object or array literal is used inside a statement. The closing brackets are not enough to signal the end of the statement. Javascript never ends a statement if the next token is an infix or bracket operator.
This has really surprised people, so make sure your assignments end with semicolons.

Categories

Resources