
function scrollTitle(title) {
	var t = title;
	if (!t.d) t.d = 1;
	t.scrollLeft = 0;
	t.wait = 0;
	t.pe = new PeriodicalExecuter(function(pe) {
		var max = this.scrollWidth - this.clientWidth;
		if (max < 0) max = 0;
		var oldScroll = this.scrollLeft + "";
		this.scrollLeft += this.d * 2;
		
		if (this.scrollLeft == parseInt(oldScroll) && this.wait > 50) {
			this.d = -1 * this.d;
			this.wait = 0;
		} else if (this.scrollLeft == parseInt(oldScroll) && this.wait <= 50) {
			this.wait++;
		}
	}.bind(t), 0.05);
}

var Story = {
	foldPage: function(id) {
		$("page_"+id).style.overflow = "hidden";
		var img = null;
		var ratio = 1.0;
		if ($("page_"+id).select(".preview img").length > 0) {
			img = $("page_"+id).select(".preview img")[0];
			ratio = img.clientWidth / img.clientHeight;
			img.ratio = ratio;
			$("page_"+id).select(".preview img")[0].morph("height:60px;width:"+Math.round(60.0*ratio)+"px;", {duration:0});
		} else {
			img = $("page_"+id).select(".preview object")[0];
			ratio = img.width / img.height;
			img.ratio = ratio;
			$("page_"+id).select(".preview object")[0].morph("height:60px;width:"+Math.round(60.0*ratio)+"px;", {duration:0});
			$("page_"+id).select(".preview embed")[0].morph("height:60px;width:"+Math.round(60.0*ratio)+"px;", {duration:0});
		}
		/*
		$("page_"+id).morph("height:60px;max-height:60px;margin-bottom:10px;", {duration:0});
		$("page_"+id).select(".preview")[0].parentNode.morph("margin-top:-10px;padding:0px;height:60px;width:"+Math.round(60.0*ratio)+"px;", {duration:0});
		$("page_"+id).select(".preview")[0].morph("height:60px;width:"+Math.round(60.0*ratio)+"px;", {duration:0});
		$("page_"+id).select(".preview .gloss")[0].hide();*/

		$("page_"+id).morph("height:60px;max-height:60px;margin-bottom:10px;", {duration:0});
		$("preview1"+id).morph("margin-top:-10px;padding:0px;height:60px;width:"+Math.round(60.0*ratio)+"px;", {duration:0});
		$("page_"+id).select(".preview")[0].morph("height:60px;width:"+Math.round(60.0*ratio)+"px;", {duration:0});
		$("page_"+id).select(".preview .gloss")[0].hide();
	},
	unfoldPage: function(id) {
		// do the reverse animation stuff here...
		$("page_"+id).morph("margin-left:-5px;margin-right:-5px;padding:5px;padding-bottom:0px;height:435px;max-height:435px;margin-bottom:0px;", {duration:0});
		var img = null;
		var ratio = 1.0;
		if ($("page_"+id).select(".preview img").length > 0) {
			ratio = $("page_"+id).select(".preview img")[0].ratio;
			$("page_"+id).select(".preview img")[0].morph("width:410px;height:"+Math.round(410 / ratio)+"px;", {duration:0});
		} else {
			ratio = $("page_"+id).select(".preview object")[0].ratio;
			$("page_"+id).select(".preview object")[0].morph("width:410px;height:"+Math.round(410.0 / ratio)+"px;", {duration:0});
			$("page_"+id).select(".preview embed")[0].morph("width:410px;height:"+Math.round(410.0 / ratio)+"px;", {duration:0});
		}
		/*
		$("page_"+id).select(".preview")[0].parentNode.morph("margin-top:30px;padding:5px;width:410px;height:278px;", {duration:0});
		$("page_"+id).select(".preview")[0].morph("width:410px;height:278px;", {duration:0});
		$("page_"+id).select(".preview .gloss")[0].show();
		*/

		$("preview1"+id).morph("margin-top:30px;padding:5px;width:410px;height:278px;", {duration:0});

		$("page_"+id).select(".preview")[0].morph("width:410px;height:310px;", {duration:0});

		$("page_"+id).select(".preview .gloss")[0].show();
		var fid = $("page_"+id).select("iframe")[0];
		var fid = $("page_"+id).select("iframe")[0];
		QEditor.makeEditable(fid, false);
		QEditor.makeEditable(fid, true);
	},
	registerPage: function(id) {				
		// enable saving for page title
	    $("page_title"+id).observe('focus', function(event) {
	    	$("page_title"+id+"_ok").show();
	    }).observe('change', function(event) {
	    	this.addClassName("saving");
	    	$('story.write.saveIndicator').show();
	    	invoke(null, "story:updatePage&gallery_id="+id+"&edit=subtitle", {value: $("page_title"+id).value}, true, function(req) {
	    		$("page_title"+id).removeClassName("saving");      	
		    	$('story.write.saveIndicator').fade();
	    	});
	    }.bind($('page_title'+id))).observe('blur', function(event){
	    	$("page_title"+id+"_ok").hide();      
	    });
		
		// enable saving for wysiwyg field
	    document.getElementsByName("page_content"+id)[0].lastContent = document.getElementsByName("page_content"+id)[0].value;
	    addLoadEvent(function() {	    		
			new PeriodicalExecuter(function(pe) {
				
				if (QEditor.doc("page_content"+id).body.innerHTML.length > 0) {
					
					var obj ;
					if(!Prototype.Browser.IE)
						obj= document.getElementsByName("page_content"+id)[0];
					else
						obj= $("pageContent"+id);
								
					if (obj.lastContent != obj.value) {
						obj.lastContent = obj.value;
						if (obj.doSave != null) {
							clearTimeout(obj.doSave);
						}
						obj.doSave = setTimeout(function() {
							
							var params = { 'value': obj.value };
							$("page_content"+id).style.border = "1px solid #9cf";
					    	$('story.write.saveIndicator').show();
					        new Ajax.Request("?event=story:updatePage&gallery_id="+id+"&edit=content", {
					        	parameters:params, 
					        	method:'post', 
					        	onComplete: function(transport,element) {
					        		$('page_content'+id).style.border='1px solid #ccc';
					    	    	$('story.write.saveIndicator').fade();
					        	}
					        });
						}, 2000);
					}
				}
			}, 0.5);
	    });
	},
	_addWYSIWYGButtons: function(id) {
		
      	QAdvancedToolbar.addButton("table", "templates/main/table.png", function(iframe) {
			s=prompt("Please enter width and height of this table (w x h):");
			a=s.split(/x/);
			var b="";
			for (i = 0; i < a[1]; i++) {
				b += "<tr>";
				for (j = 0; j < a[0]; j++)
					b += "<td><\/td>";
				b += "<\/tr>";
			}
			QEditor.exec(iframe.id, "inserthtml", "<table border=1 cellspacing=0>"+b+"</table>");
      	}, "insert a table");
//*		
      	QAdvancedToolbar.addButton("gallery", "templates/main/image.gif", function(iframe) {
      		showGallery(iframe);
      	}, "insert an image");
      	QAdvancedToolbar.addButton("floatLeft", "templates/main/float_left.gif", function(iframe) {
      		var range=document.getElementById(iframe.id).contentWindow.getSelection().getRangeAt(0);
      		var n=QEditor.doc(iframe.id).createElement("div");
      		n.setAttribute("style", "float:left;");
      		range.surroundContents(n);
      	}, "make text float right around this element");
      	QAdvancedToolbar.addButton("floatRight", "templates/main/float_right.gif", function(iframe) {
      		var range=document.getElementById(iframe.id).contentWindow.getSelection().getRangeAt(0);
      		var n=QEditor.doc(iframe.id).createElement("div");
      		n.setAttribute("style", "float:right;");
      		range.surroundContents(n);
      	}, "make text float left around this element");
      	//*/     	
      	QAdvancedToolbar.addButton("insertItem", "templates/main/story_link.png", function(iframe) {
      		showInsertOptions(iframe);
      	}, "Insert channel items.");		
		QAdvancedToolbar.addButton("flushFormatting", "templates/main/brush.png", function(iframe) {
			var content = QEditor.doc(iframe.id).body.innerHTML;
			QEditor.doc(iframe.id).body.innerHTML = content.replace(/<script[^>]*?>.*?<\/script>/gi, "").replace(/<style[^>]*?>.*?<\/style>/gi, "").replace(/<[\/\!]*?[^<>]*?>/gi, "").replace(/<![\s\S]*?--[ \t\n\r]*>/g, "");
		}, "flush formatting");
		QAdvancedToolbar.addButton("editSource", "templates/main/edit_html.gif", function(iframe) {
			QEditor.switchView(iframe, iframe.visible());
		}, "edit HTML source");					
	},
	setSortable: function() {
		Position.includeScrollOffsets = true;
	
        Sortable.create("storyPages", {
        	onUpdate: function() {
	    	$('story.write.saveIndicator').show();
        	new Ajax.Request("?event=story:updatePageSequence", {
          			method:"post",
          			parameters: {
          				data: Sortable.serialize("storyPages")
          			},
          			onSuccess: function(req) {
          				$$("span.currentPage").each(function(item, i) {
          					item.update(i+1);
          			    	$('story.write.saveIndicator').fade();
          				});
          			}
          		});
          	},
            scroll: window
          });		
	},
	unsetSortable: function() {
		Sortable.destroy($("storyPages"));
	},
	refreshPageLabels: function() {
		$$("span.currentPage").each(function(item, i) {
				item.update(i+1);
				
		    	$('story.write.saveIndicator').fade();
			});
	
		$$("span.totalPages").each(function(item, i) {
				item.update($$("span.currentPage").length);
				
		    	$('story.write.saveIndicator').fade();
			});

		
	}
};

var Upload = {
	uploadList: {},
	active: null,
	
	init: function(id, obj) {
		if(BrowserDetect.browser=="Safari") return Upload.initJavaUpload(id, obj);
		if (PluginDetect.isMinVersion("Java", "1.5") >= 1 && !(BrowserDetect.OS == "Mac" && BrowserDetect.browser == "Firefox")) {
		
			return Upload.initJavaUpload(id, obj);
		} else if (PluginDetect.getVersion("Flash") != null) {
			return Upload.initFlashUpload(id, obj);
		} else {
			Upload.initPOUM(id, obj);
		}
			
		return obj;
	},
	
	setActive: function(id) {
		Upload.active = id;
	},
	
	initJavaUpload: function(id, obj) {
		var url = "http://klatcher.com/";
		Upload.uploadList["select"+id] = function() {
			var upApp = new Element("applet", {width:1, height:1, style:'visibility:hidden;', id:'upload'+id, name:'upload'+id, code: 'qw.UploadApplet', codebase: url, archive: $("uploadSelect").archive});
			upApp.appendChild(new Element("param", {name:'config', value:obj.config}));
			upApp.appendChild(new Element("param", {name:'onProgress', value:obj.onProgress}));
			upApp.appendChild(new Element("param", {name:'onDone', value:obj.onDone}));
			upApp.appendChild(new Element("param", {name:'onError', value:obj.onError}));
			upApp.appendChild(new Element("param", {name:'salt', value:obj.salt}));
			i = 0;
			while ((file = document["uploadSelect"].getNextFile()) != null) {
				upApp.appendChild(new Element("param", {name:'file'+i, value:file}));
				i++;
			}
			upApp.appendChild(new Element("param", {name: 'numFiles', value: i}));
			document.body.appendChild(upApp);
		};
		Upload.uploadList["ready"+id] = function() {
			if (typeof obj.onReady == "function") {
				obj.onReady();
			} else {
				eval("return "+obj.onReady+"();");
			}
		};
		Upload.onSelect = function() {
			if (Upload.active != null) {
				Upload.uploadList["select"+Upload.active]();
			} else {
				Message.alert("Error during start of file upload.", "error");
			}
		};
		Upload.onReady = function() {
			if (Upload.active != null) {
				Upload.uploadList["ready"+Upload.active]();
			}
		};
		if ($("javaUploader") == null) {
			var div = new Element("div", {id: "javaUploader"}).update('<applet id="uploadSelect'+'" name="uploadSelect" code="qw.SelectFiles" archive="QuixoticUpload.jar" codebase="'+url+'" width="1" height="1" alt="">'+
												'<param name="onSelect" value="Upload.onSelect" />'+
												'<param name="onReady" value="Upload.onReady" />'+
												'<param name="id" value="uploadSelect" />' +
												'</applet>');
			div.style.position="absolute";
			div.style.zIndex = "-1000";
			div.style.visibility = "hidden";
			$(id).appendChild(div);
		}
		obj.access = document["uploadSelect"];
		return obj;
	},
	
	initFlashUpload: function(id, obj) {
        obj = new UploadMessage(obj.options);
        obj.access = obj;
        return obj;	
	},
	
	initPOUM: function(id) {
		Message.alert("Please install Flash plugin or java plugin!");
	}
};

function stopScroll(title) {
	if (title.pe) {
		title.pe.stop();
		title.scrollLeft = 0;
		title.d = 1;
	}
}

/**
 * scroll the content of an overflow:hidden element to a specific position (animated)
 * @param element object or id of the element whose content should be scrolled
 * @param target pixel position from top to which should be scrolled to
 * @param callback [OPTIONAL] what to do, when scrolling is done 
 */
function scrollEl(element, target, callback) {
	var source = $(element).scrollTop;
	var alpha = 0.0;
	new PeriodicalExecuter(function(pe) {
		alpha += 0.1;
		$(element).scrollTop = source + ((target - source) * alpha);
		if (alpha >= 1.0) {
			pe.stop();
			$(element).scrollTop = target;
			if (typeof callback == "function") {
				callback();
			}
		}
	});
}

function setPage(page) {
	if (page < 0) page = 0;
	$("pageNav").setAttribute("page", page);
	$('story_list_main').innerHTML = '';
//	$("loadingIndicator").show();
	invoke($("story_list_main"), "story:filter", {page:page}, false, function(req){
	//	$("loadingIndicator").hide();
	});
}

function getPage() {
	return parseInt($("pageNav").getAttribute("page"));
}

/**
 * initialize dynamic page navigation
 */
function initPageNav() {
	// remove any previously created page navigation
	$("pageList").innerHTML = "";
	// fetch needed vars from pageNav element
	var total = parseInt($("pageNav").getAttribute("total"));
	var show = parseInt($("pageNav").getAttribute("show"));
	var page = parseInt($("pageNav").getAttribute("page"));
	// some pre-defined stuff
	var prevNext = "if(getPage()==0)$('prev').style.visibility='hidden';else $('prev').style.visibility='visible';";
	prevNext += "if (getPage() >= x-1)$('next').style.visibility='hidden';else $('next').style.visibility='visible';";
	prevNext += "for(var j=0;j<6;j++){var p = j + (getPage()-3);if(p<0)p=0;if(p>"+(Math.ceil(total/show)-1)+")p="+(Math.ceil(total/show)-1)+";$$('.pageListItem')[p].show();}";
	var lStyle = "font-size:10px;padding-left:1px;padding-right:1px;font-family:'Verdana',sans-serif;";
	// add previous page link
	var link = (new Element("a", {id:'prev', href:'', style:lStyle+(page==0?"visibility:hidden;":"")+"margin-right:5px;", 
				onclick:"$$('.pageListItem').each(function(item){item.style.color=null;});"+
						"var x="+Math.ceil(total/show)+";setPage(getPage()-1);$$('.pageListItem')[getPage()].style.color='#000';"+prevNext+"return false;"})).update("&lt; PREVIOUS");
	$("pageList").appendChild(link);
	// add the single page number links
	for (var i = 0; i < Math.ceil(total / show); i++) {
		if ((i != 0 && i != (Math.ceil(total/show)-1)) && (i < page - 3 || i > page + 3)) hidden=true; else hidden = false;
		link = (new Element("a", {href:'', 'class':'pageListItem', style:lStyle+(i==page?"color:#000;":"")+(hidden?"display:none;":""), onclick:"$$('.pageListItem').each(function(item){item.style.color=null;item.hide();});this.style.color='#000';var i="+i+";var x="+Math.ceil(total / show)+";setPage(i);"+prevNext+"return false;"})).update("["+(i+1)+"]");
		if (((i-1) == 0 && (i < page-3)) || 
			(i == (Math.ceil(total / show) - 1) && (i-1) > (page+3))); 
//			$("pageList").appendChild((new Element("document.createTextNode("..."));
		$("pageList").appendChild(link);
	}
	// add the next page link
	link = (new Element("a", {id:'next', href:'', style:lStyle+(page>=Math.ceil(total/show)-1?"visibility:hidden;":"")+"margin-left:5px;", 
			onclick:"$$('.pageListItem').each(function(item){item.style.color=null;});"+
					"var x="+Math.ceil(total / show)+";setPage(getPage()+1);$$('.pageListItem')[getPage()].style.color='#000';"+prevNext+""+
					"return false;"})).update("NEXT &gt;");
	$("pageList").appendChild(link);
	$("pageList").highlight();
}

function initScrollTitle() {
	$$(".thumbnail .gloss").each(function(item) {
		item.observe("mouseover", function(event) {
			var t = Event.element(event);
			t.parentNode.select(".title").each(function(title) {
				scrollTitle(title);
			});
		});
		item.observe("mouseout", function(event) {
			var t = Event.element(event);
			t.parentNode.select(".title").each(function(title) {
				stopScroll(title);
			});
		});
	});
}

addLoadEvent(function() {
	initScrollTitle();	
});




	/* Function used in the Channel Page => Story Listing */

	function showChannelStoryListPage(vpage,vPerPage)
	{
	
		$('story_list').innerHTML = '';
		if(vPerPage==null)
		{
			invoke("story_list", "story:channelFilter", {page:vpage}, false, function(req){});
		}
		else
		{
			invoke("story_list", "story:channelFilter", {page:vpage,show:vPerPage}, false, function(req){});		
		}
	}


	function showStoriesByCategory(vcatID)
	{
		if (vcatID == 0) vcatID = '-1';
		$('story_list').innerHTML = '';
		invoke('story_list', 'story:channelFilter', {catID:vcatID}, false, function(){
			vcategory_id=vcatID;
			if (vcategory_id == 0 && $("cstory") != null) {
				$("cstory").setAttribute("onclick", "loadURL('writeastory');");
			} else if ($("cstory") != null) {
				$("cstory").setAttribute("onclick", "loadURL('writeastory::cid="+vcategory_id+"');");
			}
			showBottomWalls();
		});
	}
	
	function searchStories()
	{
		invoke($('story_list'), 'story:channelFilter', $('searchForm').serialize(), true, function(){
		$("story_list").style.background='#fff';
		return false;
		
		});
	}
	

	/* Function used in the Home Page => Story Listing */
	function showStoryListPage(vpage,vObject)
	{
		$('story_list_main').innerHTML = '';
		invoke("story_list_main", "story:filter", {page:vpage}, false, function(req){});
			
	}
	
	function showInsertOptions(iframe) {
		new Control.Modal("?event=story:showInsertOptions&iframe="+iframe.id, {width:520, height:330}).open();
	}
	
	function showStory(url, author_id, channel_user_id, price,story_id,vFlag,story_user_id) {
		
		if (price < 0) {	// we first need to check whether the user is a friend or not		
		
			if (channel_user_id.length > 0) {
				if (in_array(author_id,channel_user_id,false) ||  in_array(story_user_id,channel_user_id,false)) {				
					loadURL(url);
				} else {
					invoke(null,'story:getContentFlag',{story_id:story_id},false,function(res){
						if (res.responseText == "1" && vFlag == false) {
							new Control.Modal(baseHref + "?event=story:viewWarn&url=" + url + "&author_id=" + author_id + '&price=' + price + '&story_id=' + story_id, {
								width: 380,
								evalScripts: true
							}).open();
						} else {
					
							invoke(null, 'channel:isFriend', {author: author_id}, false, function(req) {
								if (req.responseText.indexOf("nofriend") >= 0) {
									author = req.responseText.split("\n");
									author = author[1];							
									Message.confirm('You need to be a friend of '+author+' to view this publications. Do you want to become a friend of '+author+'?', function() {
										invoke(null, 'user:becomeFriend', {user_id:author_id, type:1}, false, function(req){ 
											if (req.responseText=='success') {
												Message.alert('You are now a friend of '+author+' .', 'info');
												loadURL(url + "::flagval=1");
											}
										});
								});												
								} else if (req.responseText.indexOf("success") >= 0) {
									loadURL(url + "::flagval=1");					
								} else {
									invoke(null, 'user:saveReturnTo', {returnTo:url});
									login($('loginForm'),null,1,1,author_id);
								}
							});	
						}				
					});
				}
			} else {
				try {
					//if (location.href != baseHref) 
						invoke(null, 'user:saveReturnTo', {returnTo:url});
						
						login($('loginForm'),null,1,1,author_id);
				} catch(e) { alert(e); };
			}
		} else {
			if (in_array(author_id,channel_user_id,false) ||  in_array(story_user_id,channel_user_id,false)) {
				loadURL(url);
			} else {
			
				invoke(null,'story:getContentFlag',{story_id:story_id},false,function(res){
					if (res.responseText == "1" && vFlag == false) {
						new Control.Modal(baseHref + "?event=story:viewWarn&url=" + url + "&author_id=" + author_id + '&price=' + price + '&story_id=' + story_id, {
							width: 380,
							evalScripts: true
						}).open();
					} else {
						loadURL(url + "::flagval=1");	
					}
				});	
			}	
		}
	}
	
	function inStoryShowStory(author_id, channel_user_id, price,story_id,flagval,story_user_id) {
	
		if (price < 0) {
			// we first need to check whether the user is a friend or not
			if (channel_user_id.length > 0) {
				if (in_array(author_id,channel_user_id,false) ||  in_array(story_user_id,channel_user_id,false)) {
//					$("curtain").hide();
				} else {
				
					invoke(null,'story:getContentFlag',{story_id:story_id},false,function(res){
						if (res.responseText == "1" && flagval == 0) {
							new Control.Modal(baseHref + "?event=story:viewWarn&url=&author_id=" + author_id + '&price=' + price + '&story_id=' + story_id, {
								width: 380,
								evalScripts: true,
								overlayCloseOnClick: false
							}).open();
						} else {
					
							invoke(null, 'channel:isFriend', {author: author_id}, false, function(req) {
								if (req.responseText.indexOf("nofriend") >= 0) {
									$("curtain").show();
									author = req.responseText.split("\n");
									author = author[1];
									Message.confirm('You need to be a friend of '+author+' to view this publications. Do you want to become a friend of '+author+'?', function() {
										invoke(null, 'user:becomeFriend', {user_id:author_id, type:1}, false, function(req){ 
											if (req.responseText=='success') {
												Message.alert('You are now a friend of '+author+' .', 'info');
												$("curtain").hide();
											}
										});
									}, function() {
										loadURL(location.href.substr(0, location.href.lastIndexOf("/")));					
									});
								} else if (req.responseText.indexOf("success") >= 0) {
		//							$("curtain").hide();
								} else {
									if (location.href != baseHref) 
										invoke(null, 'user:saveReturnTo', {returnTo:location.href});
									login($('loginForm'), function() {
										new Control.Modal(baseHref+"?event=user:login&error=1", {width:440, evalScripts:true, overlayCloseOnClick: false}).open();
									}); 
								}
							});
						}
					});
				}
			} else {
				try {
					if (location.href != baseHref) 
						invoke(null, 'user:saveReturnTo', {returnTo:location.href});
					login($('loginForm'), function() {
						new Control.Modal(baseHref+"?event=user:login&error=1", {width:440, evalScripts:true, overlayCloseOnClick: false}).open();
					}); 
				} catch(e) { alert(e); };
			}
		} else {
			if (in_array(author_id,channel_user_id,false) ||  in_array(story_user_id,channel_user_id,false)) {
				
			} else {
				invoke(null,'story:getContentFlag',{story_id:story_id},false,function(res){
					if (res.responseText == "1" && flagval == 0) {
						new Control.Modal(baseHref + "?event=story:viewWarn&url=&author_id=" + author_id + '&price=' + price + '&story_id=' + story_id, {
							width: 380,
							evalScripts: true,
							overlayCloseOnClick: false
						}).open();
					} 
				});
			}
		}
	}


function showStoryByMode(vStoryId,vMode){
	viewMode=vMode;
	if (vMode==1){
		$('dv_full_view').show();
		invoke($('fullview_container'),"story:showFullView",{story_id:vStoryId},false);
	} else {
		$('dv_full_view').hide();
		$('fullview_container').innerHTML='';
	
	}
}

function insertStory(href, content, iframe,insertContent,desc) {
	var n=QEditor.doc(iframe).createElement("A");
	n.setAttribute("href", href);	
	if (insertContent) 
		QEditor.doc(iframe).body.innerHTML = QEditor.doc(iframe).body.innerHTML + desc;
	else
		n.appendChild(QEditor.doc(iframe).createTextNode(content));
		
	QEditor.surroundSelection(document.getElementById(iframe), n);
}
function in_array(needle, haystack, argStrict) {
    var found = false, key, strict = !!argStrict;
    for (key in haystack) {
        if (strict && haystack[key] === needle ||
            !strict && haystack[key] == needle) {
            found = true;
            break;
        }
    }
    return found;
}