PageSourceSearch

https://tierarzt-stpauli.hamburg/wp-content/plugins/wp-google-maps…/v8/atlas-major-feature-list.js?ver=10.1.10

js tierarzt-stpauli.hamburg collected 2026-10-06 04:52:39 UTC 6,857 bytes, 201 lines download raw bytes

1/**
2 * @namespace WPGMZA
3 * @module AtlasMajorFeatureList
4 * @requires WPGMZA
5 *
6 * Custom feature list renderer for Atlas Major.
7 * Renders clean lists for all shape types (polygons, polylines, circles,
8 * rectangles, point labels, heatmaps, image overlays) matching the
9 * Concept C mockup design. Same pattern as AtlasMajorMarkerList.
10 */
11jQuery(function($) {
12
13	if(!document.querySelector('.wpgmza-atlas-major'))
14		return;
15
16	WPGMZA.AtlasMajorFeatureList = function(container, featureType){
17		this.container = container;
18		this.featureType = featureType;
19		this.page = 1;
20		this.perPage = 50;
21		this.searchTerm = '';
22
23		this.render();
24		this.bindMapEvents();
25	}
26
27	/**
28	 * Get features from the map by type
29	 */
30	WPGMZA.AtlasMajorFeatureList.prototype.getFeatures = function(){
31		var map = WPGMZA.maps[0];
32		if(!map) return [];
33
34		var plural = this.featureType + 's';
35		return map[plural] || [];
36	}
37
38	/**
39	 * Get a display name for a feature
40	 */
41	WPGMZA.AtlasMajorFeatureList.prototype.getFeatureName = function(feature){
42		/* Try common name properties */
43		if(feature.title && feature.title.trim()) return feature.title;
44		if(feature.name && feature.name.trim()) return feature.name;
45		if(feature.text && feature.text.trim()) return feature.text;
46
47		/* Fallback: type + ID */
48		var type = WPGMZA.capitalizeWords(this.featureType);
49		return type + ' #' + feature.id;
50	}
51
52	/**
53	 * Get a subtitle/description for a feature
54	 */
55	WPGMZA.AtlasMajorFeatureList.prototype.getFeatureSubtitle = function(feature){
56		if(feature.address && feature.address.trim()) return feature.address;
57		if(feature.description && feature.description.trim()){
58			var text = feature.description.replace(/<[^>]*>/g, '').trim();
59			return text.length > 60 ? text.substring(0, 60) + '...' : text;
60		}
61		return '';
62	}
63
64	/**
65	 * Render the list
66	 */
67	WPGMZA.AtlasMajorFeatureList.prototype.render = function(){
68		if(!this.container) return;
69
70		var features = this.getFeatures();
71		var total = features.length;
72		var totalPages = Math.ceil(total / this.perPage);
73		if(this.page > totalPages) this.page = Math.max(1, totalPages);
74
75		var start = (this.page - 1) * this.perPage;
76		var pageItems = features.slice(start, start + this.perPage);
77
78		var html = '';
79		if(total === 0){
80			html = '<div class="am-ml-empty"><div class="am-empty-text">No ' + this.featureType + 's yet</div></div>';
81		} else {
82			html = '<ul class="am-ml">';
83			for(var i = 0; i < pageItems.length; i++){
84				html += this.renderItem(pageItems[i]);
85			}
86			html += '</ul>';
87		}
88		this.container.innerHTML = html;
89		this.bindItemEvents();
90	}
91
92	/**
93	 * Render a single feature item
94	 */
95	WPGMZA.AtlasMajorFeatureList.prototype.renderItem = function(feature){
96		var id = feature.id;
97		var name = this.esc(this.getFeatureName(feature));
98		var subtitle = this.esc(this.getFeatureSubtitle(feature));
99		var type = this.featureType;
100
101		return '<li class="am-mi" data-feature-id="' + id + '" data-feature-type="' + type + '">' +
102			'<div class="am-mi-body">' +
103				'<div class="am-mi-name">' + name + '</div>' +
104				(subtitle ? '<div class="am-mi-addr">' + subtitle + '</div>' : '') +
105			'</div>' +
106			'<div class="am-mi-ops">' +
107				'<button class="am-mi-btn" data-edit-' + type + '-id="' + id + '" title="Edit">' +
108					'<svg viewBox="0 0 24 24" width="14" height="14" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/></svg>' +
109				'</button>' +
110				'<button class="am-mi-btn" data-fit-feature-bounds-id="' + id + '" title="Center">' +
111					'<svg viewBox="0 0 24 24" width="14" height="14" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>' +
112				'</button>' +
113				'<button class="am-mi-btn am-mi-btn-danger" data-delete-' + type + '-id="' + id + '" title="Delete">' +
114					'<svg viewBox="0 0 24 24" width="14" height="14" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
114' +
115				'</button>' +
116			'</div>' +
117		'</li>';
118	}
119
120	/**
121	 * Bind click events
122	 */
123	WPGMZA.AtlasMajorFeatureList.prototype.bindItemEvents = function(){
124		var self = this;
125		var $container = $(this.container);
126
127		$container.off('click.amflist');
128
129		/* Row click → edit */
130		$container.on('click.amflist', '.am-mi', function(e){
131			if($(e.target).closest('.am-mi-ops').length) return;
132			var id = $(this).data('feature-id');
133			/* Trigger the edit click on the data attribute — core listens on body for these */
134			$('<a data-edit-' + self.featureType + '-id="' + id + '">').appendTo('body').trigger('click').remove();
135		});
136
137		/* Edit button — let it bubble to body where FeaturePanel listens */
138		$container.on('click.amflist', '[data-edit-' + self.featureType + '-id]', function(e){
139			/* Already has the data attribute, event bubbles to body handler */
140		});
141
142		/* Center/fit bounds — let it bubble to AdminFeatureDataTable on body */
143		$container.on('click.amflist', '[data-fit-feature-bounds-id]', function(e){
144			e.stopPropagation();
145			var id = $(this).attr('data-fit-feature-bounds-id');
146			/* Trigger on the datatable element so the handler catches it */
147			var dtElement = $('[data-wpgmza-feature-type="' + self.featureType + '"]');
148			if(dtElement.length){
149				$('<a data-fit-feature-bounds-id="' + id + '">').appendTo(dtElement).trigger('click').remove();
150			}
151		});
152
153		/* Delete — let it bubble to body handler */
154		$container.on('click.amflist', '[data-delete-' + self.featureType + '-id]', function(e){
155			/* Already has the data attribute, event bubbles to body handler */
156		});
157	}
158
159	/**
160	 * Bind map events for live updates
161	 */
162	WPGMZA.AtlasMajorFeatureList.prototype.bindMapEvents = function(){
163		var self = this;
164		var map = WPGMZA.maps[0];
165		if(!map) return;
166
167		var type = this.featureType;
168		map.on(type + 'added', function(){ self.render(); });
169		map.on(type + 'removed', function(){ self.render(); });
170	}
171
172	WPGMZA.AtlasMajorFeatureList.prototype.esc = function(str){
173		var d = document.createElement('div');
174		d.textContent = str;
175		return d.innerHTML;
176	}
177
178	/**
179	 * Initialize all feature lists
180	 */
181	function initFeatureLists(){
182		if(!WPGMZA.maps || !WPGMZA.maps[0]) return;
183
184		$('.am-feature-list-container[data-feature-type]').each(function(){
185			var el = this;
186			var type = $(el).attr('data-feature-type');
187
188			if(el._amFeatureList) return;
189
190			el._amFeatureList = new WPGMZA.AtlasMajorFeatureList(el, type);
191		});
192	}
193
194	$(document.body).on('wpgmza_map_edit_page_created', function(){
195		setTimeout(initFeatureLists, 1000);
196	});
197
198	$(window).on('load', function(){
199		setTimeout(initFeatureLists, 1500);
200	});
201});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.