if(!String.prototype.trim) {
	String.prototype.trim = function () {
		return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
	};
}
// ------------------------------------------------------------------------ //

/**
 * jQuery mousehold plugin - fires an event while the mouse is clicked down.
 * Additionally, the function, when executed, is passed a single
 * argument representing the count of times the event has been fired during
 * this session of the mouse hold.
 *
 * @author Remy Sharp (leftlogic.com)
 * @date 2006-12-15
 * @example $("img").mousehold(200, function(i){  })
 * @desc Repeats firing the passed function while the mouse is clicked down
 *
 * @name mousehold
 * @type jQuery
 * @param Number timeout The frequency to repeat the event in milliseconds
 * @param Function fn A function to execute
 * @cat Plugin
 */
jQuery.fn.mousehold = function(timeout, f) {
	if (timeout && typeof timeout == 'function') {
		f = timeout;
		timeout = 100;
	}
	if (f && typeof f == 'function') {
		var timer = 0;
		var fireStep = 0;
		return this.each(function() {
			jQuery(this).mousedown(function() {
				fireStep = 1;
				var ctr = 0;
				var t = this;
				timer = setInterval(function() {
					ctr++;
					f.call(t, ctr);
					fireStep = 2;
				}, timeout);
			});

			var clearMousehold = function() {
				clearInterval(timer);
				if (fireStep == 1) {
					f.call(this, 1);
				}
				fireStep = 0;
			};
			
			jQuery(this).mouseout(clearMousehold);
			jQuery(this).mouseup(clearMousehold);
		});
	}
};

/**
 * jQuery.ScrollTo - Easy element scrolling using jQuery.
 * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 5/25/2009
 * @author Ariel Flesler
 * @version 1.4.2
 *
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 */
;(function(d){var k=d.scrollTo=function(a,i,e){d(window).scrollTo(a,i,e)};k.defaults={axis:'xy',duration:parseFloat(d.fn.jquery)>=1.3?0:1};k.window=function(a){return d(window)._scrollable()};d.fn._scrollable=function(){return this.map(function(){var a=this,i=!a.nodeName||d.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!i)return a;var e=(a.contentWindow||a).document||a.ownerDocument||a;return d.browser.safari||e.compatMode=='BackCompat'?e.body:e.documentElement})};d.fn.scrollTo=function(n,j,b){if(typeof j=='object'){b=j;j=0}if(typeof b=='function')b={onAfter:b};if(n=='max')n=9e9;b=d.extend({},k.defaults,b);j=j||b.speed||b.duration;b.queue=b.queue&&b.axis.length>1;if(b.queue)j/=2;b.offset=p(b.offset);b.over=p(b.over);return this._scrollable().each(function(){var q=this,r=d(q),f=n,s,g={},u=r.is('html,body');switch(typeof f){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(f)){f=p(f);break}f=d(f,this);case'object':if(f.is||f.style)s=(f=d(f)).offset()}d.each(b.axis.split(''),function(a,i){var e=i=='x'?'Left':'Top',h=e.toLowerCase(),c='scroll'+e,l=q[c],m=k.max(q,i);if(s){g[c]=s[h]+(u?0:l-r.offset()[h]);if(b.margin){g[c]-=parseInt(f.css('margin'+e))||0;g[c]-=parseInt(f.css('border'+e+'Width'))||0}g[c]+=b.offset[h]||0;if(b.over[h])g[c]+=f[i=='x'?'width':'height']()*b.over[h]}else{var o=f[h];g[c]=o.slice&&o.slice(-1)=='%'?parseFloat(o)/100*m:o}if(/^\d+$/.test(g[c]))g[c]=g[c]<=0?0:Math.min(g[c],m);if(!a&&b.queue){if(l!=g[c])t(b.onAfterFirst);delete g[c]}});t(b.onAfter);function t(a){r.animate(g,j,b.easing,a&&function(){a.call(this,n,b)})}}).end()};k.max=function(a,i){var e=i=='x'?'Width':'Height',h='scroll'+e;if(!d(a).is('html,body'))return a[h]-d(a)[e.toLowerCase()]();var c='client'+e,l=a.ownerDocument.documentElement,m=a.ownerDocument.body;return Math.max(l[h],m[h])-Math.min(l[c],m[c])};function p(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);

// from https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/indexOf
if(!Array.prototype.indexOf){Array.prototype.indexOf=function(elt){var len=this.length>>>0;var from=Number(arguments[1])||0;from=(from<0)?Math.ceil(from):Math.floor(from);if(from<0)from+=len;for(;from<len;from++){if(from in this&&this[from]===elt)return from;}return-1;};}

var XH = { };
XH.settings = { };

XH.DeviceSelector = function (aId, aOptions) {
	var selector = this;
	aOptions = aOptions || { };
	aOptions.type = aOptions.type || 'classic';
	
	selector.qWrapper = $('#' + aId);
	
	if(!selector.qWrapper.length) {
		throw 'XH::DeviceSelector:element with id[' + aId + '] cannot be found';
	}
	/*
	if(aOptions.stylesheet) {
		$('head').append('<link rel="stylesheet" type="text/css" href="' + aOptions.stylesheet + '" />');
	}
	*/
	selector.qWrapper.show();
	
	//$('head').append('<script src="/EUROPE_NOKIA_COM_3/common_items/scripts/jquery-ui-1.8.1.custom.min.js" type="text/javascript"></script>');
	
	selector.qDeviceCont = selector.qWrapper.find('.ds-device-container');
	selector.qDeviceList = selector.qDeviceCont.find('.ds-device-list');
	
	selector.qNotFoundCont = selector.qDeviceCont.find('.ds-not-found');
	selector.qLoadingCont = selector.qDeviceCont.find('.ds-loading');
	selector.qLoadingFailedCont = selector.qDeviceCont.find('.ds-loading-failed');
	
	selector.qShowAllDevicesBtn = selector.qWrapper.find('.ds-btn-show-all-devices');
	
	selector.elemSlider = selector.qDeviceCont.find('.ds-slider').get(0);
	selector.elemSliderLeftBtn = $('.ds-slider-btn-left', selector.elemSlider).get(0);
	selector.elemSliderHandle = $('.ds-slider-handler', selector.elemSlider).get(0);
	selector.elemSliderRightBtn = $('.ds-slider-btn-right', selector.elemSlider).get(0);
	selector.elemSliderGotoStart = $('.ds-slider-start', selector.elemSlider).get(0);
	selector.elemSliderGotoEnd = $('.ds-slider-end', selector.elemSlider).get(0);
	
	selector.qSearchInput = selector.qWrapper.find('input.ds-search');
	selector.textSearchPrefills = [ ];
	selector.uiSlider = null;
	selector.devices = { };
	selector.elemSelected = null;
	
	// search
	selector.qSearchInput.each(function (i) {
		selector.textSearchPrefills[i] = this.value;
		
		$(this).keyup(function (e) {
			selector.searchFor(this.value);
		});
		
		$(this).focus(function (e) {
			if(this.value === selector.textSearchPrefills[i]) {
				this.value = '';
			}
		});
		
		$(this).blur(function (e) {
			if(this.value === '') {
				this.value = selector.textSearchPrefills[i];
			}
		});
		
		this.value = selector.textSearchPrefills[i];
	});
	
	// show all buttons
	selector.qShowAllDevicesBtn.click(function (e) {
		selector.searchFor('');
		selector.qSearchInput.each(function (i) {
			$(this).val('');
		});
		e.preventDefault();
	});
	
	// slider
	$(selector.elemSlider).css('visibility', 'visible');
	
	selector.uiSlider = $(selector.elemSliderHandle).slider({
		step: 1,
		animate: true,
		stop: function (e, ui) {
			selector._moveToItem(ui.value);
		}
	});
	/*
	// set handler width
	$(selector.elemSliderHandle).width(
		$(selector.elemSlider).width() - (
			$(selector.elemSliderLeftBtn).width() + $(selector.elemSliderRightBtn).width() +
			parseInt($(selector.elemSliderHandle).css('margin-left'), 10) +
			parseInt($(selector.elemSliderHandle).css('margin-right'), 10)
		)
	);
	*/
	$(selector.elemSliderLeftBtn).mousehold(200, function () {
		var val = selector.uiSlider.slider('value') - 1;
		
		val = val >= 0 ? val : 0;
		
		selector.uiSlider.slider('value', val);
		selector._moveToItem(val);
	});
	
	$(selector.elemSliderRightBtn).mousehold(200, function () {
		var val = selector.uiSlider.slider('value') + 1;
		
		val = val >= 0 ? val : 0;
		
		selector.uiSlider.slider('value', val);
		selector._moveToItem(val);
	});
	
	$(selector.elemSliderGotoStart).click(function () {
		selector.uiSlider.slider('value', 0);
		selector._moveToItem(0);
	});
	
	$(selector.elemSliderGotoEnd).click(function () {
		selector.uiSlider.slider('value', selector.uiSlider.slider('option', 'max') - 1);
		selector._moveToItem(selector.uiSlider.slider('option', 'max') - 1);
	});
	
	selector.deviceTemplate = aOptions.deviceTemplate || [
		'<a href="#" id="ds-item-{device id}">',
			'<img src="{device image}" alt="{device name}" />',
			'<br />',
			'{device name}',
		'</a>'
	].join('');
	
	selector.screens = aOptions.screens || [ ];
	
	selector.qDeviceList.delegate('a', 'click', function(e) {
		window.setTimeout(function () {
			$.scrollTo(selector.qWrapper, 400);
		}, 50);
		

		if(selector.elemSelected && $('a', selector.elemSelected).attr('id') === this.id) {
			selector.unselect(this.id.substring(8));
		}
		else {
			selector.select(this.id.substring(8));
		}
		e.preventDefault();
	});
	
	selector.select(function (e, id) {
		var elem = selector.devices[id].element,
			children = selector.qDeviceList.get(0).childNodes,
			x, lex;
		
		for(x = 0, lex = children.length; x < lex; x++) {
			if(children[x] === elem) {
				var index = selector.qDeviceList.find('li:visible').index(elem);
				selector.uiSlider.slider('value', index);
				selector._moveToItem(index);
			}
		}
		
		if(selector.elemSelected) {
			$(selector.elemSelected).removeClass('selected');
		}
		
		selector.elemSelected = elem;
		$(selector.elemSelected).addClass('selected');
	});
	
	selector.unselect(function (e, id) {
		if(selector.elemSelected) {
			$(selector.elemSelected).removeClass('selected');
		}
		
		selector.elemSelected = null;
	});
	
	selector._devicechange(function (e) {

		selector.qDeviceList.show();
		var itemWidth = 100,//selector.qDeviceList.find('li:first').outerWidth(true), //selector.itemOuterWidth,
			items = selector.qDeviceList.find('li:visible').length,
			listLength = itemWidth * items;
		

		if($.browser.msie && $.browser.version < 7) {
			listLength += 10;
			//selector.elemSliderHandle.style.display = 'inline';
		}
		
		selector.qDeviceList.width(listLength);
		
		if(listLength <= selector.qDeviceCont.width()) {
			$(selector.elemSlider).css('visibility', 'hidden'); /// aaaaa toggle thissss
		}
		else {
			$(selector.elemSlider).css('visibility', 'visible');
		}
		
		if(items === 0) {
			selector.qNotFoundCont.show();
			selector.qDeviceList.hide();
		}
		else {
			selector.qNotFoundCont.hide();
			selector.qDeviceList.show();
		}
		
		selector.uiSlider.slider('option', 'max', items ? items - 1 : 0);

		selector.uiSlider.slider('value', 0);/*
		window.setTimeout(function () {
			selector._moveToItem(0);
		}, 200);*/
		selector._moveToItem(0);
	});
	/*
	$(window).resize(function () {
		selector._devicechange();
	});
	*/
	$(selector.elemSlider).css('visibility', 'hidden');
	selector.qDeviceList.hide();
	selector.qNotFoundCont.hide();
	selector.qLoadingCont.show();
	selector.qLoadingFailedCont.hide();
};

XH.DeviceSelector.prototype._moveToItem = function (aItemNumber) {

	var itemWidth = 100,//this.qDeviceList.find('li:first').outerWidth(true), //this.qDeviceList.find('li:first').outerWidth(true),
		contentAreaHalf = this.qDeviceCont.width() / 2,
		margin = -(aItemNumber * itemWidth) + (contentAreaHalf - itemWidth / 2);
	
	if(margin > 0) {
		margin = 0;
	}
	/*
	if($.browser.msie && $.browser.version < 8) {
		this.elemSliderHandle.style.left = '0px';
	}
	*/
	if((-margin) > (this.qDeviceList.width() - this.qDeviceCont.width())) {
		margin = -this.qDeviceList.width() + this.qDeviceCont.width();
	}
	
	if(this.qDeviceList.width() > this.qDeviceCont.width()) {
		//this.qDeviceList.css('margin-left', Math.round(margin) + 'px');
		this.qDeviceList.animate({'margin-left': Math.round(margin) + 'px'}, 200);
	}
	else {
		//this.qDeviceList.css('margin-left', 0);
		this.qDeviceList.animate({'margin-left': 0 + 'px'}, 200);
	}
};

XH.DeviceSelector.prototype.searchFor = function (aQuery) {

	var prop,
		device,
		devices = this.devices,
		qVis;
	
	aQuery = aQuery.toLowerCase();
	
	for(prop in devices) {
		if(devices.hasOwnProperty(prop)) {
			device = devices[prop];
			
			if(device.name.indexOf(aQuery) !== -1) {
				$(device.element).show();
			}
			else {
				$(device.element).hide();
			}
		}
	}
	
	this._devicechange();
	
	qVis = this.qDeviceList.find('li:visible');
	
	if(qVis.length === 1) {
		this.select($('a', qVis).get(0).id.substring(8));
	}
};
/*
XH.DeviceSelector.prototype._changeScreen = function (aScreen, aState) {
	if(aState === 'show' || aState === 'hide') {
		switch (aScreen) {
			case 'loading':
				this.qLoadingCont[aState]();
				break;
			case 'loading-failed':
				this.qLoadingFailedCont[aState]();
				break;
			case 'search-not-found':
				this.qNotFoundCont[aState]();
				break;
			case 'device-list':
				this.qDeviceList[aState]();
				break;
			default:
		}
	}
};
*/
XH.DeviceSelector.prototype.select = function (aArg) { // this should work
	
	if(typeof aArg === 'function') {

		this.qDeviceList.bind('selectdevice', aArg);
	}
	else {

		this.qDeviceList.trigger('selectdevice', aArg);
	}
};

XH.DeviceSelector.prototype.unselect = function (aArg) { // this should work
	
	if(typeof aArg === 'function') {

		this.qDeviceList.bind('unselectdevice', aArg);
	}
	else {

		this.qDeviceList.trigger('unselectdevice', aArg);
	}
};

XH.DeviceSelector.prototype._devicechange = function (aArg) { // this should work
	
	if(typeof aArg === 'function') {

		this.qDeviceList.bind('devicechange', aArg);
	}
	else {

		this.qDeviceList.trigger('devicechange', aArg);
	}
};

// XH.getContext sets the context to the args and others can be accessed through id
/* no time to develop this, using old add method
XH.DeviceSelector.prototype.add = function (aDevices) {
	var li,
		x, lex;
	
	if(aDevices) {
		for(x = 0, lex = aDevices.length; x < lex; x++) {
			li = document.createElement('li');
			
			//li.innerHTML += XH.supplement(this.deviceTemplate, XH.getContext('device', aDevices[x]));
			li.innerHTML += XH.supplement(this.deviceTemplate, XH.getContext('device', aDevices[x]));
		}
		
		$(this.elemDeviceList).append(content);
	}
}*/

XH.DeviceSelector.prototype.add = function (aId, aDevice) {
	var li = document.createElement('li');
	
	li.innerHTML = this.deviceTemplate.replace(/\{device name\}/g, aDevice.name)
		.replace(/\{device image\}/g, aDevice.image)
		.replace(/\{device id\}/g, aId);
	
	this.qDeviceList.append(li);
	
	this.devices[aId] = {
		name: aDevice.name.toLowerCase(),
		element: li,
		index: $(this.qDeviceList).get(0).childNodes.length - 2
	};
	
	this._devicechange();
};

XH.DeviceSelector.prototype.addAll = function (aIdList, aDevices) {

	var li,
		x, lex,
		template = '',
		device,
		letterDevices = [ ], numberDevices = [ ]
	
	aIdList.sort();
	
	for(x = 0, lex = aIdList.length; x < lex; x++) {
		if(isNaN(aIdList[x].charAt(6))) {
			letterDevices.push(aIdList[x]);
		}
		else {
			numberDevices.push(aIdList[x]);
		}
	}
	
	aIdList = letterDevices.concat(numberDevices);
	
	this.qDeviceList.hide();
	this.qLoadingCont.show();
	
	for(x = 0, lex = aIdList.length; x < lex; x++) {
		li = document.createElement('li');
		template = this.deviceTemplate;
		device = aDevices[aIdList[x]];
		
		if(device && device.name && device.image) {
			li.innerHTML = template.replace(/\{device name\}/g, device.name)
				.replace(/\{device image\}/g, device.image)
				.replace(/\{device id\}/g, aIdList[x]);
			
			this.qDeviceList.append(li);
			
			this.devices[aIdList[x]] = {
				name: device.name.toLowerCase(),
				element: li,
				index: $(this.qDeviceList).get(0).childNodes.length - 2
			};
		}
	}
	
	this.qLoadingCont.hide();
	this.qDeviceList.show();
	
	//this._devicechange();
	this.searchFor('');
	this.autoSelectDevice();
};

XH.DeviceSelector.prototype.autoSelectDevice = function () {
    var seek = location.search.substring(1);
    var str = seek.split("");
    var pos = 0,
        num, afternum, fullname = "";
    seek = seek.toLowerCase();
    seek = seek.replace(/[^a-z 0-9\-]+/g, '');
    var idConvTable = {
        '8800carbonarte': 'nokia-8800-carbon-arte',
        '8800goldarte': 'nokia-8800-gold-arte',
        'c3': 'nokia-c3-00',
        'c6-00': 'nokia-c6-00',
        'e71x': 'nokia-e71x',
        'n86': 'nokia-n86-8mp',
        'x3': 'nokia-x3-00',
        'nx6': 'nokia-x6-00'
    };
    if (idConvTable[seek]) {
        fullname = idConvTable[seek]
    } else {

        //conversion - all ids to new ones
        if (seek.indexOf("nokia") != -1) {
            fullname = seek;
        } else {
            for (var x = 0, lex = str.length; x < lex; x++) {
                if (!isNaN(str[x])) {
                    pos = x;
                }
                var last = x;
            }

            if ((seek.substr(pos + 1, 1) == "i")) {
                num = (seek.substring(0, pos + 2));
                afternum = (seek.substring(pos + 2, last + 1));
            } else {
                num = (seek.substring(0, pos + 1));
                afternum = (seek.substring(pos + 1, last + 1));
            }

            if (!afternum == "") {
                fullname = "nokia-" + num + "-" + afternum;
            } else {
                fullname = "nokia-" + num;
            }
        }
        //end of conversion
    }
    var device = $('#ds-item-' + fullname).get(0);
    var dev = this;

    if (device) {
        setTimeout(function () {
            dev.select(fullname);
        }, 250);

    }
};

XH.DeviceSelector.prototype.deviceSort = function (a, b) {
	return a < b; 
};

XH.DeviceSelector.prototype.clear = function () {

	$(this.elemDeviceList).html('');
	this.devices = [ ];
	this._devicechange();
};

XH.Package = function (files, selector) {
	this.id = +new Date();
	this.files = files;
	this.selector = selector;
	this.documents = [ ];
	this.data = { };
	this.lists = { };
	this.defaults = { };
	this.groups = { };
	
	var that = this;
	

	

	
	function loadFiles(files, whenReady) {
		var fileData = [ ],
			x, lex;
		
		function areAllLoaded() {
			for(var x = 0, lex = fileData.length; x < lex; x++) {
				if(!fileData[x].isLoaded) {

					return false;
				}
			}

			return true;
		}
		
		function getDocuments() {
			var result = [ ],
				x, lex;
			
			for(x = 0, lex = fileData.length; x < lex; x++) {
				if(fileData[x].xmlDoc) {
					result.push(fileData[x].xmlDoc);
				}
			}
			

			
			return result;
		}
		
		function loadFile(fd) {
			$.ajax({
				url: fd.url + '?' + (+new Date), // !!! important fix for ie6, prevent ie6 cacheing
				dataType: 'xml',
				complete: function (xhr) {

					fd.xmlDoc = xhr.responseXML;
					fd.isLoaded = true;
					
					if(!fd.xmlDoc) {

					}
					
					if(areAllLoaded()) {
						if(typeof whenReady === 'function') {
							whenReady(getDocuments());
						}
					}
				}
			});
		}
		
		for(x = 0, lex = files.length; x < lex; x++) {
			fileData[x] = {
				url: files[x],
				isLoaded: false,
				xmlDoc: null
			};
			
			loadFile(fileData[x]);
		}
	}

	loadFiles(files, function (documents) {
		that.documents = documents;
		that.ready();
	});
	
	this.ready(function (e) {

		
		that._processResponse(that.documents, that.selector);
	});
};

XH.Package.prototype.ready = function (callback) {
	if(typeof callback === 'function') {

		$(window).bind('XH.' + this.id + '-ready', callback);
	}
	else {

		$(window).trigger('XH.' + this.id + '-ready');
	}
};

XH.Package.prototype._processResponse = function (documents, selector) {
	var x, lex,
		y, ley,
		docElem,
		docElemChildren,
		child,
		childId,
		elemName,
		elemCont;
		

	
	for(x = 0, lex = documents.length; x < lex; x++) {

		
		if(documents[x]) {

			docElem = documents[x].documentElement;
			docElemChildren = docElem.childNodes;
			
			for(y = 0, ley = docElemChildren.length; y < ley; y++) {
				child = docElemChildren[y];
				if(child.nodeType === 1) {
					childId = child.getAttribute('id');
					if(childId && this._isItForMe(child.getAttribute('for'), child.getAttribute('notFor'))) {

						elemName = docElemChildren[y].nodeName;
						
						if(!this.data[elemName]) {
							this.data[elemName] = { };
							this.lists[elemName] = [ ];
						}
						
						elemCont = this.data[elemName];
						
						if(!elemCont[childId]) {
							this.lists[elemName].push(childId);
						}
						
						this._addItem(elemCont, child, childId);
						
						if(elemName === 'defaults') {
							this._addDefault(this.get('defaults', childId), childId);
						}
						
						if(elemName === 'group') {
							this._addGroup(child, childId);
						}
					}
				}
			}
		}
	}
};

function isElement(node) {
	return node.nodeType === 1;
}

function isWhitespace(str) {
	return str.match(/^\s+$/);
}

XH.Package.prototype._getTextContent = function (node) {
	var children = node.childNodes,
		x, lex,
		content = '';
	
	for(x = 0, lex = children.length; x < lex; x++) {
		if(isElement(children[x])) {
			return null;
		}
		
		if(!isWhitespace(children[x].nodeValue)) {
			content += children[x].nodeValue;
		}
	}
	
	return content;
};

XH.Package.prototype._normalizeAttribute = function (aAttr) {
	return aAttr.replace(' ', '').indexOf(',') === -1 ? aAttr = [aAttr] : aAttr.split(',');
};

XH.Package.prototype._isItForMe = function (aFor, aNotFor) {
	var x, lex;
	
	aFor = this._normalizeAttribute(aFor || 'all');
	aNotFor = this._normalizeAttribute(aNotFor || '');
	

	
	for(x = 0, lex = aNotFor.length; x < lex; x++) {
		if(this._isGroup(aNotFor[x])) {
			if(this._isInGroup(aNotFor[x], this.selector)) {
				return false;
			}
		}
		else {
			if(aNotFor[x] === this.selector) {
				return false;
			}
		}
	}
	
	for(x = 0, lex = aFor.length; x < lex; x++) {
		if(this._isGroup(aFor[x])) {
			if(this._isInGroup(aFor[x], this.selector)) {
				return true;
			}
		}
		else {
			if(aFor[x] === this.selector || aFor[x] === 'all') {
				return true;
			}
		}
	}
	
	return false;
};

XH.Package.prototype._addItem = function (obj, elem, elemId) {
	var textContent = this._getTextContent(elem),
		children,
		child,
		elemName,
		x, lex;
	
	
	if(textContent !== null) {
		obj[elemId] = textContent;
	}
	else {
		children = elem.childNodes;
		if(!obj[elemId]) {
			obj[elemId] = { };
		}
		
		for(x = 0, lex = children.length; x < lex; x++) {
			child = children[x];
			if(child.nodeType === 1) {
				if(this._isItForMe(child.getAttribute('for'), child.getAttribute('notFor'))) {
					elemName = child.nodeName;
					obj[elemId][elemName] = $(child).text();
				}
			}
		}
	}
};

XH.Package.prototype._addDefault = function (obj, elemId) {
	this.defaults[elemId] = obj;
};

XH.Package.prototype._getDefault = function (aName, aFor) {
	if(this.defaults[aName]) {
		return this.defaults[aName][aFor] || '';
	}
	
	return '';
};

XH.Package.prototype._addGroup = function (elem, elemId) {
	this.groups[elemId] = $(elem).text().split(',');
};

XH.Package.prototype._isGroup = function (selector) {
	return selector in this.groups;
};

XH.Package.prototype._isInGroup = function (group, selector) {
	return this.groups[group].indexOf(selector) !== -1;
};

XH.Package.prototype.get = function (type, id) {
	if(id) {
		return this.data[type] ? this.data[type][id] : undefined;
	}
	else {
		return this.data[type] ? this.data[type] : null;
	}
};

XH.Package.prototype.getList = function (type) {
	return this.lists[type];
};

XH.supplement = (function () {
	var matchPattern = /\{(.*?)\}/g,
		separator = ' ',
		currentContext = null;
	
	function replacer(str) {
		var strParts,
			withinBrackets;
		

		
		withinBrackets = str.substring(1, str.length-1); // get rid of the braces
		
		withinBrackets = withinBrackets.replace('#', ' ');
		strParts = withinBrackets.split(' ');
		


		
		if(strParts.length === 2 && !(currentContext[strParts[0]] && typeof currentContext[strParts[0]][strParts[1]] === 'string')) {

			return str;
		}
		
		if(strParts.length === 3 && !(currentContext[strParts[0]] && currentContext[strParts[0]][strParts[1]] && typeof currentContext[strParts[0]][strParts[1]][strParts[2]] === 'string')) {

			return str;
		}
		
		if(strParts.length === 2) {
			return XH.supplement(currentContext[strParts[0]][strParts[1]], currentContext);
		}
		else {
			return XH.supplement(currentContext[strParts[0]][strParts[1]][strParts[2]], currentContext);
		}
	}
	
	return function (template, context) {
		currentContext = context;
		return template.replace(matchPattern, replacer);
	};
})();
// ------------------------------------------------------------------------ //
/*
var my = new XH.Package(
		[
			'/EUROPE_NOKIA_COM_3/common_items/xml-harmonization/shared-data/devices2.xml',
			'/EUROPE_NOKIA_COM_3/common_items/xml-harmonization/projects/ovi-suite/ovi-suite-test.xml'
		],
		'mea'
	);

my.ready(function (e) {

	var teststring = 'hi {text Nokia} sup? {device name} and {device image} setting: {setting#device-image-url-prefix} guide {js#guideLang}';
	
	var context = {
		device: my.get('device', 'nokia_e50'),
		text: my.get('text'),
		setting: my.get('setting'),
		js: {
			guideLang: 'jp'
		}
	};
	
	alert(XH.supplement(teststring, context));
	
	context.device = my.get('device', 'nokia_c5');
	
	alert(XH.supplement(teststring, context));
});*/
