JAL-1807 Bob's JalviewJS prototype first commit
[jalviewjs.git] / site / swingjs / js / JSmoljQueryExt.js
1 // JSmoljQueryExt.js\r
2 // 9/2/2013 7:43:12 AM BH Opera/Safari fix for binary file reading\r
3 // 3/11/2014 6:31:01 AM BH fix for MSIE not working locally\r
4 \r
5 ;(function($) {\r
6 \r
7         function createXHR(isMSIE) {\r
8                 try {\r
9                         return (isMSIE ? new window.ActiveXObject( "Microsoft.XMLHTTP" ) : new window.XMLHttpRequest());\r
10                 } catch( e ) {}\r
11         }\r
12 \r
13  $.ajaxSettings.xhr = (window.ActiveXObject === undefined ? createXHR :  \r
14         function() {\r
15                 return (this.url == document.location || this.url.indexOf("http") == 0 || !this.isLocal) &&  // BH MSIE fix\r
16                         /^(get|post|head|put|delete|options)$/i.test( this.type ) &&\r
17                         createXHR() || createXHR(1);\r
18         });\r
19 \r
20 \r
21 // Bind script tag hack transport\r
22                 $.ajaxTransport( "+script", function(s) {\r
23 \r
24         // This transport only deals with cross domain requests\r
25         // BH: No! This is not compatible with Chrome\r
26         if ( true || s.crossDomain ) {\r
27 \r
28                 var script,\r
29                         head = document.head || jQuery("head")[0] || document.documentElement;\r
30 \r
31                 return {\r
32 \r
33                         send: function( _, callback ) {\r
34                                 script = document.createElement("script");\r
35                                 //script.async = true;\r
36 \r
37                                 if ( s.scriptCharset ) {\r
38                                         script.charset = s.scriptCharset;\r
39                                 }\r
40 \r
41                                 script.src = s.url;\r
42 \r
43                                 // Attach handlers for all browsers\r
44                                 script.onload = script.onreadystatechange = function( _, isAbort ) {\r
45 \r
46                                         if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\r
47 \r
48                                                 // Handle memory leak in IE\r
49                                                 script.onload = script.onreadystatechange = null;\r
50                                                 // Remove the script\r
51                                                 if ( script.parentNode ) {\r
52                                                         script.parentNode.removeChild( script );\r
53                                                 }\r
54 \r
55                                                 // Dereference the script\r
56                                                 script = null;\r
57 \r
58                                                 // Callback if not abort\r
59                                                 if ( !isAbort ) {\r
60                                                         callback( 200, "success" );\r
61                                                 }\r
62                                         }\r
63                                 };\r
64 \r
65                                 // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending\r
66                                 // Use native DOM manipulation to avoid our domManip AJAX trickery\r
67                                 head.insertBefore( script, head.firstChild );\r
68                         },\r
69 \r
70                         abort: function() {\r
71                                 if ( script ) {\r
72                                         script.onload( undefined, true );\r
73                                 }\r
74                         }\r
75                 };\r
76         }\r
77 });\r
78  \r
79         // incorporates jquery.iecors MSIE asynchronous cross-domain request for MSIE < 10\r
80 \r
81         $.extend( $.support, { iecors: !!window.XDomainRequest });\r
82 \r
83         if ($.support.iecors) {\r
84                 // source: https://github.com/dkastner/jquery.iecors\r
85                 // author: Derek Kastner dkastner@gmail.com http://dkastner.github.com    \r
86                 $.ajaxTransport(function(s) {\r
87                 \r
88                         return {\r
89                                 send: function( headers, complete ) {                           \r
90                                         // Note that xdr is not synchronous.\r
91                                         // This is only being used in JSmol for transport of java code packages.\r
92                                         var xdr = new window.XDomainRequest();\r
93                                         xdr.onload = function() {          \r
94                                                 var headers = { 'Content-Type': xdr.contentType };\r
95                                                 complete(200, 'OK', { text: xdr.responseText }, headers);\r
96                                         };\r
97                                         if ( s.xhrFields ) {\r
98                                                 xdr.onerror = s.xhrFields.error;\r
99                                                 xdr.ontimeout = s.xhrFields.timeout;\r
100                                         }\r
101                                         xdr.open( s.type, s.url );\r
102                                         xdr.send( ( s.hasContent && s.data ) || null );\r
103                                 },\r
104                                 abort: function() {        \r
105                                         xdr.abort();\r
106                                 }\r
107                         };\r
108                 });\r
109 \r
110         } else {\r
111 \r
112         // adds support for synchronous binary file reading\r
113 \r
114                 $.ajaxSetup({\r
115                         accepts: { binary: "text/plain; charset=x-user-defined" },\r
116                         responseFields: { binary: "response" }\r
117                 })\r
118 \r
119 \r
120                 $.ajaxTransport('binary', function(s) {\r
121                 \r
122                         var callback;\r
123                         return {\r
124                                 // synchronous or asynchronous binary transfer only\r
125                                 send: function( headers, complete ) {        \r
126                                         var xhr = s.xhr();\r
127                                         console.log("xhr.open binary async=" + s.async + " url=" + s.url);\r
128                                         xhr.open( s.type, s.url, s.async );                                     \r
129                                         var isOK = false;\r
130                                         try {\r
131                                                 if (xhr.hasOwnProperty("responseType")) {\r
132                                                                 xhr.responseType = "arraybuffer";\r
133                                                                 isOK = true;\r
134                                                 } \r
135                                         } catch(e) {\r
136                                           //\r
137                                         }\r
138                                         try {\r
139                                                 if (!isOK && xhr.overrideMimeType) {\r
140                                                         xhr.overrideMimeType('text/plain; charset=x-user-defined');\r
141                                                 }\r
142                                         } catch(e) {\r
143                                                         //\r
144                                         }\r
145                                         if ( !s.crossDomain && !headers["X-Requested-With"] ) {\r
146                                                 headers["X-Requested-With"] = "XMLHttpRequest";\r
147                                         }\r
148                                         try {\r
149                                                 for (var i in headers )\r
150                                                         xhr.setRequestHeader( i, headers[ i ] );\r
151                                         } catch(_) {}\r
152 \r
153                                         xhr.send( ( s.hasContent && s.data ) || null );\r
154 \r
155                                         // Listener\r
156                                         callback = function( _, isAbort ) {\r
157 \r
158                                         var \r
159                                                 status = xhr.status,\r
160                                                 statusText = "",\r
161                                                 responseHeaders = xhr.getAllResponseHeaders(),\r
162                                                 responses = {},\r
163                                                 xml;\r
164 \r
165                                         try {\r
166 \r
167                                                 // Firefox throws exceptions when accessing properties\r
168                                                 // of an xhr when a network error occured\r
169                                                 // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\r
170                                                 // Was never called and is aborted or complete\r
171                                                 if ( callback && ( xhr.readyState === 4 ) ) {\r
172 \r
173                                                         // Only called once\r
174                                                         callback = undefined;\r
175 \r
176                                                         // When requesting binary data, IE6-9 will throw an exception\r
177                                                         // on any attempt to access responseText (#11426)\r
178                                                         try {\r
179                                                                 responses.text = (typeof xhr.responseText === "string" ? xhr.responseText : null);\r
180                                                         } catch( _ ) {\r
181                                                         }\r
182                                                         try {\r
183                                                                 responses.binary = xhr.response;\r
184                                                         } catch( _ ) {\r
185                                                         }\r
186 \r
187                                                         // Firefox throws an exception when accessing\r
188                                                         // statusText for faulty cross-domain requests\r
189                                                         try {\r
190                                                                 statusText = xhr.statusText;\r
191                                                         } catch( _ ) {\r
192                                                                 // We normalize with Webkit giving an empty statusText\r
193                                                                 statusText = "";\r
194                                                         }\r
195                                                         // Filter status for non standard behaviors\r
196 \r
197                                                         // If the request is local and we have data: assume a success\r
198                                                         // (success with no data won't get notified, that's the best we\r
199                                                         // can do given current implementations)\r
200                                                         if ( !status && s.isLocal && !s.crossDomain ) {\r
201                                                                 status = (responses.text ? 200 : 404);\r
202                                                         // IE - #1450: sometimes returns 1223 when it should be 204\r
203                                                         } else if ( status === 1223 ) {\r
204                                                                 status = 204;\r
205                                                         }\r
206                                                         complete( status, statusText, responses, responseHeaders );\r
207                                                 }\r
208                                         } catch( e ) {\r
209                                                 alert(e)\r
210                                                 complete( -1, e );\r
211                                         }\r
212                                         };\r
213                                         \r
214                                         if ( !s.async ) {\r
215                                                 // if we're in sync mode we fire the callback\r
216                                                 callback();\r
217                                         } else if ( xhr.readyState === 4 ) {\r
218                                                 // (IE6 & IE7) if it's in cache and has been\r
219                                                 // retrieved directly we need to fire the callback\r
220                                                 setTimeout( callback );\r
221                                         } else {\r
222                                                 // Add to the list of active xhr callbacks\r
223                                                 xhr.onreadystatechange = callback;\r
224                                         }\r
225                                         \r
226                                 },\r
227                                 abort: function() {}\r
228                         };\r
229                 });\r
230         }\r
231 })( jQuery );\r
232          \r
233 /*\r
234  * jQuery outside events - v1.1 - 3/16/2010\r
235  * http://benalman.com/projects/jquery-outside-events-plugin/\r
236  * \r
237  * Copyright (c) 2010 "Cowboy" Ben Alman\r
238  * Dual licensed under the MIT and GPL licenses.\r
239  * http://benalman.com/about/license/\r
240  * \r
241  * Modified by Bob Hanson for JSmol-specific events and to add parameter reference to actual jQuery event.\r
242  * Used for closing the pop-up menu.\r
243  *   \r
244  */\r
245 \r
246 ;(function($,doc,eventList,id){  \r
247         // was 'click dblclick mousemove mousedown mouseup mouseover mouseout change select submit keydown keypress keyup'\r
248         $.map(\r
249                 eventList.split(' '),\r
250                 function( event_name ) { jq_addOutsideEvent( event_name ); }\r
251         );\r
252         jq_addOutsideEvent( 'focusin',  'focus' + id );\r
253         jq_addOutsideEvent( 'focusout', 'blur' + id );\r
254         function jq_addOutsideEvent( event_name, outside_event_name ) {\r
255                 outside_event_name = outside_event_name || event_name + id;\r
256                 var elems = $(),\r
257                         event_namespaced = event_name + '.' + outside_event_name + '-special-event';\r
258                 $.event.special[ outside_event_name ] = {    \r
259                         setup: function(){\r
260                                 elems = elems.add( this );\r
261                                 if ( elems.length === 1 ) {\r
262                                         $(doc).bind( event_namespaced, handle_event );\r
263                                 }\r
264                         },\r
265                         teardown: function(){\r
266                                 self.Jmol && Jmol._setMouseOwner(null);\r
267                                 elems = elems.not( this );\r
268                                 if ( elems.length === 0 ) {\r
269                                         $(doc).unbind( event_namespaced );\r
270                                 }\r
271                         },\r
272                         add: function( handleObj ) {\r
273                                 var old_handler = handleObj.handler;\r
274                                 handleObj.handler = function( event, elem ) {\r
275                                         event.target = elem;\r
276                                         old_handler.apply( this, arguments );\r
277                                 };\r
278                         }\r
279                 };\r
280                 function handle_event( event ) {\r
281                         $(elems).each(function(){\r
282                                 self.Jmol && (outside_event_name.indexOf("mouseup") >= 0 || outside_event_name.indexOf("touchend") >= 0) && Jmol._setMouseOwner(null);\r
283                                 var elem = $(this);\r
284                                 if ( this !== event.target && !elem.has(event.target).length ) {\r
285                                         //BH: adds event to pass that along to our handler as well.\r
286                                         elem.triggerHandler( outside_event_name, [ event.target, event ] );\r
287                                 }\r
288                         });\r
289                 };\r
290         };\r
291 })(jQuery,document,"click mousemove mouseup touchmove touchend", "outjsmol");\r