var dc = {
	
	global : {
		
		initialize : function() {
			dc.global.initializeMenu();			
			dc.global.initializeBreadcrumbs();
			dc.global.initializeNewWindowLinks();
		},
		
		initializeMenu : function() {
			$('#site_navigation').nmcDropDown();
		},

		initializeNewWindowLinks : function() {
		    $('a[rel="new_window"]').click(function(){
		        window.open(this.href);
		        return false;
		    });
		},

		initializeBreadcrumbs : function() {
			$('#breadcrumbs li').each(function(i) {
				var self = this;
				
				if ($(self).is(':last-child')) {
					$(self).addClass('current');
				}
				else {
					$(self).after('<li class="separator">&raquo;</li>');
				}
			});
		},
		
		addProductToBag: function(button) {
			
			var url = button.hasClass('associated') 
				? button.attr('href')
				: '/cart.jsp?' + $.param(button.metadata().param)+'&sessionprop=';
				
			var required = $('select.required','ul.details');
			
			if ( required.find('option:selected').index() === 0 ) {
				required.each(function( index ) {
					if ( $(this).find('option:selected').index() === 0 ) {
						error_msg = '<span class="error">&nbsp; Required.</span>';
						$(this).css('border-color','red').after(error_msg);
					}
				});
				return false; 
			}
				
			var rsz_select = $('select#session_prop_misc'), rsz_selected = rsz_select.find('option:selected');
			var metal_select = $('select#session_prop_metal'), metal_selected = metal_select.find('option:selected');
			
			if (rsz_select.length) { url = url + 'Ring_Size@' + rsz_selected.val(); }
			if (metal_select.length) { url = url + ';Metal@' + metal_selected.val(); }

			for( i=1; i <= no_birth_stones; i++){
				var bs_select = $('select#session_prop_birthstones'+i), bs_selected = bs_select.find('option:selected')
				if (bs_select.length > 0) { url = url +';'+ bs_selected.val(); }
			}

			$.ajax({

				url: url,
				type: 'post',
				success: function(data) {
					button.qtip({
						content: {
							text: '<div class="add_message"><p>This item has been added to your shopping bag.</p> <p><a href="#" class="continue">Continue Shopping</a> | <a href="'+cartURL+'">View Shopping Bag</a></p></div>'
						},
						container: $(this).parent(),
						show: {
							ready: true
						},
						hide: false,
						position: {
							corner: {
								tip: true,
								target: 'topMiddle',
								tooltip: 'bottomMiddle'
							},
							adjust: {
								y: - 2
							}
						},
						style: {
							'font-size': '10px',
							'font-weight': 'bold',
							'text-align': 'center',
			        color: '#333',
							border: {
								width: 2,
								radius: 2,
								color: '#666'
							},
							width: {
								max: 400
							},
							tip: {
								corner: 'bottomMiddle',
								size: {
									x: 10,
									y: 6
								}
							}
						},
						api: {
							onRender: function () {
								var self = this;

								$(self.elements.tooltip).find('a.continue').click(function() {
									$(self.elements.target).html('Add to shopping bag');
									self.destroy();
									
									return false;
								});
							}
						}
					});
				},
				error: function(req, textStatus, errorThrown) {
					alert('error');
				}
			});
			
			required.css('border-color','#000');
			$('.error').remove();
			
		}
	},
	
	home : {
		
		initialize : function() {
			dc.home.initializeCycle();
		},
		
		initializeCycle : function() {
			var $container = $('div.slide_container');
			
			var $buttons = $('<ul class="indicator"></ul>').appendTo($container);

			var $prev = $('<a href="#" class="prev">Previous</a>').prependTo($container);
			var $next = $('<a href="#" class="next">Next</a>').prependTo($container);
			

			var $slides = $('#home ul.slides').cycle({
				// fx:			'scrollHorz',
				speed:		300,
				timeout:	9000,
				prev:		$prev,
				next:		$next,
				after:		dc.home.cycleCallback
			});

			$slides.children().each(function(i) {
				// create input
				$('<li><a href="#" id="goto-'+i+'"></a></li>')
					// append to button container
					.appendTo($buttons)
					// bind click handler
					.click(function() {
						// cycle to the corresponding slide
						$slides.cycle(i);

						$(this).find('a').siblings().removeClass();

						$(this).find('a').addClass('current');
						return false;
					});
			});

			$buttons.find('li:first-child a').addClass('current');
		},
		
		cycleCallback : function(curr, next, opts) {
		    var index = opts.currSlide;

			$('ul.indicator li a').removeClass();
			$('a[id="goto-'+index+'"]').addClass('current');
		}
		
	},
	
	aboutUs : {
		
		initialize : function() {
			dc.aboutUs.initializeStaffMenu();
			dc.aboutUs.initializeNewsSlides();
			
			$('#accent_signup').optPopup(function() {
				var boxForm = $('#popup_container form');

				boxForm.validate({
					submitHandler: function(form) {
						var postUrl = boxForm.attr('action');

						if (postUrl.substr(0, 1) != "/") {
							postUrl = "/" + postUrl;
						}

						$.ajax({
							type: "POST",
							url: postUrl,
							data: boxForm.serialize(),
							beforeSend: function() {
								boxForm.find('input').attr('disabled', true).addClass('disabled');
								boxForm.find('textarea').attr('disabled', true).addClass('disabled');
							},
							success: function(data) {
								boxForm.find('h2').html(data);

								if (typeof (Cufon) != "undefined" && Cufon != null) {
									Cufon.refresh();
								}

								setTimeout(function() {
									close(); }, 3000);
							},
							error: function() {
								alert('An error has occurred.')
							}
						});
						return false;
					},
					invalidHandler: function(form, validator) {						
			      var errors = validator.numberOfInvalids();
			      if (errors) {
			        var message = errors == 1
			          ? "You've missed 1 required field. It has been highlighted"
			          : "You missed some required fields. They have been highlighted";
			
							alert(message);
			      }
					}
				});
			});
		},
		
		initializeStaffMenu : function() {
			$('#staff_menu').kwicks({
				max: 370,
				spacing: 0
			});
		},
		
		initializeNewsSlides : function() {
			var $buttons = $('ul.indicator');

			var $container = $('#news_slides ul.slides').cycle({
				fx:			'scrollHorz',
				speed:		500,
				timeout:	0,
				prev:		'div.slide_container a.prev',
				next:		'div.slide_container a.next',
				after:		dc.home.cycleCallback
			});

			$container.children().each(function(i) {
				// create input
				$('<li><a href="#" id="goto-'+i+'"></a></li>')
					// append to button container
					.appendTo($buttons)
					// bind click handler
					.click(function() {
						// cycle to the corresponding slide
						$container.cycle(i);

						$(this).find('a').siblings().removeClass();

						$(this).find('a').addClass('current');
						return false;
					});
			});

			$buttons.find('li:first-child a').addClass('current');
		},
		
		video : {
			
			initialize: function() {
				$('#video_list li').each(function(i) {
					if (i % 3 == 2) {
						$(this).css('margin-right', 0);
					}
				});
			}
		}
	},
	
	education: {
		initialize : function() {
			dc.education.initializeCycle();
		},
		
		initializeCycle : function() {
			var $container = $('#content_slides').cycle({
				fx:			'scrollHorz',
				speed:		500,
				timeout:	0
			});
			
			var $links = $('ul.navigation a');
			
			$('#cut_link').click(function() {
				$container.cycle(0);
				$links.removeClass();
				$(this).addClass('current');
				Cufon.refresh();
				return false;
			});
			
			$('#carat_link').click(function() {
				$container.cycle(1);
				$links.removeClass();
				$(this).addClass('current');
				Cufon.refresh();
				return false;
			});

			$('#clarity_link').click(function() {
				$container.cycle(2);
				$links.removeClass();
				$(this).addClass('current');
				Cufon.refresh();
				return false;
			});

			$('#color_link').click(function() {
				$container.cycle(3);
				$links.removeClass();
				$(this).addClass('current');
				Cufon.refresh();
				return false;
			});
		}
	},
	
	careers : {
		
		application : {
			
			initialize : function() {
				var $state_select = $('select#state');
				
				// Get the JSON list of states
				$.getJSON('/js/states.js', function(data) {
					$.each(data, function(i, state) {
						// Create the state options and append them to the select list
						$('<option value="'+i+'">'+state+'</option>').appendTo($state_select);
					});
				});
			}
		}
		
	},
	
	registerEvent : {
		
		application : {
			
			initialize : function() {
				var $state_select = $('select#state');
				
				// Get the JSON list of states
				$.getJSON('/js/states.js', function(data) {
					$.each(data, function(i, state) {
						// Create the state options and append them to the select list
						$('<option value="'+i+'">'+state+'</option>').appendTo($state_select);
					});
				});
			}
		}
		
	},
	
	shop : {
		
		initialize : function() {
			dc.shop.initializeBrowseMenu();
			//dc.shop.initializeDesignerJewelrySlides();
		},
		
		initializeBrowseMenu : function() {
			$('.browse_menu ul').browseMenu();
		},
		
		abc : {
			initialize : function() {
				if ($('div.featured_product div.items').children().size() > 1) {
					dc.shop.abc.initializeProductCycle();									
				}
			},
			
			initializeProductCycle : function() {
				var $container = $('div.featured_product div.items');
				
				$('<a href="#" id="prev_link">Prev</a>').insertBefore($container);
				$('<a href="#" id="next_link">Prev</a>').insertBefore($container);

				$container.cycle({
					fx:			'scrollHorz',
					speed:		500,
					timeout:	0,
					prev:		'#prev_link',
					next:		'#next_link',
					after:		dc.home.cycleCallback
				});
				
			}
		},
		
		designerJewelry : {
			
			initialize : function() {
				dc.shop.designerJewelry.initializeCycle();				
				dc.shop.designerJewelry.initializeInStoreTooltip();				
			},
			
			initializeCycle : function() {
				var $buttons = $('ul.indicator');

				var $container = $('#designer_jewelry_slides ul.slides').cycle({
					fx:			'scrollHorz',
					speed:		500,
					timeout:	0,
					prev:		'div.slide_container a.prev',
					next:		'div.slide_container a.next',
					after:		dc.home.cycleCallback
				});

				$container.children().each(function(i) {
					// create input
					$('<li><a href="#" id="goto-'+i+'"></a></li>')
						// append to button container
						.appendTo($buttons)
						// bind click handler
						.click(function() {
							// cycle to the corresponding slide
							$container.cycle(i);

							$(this).find('a').siblings().removeClass();

							$(this).find('a').addClass('current');
							return false;
						});
				});

				$buttons.find('li:first-child a').addClass('current');
			},
			
			initializeInStoreTooltip : function() {
				$('a.in_store').qtip({
					content: "Available only in store",
					show: { 
						solo: true,
						when: { event: 'mouseover' },
						effect: { type: 'slide' }
					},
					hide: 'mouseout',
					position: {
						corner: {
							tip: true,
							target: 'rightMiddle',
							tooltip: 'leftMiddle'
						},
						adjust: {
							x: 2,
							y: 0
						}
					},
					style: {
						background: '#333',
						'font-size': '10px',
						'font-weight': 'bold',
		        color: '#fff',
						border: {
							width: 2,
							radius: 2,
							color: '#333'
						},
						width: {
							max: 400
						},
						tip: {
							corner: 'leftMiddle',
							size: {
								x: 6,
								y: 10
							}
						}
					}
				}).click(function() { return false; });
				
			}			
		},
		
		results : {
			
			initialize : function() {
				//dc.shop.results.initializeProductCycle();
				
				$('#modify_list ul').browseMenu().hide();
								
				$('#modify_link').click(function() {
					$(this).siblings('ul').toggle();
					
					$('#modify_list').toggleClass('open');
					Cufon.refresh();
					
					return false;
				});
			},
			
			initializeProductCycle : function() {
				$('ul.product_display').each(function() {
					var self = $(this);
					
					if (self.children().size() > 1) {			
						var $prev = $('<a href="#" class="prev">Previous</a>').appendTo(self.parent());
						var $next = $('<a href="#" class="next">Next</a>').appendTo(self.parent());
					
						self.cycle({
							fx:			'scrollHorz',
							speed:		500,
							timeout:	0,
							prev:		$prev,
							next:		$next,
							after:		dc.shop.results.cycleCallback 
						}).css('padding-left', '0');		
					}
				});
				
				
				$(window).bind( 'hashchange', function(e) {
					$('div.brand_row').each(function() {
						var self = $(this),
						
						index = $.bbq.getState( self.attr( 'id' ), true ) || 0;
												
						self.find('ul.product_display').cycle(index);
					});
				});
				
				$(window).trigger( 'hashchange' );
			},
			
			cycleCallback : function(curr, next, opts) {
				var state = {},

				// Get the id of this .bbq widget.
				id = $( next ).closest( '.brand_row' ).attr( 'id' ),

				// Get the url from the link's href attribute, stripping any leading #.
				url = opts.currSlide;

				// Set the state!
				state[ id ] = url;
				$.bbq.pushState( state );
			},
			
			productPage : {
				initialize : function() {
					dc.shop.results.productPage.initializeEmailLink();
					dc.shop.results.productPage.initializeContactLink();
				},
				
				initializeEmailLink : function() {
					$('a.email_link').optPopup(function() {
						dc.shop.results.productPage.initialize();

						var boxForm = $('#popup_container form');

						boxForm.validate({
							submitHandler: function(form) {

								var postUrl = boxForm.attr('action');

								if (postUrl.substr(0, 1) != "/") {
									postUrl = "/" + postUrl;
								}

								$.ajax({
									type: "POST",
									url: postUrl,
									data: boxForm.serialize(),
									beforeSend: function() {
										boxForm.find('input').attr('disabled', true).addClass('disabled');
										boxForm.find('textarea').attr('disabled', true).addClass('disabled');
									},
									success: function(data) {
										boxForm.find('h2').html(data);

										if (typeof (Cufon) != "undefined" && Cufon != null) {
											Cufon.refresh();
										}

										setTimeout(function() {
											closePopup();
										}, 3000);
									}
								});

								dc.shop.results.productPage.initialize();

								return false;
							}
						});
					});					
				},

				initializeContactLink : function() {
					$('a.contact').optPopup(function() {
						dc.shop.results.productPage.initialize();

						var boxForm = $('#popup_container form');

						boxForm.validate({
							submitHandler: function(form) {

								var postUrl = boxForm.attr('action');

								if (postUrl.substr(0, 1) != "/") {
									postUrl = "/" + postUrl;
								}

								$.ajax({
									type: "POST",
									url: postUrl,
									data: boxForm.serialize(),
									beforeSend: function() {
										boxForm.find('input').attr('disabled', true).addClass('disabled');
										boxForm.find('textarea').attr('disabled', true).addClass('disabled');
									},
									success: function(data) {
										boxForm.find('h2').html(data);

										if (typeof (Cufon) != "undefined" && Cufon != null) {
											Cufon.refresh();
										}

										setTimeout(function() {
											closePopup();
										}, 3000);
									}
								});

								dc.shop.results.productPage.initialize();

								return false;
							}
						});
					});					
				}
			}
		}
	}
};

$(function() {
	dc.global.initialize();
	
	var birthstones = $('select.birthstone'),
			price_wrapp = $('li.price'),
			original_price = parseInt(price_wrapp.text().replace('Price: $',''));
	
	if ( birthstones.length ) {
		
		birthstones.change(function() {
			
			var add_on = 0,
					selected = $(this).find('option:selected'),
					price = parseInt(price_wrapp.text().replace('Price: $','')),
					nums = $.map(birthstones, function(value, index) {
						var _selected = $(value).find('option:selected');
						return _selected.index() === 0 ? 0 : parseInt(_selected.text().match(/\$[0-9]+/gi).toString().replace('$',''));
					});
			
			for ( var i = 0; i < nums.length; i++ ) {
				add_on += nums[i];
			}
			
			price_wrapp.text('Price: $' + ( original_price + add_on ) );
			
		});
		
	}
	
});

/* Minor Plugins */
 
 
(function($) {
	 
	/* Plugin for the drop-down page menus */
 
	$.fn.dropdownMenu = function() {
		var menu = this;
		
		menu.find('li').mouseover(function() {
			$(this).children('ul:hidden').show();
		}).mouseout(function() {
			$(this).children('ul:visible').hide();
		});
		
		return this;
	};
	
	$.fn.dropdown = function() {
		var menu = this;
		
		menu.find('li').toggle(function() {
			$(this).children('ul:hidden').show();
		}, function() {
			$(this).children('ul:visible').hide();
		});
		
		return this;
	};
	
	
	/* Browse menu */
	
	$.fn.browseMenu = function() {
		$(this).find('ul:not(:first)').hide();
		$(this).find('a.select').parent('li').show().parent('ul').show().parent('li').show().parent('ul').show();
		
		this.find('a').click(function() {
			$(this).parent().siblings().children('ul').slideUp();
		
			var child = $(this).parent().children('ul');
		
			if (child.is(':hidden')) {
				child.slideDown('slow');
			}
			else {
				child.slideUp('slow');
			}
					
			if ($(this).attr('href') == "#") {
				return false;
			}			
		});
		
		return this;
	};
	
	
	/* Dimming Plugin */
	
	$.fn.dimming = function() {
		
		function show(element) {
			element.children('.dim').animate({ opacity: 1 }, 300);
			element.children('.hide').fadeIn(300);
		}

		function hide(element) {
			element.children('.dim').animate({ opacity: 0.7 }, 300);
			element.children('.hide').fadeOut(300);
		}
		
		return this.each(function() {
			var self = $(this);
			
			self.hover(function() {
				show(self);
			}, function() {
				hide(self);
			});
		});
	};
	
	$.fn.nmcDropDown = function(options) {
	
        // build main options before element iteration
        var opts = $.extend({}, $.fn.nmcDropDown.defaults, options);

        // iterate each matched element
        return this.each(function() {
            var menu = $(this);
            submenus = menu.children('li:has('+opts.submenu_selector+')');
            
            if (opts.fix_IE) {
                // Fix IE 6+7 z-index bug
                menu.css('z-index', 51)
                    .parents().each(function(i) {
                        if ($(this).css('position') == 'relative') {
                            $(this).css('z-index', (i + 52));
                        }
                    });
                submenus.children(opts.submenu_selector).css('z-index', 50);
            }

            if (opts.fix_IE_less) {
                // Fix IE 6+7 z-index bug
                menu.css('z-index', 31)
                    .parents().each(function(i) {
                        if ($(this).css('position') == 'relative') {
                            $(this).css('z-index', (i + 32));
                        }
                    });
                submenus.children(opts.submenu_selector).css('z-index', 30);
            }

			
            // Function that is called to show the submenu
            over = function() {
                $(this).addClass(opts.active_class)
                       .children(opts.submenu_selector).animate(opts.show, opts.show_speed);
                return false;
            };
			
            // Function that is called to hide the submenu
            out = function() {
                $(this).removeClass(opts.active_class)
                       .children(opts.submenu_selector).animate(opts.hide, opts.hide_speed);
                return false;
            };
			
            // Show and hide the sub-menus
            if (opts.trigger == 'click') {
                submenus
                    .toggle(over, out)
                    .children(opts.submenu_selector).hide();
            } else if ($().hoverIntent) {
                submenus
                    .hoverIntent({
                        interval: opts.show_delay, 
                        over: over, 
                        timeout: opts.hide_delay, 
                        out: out
                    }).children(opts.submenu_selector).hide();
            } else {
                submenus
                    .hover(over, out)
                    .children(opts.submenu_selector).hide();
            }
        });
    };

    // Default options
    $.fn.nmcDropDown.defaults = {
        trigger: 'hover',           // Event to show and hide sub-menu - hover or click
        active_class: 'open',       // Class to give open menu items
        submenu_selector: 'ul',     // The element immediately below the <li> containing the sub-menu
        show: {opacity: 'show'},    // Effect(s) to use when showing the sub-menu
        show_speed: 300,            // Speed of the show transition
        show_delay: 50,             // Delay before the sub-menu is show (requires HoverIntent)
        hide: {opacity: 'hide'},    // Effect(s) to use when hiding the sub-menu
        hide_speed: 200,            // Speed of the hide transition
        hide_delay: 100,            // Delay before the sub-menu is hidden (requires HoverIntent)
        fix_IE: true,               // IE 6 and 7 have problems with z-indexes. This tries to fix them
        fix_IE_less: false          // IE 6 and 7 have problems with z-indexes. This tries to fix them
    };
	
})(jQuery);

/**
* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
* 
* @param  f  onMouseOver function || An object with configuration options
* @param  g  onMouseOut function  || Nothing (use configuration options object)
* @author    Brian Cherne <brian@cherne.net>
*/
(function($){$.fn.hoverIntent=function(f,g){var cfg={sensitivity:7,interval:100,timeout:0};cfg=$.extend(cfg,g?{over:f,out:g}:f);var cX,cY,pX,pY;var track=function(ev){cX=ev.pageX;cY=ev.pageY;};var compare=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);if((Math.abs(pX-cX)+Math.abs(pY-cY))<cfg.sensitivity){$(ob).unbind("mousemove",track);ob.hoverIntent_s=1;return cfg.over.apply(ob,[ev]);}else{pX=cX;pY=cY;ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}};var delay=function(ev,ob){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);ob.hoverIntent_s=0;return cfg.out.apply(ob,[ev]);};var handleHover=function(e){var p=(e.type=="mouseover"?e.fromElement:e.toElement)||e.relatedTarget;while(p&&p!=this){try{p=p.parentNode;}catch(e){p=this;}}if(p==this){return false;}var ev=jQuery.extend({},e);var ob=this;if(ob.hoverIntent_t){ob.hoverIntent_t=clearTimeout(ob.hoverIntent_t);}if(e.type=="mouseover"){pX=ev.pageX;pY=ev.pageY;$(ob).bind("mousemove",track);if(ob.hoverIntent_s!=1){ob.hoverIntent_t=setTimeout(function(){compare(ev,ob);},cfg.interval);}}else{$(ob).unbind("mousemove",track);if(ob.hoverIntent_s==1){ob.hoverIntent_t=setTimeout(function(){delay(ev,ob);},cfg.timeout);}}};return this.mouseover(handleHover).mouseout(handleHover);};})(jQuery);

/*
 * Metadata - jQuery plugin for parsing metadata from elements
 *
 * Copyright (c) 2006 John Resig, Yehuda Katz, J�örn Zaefferer, Paul McLanahan
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.metadata.js 3640 2007-10-11 18:34:38Z pmclanahan $
 *
 */

/**
 * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 * in the JSON will become a property of the element itself.
 *
 * There are four supported types of metadata storage:
 *
 *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
 *          
 *   class: Inside the class attribute, wrapped in curly braces: { }
 *   
 *   elem:  Inside a child element (e.g. a script tag). The
 *          name parameter indicates *which* element.
 *   html5: Values are stored in data-* attributes.
 *          
 * The metadata for an element is loaded the first time the element is accessed via jQuery.
 *
 * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 * 
 * @name $.metadata.setType
 *
 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("class")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from the class attribute
 * 
 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("attr", "data")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a "data" attribute
 * 
 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 * @before $.metadata.setType("elem", "script")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a nested script element
 * 
 * @example <p id="one" class="some_class" data-item_id="1" data-item_label="Label">This is a p</p>
 * @before $.metadata.setType("html5")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a series of data-* attributes
 *
 * @param String type The encoding type
 * @param String name The name of the attribute to be used to get metadata (optional)
 * @cat Plugins/Metadata
 * @descr Sets the type of encoding to be used when loading metadata for the first time
 * @type undefined
 * @see metadata()
 */

(function($) {

$.extend({
  metadata : {
    defaults : {
      type: 'class',
      name: 'metadata',
      cre: /({.*})/,
      single: 'metadata'
    },
    setType: function( type, name ){
      this.defaults.type = type;
      this.defaults.name = name;
    },
    get: function( elem, opts ){
      var settings = $.extend({},this.defaults,opts);
      // check for empty string in single property
      if ( !settings.single.length ) settings.single = 'metadata';
      
      var data = $.data(elem, settings.single);
      // returned cached data if it already exists
      if ( data ) return data;
      
      data = "{}";
      
      var getData = function(data) {
        if(typeof data != "string") return data;
        
        if( data.indexOf('{') < 0 ) {
          data = eval("(" + data + ")");
        }
      }
      
      var getObject = function(data) {
        if(typeof data != "string") return data;
        
        data = eval("(" + data + ")");
        return data;
      }
      
      if ( settings.type == "html5" ) {
        var object = {};
        $( elem.attributes ).each(function() {
          var name = this.nodeName;
          if(name.match(/^data-/)) name = name.replace(/^data-/, '');
          else return true;
          object[name] = getObject(this.nodeValue);
        });
      } else {
        if ( settings.type == "class" ) {
          var m = settings.cre.exec( elem.className );
          if ( m )
            data = m[1];
        } else if ( settings.type == "elem" ) {
          if( !elem.getElementsByTagName ) return;
          var e = elem.getElementsByTagName(settings.name);
          if ( e.length )
            data = $.trim(e[0].innerHTML);
        } else if ( elem.getAttribute != undefined ) {
          var attr = elem.getAttribute( settings.name );
          if ( attr )
            data = attr;
        }
        object = getObject(data.indexOf("{") < 0 ? "{" + data + "}" : data);
      }
      
      $.data( elem, settings.single, object );
      return object;
    }
  }
});

/**
 * Returns the metadata object for the first member of the jQuery object.
 *
 * @name metadata
 * @descr Returns element's metadata object
 * @param Object opts An object contianing settings to override the defaults
 * @type jQuery
 * @cat Plugins/Metadata
 */
$.fn.metadata = function( opts ){
  return $.metadata.get( this[0], opts );
};

})(jQuery);
