xref: /webtrees/resources/js/treeview.js (revision 2ebb07b4bd8cf7010946ea4d75bb6160666157f6)
1*2ebb07b4SGreg Roach/**
2*2ebb07b4SGreg Roach * webtrees: online genealogy
3*2ebb07b4SGreg Roach * Copyright (C) 2019 webtrees development team
4*2ebb07b4SGreg Roach * This program is free software: you can redistribute it and/or modify
5*2ebb07b4SGreg Roach * it under the terms of the GNU General Public License as published by
6*2ebb07b4SGreg Roach * the Free Software Foundation, either version 3 of the License, or
7*2ebb07b4SGreg Roach * (at your option) any later version.
8*2ebb07b4SGreg Roach * This program is distributed in the hope that it will be useful,
9*2ebb07b4SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
10*2ebb07b4SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11*2ebb07b4SGreg Roach * GNU General Public License for more details.
12*2ebb07b4SGreg Roach * You should have received a copy of the GNU General Public License
13*2ebb07b4SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
14*2ebb07b4SGreg Roach */
15*2ebb07b4SGreg Roach
16*2ebb07b4SGreg Roachfunction TreeViewHandler(treeview_instance, ged) {
17*2ebb07b4SGreg Roach	var tv = this; // Store "this" for usage within jQuery functions where "this" is not this ;-)
18*2ebb07b4SGreg Roach
19*2ebb07b4SGreg Roach	this.treeview = $("#" + treeview_instance + "_in");
20*2ebb07b4SGreg Roach	this.loadingImage = $("#" + treeview_instance + "_loading");
21*2ebb07b4SGreg Roach	this.toolbox = $("#tv_tools");
22*2ebb07b4SGreg Roach	this.buttons = $(".tv_button:first", this.toolbox);
23*2ebb07b4SGreg Roach	this.zoom = 100; // in percent
24*2ebb07b4SGreg Roach	this.boxWidth = 180; // default family box width
25*2ebb07b4SGreg Roach	this.boxExpandedWidth = 250; // default expanded family box width
26*2ebb07b4SGreg Roach	this.cookieDays = 3; // lifetime of preferences memory, in days
27*2ebb07b4SGreg Roach	this.ajaxUrl = "index.php?route=module&module=tree&ged=" + encodeURIComponent(ged) + "&instance=" + treeview_instance + "&action=";
28*2ebb07b4SGreg Roach
29*2ebb07b4SGreg Roach	this.container = this.treeview.parent(); // Store the container element ("#" + treeview_instance + "_out")
30*2ebb07b4SGreg Roach	this.auto_box_width = false;
31*2ebb07b4SGreg Roach	this.updating = false;
32*2ebb07b4SGreg Roach
33*2ebb07b4SGreg Roach	// Restore user preferences
34*2ebb07b4SGreg Roach	if (readCookie("compact") === "true") {
35*2ebb07b4SGreg Roach		tv.compact();
36*2ebb07b4SGreg Roach	}
37*2ebb07b4SGreg Roach
38*2ebb07b4SGreg Roach	///////////////////////////////////////////////
39*2ebb07b4SGreg Roach	// Based on https://codepen.io/chriscoyier/pen/zdsty
40*2ebb07b4SGreg Roach	(function($) {
41*2ebb07b4SGreg Roach		$.fn.drags = function(opt) {
42*2ebb07b4SGreg Roach			var $el = this;
43*2ebb07b4SGreg Roach
44*2ebb07b4SGreg Roach			return $el.css('cursor', 'move').on("mousedown", function(e) {
45*2ebb07b4SGreg Roach				var $drag = $(this);
46*2ebb07b4SGreg Roach				var drg_h = $drag.outerHeight();
47*2ebb07b4SGreg Roach				var drg_w = $drag.outerWidth();
48*2ebb07b4SGreg Roach				var pos_y = $drag.offset().top + drg_h - e.pageY;
49*2ebb07b4SGreg Roach				var pos_x = $drag.offset().left + drg_w - e.pageX;
50*2ebb07b4SGreg Roach
51*2ebb07b4SGreg Roach				$drag.addClass('draggable');
52*2ebb07b4SGreg Roach
53*2ebb07b4SGreg Roach				$(document)
54*2ebb07b4SGreg Roach					.on("mousemove", function(e) {
55*2ebb07b4SGreg Roach						$('.draggable').offset({
56*2ebb07b4SGreg Roach							top:e.pageY + pos_y - drg_h,
57*2ebb07b4SGreg Roach							left:e.pageX + pos_x - drg_w
58*2ebb07b4SGreg Roach						}).on("mouseup", function() {
59*2ebb07b4SGreg Roach							$drag.removeClass('draggable');
60*2ebb07b4SGreg Roach						});
61*2ebb07b4SGreg Roach					}).on("mouseup", function() {
62*2ebb07b4SGreg Roach						$drag.removeClass('draggable');
63*2ebb07b4SGreg Roach						tv.updateTree();
64*2ebb07b4SGreg Roach					});
65*2ebb07b4SGreg Roach				e.preventDefault();
66*2ebb07b4SGreg Roach			});
67*2ebb07b4SGreg Roach
68*2ebb07b4SGreg Roach		}
69*2ebb07b4SGreg Roach	})(jQuery);
70*2ebb07b4SGreg Roach
71*2ebb07b4SGreg Roach	tv.treeview.drags();
72*2ebb07b4SGreg Roach	///////////////////////////////////////////////
73*2ebb07b4SGreg Roach
74*2ebb07b4SGreg Roach	// Add click handlers to buttons
75*2ebb07b4SGreg Roach	tv.toolbox.find("#tvbCompact").each(function (index, tvCompact) {
76*2ebb07b4SGreg Roach		tvCompact.onclick = function () {
77*2ebb07b4SGreg Roach			tv.compact();
78*2ebb07b4SGreg Roach		};
79*2ebb07b4SGreg Roach	});
80*2ebb07b4SGreg Roach	// If we click the "hide/show all partners" button, toggle the setting before reloading the page
81*2ebb07b4SGreg Roach	tv.toolbox.find("#tvbAllPartners").each(function (index, tvAllPartners) {
82*2ebb07b4SGreg Roach		tvAllPartners.onclick = function () {
83*2ebb07b4SGreg Roach			createCookie("allPartners", readCookie("allPartners") === "true" ? "false" : "true", tv.cookieDays);
84*2ebb07b4SGreg Roach			document.location = document.location;
85*2ebb07b4SGreg Roach		};
86*2ebb07b4SGreg Roach	});
87*2ebb07b4SGreg Roach	tv.toolbox.find("#tvbOpen").each(function (index, tvbOpen) {
88*2ebb07b4SGreg Roach		var b = $(tvbOpen, tv.toolbox);
89*2ebb07b4SGreg Roach		tvbOpen.onclick = function () {
90*2ebb07b4SGreg Roach			b.addClass("tvPressed");
91*2ebb07b4SGreg Roach			tv.setLoading();
92*2ebb07b4SGreg Roach			var e = jQuery.Event("click");
93*2ebb07b4SGreg Roach			tv.treeview.find(".tv_box:not(.boxExpanded)").each(function (index, box) {
94*2ebb07b4SGreg Roach				var pos = $(box, tv.treeview).offset();
95*2ebb07b4SGreg Roach				if (pos.left >= tv.leftMin && pos.left <= tv.leftMax && pos.top >= tv.topMin && pos.top <= tv.topMax) {
96*2ebb07b4SGreg Roach					tv.expandBox(box, e);
97*2ebb07b4SGreg Roach				}
98*2ebb07b4SGreg Roach			});
99*2ebb07b4SGreg Roach			b.removeClass("tvPressed");
100*2ebb07b4SGreg Roach			tv.setComplete();
101*2ebb07b4SGreg Roach		};
102*2ebb07b4SGreg Roach	});
103*2ebb07b4SGreg Roach	tv.toolbox.find("#tvbClose").each(function (index, tvbClose) {
104*2ebb07b4SGreg Roach		var b = $(tvbClose, tv.toolbox);
105*2ebb07b4SGreg Roach		tvbClose.onclick = function () {
106*2ebb07b4SGreg Roach			b.addClass("tvPressed");
107*2ebb07b4SGreg Roach			tv.setLoading();
108*2ebb07b4SGreg Roach			tv.treeview.find(".tv_box.boxExpanded").each(function (index, box) {
109*2ebb07b4SGreg Roach				$(box).css("display", "none").removeClass("boxExpanded").parent().find(".tv_box.collapsedContent").css("display", "block");
110*2ebb07b4SGreg Roach			});
111*2ebb07b4SGreg Roach			b.removeClass("tvPressed");
112*2ebb07b4SGreg Roach			tv.setComplete();
113*2ebb07b4SGreg Roach		};
114*2ebb07b4SGreg Roach	});
115*2ebb07b4SGreg Roach
116*2ebb07b4SGreg Roach	tv.centerOnRoot(); // fire ajax update if needed, which call setComplete() when all is loaded
117*2ebb07b4SGreg Roach}
118*2ebb07b4SGreg Roach/**
119*2ebb07b4SGreg Roach * Class TreeView setLoading method
120*2ebb07b4SGreg Roach */
121*2ebb07b4SGreg RoachTreeViewHandler.prototype.setLoading = function () {
122*2ebb07b4SGreg Roach	this.treeview.css("cursor", "wait");
123*2ebb07b4SGreg Roach	this.loadingImage.css("display", "block");
124*2ebb07b4SGreg Roach};
125*2ebb07b4SGreg Roach/**
126*2ebb07b4SGreg Roach * Class TreeView setComplete  method
127*2ebb07b4SGreg Roach */
128*2ebb07b4SGreg RoachTreeViewHandler.prototype.setComplete = function () {
129*2ebb07b4SGreg Roach	this.treeview.css("cursor", "move");
130*2ebb07b4SGreg Roach	this.loadingImage.css("display", "none");
131*2ebb07b4SGreg Roach};
132*2ebb07b4SGreg Roach
133*2ebb07b4SGreg Roach/**
134*2ebb07b4SGreg Roach * Class TreeView getSize  method
135*2ebb07b4SGreg Roach * Store the viewport current size
136*2ebb07b4SGreg Roach */
137*2ebb07b4SGreg RoachTreeViewHandler.prototype.getSize = function () {
138*2ebb07b4SGreg Roach	var tv = this;
139*2ebb07b4SGreg Roach	// retrieve the current container bounding box
140*2ebb07b4SGreg Roach	var container = tv.container.parent();
141*2ebb07b4SGreg Roach	var offset = container.offset();
142*2ebb07b4SGreg Roach	tv.leftMin = offset.left;
143*2ebb07b4SGreg Roach	tv.leftMax = tv.leftMin + container.innerWidth();
144*2ebb07b4SGreg Roach	tv.topMin = offset.top;
145*2ebb07b4SGreg Roach	tv.topMax = tv.topMin + container.innerHeight();
146*2ebb07b4SGreg Roach	/*
147*2ebb07b4SGreg Roach	 var frm = $("#tvTreeBorder");
148*2ebb07b4SGreg Roach	 tv.treeview.css("width", frm.width());
149*2ebb07b4SGreg Roach	 tv.treeview.css("height", frm.height());*/
150*2ebb07b4SGreg Roach};
151*2ebb07b4SGreg Roach
152*2ebb07b4SGreg Roach/**
153*2ebb07b4SGreg Roach * Class TreeView updateTree  method
154*2ebb07b4SGreg Roach * Perform ajax requests to complete the tree after drag
155*2ebb07b4SGreg Roach * param boolean @center center on root person when done
156*2ebb07b4SGreg Roach */
157*2ebb07b4SGreg RoachTreeViewHandler.prototype.updateTree = function (center, button) {
158*2ebb07b4SGreg Roach	var tv = this; // Store "this" for usage within jQuery functions where "this" is not this ;-)
159*2ebb07b4SGreg Roach	var to_load = [];
160*2ebb07b4SGreg Roach	var elts = [];
161*2ebb07b4SGreg Roach	this.getSize();
162*2ebb07b4SGreg Roach
163*2ebb07b4SGreg Roach	// check which td with datafld attribute are within the container bounding box
164*2ebb07b4SGreg Roach	// and therefore need to be dynamically loaded
165*2ebb07b4SGreg Roach	tv.treeview.find("td[abbr]").each(function (index, el) {
166*2ebb07b4SGreg Roach		el = $(el, tv.treeview);
167*2ebb07b4SGreg Roach		var pos = el.offset();
168*2ebb07b4SGreg Roach		if (pos.left >= tv.leftMin && pos.left <= tv.leftMax && pos.top >= tv.topMin && pos.top <= tv.topMax) {
169*2ebb07b4SGreg Roach			to_load.push(el.attr("abbr"));
170*2ebb07b4SGreg Roach			elts.push(el);
171*2ebb07b4SGreg Roach		}
172*2ebb07b4SGreg Roach	});
173*2ebb07b4SGreg Roach	// if some boxes need update, we perform an ajax request
174*2ebb07b4SGreg Roach	if (to_load.length > 0) {
175*2ebb07b4SGreg Roach		tv.updating = true;
176*2ebb07b4SGreg Roach		tv.setLoading();
177*2ebb07b4SGreg Roach		jQuery.ajax({
178*2ebb07b4SGreg Roach			url: tv.ajaxUrl + "Persons",
179*2ebb07b4SGreg Roach			dataType: "json",
180*2ebb07b4SGreg Roach			data: "q=" + to_load.join(";"),
181*2ebb07b4SGreg Roach			success: function (ret) {
182*2ebb07b4SGreg Roach				var nb = elts.length;
183*2ebb07b4SGreg Roach				var root_element = $(".rootPerson", this.treeview);
184*2ebb07b4SGreg Roach				var l = root_element.offset().left;
185*2ebb07b4SGreg Roach				for (var i = 0; i < nb; i++) {
186*2ebb07b4SGreg Roach					elts[i].removeAttr("abbr").html(ret[i]);
187*2ebb07b4SGreg Roach				}
188*2ebb07b4SGreg Roach				// we now ajust the draggable treeview size to its content size
189*2ebb07b4SGreg Roach				tv.getSize();
190*2ebb07b4SGreg Roach			},
191*2ebb07b4SGreg Roach			complete: function () {
192*2ebb07b4SGreg Roach				if (tv.treeview.find("td[abbr]").length) {
193*2ebb07b4SGreg Roach					tv.updateTree(center, button); // recursive call
194*2ebb07b4SGreg Roach				}
195*2ebb07b4SGreg Roach				// the added boxes need that in mode compact boxes
196*2ebb07b4SGreg Roach				if (tv.auto_box_width) {
197*2ebb07b4SGreg Roach					tv.treeview.find(".tv_box").css("width", "auto");
198*2ebb07b4SGreg Roach				}
199*2ebb07b4SGreg Roach				tv.updating = true; // avoid an unuseful recursive call when all requested persons are loaded
200*2ebb07b4SGreg Roach				if (center) {
201*2ebb07b4SGreg Roach					tv.centerOnRoot();
202*2ebb07b4SGreg Roach				}
203*2ebb07b4SGreg Roach				if (button) {
204*2ebb07b4SGreg Roach					button.removeClass("tvPressed");
205*2ebb07b4SGreg Roach				}
206*2ebb07b4SGreg Roach				tv.setComplete();
207*2ebb07b4SGreg Roach				tv.updating = false;
208*2ebb07b4SGreg Roach			},
209*2ebb07b4SGreg Roach			timeout: function () {
210*2ebb07b4SGreg Roach				if (button) {
211*2ebb07b4SGreg Roach					button.removeClass("tvPressed");
212*2ebb07b4SGreg Roach				}
213*2ebb07b4SGreg Roach				tv.updating = false;
214*2ebb07b4SGreg Roach				tv.setComplete();
215*2ebb07b4SGreg Roach			}
216*2ebb07b4SGreg Roach		});
217*2ebb07b4SGreg Roach	} else {
218*2ebb07b4SGreg Roach		if (button) {
219*2ebb07b4SGreg Roach			button.removeClass("tvPressed");
220*2ebb07b4SGreg Roach		}
221*2ebb07b4SGreg Roach		tv.setComplete();
222*2ebb07b4SGreg Roach	}
223*2ebb07b4SGreg Roach	return false;
224*2ebb07b4SGreg Roach};
225*2ebb07b4SGreg Roach
226*2ebb07b4SGreg Roach/**
227*2ebb07b4SGreg Roach * Class TreeView compact method
228*2ebb07b4SGreg Roach */
229*2ebb07b4SGreg RoachTreeViewHandler.prototype.compact = function () {
230*2ebb07b4SGreg Roach	var tv = this;
231*2ebb07b4SGreg Roach	var b = $("#tvbCompact", tv.toolbox);
232*2ebb07b4SGreg Roach	tv.setLoading();
233*2ebb07b4SGreg Roach	if (tv.auto_box_width) {
234*2ebb07b4SGreg Roach		var w = tv.boxWidth * (tv.zoom / 100) + "px";
235*2ebb07b4SGreg Roach		var ew = tv.boxExpandedWidth * (tv.zoom / 100) + "px";
236*2ebb07b4SGreg Roach		tv.treeview.find(".tv_box:not(boxExpanded)", tv.treeview).css("width", w);
237*2ebb07b4SGreg Roach		tv.treeview.find(".boxExpanded", tv.treeview).css("width", ew);
238*2ebb07b4SGreg Roach		tv.auto_box_width = false;
239*2ebb07b4SGreg Roach		if (readCookie("compact")) {
240*2ebb07b4SGreg Roach			createCookie("compact", false, tv.cookieDays);
241*2ebb07b4SGreg Roach		}
242*2ebb07b4SGreg Roach		b.removeClass("tvPressed");
243*2ebb07b4SGreg Roach	} else {
244*2ebb07b4SGreg Roach		tv.treeview.find(".tv_box").css("width", "auto");
245*2ebb07b4SGreg Roach		tv.auto_box_width = true;
246*2ebb07b4SGreg Roach		if (!readCookie("compact")) {
247*2ebb07b4SGreg Roach			createCookie("compact", true, tv.cookieDays);
248*2ebb07b4SGreg Roach		}
249*2ebb07b4SGreg Roach		if (!tv.updating) {
250*2ebb07b4SGreg Roach			tv.updateTree();
251*2ebb07b4SGreg Roach		}
252*2ebb07b4SGreg Roach		b.addClass("tvPressed");
253*2ebb07b4SGreg Roach	}
254*2ebb07b4SGreg Roach	tv.setComplete();
255*2ebb07b4SGreg Roach	return false;
256*2ebb07b4SGreg Roach};
257*2ebb07b4SGreg Roach
258*2ebb07b4SGreg Roach/**
259*2ebb07b4SGreg Roach * Class TreeView centerOnRoot method
260*2ebb07b4SGreg Roach */
261*2ebb07b4SGreg RoachTreeViewHandler.prototype.centerOnRoot = function () {
262*2ebb07b4SGreg Roach	this.loadingImage.css("display", "block");
263*2ebb07b4SGreg Roach	var tv = this;
264*2ebb07b4SGreg Roach	var tvc = this.container;
265*2ebb07b4SGreg Roach	var tvc_width = tvc.innerWidth() / 2;
266*2ebb07b4SGreg Roach	if (isNaN(tvc_width)) {
267*2ebb07b4SGreg Roach		return false;
268*2ebb07b4SGreg Roach	}
269*2ebb07b4SGreg Roach	var tvc_height = tvc.innerHeight() / 2;
270*2ebb07b4SGreg Roach	var root_person = $(".rootPerson", this.treeview);
271*2ebb07b4SGreg Roach
272*2ebb07b4SGreg Roach	if (!this.updating) {
273*2ebb07b4SGreg Roach		tv.setComplete();
274*2ebb07b4SGreg Roach	}
275*2ebb07b4SGreg Roach	return false;
276*2ebb07b4SGreg Roach};
277*2ebb07b4SGreg Roach
278*2ebb07b4SGreg Roach/**
279*2ebb07b4SGreg Roach * Class TreeView expandBox method
280*2ebb07b4SGreg Roach * param string @box the person box element
281*2ebb07b4SGreg Roach * param string @event the call event
282*2ebb07b4SGreg Roach * param string @pid the person id
283*2ebb07b4SGreg Roach *
284*2ebb07b4SGreg Roach * called ONLY for elements which have NOT the class tv_link to avoid unuseful requests to the server
285*2ebb07b4SGreg Roach */
286*2ebb07b4SGreg RoachTreeViewHandler.prototype.expandBox = function (box, event) {
287*2ebb07b4SGreg Roach	var t = $(event.target);
288*2ebb07b4SGreg Roach	if (t.hasClass("tv_link")) {
289*2ebb07b4SGreg Roach		return false;
290*2ebb07b4SGreg Roach	}
291*2ebb07b4SGreg Roach
292*2ebb07b4SGreg Roach	var box = $(box, this.treeview);
293*2ebb07b4SGreg Roach	var bc = box.parent(); // bc is Box Container
294*2ebb07b4SGreg Roach	var pid = box.attr("abbr");
295*2ebb07b4SGreg Roach	var tv = this; // Store "this" for usage within jQuery functions where "this" is not this ;-)
296*2ebb07b4SGreg Roach	var expanded;
297*2ebb07b4SGreg Roach	var collapsed;
298*2ebb07b4SGreg Roach
299*2ebb07b4SGreg Roach	if (bc.hasClass("detailsLoaded")) {
300*2ebb07b4SGreg Roach		collapsed = bc.find(".collapsedContent");
301*2ebb07b4SGreg Roach		expanded = bc.find(".tv_box:not(.collapsedContent)");
302*2ebb07b4SGreg Roach	} else {
303*2ebb07b4SGreg Roach		// Cache the box content as an hidden person's box in the box's parent element
304*2ebb07b4SGreg Roach		expanded = box;
305*2ebb07b4SGreg Roach		collapsed = box.clone();
306*2ebb07b4SGreg Roach		bc.append(collapsed.addClass("collapsedContent").css("display", "none"));
307*2ebb07b4SGreg Roach		// we add a waiting image at the right side of the box
308*2ebb07b4SGreg Roach		var loading_image = this.loadingImage.find("img").clone().addClass("tv_box_loading").css("display", "block");
309*2ebb07b4SGreg Roach		box.prepend(loading_image);
310*2ebb07b4SGreg Roach		tv.updating = true;
311*2ebb07b4SGreg Roach		tv.setLoading();
312*2ebb07b4SGreg Roach		// perform the Ajax request and load the result in the box
313*2ebb07b4SGreg Roach		box.load(tv.ajaxUrl + "Details&pid=" + pid, function () {
314*2ebb07b4SGreg Roach			// If Lightbox module is active, we reinitialize it for the new links
315*2ebb07b4SGreg Roach			if (typeof CB_Init === "function") {
316*2ebb07b4SGreg Roach				CB_Init();
317*2ebb07b4SGreg Roach			}
318*2ebb07b4SGreg Roach			box.css("width", tv.boxExpandedWidth * (tv.zoom / 100) + "px");
319*2ebb07b4SGreg Roach			loading_image.remove();
320*2ebb07b4SGreg Roach			bc.addClass("detailsLoaded");
321*2ebb07b4SGreg Roach			tv.setComplete();
322*2ebb07b4SGreg Roach			tv.updating = false;
323*2ebb07b4SGreg Roach		});
324*2ebb07b4SGreg Roach	}
325*2ebb07b4SGreg Roach	if (box.hasClass("boxExpanded")) {
326*2ebb07b4SGreg Roach		expanded.css("display", "none");
327*2ebb07b4SGreg Roach		collapsed.css("display", "block");
328*2ebb07b4SGreg Roach		box.removeClass("boxExpanded");
329*2ebb07b4SGreg Roach	} else {
330*2ebb07b4SGreg Roach		expanded.css("display", "block");
331*2ebb07b4SGreg Roach		collapsed.css("display", "none");
332*2ebb07b4SGreg Roach		expanded.addClass("boxExpanded");
333*2ebb07b4SGreg Roach	}
334*2ebb07b4SGreg Roach	// we must ajust the draggable treeview size to its content size
335*2ebb07b4SGreg Roach	this.getSize();
336*2ebb07b4SGreg Roach	return false;
337*2ebb07b4SGreg Roach};
338*2ebb07b4SGreg Roach
339*2ebb07b4SGreg Roachfunction createCookie(name, value, days) {
340*2ebb07b4SGreg Roach	if (days) {
341*2ebb07b4SGreg Roach		var date = new Date();
342*2ebb07b4SGreg Roach		date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
343*2ebb07b4SGreg Roach		document.cookie = name + "=" + value + "; expires=" + date.toGMTString() + "; path=/";
344*2ebb07b4SGreg Roach	} else {
345*2ebb07b4SGreg Roach		document.cookie = name + "=" + value + "; path=/";
346*2ebb07b4SGreg Roach	}
347*2ebb07b4SGreg Roach}
348*2ebb07b4SGreg Roach
349*2ebb07b4SGreg Roachfunction readCookie(name) {
350*2ebb07b4SGreg Roach	var name_equals = name + "=";
351*2ebb07b4SGreg Roach	var ca = document.cookie.split(';');
352*2ebb07b4SGreg Roach	for (var i = 0; i < ca.length; i++) {
353*2ebb07b4SGreg Roach		var c = ca[i];
354*2ebb07b4SGreg Roach		while (c.charAt(0) === ' ') {
355*2ebb07b4SGreg Roach			c = c.substring(1, c.length);
356*2ebb07b4SGreg Roach		}
357*2ebb07b4SGreg Roach		if (c.indexOf(name_equals) === 0) {
358*2ebb07b4SGreg Roach			return c.substring(name_equals.length, c.length);
359*2ebb07b4SGreg Roach		}
360*2ebb07b4SGreg Roach	}
361*2ebb07b4SGreg Roach	return null;
362*2ebb07b4SGreg Roach}
363