Assembla home | Assembla project page
 

root/colbrowser/colbrowser.js

Revision 68, 115.6 kB (checked in by brettz9, 1 year ago)

subtle global fixed

Line 
1 /*global HTTP, Keymap, Tooltip, XML, netscape */
2 // Check JS with jslint.com
3
4 // See references marked 'fix:' and in the other files written by originally by others, see references to 'Brett'
5 // "Deprecated comment" means I want to keep the comment in in case problems turn up with my having commented the
6 //     code out (but they should be removed eventually)
7 // Might use alert(document.activeElement); for getting element for adding, deleting, modifying items but works in FF3 only
8 // Do class hierarchy for different types of column browsers (XML/JSON, file browsing/generic, etc.)
9 // See note in the tooltip-mouse.js file on the need to let the column browser work with static (default) positioning
10 //      as well as absolute, fixed, and relative positioning
11 // Fix: make positioning of input box perfect within scroll area
12 // Could make processing instructions broken up by name, pseudo-attribute names and pseudo-attribute values
13 // Fix: Caching requests in http.js file don't seem to work always
14 // Fix: change "rendered" metadata behavior not to imbed directly (as can interfere with DOCTYPE, etc.) but put as iframe
15 // The code might be sped up quite a bit with the finding of all processing instructions and comments removed, but
16 //   keeping it in now for testing
17 // Fix rendering meta section to not show nodes which an XPath expression for an XLink or XInclude should avoid (but show the ones it should)
18
19 // IE BUGS
20 // Fix: xhtml and svg extensioned files don't work as XML in IE but pure xml works fine
21 // MOV code not working in IE
22 // To get local permissions to work from file:// to external sites, in IE go to: Tools->Internet Options->Security->Internet-> ( -> ) Miscellaneous -> Access data sources across domains
23
24
25 // Can use a different _MetaInfoStrategy (requires , e.g.,:
26 //      brettz9.mycolbrowser1 = new brettz9.colbrowser('<root><dog/><cat/><fred>adfdfds</fred></root>', myMetaInfoStrategy);
27 // Can use a different _ColDisplayStrategy too
28
29
30 var brettz9 = function () {
31
32         // Class methods (but making private instead of attaching directly to _MetaInfoStrategy (for _getNodeInfo()) or _colbrowser. (like "_colbrowser.getNodeInfo"); also allows shorter reference
33
34         var that = this;
35
36         /**
37          *@constructor
38          */
39         function _ColDisplayStrategy () {
40         }
41         _ColDisplayStrategy.prototype.addColumnEntryName = function (appendEl, colElement) {
42                 // Fix: Make the following (and that under 'title' (which should be tooltip) as private functions of this class (but only nodeName on by default; let its constructor and methods take arguments, etc., for attribute name)
43                 /* The following could add by attribute (let user opt for attribute if present (or text content) or make required and with optional namespace)
44                         if (thisitem.hasAttribute('abc')) {
45                                 option.innerHTML = thisitem.getAttribute('abc');
46                         }
47                         else
48                         */
49                        /* Works for showing all immediate text content
50                        var textoutput = '';
51                        var nodes = thisitem.childNodes;
52                         for (j = 0; j < nodes.length; j++) {
53                                 if (nodes[j].nodeType === 3) { // TEXT_NODE
54                                         if (!nodes[j].nodeValue.match(/^\s+$/)) {
55                                                 textoutput += brettz9.XML.escapeString(nodes[j].nodeValue);
56                                         }
57                                 }
58                         }
59                         
60                         if (textoutput) {
61                                 option.innerHTML = textoutput;
62                                 option.setAttribute('title', textoutput); // Could also put as tooltip
63                         }
64                         else
65                         */
66                 appendEl.innerHTML = colElement.nodeName;
67         }
68         /**
69          * Might do a tooltip that was JavaScript based (e.g., so Firefox could show tooltip in 2d plane)
70          */
71         _ColDisplayStrategy.prototype.addColumnEntryTitle = function (appendEl, colElement) {
72                 //var colElementTextContent = _colbrowser.MSIE ? colElement.text : colElement.textContent;
73                 // appendEl.title = colElementTextContent;
74                 return null;
75         }
76        
77        
78         // A UTILITY FUNCTION FOR POPULATE INFO METHODS
79         function _getNodeInfo (nodes, spanclass) { // Builds meta info display for a node
80                 var commentsproc = ''; // Make sure it has something to overwrite as well for appending
81                 if (spanclass === undefined) {
82                         spanclass = 'colbrows_characteristic';
83                 }
84                 for (var i = 0; i < nodes.length; i++) {
85                         if (nodes[i]) { // Not sure why this would be blank, but it was
86                                 switch (nodes[i].nodeType) {
87                                         case 1: // ELEMENT_NODE
88                                         // Ignore
89                                                 break;
90                                         /*/
91                                         case 2: // ATTRIBUTE_NODE
92                                         break;
93                                         */
94                                         case 3: // TEXT_NODE
95                                                 if (!nodes[i].nodeValue.match(/^\s+$/) && 1) {
96                                                         commentsproc += '<span class="'+spanclass+'">Text:<\/span> '+brettz9.XML.escapeString(nodes[i].nodeValue)+'<br />';
97                                                 }
98                                                 break;
99                                         case 4: // CDATA_SECTION_NODE
100                                                 commentsproc += '<span class="'+spanclass+'">CDATA section:<\/span> '+brettz9.XML.escapeString(nodes[i].nodeValue)+'<br />';
101                                                 break;
102                                         /* These are already resolved by this time in FF's DOM
103                                         case 5: // ENTITY_REFERENCE_NODE
104                                                 // alert('Entity: '+nodes[i].nodeName);
105                                                 // Also cycle child nodes to get replacement text
106                                                 break;
107                                         */
108                                         /* These are just added here if we need them later; but these would occur at a higher order level
109                                         case 6: // ENTITY_NODE
110                                                 break;
111                                         */
112                                         case 7: // PROCESSING_INSTRUCTION_NODE
113                                                 commentsproc += '<span class="'+spanclass+'">Proc Inst:<\/span> &lt;?'+nodes[i].nodeName +' '+ nodes[i].nodeValue+'?&gt;<br />';
114                                                 break;
115                                         case 8: // COMMENT_NODE
116                                                 commentsproc += '<span class="'+spanclass+'">Comment:<\/span> '+nodes[i].nodeValue+'<br />';
117                                                 break;
118                                         /*
119                                         case 9: // DOCUMENT_NODE
120                                                 break;
121                                         */
122                                         case 10: // DOCUMENT_TYPE_NODE
123                                                 // Just ignore
124                                                 break;
125                                         /*
126                                         case 11: // DOCUMENT_FRAGMENT_NODE
127                                                 break;
128                                         case 12: // NOTATION_NODE
129                                                 break;
130                                         */
131                                         default:
132                                                 throw 'Unexpected element: '+nodes[i].nodeType;
133                                 }
134                         }
135                 }
136                 return commentsproc;
137         }
138        
139         /**
140          *@constructor
141          */
142         function _MetaInfoStrategy (defaultXmlString) {
143                 // Constructor
144 //              this.xmlstring = defaultXmlString;
145         }
146         _MetaInfoStrategy.prototype.populateMetaInfo = function (thisitem) {
147                 if (!thisitem) {
148                         return;
149                 }
150                
151
152                 // ATTRIBUTES OF NODE
153                 var attdisplay = '';
154                 if (thisitem.attributes) {
155                         var attrs = thisitem.attributes;
156                         if (attrs.length > 0) {
157                                 attdisplay += '<table class="colbrows_att"><th class="colbrows_att">Name<\/th><th class="colbrows_att">Value<\/th>';
158                                 for (var i = 0; i < attrs.length; i++) {
159                                         attdisplay += "<tr class='colbrows_att'><td class='colbrows_attrname'>"+attrs[i].nodeName+"<\/td>";
160                                         attdisplay += "<td class='colbrows_attrval'>"+brettz9.XML.escapeString(attrs[i].nodeValue)+"<\/td><\/tr>";
161                                 }
162                                 attdisplay += '<\/table>';
163                         }
164                 }
165
166                 var colbrows_attributes = document.getElementById('colbrows_attributes');
167                 colbrows_attributes.innerHTML = attdisplay;
168
169                 // FULL PLAIN TEXT CONTENT OF NODE
170                 var colbrows_text = document.getElementById('colbrows_text');
171                 var thisitemTextContent = _colbrowser.MSIE ? thisitem.text : thisitem.textContent;
172                
173                 colbrows_text.innerHTML = '<textarea rows="5" cols="40">'+brettz9.XML.escapeString(thisitemTextContent)+'<\/textarea>';
174
175                 // Fix: report bug: Note that FF seems to mistakenly escape gt signs within attributes when serializing
176                 var renderedXML = XML.serialize(thisitem);
177
178
179                 // NODE'S FULL ESCAPED CONTENT (I.E., AS TEXT)
180                 var colbrows_textchild = document.getElementById('colbrows_textchild');
181                 colbrows_textchild.innerHTML = '<textarea rows="5" cols="40">'+brettz9.XML.escapeString(renderedXML)+'<\/textarea>';
182
183                 // NODE'S FULL UNESCAPED CONTENT (I.E., RENDERED)
184                 var colbrows_rendered = document.getElementById('colbrows_rendered');
185                 colbrows_rendered.innerHTML = renderedXML;
186
187                 // COMMENTS, PROCESSING INSTRUCTIONS, TEXT, AND CDATA WITHIN JUST THIS NODE
188                 var children = thisitem.childNodes;
189                 var commentsProcTextCdata = _getNodeInfo(children);
190                 var colbrows_commentsprocinst = document.getElementById('colbrows_commentsprocinst');
191                 colbrows_commentsprocinst.innerHTML = commentsProcTextCdata;
192         };
193        
194         _MetaInfoStrategy.prototype.populateDocInfo = function (xml) {
195                 var docel = xml.documentElement ? xml.documentElement : xml.ownerDocument.documentElement; // Necessary for root node data (and what is before/after root)
196
197                 var colbrows_doc = document.getElementById('colbrows_document');
198
199                
200                 // ROOT NODE AND DOCTYPE DATA
201                 colbrows_doc.innerHTML = '<span class="colbrows_characteristic">Root node:<\/span> '+docel.nodeName+', <span class="colbrows_rootns">Namespace<\/span>: '+docel.namespaceURI+'<br />'+ /* (xml.doctype)?xml.doctype.name */
202                         '<span class="colbrows_characteristic">Internal subset:<\/span> '+(xml.doctype ? brettz9.XML.escapeString(xml.doctype.internalSubset) : 'none')+'<br />'+
203                         '<span class="colbrows_characteristic">Public ID:<\/span> '+(xml.doctype ? brettz9.XML.escapeString(xml.doctype.publicId) : 'none') + '<br />'+
204                         '<span class="colbrows_characteristic">System ID:<\/span> '+(xml.doctype ? brettz9.XML.escapeString(xml.doctype.systemId) : 'none') + '<br />';
205
206
207                 // NODES BEFORE AND AFTER THE ROOT
208                 var nodedata;
209                 var i=0;
210                 var rootprevtemp = docel;
211                 var rootposttemp = docel;
212                 var rootpre = [];
213                 var rootpost = [];
214                 while (rootprevtemp) {
215                         rootpre[i] = rootprevtemp.previousSibling;
216                         i++;
217                         rootprevtemp = rootprevtemp.previousSibling;
218                 }
219
220                 rootpre = brettz9.PHP.array_reverse(rootpre);
221
222                 colbrows_doc.innerHTML += '<span class="colbrows_preroot">Before the root<\/span><br />';
223                 colbrows_doc.innerHTML += _getNodeInfo(rootpre, 'colbrows_prepostnodes');
224
225                 i=0;
226                 while (rootposttemp) {
227                         rootpost[i] = rootposttemp.nextSibling;
228                         i++;
229                         rootposttemp = rootposttemp.nextSibling;
230                 }
231                 colbrows_doc.innerHTML += '<span class="colbrows_postroot">After the root<\/span><br />';
232                 colbrows_doc.innerHTML += _getNodeInfo(rootpost, 'colbrows_prepostnodes');
233
234                 // UNIMPLEMENTED FEATURES
235                 // alert(document.domConfig); // Not implemented
236                 // alert(document.schemaTypeInfo); // 'undefined''
237                 //alert(document.setUserData()); // Not enough arguments
238                 //alert(DOMLocator); // Used by error // is not defined error
239
240                 // ADDITIONAL DOCUMENT METADATA FEATURES
241                 /**
242                 // From http://www.w3.org/TR/DOM-Level-2-Core/introduction.html#ID-Conformance for others
243                 var DOMFeatures = ['XML', 'HTML', 'Core', 'Views', 'StyleSheets', 'CSS', 'CSS2', 'Events', 'UIEvents', 'MouseEvents', 'MutationEvents', 'HTMLEvents', 'Range', 'Traversal'];
244                 for (var j=1; j <= 2; j++) {
245                         for (i=0; i < DOMFeatures.length; i++) {
246                                 colbrows_doc.innerHTML += DOMFeatures[i]+" Lev. "+j+": ";
247                                 colbrows_doc.innerHTML += document.implementation.hasFeature(DOMFeatures[i], j+".0");
248                                 colbrows_doc.innerHTML += '<br />';
249                         }
250                 }
251                 */
252
253                 // NOT SUPPORTED:
254                 /*
255                 // ENTITIES
256                 colbrows_doc.innerHTML += '<span class="colbrows_characteristic">Entities:<\/span> ';
257                 for (i=0; i < xml.doctype.entities.length; i++) {
258                         colbrows_doc.innerHTML += xml.doctype.entities.item[i];
259                         colbrows_doc.innerHTML += '<br />';
260                 }
261                 // NOTATIONS
262                 colbrows_doc.innerHTML += '<span class="colbrows_characteristic">Notations:<\/span> ';
263                 for (i=0; i < xml.doctype.notations.length; i++) {
264                         colbrows_doc.innerHTML += xml.doctype.notations.item[i];
265                 }
266                 colbrows_doc.innerHTML += '<br />';
267                 */
268
269                
270                 // ALL PROCESSING INSTRUCTIONS IN THE DOCUMENT
271                 var colbrows_procinsts = document.getElementById('colbrows_procinsts');
272                 // Proc. inst's and comments are not supposed to have namespaces: http://www.w3.org/TR/REC-xml-names/#Conformance
273                 var allprocinsts = XML.getNodes(xml, '//processing-instruction()', null, xml);
274
275                 var procinsts = '';
276                 for (i = 0; i < allprocinsts.length; i++) {
277                         procinsts += '&lt;?'+allprocinsts[i].nodeName+' '+allprocinsts[i].nodeValue+'?&gt;\n';
278                 }
279                 colbrows_procinsts.innerHTML = '<textarea rows="5" cols="40">'+procinsts+'<\/textarea>';
280
281                  // ALL COMMENTS IN THE DOCUMENT
282                 var colbrows_comments = document.getElementById('colbrows_comments');
283                 var allcomments = XML.getNodes(xml, '//comment()', null, xml);
284                
285                 var comments = '';
286                 for (i = 0; i < allcomments.length; i++) {
287                         comments += '&lt;!--'+allcomments[0].nodeValue+'--&gt;\n';
288                 }
289                 colbrows_comments.innerHTML = '<textarea rows="5" cols="40">'+comments+'<\/textarea>';
290         };
291         _MetaInfoStrategy.prototype.populateAllInfo = function (targvalue, URLtoXMLDoc) {
292                 if (!targvalue) {
293                         return; // avoid if one has deleted all
294                 }
295                
296                 var pattern = _colbrowser.XPathPlus;
297                 var doc = targvalue.match(pattern);
298                 var xml;
299                 if (doc) {
300                         var docFileXLink = doc[1];
301                         var fileXLinkAndXPath = doc[3]+(doc[4]?doc[4]:'');
302                         var currentXPath = doc[6];
303                         var fileXLink = doc[3];
304                 }
305
306                 if (doc && fileXLink) {
307                         if (fileXLink.match(/^this\./)) { // If it is a string stored locally
308                                 xml = URLtoXMLDoc[docFileXLink];
309                         }
310                         else if (URLtoXMLDoc[fileXLinkAndXPath]) {
311                                 xml = URLtoXMLDoc[fileXLinkAndXPath]; // Grab XML in 'cache'/memory
312                         }
313                         targvalue = currentXPath;
314                 }
315
316                 targvalue = (targvalue === '') ? '/*' : targvalue;
317
318                 // var nsResolver = document.createNSResolver((xml.ownerDocument === null)?xml.documentElement:contextNode.ownerDocument.documentElement);
319                 var thislevel = XML.getNodes(xml, targvalue, null, xml);
320                 var thisitem = thislevel[0];
321                
322                 this.populateMetaInfo(thisitem);
323
324                 this.populateDocInfo(xml); // Need to repopulate since
325         };
326
327
328        
329         /**
330          *@constructor
331         * Private method to become public when returned
332         * Advantage of being embedded here (though less modular and requires return code) is access to private functions above throughout even instance classes
333         */
334         function _colbrowser (/*optional*/ defaultXml, /*optional*/ UserMetaInfoStrat, /*optional*/ ColDisplayStrat) { // Fix: define this constructor to set some of the following values
335                 // Private should come first since nested should be first (though might be preced by 'var that = this;' if want access to instance vars'
336                 // See http://www.crockford.com/javascript/private.html
337
338                 // Should be private instance methods (require 'this')
339                 // Instance properties (if want any of these private, could declare getters/setters: JDG, p. 163 (using priv. methods; instance methods couldn't otherwise reach THESE private members); good for allowing redefinitions and extra processing)
340                 // Could compartmentalize the following into private functions with 'this' access (via 'that')'
341                 
342                 // INITIALIZE TRACKING VARS
343                 this.idCounter = 0;
344                 this.tabIndex = true;
345
346                 // DEFAULT CLASS NAME AFFIXES
347                 this.colbrows_prfx = 'colbrows_'; // Identify the column for internal use
348                 this.colbrows_suffix = 'colbrowser';
349                 this.css_prfx = 'colbrows_'; // Create the columns' class (for use with CSS); DIsabling this makes a very interesting wrapping column browser!
350                 
351                
352                 // DEFAULT COLBROWSER STYLING
353                 this.colbrows_style_top = '50px';
354                 this.colbrows_style_left = '60px';
355                 this.colbrows_style_height = '250px';
356                 this.colbrows_style_width = '640px'; /* Should be somewhat larger than a multiple of the select widths to show new column */
357                 this.colbrows_style_position = 'relative';
358                 this.colbrows_style_overflow = 'auto'; // Can turn this off to allow the column to go beyond a predefined area
359
360                 // DEFAULT COLUMN STYLING
361                 this.select_size = '10';
362                 this.select_style_top = '80px';
363                 this.select_style_width = '200px';
364                 this.select_style_left = 0;
365                 this.select_start_selindex = 0;
366                
367                 // REGULAR EXPRESSIONS FOR MEDIA FILES
368                 // These could be class methods but still might change per object
369                 this.pattern_img = /(.*\.js)(\?.*\.(jpg|jpeg|png|gif|bmp|ico))$/i;
370                 this.pattern_iframe = new RegExp ('(.*\\.js)(\\?.*\\.(html|htm|dhtml|svg|xml|xul|rdf'+(!this.MSIE ? '|xhtml':'')+'))$', 'i');
371                 this.pattern_text = /(.*\.js)(\?.*\.(txt|rtf|js|css|php|dtd|url|lrc|properties|htaccess|xsl))$/i;
372                 this.pattern_obj = /(.*\.js)(\?.*\.(mov))$/i;
373                 this.pattern_mp3 = /(.*\.js)(\?.*\.(mp3))$/i;
374                
375                
376                 if (defaultXml === '' || defaultXml === null) {
377                         defaultXml = undefined;
378                 }
379                 // DEFAULT XML DOCUMENT PASSED AS ARGUMENT OR SAMPLE IF NONE PRESENT
380                 switch (typeof defaultXml) {
381                         case 'undefined':
382                                 this.xmlstring = _colbrowser.sampleXml;
383                                 break;
384                         case 'string':
385                                 this.xmlstring = defaultXml;
386                                 break;
387                         case 'object':
388                                 this.xmlstring = XML.parse(defaultXml);
389                                 break;
390                         default:
391                                 this.xmlstring = _colbrowser.sampleXml;
392                                 break;
393                 }
394                
395                 // Privileged methods (can access private and be called from public/outside); can
396                 //      be deleted or replaced but not alter or get its "secrets" (can get the declaration too, though not a instance variable inside)
397                 /* Works but not necessary (see setColbrowserStyle private method below)
398                 var that = this; // "that" actually doesn't seem that it needs to be referenced inside here for some reason'
399                 this.setColbrowserStyle = function (colbrows){
400                         // SET COLUMN BROWSER'S INITIAL STYLES
401                         colbrows.style.height = this.colbrows_style_height;
402                         colbrows.style.width = this.colbrows_style_width;
403                         colbrows.style.top = this.colbrows_style_top;
404                         colbrows.style.left = this.colbrows_style_left;
405                         colbrows.style.position = this.colbrows_style_position;
406                         colbrows.style.overflow = this.colbrows_style_overflow;
407                 }
408                 */
409                 this.origxmlstring = this.xmlstring; // Store if want to use for something (but doesn't resolve XInclude)
410                 // InfoStrategy Interface defined outside, but before instantiation here
411                 
412                if (brettz9.JSClassUtil.classHasInterface(UserMetaInfoStrat, 'InfoStrategy')) { // If user submits valid interface, instantiate
413                        this.InfoStrategy = new UserMetaInfoStrat(this.xmlstring);
414                }
415                else {
416                         this.InfoStrategy = new _MetaInfoStrategy(this.xmlstring); // If user doesn't submit valid interface, create sample'
417                 }
418                 if (brettz9.JSClassUtil.classHasInterface(ColDisplayStrat, 'ColDisplayStrategy')) {
419                         this.colDisplayStrategy = new ColDisplayStrat();
420                 }
421                 else {
422                         this.colDisplayStrategy = new _ColDisplayStrategy();
423                 }
424                                
425         }
426
427         // Instance methods (changeable across instances)
428
429         // To become public instance method
430         _colbrowser.prototype.init = function (e,
431                               /* boolean; set to true if want to allow an earlier colBrowser to pick up the focus*/ noColViewHandlers) { // Can refer to onload event object
432                 // Fix: Could have these specified via arguments
433                 
434                 var that = this; // If want private methods without access to instance methods/members, put those methods above this line
435                 
436                 function _setColbrowserStyle (colbrows) { // add private instance-aware function here just for compartmentalization; better than as privileged method since not needed publicly, though could just remove from function
437                         colbrows.style.height = that.colbrows_style_height;
438                         colbrows.style.width = that.colbrows_style_width;
439                         colbrows.style.top = that.colbrows_style_top;
440                         colbrows.style.left = that.colbrows_style_left;
441                         colbrows.style.position = that.colbrows_style_position;
442                         colbrows.style.overflow = that.colbrows_style_overflow;
443                 }
444
445                 // STORE INITIAL OBJECT VALUES (POSSIBLY ALTERED BY USER) TO BE ABLE TO RESET BACK TO LATER
446                 this.select_style_left_orig = this.select_style_left;
447                 this.idCounter_orig = this.idCounter;
448
449                 // RESOLVE XINCLUDES
450                 // Fix: Make this optional?
451                 this.xmlstring = XML.serialize(brettz9.DOM.resolveXIncludes(XML.parse(this.xmlstring)));
452                
453                 this.URLtoXMLDoc = {'show^embed^doc^this.xmlstring^' : XML.parse(this.xmlstring)};
454                 // RESET THE CACHE WHEN THE USER CLICKS ON THE "Hide Hidden Files?" CHECKBOX, SO NEW VIEW WILL BE A
455                 //   VAILABLE AFTER LEAVING CURRENT VIEW
456                 function resetXMLCache () {
457                     that.URLtoXMLDoc = {'show^embed^doc^this.xmlstring^' : XML.parse(that.xmlstring)};
458                 }
459                 brettz9.DOM.addEvent('colbrowser_hide_hidden_files', 'click', resetXMLCache, false);
460
461                 // INCREMENT TOTAL COLBROWSER COUNT (E.G., FOR TABINDEX)
462                 _colbrowser.colbrowsCount++;
463
464                 // SET COLUMN BROWSER STYLES
465                 // Fix: could give a means to alter these styles and register the changes after initialization? (probably not useful though)
466                 var colbrows = document.getElementById(this.colbrows_prfx+this.colbrows_suffix);
467                 //this.setColbrowserStyle(colbrows); // Call privileged method (method content could be added here, but cleaner this way)
468                 _setColbrowserStyle(colbrows); // Call private method but which has access to 'this' instance variables
469                 
470                 // "GO TO COLUMN VIEW" BUTTON
471                 var colbrows_colview = document.getElementById('colbrows_colview');
472                 // Note that if multiple column browsers are used, a new button with the right id must be added to the HTML (Fix: do this dynamically?)
473                 function _goToColumnView (e) { // Use 'e'?'
474                         var count = 1;
475                         var sel = document.getElementById(that.colbrows_prfx+count); // Go to first column
476                         
477                         while(document.getElementById(that.colbrows_prfx+ (++count))) {
478                                 sel = document.getElementById(that.colbrows_prfx+(count-1));
479                         }
480                        
481                         if (sel.selectedIndex === -1 ||
482                                         (_colbrowser.MOZ &&
483                                                 sel.selectedIndex === (sel.options.length-1)
484                                         )
485                                 ) { // If none already selected or in Firefox and last (hidden) item selected, set to the preferred item (first by default)
486                                 sel.selectedIndex = that.select_start_selindex;
487                         }
488                         sel.focus();
489                 }
490                 if (!noColViewHandlers) {
491                         brettz9.DOM.addEvent(colbrows_colview, 'click', _goToColumnView);
492                         brettz9.DOM.addEvent(colbrows_colview, 'keypress', _goToColumnView);
493                 }
494
495                 // CLICK ANYWHERE TO GET OFF OF A RENAME INPUT BOX
496                 // Allow user to click away from a generated input area without committing changes (by keyboard, one can click to undo(s) and then hit return)
497                 function _clickOffInputBox (e) { // event doesn't matter, so could drop 'e''
498                         var inputarea = Tooltip.tooltip.tooltip;
499                         if (inputarea.style.visibility === 'visible') {
500                                 if (inputarea.parentNode) {
501                                         inputarea.parentNode.removeChild(inputarea); // Remove the input box
502                                 }
503                         }
504 //                        _colbrowser.currFocus.focus(); // Doesn't seem to help in IE // Causes problems with textbox
505                 }
506                 brettz9.DOM.addEvent(document, 'click', _clickOffInputBox);
507
508
509                 // UPDATE COLUMN BROWSER WITH CHANGED XML TEXTBOX CONTENTS
510                 function _updateColbrowserFromXMLTextBox (e) {
511                         var targ = _colbrowser.MSIE ? e.srcElement : e.target;
512                         that.xmlstring = targ.value;
513                         while (colbrows.childNodes.length > 0) {
514                                 colbrows.removeChild(colbrows.firstChild);
515                         }
516                         that.select_style_left = that.select_style_left_orig;
517                         that.idCounter = that.idCounter_orig;
518                         that.URLtoXMLDoc = {'show^embed^doc^this.xmlstring^' : XML.parse(that.xmlstring)};
519                         that._buildCol(colbrows, false, 'show^embed^doc^this.xmlstring^', targ.value); // Start with the root
520                         colbrows.firstChild.selectedIndex = 0; // this.select_start_selindex; // Since user is changing the contents, we can't assume the user wants the starting value (it might not even have that column)'
521                         colbrows.firstChild.focus(); // If user is changing, we can assume they want focus
522                 }
523                 brettz9.DOM.addEvent(document.getElementById('colbrows_xmldocbox'),
524                                                                 'change', _updateColbrowserFromXMLTextBox);
525
526
527                 // FIX: Make these variable, so multiple newitems could be created depending on the column browser (do via static incrementor?)
528                 // CREATE NEW ELEMENT
529                 // Options for elements to create could ideally be available as dynamically-created ones based on the parsing of a DTD/schema
530                 function _newItem (e) {
531                         // Fix: !!!! creating new element shouldn't add hierarchy within it!
532                         // other todos: port newItem and deleteItem? for key command;
533                         // button for alter name;
534                         // reserialize and post
535
536                         var optval;
537                         var targ = _colbrowser.MSIE ? e.srcElement : e.target;
538                         switch (targ.nodeName.toLowerCase()) {
539                                 case 'option':
540                                         optval = targ.value; // 'dir';
541                                         break;
542                                 case 'input': // i.e., if a button
543                                         var newitem = document.getElementById('newitem');
544                                         optval = newitem.options[newitem.selectedIndex].value; // 'dir';
545                                         break;
546                                 default :
547                                         throw('Unexpected element');
548                         }
549
550                         // Start whole new document if nothing left since deleted everything (but not more than one root!)
551                         if (!document.getElementById(_colbrowser.currFocus.id)) { // Element doesn't even exist
552                                 that.xmlstring = '<'+optval+'></'+optval+'>';
553                                 try {
554                                         that._buildCol(colbrows, false, 'show^embed^doc^this.xmlstring^');                                       
555                                 } catch (e) {
556                                         alert(e.message?e.message:e);
557                                 }
558                         }
559                         if (_colbrowser.currFocus.id.match(/_1$/)) { // On first element
560                                 return; // Can't have more than one root
561                         }
562
563                         var option = _colbrowser.currFocus.options[_colbrowser.currFocus.selectedIndex];
564                         var option2 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'option');
565
566
567 // Will need to submit and perform any action (e.g., create a file, update remote/local XML tree in file) and
568 //   refresh in cache and view (e.g., alphabetically if like directories, or as placed if regular XML),
569 //   (with any filter/sort/search?--use XPath/XSL/XQuery for these?)
570 // Need to make action dependent on XML file--root or element namespace of parent or of
571 //   new element????; parent probably better, since child can still have its own behaviors for its
572 //   children e.g., have namespace for our dir. files
573 // that.URLtoXMLDoc[fileXLinkAndXPath];
574  
575                           // _colbrowser.XPathPlus = /^(show\^([^\^]*)\^doc\^([^)#\^]*)(#xpath1\((.*)\))?\^)(.*)$/;
576                           var pattern = _colbrowser.XPathPlus;
577                           var doc = option.value.match(pattern);
578                           if (doc) {
579                                   var docFileXLink = doc[1];
580                                   var fileXLinkAndXPath = doc[3]+(doc[4]?doc[4]:''); // Caching key
581                                   var currentXPath = doc[6]; // XPath to use for changing stored value
582                                   var fileXLink = doc[3];
583                                   // var showVal = doc[2];
584                                   var newXPath = doc[5];
585                          }         
586                          var xml, key;
587                          if (doc && fileXLink) {
588                                 if (fileXLink.match(/^this\./)) { // If it is a string stored locally
589                                         key = docFileXLink;
590                                         xml = that.URLtoXMLDoc[key];
591                                 }
592                                 else if (URLtoXMLDoc[fileXLinkAndXPath]) {
593                                         key = fileXLinkAndXPath;
594                                         xml = that.URLtoXMLDoc[fileXLinkAndXPath]; // Grab XML in 'cache'/memory
595                                 }
596                         }
597                        
598                         var node = XML.getNode(xml, currentXPath, null, xml);
599
600                         var newEl = brettz9.DOM.createElementNSwrapper('', 'dir', xml);
601                         node.parentNode.insertBefore(newEl, node.nextSibling);
602 //                        alert(XML.serialize(that.URLtoXMLDoc[key]));
603 //                        that.URLtoXMLDoc[key] = xml;
604 //                        alert(key);
605
606
607                         if (optval === '') {return;}
608                         option2.innerHTML = optval;
609                         option2.value = '(null)';
610
611 //                      option2.value = '';
612
613                         // If we are working with a non-sequence-alterable XML file (like directory listing), this should just append to end in view, or append to the right alphabetical position
614                         option.parentNode.insertBefore(option2, option.nextSibling); //i.e., insertAfter
615                         
616
617                         if (option.value === '(null)') {// Now remote the text node if it was one (since we only show last text node)...
618                                 option.parentNode.removeChild(option);
619                         }
620                         // that.xmlstring = '<'+optval+'></'+optval+'>';
621
622                         //that._buildCol(colbrows, false, 'show^embed^doc^this.xmlstring^');
623                         //_ctrlShiftN(el, keyid, e);
624                 }
625
626                 var newitem = document.getElementById('newitem');
627                 for (var i=0; i < newitem.options.length; i++) {
628                         brettz9.DOM.addCommandEvent(newitem.options[i], _newItem);
629                 }
630                 var createitem = document.getElementById('createitem');
631                 brettz9.DOM.addCommandEvent(createitem, _newItem);
632
633                 // DELETE ELEMENT
634                 function _deleteItem (e) { // Use 'e'?'
635                         // Fix: allow deleting of text nodes
636                         var option = _colbrowser.currFocus.options[_colbrowser.currFocus.selectedIndex];
637
638                         option.parentNode.removeChild(option);
639 //                      alert(_colbrowser.currFocus.options.length);
640
641                         var currid = _colbrowser.currFocus.id.replace(new RegExp(that.colbrows_prfx), '');
642                         if (_colbrowser.currFocus.options.length === 1) {
643                                 currid--; // If nothing left, make sure to delete the current column too
644                         }
645                         var origid = currid;
646                         var nextid;
647                         var nextcol = document.getElementById(that.colbrows_prfx + (++currid));
648                         var selwidth = that.select_style_width;
649
650                         while (nextcol) {
651                                 nextcol.parentNode.removeChild(nextcol);
652                                 nextcol = document.getElementById(that.colbrows_prfx + (++currid));
653                                 that.select_style_left -= parseInt(selwidth.substr(0, selwidth.length-2), 10); // Don't grab pixels from width;
654                         }
655                         that.idCounter = origid;
656                         var currcol = document.getElementById(that.colbrows_prfx + (origid));
657
658                         if (currcol) { // currcol might not be left if deleting everything
659                                 currcol.focus();
660                                 _colbrowser.currFocus = currcol;
661                         }
662                 }
663                 var deleteitem = document.getElementById('deleteitem');
664                 brettz9.DOM.addCommandEvent(deleteitem, _deleteItem);
665
666                
667                 // ADD DEFAULT XML DOCUMENT TO TEXTBOX
668                 document.getElementById('colbrows_xmldocbox').value = this.xmlstring;
669                
670                 // BUILD METADATA FOR THE FIRST TIME
671                 // this.InfoStrategy.populateDocInfo(XML.parse(this.xmlstring));
672                 
673                 this.InfoStrategy.populateAllInfo('show^embed^doc^this.xmlstring^', this.URLtoXMLDoc);
674
675                 // BUILD COLUMN WITH INITIAL XML DOCUMENT
676                 this._buildCol(colbrows, false, 'show^embed^doc^this.xmlstring^'); // Start with the root
677
678                 // SET INDEX AT BEGINNING
679                 // Fix: Might find some way to start beyond the first column
680                 colbrows.firstChild.selectedIndex = this.select_start_selindex;
681                
682                 // SET FOCUS ON LATEST COLUMN WITH VIEW HANDLERS (ASSUMED TO BE ONE TO SHOW -- if allowing other column views, this (and the above setting of selectedIndex) might not be desirable)
683                 if (!noColViewHandlers) { // DON'T FOCUS IF USER HAS OTHER COLBROWSERS IN THE WINDOW
684                         colbrows.firstChild.focus();
685                 }
686         };
687
688         // Wanted these as private (instance methods) but since wanted to access from both private and public, this seemed impossible;
689         //      however, I could redo buildcol (after including makeOptions within it too) to be within init() and a different one within _selectClick (they might even ideally be slightly different anyways)
690         // Could also do as privileged method inside _colbrowser constructor, but adds memory for each instance apparently
691         _colbrowser.prototype._buildCol = function (colbrows, col2rmv, fullXPathText, xml) { // XPath, XML/DOM/JSON
692                 var that = this;
693
694                 // BUILD REFERENCES FOR XML FILE (OUR OWN XML OR XLINK)
695                 var pattern = _colbrowser.XPathPlus; // Expect doc^^ for file delimiting (or local this.xmlstring if using a variable)
696                 var doc = fullXPathText.match(pattern);
697                 if (doc) {
698                         // var showVal = doc[2];
699                         var fileXLinkAndXPath = doc[3]+(doc[4]?doc[4]:'');
700                         var currentXPath = doc[6];
701                         var newXPath = doc[5];
702                         var fileXLink = doc[3];
703                         var jsmatch = fileXLink.match(/(.*\.js)(\?.*)?$/);
704                         if (jsmatch) {
705                                 var jslink = jsmatch[0];
706                                 var parsedfile = brettz9.URI.parse(jsmatch[2]).key.f;
707                         }
708                 }
709                 var hideHiddenFiles = false;
710                 if (document.getElementById('colbrowser_hide_hidden_files').checked) {
711                     hideHiddenFiles = true;
712                 }
713                
714                 // PREPARATORY HANDLER FOR STORING XML FROM XLINK  (FUNCTIONS TO GET DATA ARE BELOW)
715                 // This function can't be within the else block below (the only place it would be needed)
716                 // Depends on doc/fullXPathText (specifically newXPath, fileXLinkAndXPath, jsmatch) just above
717                 function _storeXMLPreparer (xmldoc) { // This must be here to collect newXPath, fileXLinkAndXPath from above (and can't be declared in a block below)
718                         that._storeXML(xmldoc, newXPath, fileXLinkAndXPath, jsmatch);
719                 }
720                
721                 // SET OR GRAB CACHING OF DATA FOR OUR OWN XML, THE USER'S XML, OR XLINKED/REMOTE XML
722                 // Fix: If supporting non-embed (new/replace), have to add that behavior here (not only in processXLinkShow() coming from processXLinkActuateOnLoad())
723                 
724                 if (doc && fileXLinkAndXPath) {
725                         if (this.URLtoXMLDoc[fileXLinkAndXPath]) {
726                                 xml = this.URLtoXMLDoc[fileXLinkAndXPath]; // Grab XML in 'cache'/memory                             
727                         }
728                         else if (fileXLink.match(/^this\./)) { // If it is a string stored locally
729                                 //xml = eval(fileXLink); // Uncomment if want flexibility to add other strings (but dangerous)
730                                 xml = this.xmlstring;
731                                 xml = XML.parse(xml);
732                                 this.URLtoXMLDoc[fileXLinkAndXPath] = xml;
733                         }
734                         else {
735                                 if (_colbrowser.MOZ) {
736                                         try {
737                                                 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserRead'); // Necessary with file:///-located files trying to reach external sites
738                                         }
739                                         catch (e) {
740                                                 alert("Permission UniversalBrowserRead denied. You must install this file and its attached scripts "+
741                                                         "on your local drive and find 'file:///' references in the code and change to lead to XML "+
742                                                         "files you wish to try out; for Firefox, you could type about:config in the URL window and set "+
743                                                         "signed.applets.codebase_principal_support to true in Firefox or if in Explorer, go to Tools -> "+
744                                                         "Options -> Security -> Custom Level -> ActiveX Controls and Plugins ->  'Initialize and script "+
745                                                         "ActiveX control not marked as safe.' Miscellaneous -> 'Access data sources across domains' "+
746                                                         "should also be marked as 'prompt' or 'enable'. Note that this may be less secure for your system!");
747                                         }
748                                 }
749                                 var fso, file, all;
750                                 if (jsmatch) { // Need to grab JS as text and eval() for XML
751                                         if (fileXLink.match(/\.\w+$/)) {return;}
752                                         var fileXLinkFileURL;
753                                         if (_colbrowser.MSIE && fileXLink.indexOf('file://') === 0) {
754                                                 fso = new ActiveXObject('Scripting.FileSystemObject');
755                                                 fileXLink = jsmatch[1];
756                                                 fileXLinkFileURL = fileXLink.replace(/file\:\/\/\//g, '')
757                                                 if (_colbrowser.OS === 'Windows') {
758                                                         fileXLinkFileURL = fileXLinkFileURL.replace(/\//g, '\\');
759                                                 }
760                                                 file = fso.OpenTextFile(fileXLinkFileURL, 1); // 1 is reading, 2 is writing, 8 is appending  per http://msdn.microsoft.com/en-us/library/314cz14s(VS.85).aspx
761                                                                                                                         // Third argument can be -2 sys default, -1 Unicode, 0 ASCII
762                                                 all = file.ReadAll();
763                                                 file.Close();
764                                                 eval(all);
765                                                 _storeXMLPreparer(XML.parse(brettz9.XML.XMLOutput)); // Explorer gave error with empty DOCTYPE parsed this way
766                                         }
767                                         else {
768                                                 HTTP.getText(fileXLink, _storeXMLPreparer, false); // Synchronous call so that the XML doc is available in rest of function
769                                         }
770                                 }
771                                 else if (_colbrowser.MSIE && fileXLink.indexOf('file://') === 0) {
772                                         fso = new ActiveXObject('Scripting.FileSystemObject');
773                                         fileXLinkFileURL = fileXLink.replace(/file\:\/\/\//g, '')
774                                         if (_colbrowser.OS === 'Windows') {
775                                                 fileXLinkFileURL = fileXLinkFileURL.replace(/\//g, '\\');
776                                         }
777                                         file = fso.OpenTextFile(fileXLinkFileURL, 1 ); // 1 is reading, 2 is writing, 8 is appending  per http://msdn.microsoft.com/en-us/library/314cz14s(VS.85).aspx
778                                                                                                                 // Third argument can be -2 sys default, -1 Unicode, 0 ASCII
779                                         all = file.ReadAll();
780                                         file.Close();
781                                         _storeXMLPreparer(XML.parse(all)); // Explorer gave error with empty DOCTYPE parsed this way
782                                 }
783                                 else {
784                                         HTTP.getXML(fileXLink, _storeXMLPreparer, false); // Synchronous call so that the XML doc is available in rest of function
785                                 }
786
787                                 xml = this.URLtoXMLDoc[fileXLinkAndXPath];
788                                 // currentXPath = ''; // Deprecated comment
789                         }
790
791                 }
792                 // STORE THE USER'S SUBMITTED XML
793                 else if (typeof xml === 'string') { // Don't need to parse if it is already a DOM Document/Element
794                 //if (xml instanceof HTMLDocument || xml instanceof XMLDocument) { // how to test for element?
795                         xml = XML.parse(xml);
796                         this.URLtoXMLDoc['show^embed^doc^this.xmlstring^'] = xml;
797                 }
798
799                 // PREPARATORY HANDLER FOR RIGHT ARROW HANDLER (REPEATED HERE SO METHODS COULD BE BORROWED
800                 // Depends on that and xml (just above) (must be kept here
801                 function _rightHandle (el, keyid, e) {
802                         that._rightHandle(el, keyid, e, xml);
803                 }
804                
805                 // All of the following only depend on that
806                 // Could therefore move these to the constructor and make as privileged methods, but takes up memory
807                 //   and needs this call; but the advantage would be overriding this method would be easier (and overriding
808                 //   the constructor more involved as  this one is now)
809                 function _ctrlShiftN (el, keyid, e) {
810                         that._ctrlShiftN(el, keyid, e);
811                 }
812                 function _deleteHandle (el, keyid, e) {
813                         that._deleteHandle(el, keyid, e);
814                 }
815                 function _endHandle (el, keyid, e) {
816                         that._endHandle(el, keyid, e);
817                 }
818                 function _homeHandle (el, keyid, e) {
819                         that._homeHandle(el, keyid, e);
820                 }
821                 function _pageDownHandle (el, keyid, e) {
822                         that._pageDownHandle(el, keyid, e);
823                 }
824                 function _pageUpHandle (el, keyid, e) {
825                         that._pageUpHandle(el, keyid, e);
826                 }
827                 function _returnHandle (el, keyid, e) {
828                         that._returnHandle(el, keyid, e);
829                 }
830                 function _downHandle (el, keyid, e) {
831                         that._downHandle(el, keyid, e);
832                 }
833                 function _upHandle (el, keyid, e) {
834                         that._upHandle(el, keyid, e);
835                 }
836                 function _leftHandle (el, keyid, e) {
837                         that._leftHandle(el, keyid, e);
838                 }
839                
840                 var selwidth = this.select_style_width;
841                
842                 // REMOVE OLD COLUMNS (IF GOING LEFTWARD OR VERTICALLY TO A NEW ONE)
843                 if (col2rmv) {
844                         var num0 = parseInt(col2rmv.id.substr(this.colbrows_prfx.length), 10);
845                         ++num0;
846                         var nextcolumn = document.getElementById(this.colbrows_prfx+num0);
847                         while (nextcolumn) {
848                                 // Don't just change visibility, since the user might choose a different column next time
849                                 nextcolumn.parentNode.removeChild(nextcolumn);
850                                 // Decrement the id and the left setting so next item will be placed correctly:
851                                 --this.idCounter;
852                                 this.select_style_left -= parseInt(selwidth.substr(0, selwidth.length-2), 10); // Don't grab pixels from width;
853                                 nextcolumn = document.getElementById(this.colbrows_prfx + (++num0));
854                         }
855                 }
856
857 // Deprecated comment
858 // (if it is actually necessary, try uncommenting just the first line instead of the text afterwards)               
859 //                this.InfoStrategy.populateMetaInfo(xml);
860                 /*
861                 // Could use a separate textbox for this "whole document" XML serialization
862                 var colbrows_textchild = document.getElementById('colbrows_textchild');
863
864                 if (colbrows_textchild.innerHTML === '') { // This would otherwise overwrite the existing data when the user should be seeing just that element's content
865                         colbrows_textchild.innerHTML = '<textarea rows="5" cols="40">'+brettz9.XML.escapeString(XML.serialize(xml))+'<\/textarea>';
866                 }
867                 */
868
869                
870                 /*
871                  * Deprecated comment : block seems to have no effect
872                 var startNode;
873                 if (currentXPath === undefined) {
874                         alert('a');
875                         if (xml.documentElement) { // Might want firstChild instead if allowing comments, proc. inst., etc.
876                                 alert('b');
877                                 startNode = xml.documentElement;
878                                 currentXPath = '//';
879                         }
880                 }
881                 else { // Perform XPath to find starting node (should always be a single node or make a constructed one if not????)
882                         // startNode = ;
883                 }
884                 */
885
886                 // CONFIGURE SELECT COLUMN'S STYLES AND DISPLAY PROPERTIES
887                 var selectCol = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'select');
888                 selectCol.style.width = selwidth;
889                 selectCol.style.top = this.select_style_top;
890                 selectCol.style.left = this.select_style_left+'px';
891                 this.select_style_left += parseInt(selwidth.substr(0, selwidth.length-2), 10); // Don't grab pixels from width;
892
893                 selectCol.setAttribute('multiple', 'multiple'); // Fix: May wish to allow moving of items (could make this variable)
894                 if (this.select_size) { // Size attribute shouldn't be 'undefined' if none present
895                         selectCol.setAttribute('size', this.select_size);
896                 }
897                 selectCol.setAttribute(_colbrowser.CLASSATT, this.css_prfx+'col'); // Make the column a visible one
898
899                 // INCREMENT COLUMN ID
900                 // Does this need to be reset at any point, such as if going backwards?
901                 // Name of this id should be unique per instance of this object (not only numerically as that could cause one to lead into the other)
902                                 
903                 selectCol.setAttribute('id', this.colbrows_prfx + (++this.idCounter)); // Give an id for referencing
904
905                 // RECORD FOCUS IF THE FIRST COLUMN (FOR THE SAKE OF HAVING SOMETHING TO DELETE)
906                 // Don't set this for subsequent selects
907                 if (this.idCounter === 1) {
908                         _colbrowser.currFocus = selectCol; // Enable to make sure there is something to delete if user tries
909                                                                                             //   to delete root; otherwise, don't need to increment
910                 }
911
912                 // SET TABINDEX FOR COLUMN
913                 if (this.tabIndex === true) { // Allow auto-increment (default)  (if set to false, will not have any tabindex)
914                         // It is ok not to increment here, since that would interfere with chances to increment for a new column browser being added;
915                         //   It is also fine since tabindex's with the same value are not invalid and follow in document order (allows user to tab to next column)
916                         selectCol.setAttribute('tabindex', _colbrowser.colbrowsCount); // To get this to be even more accessible, one could set a document event handler to detect a keystroke and then highlight this box (then remove the handler)
917                         this.tabIndex = false; // Fix: This doesn't work to stop tabbing and there should be a tab handler anyways'
918                 }
919                 else if (this.tabIndex) { // Allow setting numeric
920                         selectCol.setAttribute('tabindex', this.tabIndex); // Fix: see fix just above
921                         this.tabIndex = false;
922                 }
923                
924
925                 // ATTACH HANDLERS
926                 // Map key to handler
927                 var bindings = {ctrl_shift_n:_ctrlShiftN, "delete":_deleteHandle, end:_endHandle,
928                                                 home:_homeHandle, pagedown:_pageDownHandle,
929                                                 pageup:_pageUpHandle, returnname:_returnHandle, down:_downHandle,
930                                                 up:_upHandle, left:_leftHandle, right:_rightHandle};
931                 var keymap = new Keymap(bindings);
932                 keymap.install(selectCol); // Attach to document (or input box, textarea apparently)
933
934                 // BUILD OPTIONS
935                 selectCol = this._makeOptions(selectCol, xml, currentXPath);
936                 if (!selectCol) {
937 //                        var xlinkEl = col2rmv.options[col2rmv.selectedIndex];
938 //                        alert(xlinkEl.value);
939 //                        alert(XML.serialize(xlinkEl));
940 //                        var href = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'href');
941 //                        alert(href);
942                         return;
943                 }
944                
945                 // ADD FAKE OPTION IN COLUMN FOR SAKE OF MOZILLA BUG
946                 if (_colbrowser.MOZ) {
947                         // Due to a bug in FF Windows (see https://bugzilla.mozilla.org/show_bug.cgi?id=291082 ),
948                         // preventDefault will not work in a select menu, so we have to recompensate by having the left
949                         // arrow bumped one up (and there must be such an option for it to go to)
950                         var option2 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'option');
951                         option2.setAttribute('style', 'display:none;');
952                         option2.setAttribute('value', 'null');
953                         selectCol.appendChild(option2);
954                 }               
955                
956                 // CLICK AND CHANGE HANDLERS
957                 function _selectClickPreparer (e) {
958                         that._selectClick(e, xml);
959                 }
960                 brettz9.DOM.addEvent(selectCol, 'click', _selectClickPreparer);
961                
962                 function _selectChangePreparer (e) {
963                         that._selectChange(e, xml);
964                 }
965                 brettz9.DOM.addEvent(selectCol, 'change', _selectChangePreparer);
966
967                 // ADD COLUMN TO COLUMN BROWSER
968                 colbrows.appendChild(selectCol);
969 /* Deprecated comment
970                 if (selectCol.options[0].value !== 'null') { // Note that this is different from '(null)'!!!
971                         colbrows.appendChild(selectCol);
972                 }
973                 else {
974                         // Bring the column back down
975                         --this.idCounter;
976                         this.select_style_left -= parseInt(selwidth.substr(0, selwidth.length-2), 10); // Don't grab pixels from width;
977                 }
978 */
979         };
980
981         _colbrowser.prototype._makeOptions = function (select, xml, currentXPath) {
982
983                 var option;               
984                 // GET DATA FOR OPTION AND SET FOR XLINK TYPE (IF NOT JUST STARTING)
985                 if (currentXPath !== '') {
986                         // FIND OPTIONS WHICH DO NOT HAVE XLINKS
987                         var notXlinkPath = currentXPath + '[@*[not((local-name() = "href" or local-name() = "type") and namespace-uri() = "http://www.w3.org/1999/xlink")]]'; // Do separate processing for those with XLink
988                         var notXlinkEls = XML.getNodes(xml, notXlinkPath, null, xml);
989                         var notXlinkEl = notXlinkEls[0];
990                
991                         // SET OPTIONS WHICH HAVE XLINKS (AND IF SO, RETURN)
992                         var xlinkPath = currentXPath + '[@*[(local-name() = "href" or local-name() = "type") and namespace-uri() = "http://www.w3.org/1999/xlink"]]'; // '[@xlink:href]';
993                         var xlinkEls = XML.getNodes(xml, xlinkPath, null, xml);         
994                         var xlinkEl = xlinkEls[0];
995                         //xlinkEl = _colbrowser.MSIE ? xlinkEl : xlinkEl.ownerElement; // Explorer before 8 didn't support ownerElement so changed XPath above'
996                         if (xlinkEl) {
997                                 // GET OPTION ELEMENT UPON WHICH TO ADD DATA
998                                 option = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'option');
999                                 this.a++;
1000                                 // PROCESS XLINK DEPENDING ON TYPE (AND SHOW/ACTUATE)
1001                                 // Before calling show/actuate-related methods, could override depending on user preferences (this is fine with the XLink spec)
1002                                 var xlinkselect = this.processXLinkType(xlinkEl, select, option, xml);
1003                                 if (xlinkselect && xlinkselect.nodeName && xlinkselect.nodeName.toLowerCase() === 'select') {
1004                                         return xlinkselect;
1005                                 }
1006                                 else if (xlinkselect) {
1007                                         return false;
1008                                 }
1009                                 else {
1010                                         alert('Unexpected error 7');
1011                                 }
1012                         }
1013                 }
1014                
1015
1016
1017                 // GET ANY CHILDREN
1018                 var thislevel = XML.getNodes(xml, currentXPath+'/*', null, xml);
1019                 var thisitem = thislevel[0];
1020                 var thisitemTextContent;
1021                
1022 //                alert(thisitem);
1023 //                if (notXlinkEl) {alert(notXlinkEl.childNodes);}
1024                 
1025                 // GET AND SET DATA FOR OPTION IF NO FURTHER ELEMENT CHILDREN AND ADD TO SELECT
1026                 if (!thisitem) {
1027                         // This section might be made optional or commented out if one only wishes to see text content (note that _selectClick tests for '(null)' as created here)
1028                         if (notXlinkEl) {
1029                                 thisitem = notXlinkEl;
1030                         }
1031                         else { // IF OPENS UP TO TEXT
1032                                 if (!currentXPath) {currentXPath = '/*';}
1033                                 thislevel = XML.getNodes(xml, currentXPath, null, xml);
1034                                 thisitem = thislevel[0];
1035                                 // if (!thisitem) {return select;} // DEPRECATED COMMENT
1036                         }
1037                        
1038                         // Might allow an onclick as below? to show metadata...
1039                         option = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'option');
1040                         thisitemTextContent = _colbrowser.MSIE ? thisitem.text : thisitem.textContent;
1041
1042                         option.innerHTML = '('+brettz9.XML.escapeString(thisitemTextContent)+')';
1043                         option.value = '(null)';
1044
1045                         // ADD OPTION TO SELECT COLUMN
1046                         select.appendChild(option);
1047
1048                         return select;
1049                 }
1050
1051                 // ADD OPTION DATA FOR REGULAR NON-XLINK ENTRY WITH CHILDREN
1052                 for (var i = 0; i < thislevel.length; i++) {
1053                         thisitem = thislevel[i];
1054                         option = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'option');
1055                        
1056                         // DISPLAY COLUMN INTERNAL DATA PER USER'S STRATEGY (FOR TEXT AND TOOLTIP)
1057                         this.colDisplayStrategy.addColumnEntryName(option, thisitem);
1058                         this.colDisplayStrategy.addColumnEntryTitle(option, thisitem);
1059                        
1060                         // ADD FILE/XPATH TO OPTION
1061                         var xml_in_URLtoXML = brettz9.PHP.array_search(xml, this.URLtoXMLDoc);
1062                         var docval = xml_in_URLtoXML ? xml_in_URLtoXML : 'this.xmlstring';
1063                         var thisxpath = brettz9.XPath.getXPathForElement(thisitem, xml);
1064                        
1065                         if (docval.match(/^show\^[^\^]*\^doc\^[^^]*\^$/)) { // Just test for doc^this.xmlstring^? // Fix: allow specification of @show (e.g,. show^new/replace/emed^) for this.xmlstring too
1066 //                              option.value = docval+thisxpath;
1067                         }
1068                         else {
1069                                 option.value = 'show^embed^doc^'+docval+'^'+thisxpath; // 'this.xmlstring'
1070                         }
1071
1072                         // ADD OPTION TO SELECT COLUMN
1073                         select.appendChild(option);
1074                 }
1075                 return select;
1076         };
1077         // Fix: Could put each media display routine into its own method so it could be overridden
1078         _colbrowser.prototype.displayMedia = function (xlinkEl, attrs) {
1079
1080                 var href0 = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'href');
1081                
1082                 var imgmatch = href0.match(this.pattern_img);
1083                 var iframematch = href0.match(this.pattern_iframe);
1084                 var textmatch = href0.match(this.pattern_text);
1085                 var objmatch = href0.match(this.pattern_obj);
1086                 var mp3match = href0.match(this.pattern_mp3);
1087                 var parsedfile, addedEl, pfile, param, param2, param3, obj2;
1088                 var holder = document.getElementById('colbrows_img_display');
1089                
1090                 function getTextHandler (text) {
1091                           var textarea = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'textarea');
1092                           textarea.setAttribute('rows', 10);
1093                           textarea.setAttribute('cols', 40);
1094                           while (holder.childNodes.length > 0) {
1095                                   holder.removeChild(holder.firstChild);
1096                           }
1097                           textarea.innerHTML = text;
1098                           holder.appendChild(textarea);
1099                  }
1100                  
1101                  function parsedFileReplace(parsedfile) {
1102                         var unslashed = parsedfile;
1103                         if (_colbrowser.OS === 'Windows') {
1104                                 unslashed = parsedfile.replace(/\\/g, '/');
1105                         }                                               
1106                         return (!parsedfile.match(/^file:\/\/\/?/)?'file://':'')+unslashed;
1107                  }
1108                  
1109                 if (imgmatch) {
1110                         parsedfile = brettz9.URI.parse(imgmatch[2]).key.f;
1111                         addedEl = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'img');
1112                         addedEl.setAttribute('src', parsedFileReplace(parsedfile));
1113                         addedEl.setAttribute('height', 500*7/16);
1114                         addedEl.setAttribute('width', 500*9/16);
1115                 }
1116                 else if (mp3match) {
1117                         parsedfile = brettz9.URI.parse(mp3match[2]).key.f;
1118                         pfile = parsedFileReplace(parsedfile);
1119                         addedEl = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'object');
1120                         addedEl.setAttribute('classid', 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B');
1121                         addedEl.setAttribute('codebase', 'http://www.apple.com/qtactivex/qtplugin.cab');
1122                         addedEl.setAttribute('width', '200');
1123                         addedEl.setAttribute('height', '16');
1124                        
1125                         obj2 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'object');
1126                         obj2.setAttribute('data', pfile);
1127                         obj2.setAttribute('type', 'audio/x-mpeg');
1128                         obj2.setAttribute('width', '200');
1129                         obj2.setAttribute('height', '16');
1130                         // obj2.setAttribute('autoplay', 'false');
1131                         // addedEl.setAttribute('title', '');
1132                         param = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'param');
1133                         param.setAttribute('name', 'autostart');
1134                         param.setAttribute('value', '0');
1135                         param2 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'param');
1136                         param2.setAttribute('name', 'autoplay');
1137                         param2.setAttribute('value', 'false');
1138                         param3 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'param');
1139                         param3.setAttribute('name', 'controller');
1140                         param3.setAttribute('value', 'true');
1141                         var param4 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'param');
1142                         param4.setAttribute('name', 'src');
1143                         param4.setAttribute('value', pfile);
1144                         var param5 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'param');
1145                         param5.setAttribute('name', 'pluginspage');
1146                         param5.setAttribute('value', 'http://www.apple.com/quicktime/download');
1147                        
1148                         addedEl.appendChild(param);
1149                         addedEl.appendChild(param2);
1150                         addedEl.appendChild(param3);
1151                         addedEl.appendChild(param4);
1152                         addedEl.appendChild(param5);
1153                          
1154                 }
1155                 else if (objmatch) {
1156                         parsedfile = brettz9.URI.parse(objmatch[2]).key.f;
1157
1158                         pfile = parsedFileReplace(parsedfile);
1159 //  pfile = 'P5170010.MOV';
1160
1161                         addedEl = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'object');
1162                         addedEl.setAttribute('classid', 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B');
1163                         addedEl.setAttribute('codebase', 'http://www.apple.com/qtactivex/qtplugin.cab');
1164                         addedEl.setAttribute('width', 320);
1165                         addedEl.setAttribute('height', 260);
1166
1167                         param = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'param');
1168                         param.setAttribute('name', 'src');
1169                         param.setAttribute('value', pfile);
1170                         param2 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'param');
1171                         param2.setAttribute('name', 'controller');
1172                         param2.setAttribute('value', 'true');
1173                         param3 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'param');
1174                         param3.setAttribute('name', 'autoplay');
1175                         param3.setAttribute('value', 'true');
1176
1177                         obj2 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'embed');
1178                         obj2.setAttribute('src', pfile);
1179                         obj2.setAttribute('width', 320);
1180                         obj2.setAttribute('height', 260);
1181                         obj2.setAttribute('autoplay', 'true');
1182                         obj2.setAttribute('controller', 'true');
1183                         obj2.setAttribute('pluginspage', 'http://www.apple.com/quicktime/download/');
1184
1185 /*/
1186                         var obj2 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'object');
1187                         obj2.setAttribute('type', 'video/quicktime');
1188                         obj2.setAttribute('data', pfile);
1189                         obj2.setAttribute('width', '320');
1190                         obj2.setAttribute('height', '240');
1191                         obj2.setAttribute(_colbrowser.CLASSATT, 'hiddenObjectForIE');
1192                         var paramB1 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'param');
1193                         var paramB2 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'param');
1194                         paramB1.setAttribute('name', 'controller');
1195                         paramB1.setAttribute('value', 'true');
1196                         paramB2.setAttribute('name', 'autoplay');
1197                         paramB2.setAttribute('value', 'false');
1198 /*                                      var alink = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'a');
1199                         alink.setAttribute('href', pfile);
1200                         var title = attrs.title;
1201                         alink.innerHTML = 'Movie '+title;
1202                         paramB2.appendChild(alink)
1203
1204                         obj2.appendChild(paramB1);
1205                         obj2.appendChild(paramB2);
1206                             */
1207                         addedEl.appendChild(param);
1208                         addedEl.appendChild(param2);
1209                         addedEl.appendChild(param3);
1210                         addedEl.appendChild(obj2);
1211
1212                 }
1213                 else if (iframematch) {
1214                         parsedfile = brettz9.URI.parse(iframematch[2]).key.f;
1215                         addedEl = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'iframe');
1216                         addedEl.setAttribute('src', parsedFileReplace(parsedfile));
1217                         addedEl.setAttribute('height', 600*7/16);
1218                         addedEl.setAttribute('width', 600*9/16);
1219                 }
1220                 else if (textmatch) {
1221                         parsedfile = brettz9.URI.parse(textmatch[2]).key.f;
1222                         if (_colbrowser.MOZ) {
1223                                 try {
1224                                         netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect UniversalBrowserRead'); // Necessary with file:///-located files trying to reach external sites
1225                                 }
1226                                 catch (e) {
1227                                         alert("Permission UniversalBrowserRead denied. You must install this file and its attached scripts "+
1228                                                 "on your local drive and find 'file:///' references in the code and change to lead to XML "+
1229                                                 "files you wish to try out; for Firefox, you could type about:config in the URL window and set "+
1230                                                 "signed.applets.codebase_principal_support to true in Firefox or if in Explorer, go to Tools -> "+
1231                                                 "Options -> Security -> Custom Level -> ActiveX Controls and Plugins ->  'Initialize and script "+
1232                                                 "ActiveX control not marked as safe.' Miscellaneous -> 'Access data sources across domains' "+
1233                                                 "should also be marked as 'prompt' or 'enable'. Note that this may be less secure for your system!");
1234                                 }
1235                         }
1236                        
1237                  
1238                        
1239                         var gettextfile = parsedFileReplace(parsedfile);
1240                         if (_colbrowser.MSIE) {
1241                                 try {
1242                                         var fso = new ActiveXObject('Scripting.FileSystemObject');
1243                                         var file = fso.OpenTextFile(parsedfile, 1 ); // 1 is reading, 2 is writing, 8 is appending  per http://msdn.microsoft.com/en-us/library/314cz14s(VS.85).aspx
1244                                                                                                                 // Third argument can be -2 sys default, -1 Unicode, 0 ASCII
1245                                                                                                                 // had gettextfile.replace(/file\:\/\/\/?/g, '').replace(/\//g, '\\')
1246                                         var all = file.ReadAll();
1247                                         file.Close();
1248                                         getTextHandler(all);
1249                                 }
1250                                 catch (e) { // Need a catch to ignore some errors
1251                                         
1252                                 }
1253                         }
1254                         else {
1255                                 HTTP.getText(gettextfile, getTextHandler, false); // Synchronous call so that text is not overwritten accidentally by moving
1256                         }
1257                 }
1258                 if (addedEl) { // As in the (Ajax) routine to get text data to display,  will not return a holder but will return it in its own callback
1259                         while (holder.childNodes.length > 0) { // This is also triggered in selectChange() (necessary here too)
1260                                 holder.removeChild(holder.firstChild);
1261                         }
1262                         holder.appendChild(addedEl);
1263                 }
1264         };
1265        
1266         _colbrowser.prototype.getXLinkAttributes = function (xlinkEl) {
1267                 // GET XLINK ATTRIBUTES
1268                 // See http://www.w3.org/TR/xlink11/#xlinkattusagepat
1269                 var attrs = {};
1270
1271                 // simple or locator
1272                 var href = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'href');
1273                 attrs.href = href ? href : '';
1274
1275                 // All have a type unless there is an 'href' (only for simple type)
1276                 //   The XPath leading to this xlinkEl should ensure that the element has an 'href'', but we'll check anyways
1277                 // XLink 1.1 allows type to be unspecified (default type of 'simple')
1278                 var type = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'type');
1279                 if (!type && !href) {
1280                         alert('The XLink element submitted to processXLinkType() must have a @type or an @href attribute.');
1281                         return false;
1282                 }
1283                 attrs.type = type = type ? type : 'simple'; // Now we can overwrite the type since original tested just above
1284                 if (href && type !== 'simple' && type !== 'locator') {
1285                         alert('You cannot have an @href attribute on any XLink besides a simple or locator type one.');
1286                         return false;
1287                 }
1288                
1289
1290                 // The conditional checking below is to avoid the namespace wrapper which could be expensive in
1291                 //    needing to traverse all the way up a DOM tree to find a "namespace" in the case of
1292                 //    non-namespace-aware DOM processors (Explorer); also has the side-benefit of ensuring that
1293                 //    a method doesn't try to use an attribute not allowed in that context
1294                 // i.e., The type it is not a type 'title''
1295                 if (type === 'simple' || type === 'extended' || type === 'locator' || type === 'resource' || type === 'arc') {
1296                         var title = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'title');
1297                         attrs.title = title ? title : '';
1298                         if (type !== 'arc') {
1299                                 // simple, extended, locator, resource
1300                                 var role = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'role');
1301                                 attrs.role = role ? role : '';
1302                         }
1303                         if (type === 'simple' || type === 'arc') {
1304                                 var actuate = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'actuate');
1305                                 attrs.actuate = actuate ? actuate : '';
1306                                 var show = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'show');
1307                                 attrs.show = show ? show : '';
1308                                 var arcrole = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'arcrole');
1309                                 attrs.arcrole = arcrole ? arcrole : '';
1310                                 if (type === 'arc') {
1311                                         var from = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'from');
1312                                         attrs.from = from ? from : '';
1313                                         var to = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'to');
1314                                         attrs.to = to ? to : '';
1315                                 }
1316                         }
1317                         else if (type === 'locator' || type === 'resource') {
1318                                 var label = brettz9.DOM.getAttributeNSWrapper(xlinkEl, _colbrowser.XLINKNS, 'label');
1319                                 attrs.label = label ? label : '';
1320                         }
1321                 }
1322                 return attrs;
1323         };
1324         _colbrowser.prototype.processXLinkType = function (xlinkEl, select, option, xml) {
1325                 var attrs = this.getXLinkAttributes(xlinkEl);
1326                 var type = attrs.type;
1327                 // Will always be a type here
1328                 switch (type) {
1329                         // http://www.w3.org/TR/xlink11/#xlinkattusagepat provides allowable attrs as commented below
1330                         case 'simple': // Default set to simple if none present per XLink 1.1
1331                                      // Allowable other atts:  href, role, arcrole, title, show, actuate (note, all including href! are not required)
1332                                 return this.processXLinkTypeSimple(xlinkEl, attrs, select, option, xml);
1333                                 break;
1334                         case 'arc': // Allowable other atts:  arcrole, title, show, actuate, from, to
1335                                                 // @from and @to are defined here as they only pertain to 'arc'
1336                                 return this.processXLinkTypeArc(xlinkEl, attrs, select, option, xml);
1337                                 // break;
1338                         case 'extended': // Allowable other atts:  role and title
1339                                 // break;
1340                         case 'title': // Allowable other atts:  NONE
1341                                 // Fix: While using the DOM to import nodes seemed to add the nodes per the "view selected source", only innerHTML seems to actually allow styling, etc. inside of the option element when added in this way
1342 //                                var toappend = brettz9.DOM.importNode(xlinkEl, true, document); // As title type should have no other attributes (including 'title'),
1343                                                                                       //    the element's contents should be used
1344                                 var optionhtml = '';
1345                                 for (var i=0; i < xlinkEl.childNodes.length; i++) {
1346                                         optionhtml += XML.serialize(xlinkEl.childNodes.item(i));
1347                                 }
1348                                if (_colbrowser.MSIE) { // Inclusion of certain tags (or all?) doesn't work in IE'
1349                                        optionhtml = optionhtml.replace(/\<[^>]*\>/g, '');
1350                                }
1351                                 // Can put tables, buttons, checkboxes, etc. (but not active, though menus inside menus work!)
1352                                 option.innerHTML = optionhtml;
1353                                 option.value = '(null)';
1354                                
1355                                 // ADD OPTION TO SELECT COLUMN
1356                                 select.appendChild(option);
1357 //                                var opt2 = option.cloneNode(true);
1358 //                                select.appendChild(opt2);
1359
1360                                return select;
1361                         case 'resource': // Allowable other atts:  role, title, label
1362                                 // break;
1363                         case 'locator': // Allowable other atts:  href (REQUIRED), role, title, label
1364                                 // Note: need to also add 'arc' support even though there is a method for it above (see processXLinkActuateOnRequest())
1365                                 alert('The '+type+' XLink link type is not currently supported but will be treated as a simple link');
1366                                 break;
1367                         default:
1368                                 alert('Invalid XLink type value');
1369                                 break;
1370                 }
1371                 return false;
1372         };
1373         _colbrowser.prototype.processXLinkTypeSimple = function (xlinkEl, attrs, select, option, xml) {
1374                 return this.processXLinkActuate(xlinkEl, attrs, select, option, xml);
1375         };
1376         _colbrowser.prototype.processXLinkTypeArc = function (xlinkEl, attrs, select, option, xml) {
1377                 // @from and @to are available here unlike other methods
1378                 return this.processXLinkActuate(xlinkEl, attrs, select, option, xml);
1379         };
1380         _colbrowser.prototype.processXLinkActuate = function (xlinkEl, attrs, select, option, xml) {
1381                 var actuate = attrs.actuate;
1382                  // Fix: onLoad to be used to auto-load the root node?
1383                 switch (actuate) {
1384                         case 'onRequest':
1385                                 return this.processXLinkActuateOnRequest(xlinkEl, attrs, select, option);
1386                                 break;
1387                         case 'other':
1388                                  // use role/arcrole with 'other' or with user prefs?
1389                                 // Make provision for loading more than one--one resource might be onLoad,
1390                                 //   another onRequest; e.g., attribute xle (our own "XLink Extension"
1391                                 //   xle:actuate="onLoad onRequest") or better, rely on extended link to have data
1392                                 //   embedded (e.g., let one resource lead to both say HTML display and HTML text view),
1393                                 //   but as 'extended'/'locator' doesn't allow actuate/show, its simple links might repeat the content;
1394                                 //   However, the 'locator' of an 'extended' link can include nested XLink (like simple or arc) though
1395                                 //     behavior is undefined. Use an arc instead?
1396                                 break;
1397                         case undefined:
1398                         case '': // Our default is onLoad so pass through
1399                                 // break;
1400                         case 'none': // Our default is onLoad so pass through
1401                                 // break;
1402                         case 'onLoad':
1403                                 // Fix: The following line shouldn't be here but is here just temporarily to make things work
1404 //                                this.processXLinkActuateOnRequest(xlinkEl, attrs, select, option);// just testing (can delete later)
1405                                 return this.processXLinkActuateOnLoad(xlinkEl, attrs, select, option, xml);
1406                                 break;
1407                         default :
1408                                 alert('Invalid XLink actuate value');
1409                                 break;
1410                 }
1411                 return false;
1412         };
1413         _colbrowser.prototype.processXLinkActuateOnRequest = function (xlinkEl, attrs, select, option) {
1414                   // PREPARE THE OPTION FOR LATER CLICKING (A SIMPLE OR ARC TYPE, XLINK BY NOW)
1415                   var type = attrs.type,
1416                          href = attrs.href,
1417                          title = attrs.title,
1418                          role = attrs.role,
1419                          arcrole = attrs.arcrole,
1420                          show = attrs.show;
1421                  
1422                   if (type === 'arc') { // Arc itself does not have @href or @role (like simple), but does have the rest simple has and @from/@to
1423                           alert('Arcs not supported yet');
1424                           return false;
1425                   }
1426
1427                   // PREPARE TEXTUAL ADDITIONS
1428                   var introtitle = ((title === '') ? '' : ': '+ title);
1429                   var introarcrole = arcrole ? 'Arcrole: '+arcrole : 'Arcrole: none';
1430                   var introrole = role ? 'Role: '+role+';' : 'Role: none;';
1431                   var introhref = href ? 'href: '+ href : 'href: none;';
1432                  
1433                   // MAKE PLACE HOLDER FOR XLINK
1434                   option.innerHTML = '[['+type+' XLink'+introtitle+']]'; // If don't want link showing up (as might be large) // If enable this, then enable the following
1435
1436                   // ADD ANY ROLE AND ARCROLE TO TOOLTIP
1437                   option.title = introhref+'; \n\n'+introrole+' \n\n'+introarcrole+ '; \n\nTitle'+ introtitle;
1438                   option.setAttribute(_colbrowser.CLASSATT, 'xlink-'+type);
1439
1440                   // GET FULL LINK (INCLUDING XML:BASE)
1441                   var fullxlink = brettz9.DOM.getXmlBaseLink (/* XLink sans xml:base */ href,
1442                                                                                                         /* Element to query from */ xlinkEl);
1443                   option.value = 'show^'+show+'^doc^'+fullxlink+'^';
1444
1445                
1446                   // OVERPASS OUR TEMPORARY HOLDER ELEMENT
1447                   if (fullxlink.match(/#xpath1\(/)) {
1448                           option.value += '/holder';
1449                   }
1450
1451                   // ADD OPTION TO SELECT COLUMN
1452                   select.appendChild(option);
1453                   return select;
1454         };
1455         _colbrowser.prototype.processXLinkActuateOnLoad = function (xlinkEl, attrs, select, option, xml) {
1456                    if (attrs.type === 'arc') { // Arc itself does not have @href or @role (like simple), but does have the rest simple has and @from/@to
1457                           alert('Arcs not supported yet');
1458                           return false;
1459                   }
1460                   return this.processXLinkShow(xlinkEl, attrs, select, option, xml);
1461         };
1462
1463         _colbrowser.prototype.processXLinkShow = function (xlinkEl, attrs, select, option, xml) {
1464                 var show = attrs.show;
1465                 // Load in a new window (as columns?), replace this window (as columns?), or put within the document: new, replace, embed
1466                 // Fix: could replace the following with an overloading type (exceptions for empty or other)
1467                 switch (show) {
1468                         case 'new':
1469                                 this.processXLinkShowNew(xlinkEl, attrs);
1470                                 break;
1471                         case 'replace':
1472                                 this.processXLinkShowReplace(xlinkEl, attrs);
1473                                 break;
1474                         case 'other': // use role/arcrole with 'other' or with user prefs?; add markup to express both (e.g., new and embed)
1475                                 return this.processXLinkShowOther(xlinkEl, attrs, select, option);
1476                                 break;
1477                         case undefined: // Should this be here?
1478                         case '':
1479                                 return this.processXLinkShowEMPTY(xlinkEl, attrs, select, option, xml);
1480                                 break;
1481                         case 'none':
1482                                 this.processXLinkShowNone(xlinkEl, attrs, select, option, xml);
1483                                 break;
1484                         case 'embed':
1485                                 return this.processXLinkShowEmbed(xlinkEl, attrs, select, option, xml);
1486                                 break;
1487                         default :
1488                                 alert('Invalid XLink show value');
1489                                 break;
1490                 }
1491                 return false;
1492         };
1493         _colbrowser.prototype.processXLinkShowNew = function (xlinkEl, attrs) {
1494                 window.open(attrs.href);
1495         };
1496         _colbrowser.prototype.processXLinkShowReplace = function (xlinkEl, attrs) {
1497                 window.location.href = attrs.href;
1498         };
1499         _colbrowser.prototype.processXLinkShowEmbed = function (xlinkEl, attrs, select, option, xml) {
1500                 var href = attrs.href;
1501                 var colbrows = document.getElementById(this.colbrows_prfx+this.colbrows_suffix);
1502                 var selwidth = this.select_style_width;
1503                
1504                 // If appropriate, display any media, text, etc. when focused on an XLinked file
1505                 // GET FULL LINK (INCLUDING XML:BASE)
1506                 var fullxlink = brettz9.DOM.getXmlBaseLink (/* XLink sans xml:base */ href,
1507                                                                                                       /* Element to query from */ xlinkEl);
1508                 // FOR FILES, ADD A DUMMY COLUMN TO KEEP THE NAVIGATION STEADY (and possibly add functionality or text within later?)
1509                 if (href.match(/\.\w+$/) && fullxlink.match(/file:\/\//)) { // // Might also create a column and data for XML files retrieved on the local system
1510                         select.setAttribute('multiple', 'multiple'); // Fix: May wish to allow moving of items (could make this variable)
1511                         if (this.select_size) { // Size attribute shouldn't be 'undefined' if none present
1512                                 select.setAttribute('size', this.select_size);
1513                         }
1514                         select.setAttribute(_colbrowser.CLASSATT, this.css_prfx+'col'); // Make the column a visible one
1515
1516                         select.style.width = selwidth;
1517                         select.style.top = this.select_style_top;
1518                         select.style.left = (this.select_style_left - parseInt(selwidth.substr(0, selwidth.length-2), 10) ) +'px';
1519                         this.select_style_left += parseInt(selwidth.substr(0, selwidth.length-2), 10); // Don't grab pixels from width;
1520                         select.setAttribute('id', this.colbrows_prfx + (this.idCounter)); // Give an id for referencing
1521                         ++this.idCounter;
1522
1523                         option.innerHTML = '('+brettz9.XML.escapeString('File')+')';
1524                         option.value = '(null)';
1525                         select.appendChild(option);
1526                 }
1527
1528                 var fullxlinkText = 'show^embed^doc^'+fullxlink+'^';
1529                
1530                 if (fullxlinkText.match(/#xpath1\(/) || fullxlinkText.match(/dirGen\.js/)) {
1531                           fullxlinkText += '/holder';
1532                  }
1533                
1534                 // Fix: uncertain of this
1535                 // Bring the counter and left position down since we're already in one buildCol (?)
1536                 --this.idCounter;
1537                 this.select_style_left -= parseInt(selwidth.substr(0, selwidth.length-2), 10); // Don't grab pixels from width;
1538
1539                 if (!href.match(/\.\w+$/) || !fullxlink.match(/file:\/\//)) { // Brett added as don't seem to need to execute if just a file
1540                         this._buildCol(colbrows, false, fullxlinkText, xml);
1541                 }
1542                 else {
1543                         colbrows.appendChild(select);
1544                 }
1545                 // DISPLAY MEDIA AFTER COLUMNS ABOVE HAVE BEEN CREATED (MORE STEADY VIEW BY NOT WAITING ON MEDIA DISPLAY)
1546                 this.displayMedia(xlinkEl, attrs);
1547                 return true;
1548         };
1549         _colbrowser.prototype.processXLinkShowOther = function (xlinkEl, attrs, select, option) {
1550                 // Could use to put as new and embed (should require other namespaced attributes since
1551                 //    could be some other combination)
1552                 this.processXLinkShowNew(xlinkEl, attrs);
1553                 return this.processXLinkShowEmbed(xlinkEl, attrs, select, option);
1554         };
1555         _colbrowser.prototype.processXLinkShowNone = function (xlinkEl, attrs, select, option, xml) {
1556                 // Our default is embed, so pass through
1557                 this.processXLinkShowEmbed(xlinkEl, attrs, select, option, xml);
1558         };
1559         _colbrowser.prototype.processXLinkShowEMPTY = function (xlinkEl, attrs, select, option, xml) {
1560                 // Our default is embed, so pass through
1561                 return this.processXLinkShowEmbed(xlinkEl, attrs, select, option, xml);
1562         };
1563                                                
1564         // STORE XLINK DATA
1565         // Depends on: doc (newXPath, fileXLinkAndXPath), that (actually, now 'this' again)
1566         _colbrowser.prototype._storeXML = function (xmldoc, newXPath, fileXLinkAndXPath, jsmatch) {
1567                 var docu;
1568                 var hideHiddenFiles = false;
1569                 if (document.getElementById('colbrowser_hide_hidden_files').checked) {
1570                     hideHiddenFiles = true;
1571                 }
1572                 // Fix: Apply XPointer here based on #xpath1() ? (ensure XPath is available after the call to this function too)
1573                 if (typeof xmldoc === 'number') {
1574                         throw (new Error('HTTP Error code '+xmldoc));
1575                         return;
1576                 }
1577                 else if (typeof xmldoc === 'string') {
1578                         if (jsmatch) {
1579                                 var jslink = jsmatch[0];
1580                                 var parsedfile = brettz9.URI.parse(jsmatch[2]).key.f;
1581                         }
1582                         eval(xmldoc);
1583                         xmldoc = XML.parse(brettz9.XML.XMLOutput);
1584                 }
1585                 /*
1586                 else if (typeof xmldoc === 'string') {
1587
1588                         docu = XML.parse(xmldoc);
1589                 }
1590                 */
1591                 if (newXPath) {
1592                         // Need to import, since can't serialize newly retrieved xml above as it is a security error (from an external document)
1593                         var xmlToImport = XML.getNodes(xmldoc, newXPath, null, xmldoc);
1594                         if (document.implementation && document.implementation.createDocument) {
1595                                 docu = document.implementation.createDocument('', '', null);
1596 //                                                docu = document.createDocumentFragment();
1597                         }
1598                         else {
1599                                 docu = new ActiveXObject("Microsoft.XMLDOM");
1600                         }
1601                         try {
1602
1603                                 var holder = brettz9.DOM.createElementNSwrapper('', 'holder', docu); // This holder will be circumvented later
1604                                 for (var clone, i=0; i < xmlToImport.length; i++) {
1605 //                                                clone = docu.importNode(xmlToImport[i], true); // Do a deep copy of these nodes
1606                                         clone = brettz9.DOM.importNode(xmlToImport[i], true, docu); // docu
1607                                         holder.appendChild(clone); // docu.appendChild(clone);
1608                                 }
1609                                 docu.appendChild(holder);
1610
1611                         } catch (e) {
1612                                 alert('4:'+e.message?e.message:e);
1613                         }
1614                 }
1615                 else {
1616                         docu = xmldoc;
1617                 }
1618                
1619                 docu = brettz9.DOM.resolveXIncludes(docu);
1620                
1621                 this.URLtoXMLDoc[fileXLinkAndXPath] = docu;
1622         };
1623              
1624        
1625         // NAVIGATION HANDLERS
1626         //
1627         // depends on that, xml, _scrollColItemIntoView(), _getCurrentColNum(), _getColByNum()
1628         _colbrowser.prototype._rightHandle = function (el, keyid, e, xml) { // Triggered in each case with _selectChange in FF
1629                 var targ = _colbrowser.MSIE ? e.srcElement : e.target;
1630
1631                 // AVOID ACTING FURTHER ON FURTHERMOST RIGHT COLUMN
1632                 if (targ.value === '(null)') {// Deprecated comment: el.options[el.selectedIndex].value === 'null') {
1633                         return false; // catching 'null' (as opposed to '(null)') is not necessary if selectedIndex is set in buildCol since the option will not be the last hidden one (in FF)
1634                 }
1635
1636                 // var column = new Column(el);
1637                 // selectchange is insufficient since not triggered in beginning or at end
1638                 var colbrows = document.getElementById(this.colbrows_prfx+this.colbrows_suffix);
1639
1640
1641                 // BUILD COLUMN INTO WHICH RIGHT ARROW IS NOW MOVING
1642                 try {
1643                         this._buildCol(colbrows, el, el.value, xml);
1644
1645                         var num = _colbrowser._getCurrentColNum(this, el);
1646                         ++num;
1647                         var nextcol = _colbrowser._getColByNum(this, num);
1648
1649
1650                         if (nextcol && 1) { // if it is a directory, go to the next column
1651                                 nextcol.setAttribute(_colbrowser.CLASSATT, this.css_prfx+'col');
1652                                 nextcol.selectedIndex = 0;
1653                                 nextcol.focus();
1654                                 // nextcol.scrollIntoView(true); // Causes jerky screen behavior (e.g., scrolls down)
1655
1656                                 // The following was necessary in Explorer (needs testing), but since the "selectclick" onchange handler gets
1657                                 //      calls in Firefox (not anymore, but still causes problems in FF when done here), so this is not necessary
1658                                 //      for FF and causes the selectedIndex to go up unnecessarily
1659                                 // More recent note: I added "_colbrowser.MSIE" since Firefox doesn't seem to use the following at all (if IE doesn't use it, the view won't scroll into the next column)
1660                                 if (_colbrowser.MSIE && nextcol.options[0].value !== '(null)') { // Test needed (in IE only, but doesn't hurt FF) to avoid error when right-clicking item already on furthermost right text
1661                                         try {
1662                                                 this._buildCol(colbrows, nextcol.options[0], nextcol.options[0].value, xml);
1663                                         }
1664                                         catch (e) {
1665                                                 /*
1666                                                  *alert(colbrows); // div
1667                                                 alert(nextcol.options[0]); // option
1668                                                 alert( nextcol.options[0].value); // ...
1669                                                 */
1670 //                                                        alert(XML.serialize(xml));
1671
1672                                                 alert('1:For '+nextcol.options[0].value+':\n\t'+(e.message?e.message:e));
1673                                                 return false;
1674                                         }
1675                                 }
1676
1677                                 if (_colbrowser.MOZ && 1) { // Only do this if the current item is a folder //  && !returnkey
1678                                         --nextcol.selectedIndex; // Decrement position in select menu to anticipate unstoppable action in FF Windows
1679                                 }
1680                                 else if (_colbrowser.MSIE) { // Needed for some reason here in IE (_selectChange handles it for FF, but though _selectChange is called for IE too, doesn't work with IE)
1681                                         // Fix: might be able to get it to trigger in IE too if get selectChange right
1682                                         _colbrowser._scrollColItemIntoView(this, nextcol);
1683                                         if (nextcol.options[0].value !== '(null)') { // Not triggered in IE otherwise
1684                                               this.InfoStrategy.populateAllInfo(nextcol.options[0].value, this.URLtoXMLDoc);
1685                                         }
1686                                 }
1687                         }
1688                  } catch (e) {
1689                         alert('2: For '+el.value+':\n\t'+(e.message?e.message:e));
1690                 }
1691                 return false;
1692         };
1693
1694         // depends on that, _getCurrentColNum(), _getColByNum()
1695         _colbrowser.prototype._leftHandle = function (el, keyid, e) {
1696                 // Note that _selectChange() will also be called (so repopulating metadata is not necessary here) (Fix: make sure that's true for IE once IE code is fixed)'
1697
1698                 var num2 = _colbrowser._getCurrentColNum(this, el);
1699                 ++num2;
1700                 var nextcol = document.getElementById(this.colbrows_prfx+num2);
1701                 while (nextcol) {
1702                         // Don't just change visibility, since the user might choose a different column next time
1703                         nextcol.parentNode.removeChild(nextcol);
1704                         // Decrement the id and the left setting so next item will be placed correctly:
1705                         --this.idCounter;
1706                         var selwidth = this.select_style_width;
1707                         this.select_style_left -= parseInt(selwidth.substr(0, selwidth.length-2), 10); // Don't grab pixels from width;
1708                         nextcol = document.getElementById(this.colbrows_prfx + (++num2));
1709                 }
1710
1711                 var num = _colbrowser._getCurrentColNum(this, el);
1712                 --num;
1713                 var prevcol = _colbrowser._getColByNum(this, num);
1714                 if (prevcol) { // if there is a previous column, go there (regardless of whether this is a file or not)
1715                         el.selectedIndex = -1;
1716                         prevcol.focus();
1717
1718                         // Fix:? If some browsers won't support this, could use anchors and window.location.hash
1719                         //prevcol.scrollIntoView(true); // Needed by Firefox, but IE (incorrectly?) seems to assume this
1720                         if ((prevcol.selectedIndex !== (prevcol.options.length-1)) && _colbrowser.MOZ) {
1721                                 ++prevcol.selectedIndex;
1722                         }
1723                         else {
1724                                 brettz9.DOM.stopEventFully(e);
1725                         }
1726                         if (_colbrowser.MSIE && prevcol.options[0].value !== '(null)') { // Not triggered in IE otherwise
1727                                       this.InfoStrategy.populateAllInfo(prevcol.options[0].value, this.URLtoXMLDoc);
1728                         }
1729                 }
1730                 return false;
1731         };
1732
1733         // Next two depend on _selectChange
1734         // Presence of these handles had earlier seemed to prohibit Explorer from taking its default actions
1735         _colbrowser.prototype._downHandle = function (el, keyid, e) {
1736                 if (_colbrowser.MOZ && el.selectedIndex === el.options.length-2) {
1737                         el.selectedIndex = el.options.length-3;
1738                 }
1739                 else if (_colbrowser.MSIE) {
1740                         if (el.selectedIndex < el.length-1) {
1741                                 el.selectedIndex++; // This was necessary when inside the function but not when called here!
1742                         }
1743                         this._selectChange(e);
1744                 }
1745         };
1746         _colbrowser.prototype._upHandle = function (el, keyid, e) {
1747                 if (_colbrowser.MSIE) {
1748                         if (el.selectedIndex > 0) {
1749                                  el.selectedIndex--; // This was necessary when inside the function but not when called here!
1750                         }
1751                         this._selectChange(e);
1752                 }
1753         };
1754
1755         // Next 4 depend on that
1756         // Fix: End doesn't work in FF2 or FF3 (but does in IE)
1757         // Fix: pagedown also doesn't work in FF3 for some reason
1758         // Fix: Page up/down behave like home/end (could fix by detecting column height and doubling unless over length)
1759         _colbrowser.prototype._pageDownHandle = function (el, keyid, e) {
1760                 el.selectedIndex = el.length-1; // Taking into account invisible last option
1761                 // Scroll to the bottom
1762                 var id0 = document.getElementById(this.colbrows_prfx+this.colbrows_suffix);
1763                 id0.scrollTop = id0.scrollHeight;
1764         };
1765         _colbrowser.prototype._pageUpHandle = function (el, keyid, e) {
1766                 el.selectedIndex = _colbrowser.MSIE ? 0 : -1; // Setting to negative one since will be 'upped' next time.
1767                 // Scroll to the bottom
1768                 var id0 = document.getElementById(this.colbrows_prfx+this.colbrows_suffix);
1769                 id0.scrollTop = 0;
1770         };
1771
1772         _colbrowser.prototype._homeHandle = function (el, keyid, e) {
1773                 el.selectedIndex = _colbrowser.MSIE ? 0 : -1; // Setting to negative one since will be 'upped' next time.
1774                 // Scroll to the bottom
1775                 var id0 = document.getElementById(this.colbrows_prfx+this.colbrows_suffix);
1776                 id0.scrollTop = 0;
1777         };
1778         _colbrowser.prototype._endHandle = function (el, keyid, e) {
1779                 el.selectedIndex = el.length-1; // Taking into account invisible last option
1780                 // Scroll to the bottom
1781                 var id0 = document.getElementById(this.colbrows_prfx+this.colbrows_suffix);
1782                 id0.scrollTop = id0.scrollHeight;
1783         };
1784
1785         // The next 2 depend on nothing (so far)
1786         // DELETE OR ADD ELEMENT HANDLERS
1787         _colbrowser.prototype._deleteHandle = function (el, keyid, e) {
1788                 var option = el.options[el.selectedIndex];
1789                 option.parentNode.removeChild(option);
1790         };
1791         _colbrowser.prototype._ctrlShiftN = function (el, keyid, e) {
1792                 var option = el.options[el.selectedIndex];
1793                 var option2 = brettz9.DOM.createElementNSwrapper(_colbrowser.HTMLNS, 'option');
1794                 option2.innerHTML = 'dir';
1795                 option2.value = '';
1796
1797                 option.parentNode.insertBefore(option2, option.nextSibling); //i.e., insertAfter
1798
1799                 // Fix: Recalculate subsequent options' values!!!!!
1800         };
1801
1802         // Depends on that
1803         // RENAME HANDLER
1804         _colbrowser.prototype._returnHandle = function (el, keyid, e) {
1805                 if (1) { // !this.editmode
1806                         Tooltip.lastel = _colbrowser.MSIE ? e.srcElement : e.target;
1807                         var startleft = this.colbrows_style_left.replace(/px$/, '');
1808                         var starttop = this.colbrows_style_top.replace(/px$/, '');
1809                         Tooltip.schedule(this.colbrows_prfx+this.colbrows_suffix, el, e, startleft, starttop);
1810                 }
1811                 else {
1812                         // Remove the edit box and return focus
1813
1814                 }
1815                 return false;
1816         };
1817         _colbrowser.prototype._selectClick = function (e, xml) { // CLICK AND CHANGE HANDLERS
1818                 // local vars needed: 'that', 'xml'
1819                 // GET SELECT
1820                 // For IE, sometimes the click event is a SELECT and other times it is an OPTION (we only need (and for some reason in IE can only use) the SELECT)
1821                 var selectCol = _colbrowser.MSIE ? e.srcElement : e.target.parentNode; // In FF, the event only occurs on an 'option' (though attached to 'select'), so grab its parent to get the 'select'
1822
1823                 // AVOID IE OPTION CLICK EVENTS
1824                 if (selectCol.nodeName.toLowerCase() !== 'select') { // Need to convert to lower case since IE treats as HTML despite XHTML namespace
1825                         return;
1826                 }
1827                 // AVOID STRAY CLICK PROBLEMS IN IE
1828                 if (_colbrowser.MSIE) {
1829                         // If clicked in corner of window, there were problems of extra column appearing (even if clicked on item which was selected, it still seemed to open an extra column briefly)
1830                         if (selectCol.selectedIndex === undefined || selectCol.selectedIndex == -1) {return;}
1831                 }
1832                 // DO NOTHING WITH FURTHERMOST RIGHT ITEM
1833                 if (selectCol.value === '(null)') { // We can refer to the option's value, even though 'targ' is a select'
1834                         return;
1835                 }
1836                 // LET NEW/DELETE OPERATIONS KNOW THAT THIS COLUMN IS THE CURRENTLY FOCUSED ITEM
1837                 _colbrowser.currFocus = selectCol;
1838                 try {
1839                         // REFRESH METADATA DISPLAY
1840                         // _selectChange (which runs before a click if it runs) doesn't run if one clicks on an
1841                         //      item already highlighted in an earlier column
1842                         this.InfoStrategy.populateAllInfo(selectCol.value, this.URLtoXMLDoc);
1843
1844                         // BUILD VIEW OF NEXT COLUMN (BUT DON'T GO INTO IT YET)
1845                         var colbrows = document.getElementById(this.colbrows_prfx+this.colbrows_suffix);
1846                         this._buildCol(colbrows, selectCol, selectCol.value, xml);
1847                 } catch (e) {
1848                         if (e.name !== 'NS_ERROR_ILLEGAL_VALUE') { // Don't repeat this error since there is already the HTTP one
1849                             alert(e.message?e.message:e);
1850                         }
1851                 }
1852         };
1853         // local vars needed: 'that', 'xml', _scrollColItemIntoView()
1854         _colbrowser.prototype._selectChange = function (e, xml) {
1855                  // ENSURE MEDIA DISPLAY WINDOW CHANGES
1856                 var holder = document.getElementById('colbrows_img_display');
1857                 while (holder.childNodes.length > 0) {
1858                         holder.removeChild(holder.firstChild);
1859                 }
1860                
1861                 // Brett trying this
1862                 var targ = _colbrowser.MSIE ? e.srcElement : e.target;
1863                 _colbrowser.currFocus = targ; // Record latest for use with new item / delete item functions
1864                 if (targ.value === '(null)') { // Can't do in click handler since in IE this happens first
1865                         return;
1866                 }
1867                 else if (targ.value === 'null') { // If last item already
1868                         targ.selectedIndex = 0; // This is required so right clicks will work
1869                         return;
1870                 }
1871                 else if (targ.selectedIndex === undefined) { // In case one click on the edge of the select before an item is selected
1872                         return;
1873                 }
1874
1875                 var colbrows = document.getElementById(this.colbrows_prfx+this.colbrows_suffix);
1876                 try {
1877                         this._buildCol(colbrows, targ, targ.value, xml);
1878
1879                         // SCROLL NEXT COLUMN INTO VIEW (AFTER CLICK OR RIGHT ARROW)
1880                         _colbrowser._scrollColItemIntoView(this, targ);
1881
1882                         // REFRESH METADATA DISPLAY
1883                         this.InfoStrategy.populateAllInfo(targ.value, this.URLtoXMLDoc);
1884                 } catch (e) {
1885                         alert('3: For '+targ.value+':\n\t'+(e.message?e.message:e));
1886                 }
1887         };
1888
1889         // CONSTANTS (NAMESPACE, BROWSER/PLATFORM)
1890         // Class property (not to be different across instances and can be called from the outside too)
1891         _colbrowser.HTMLNS = 'http://www.w3.org/1999/xhtml';
1892         _colbrowser.XLINKNS = 'http://www.w3.org/1999/xlink';
1893         _colbrowser.MOZ = navigator.userAgent.indexOf('Gecko/') !== -1 &&
1894                                                         navigator.vendor.indexOf('Apple') === -1; // Testing only for Firefox will miss Seamonkey, etc.
1895         _colbrowser.MOZWIN = navigator.appVersion.indexOf('Win') !== -1 && _colbrowser.MOZ;
1896         _colbrowser.MSIE = navigator.userAgent.indexOf('MSIE') !== -1;
1897         _colbrowser.CLASSATT = _colbrowser.MSIE ? 'className' : 'class';
1898        
1899         // Adapted a portion of script from http://www.quirksmode.org/js/detect.html used here for OS detection
1900         _colbrowser.searchString = function (data) {
1901               for (var i=0;i<data.length;i++)    {
1902                   var dataString = data[i].string;
1903                   if (dataString) {
1904                       if (dataString.indexOf(data[i].subString) !== -1)
1905                           return data[i].identity;
1906                   }
1907               }
1908               return false;
1909         };
1910         _colbrowser.dataOS = [
1911               {
1912                   string: navigator.platform,
1913                   subString: "Win",
1914                   identity: "Windows"
1915               },
1916               {
1917                   string: navigator.platform,
1918                   subString: "Mac",
1919                   identity: "Mac"
1920               },
1921               {
1922                   string: navigator.platform,
1923                   subString: "Linux",
1924                   identity: "Linux"
1925               }
1926           ]
1927  
1928         // Must come after the function above
1929         _colbrowser.OS = _colbrowser.searchString(_colbrowser.dataOS);
1930         _colbrowser.OSfile_slash = (_colbrowser.OS === 'Windows') ? '\\' : '/'; // The following doesn't seem to auto-convert forward slashes to backslashes, so this is needed (though why is there no problem in overlay.js for Windows? Probably since only being used there for Java)
1931         _colbrowser.XPathPlus = /^(show\^([^\^]*)\^doc\^([^)#\^]*)(#xpath1\((.*)\))?\^)(.*)$/; // Inside of xpath1 allows for parentheses since URL's do, but closing ^ (which is not allowed in URL's) should ensure the right parenthesis is grabbed
1932
1933         var currFilePath = window.location.href.replace(/\/[\w\.]+$/, '/');
1934         _colbrowser.currFilePath = currFilePath; // Use in dirGen.js
1935
1936         // DEFAULT XML DOCUMENT
1937         //this.xmlstring1 = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'+
1938         //      '<html><body><\/body><\/html>'; /* Used for testing Public Doctype */
1939         // Note that in IE you cannot seem to ask for privs like in Firefox to work with local files (unless on a server as localhost).
1940         // Explorer also doesn't seem to be able to open a file with an extension (like .rdf) and treat it as XML (unless served presumably).
1941         _colbrowser.sampleXml = ''+ // "<!DOCTYPE orig [ <!ENTITY blah 'okeeee'> ]>\n"+ /* SYSTEM 'ABC.dtd' */
1942         "               <"+"?js pseudo2='attr'?><!-- mycomment2 -->"+
1943         "<Home:Base xmlns:xi='http://www.w3.org/2001/XInclude' xml:base='http://localhost/navbarcrumbs' xmlns:xlink='http://www.w3.org/1999/xlink' xmlns:Home='abcdef' dog='ca&amp;t' war='peace'>\n"+
1944         "                       <"+"?js pseudo='attr'?><!-- mycomment1 -->blah;<someXML abc='ok'>\neee"+
1945         "                               <anElement a='abc&amp;>&lt;'><Great-Grandparents><Grandparents>Joe &amp; Ellen<Parents>Harry &amp; Joan<Child>Steve<\/Child><Sibling>Sue<\/Sibling><\/Parents>Fred &amp; Mary<\/Grandparents><\/Great-Grandparents><Dog>Fritz<\/Dog>some Text<cat>Fifi<\/cat>moretext<\/anElement>\n"+
1946         "                               <anotherElement><![CDATA[ abc<>def ]]"+"> blah; def<\/anotherElement>\n"+
1947         "                               <MoreXML><a>dog</a>\n"+
1948         "                                       <b>Some text 2<\/b>\n"+
1949         "                                       <otherMeaninglessJunk>ghi<\/otherMeaninglessJunk>\n"+
1950         "                               <\/MoreXML>\n"+
1951         "                       <\/someXML>\n"+
1952         "                       <webXML xlink:href='http://bahai-library.com/zamir/chintest9.xml'></webXML>"+
1953         "                       <XLinkTitle xlink:type='title'><select size='2'><option>def</option><option>abc</option></select><input type='checkbox' checked='checked' /><table border='1'><tr><td>ab</td><td>cd</td></tr><tr><td>ef</td><td>gh</td></tr></table><input type='button' value='Hi!' onclick='alert(123);'  /><i style='color:red;'>Testing</i> now</XLinkTitle>";
1954         switch (_colbrowser.OS) {
1955                 case 'Windows':
1956                          _colbrowser.sampleXml += "<Windows_only xlink:title='Windows only (C:\\)' xlink:href='"+currFilePath+"dirGen.js?f=C:\\'></Windows_only>";
1957                          break;
1958                 case "Mac":
1959                          _colbrowser.sampleXml += "<Mac_only xlink:title='Mac only (/Users)' xlink:href='"+currFilePath+"dirGen.js?f=/Users'></Mac_only>";
1960                case "Linux":
1961                default:
1962                        _colbrowser.sampleXml += "<Other_OS xlink:title='Other OS (/)' xlink:href='"+currFilePath+"dirGen.js?f=/'></Other_OS>";
1963                        break;
1964         }
1965
1966 /* Doesn't work from file:/// or localhost
1967         "                       <file xlink:href='http://localhost/brettz9/colbrowser/dirGen.js'></file>"+ */
1968  /* file:///C:/wamp/www/navbarcrumbs/sitemap.xml */
1969         // UTF-16 can work in IE but not in Firefox due to our configuration
1970         _colbrowser.sampleXml += "<tests xlink:title='Brett&apos;s tests'><TestLocalhost><name xlink:title='my xltitle (localhost)' xlink:href='http://localhost/standard-sitemap/stdsitemap-ff-ext/trunk/install.xml#xpath1(//*[local-name()=\"id\" and namespace-uri()=\"http://www.mozilla.org/2004/em-rdf#\"])'>directory1 and more<\/name>\n"+
1971         "                       <_127.0.0.1 xlink:href='http://127.0.0.1/navbarcrumbs/sitemap.xml' abc='oka'>filea<\/_127.0.0.1></TestLocalhost>\n"+
1972         "                       <TestXPathId xlink:href='http://localhost/navbarcrumbs/sitemap.xml#xpath1(//pg[@id=&quot;pg1&quot;])' abc='ok'>file1<\/TestXPathId>\n"+
1973         "                       <TestXPath xlink:href='http://localhost/navbarcrumbs/sitemap.xml#xpath1(//pg)' abc='oka'>file2<\/TestXPath>\n"+
1974         "                       <TextXIncludeXML><xi:include parse='xml' xpointer='//node' href='file:///C:/Users/Brett/Documents/MindMaps-test.xml'><xi:fallback>Some text</xi:fallback></xi:include></TextXIncludeXML>"+
1975         "                       <TextXIncludeText><xi:include parse='text' encoding='GB2312' href='file:///C:/Users/Brett/Documents/MindMaps-test4.xml'><xi:fallback>Some text</xi:fallback></xi:include></TextXIncludeText>"+
1976         "                       </tests>\n<\/Home:Base><"+"?js pseudo3='attr'?><!-- mycomment3 --"+">";
1977
1978         // STATIC (CHANGEABLE) VARS ACROSS ALL INSTANCES
1979         _colbrowser.colbrowsCount = 0;
1980
1981        
1982         // UTILITY METHODS
1983         // These 4 only depend on 'that' (and the 3rd depends on the first two)
1984         // 'that' must be passed in here since we're avoiding crowding the _colbrowser class
1985         //    with privileged methods and avoiding public ones (could also be class methods)
1986         // Fixed: will probably need to make as public or class methods (or privileged?) though in order to easily
1987         //           and selectively borrow the methods that depend on these
1988         // Before: Had been as private functions (which had 'that' sent to them)
1989         // Now: Implemented as class methods just to indicate that these methods did not have side
1990         //   effects (and can still be borrowed)
1991
1992         _colbrowser._getCurrentColNum = function (that, col) {
1993                 return parseInt(col.id.substr(that.colbrows_prfx.length), 10);
1994         };
1995         _colbrowser._getColByNum = function (that, num) {
1996                 return document.getElementById(that.colbrows_prfx + num);
1997         };
1998         _colbrowser._getNextCol = function (that, col) {
1999                 var num = _getCurrentColNum(that, col);
2000                 num++;
2001                 return _getColByNum(that, num);
2002         };
2003         _colbrowser._scrollColItemIntoView = function (that, targ) {
2004                
2005                 // CAUSE CLICK OR RIGHT ARROW TO SCROLL NEXT COLUMN INTO VIEW
2006                 var id0 = document.getElementById(that.colbrows_prfx+that.colbrows_suffix);
2007                 var selwidth = that.select_style_width;
2008
2009                 // ADVANCE SCROLL TO THE RIGHT
2010                 id0.scrollLeft = id0.scrollLeft +
2011                                                         parseInt(       selwidth.substr(0, selwidth.length-2), 10       ); // Don't grab pixels from width
2012
2013                 if (!that.select_size) { // Not necessary to do this if the select size is fixed
2014                         // ADVANCE SCROLL HIGHER OR LOWER AS NEEDED
2015                         // Fix: Scroll top doesn't work in IE in select menus: (works in FF, not in IE7): see http://www.quirksmode.org/bugreports/archives/2006/02/scrollTop_in_select_list_in_IE_is_always_0.html ?
2016                         // id0.scrollTop = id0.scrollTop + Tooltip.Y_MENUOFFSET * 2; // 15 * 2; // double it to show extra blank area at bottom too
2017
2018                         // Scroll down a little if option chosen is farther down than 3/5 the visible height, and scroll up if less than 2/5 (could change this formula, and the fractions wouldn't need to total either)
2019                         //if (brettz9.STYLE.getY(targ.options[targ.selectedIndex]) > ...)
2020                         if (targ.selectedIndex*16 >=
2021                                 that.colbrows_style_height.replace(/px$/, '') * 50/100) {
2022                         //      id0.scrollTop = id0.scrollTop + Tooltip.Y_MENUOFFSET * 1.5; // 15 * 2; // double it to show extra blank area at bottom too
2023                         //      id0.scrollTop = brettz9.STYLE.getY(targ.options[targ.selectedIndex]);
2024                                 id0.scrollTop = targ.selectedIndex*16 + 46;
2025                         }
2026                         else if (targ.selectedIndex*16 <
2027                                 that.colbrows_style_height.replace(/px$/, '') * 50/100) { // Otherwise, bring it up
2028                                 id0.scrollTop = targ.selectedIndex*16 - 26;
2029                         //      id0.scrollTop = id0.scrollTop - Tooltip.Y_MENUOFFSET * 1.5; // 15 * 2; // double it to show extra blank area at bottom too
2030                         //      id0.scrollTop = brettz9.STYLE.getY(targ.options[targ.selectedIndex]);
2031                         }
2032                         // id0.scrollTop = that.colbrows_style_height.replace(/px$/, '')*1/2;
2033                 }
2034         };
2035
2036
2037         // MAKE ONE PRIVATE CONSTRUCTOR FUNCTION ABOVE PUBLIC
2038         var _public = {
2039                 colbrowser : _colbrowser
2040         };
2041         return _public;
2042 }();
Note: See TracBrowser for help on using the browser.