xref: /webtrees/resources/js/treeview.js (revision 06f42609e3f1764a2e55be21f0ce941f29f42167)
12ebb07b4SGreg Roach/**
22ebb07b4SGreg Roach * webtrees: online genealogy
32ebb07b4SGreg Roach * Copyright (C) 2019 webtrees development team
42ebb07b4SGreg Roach * This program is free software: you can redistribute it and/or modify
52ebb07b4SGreg Roach * it under the terms of the GNU General Public License as published by
62ebb07b4SGreg Roach * the Free Software Foundation, either version 3 of the License, or
72ebb07b4SGreg Roach * (at your option) any later version.
82ebb07b4SGreg Roach * This program is distributed in the hope that it will be useful,
92ebb07b4SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
102ebb07b4SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
112ebb07b4SGreg Roach * GNU General Public License for more details.
122ebb07b4SGreg Roach * You should have received a copy of the GNU General Public License
132ebb07b4SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
142ebb07b4SGreg Roach */
152ebb07b4SGreg Roach
162ebb07b4SGreg Roachfunction TreeViewHandler(treeview_instance, ged) {
172ebb07b4SGreg Roach	var tv = this; // Store "this" for usage within jQuery functions where "this" is not this ;-)
182ebb07b4SGreg Roach
192ebb07b4SGreg Roach	this.treeview = $("#" + treeview_instance + "_in");
202ebb07b4SGreg Roach	this.loadingImage = $("#" + treeview_instance + "_loading");
212ebb07b4SGreg Roach	this.toolbox = $("#tv_tools");
222ebb07b4SGreg Roach	this.buttons = $(".tv_button:first", this.toolbox);
232ebb07b4SGreg Roach	this.zoom = 100; // in percent
242ebb07b4SGreg Roach	this.boxWidth = 180; // default family box width
252ebb07b4SGreg Roach	this.boxExpandedWidth = 250; // default expanded family box width
262ebb07b4SGreg Roach	this.cookieDays = 3; // lifetime of preferences memory, in days
27*06f42609SGreg Roach	this.ajaxDetails = document.getElementById(treeview_instance + "_out").dataset.urlDetails + "?instance=" + encodeURIComponent(treeview_instance);
28*06f42609SGreg Roach	this.ajaxPersons = document.getElementById(treeview_instance + "_out").dataset.urlIndividuals + "?instance=" + encodeURIComponent(treeview_instance);
292ebb07b4SGreg Roach
302ebb07b4SGreg Roach	this.container = this.treeview.parent(); // Store the container element ("#" + treeview_instance + "_out")
312ebb07b4SGreg Roach	this.auto_box_width = false;
322ebb07b4SGreg Roach	this.updating = false;
332ebb07b4SGreg Roach
342ebb07b4SGreg Roach	// Restore user preferences
352ebb07b4SGreg Roach	if (readCookie("compact") === "true") {
362ebb07b4SGreg Roach		tv.compact();
372ebb07b4SGreg Roach	}
382ebb07b4SGreg Roach
392ebb07b4SGreg Roach	///////////////////////////////////////////////
402ebb07b4SGreg Roach	// Based on https://codepen.io/chriscoyier/pen/zdsty
412ebb07b4SGreg Roach	(function($) {
422ebb07b4SGreg Roach		$.fn.drags = function(opt) {
432ebb07b4SGreg Roach			var $el = this;
442ebb07b4SGreg Roach
452ebb07b4SGreg Roach			return $el.css('cursor', 'move').on("mousedown", function(e) {
462ebb07b4SGreg Roach				var $drag = $(this);
472ebb07b4SGreg Roach				var drg_h = $drag.outerHeight();
482ebb07b4SGreg Roach				var drg_w = $drag.outerWidth();
492ebb07b4SGreg Roach				var pos_y = $drag.offset().top + drg_h - e.pageY;
502ebb07b4SGreg Roach				var pos_x = $drag.offset().left + drg_w - e.pageX;
512ebb07b4SGreg Roach
522ebb07b4SGreg Roach				$drag.addClass('draggable');
532ebb07b4SGreg Roach
542ebb07b4SGreg Roach				$(document)
552ebb07b4SGreg Roach					.on("mousemove", function(e) {
562ebb07b4SGreg Roach						$('.draggable').offset({
572ebb07b4SGreg Roach							top:e.pageY + pos_y - drg_h,
582ebb07b4SGreg Roach							left:e.pageX + pos_x - drg_w
592ebb07b4SGreg Roach						}).on("mouseup", function() {
602ebb07b4SGreg Roach							$drag.removeClass('draggable');
612ebb07b4SGreg Roach						});
622ebb07b4SGreg Roach					}).on("mouseup", function() {
632ebb07b4SGreg Roach						$drag.removeClass('draggable');
642ebb07b4SGreg Roach						tv.updateTree();
652ebb07b4SGreg Roach					});
662ebb07b4SGreg Roach				e.preventDefault();
672ebb07b4SGreg Roach			});
682ebb07b4SGreg Roach
692ebb07b4SGreg Roach		}
702ebb07b4SGreg Roach	})(jQuery);
712ebb07b4SGreg Roach
722ebb07b4SGreg Roach	tv.treeview.drags();
732ebb07b4SGreg Roach	///////////////////////////////////////////////
742ebb07b4SGreg Roach
752ebb07b4SGreg Roach	// Add click handlers to buttons
762ebb07b4SGreg Roach	tv.toolbox.find("#tvbCompact").each(function (index, tvCompact) {
772ebb07b4SGreg Roach		tvCompact.onclick = function () {
782ebb07b4SGreg Roach			tv.compact();
792ebb07b4SGreg Roach		};
802ebb07b4SGreg Roach	});
812ebb07b4SGreg Roach	// If we click the "hide/show all partners" button, toggle the setting before reloading the page
822ebb07b4SGreg Roach	tv.toolbox.find("#tvbAllPartners").each(function (index, tvAllPartners) {
832ebb07b4SGreg Roach		tvAllPartners.onclick = function () {
842ebb07b4SGreg Roach			createCookie("allPartners", readCookie("allPartners") === "true" ? "false" : "true", tv.cookieDays);
852ebb07b4SGreg Roach			document.location = document.location;
862ebb07b4SGreg Roach		};
872ebb07b4SGreg Roach	});
882ebb07b4SGreg Roach	tv.toolbox.find("#tvbOpen").each(function (index, tvbOpen) {
892ebb07b4SGreg Roach		var b = $(tvbOpen, tv.toolbox);
902ebb07b4SGreg Roach		tvbOpen.onclick = function () {
912ebb07b4SGreg Roach			b.addClass("tvPressed");
922ebb07b4SGreg Roach			tv.setLoading();
932ebb07b4SGreg Roach			var e = jQuery.Event("click");
942ebb07b4SGreg Roach			tv.treeview.find(".tv_box:not(.boxExpanded)").each(function (index, box) {
952ebb07b4SGreg Roach				var pos = $(box, tv.treeview).offset();
962ebb07b4SGreg Roach				if (pos.left >= tv.leftMin && pos.left <= tv.leftMax && pos.top >= tv.topMin && pos.top <= tv.topMax) {
972ebb07b4SGreg Roach					tv.expandBox(box, e);
982ebb07b4SGreg Roach				}
992ebb07b4SGreg Roach			});
1002ebb07b4SGreg Roach			b.removeClass("tvPressed");
1012ebb07b4SGreg Roach			tv.setComplete();
1022ebb07b4SGreg Roach		};
1032ebb07b4SGreg Roach	});
1042ebb07b4SGreg Roach	tv.toolbox.find("#tvbClose").each(function (index, tvbClose) {
1052ebb07b4SGreg Roach		var b = $(tvbClose, tv.toolbox);
1062ebb07b4SGreg Roach		tvbClose.onclick = function () {
1072ebb07b4SGreg Roach			b.addClass("tvPressed");
1082ebb07b4SGreg Roach			tv.setLoading();
1092ebb07b4SGreg Roach			tv.treeview.find(".tv_box.boxExpanded").each(function (index, box) {
1102ebb07b4SGreg Roach				$(box).css("display", "none").removeClass("boxExpanded").parent().find(".tv_box.collapsedContent").css("display", "block");
1112ebb07b4SGreg Roach			});
1122ebb07b4SGreg Roach			b.removeClass("tvPressed");
1132ebb07b4SGreg Roach			tv.setComplete();
1142ebb07b4SGreg Roach		};
1152ebb07b4SGreg Roach	});
1162ebb07b4SGreg Roach
1172ebb07b4SGreg Roach	tv.centerOnRoot(); // fire ajax update if needed, which call setComplete() when all is loaded
1182ebb07b4SGreg Roach}
1192ebb07b4SGreg Roach/**
1202ebb07b4SGreg Roach * Class TreeView setLoading method
1212ebb07b4SGreg Roach */
1222ebb07b4SGreg RoachTreeViewHandler.prototype.setLoading = function () {
1232ebb07b4SGreg Roach	this.treeview.css("cursor", "wait");
1242ebb07b4SGreg Roach	this.loadingImage.css("display", "block");
1252ebb07b4SGreg Roach};
1262ebb07b4SGreg Roach/**
1272ebb07b4SGreg Roach * Class TreeView setComplete  method
1282ebb07b4SGreg Roach */
1292ebb07b4SGreg RoachTreeViewHandler.prototype.setComplete = function () {
1302ebb07b4SGreg Roach	this.treeview.css("cursor", "move");
1312ebb07b4SGreg Roach	this.loadingImage.css("display", "none");
1322ebb07b4SGreg Roach};
1332ebb07b4SGreg Roach
1342ebb07b4SGreg Roach/**
1352ebb07b4SGreg Roach * Class TreeView getSize  method
1362ebb07b4SGreg Roach * Store the viewport current size
1372ebb07b4SGreg Roach */
1382ebb07b4SGreg RoachTreeViewHandler.prototype.getSize = function () {
1392ebb07b4SGreg Roach	var tv = this;
1402ebb07b4SGreg Roach	// retrieve the current container bounding box
1412ebb07b4SGreg Roach	var container = tv.container.parent();
1422ebb07b4SGreg Roach	var offset = container.offset();
1432ebb07b4SGreg Roach	tv.leftMin = offset.left;
1442ebb07b4SGreg Roach	tv.leftMax = tv.leftMin + container.innerWidth();
1452ebb07b4SGreg Roach	tv.topMin = offset.top;
1462ebb07b4SGreg Roach	tv.topMax = tv.topMin + container.innerHeight();
1472ebb07b4SGreg Roach	/*
1482ebb07b4SGreg Roach	 var frm = $("#tvTreeBorder");
1492ebb07b4SGreg Roach	 tv.treeview.css("width", frm.width());
1502ebb07b4SGreg Roach	 tv.treeview.css("height", frm.height());*/
1512ebb07b4SGreg Roach};
1522ebb07b4SGreg Roach
1532ebb07b4SGreg Roach/**
1542ebb07b4SGreg Roach * Class TreeView updateTree  method
1552ebb07b4SGreg Roach * Perform ajax requests to complete the tree after drag
1562ebb07b4SGreg Roach * param boolean @center center on root person when done
1572ebb07b4SGreg Roach */
1582ebb07b4SGreg RoachTreeViewHandler.prototype.updateTree = function (center, button) {
1592ebb07b4SGreg Roach	var tv = this; // Store "this" for usage within jQuery functions where "this" is not this ;-)
1602ebb07b4SGreg Roach	var to_load = [];
1612ebb07b4SGreg Roach	var elts = [];
1622ebb07b4SGreg Roach	this.getSize();
1632ebb07b4SGreg Roach
1642ebb07b4SGreg Roach	// check which td with datafld attribute are within the container bounding box
1652ebb07b4SGreg Roach	// and therefore need to be dynamically loaded
1662ebb07b4SGreg Roach	tv.treeview.find("td[abbr]").each(function (index, el) {
1672ebb07b4SGreg Roach		el = $(el, tv.treeview);
1682ebb07b4SGreg Roach		var pos = el.offset();
1692ebb07b4SGreg Roach		if (pos.left >= tv.leftMin && pos.left <= tv.leftMax && pos.top >= tv.topMin && pos.top <= tv.topMax) {
1702ebb07b4SGreg Roach			to_load.push(el.attr("abbr"));
1712ebb07b4SGreg Roach			elts.push(el);
1722ebb07b4SGreg Roach		}
1732ebb07b4SGreg Roach	});
1742ebb07b4SGreg Roach	// if some boxes need update, we perform an ajax request
1752ebb07b4SGreg Roach	if (to_load.length > 0) {
1762ebb07b4SGreg Roach		tv.updating = true;
1772ebb07b4SGreg Roach		tv.setLoading();
1782ebb07b4SGreg Roach		jQuery.ajax({
179*06f42609SGreg Roach			url: tv.ajaxPersons,
1802ebb07b4SGreg Roach			dataType: "json",
1812ebb07b4SGreg Roach			data: "q=" + to_load.join(";"),
1822ebb07b4SGreg Roach			success: function (ret) {
1832ebb07b4SGreg Roach				var nb = elts.length;
1842ebb07b4SGreg Roach				var root_element = $(".rootPerson", this.treeview);
1852ebb07b4SGreg Roach				var l = root_element.offset().left;
1862ebb07b4SGreg Roach				for (var i = 0; i < nb; i++) {
1872ebb07b4SGreg Roach					elts[i].removeAttr("abbr").html(ret[i]);
1882ebb07b4SGreg Roach				}
1892ebb07b4SGreg Roach				// we now ajust the draggable treeview size to its content size
1902ebb07b4SGreg Roach				tv.getSize();
1912ebb07b4SGreg Roach			},
1922ebb07b4SGreg Roach			complete: function () {
1932ebb07b4SGreg Roach				if (tv.treeview.find("td[abbr]").length) {
1942ebb07b4SGreg Roach					tv.updateTree(center, button); // recursive call
1952ebb07b4SGreg Roach				}
1962ebb07b4SGreg Roach				// the added boxes need that in mode compact boxes
1972ebb07b4SGreg Roach				if (tv.auto_box_width) {
1982ebb07b4SGreg Roach					tv.treeview.find(".tv_box").css("width", "auto");
1992ebb07b4SGreg Roach				}
2002ebb07b4SGreg Roach				tv.updating = true; // avoid an unuseful recursive call when all requested persons are loaded
2012ebb07b4SGreg Roach				if (center) {
2022ebb07b4SGreg Roach					tv.centerOnRoot();
2032ebb07b4SGreg Roach				}
2042ebb07b4SGreg Roach				if (button) {
2052ebb07b4SGreg Roach					button.removeClass("tvPressed");
2062ebb07b4SGreg Roach				}
2072ebb07b4SGreg Roach				tv.setComplete();
2082ebb07b4SGreg Roach				tv.updating = false;
2092ebb07b4SGreg Roach			},
2102ebb07b4SGreg Roach			timeout: function () {
2112ebb07b4SGreg Roach				if (button) {
2122ebb07b4SGreg Roach					button.removeClass("tvPressed");
2132ebb07b4SGreg Roach				}
2142ebb07b4SGreg Roach				tv.updating = false;
2152ebb07b4SGreg Roach				tv.setComplete();
2162ebb07b4SGreg Roach			}
2172ebb07b4SGreg Roach		});
2182ebb07b4SGreg Roach	} else {
2192ebb07b4SGreg Roach		if (button) {
2202ebb07b4SGreg Roach			button.removeClass("tvPressed");
2212ebb07b4SGreg Roach		}
2222ebb07b4SGreg Roach		tv.setComplete();
2232ebb07b4SGreg Roach	}
2242ebb07b4SGreg Roach	return false;
2252ebb07b4SGreg Roach};
2262ebb07b4SGreg Roach
2272ebb07b4SGreg Roach/**
2282ebb07b4SGreg Roach * Class TreeView compact method
2292ebb07b4SGreg Roach */
2302ebb07b4SGreg RoachTreeViewHandler.prototype.compact = function () {
2312ebb07b4SGreg Roach	var tv = this;
2322ebb07b4SGreg Roach	var b = $("#tvbCompact", tv.toolbox);
2332ebb07b4SGreg Roach	tv.setLoading();
2342ebb07b4SGreg Roach	if (tv.auto_box_width) {
2352ebb07b4SGreg Roach		var w = tv.boxWidth * (tv.zoom / 100) + "px";
2362ebb07b4SGreg Roach		var ew = tv.boxExpandedWidth * (tv.zoom / 100) + "px";
2372ebb07b4SGreg Roach		tv.treeview.find(".tv_box:not(boxExpanded)", tv.treeview).css("width", w);
2382ebb07b4SGreg Roach		tv.treeview.find(".boxExpanded", tv.treeview).css("width", ew);
2392ebb07b4SGreg Roach		tv.auto_box_width = false;
2402ebb07b4SGreg Roach		if (readCookie("compact")) {
2412ebb07b4SGreg Roach			createCookie("compact", false, tv.cookieDays);
2422ebb07b4SGreg Roach		}
2432ebb07b4SGreg Roach		b.removeClass("tvPressed");
2442ebb07b4SGreg Roach	} else {
2452ebb07b4SGreg Roach		tv.treeview.find(".tv_box").css("width", "auto");
2462ebb07b4SGreg Roach		tv.auto_box_width = true;
2472ebb07b4SGreg Roach		if (!readCookie("compact")) {
2482ebb07b4SGreg Roach			createCookie("compact", true, tv.cookieDays);
2492ebb07b4SGreg Roach		}
2502ebb07b4SGreg Roach		if (!tv.updating) {
2512ebb07b4SGreg Roach			tv.updateTree();
2522ebb07b4SGreg Roach		}
2532ebb07b4SGreg Roach		b.addClass("tvPressed");
2542ebb07b4SGreg Roach	}
2552ebb07b4SGreg Roach	tv.setComplete();
2562ebb07b4SGreg Roach	return false;
2572ebb07b4SGreg Roach};
2582ebb07b4SGreg Roach
2592ebb07b4SGreg Roach/**
2602ebb07b4SGreg Roach * Class TreeView centerOnRoot method
2612ebb07b4SGreg Roach */
2622ebb07b4SGreg RoachTreeViewHandler.prototype.centerOnRoot = function () {
2632ebb07b4SGreg Roach	this.loadingImage.css("display", "block");
2642ebb07b4SGreg Roach	var tv = this;
2652ebb07b4SGreg Roach	var tvc = this.container;
2662ebb07b4SGreg Roach	var tvc_width = tvc.innerWidth() / 2;
2672ebb07b4SGreg Roach	if (isNaN(tvc_width)) {
2682ebb07b4SGreg Roach		return false;
2692ebb07b4SGreg Roach	}
2702ebb07b4SGreg Roach	var tvc_height = tvc.innerHeight() / 2;
2712ebb07b4SGreg Roach	var root_person = $(".rootPerson", this.treeview);
2722ebb07b4SGreg Roach
2732ebb07b4SGreg Roach	if (!this.updating) {
2742ebb07b4SGreg Roach		tv.setComplete();
2752ebb07b4SGreg Roach	}
2762ebb07b4SGreg Roach	return false;
2772ebb07b4SGreg Roach};
2782ebb07b4SGreg Roach
2792ebb07b4SGreg Roach/**
2802ebb07b4SGreg Roach * Class TreeView expandBox method
2812ebb07b4SGreg Roach * param string @box the person box element
2822ebb07b4SGreg Roach * param string @event the call event
2832ebb07b4SGreg Roach * param string @pid the person id
2842ebb07b4SGreg Roach *
2852ebb07b4SGreg Roach * called ONLY for elements which have NOT the class tv_link to avoid unuseful requests to the server
2862ebb07b4SGreg Roach */
2872ebb07b4SGreg RoachTreeViewHandler.prototype.expandBox = function (box, event) {
2882ebb07b4SGreg Roach	var t = $(event.target);
2892ebb07b4SGreg Roach	if (t.hasClass("tv_link")) {
2902ebb07b4SGreg Roach		return false;
2912ebb07b4SGreg Roach	}
2922ebb07b4SGreg Roach
2932ebb07b4SGreg Roach	var box = $(box, this.treeview);
2942ebb07b4SGreg Roach	var bc = box.parent(); // bc is Box Container
2952ebb07b4SGreg Roach	var pid = box.attr("abbr");
2962ebb07b4SGreg Roach	var tv = this; // Store "this" for usage within jQuery functions where "this" is not this ;-)
2972ebb07b4SGreg Roach	var expanded;
2982ebb07b4SGreg Roach	var collapsed;
2992ebb07b4SGreg Roach
3002ebb07b4SGreg Roach	if (bc.hasClass("detailsLoaded")) {
3012ebb07b4SGreg Roach		collapsed = bc.find(".collapsedContent");
3022ebb07b4SGreg Roach		expanded = bc.find(".tv_box:not(.collapsedContent)");
3032ebb07b4SGreg Roach	} else {
3042ebb07b4SGreg Roach		// Cache the box content as an hidden person's box in the box's parent element
3052ebb07b4SGreg Roach		expanded = box;
3062ebb07b4SGreg Roach		collapsed = box.clone();
3072ebb07b4SGreg Roach		bc.append(collapsed.addClass("collapsedContent").css("display", "none"));
3082ebb07b4SGreg Roach		// we add a waiting image at the right side of the box
3092ebb07b4SGreg Roach		var loading_image = this.loadingImage.find("img").clone().addClass("tv_box_loading").css("display", "block");
3102ebb07b4SGreg Roach		box.prepend(loading_image);
3112ebb07b4SGreg Roach		tv.updating = true;
3122ebb07b4SGreg Roach		tv.setLoading();
3132ebb07b4SGreg Roach		// perform the Ajax request and load the result in the box
314*06f42609SGreg Roach		box.load(tv.ajaxDetails + "&pid=" + encodeURIComponent(pid), function () {
3152ebb07b4SGreg Roach			// If Lightbox module is active, we reinitialize it for the new links
3162ebb07b4SGreg Roach			if (typeof CB_Init === "function") {
3172ebb07b4SGreg Roach				CB_Init();
3182ebb07b4SGreg Roach			}
3192ebb07b4SGreg Roach			box.css("width", tv.boxExpandedWidth * (tv.zoom / 100) + "px");
3202ebb07b4SGreg Roach			loading_image.remove();
3212ebb07b4SGreg Roach			bc.addClass("detailsLoaded");
3222ebb07b4SGreg Roach			tv.setComplete();
3232ebb07b4SGreg Roach			tv.updating = false;
3242ebb07b4SGreg Roach		});
3252ebb07b4SGreg Roach	}
3262ebb07b4SGreg Roach	if (box.hasClass("boxExpanded")) {
3272ebb07b4SGreg Roach		expanded.css("display", "none");
3282ebb07b4SGreg Roach		collapsed.css("display", "block");
3292ebb07b4SGreg Roach		box.removeClass("boxExpanded");
3302ebb07b4SGreg Roach	} else {
3312ebb07b4SGreg Roach		expanded.css("display", "block");
3322ebb07b4SGreg Roach		collapsed.css("display", "none");
3332ebb07b4SGreg Roach		expanded.addClass("boxExpanded");
3342ebb07b4SGreg Roach	}
3352ebb07b4SGreg Roach	// we must ajust the draggable treeview size to its content size
3362ebb07b4SGreg Roach	this.getSize();
3372ebb07b4SGreg Roach	return false;
3382ebb07b4SGreg Roach};
3392ebb07b4SGreg Roach
3402ebb07b4SGreg Roachfunction createCookie(name, value, days) {
3412ebb07b4SGreg Roach	if (days) {
3422ebb07b4SGreg Roach		var date = new Date();
3432ebb07b4SGreg Roach		date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
3442ebb07b4SGreg Roach		document.cookie = name + "=" + value + "; expires=" + date.toGMTString() + "; path=/";
3452ebb07b4SGreg Roach	} else {
3462ebb07b4SGreg Roach		document.cookie = name + "=" + value + "; path=/";
3472ebb07b4SGreg Roach	}
3482ebb07b4SGreg Roach}
3492ebb07b4SGreg Roach
3502ebb07b4SGreg Roachfunction readCookie(name) {
3512ebb07b4SGreg Roach	var name_equals = name + "=";
3522ebb07b4SGreg Roach	var ca = document.cookie.split(';');
3532ebb07b4SGreg Roach	for (var i = 0; i < ca.length; i++) {
3542ebb07b4SGreg Roach		var c = ca[i];
3552ebb07b4SGreg Roach		while (c.charAt(0) === ' ') {
3562ebb07b4SGreg Roach			c = c.substring(1, c.length);
3572ebb07b4SGreg Roach		}
3582ebb07b4SGreg Roach		if (c.indexOf(name_equals) === 0) {
3592ebb07b4SGreg Roach			return c.substring(name_equals.length, c.length);
3602ebb07b4SGreg Roach		}
3612ebb07b4SGreg Roach	}
3622ebb07b4SGreg Roach	return null;
3632ebb07b4SGreg Roach}
364