I have a simple chat application build with strophe js. I am showing the only users who are online. But the problem is when the user goes online, after some seconds the users goes offline automatically.
Here is my code:
function onConnect(status)
{
// Functions runs while users trys to login to the XMPP server
var iq = null;
switch (status)
{
case Strophe.Status.CONNECTING:
log('Connecting.');
break;
case Strophe.Status.CONNFAIL:
log('Failed to connect.');
$('#connect').get(0).value = 'connect';
break;
case Strophe.Status.DISCONNECTING:
log('Disconnecting.');
break;
case Strophe.Status.DISCONNECTED:
log('Disconnected.');
$('#connect').get(0).value = 'connect';
break;
case Strophe.Status.CONNECTED:
log('Connected.');
connection.addHandler(onMessage, null, 'message', null, null, null);
connection.addHandler(onPresence, null, 'presence', null, null, null);
iq = $iq({type: 'get'}).c('query', {xmlns: 'jabber:iq:roster'});
connection.sendIQ(iq, onRoster);
break;
default:
break;
}
}
function onPresence(pres)
{
var fromJid = $(pres).attr("from"),
fromBareJid = Strophe.getBareJidFromJid(fromJid),
myBareJid = Strophe.getBareJidFromJid(connection.jid),
type = $(pres).attr("type"),
show = $(pres).children("show").text(),
statusMsg = $(pres).children("status").text(),
contactDropDown = $('#to-jid'),
line;
$.each(roster, function (index, rosterEntry) {
if (rosterEntry.jid === fromBareJid) {
if (type === "unavailable") {
rosterEntry.presence = "offline";
rosterEntry.message = null;
} else {
if (show) {
rosterEntry.presence = show;
} else {
rosterEntry.presence = 'online';
}
if (statusMsg) {
rosterEntry.message = statusMsg;
} else {
rosterEntry.message = null;
}
}
}
});
showRoster();
if (fromBareJid !== myBareJid) {
if (type !== 'unavailable') {
if (!_.contains(onlineContacts, fromBareJid)) {
onlineContacts.push(fromBareJid);
}
line = fromBareJid + " is ";
if (show) {
line += show;
} else {
line += "online";
}
if (statusMsg) {
line += ", \"" + statusMsg + "\"";
}
showMessage(line);
} else {
onlineContacts = _.reject(onlineContacts, function (jid) {
return (jid === fromBareJid);
});
showMessage(fromBareJid + " is offline");
}
contactDropDown.empty();
contactDropDown.append($("<option />").text("Choose a contact..."));
$.each(onlineContacts, function (index, contact) {
contactDropDown.append($("<option />").val(contact).text(contact));
});
}
return true;
}
function onRoster(iq) {
$(iq).find('item').each(function () {
var jid = $(this).attr('jid'),
name = $(this).attr('name'),
show = "",
rosterEntry = {
jid: jid,
name: name,
presence: 'offline',
message: null
};
roster.push(rosterEntry);
});
// showRoster();
connection.send($pres().tree());
}
function showRoster() {
rosterbox.val("");
$.each(roster, function (index, rosterEntry) {
var line = "";
line += rosterEntry.jid;
if (rosterEntry.name) {
line += " (" + rosterEntry.name + ")";
}
line += ": " + rosterEntry.presence;
if (rosterEntry.message !== null) {
line += ", \"" + rosterEntry.message + "\"";
}
rosterbox.val(rosterbox.val() + line + "\n");
});
}
With this code, the user goes offline automatically. Cant find where's the exact problem. Please help
Related
I have created a JavaScript plugin, I'd like to have the potential to use this multiple times, however, having it called one the page twice like follows doesn't seem to make a new instance:
var lightbox = new MarvLightbox({
imagesContainer: 'detail-hdr__detail-images',
limit: 11
});
var lightbox2 = new MarvLightbox({
imagesContainer: 'image-grid-2',
galleryFolder: 2,
mobileFolder: 0
});
The following code seems to be returning the same values, so for example, if I click an image to set the c value within the state object then it's changed for instance lightbox2 AND lightbox.
MarvLightbox.prototype.current = function() {
console.log(state);
};
I have tried to remove any none required code from my plugin. But what I'm basically doing is:
1. Compile a list of the images within a container.
2. Generate HTML from a JSON string.
3. Assigning click events to the images, and then when clicked they open the lightbox and change the image etc.
(function() {
var instance = null,
container;
// Constructor
this.MarvLightbox = function() {
instance = this;
// Create global variables
this.images_count = -1;
this.active = false;
this.error = false;
this.debug = false;
// Define option defaults
var defaults = {
activeClass: 'marvLightbox',
appendTo: '#wrapper',
imagesContainer: null,
thumbClass: null,
lightboxId: 'marvLightbox',
galleryFolder: null,
mobileFolder: null,
showAlt: true,
showMax: true,
limit: null,
html: '{ "div": { "id": "{lightboxId}", "0": { "div": { "class": "{lightboxId}__container", "data-click": "EventClose", "0": { "div": { "class": "{lightboxId}__controls {lightboxId}__controls--top", "0": { "div": { "class": "{lightboxId}__eschint", "content": "Press <span>ESC</span> to close" } }, "1": { "div": { "class": "{lightboxId}__close", "data-click": "EventClose" } } } }, "1": { "div": { "class": "{lightboxId}__image", "0": { "img": { "src": "", "class": "responsive-img image", "data-click": "EventRight" } } } }, "2": { "div": { "class": "{lightboxId}__controls {lightboxId}__controls--bottom", "3": { "div": { "class": "{lightboxId}__left", "data-click": "EventLeft", "data-hover": "EventClass(#{lightboxId}, toggle: left)" } }, "4": { "div": { "class": "{lightboxId}__right", "data-click": "EventRight", "data-hover": "EventClass(#{lightboxId}, toggle: right)" } }, "5": { "div": { "class": "{lightboxId}__alt" } }, "6": { "div": { "class": "{lightboxId}__num" } } } } } } } }'
};
// Create options by extending defaults with the passed in arugments
if (arguments[0] && typeof arguments[0] === "object") {
this.options = extendDefaults(defaults, arguments[0]);
}
this.options.html = this.options.html.replace(/\{(lightboxId)}/g, this.options.lightboxId);
// this.options.limit = this.options.limit + 1;
// Check if debugging is enabled
(function() {
var args = document.querySelectorAll('[data-external-arg]');
if(args.length > 0 && args[0].src.indexOf('marv.lightbox') !== -1) {
if (args[0].dataset.externalArg === 'debug') instance.debug = true;
}
}());
// Initialise plugin
this.init();
};
// Debugging messages
var debug = function(code, arg) {
var args = function(n) {
if (arg === undefined) {
return '[arg undefined]';
}
if (arg[n] === undefined) {
return '[arg undefined]';
} else {
return arg[n];
}
};
var messages = function(code, argument) {
return [
'marv.lightbox(debug): Debugging mode is on, make sure you turn this off before you launch',
'marv.lightbox(debug): HTMLElement(' + args(0) + ') with the name of ' + args(1) + ' has been detected',
'marv.lightbox(debug): Found '+ arg + ' image/s within your Lightbox container ',
'marv.lightbox(debug): ' + args(0) + ' key pressed, changing current (' + args(1) + '), number of images (' + args(2) + ')',
'marv.lightbox(debug): Current is set to null, closing lightbox',
'marv.lightbox(debug): Inserting Lightbox within HTMLElement(' + args(1) + '), using ' + args(0),
'marv.lightbox(debug): 1 image found, don\'t add previous/next arrows, don\'t show numbers either',
'marv.lightbox(debug): showAlt set to false, don\'t display alt text',
'marv.lightbox(debug): showMax set to false, don\'t display numbers below alt text',
'marv.lightbox(debug): Reverting to mobile version (' + instance.options.mobileFolder + ') of images',
'marv.lightbox(debug): Over-riding to ' + instance.options.galleryFolder + ' version of images'
][code];
};
if (instance.debug === true)
console.log(messages(code, arg));
};
// Error messages
var error = function(code, arg) {
var args = function(n) {
if (arg === undefined) {
return '[arg undefined]';
}
if (arg[n] === undefined) {
return '[arg undefined]';
} else {
return arg[n];
}
};
var messages = function(code, argument) {
return [
'marv.lightbox(error): I need to know which images to use... add { imagesContainer: "id/class" } to the plugin initialization',
'marv.lightbox(error): The HTML structure provided appears to have an error: ' + arg,
'marv.lightbox(error): Issue compiling list of images, speak to Dev, error: ' + arg,
'marv.lightbox(error): Your going to need some images for this to work... make sure they have the class: ' + instance.options.thumbClass,
'marv.lightbox(error): I was unable to find an element which matches ' + instance.options.imagesContainer + ', please double check this',
'marv.lightbox(error): I was unable to find a container with the name of ' + args[0],
'marv.lightbox(error): EventListener with arguments passed, had an issue seperating arguments, check formatting',
'marv.lightbox(error): Unable to apply class event to element, please check your attribute',
'marv.lightbox(error): You have attempted to over-ride the images folder with a size that doesn\'t exist, please choose a size between 0 and ' + arg
][code];
};
console.log(messages(code, arg));
};
var imageSizes = function(e) {
var sizes = [ '344x258', 'full', 'large1' ];
if (sizes[e] !== undefined) {
return sizes[e];
}
error(8, sizes.length);
};
// Initilise the plugin
MarvLightbox.prototype.init = function() {
if (this.options.imagesContainer === null) {
error(0);
return;
}
container = (instance.options.imagesContainer).objectType();
if (container === null || container === undefined) {
error(4);
return;
}
debug(0);
setupLightbox();
};
// Generate HTML from JSON
function buildHTML(json) {
"use strict";
var handleAttribute = function(element, attribute, value) {
if (value instanceof HTMLElement) {
return element.appendChild(value);
}
switch (attribute) {
case 'class':
case 'src':
case 'id':
case 'data-click':
case 'data-hover':
return element.setAttribute(attribute, value);
case 'content':
element.innerHTML = value;
return;
// other keys...
default:
console.log(element.tagName, attribute, value);
}
};
var htmlReviver = function(key, value) {
// parse as element
if (isNaN(key) && typeof value === 'object') {
var element = document.createElement(key);
var subValue;
for (var attribute in value) {
handleAttribute(element, attribute, value[attribute]);
}
return element;
// move element from { index: { tagName: Element } } to { index: Element }
} else if (!isNaN(key)) {
return value[Object.keys(value)[0]];
// leave property alone
} else {
return value;
}
};
try {
var htmlObject = JSON.parse(json, htmlReviver);
return htmlObject;
} catch (e) {
error(1, e);
}
}
// Manage item change
var images_compiled;
var state = {
c: null,
altValue: null,
maxValue: null,
get current() { return this.c; },
get max() { return this.maxValue; },
get alt() { return this.altValue; },
set max(e) { this.maxValue = e; },
set alt(e) { this.altValue = e; },
set current(e) {
if (this.c !== null) {
// Remove class from current
(images_compiled[this.c].target).classList.remove('expand');
}
if (e === null) {
debug(4);
// Collapse Lightbox
if (document.getElementById(instance.options.lightboxId)) {
(images_compiled[this.c].target).classList.remove('expand');
document.getElementsByTagName('body')[0].classList.remove(instance.options.activeClass);
(document.getElementById(instance.options.lightboxId).parentNode).removeChild(document.getElementById(instance.options.lightboxId));
}
this.c = e;
return;
}
// Change current element, update lightbox
this.c = e;
var lightbox = document.getElementById(instance.options.lightboxId),
res;
// Check lightbox exists, if so change the image src
if (lightbox) {
var image = images_compiled[e].image.src;
if (instance.options.galleryFolder !== null) {
var filter = image.match(/([^\/]*)/g).filter(Boolean);
image = image.replace(filter[filter.length - 2], imageSizes(instance.options.galleryFolder));
}
lightbox.getElementsByTagName('img')[0].src = image;
if (instance.options.showAlt) {
debug(7);
lightbox.getElementsByClassName(instance.options.lightboxId + '__alt')[0].innerHTML = images_compiled[e].alt;
}
if (instance.options.showMax && this.max > 1) {
debug(8);
lightbox.getElementsByClassName(instance.options.lightboxId + '__num')[0].innerHTML = (images_compiled[e].index + 1) + '/' + this.max;
}
} else {
res = generateExpand(images_compiled[e]);
}
// Add active class
if (res) {
(images_compiled[e].target).classList.add('expand');
document.getElementsByTagName('body')[0].classList.add(instance.options.lightboxId);
}
}
};
// Setup light box
function setupLightbox() {
var images;
images = container.getElementsByTagName('img');
if (instance.options.limit !== null) {
var tmp = [];
for (var i = 0, length = images.length; i < length; i++) {
if (i < instance.options.limit) {
tmp.push(images[i]);
}
}
images = tmp;
}
if (images.length < 1 || images === undefined) {
error(3);
return;
}
try {
images_compiled = Array.from(images, function(el) {
// Generate array of objects containing image information
instance.images_count++;
return {
target: function() {
if (el.parentElement.nodeName === 'A') {
return el.parentElement;
}
return el;
}(),
index: instance.images_count,
alt: ((el.alt) ? el.alt : ''),
image: function() {
// If class put on an A link then find the image
if (el.tagName === 'A') {
return el.getElementsByTagName('img')[0];
} else {
return el;
}
}()
};
});
} catch(e) {
// Issue with generating array
error(2, e);
}
debug(2, images_compiled.length);
// Add image click event
images_compiled.forEach(function(el) {
if (el !== null) {
var elm = el.target;
elm.addEventListener('click', function(e) {
if (elm.nodeName === 'A') {
e.preventDefault();
}
instance.active = true;
if (state.current === el.index) {
state.current = null;
return;
}
state.current = el.index;
state.alt = el.alt;
});
}
});
state.max = images_compiled.length;
}
function generateExpand(img) {
// Generate lightbox HTML and append
var html = buildHTML(instance.options.html);
instance.events = {
EventClose: function(evt) {
if (evt !== undefined) {
evt.stopPropagation();
}
instance.active = false;
state.current = null;
},
EventLeft: function(evt) {
if (evt !== undefined) {
evt.stopPropagation();
}
if (state.current !== 0 && state.max > 1) {
state.current = state.current - 1;
} else {
state.current = instance.images_count;
}
},
EventRight: function(evt) {
if (evt !== undefined) {
evt.stopPropagation();
}
if (state.current !== instance.images_count && state.max > 1) {
state.current = state.current + 1;
} else {
state.current = 0;
}
},
EventClass: function(evt) {
var arg = (evt.dataset.hover).replace(/ /g,''),
args = (arg.match(/[^(]*/g).filter(Boolean))[1].match(/(?:([^,()]+)?)+/g).filter(Boolean),
target = args[0].objectType(),
action = args[1].match(/^(.*):(.*)/).filter(Boolean);
switch(action[1]) {
case 'add':
// Add class
target.classList.add(action[2]);
break;
case 'remove':
// Remove class
target.classList.remove(action[2]);
break;
case 'toggle':
target.classList.add(action[2]);
evt.addEventListener('mouseout', function() {
target.classList.remove(action[2]);
});
break;
default:
// Error
error(7);
break;
}
}
};
// Lightbox is active
instance.active = true;
// Assign event listeners
Array.prototype.forEach.call(html.querySelectorAll('[data-click]'), function (e) {
e.addEventListener('click', instance.events[eventName(e.dataset.click)]);
});
Array.prototype.forEach.call(html.querySelectorAll('[data-hover]'), function (e) {
e.addEventListener('mouseover', function() { instance.events[eventName(e.dataset.hover)](e); });
});
// Insert lightbox into website
var appendTo = (instance.options.appendTo).objectType();
if (appendTo === null || (instance.options.appendTo).objectType() === undefined) {
error(5, [instance.options.appendTo]);
return false;
}
debug(5, ['id', instance.options.imagesContainer]);
appendTo.insertBefore(html, appendTo.firstChild);
return true;
}
MarvLightbox.prototype.current = function() {
console.log(state);
};
}());
As I said above though the state object appears to be shared between both instances, it should be unique.
The problem lies at instance i think:
var instance = null;
MarvLightbox = function() {
instance = this;
So whenever a new Lightbox is created, instance points to it. This also applies to asynchronous callback functions which will all point to the last instead of the current instance. You may scope instance locally:
var instance=this;
Same applies to state:
MarvLightbox.prototype.current = function() {
console.log(this.state); //make it an objects property, not global
};
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.
I'm having a little problem. I thought I had understood Event Handling, but now I don't think so anymore.
I've created a Chrome Event():
this.onReadLine = new chrome.Event();
this event is dispatched in a function:
this.onReadLine.dispatch(line);
before the dispatch instruction I've tried to log 'line', the argument of the dispatch instruction. No problem, 'line' exists.
Going straight down with the code you will find this part:
connection.onReadLine.addListener(function(line) {
logJSON(line);
});
this is what must be fired every time the onReadLine event is dispatched.
The problem is that the Event onReadLine is only dispatched when I push or release the button '#dimmer1_Chrome_Input' defined at the end of my code.
Where I'm wrong?
My full code here. The parts related to problem are highlighted with ////\///\/\///\\ lines.
// Serial used from Arduino board
const Arduino_COM = 'COM3'; // PC
var SerialConnection = function() {
this.connectionId = -1;
this.lineBuffer = "";
this.boundOnDataReceiving = this.onDataReceiving.bind(this);
this.boundOnDataReceivingError = this.onDataReceivingError.bind(this);
this.onConnect = new chrome.Event();
///////////////////////////\\\\\\\\\\\\\\\/////////////\\\\\\\\\\////////\\\\\\\\\\\\////////\\\\\\\\\\//////PROBLEM
this.onReadLine = new chrome.Event();
///////////////////////////\\\\\\\\\\\\\\\/////////////\\\\\\\\\\////////\\\\\\\\\\\\////////\\\\\\\\\\//////PROBLEM
this.onError = new chrome.Event();
};
SerialConnection.prototype.connect = function(Serial_COM_Port) {
chrome.serial.connect(Serial_COM_Port, this.onConnectComplete.bind(this));
};
SerialConnection.prototype.onConnectComplete = function(connectionInfo) {
if (!connectionInfo) {
log("Connection failed.");
return;
}
this.connectionId = connectionInfo.connectionId;
chrome.serial.onReceive.addListener(this.boundOnDataReceiving);
chrome.serial.onReceiveError.addListener(this.boundOnDataReceivingError);
this.onConnect.dispatch();
};
SerialConnection.prototype.send = function(msg) {
if (this.connectionId < 0) {
throw 'Invalid connection';
}
chrome.serial.send(this.connectionId, String_to_ArrayBuffer(msg), function() {});
};
SerialConnection.prototype.onDataReceiving = function(receiveInfo) {
if (receiveInfo.connectionId !== this.connectionId) {
return;
}
this.lineBuffer += ArrayBuffer_to_String(receiveInfo.data);
var index;
while ((index = this.lineBuffer.indexOf('\n')) >= 0) {
var line = this.lineBuffer.substr(0, index + 1);
console.log(line);
///////////////////////////\\\\\\\\\\\\\\\/////////////\\\\\\\\\\////////\\\\\\\\\\\\////////\\\\\\\\\\//////PROBLEM
this.onReadLine.dispatch(line);
///////////////////////////\\\\\\\\\\\\\\\/////////////\\\\\\\\\\////////\\\\\\\\\\\\////////\\\\\\\\\\//////PROBLEM
this.lineBuffer = this.lineBuffer.substr(index + 1);
}
};
SerialConnection.prototype.onDataReceivingError = function(errorInfo) {
if (errorInfo.connectionId === this.connectionId) {
this.onError.dispatch(errorInfo.error);
}
};
SerialConnection.prototype.disconnect = function() {
if (this.connectionId < 0) {
throw 'Invalid connection';
}
chrome.serial.disconnect(this.connectionId, function() {});
};
var connection = new SerialConnection();
connection.onConnect.addListener(function() {
log('connected to: ' + Arduino_COM);
});
///////////////////////////\\\\\\\\\\\\\\\/////////////\\\\\\\\\\////////\\\\\\\\\\\\////////\\\\\\\\\\//////PROBLEM
connection.onReadLine.addListener(function(line) {
logJSON(line);
});
///////////////////////////\\\\\\\\\\\\\\\/////////////\\\\\\\\\\////////\\\\\\\\\\\\////////\\\\\\\\\\//////PROBLEM
connection.connect(Arduino_COM);
function logJSON(result) {
var response = jQuery.parseJSON( result );
dimmer1_state = response.dimmer1_state;
dimmer1_value = response.dimmer1_value;
SerialIn = response.SerialIn;
dimmer1_Chrome_Input = response.dimmer1_Chrome_Input;
temperature1_value = response.temperature1_value;
s=Math.round(dimmer1_value * 80 / 255 + 20);
hsl='hsl(115,'+s+'%,60%)';
if (dimmer1_state == 0)
{
$('#statusCircle').css('fill','hsl(115,20%,60%)');
}
else
{
$('#statusCircle').css('fill', hsl);
};
// Print led Status to HTML buffer area
messaggio = "dimmer1 state: " + dimmer1_state
+ "<br />dimmer1 value: " + dimmer1_value
+ "<br />SerialIn: " + SerialIn
+ "<br />dimmer1_Chrome_Input: " + dimmer1_Chrome_Input
+ "<br />temperature1_value: " + temperature1_value + " °C";
log(messaggio);
};
function log(msg) {
$('#buffer').html(msg);
};
$(function(){
$('#dimmer1_Chrome_Input') .button()
.mousedown(function() {
connection.send("101");
})
.mouseup(function() {
connection.send("100");
});
});
The code is correct, the error was in another part of program
I'm trying to make this javascript code (made by Esailija) to write folders as well
http://jsfiddle.net/JwgqC/
Currently it only shows files, not folders.. Folders appear as dots..
Here's my mod
http://jsfiddle.net/JwgqC/46/
function selectFolder(e) {
var theFiles = e.target.files;
for (var i=0, file; file=theFiles[i]; i++) {
document.body.innerHTML+="<li>" + file.webkitRelativePath;
}
}
document.querySelector("input").onchange = function() {
[].slice.call( this.files ).forEach( function(selectFolder) {
$("body").append("<div>"+v.name+"</div>" );
});
};
But i can't get the folders to show up..
Mind pointing me which part is incorrect?
My background isn't exactly programing so it's kinda difficult for me
Thanks
If you would like to display the folders only:
http://jsfiddle.net/F6yEW/
function isFolder(x) {
if (x.name == "." && x.type == "") {
return true;
} else {
return false;
}
}
document.querySelector("input").onchange = function () {
[].slice.call(this.files).forEach(function (v) {
var folderName = "";
var path = v.webkitRelativePath.replace("/.", "");
if (isFolder(v)) {
folderName = path.match(/([^\/]*)\/*$/)[1];
$("body").append("<div>" + folderName + "</div>");
}
});
};
If you would like to display folders + files: http://jsfiddle.net/K22RT/
function isFolder(x) {
if (x.name == "." && x.type == "") {
return true;
} else {
return false;
}
}
document.querySelector("input").onchange = function () {
[].slice.call(this.files).forEach(function (v) {
var displayName = v.name;
var path = v.webkitRelativePath.replace("/.", "");
if (isFolder(v)) {
displayName = path.match(/([^\/]*)\/*$/)[1];
$("body").append("<div>folder: " + displayName + "</div>");
} else {
$("body").append("<div>file: " + displayName + "</div>");
}
});
};
I hope this solution can help you out :)
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);