PageSourceSearch

https://www.stwab.de/static/js/HRSysLib/DragAndDrop/DragAndDropManager.js?nc=1790927228516

js stwab.de collected 2026-10-02 17:48:49 UTC 21,295 bytes, 626 lines download raw bytes

1/**
2 * Drag-and-Drop-Manager als Verwaltung
3 * 
4 * Hier sind alle Draggables und DragTargets verzeichnet
5 */
6var DragAndDropManager = function()
7{
8	this.ZuordnungsArray = new Array();
9	this.dropTargets     = new Array();
10	this.actualDragObject = null;             // 
11	this.actualDropTarget = null;             // 
12	this.StartDropTarget = null;             // 
13//	this.StartDropTargetOrgWidth  = null;             //	 
14//	this.StartDropTargetOrgHeight = null;             // 
15	this.lastDropTargetWithMouseDown = null;  // Das DropTarget auf dem zuletzt der MouseDown-Event ausgelöst wird merken, für den MouseUp-Event
16	this.lastDraggablePosition = null;        // Die letzte Position im DropTarget   
17	this.x_onMouseDown = -1;                  // Die x-MausKoordinaten beim onMouseDown   
18	this.y_onMouseDown = -1;                  // Die y-MausKoordinaten beim onMouseDown
19	
20	this.interval_vertical   = null;
21	this.interval_horizontal = null;
22	
23	this.interval_time = 5;						// 
24	this.scroll_offset = 20;					// 
25	this.scroll_step   = 5;   					// 
26};
27
28
29
30
31/*
32 * Methoden-deklaration
33 */
34
35
36
37
38
39// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 
40// Event-Methoden - für MouseDown, MouseMove, MouseUp 
41// // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
42   
43
44/**
45 * Einstiegspunkt
46 */
47DragAndDropManager.prototype.onMouseDown = function(event)
48{
49   event = event || window.event;                                  // event überprüfen und IE-kompatibel machen
50	
51	// kurzschreibweise definieren, damit der Code besser lesbar wird
52	var m_ = m_DragAndDropManager;
53	
54	// Das aktuelle Draggable müsste null sein
55	if(m_.actualDragObject)
56      return;		
57	
58	// Koordinaten der Maus abspeichern, um zu später falsche onMouseMove Events auszufiltern
59	var mousePos = getMouseCoords(event);
60	m_.x_onMouseDown = mousePos.x;
61   m_.y_onMouseDown = mousePos.y;
62	
63    // this zeigt auf das Element auf dem onMouseDown registriert ist, das ist beim MouseDown das HTML-Element names
64	// "htmlAreaToDragOn" und beim onmousemove und onmouseup das "document"
65	
66	// das aktuelle Draggable merken
67	m_.actualDragObject = this.parentObject;  
68	
69	// DropTarget unter der Mouseposition ermitteln und merken
70	m_.actualDropTarget = m_.getDropTargetUnderMousePosition(event);
71	m_.StartDropTarget = m_.actualDropTarget;
72
73	//
74	// Wir merken uns die OrginalGröße vom Container und setzen diese temporär auf feste Werte,
75	// damit es nicht zu unbeabsichtigtem Scrollen oder so kommt, wenn übergangsweise das
76	// DragObjekt aus dem Container entfernt wird.
77	//
78	// m_.StartDropTargetOrgWidth = -1;
79	// m_.StartDropTargetOrgHeight  = -1;
80
81	if (m_.actualDropTarget && m_.actualDropTarget.htmlElementToDropOn && m_.actualDropTarget.htmlElementToDropOn.style)
82	{	//
83		// Zuerst bestimmen wir die maximale Höhe aller Droptargets, um sie auf die gleiche Höhe zu bringen,
84		// um Draggables bequem zwischen unterschiedlichen Containern hin und herschieben zu können.
85		// Bei den Container, die dabei nicht das aktuelle Draggable enthalten, muss dabei dessen Höhe draufgerechnet
86		// werden, damit auch genug Platz für das neue Objekt ist, da die Höhe dann ja nicht mehr flexibel ist.
87		// !!!ACHTUNG!!! Wir nehmen hier fix an, dass die Container Spaltenweise angeordnet sind!!!
88		var maxHeight = 0;
89		var dragObjectHeight = getElementHeightValue(m_.actualDragObject.rootElement);
90		for(var i = 0; i < m_.dropTargets.length; i++)
91		{
92			var targetHeight = m_.dropTargets[i].getHeightValue();
93			if (m_.dropTargets[i] == m_.actualDropTarget) 
94			{
95				if (targetHeight > maxHeight) 
96					maxHeight = targetHeight;
97			}
98			else 
99			{
100				if (targetHeight + dragObjectHeight > maxHeight) 
101					maxHeight = targetHeight + dragObjectHeight;
102			}
103		}
104		maxHeight = maxHeight + "px"; // !!!Achtung!!! Einbrennung auf Pixel als Einheit!!!
105		
106		// Nun setzen wir diese Höhe für alle Container!
107		for (var i = 0; i < m_.dropTargets.length; i++) 
108		{
109			m_.dropTargets[i].setHeight(maxHeight);
110		}		
111		m_.actualDropTarget.setWidth(m_.actualDropTarget.getWidth());		// Wahrscheinlich überflüssig, die Breite festzusetzen. 
112//		m_.StartDropTargetOrgHeight = m_.actualDropTarget.htmlElementToDropOn.style.height;
113//		m_.actualDropTarget.htmlElementToDropOn.style.height = getStyleValue (m_.actualDropTarget.htmlElementToDropOn, "height");
114//		m_.StartDropTargetOrgWidth = m_.actualDropTarget.htmlElementToDropOn.style.width;
115//		m_.actualDropTarget.htmlElementToDropOn.style.width = getStyleValue (m_.actualDropTarget.htmlElementToDropOn, "width");
116	}
117	
118	// Timer zurücksetzen
119	clearInterval(m_.interval_vertical);
120	clearInterval(m_.interval_horizontal);
121	
122	
123	// den MouseDown-Event zum aktuellen DragObjekt delegieren, welches als Statischer Member im Draggable gespeichert ist.
124	m_.actualDragObject.mouseDown(event);         
125   
126   // letzte Position des Draggables merken	
127	if(m_.actualDropTarget)
128	{
129	   m_.lastDraggablePosition = m_.actualDropTarget.getPosition (m_.actualDragObject);
130      
131      // zum aktuellen DropTarget den Aufruf delegieren
132      m_.actualDropTarget.mouseDown(event, this.parentObject);
133		
134      // Das Target auf dem zuletzt geklickt wurde für später merken
135      m_.lastDropTargetWithMouseDown = m_.actualDropTarget;
136	}
137	else
138	{
139	}
140
141	// Events registrieren  
142	// das "this" zeigt auf das HTML-Element mit dem der onmousedown-Event verknüpft ist
143	document.onmousemove = DragAndDropManager_onmousemove;
144	document.onmouseup   = DragAndDropManager_onmouseup;
145   
146//	m_.printEverythingToFixedDiv();
147//	m_.triggerDraggablePrintMethods();
148	
149	//writeToDocumentBody("DragAndDropManager.prototype.onMouseDown - abgearbeitet ", "ok");
150   return false;
151};
152
153
154/**
155 * Einstiegspunkt
156 */
157DragAndDropManager.prototype.onMouseMove = function(event)
158{	
159   event = event || window.event;                                  // event überprüfen und IE-kompatibel machen
160   
161	// Schauen ob sich der Mauszeiger seit dem MouseDown-Event wirklich bewegt hat
162	var mousePos = getMouseCoords(event); 
163	
164   if (this.x_onMouseDown == mousePos.x && this.y_onMouseDown == mousePos.y)
165	   return;
166	   
167 	
168   // wenn kein DragObjekt bewegt wird, wird die Methode verlassen
169   if (!this.actualDragObject)
170	   return;
171	
172	
173   var mouseButton;
174	if(navigator.appName == "Microsoft Internet Explorer")
175	{
176		mouseButton = event.button;
177	}
178	else
179	{
180		mouseButton = event.which;
181	}
182
183	// Für nicht IE7 und nicht IE8
184	if( ( (navigator.userAgent.indexOf('MSIE 6') > 0) || (navigator.userAgent.indexOf('MSIE 7') > 0) ) && (mouseButton == 0) )
185	{
186      // setze Draggable zurück an ursprüngliche Position
187      this.actualDragObject.bringZurueckZurUrspruenglichenPosition();
188		if(this.lastDropTargetWithMouseDown && this.lastDraggablePosition && this.actualDragObject)
189         this.lastDropTargetWithMouseDown.insertAt(this.lastDraggablePosition, this.actualDragObject);
190		this.actualDragObject = null;
191		this.restoreSizeOfStartDropTarget();
192      return;
193	}
194	
195  // Scrollen wenn nötig
196   this.scrollIfNecessary(event);
197   
198 	// den MouseMove-Event delegieren zum aktuellen DragObjekt, damit sich dieses bewegt und am Mauspfeil bleibt 
199   this.actualDragObject.mouseMove(event);
200	
201   // DropTarget unter dem Mauspfeil ermitteln	
202	var dropTarget = this.getDropTargetUnderMousePosition(event);
203	
204	// Wenn das ermittelte DropTarget unter der Mouseposition ein anderes ist, als das Letzte. Es kann auch null sein. 
205	if(this.actualDropTarget != dropTarget)                               
206	{
207      if(this.actualDropTarget)
208		    this.actualDropTarget.mouseOut(event, this.actualDragObject);
209		
210		//this.entfernePlatzhalterBeiAllenDropTargets();                    // alle möglichen Platzhalter löschen
211		this.actualDropTarget = dropTarget;                               // gefundenes DropTarget merken
212		
213		// dem DropTarget mitteilen, dass da kein MouseOver mehr ist, quasi ein onLeave-Event
214      if(this.actualDropTarget)
215		    this.actualDropTarget.mouseEnter(event,this.actualDragObject);
216	}
217	if(this.actualDropTarget)
218	{
219	   this.actualDropTarget.mouseMove(event,this.actualDragObject);
220	}
221	
222//	this.printEverythingToFixedDiv();
223//	this.triggerDraggablePrintMethods();
224	
225   return;
226
227};
228
229
230/**
231 * Einstiegspunkt
232 */
233DragAndDropManager.prototype.onMouseUp = function(event)
234{
235	event = event || window.event;                                  // event überprüfen und IE-kompatibel machen
236
237	// Timer zurücksetzen
238	clearInterval(this.interval_vertical);
239	clearInterval(this.interval_horizontal);
240		
241	// Wenn das aktuelle DragObject existiert 
242   if(this.actualDragObject)
243   {
244		// den MouseUp-Event delegieren zum aktuellen DragObjekt
245		this.actualDragObject.mouseUp(event); 
246   }
247	
248	// Wenn das aktuelle DropTarget existiert 
249   if(this.actualDropTarget)
250   {
251      // Das Draggable aus der alten Position löschen
252		if(this.lastDropTargetWithMouseDown)
253         this.lastDropTargetWithMouseDown.removeDraggable(this.actualDragObject);
254      // den MouseUp-Event delegieren zum aktuellen DropTarget
255      this.actualDropTarget.mouseUp(event,this.actualDragObject);
256   }
257	else if(!this.dropTargets || this.dropTargets.length == 0)
258	{
259		; // do nothing
260	}
261	else
262	{
263       // setze Draggable zurück an ursprüngliche Position
264		 
265		 
266		 if(this.lastDropTargetWithMouseDown && this.actualDragObject)
267		 {
268         this.lastDropTargetWithMouseDown.insertAt(this.lastDraggablePosition, this.actualDragObject);
269		 }
270       this.actualDragObject.bringZurueckZurUrspruenglichenPosition();
271	}
272	
273	this.restoreSizeOfStartDropTarget();
274	
275	// aktuelles Draggable löschen
276	this.actualDragObject = null;
277	
278	// Events wieder löschen
279	document.onmousemove  = null;
280   document.onmouseup    = null;
281	
282//	this.printEverythingToFixedDiv();
283//	this.triggerDraggablePrintMethods();
284	
285   return;
286};
287
288
289
290
291
292// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 
293// Scroll
294// // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
295
296/**
297 * Einstiegspunkt
298 */
299DragAndDropManager.prototype.scrollIfNecessary = function(event)
300{   
301   var scroll_step = this.scroll_step;
302	var m_ = this;
303                                                                      
304   // links
305   if(event.clientX < this.scroll_offset && event.clientX < 0)      
306   {     
307      if ( ! this.interval_vertical)
308        this.interval_vertical = setInterval( 
309        	function() { 
310        			setScrollPosition (getScrollPosition().x - scroll_step , getScrollPosition().y); 
311		        	m_.actualDragObject.addPostionOffset(-scroll_step,0);
312		        	if( getScrollPosition().x <= 0 )
313		        	{ 
314		        		clearInterval(m_.interval_vertical);
315		        	}
316        		}, this.interval_time);
317   }  
318   // rechts
319   else if(event.clientX > window.innerWidth - this.scroll_offset)
320   {
321      if ( ! this.interval_vertical)
322         this.interval_vertical = setInterval( 
323         	function() { 
324         			setScrollPosition (getScrollPosition().x + scroll_step , getScrollPosition().y ); 
325         			m_.actualDragObject.addPostionOffset(scroll_step,0); 
326		        	if( getScrollPosition().x >= window.innerWidth )
327		        	{ 
328		        		clearInterval(m_.interval_vertical);
329		        	}      			
330         		}, this.interval_time);
331   }
332   else
333   {
334      clearInterval(this.interval_vertical);
335      this.interval_vertical = null;
336   }
337
338            
339   // oberhalb
340   if(event.clientY < this.scroll_offset)
341   {
342      if ( ! this.interval_horizontal)
343         this.interval_horizontal = setInterval( 
344         	function() { 
345         			setScrollPosition (getScrollPosition().x, getScrollPosition().y - scroll_step ); 
346         			m_.actualDragObject.addPostionOffset(0,-scroll_step); 
347		        	if( getScrollPosition().y <= 0 )
348		        	{ 
349		        		clearInterval(m_.interval_horizontal);
350		        	}
351         		}, this.interval_time);
352   }
353   // unterhalb
354   else if(event.clientY > getWindowHeight() - this.scroll_offset)       
355   {
356      if ( ! this.interval_horizontal)
357         this.interval_horizontal = setInterval( 
358         	function() { 
359         			setScrollPosition (getScrollPosition().x, getScrollPosition().y + scroll_step ); 
360         			m_.actualDragObject.addPostionOffset(0,scroll_step); 
361		        	if( getScrollPosition().y >= window.innerHeight )
362		        	{ 
363		        		clearInterval(m_.interval_horizontal);
364		        	}
365         		}, this.interval_time);
366   }
367   else
368   {
369      clearInterval(this.interval_horizontal);
370      this.interval_horizontal = null;
371   }
372}
373
374
375
376// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 
377// Commands
378// // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
379
380/**
381 * Fügt der Verwaltung vom Manager ein DropTarget hinzu
382 */
383DragAndDropManager.prototype.addDropTarget = function(dropTarget)
384{
385	this.dropTargets.push(dropTarget);
386   return;
387}
388
389/**
390 * Fügt der Verwaltung vom Manager ein DropTarget hinzu
391 */
392DragAndDropManager.prototype.restoreSizeOfStartDropTarget = function()
393{
394	if (this.StartDropTarget && this.StartDropTarget.htmlElementToDropOn && this.StartDropTarget.htmlElementToDropOn.style)
395	{
396//		this.StartDropTarget.htmlElementToDropOn.style.height = this.StartDropTargetOrgHeight;
397//		this.StartDropTarget.htmlElementToDropOn.style.width = this.StartDropTargetOrgWidth;
398		this.StartDropTarget.restoreWidth();
399		for (var i = 0; i < this.dropTargets.length; i++) 
400		{
401			this.dropTargets[i].restoreHeight();
402		}		
403	}
404	this.StartDropTarget = null;
405//	this.StartDropTargetOrgHeight = -1;
406//	this.StartDropTargetOrgWidth = -1;
407   return;
408}
409
410
411/**
412 * Hiermit wird eine Zuordnung von Draggable zu DropTarget-Art zu gemacht
413 * @param {Object} dropObjekte Array mit DragObjekten
414 * @param {Object} zielContainer Array mit ZielContainern
415 */ 
416DragAndDropManager.prototype.addZuordnung = function(draggables, dropTargets)
417{
418    this.ZuordnungsArray.push(draggables);    // index 2*n 
419    this.ZuordnungsArray.push(dropTargets);  // index 2*n+1
420}
421
422/**
423 * Löscht alle möglichen Platzhalter, in dem es bei jedem DropTarget die Methode entfernePlatzhalter aufruft
424 */ 
425DragAndDropManager.prototype.entfernePlatzhalterBeiAllenDropTargets = function()
426{
427    for (var i = 0; i < m_DragAndDropManager.dropTargets.length; i++)
428    {
429       m_DragAndDropManager.dropTargets[i].entfernePlatzhalter();
430    }
431}
432
433/**
434 * Fügt dem ersten DropTarget im Manager das übergebene GipsApp an der Position 0 hinzu.
435 * @param {Object} gipsApp
436 */
437DragAndDropManager.prototype.pushGipsAppToFirstDropTarget = function(gipsApp)
438{
439	if(this.dropTargets[0])
440	   this.dropTargets[0].insertAt(0,gipsApp);
441//	this.printEverythingToFixedDiv();
442//	this.triggerDraggablePrintMethods();
443}
444
445
446/**
447 * Diese Funktion ist zum Löschen eine GipsApps. Dazu wird der Löschbefehl weitergeleitet
448 * an den Server, um den Eintrag in der DB zu löschen, 
449 * an das DropTarget, um alle Referenzen darauf zu entfernen
450 * an das Draggable selbst, damit es sich und seine HTML-Elemente löscht
451 * 
452 * @param {Object} urlZumLoeschen
453 * @param {Object} id
454 */
455DragAndDropManager.prototype.destroyDraggable = function(closeButtonDiv, urlZumLoeschen,id)
456{
457   // Destroy-Meldung an Server schicken um Datenbankeintrag zu entfernen
458   sendRequest(urlZumLoeschen, null);
459   
460	// Draggable als Objekt holen   
461	var draggable = null;
462	var element = closeButtonDiv;
463	while ((typeof(element)=="object")&&(typeof(element.tagName)!="undefined"))  
464	{
465		// Suchen bis das von der Klasse Draggable künstlich injizierte Objekt parentObject gefunden wurde
466		if(element.parentObject && element.parentObject instanceof Draggable)                
467		{
468			draggable = element.parentObject;
469			break;
470		}
471		element = element.parentNode;
472	}
473	
474	
475	
476   // Destroy-Meldung an die DropTargets weiterleiten, um innere Datenstrukturen aufzuräumen
477	for(var i = 0; i < this.dropTargets.length; i++)
478	{
479	   this.dropTargets[i].removeDraggable(draggable);	
480	}
481	
482   
483   // Destroy-Meldung um das DragObjekt (und alle seine HTML-Elemente) zu löschen
484   draggable.removeHTML();             //
485   delete draggable;                   // Objekt abräumen
486	
487   // Datenstrukturen im Manager aufräumen
488	this.ZuordnungsArray.removeObject(draggable); // TODO: wird das ZuordnungsArray überhaupt verwendet? 
489	this.actualDragObject = null;             // 
490   this.actualDropTarget = null;             // 
491   this.lastDropTargetWithMouseDown = null;  // 
492   this.lastDraggablePosition = null;        // 
493   
494//	this.triggerDraggablePrintMethods();
495//	this.printEverythingToFixedDiv();
496}
497
498 
499 
500// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // 
501// Queries
502// // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
503
504
505/**
506 *  Gibt das im Manager registrierte DropTarget zurück, welches sich unter der Maus befindet
507 */
508DragAndDropManager.prototype.getDropTargetUnderMousePosition = function(event)
509{
510
511   for(var i = 0 ; i < this.dropTargets.length; i++)
512   {
513      if(isMouseOverElement(this.dropTargets[i].htmlElementToDropOn,event))
514      {
515         return this.dropTargets[i];
516      }
517   }
518   return null;
519}
520
521/**
522 * Gibt das aktuelle DragObject zurück
523 */
524DragAndDropManager.prototype.getActualDragObject = function()
525{
526	return this.actualDragObject;	
527}
528
529
530//////////////////////////////////////////////////////////////////////////
531    //                                                              //    
532    //                        Globaler Member                       //    
533    //                                                              //    
534//////////////////////////////////////////////////////////////////////////
535var m_DragAndDropManager = new DragAndDropManager();
536
537function DragAndDropManager_onmousemove(event)
538{
539	m_DragAndDropManager.onMouseMove(event);
540}
541function DragAndDropManager_onmouseup(event)
542{
543	m_DragAndDropManager.onMouseUp(event);
544}
545
546
547
548/**
549 * Print-Funktion
550 */
551DragAndDropManager.prototype.printMember = function()
552{
553	for(var i = 0 ; i < this.ZuordnungsArray.length; i++)
554	{
555	   console.log("this.ZuordnungsArray[" , i, "]", this.ZuordnungsArray[i]);
556	}
557	for(var i = 0 ; i < this.dropTargets.length; i++)
558	{
559	   console.log("this.dropTargets[", i, "]", this.dropTargets[i].htmlElementToDropOn.id);
560	}
561	
562	console.log("actualDragObject",this.actualDragObject);
563	console.log("this.actualDropTarget",this.actualDropTarget);
564	console.log("this.lastDropTargetWithMouseDown",this.lastDropTargetWithMouseDown);
565	console.log("",this.lastDraggablePosition);
566}	
567	
568DragAndDropManager.prototype.writeKeyValuesToFixedDiv = function(key, string)
569{
570    // Ausgabe-Div mit weissem Hintergrund und Fensterleiste kreieren
571    var ausgabeDiv = document.getElementById( "DasTemporaereSchwebendeAusgabeDiv");
572    var fensterLeisteDiv;
573    if (ausgabeDiv == null)
574    {
575        ausgabeDiv = document.createElement('div');
576        document.getElementsByTagName("body")[0].appendChild(ausgabeDiv);
577        ausgabeDiv.id = "DasTemporaereSchwebendeAusgabeDiv";
578        fensterLeisteDiv = document.createElement('div');
579        fensterLeisteDiv.style.height = "20px";
580        ausgabeDiv.appendChild(fensterLeisteDiv);
581        ausgabeDiv.style.backgroundColor = "white";
582        ausgabeDiv.style.border          = "1px solid black";
583        ausgabeDiv.style.zIndex          = 10000; 
584        ausgabeDiv.style.position        = 'absolute'; 
585        ausgabeDiv.style.top             = '0px';
586    }
587    ausgabeDiv.ondblclick = function() {document.getElementsByTagName("body")[0].removeChild(ausgabeDiv);};
588    
589    // Key-Values ausgeben. Der Key ist die ID des DIVs und das Label.
590    var keyValueDiv = document.getElementById("IdKeyValueDiv"+key);
591    if (keyValueDiv == null )
592    {
593        keyValueDiv = document.createElement( "DIV" );
594        keyValueDiv.id = "IdKeyValueDiv"+key;
595        ausgabeDiv.appendChild(keyValueDiv);
596    }
597    keyValueDiv.innerHTML = "<p>" + key + ": " + string + "</p>";
598    return ausgabeDiv;    
599}
600
601/**
602 * 
603 */
604DragAndDropManager.prototype.printEverythingToFixedDiv = function()
605{
606   for(var i = 0; i < this.dropTargets.length; i++)
607	{
608//	   for(var i = 0; i < this.draggables.length; i++)
609	   if(this.dropTargets[i].htmlElementToDropOn && this.dropTargets[i].htmlElementToDropOn.id)
610		{
611         this.writeKeyValuesToFixedDiv(this.dropTargets[i].htmlElementToDropOn.id + "_Anzahl", this.dropTargets[i].draggables.length );
612			
613		}
614	}
615};
616
617DragAndDropManager.prototype.triggerDraggablePrintMethods = function()
618{
619	for(var i = 0; i < this.dropTargets.length; i++)
620	{
621		for(var j = 0; j < this.dropTargets[i].draggables.length; j++)
622		{
623			this.dropTargets[i].draggables[j].printEverythingToDebuggingInfoDiv();
624		}
625	}
626}

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.