PageSourceSearch

https://realtorchad.ca/__ext.js?c=8&r=js+weblets+responsive+menu.j…form.min.js,js+weblets+responsive+forms.js,

js realtorchad.ca collected 2026-10-07 05:01:07 UTC 124,964 bytes, 3,429 lines download raw bytes

1
2
3/* ==== INCLUDE: /js/weblets/responsive/menu.js ==== */
4
5jQuery( function($) {
6	
7	function calcHorizontalLeaning( $menuitem ) {
8		
9		var left = $menuitem.offset().left;
10		var width = $menuitem.outerWidth();
11		var screen = $(document).width();
12		
13		var rightEdge = screen - ( left + width );
14		var tolerance = screen / 4; // quarter of screen
15		console.log( "rightedge", rightEdge, "tolerance", tolerance );
16		if( rightEdge < tolerance ) {
17			return "left";
18		}
19		else {
20			return "";
21		}
22	}
23		
24	$( document ).on ( "click", ".mrp-menu-resp-wrapper .top-handle", function( e ) {
25		e.stopImmediatePropagation();
26		$(this).toggleClass( "on" );
27		$("html").toggleClass( "mrp-menu-on" );
28		return false;
29	});
30	
31	$( document ).on( "click", ".mrp-menu-resp-wrapper li", function(e) {
32		//if( e.target && e.target.nodeName && e.target.nodeName.toLowerCase() == "a" ) {
33		if( e.target && e.target.nodeName && $(e.target).closest("a").length > 0 ) {
34			var $target = $(e.target).closest("a");
35			if( $target.attr( "href" ) && $target.attr( "href" ) != "javascript:;" ) {
36				return;
37			}
38		}
39		var $on = $( this ).closest( "li" );
40		var $menu = $(this).closest( ".mrp-menu-resp-wrapper" );
41		if( $on.hasClass( "on" ) ) {
42			$on.parent().removeClass( "on" );
43			$on.removeClass( "on" );
44			$on.find( ".on" ).removeClass( "on left" );
45			return false;
46		}
47		$menu.find( "li.on" ).filter( function() {
48			return !( $.contains( this, $on[0] ) ); // this not $(this)!! it's correct
49		}).removeClass( "on left" ).parent().removeClass( "on" );
50		
51		$on.addClass( "on" );
52		$on.addClass( calcHorizontalLeaning( $on ) );
53		$on.parent().addClass( "on" );
54		
55		return false;
56	});
57	
58	$( document ).on( "click.mrp-menu-close", function() {
59		$( ".mrp-menu-resp-wrapper .on" ).removeClass( "on left" );
60		$("html").removeClass( "mrp-menu-on" );
61	});
62});
63
64/* ==== INCLUDE: /w/w=realtorchad.ca/dwr/engine.js ==== */
65
66/*
67 * Copyright 2005 Joe Walker
68 *
69 * Licensed under the Apache License, Version 2.0 (the "License");
70 * you may not use this file except in compliance with the License.
71 * You may obtain a copy of the License at
72 *
73 *     http://www.apache.org/licenses/LICENSE-2.0
74 *
75 * Unless required by applicable law or agreed to in writing, software
76 * distributed under the License is distributed on an "AS IS" BASIS,
77 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
78 * See the License for the specific language governing permissions and
79 * limitations under the License.
80 */
81
82/**
83 * The DWR object is also defined by dwr.util etc.
84 */
85if (typeof dwr == 'undefined') dwr = {};
86
87(function() {
88  if (!dwr.engine) dwr.engine = {};
89
90  /**
91    * Set an alternative error handler from the default alert box.
92    * @param {Function} handler The function to call when an error happens
93    */
94  dwr.engine.setErrorHandler = function(handler) {
95    dwr.engine._errorHandler = handler;
96  };
97
98  /**
99    * Set an alternative warning handler from the default alert box.
100    * @param {Function} handler The function to call when a warning happens
101    */
102  dwr.engine.setWarningHandler = function(handler) {
103    dwr.engine._warningHandler = handler;
104  };
105
106  /**
107    * @deprecated - In favor of the errorHandler being called with an exception name:"dwr.engine.textHtmlReply"
108    * containing a responseText property if available.
109    *
110    * Setter for the text/html handler - what happens if a DWR request gets an HTML
111    * reply rather than the expected Javascript. Often due to login timeout
112    * @param {Function} handler The function to call on an unexpected text/html content type
113    */
114  dwr.engine.setTextHtmlHandler = function(handler) {
115    dwr.engine._textHtmlHandler = handler;
116  };
117
118  dwr.engine.setPollStatusHandler = function(handler) {
119    dwr.engine._pollStatusHandler = handler;
120  };
121
122  /**
123   * Set a default timeout value for all calls. 0 (the default) turns timeouts off.
124   * @param {Function} handler The function to call when we get bored of waiting for a call
125   */
126  dwr.engine.setTimeout = function(timeout) {
127    dwr.engine._timeout = timeout;
128  };
129
130  /**
131   * Set a timeout value for Reverse Ajax polls. 0 (the default) turns timeouts off.
132   */
133  dwr.engine.setPollTimeout = function(timeout) {
134    dwr.engine._pollTimeout = timeout;
135  };
136
137  /**
138    * The Pre-Hook is called before any DWR remoting is done.
139    * @param {Function} handler The function to call before any remote calls
140    */
141  dwr.engine.setPreHook = function(handler) {
142    dwr.engine._preHook = handler;
143  };
144
145  /**
146   * The Post-Hook is called after any DWR remoting is done.
147   * @param {Function} handler The function to call after any remote calls
148   */
149  dwr.engine.setPostHook = function(handler) {
150    dwr.engine._postHook = handler;
151  };
152
153  /**
154   * Set a custom path to the DWR servlet (may be a full URL for cross-domain usage)
155   * @param {string} path path or URL
156   */
157  dwr.engine.setOverridePath = function(path) {
158    dwr.engine._overridePath = path;
159  };
160
161  /**
162   * Set a custom contextPath (typically used when rewriting paths through a web server)
163   * @param {string} path path
164   */
165  dwr.engine.setOverrideContextPath = function(path) {
166    dwr.engine._overrideContextPath = path;
167  };
168
169  /**
170   * Extra attributes to append to the DWRSESSIONID cookie (domain, secure, etc)
171   * @param {string} attributeString attribute string according to cookie syntax
172   */
173  dwr.engine.setCookieAttributes = function(attributeString) {
174    dwr.engine._cookieAttributes = attributeString;
175  };
176
177  /**
178   * Custom headers for all DWR calls
179   * @param {Object} headers Object containing name/value pairs for extra headers
180   */
181  dwr.engine.setHeaders = function(headers) {
182    dwr.engine._headers = headers;
183  };
184
185  /**
186   * Custom attributes transferred to server for all DWR calls
187   * @param {Object} attributes Object containing name/value pairs for attributes
188   */
189  dwr.engine.setAttributes = function(attributes) {
190    dwr.engine._attributes = attributes;
191  };
192
193  /**
194   * Ensure that remote calls happen in the order in which they were sent? (Default: false)
195   * @param {boolean} ordered true to enable ordered processing
196   */
197  dwr.engine.setOrdered = function(ordered) {
198    dwr.engine._ordered = ordered;
199  };
200
201  /**
202   * Do we ask the XHR object to be asynchronous? (Default: true)
203   * Warning: it is <strong>highly</strong> advised to use the default of async
204   * processing, especially when dealing with Internet based requests.
205   * @param {boolean} async false to enable sync processing for XHR queries
206   */
207  dwr.engine.setAsync = function(async) {
208    dwr.engine._async = async;
209  };
210
211  /**
212   * Does the client actively check the server for updates? (Default: false)
213   * @param {boolean} async true to enable low latency reverse ajax
214   */
215  dwr.engine.setActiveReverseAjax = function(activeReverseAjax) {
216    if (activeReverseAjax) {
217      // Bail if we are already started
218      if (dwr.engine._activeReverseAjax) return;
219      // We always want a retry policy when reverse AJAX is enabled.
220      if (!dwr.engine._retryIntervals || dwr.engine._retryIntervals.length === 0) { dwr.engine._retryIntervals = dwr.engine._defaultRetryIntervals; }
221      dwr.engine._activeReverseAjax = true;
222      if (dwr.engine._initializing) return; // We'll start after init is done
223      dwr.engine._poll();
224    }
225    else {
226      // Can we cancel an existing request?
227      if (dwr.engine._activeReverseAjax && dwr.engine._pollBatch) {
228        dwr.engine.transport.abort(dwr.engine._pollBatch);
229      }
230      dwr.engine._activeReverseAjax = false;
231    }
232    // TODO: in iframe mode, if we start, stop, start then the second start may
233    // well kick off a second iframe while the first is still about to return
234    // we should cope with this but we don't
235  };
236
237  /**
238   * Turn server notification of page unload on and off
239   * @param {boolean} notify true or false depending on if we want to turn unload notification on or off
240   */
241  dwr.engine.setNotifyServerOnPageUnload = function(notify, asyncUnload) {
242    dwr.engine._asyncUnload = (asyncUnload !== undefined) ? asyncUnload : false;
243    dwr.engine._isNotifyServerOnPageUnload = notify;
244  };
245
246  /**
247   * Turn server notification of page load on and off
248   * @param {boolean} notify true or false depending on if we want to turn load notification on or off
249   */
250  dwr.engine.setNotifyServerOnPageLoad = function(notify) {
251    dwr.engine._isNotifyServerOnPageLoad = notify;
252    if (notify && !dwr.engine._initializing && !dwr.engine._isNotifyServerOnPageLoadSent) {
253      eval("dwr.engine._execute(dwr.engine._pathToDwrServlet, '__System', 'pageLoaded', [ function() { dwr.engine._ordered = false; }]);");
254      dwr.engine._isNotifyServerOnPageLoadSent = true;
255    }
256  };
257
258  /*
259   * The maximum number of retries, when reached we will no longer attempt to check for server status.
260   * @param - maxRetries
261   */
262  dwr.engine.setMaxRetries = function(maxRetries) {
263    dwr.engine._maxRetries = maxRetries;
264  };
265
266  /*
267   * The intervals between successive retries in seconds
268   * @param - array of integers representing the retry interval in seconds.
269   */
270  dwr.engine.setRetryIntervals = function(intervalsArray) {
271    dwr.engine._retryIntervals = intervalsArray;
272  };
273
274  /**
275   * The default message handler.
276   * @param {String} message The text of the error message
277   * @param {Object}
277 ex An error object containing at least a name and message
278   */
279  dwr.engine.defaultErrorHandler = function(message, ex) {
280    dwr.engine._debug("Error: " + ex.name + ", " + ex.message, true);
281    if (!message) message = "A server error has occurred.";
282    // Ignore NS_ERROR_NOT_AVAILABLE if Mozilla is being narky
283    if (message.indexOf("0x80040111") != -1) return;
284    if ("true" == "true") alert(message);
285  };
286
287  /**
288   * The default warning handler.
289   * @param {String} message The text of the error message
290   * @param {Object} ex An error object containing at least a name and message
291   */
292  dwr.engine.defaultWarningHandler = function(message, ex) {
293    dwr.engine._debug(message);
294  };
295
296  /**
297   * The default poll status handler.
298   * @param {boolean} newStatus - true = online, false = offline
299   * @param {object} ex - The exception if one exists (offline).
300   */
301  dwr.engine.defaultPollStatusHandler = function(newStatus, ex) {
302    dwr.engine.util.logHandlerEx(function() {
303      if (newStatus === false && dwr.engine._errorHandler) dwr.engine._errorHandler(ex.message, ex);
304    });
305  };
306
307  /**
308   * For reduced latency you can group several remote calls together using a batch.
309   */
310  dwr.engine.beginBatch = function() {
311    if (dwr.engine._batch) {
312      dwr.engine._handleError(null, { name:"dwr.engine.batchBegun", message:"Batch already begun" });
313      return;
314    }
315    dwr.engine._batch = dwr.engine.batch.create();
316  };
317
318  /**
319   * Finished grouping a set of remote calls together. Go and execute them all.
320   * @param {Object} options A options object to customize processing
321   */
322  dwr.engine.endBatch = function(options) {
323    var batch = dwr.engine._batch;
324    if (batch == null) {
325      dwr.engine._handleError(null, { name:"dwr.engine.batchNotBegun", message:"No batch in progress" });
326      return;
327    }
328    dwr.engine._batch = null;
329    if (batch.map.callCount === 0) {
330      return;
331    }
332
333    // The hooks need to be merged carefully to preserve ordering
334    if (options) {
335      dwr.engine.batch.merge(batch, options);
336    }
337
338    // In ordered mode, we don't send unless the list of sent items is empty
339    // (queuing is not possible for sync calls so let them slip through)
340    if (batch.async && (dwr.engine._ordered || dwr.engine._internalOrdered) && dwr.engine._batchesLength !== 0) {
341      dwr.engine._batchQueue[dwr.engine._batchQueue.length] = batch;
342    }
343    else {
344      return dwr.engine.transport.send(batch);
345    }
346  };
347
348  /**
349   * For use with file downloads. When a DWR function returns a binary download
350   * you can prompt the user to save it using this function
351   * @param {Object} data The binary data passed from DWR
352   */
353  dwr.engine.openInDownload = function(data) {
354    var div = document.createElement("div");
355    document.body.appendChild(div);
356    div.innerHTML = "<iframe width='0' height='0' scrolling='no' frameborder='0' src='" + data + "'></iframe>";
357  };
358
359  /**
360   * What is the current version DWR number
361   * DWR version numbers are of the form "Version 1.2.3.3128[.beta]", where:
362   * 1 is the major release number. Changes in major version number indicate
363   * significant enhancements in functionality
364   * 2 is the minor release number. Changes in minor version number indicate
365   * less significant changes in functionality
366   * 3 is the revision release number. Changes here typically indicate bug
367   * fixes only
368   * 3128 is the build number. This number increments for each build
369   * .beta is a release title that is generally only used for non production
370   * releases to indicate the purpose/quality of the release
371   * The label is these strings concatenated
372   */
373  dwr.version = {
374    /**
375     * Changes in major version number indicate significant enhancements
376     */
377    major:parseInt("3", 10),
378
379    /**
380     * Changes in minor version number indicate smaller enhancements
381     */
382    minor:parseInt("0", 10),
383
384    /**
385     * Changes with the revision number typically indicate bug-fixes only
386     */
387    revision:parseInt("3", 10),
388
389    /**
390     * The build number increments for each build
391     */
392    build:parseInt("-1", 10),
393
394    /**
395     * Only used for non production releases to indicate the purpose/quality of
396     * the release. Example titles include 'milestone1' or 'beta3'.
397     */
398    title:"dev",
399
400    /**
401     * The strings above concatenated
402     */
403    label:"3.0.3-dev"
404  };
405
406  //==============================================================================
407  // Only private stuff below here
408  //==============================================================================
409
410  /** Keep track of page load initialization */
411  dwr.engine._initializing = true;
412
413  /** Is GET enabled? */
414  dwr.engine._allowGetButMakeForgeryEasier = "true";
415
416  /** The script prefix to strip in the case of scriptTagProtection. */
417  dwr.engine._scriptTagProtection = "throw 'allowScriptTagRemoting is false.';";
418
419  /** The default path to the DWR servlet */
420  dwr.engine._pathToDwrServlet = "/w/w=realtorchad.ca/dwr";
421
422  /** Custom path to the DWR servlet */
423  dwr.engine._overridePath = "";
424  if (typeof pathToDwrServlet != "undefined") {
425    dwr.engine._overridePath = pathToDwrServlet;
426  }
427  
428  dwr.engine._effectivePath = function() {
429    return dwr.engine._overridePath || dwr.engine._pathToDwrServlet;
430  };
431
432  /** The webapp's contextPath */
433  dwr.engine._contextPath = "";
434
435  /** Custom contextPath */
436  dwr.engine._overrideContextPath = "";
437
438  dwr.engine._effectiveContextPath = function() {
439    return dwr.engine._overrideContextPath || dwr.engine._contextPath;
440  };
441
442  /** Extra attributes to append to the DWRSESSIONID cookie (domain, secure, etc) */
443  dwr.engine._cookieAttributes = "";
444
445  /** Do we use XHR for reverse ajax because we are not streaming? */
446  dwr.engine._useStreamingPoll = "true";
447
448  dwr.engine._pollOnline = true;
449
450  /** These URLs can be configured from the server */
451  dwr.engine._ModePlainCall = "/call/plaincall/";
452  dwr.engine._ModePlainPoll = "/call/plainpoll/";
453  dwr.engine._ModeHtmlCall = "/call/htmlcall/";
454  dwr.engine._ModeHtmlPoll = "/call/htmlpoll/";
455
456  /** Do we make the calls async? Default to 'true' */
457  dwr.engine._async = Boolean("true");
458
459  /** The local page id */
460  dwr.engine._pageId = null;
461
462  /** The browser instance id */
463  dwr.engine._dwrSessionId = null;
464
465  /** The global page id (browser instance + local page id) */
466  dwr.engine._scriptSessionId = ""; // we must use "" and not null
467
468  /** A function to be called before requests are marshalled. Can be null. */
469  dwr.engine._preHook = null;
470
471  /** A function to be called after replies are received. Can be null. */
472  dwr.engine._postHook = null;
473
474  /** A map of the batches that we have sent and are awaiting a reply on. */
475  dwr.engine._batches = {};
476
477  /** A count of the number of outstanding batches. Should be == to _batches.length unless prototype has messed things up */
478  dwr.engine._batchesLength = 0;
479
480  /** In ordered mode, the array of batches waiting to be sent */
481  dwr.engine._batchQueue = [];
482
483  /** User setting for saying that calls should execute one by one in the order in which they were sent */
484  dwr.engine._ordered = false;
485
486  /** Internal state forcing calls to execute one by one in the order in which they were sent */
487  dwr.engine._internalOrdered = false;
488
489  /** The current batch (if we are in batch mode) */
490  dwr.engine._batch = null;
491
492  /** The global timeout */
493  dwr.engine._timeout = 0;
494
495  /** Are we doing comet or polling? */
496  dwr.engine._activeReverseAjax = false;
497  
498  /** All reverse ajax scripts before this index have been received and executed */
499  dwr.engine._nextReverseAjaxIndex = 0;
500  
501  /** Queue of reverse ajax scripts (functions) that have been received but not yet executed due to receiving in wrong order */
502  dwr.engine._reverseAjaxQueue = {};
503  
504  /** The batch that we are using to poll */
505  dwr.engine._pollBatch = null;
506
507  /** Maximum time we wait for a poll to return (0 = no timeout) */
508  dwr.engine._pollTimeout = 0;
509
510  /** How many milliseconds between internal comet polls */
511  dwr.engine._pollCometInterval = 200;
512
513  /** How many times have we re-tried a call? */
514  dwr.engine._retries = 1;
515  dwr.engine._maxRetries = -1;
516
517  /** The intervals between successive retries in seconds */
518  dwr.engine._retryIntervals = [];
519
520  /** Used as the default for reverse ajax/polling
521   *  Retry immediately twice first with a one second interval, next with a 3 second interval, then go offline.
522   *  Therafter, retry every 3 seconds.
523   */
524  dwr.engine._defaultRetryIntervals = [ 1, 3, 3 ];
525
526  dwr.engine._textHtmlHandler = null;
527
528  /** If you wish to send custom headers with every request */
529  dwr.engine._headers = null;
530
531  /** If you wish to send extra custom request attributes with each request */
532  if (typeof attributes != "undefined") {
533    dwr.engine._attributes = attributes;
534  }
535  else {
536    dwr.engine._attributes = null;
537  }
538
539  /** Batch ids allow us to know which batch the server is answering */
540  dwr.engine._nextBatchId = 0;
541
542  /** The instance id helps us distinguish multiple engine.js loaded in one page */
543  dwr.engine._instanceId = -1;
544
545  /** A list of the properties that need merging from calls to a batch */
546  dwr.engine._propnames = [ "async", "timeout", "errorHandler", "warningHandler", "textHtmlHandler" ];
547
548  /** Do we stream, or can be hacked to do so? */
549  dwr.engine._partialResponseNo = 0;
550  dwr.engine._partialResponseYes = 1;
551
552  /** Are we notifying the server on page unload? */
553  dwr.engine._isNotifyServerOnPageUnload = false;
554
555  /** Are we notifying the server on page load? */
556  dwr.engine._isNotifyServerOnPageLoad = false;
557  dwr.engine._isNotifyServerOnPageLoadSent = false;
558
559  /** Should the unload call be asynchronous?  If true it may not be called by the browser. */
560  dwr.engine._asyncUnload = false;
561
562  /**
563   * A map of all mapped classes whose class declarations have been loaded
564   * (dwrClassName -> constructor function)
565   */
566  dwr.engine._mappedClasses = {};
567
568  /** A function to call if something fails. */
569  dwr.engine._errorHandler = dwr.engine.defaultErrorHandler;
570
571  /** For debugging when something unexplained happens. */
572  dwr.engine._warningHandler = dwr.engine.defaultWarningHandler;
573
574  dwr.engine._pollStatusHandler = dwr.engine.defaultPollStatusHandler;
575
576  /** Undocumented interceptors - do not use */
577  dwr.engine._postSeperator = "\n";
578  dwr.engine._defaultInterceptor = function(data) { return data; };
579  dwr.engine._urlRewriteHandler = dwr.engine._defaultInterceptor;
580  dwr.engine._contentRewriteHandler = dwr.engine._defaultInterceptor;
581  dwr.engine._replyRewriteHandler = dwr.engine._defaultInterceptor;
582
583  /** Object attributes to ignore when serializing */
584  dwr.engine._excludeObjectAttributes = {
585    "$dwrClassName": true,
586    "$dwrByRef": true,
587    "$_dwrConversionRef": true
588  };
589
590  dwr.engine._ieConditions = {};
591  
592  /** Is this page doing beforeunload processing? */
593  dwr.engine._beforeUnloading = false;
594
595  /** A place to temporarily store exception before reporting */
596  dwr.engine._queuedBatchException = null;
597
598  /** @private Keep beforeunload flag set during beforeunload processing (including potential
599   *  "Are you sure?" popups). */
600  dwr.engine._beforeUnloader = function() {
601    dwr.engine._beforeUnloading = true;
602    // We want to reset the flag if unloading is aborted by "Are you sure?" popup. We detect
603    // return to interactive mode with a timeout that normally will execute directly after
604    // unload is aborted through popup.
605    setTimeout(function() {
606      // Some browsers (f ex Firefox) will execute the timeout even if unload is not aborted.
607      // To keep a continuous unloading state we therefore prolong the beforeunload state for
608      // a second so the unload flag gets time to trigger.
609      setTimeout(function() {
610        dwr.engine._beforeUnloading = false;
611      }, 1000);
612    }, 1);
613  };
614
615  /** Is this page in the process of unloading? */
616  dwr.engine._unloading = false;
617
618  /** @private Abort any XHRs in progress at page unload (solves zombie socket problems in IE). */
619  dwr.engine._unloader = function() {
620    dwr.engine._unloading = true;
621
622    // Empty queue of waiting ordered requests
623    dwr.engine._batchQueue.length = 0;
624
625    // Abort any ongoing requests and clear their batches
626    var batch;
627    for (var batchId in dwr.engine._batches) {
628      batch = dwr.engine._batches[batchId];
629      if (batch.transport && batch.transport.abort) {
630        batch.transport.abort(batch);
631      }
632    }
633
634    // If we have used reverse ajax then we try to tell the server we are gone
635    if (dwr.engine._isNotifyServerOnPageUnload) {
636      dwr.engine._debug("calling unloader for: " + dwr.engine._scriptSessionId);
637      batch = {
638        map:{
639          callCount:1,
640          'c0-scriptName':'__System',
641          'c0-methodName':'pageUnloaded',
642          'c0-id':0
643        },
644        paramCount:0, isPoll:false, async:dwr.engine._asyncUnload,
645        headers:{}, preHooks:[], postHooks:[],
646        timeout:dwr.engine._timeout,
647        errorHandler:null, globalErrorHandler:dwr.engine._errorHandler, warningHandler:null, textHtmlHandler:null, globalTextHtmlHandler:null,
648        handlers:[{ exceptionHandler:null, callback:null }]
649      };
650      dwr.engine.transport.send(batch);
651      dwr.engine._isNotifyServerOnPageUnload = false;
652    }
653  };
654
655  function ignoreIfUnloading(batch, f) {
656    // Do nothing if we are unloading
657    if (dwr.engine._unloading) return;
658    // Retry later if beforeunload is in progress and this is not a sync call
659    if (dwr.engine._beforeUnloading && (batch == null || batch.async)) {
660      setTimeout(function() {
661        ignoreIfUnloading(batch, f);
662      }, 100);
663    }
664    // Otherwise trigger the target func
665    else {
666      return f();
667    }
668  }
669
670  dwr.engine._initializer = {
671    /*
672     * Load-time initializations
673     */
674    preInit: function() {
675      // Make random local page id
676      dwr.engine._pageId = dwr.engine.util.tokenify(new Date().getTime()) + "-" + dwr.engine.util.tokenify(Math.random() * 1E16);
677
678      // Reuse any existing dwr session
679      dwr.engine.transport.updateDwrSessionFromCookie();
680
681      // Register unload handlers
682      dwr.engine.util.addEventListener(window, 'beforeunload', dwr.engine._beforeUnloader);
683      dwr.engine.util.addEventListener(window, 'unload', dwr.engine._unloader);
684
685      // Register this engine instance globally
686      var g = dwr.engine._global;
687      if (!g.dwr) g.dwr = {};
688      if (!g.dwr._) g.dwr._ = [];
689      dwr.engine._instanceId = g.dwr._.length;
690      g.dwr._[dwr.engine._instanceId] = dwr;
691    },
692
693    loadDwrConfig: function() {
694      if (typeof dwrConfig != "undefined") {
695        for(p in dwrConfig) {
696          var methodName = "set" + p.charAt(0).toUpperCase() + p.substring(1);
697          var setter = dwr.engine[methodName];
698          if (setter) setter(dwrConfig[p]);
699        }
700      }
701    },
702    
703    init: function() {
704      dwr.engine._initializer.preInit();
705      dwr.engine._initializer.loadDwrConfig();
706      dwr.engine._initializing = false;
707      // Now we can start sending requests
708      if (dwr.engine._isNotifyServerOnPageLoad) {
709        eval("dwr.engine._execute(dwr.engine._pathToDwrServlet, '__System', 'pageLoaded', [ function() { dwr.engine._ordered = false; }]);");
710        dwr.engine._isNotifyServerOnPageLoadSent = true;
711      }
712      if (dwr.engine._activeReverseAjax) {
713        dwr.engine._poll();
714      }
715    }
716  };
717
718  /**
719   * Send a request. Called by the JavaScript interface stub
720   * @private
721   * @param path part of URL after the host and before the exec bit without leading or trailing /s
722   * @param scriptName The class to execute
723   * @param methodName The method on said class to execute
724   * @param func The callback function to which any returned data should be passed
725   *       if this is null, any returned data will be ignored
726   * @param args The parameters to passed to the above method
727   */
728  dwr.engine._execute = function(overridePath, scriptName, methodName, args) {
729    var path = overridePath || dwr.engine._effectivePath();
730    dwr.engine._singleShot = false;
731    if (dwr.engine._batch == null) {
732      dwr.engine.beginBatch();
733      dwr.engine._singleShot = true;
734    }
735
736    var batch = dwr.engine._batch;
737
738    // All the paths MUST be to the same servlet
739    if (batch.path == null) {
740      batch.path = path;
741    }
742    else {
743      if (batch.path != path) {
744        dwr.engine._handleError(batch, { name:"dwr.engine.multipleServlets", message:"Can't batch requests to multiple DWR Servlets." });
745        return;
746      }
747    }
748
749    dwr.engine.batch.addCall(batch, scriptName, methodName, args);
750
751    if (dwr.engine._isHeartbeatBatch(batch)) {
752      // Heartbeats should fail fast.
753      batch.timeout = 750;
754    }
755
756    // Now we have finished remembering the call, we increment the call count
757    batch.map.callCount++;
758    if (dwr.engine._singleShot) {
759      return dwr.engine.endBatch();
760    }
761  };
762
763  /**
764   * Poll the server to see if there is any data waiting
765   * @private
766   */
767  dwr.engine._poll = function() {
768    if (!dwr.engine._activeReverseAjax) {
769      return;
770    }
771    dwr.engine._pollBatch = dwr.engine.batch.createPoll();
772    dwr.engine.transport.send(dwr.engine._pollBatch);
773  };
774
775  /** @private Utility to execute incoming scripts */
776  dwr.engine._executeScript = function(script) {
777    if (script == null) {
778      return null;
779    }
780    if (script === "") {
781      dwr.engine._debug("Warning: blank script", true);
782      return null;
783    }
784    // Using Function instead of eval as the latter has memory problems on IE9
785    (new Function("dwr", script))(dwr);
786  };
787
788  /** @private call all the post hooks for a batch */
789  dwr.engine._callPostHooks = function(batch) {
790    if (batch.postHooks) {
791      for (var i = 0; i < batch.postHooks.length; i++) {
792        batch.postHooks[i]();
793      }
794      batch.postHooks = null;
795    }
796  };
797
798  /**
799   * Is this a batch that is checking for a heartbeat?
800   * If so we want to ignore errors/warnings, etc.
801   * @private
802   * @param {Object} batch
803   */
804  dwr.engine._isHeartbeatBatch = function(batch) {
805    return (batch.map && batch.map['c0-methodName'] === 'checkHeartbeat' && batch.map['c0-scriptName'] === '__System');
806  };
807
808  /**
809   * Generic error handling routing to save having null checks everywhere
810   * @private
811   * @param {Object} batch
812   * @param {Object} ex
813   */
814  dwr.engine._handleError = function(batch, ex) {
815    if (batch && dwr.engine._isHeartbeatBatch(batch)) { // Ignore errors that happen while checking for a heartbeat.
816      return;
817    }
818    var errorHandlers = [];
819    var anyCallWithoutErrorHandler = false;
820    if (batch && batch.isPoll) { // No error reporting and only retry for polls
821      dwr.engine._handlePollRetry(batch, ex);
822    } else {
823      // Perform error cleanup synchronously
824      if (batch) {
825        for (var i = 0; i < batch.map.callCount; i++) {
826          var handlers = batch.handlers[i];
827          if (!handlers.completed) {
828            if (typeof handlers.errorHandler == "function")
829              errorHandlers.push(handlers.errorHandler);
830            else
831              anyCallWithoutErrorHandler = true;
832            handlers.completed = true;
833          }
834        }
835      }
836      // Perform error reporting asynchronously (possibly)
837      ignoreIfUnloading(batch, function() {
838        if (batch) {
839          var textHtmlHandler = batch.textHtmlHandler || batch.globalTextHtmlHandler;
840          if (ex.name === "dwr.engine.textHtmlReply" && textHtmlHandler) {
841            dwr.engine.util.logHandlerEx(function() {
842              textHtmlHandler(ex);
843            });
844            return;
845          }
846        }
847        dwr.engine._prepareException(ex);
848        var errorHandler;
849        while(errorHandlers.length > 0) {
850          errorHandler = errorHandlers.shift();
851          dwr.engine.util.logHandlerEx(function() {
852            errorHandler(ex.message, ex);
853          });
854        }
855        if (batch) {
856          dwr.engine.util.logHandlerEx(function() {
857            if (typeof batch.errorHandler == "function") batch.errorHandler(ex.message, ex);
858            else if (anyCallWithoutErrorHandler) {
859              if (typeof batch.globalErrorHandler == "function") batch.globalErrorHandler(ex.message, ex);
860            }
861          });
862          dwr.engine.batch.remove(batch);
863        }
864      });
865    }
866  };
867
868  /**
869   * Handle retries for polling as well as online/offline status.
870   * @private
871   * @param {Object} batch
872   * @param {Object} ex
873   */
874  dwr.engine._handlePollRetry = function(batch, ex) {
875      var retryInterval = dwr.engine._getRetryInterval();
876      // If number of retries is equal to the retryIntervals array length, call the supplied pollStatusHandler and go offline.
877      if (dwr.engine._retries === dwr.engine._retryIntervals.length - 1) {
878        dwr.engine._debug("poll retry - going offline: " + retryInterval/1000 + " seconds");
879        dwr.engine._handlePollStatusChange(false, ex, batch);
880        // We are offline, continue to check for a heartbeat until _retries is > _maxRetries.
881        var heartbeatInterval = setInterval(function() {
882          if (dwr.engine._maxRetries === -1 || dwr.engine._retries < dwr.engine._maxRetries) {
883            dwr.engine._execute(null, '__System', 'checkHeartbeat', [ function() {
884              // We found a heartbeat, we are back online!
885              clearInterval(heartbeatInterval);
886              dwr.engine._poll();
887            }]);
888            dwr.engine._retries++;
889            dwr.engine._debug("DWR Offline - poll retry - interval: " + retryInterval/1000 + " seconds");
890          } else {
891            // maxRetries has been reached, stop the heartbeat check.
892            clearInterval(heartbeatInterval);
893            dwr.engine._debug("max retries reached, stop polling for server status.");
894            dwr.engine._handlePollStatusChange(false, ex, batch);
895          }
896        }, retryInterval);
897      } else { // We are still online, poll again.
898        dwr.engine._retries++;
899        dwr.engine.batch.remove(batch);
900        dwr.engine._debug("DWR Online - poll retry - interval: " + retryInterval/1000 + " seconds");
901        setTimeout(dwr.engine._poll, retryInterval);
902      }
903  };
904
905  dwr.engine._getRetryInterval = function() {
906    var retryInterval;
907    if (dwr.engine._retries < dwr.engine._retryIntervals.length) {
908      retryInterval = dwr.engine._retryIntervals[dwr.engine._retries] * 1000;
909    } else {
910      // The last interval in retryIntervals is the number that will be used to poll when offline.
911      retryInterval = dwr.engine._retryIntervals[dwr.engine._retryIntervals.length - 1] * 1000;
912    }
913    return retryInterval;
914  };
915
916  /**
917   * Handles polling status changes - online or offline.
918   * @param {boolean} newStatus - true = online, false = offline
919   * @param {object} ex - The exception if one exists (offline).
920   */
921  dwr.engine._handlePollStatusChange = function(newStatus, ex, batch) {
922  if (batch.isPoll || dwr.engine._isHeartbeatBatch(batch)) {
923      var changed = dwr.engine._pollOnline !== newStatus;
924      var maxRetriesReached = dwr.engine._maxRetries === dwr.engine._retries;
925      dwr.engine._pollOnline = newStatus;
926      if ((changed || maxRetriesReached) && typeof dwr.engine._pollStatusHandler === "function") 
927        dwr.engine.util.logHandlerEx(function() {
928          dwr.engine._pollStatusHandler(newStatus, ex, maxRetriesReached);
929        });
930      if (newStatus) {
931        dwr.engine._retries = 1;
932      }
933  }
934  };
935
936  /**
937   * Generic error handling routing to save having null checks everywhere.
938   * @private
939   * @param {Object} batch
940   * @param {Object} ex
941   */
942  dwr.engine._handleWarning = function(batch, ex) {
943    if (batch && dwr.engine._isHeartbeatBatch(batch)) { // Ignore warnings that happen while checking for a heartbeat.
944      return;
945    }
946    ignoreIfUnloading(batch, function() {
947      // If this is a poll, we should retry!
948      dwr.engine._prepareException(ex);
949      dwr.engine.util.logHandlerEx(function() {
950        if (batch && typeof batch.warningHandler == "function") batch.warningHandler(ex.message, ex);
951        else if (dwr.engine._warningHandler) dwr.engine._warningHandler(ex.message, ex);
952      });
953      if (batch) dwr.engine.batch.remove(batch);
954    });
955  };
956
957  /**
958   * Prepares an exception for an error/warning handler.
959   * @private
960   * @param {Object} ex
961   */
962  dwr.engine._prepareException = function(ex) {
963    if (typeof ex == "string") ex = { name:"unknown", message:ex };
964    if (ex.message == null) ex.message = "";
965    if (ex.name == null) ex.name = "unknown";
966  };
967
968  /**
969   * Create a new object that delegates to obj
970   * @param obj
971   */
972  dwr.engine._delegate = (function() {
973    function F(){}
974    return (function(obj){
975      F.prototype = obj;
976      return new F();
977    });
978  })();
979
980  /**
981   * Create a new object that delegates to obj
982   * @param obj
983   */
984  dwr.engine._createFromMap = function(map) {
985    var obj = new this(); // this should be set to a constructor function!
986    for(prop in map) if (map.hasOwnProperty(prop)) obj[prop] = map[prop];
987    return obj;
988  };
989
990  /**
991   * A reference to the global context (window when in a browser)
992   */
993  dwr.engine._global = (function(){return this;}).call(null);
994
995  /**
996   * Navigates properties from the global scope and down to fetch a property
997   * value.
998   * @param prop hierarchical property name
999   * @return property value, or undefined if doesn't exist
1000   */
1001  dwr.engine._getObject = function(prop) {
1002    var parts = prop.split(".");
1003    var value = undefined;
1004    var scope = dwr.engine._global;
1005    while(parts.length > 0) {
1006      var currprop = parts.shift();
1007      if (!scope) return undefined;
1008      value = scope[currprop];
1009      if (value && value.tagName && document.getElementById(currprop) == value) return undefined;
1010      scope = value;
1011    }
1012    return value;
1013  };
1014
1015  /**
1016   * Navigates properties from the global scope and down to set a value.
1017   * @param prop hierarchical property name
1018   * @param obj property value to set
1019   */
1020  dwr.engine._setObject = function(prop, obj) {
1021    var parts = prop.split(".");
1022    var level;
1023    var scope = dwr.engine._global;
1024    while(parts.length > 0) {
1025      var currprop = parts.shift();
1026      if (parts.length === 0) {
1027        scope[currprop] = obj;
1028      }
1029      else {
1030        level = scope[currprop];
1031        if (level == null || level.tagName && document.getElementById(currprop) == level) {
1032          scope[currprop] = level = {};
1033        }
1034        scope = level;
1035      }
1036    }
1037  };
1038
1039  /**
1040   * Used internally when some message needs to get to the programmer
1041   * @private
1042   * @param {String} message
1043   * @param {Object} stacktrace
1044   */
1045  dwr.engine._debug = function(message, stacktrace) {
1046    var written = false;
1047    try {
1048      if (window.console) {
1049        if (stacktrace && window.console.trace) window.console.trace();
1050        if (window.console.log) window.console.log(message);
1051        written = true;
1052      }
1053      else if (window.opera && window.opera.postError) {
1054        window.opera.postError(message);
1055        written = true;
1056      }
1057    }
1058    catch (ex) { /* ignore */ }
1059
1060    if (!written) {
1061      var debug = document.getElementById("dwr-debug");
1062      if (debug) {
1063        var contents = message + "<br/>" + debug.innerHTML;
1064        if (contents.length > 2048) contents = contents.substring(0, 2048);
1065        debug.innerHTML = contents;
1066      }
1067    }
1068  };
1069
1070  /**
1071   * Functions called by the server
1072   */
1073  dwr.engine.remote = {
1074    /**
1075     * Execute a callback
1076     * @private
1077     * @param {int} batchId The ID of the batch that we are replying to
1078     * @param {int} callId The call ID that the script relates to
1079     * @param {String} reply The script to execute
1080     */
1081    handleCallback:function(batchId, callId, reply) {
1082      var batch = dwr.engine._batches[batchId];
1083      if (!batch) return;
1084
1085      // We store the reply in the batch so we can return the data when in sync mode
1086      batch.reply = reply;
1087
1088      // Error handlers inside here indicate an error that is nothing to do
1089      // with DWR so we handle them differently.
1090      try {
1091        var handlers = batch.handlers[callId];
1092        if (!handlers) {
1093          dwr.engine._debug("Warning: Missing handlers. callId=" + callId, true);
1094        }
1095        else {
1096          batch.handlers[callId].completed = true;
1097          if (typeof handlers.callback == "function") {
1098            dwr.engine.util.logHandlerEx(function() {
1099              if(handlers.callbackArg !== undefined)
1100        	    handlers.callback.call(handlers.callbackScope, reply, handlers.callbackArg);
1101              else
1102                handlers.callback.call(handlers.callbackScope, reply);
1103            });
1104          }
1105        }
1106      }
1107      catch (ex) {
1108        dwr.engine._handleError(batch, ex);
1109      }
1110    },
1111
1112    /**
1113     * Called by the server when a JavascriptFunction is executed
1114     * @param id The ID of the serialized function
1115     * @param args The arguments to pass to the function
1116     */
1117    handleFunctionCall:function(id, args) {
1118      var func = dwr.engine.serialize.remoteFunctions[id];
1119      func.apply(window, args);
1120    },
1121
1122    /**
1123     * Called by the server when a JavascriptFunction is executed
1124     * @param id The ID of the serialized function
1125     * @param args The arguments to pass to the function
1126     */
1127    handleObjectCall:function(id, methodName, args) {
1128      var obj = dwr.engine.serialize.remoteFunctions[id];
1129      obj[methodName].apply(obj, args);
1130    },
1131
1132    /**
1133     * Called by the server when a JavascriptFunction is executed
1134     * @param propertyName The ID of the serialized function
1135     * @param data The arguments to pass to the function
1136     */
1137    handleSetCall:function(id, propertyName, data) {
1138      var obj = dwr.engine.serialize.remoteFunctions[id];
1139      obj[propertyName] = data;
1140    },
1141
1142    /**
1143     * Called by the server when a JavascriptFunction is closed
1144     * @param id The ID of the serialized function
1145     */
1146    handleFunctionClose:function(id) {
1147      delete dwr.engine.serialize.remoteFunctions[id];
1148    },
1149
1150    /**
1151     * Called by the server: Handle an exception for a call
1152     * @private
1153     * @param {int} batchId The ID of the batch that we are replying to
1154     * @param {int} callId The call ID that the script relates to
1155     * @param {String} reply The script to execute
1156     */
1157    handleException:function(batchId, callId, ex) {
1158      var batch = dwr.engine._batches[batchId];
1159      if (!batch) return;
1160
1161      var handlers = batch.handlers[callId];
1162      batch.handlers[callId].completed = true;
1163      if (handlers == null) {
1164        dwr.engine._debug("Warning: null handlers in remoteHandleException", true);
1165        return;
1166      }
1167
1168      if (ex.message === undefined) {
1169        ex.message = "";
1170      }
1171
1172      dwr.engine.util.logHandlerEx(function() {
1173        if (typeof handlers.exceptionHandler == "function") {
1174          if (handlers.exceptionArg !== undefined)
1175            handlers.exceptionHandler.call(handlers.exceptionScope, ex.message, ex, handlers.exceptionArg);
1176          else
1177            handlers.exceptionHandler.call(handlers.exceptionScope, ex.message, ex);
1178        }
1179        else if (typeof handlers.errorHandler == "function") {
1180          handlers.errorHandler(ex.message, ex);
1181        }
1182        else if (typeof batch.errorHandler == "function") {
1183          batch.errorHandler(ex.message, ex);
1184        }
1185        else if (typeof batch.globalErrorHandler == "function") {
1186          batch.globalErrorHandler(ex.message, ex);
1187        }
1188      });
1189    },
1190
1191    /**
1192     * Called by the server when a new Reverse Ajax script arrives
1193     */
1194    handleReverseAjax:function(reverseAjaxIndex, reverseAjaxFunc) {
1195      if (reverseAjaxIndex < dwr.engine._nextReverseAjaxIndex) return;
1196      dwr.engine._reverseAjaxQueue[reverseAjaxIndex] = reverseAjaxFunc;
1197      while(true) {
1198        var nextFunc = dwr.engine._reverseAjaxQueue[dwr.engine._nextReverseAjaxIndex];
1199        if (!nextFunc) return;
1200        dwr.engine.util.logHandlerEx(function() {
1201          nextFunc();
1202        });
1203        delete dwr.engine._reverseAjaxQueue[dwr.engine._nextReverseAjaxIndex];
1204        dwr.engine._nextReverseAjaxIndex++;
1205      }
1206    },
1207    
1208    /**
1209     * Called by the server: The whole batch is broken
1210     * @private
1211     * @param {Object} ex The data about what broke
1212     * @param {int} batchId The ID of the batch that we are replying to
1213     */
1214    handleBatchException:function(ex, batchId) {
1215      var batch = dwr.engine._batches[batchId];
1216      if (ex.message === undefined) ex.message = "";
1217      if (batch) {
1218        dwr.engine._handleError(batch, ex);
1219      } else {
1220        dwr.engine._queuedBatchException = ex;
1221      }
1222    },
1223
1224    /**
1225     * Called by the server: Reverse ajax should not be used
1226     * @private
1227     * @param {Object} ex
1228     * @param {int} batchId
1229     */
1230    pollCometDisabled:function(ex, batchId){
1231      dwr.engine.setActiveReverseAjax(false);
1232      var batch = dwr.engine._batches[batchId];
1233      if (ex.message === undefined) {
1234        ex.message = "";
1235      }
1236      dwr.engine._handleError(batch, ex);
1237    },
1238
1239    /**
1240     * Called by the server: Create a new object of a mapped class
1241     * @private
1242     * @param {string} dwrClassName the name of the mapped class
1243     * @param {Object} memberMap the object's data members
1244     */
1245    newObject:function(dwrClassName, memberMap){
1246      var classfunc = dwr.engine._mappedClasses[dwrClassName];
1247      if (classfunc && classfunc.createFromMap) {
1248        return classfunc.createFromMap(memberMap);
1249      }
1250      else {
1251        memberMap.$dwrClassName = dwrClassName;
1252        return memberMap;
1253      }
1254    }
1255  };
1256
1257  /**
1258   * Functions to serialize a data set into a list of parameters
1259   */
1260  dwr.engine.serialize = {
1261    /**
1262     * ActiveX objects to use when we want to convert an xml string into a DOM object
1263     */
1264    domDocument:[
1265      "Msxml2.DOMDocument.6.0",
1266      "Msxml2.DOMDocument.5.0",
1267      "Msxml2.DOMDocument.4.0",
1268      "Msxml2.DOMDocument.3.0",
1269      "MSXML2.DOMDocument",
1270      "MSXML.DOMDocument",
1271      "Microsoft.XMLDOM"
1272    ],
1273
1274    /**
1275     * A holder for functions that we have serialized for remote calling.
1276     */
1277    remoteFunctions:{},
1278
1279    /**
1280     * The ID of the next function that we serialize
1281     */
1282    funcId:0,
1283
1284    /**
1285     * Convert a text representation of XML into a DOM element
1286     * @param {String} xml An xml string
1287     */
1288    toDomElement:function(xml) {
1289      return dwr.engine.serialize.toDomDocument(xml).documentElement;
1290    },
1291
1292    /**
1293     * Convert a text representation of XML into a DOM document
1294     * @param {String} xml An xml string
1295     */
1296    toDomDocument:function(xml) {
1297      var dom;
1298      if (window.DOMParser) {
1299        var parser = new DOMParser();
1300        dom = parser.parseFromString(xml, "text/xml");
1301        if (!dom.documentElement || dom.documentElement.tagName == "parsererror") {
1302          var message = dom.documentElement.firstChild.data;
1303          message += "\n" + dom.documentElement.firstChild.nextSibling.firstChild.data;
1304          throw message;
1305        }
1306        return dom;
1307      }
1308      else if (window.ActiveXObject) {
1309        dom = dwr.engine.util.newActiveXObject(dwr.engine.serialize.domDocument);
1310        dom.loadXML(xml); // What happens on parse fail with IE?
1311        return dom;
1312      }
1313      else {
1314        var div = document.createElement("div");
1315        div.innerHTML = xml;
1316        return div;
1317      }
1318    },
1319
1320    /**
1321     * Marshall a data item
1322     * @private
1323     * @param batch A map of variables to how they have been marshalled
1324     * @param directrefmap A map of already marshalled variables to prevent recurrsion (these have direct links from their data object)
1325     * @param otherrefmap A map of already marshalled variables to prevent recursion (these have no links from data objects)
1326     * @param data The data to be marshalled
1327     * @param name The name of the data being marshalled
1328     */
1329    convert:function(batch, directrefmap, otherrefmap, data, name, depth) {
1330      if (data == null) {
1331        batch.map[name] = "null:null";
1332        return;
1333      }
1334
1335      switch (typeof data) {
1336      case "boolean":
1337        batch.map[name] = "boolean:" + data;
1338        break;
1339      case "number":
1340        batch.map[name] = "number:" + data;
1341        break;
1342      case "string":
1343        batch.map[name] = "string:" + encodeURIComponent(data);
1344        break;
1345      case "object":
1346        var ref = dwr.engine.serialize.lookup(directrefmap, otherrefmap, data, name);
1347        var objstr = Object.prototype.toString.call(data);
1348        if (data.$dwrByRef) batch.map[name] = dwr.engine.serialize.convertByReference(batch, directrefmap, otherrefmap, data, name, depth + 1);
1349        else if (ref != null) batch.map[name] = ref;
1350        else if (objstr == "[object String]") batch.map[name] = "string:" + encodeURIComponent(data);
1351        else if (objstr == "[object Boolean]") batch.map[name] = "boolean:" + data;
1352        else if (objstr == "[object Number]") batch.map[name] = "number:" + data;
1353        else if (objstr == "[object Date]") batch.map[name] = "date:" + data.getTime();
1354        else if (objstr == "[object Array]") batch.map[name] = dwr.engine.serialize.convertArray(batch, directrefmap, otherrefmap, data, name, depth + 1);
1355        else if (data && data.tagName && data.tagName.toLowerCase() == "input" && data.type && data.type.toLowerCase() == "file") {
1356          batch.fileUpload = true;
1357          batch.map[name] = data;
1358        }
1359        else {
1360          // This check for an HTML is not complete, but is there a better way?
1361          // Maybe we should add: data.hasChildNodes typeof "function" == true
1362          if (data.nodeName && data.nodeType) {
1363            batch.map[name] = dwr.engine.serialize.convertDom(data);
1364          }
1365          else {
1366            batch.map[name] = dwr.engine.serialize.convertObject(batch, directrefmap, otherrefmap, data, name, depth + 1);
1367          }
1368        }
1369        break;
1370      case "function":
1371        // Ignore functions unless they are directly passed in
1372        if (depth === 0) {
1373          batch.map[name] = dwr.engine.serialize.convertByReference(batch, directrefmap, otherrefmap, data, name, depth + 1);
1374        }
1375        break;
1376      default:
1377        dwr.engine._handleWarning(null, { name:"dwr.engine.unexpectedType", message:"Unexpected type: " + typeof data + ", attempting default converter." });
1378        batch.map[name] = "default:" + data;
1379        break;
1380      }
1381    },
1382
1383    /**
1384     * Marshall an object by reference
1385     * @private
1386     * @see dwr.engine.serialize.convert() for parameter details
1387     */
1388    convertByReference:function(batch, directrefmap, otherrefmap, data, name, depth) {
1389      var funcId = "f" + dwr.engine.serialize.funcId;
1390      dwr.engine.serialize.remoteFunctions[funcId] = data;
1391      dwr.engine.serialize.funcId++;
1392      return "byref:" + funcId;
1393    },
1394
1395    /**
1396     * Marshall an array
1397     * @private
1398     * @see dwr.engine.serialize.convert() for parameter details
1399     */
1400    convertArray:function(batch, directrefmap, otherrefmap, data, name, depth) {
1401      var childName, i;
1402      if (dwr.engine.util.ieCondition("if lte IE 7")) {
1403        // Use array joining on IE1-7 (fastest)
1404        var buf = ["array:["];
1405        for (i = 0; i < data.length; i++) {
1406          if (i !== 0) buf.push(",");
1407          batch.paramCount++;
1408          childName = "c" + dwr.engine._batch.map.callCount + "-e" + batch.paramCount;
1409          dwr.engine.serialize.convert(batch, directrefmap, otherrefmap, data[i], childName, depth + 1);
1410          buf.push("reference:");
1411          buf.push(childName);
1412        }
1413        buf.push("]");
1414        reply = buf.join("");
1415      }
1416      else {
1417        // Use string concat on other browsers (fastest)
1418        var reply = "array:[";
1419        for (i = 0; i < data.length; i++) {
1420          if (i !== 0) reply += ",";
1421          batch.paramCount++;
1422          childName = "c" + dwr.engine._batch.map.callCount + "-e" + batch.paramCount;
1423          dwr.engine.serialize.convert(batch, directrefmap, otherrefmap, data[i], childName, depth + 1);
1424          reply += "reference:";
1425          reply += childName;
1426        }
1427        reply += "]";
1428      }
1429
1430      return reply;
1431    },
1432
1433    /**
1434     * Marshall an object by value
1435     * @private
1436     * @see dwr.engine.serialize.convert() for parameter details
1437     */
1438    convertObject:function(batch, directrefmap, otherrefmap, data, name, depth) {
1439      // treat objects as an associative arrays
1440      var reply = "Object_" + dwr.engine.serialize.getObjectClassName(
1440data).replace(/:/g, "?") + ":{";
1441      var elementset = (data.constructor && data.constructor.$dwrClassMembers ? data.constructor.$dwrClassMembers : data);
1442      var element;
1443      for (element in elementset) {
1444        if (typeof data[element] != "function" && !dwr.engine._excludeObjectAttributes[element]) {
1445          batch.paramCount++;
1446          var childName = "c" + dwr.engine._batch.map.callCount + "-e" + batch.paramCount;
1447          dwr.engine.serialize.convert(batch, directrefmap, otherrefmap, data[element], childName, depth + 1);
1448          reply += encodeURIComponent(element) + ":reference:" + childName + ", ";
1449        }
1450      }
1451
1452      if (reply.substring(reply.length - 2) == ", ") {
1453        reply = reply.substring(0, reply.length - 2);
1454      }
1455      reply += "}";
1456
1457      return reply;
1458    },
1459
1460    /**
1461     * Marshall an object
1462     * @private
1463     * @see dwr.engine.serialize.convert() for parameter details
1464     */
1465    convertDom:function(data) {
1466      return "xml:" + encodeURIComponent(dwr.engine.serialize.serializeDom(data));
1467    },
1468    serializeDom:function(data) {
1469      var output;
1470      if (window.XMLSerializer) output = new XMLSerializer().serializeToString(data);
1471      else if (data.xml) output = data.xml;
1472      else throw new Error("The browser doesn't support XML serialization of: " + data);
1473      return output;
1474    },
1475
1476    /**
1477     * Have we already converted this object?
1478     * @private
1479     * @see dwr.engine.serialize.convert() for parameter details
1480     */
1481    lookup:function(directrefmap, otherrefmap, data, name) {
1482      // Look for reference to previous conversion
1483      var ref;
1484      if ("$_dwrConversionRef" in data) {
1485        ref = data.$_dwrConversionRef;
1486        if (ref && directrefmap[ref] != data) ref = null;
1487      }
1488      if (ref == null) {
1489        for(r in otherrefmap) {
1490          if (otherrefmap[r] == data) {
1491            ref = r;
1492            break;
1493          }
1494        }
1495      }
1496      if (ref != null) return "reference:" + ref;
1497      // This was a new conversion - save the reference!
1498      try {
1499        data.$_dwrConversionRef = name;
1500        directrefmap[name] = data;
1501      }
1502      catch(err) {
1503        otherrefmap[name] = data;
1504      }
1505      return null;
1506    },
1507
1508    /**
1509     * Clean up our conversion markers from user data
1510     * @private
1511     */
1512    cleanup:function(directrefmap) {
1513      for(var refName in directrefmap) {
1514        var data = directrefmap[refName];
1515        try {
1516          delete data.$_dwrConversionRef;
1517        }
1518        catch(err) {
1519          data.$_dwrConversionRef = undefined;
1520        }
1521      }
1522    },
1523
1524    /**
1525     * Returns the classname of supplied argument obj. Similar to typeof, but
1526     * which returns the name of the constructor that created the object rather
1527     * than 'object'
1528     * @private
1529     * @param {Object} obj The object to detect the type of
1530     * @return The name of the object
1531     */
1532    getObjectClassName:function(obj) {
1533      // Different handling depending on if, and what type of, class-mapping is used
1534      if (obj.$dwrClassName)
1535        return obj.$dwrClassName; // Light class-mapping uses the classname from a property on the instance
1536      else if (obj.constructor && obj.constructor.$dwrClassName)
1537        return obj.constructor.$dwrClassName; // Full class-mapping uses the classname from a property on the constructor function
1538      else
1539        return "Object";
1540    }
1541  };
1542
1543  /**
1544   * Functions to handle the various remoting transport
1545   */
1546  dwr.engine.transport = {
1547    /**
1548     * Manage the DWR session and then send.
1549     * @private
1550     * @param {Object} batch
1551     */
1552    send:function(batch) {
1553      if (batch.path == null) {
1554        batch.path = dwr.engine._effectivePath();
1555      }
1556      dwr.engine.transport.updateDwrSessionFromCookie();
1557      if (!dwr.engine._dwrSessionId) {
1558        dwr.engine._internalOrdered = true;
1559        var retval;
1560        var idbatch = {
1561          map:{
1562            callCount:1,
1563            'c0-scriptName':'__System',
1564            'c0-methodName':'generateId',
1565            'c0-id':0
1566          },
1567          paramCount:0, isPoll:false, async:batch.async,
1568          headers:{}, preHooks:[],
1569          postHooks:[function() {
1570            dwr.engine._internalOrdered = false;
1571          }],
1572          timeout:dwr.engine._timeout,
1573          errorHandler:batch.errorHandler, globalErrorHandler:batch.globalErrorHandler, warningHandler:batch.warningHandler, textHtmlHandler:batch.textHtmlHandler, globalTextHtmlHandler:batch.globalTextHtmlHandler,
1574          path:batch.path,
1575          handlers:[{
1576            exceptionHandler:null,
1577            callback:function(id) {
1578              dwr.engine.transport.updateDwrSessionFromCookie();
1579              if (!dwr.engine._dwrSessionId) {
1580                dwr.engine.transport.setDwrSession(id);
1581              }
1582              retval = dwr.engine.transport.send2(batch);
1583            }
1584          }]
1585        };
1586        dwr.engine.transport.send2(idbatch);
1587        return retval;
1588      }
1589      else {
1590        return dwr.engine.transport.send2(batch);
1591      }
1592    },
1593
1594    /**
1595     * Actually send the block of data in the batch object.
1596     * @private
1597     * @param {Object} batch
1598     */
1599    send2:function(batch) {
1600      dwr.engine.batch.prepareToSend(batch);
1601
1602      // Work out if we are going cross domain
1603      var isCrossDomain = false;
1604      if (batch.path.indexOf("http://") === 0 || batch.path.indexOf("https://") === 0) {
1605        var dwrShortPath = batch.path.split("/", 3).join("/");
1606        var hrefShortPath = window.location.href.split("/", 3).join("/");
1607        isCrossDomain = (dwrShortPath != hrefShortPath);
1608      }
1609
1610      if (batch.fileUpload) {
1611        if (isCrossDomain) {
1612          throw new Error("Cross domain file uploads are not possible with this release of DWR");
1613        }
1614        batch.transport = dwr.engine.transport.iframe;
1615      }
1616      else if (isCrossDomain) {
1617        batch.transport = dwr.engine.transport.scriptTag;
1618      }
1619      else if (batch.isPoll && dwr.engine._useStreamingPoll == "true" && dwr.engine.util.ieCondition("if (IE 8)|(IE 9)")) {
1620        batch.transport = dwr.engine.transport.iframe;
1621      }
1622      else {
1623        batch.transport = dwr.engine.transport.xhr;
1624      }
1625
1626      return batch.transport.send(batch);
1627    },
1628
1629    /**
1630     * Called to signal that the batch response has been delivered
1631     */
1632    complete:function(batch) {
1633        dwr.engine.batch.validate(batch);
1634        dwr.engine.transport.remove(batch);
1635    },
1636
1637    /**
1638     * Called as a result of a request timeout
1639     * @private
1640     * @param {Object} batch The batch that is aborting
1641     */
1642    abort:function(batch) {
1643      var transport = batch.transport;
1644      if (transport.abort) {
1645        transport.abort(batch);
1646      }
1647      dwr.engine.transport.remove(batch);
1648    },
1649
1650    /**
1651     * Remove all remoting artifacts
1652     * @param {Object} batch The batch that has completed
1653     */
1654    remove:function(batch) {
1655      if (batch.transport) {
1656        dwr.engine._callPostHooks(batch);
1657        batch.transport.remove(batch);
1658        batch.transport = null;
1659      }
1660      dwr.engine.batch.remove(batch);
1661    },
1662
1663    setDwrSession:function(dwrsess) {
1664      dwr.engine._dwrSessionId = dwrsess;
1665      var attrs = "";
1666      if (!dwr.engine._cookieAttributes.match(/^path=/i)) {
1667        attrs = "; path=" + (dwr.engine._effectiveContextPath() || "/");
1668      }
1669      if (dwr.engine._cookieAttributes) {
1670        attrs += "; " + dwr.engine._cookieAttributes;
1671      }
1672      document.cookie = "DWRSESSIONID=" + dwrsess + attrs;
1673      dwr.engine._scriptSessionId = dwrsess + "/" + dwr.engine._pageId;
1674    },
1675
1676    updateDwrSessionFromCookie:function() {
1677      if (!dwr.engine._dwrSessionId) {
1678        var match = document.cookie.match(/(?:^|; )DWRSESSIONID=([^;]+)/);
1679        if (match) {
1680          dwr.engine.transport.setDwrSession(match[1]);
1681        }
1682      }
1683    },
1684
1685    /**
1686     * Remoting through XHR
1687     */
1688    xhr:{
1689      /**
1690       * The default HTTP method to use
1691       */
1692      httpMethod:"POST",
1693
1694      /**
1695       * The ActiveX objects to use when we want to do an XMLHttpRequest call.
1696       * TODO: We arrived at this by trial and error. Other toolkits use
1697       * different strings, maybe there is an officially correct version?
1698       */
1699      XMLHTTP:["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"],
1700
1701      /**
1702       * Setup a batch for transfer through XHR
1703       * @param {Object} batch The batch to alter for XHR transmit
1704       */
1705      send:function(batch) {
1706        if (batch.isPoll) {
1707          batch.map.partialResponse = dwr.engine._partialResponseYes;
1708        }
1709
1710        // Are we told to use early closing mode?
1711        if (batch.isPoll && dwr.engine._useStreamingPoll == "false") {
1712          batch.map.partialResponse = dwr.engine._partialResponseNo;
1713        }
1714        if (batch.isPoll && dwr.engine.util.ieCondition("if lte IE 9")) {
1715          batch.map.partialResponse = dwr.engine._partialResponseNo;
1716        }
1717
1718        if (window.XMLHttpRequest) {
1719          batch.req = new XMLHttpRequest();
1720        }
1721        else if (window.ActiveXObject) {
1722          batch.req = dwr.engine.util.newActiveXObject(dwr.engine.transport.xhr.XMLHTTP);
1723        }
1724
1725        // Proceed using XMLHttpRequest
1726        if (batch.async === true) {
1727          batch.req.onreadystatechange = function() {
1728            if (typeof dwr != 'undefined') {
1729              dwr.engine.transport.xhr.stateChange(batch);
1730            }
1731          };
1732        }
1733
1734        httpMethod = dwr.engine.transport.xhr.httpMethod;
1735
1736        batch.mode = batch.isPoll ? dwr.engine._ModePlainPoll : dwr.engine._ModePlainCall;
1737        var request = dwr.engine.batch.constructRequest(batch, httpMethod);
1738
1739        try {
1740          batch.req.open(httpMethod, request.url, batch.async);
1741          try {
1742            for (var prop in batch.headers) {
1743              var value = batch.headers[prop];
1744              if (typeof value == "string") {
1745                batch.req.setRequestHeader(prop, value);
1746              }
1747            }
1748            if (!batch.headers["Content-Type"]) {
1749              batch.req.setRequestHeader("Content-Type", "text/plain");
1750            }
1751          }
1752          catch (ex) {
1753            dwr.engine._handleWarning(batch, ex);
1754          }
1755
1756          batch.req.send(request.body);
1757          if (batch.async === false) {
1758            dwr.engine.transport.xhr.stateChange(batch);
1759          }
1760        }
1761        catch (ex2) {
1762          dwr.engine._handleError(batch, ex2);
1763        }
1764
1765        if (batch.isPoll && batch.map.partialResponse == dwr.engine._partialResponseYes) {
1766          dwr.engine.transport.xhr.checkCometPoll();
1767        }
1768
1769        // This is only of any use in sync mode to return the reply data
1770        return batch.reply;
1771      },
1772
1773      /**
1774       * Called by XMLHttpRequest to indicate that something has happened
1775       * @private
1776       * @param {Object} batch The current remote operation
1777       */
1778      stateChange:function(batch) {
1779        var toEval;
1780
1781        if (batch.aborted) return;
1782        if (batch.completed) {
1783          if (batch.transport) dwr.engine._debug("Error: _stateChange() with batch.completed");
1784          return;
1785        }
1786
1787        // Try to get the response HTTP status if applicable
1788        var req = batch.req;
1789        var status = 0;
1790        try {
1791          if (req.readyState >= 2) {
1792            status = req.status; // causes Mozilla to except on page moves
1793          }
1794        }
1795        catch(ignore) {}
1796
1797        // If we couldn't get the status we bail out, unless the request is
1798        // complete, which means error (handled further below)
1799        if (status === 0 && req.readyState < 4) {
1800          return;
1801        }
1802
1803        // If the status is 200, we are now online.
1804        // Future improvement per Mike W. - A solution where we only use the callbacks/handlers of the poll call to trigger
1805        // the retry handling would be ideal.  We would need something like a new internal callback that reports
1806        // progress back to the caller, and the design should be compatible with getting it to work with iframes as well.
1807        if (status === 200) {
1808          dwr.engine._handlePollStatusChange(true, null, batch);
1809        }
1810
1811        // The rest of this function only deals with request completion
1812        if (req.readyState != 4) {
1813          return;
1814        }
1815
1816        if (dwr.engine._unloading) {
1817          dwr.engine._debug("Ignoring reply from server as page is unloading.");
1818          return;
1819        }
1820
1821        try {
1822          var reply = req.responseText;
1823          reply = dwr.engine._replyRewriteHandler(reply);
1824          var contentType = req.getResponseHeader("Content-Type");
1825          if (status >= 200 && status < 300) {
1826            if (contentType.indexOf("text/plain") < 0 && contentType.indexOf("text/javascript") < 0) {
1827              if (contentType.indexOf("text/html") == 0) {
1828                dwr.engine._handleError(batch, { name:"dwr.engine.textHtmlReply", message:"HTML reply from the server.", responseText:reply||"" });
1829              } else {
1830                dwr.engine._handleError(batch, { name:"dwr.engine.invalidMimeType", message:"Invalid content type: '" + contentType + "'" });
1831              }
1832            } else if (reply == null || reply === "") {
1833              dwr.engine._handleError(batch, { name:"dwr.engine.missingData", message:"No data received from server" });
1834            } else {
1835              if (batch.isPoll && batch.map.partialResponse == dwr.engine._partialResponseYes) {
1836                dwr.engine.transport.xhr.processCometResponse(reply, batch);
1837              } else {
1838                if (reply.search("//#DWR") === -1) {
1839                  dwr.engine._handleError(batch, { name:"dwr.engine.invalidReply", message:"Invalid reply from server" });
1840                } else {
1841                  toEval = reply;
1842                }
1843              }
1844            }
1845          } else if (status >= 400) {
1846            var statusText = "statusText could not be read.";
1847            try {
1848              statusText = req.statusText;
1849            } catch (ex) {
1850             // Eat this, if the server just went down an exception can occur reading statusText.
1851            }
1852            dwr.engine._handleError(batch, { name:"dwr.engine.http." + status, message:statusText });
1853          }
1854
1855          if (toEval != null) toEval = toEval.replace(dwr.engine._scriptTagProtection, "");
1856          dwr.engine._executeScript(toEval);
1857          dwr.engine.transport.complete(batch);
1858
1859        } catch (ex2) {
1860          dwr.engine._handleError(batch, ex2);
1861        }
1862      },
1863
1864      /**
1865       * Check for reverse Ajax activity
1866       * @private
1867       */
1868      checkCometPoll:function() {
1869        var req = dwr.engine._pollBatch && dwr.engine._pollBatch.req;
1870        if (req) {
1871          var text = req.responseText;
1872          if (text != null) {
1873            dwr.engine.transport.xhr.processCometResponse(text, dwr.engine._pollBatch);
1874          }
1875        }
1876        // If the poll resources are still there, come back again
1877        if (dwr.engine._pollBatch) {
1878          setTimeout(dwr.engine.transport.xhr.checkCometPoll, dwr.engine._pollCometInterval);
1879        }
1880      },
1881
1882      /**
1883       * Some more text might have come in, test and execute the new stuff.
1884       * This method could also be called by the iframe transport
1885       * @private
1886       * @param {Object} response from xhr.responseText
1887       * @param {Object} batch The batch that the XHR object pertains to
1888       */
1889      processCometResponse:function(response, batch) {
1890        if (batch.charsProcessed == response.length) return;
1891        if (response.length === 0) {
1892          batch.charsProcessed = 0;
1893          return;
1894        }
1895
1896        var firstStartTag = response.indexOf("//#DWR-START#", batch.charsProcessed);
1897        if (firstStartTag == -1) {
1898          // dwr.engine._debug("No start tag (search from " + batch.charsProcessed + "). skipping '" + response.substring(batch.charsProcessed) + "'");
1899          return;
1900        }
1901        // if (firstStartTag > 0) {
1902        //   dwr.engine._debug("Start tag not at start (search from " + batch.charsProcessed + "). skipping '" + response.substring(batch.charsProcessed, firstStartTag) + "'");
1903        // }
1904
1905        var lastEndTag = response.lastIndexOf("//#DWR-END#");
1906        if (lastEndTag == -1) {
1907          // dwr.engine._debug("No end tag. unchanged charsProcessed=" + batch.charsProcessed);
1908          return;
1909        }
1910
1911        // Skip the end tag too for next time, remembering CR and LF
1912        if (response.charCodeAt(lastEndTag + 11) == 13 && response.charCodeAt(lastEndTag + 12) == 10) {
1913          batch.charsProcessed = lastEndTag + 13;
1914        }
1915        else {
1916          batch.charsProcessed = lastEndTag + 11;
1917        }
1918
1919        var exec = response.substring(firstStartTag + 13, lastEndTag);
1920
1921        try {
1922          dwr.engine._executeScript(exec);
1923        }
1924        catch (ex) {
1925          // This is one of these annoying points where we might be executing
1926          // while the window is being destroyed. If dwr == null, bail out.
1927          if (dwr != null) {
1928            dwr.engine._handleError(batch, ex);
1929          }
1930        }
1931      },
1932
1933      /**
1934       * Aborts ongoing request (for timeouts etc)
1935       */
1936      abort:function(batch) {
1937        if (batch.req) {
1938          batch.aborted = true;
1939          batch.req.abort();
1940        }
1941      },
1942
1943      /**
1944       * Tidy-up when an XHR call is done
1945       * @param {Object} batch
1946       */
1947      remove:function(batch) {
1948        // XHR tidyup: avoid IE handles increase
1949        if (batch.req) {
1950          delete batch.req;
1951        }
1952      }
1953    },
1954
1955    /**
1956     * Functions for remoting through IFrame
1957     */
1958    iframe:{
1959      /**
1960       * The default HTTP method to use
1961       */
1962      httpMethod:"POST",
1963
1964      /**
1965       * Setup a batch for transfer through IFrame
1966       * @param {Object} batch The batch to alter for IFrame transmit
1967       */
1968      send:function(batch) {
1969        if (document.body == null) {
1970          setTimeout(function(){dwr.engine.transport.iframe.send(batch);}, 100);
1971          return;
1972        }
1973        batch.httpMethod = dwr.engine.transport.iframe.httpMethod;
1974        if (batch.fileUpload) {
1975          batch.httpMethod = "POST";
1976          batch.encType = "multipart/form-data";
1977        }
1978        batch.loadingStarted = false;
1979        if (window.location.hostname != document.domain) batch.map.documentDomain = document.domain;
1980        var idname = dwr.engine.transport.iframe.getId(batch);
1981        batch.div1 = document.createElement("div");
1982        batch.div1.innerHTML = "<iframe frameborder='0' style='width:0px;height:0px;border:0;display:none;' id='" + idname + "' name='" + idname + "'></iframe>";
1983        batch.iframe = batch.div1.firstChild;
1984        batch.document = document;
1985        batch.iframe.batch = batch;
1986        batch.fileInputs = [];
1987        dwr.engine.util.addEventListener(batch.iframe, "load", function(ev) {
1988          // Bail out if this is a premature load event (IE) 
1989          if (!batch.loadingStarted) return;
1990          // Put back file inputs
1991          while(batch.fileInputs.length > 0) {
1992            var entry = batch.fileInputs.pop();
1993            entry.original.setAttribute("id", entry.clone.getAttribute("id"));
1994            entry.original.setAttribute("name", entry.clone.getAttribute("name"));
1995            entry.original.style.display = entry.clone.style.display;
1996            entry.clone.parentNode.replaceChild(entry.original, entry.clone);
1997          }
1998          // Bail out if the batch was completed the normal way 
1999          if (batch.completed) return;
2000          // Check for a queued batch exception
2001          if (dwr.engine._queuedBatchException) {
2002            dwr.engine._handleError(batch, dwr.engine._queuedBatchException);
2003            dwr.engine._queuedBatchException = null;
2004            return;
2005          }
2006          // The batch hasn't been completed the normal way, trigger a textHtmlReply error
2007          try {
2008            var contentDoc = batch.iframe.contentDocument || batch.iframe.contentWindow.document;
2009          } catch(ex) {
2010            var contentEx = ex; // may be caused by a HTML error page reply when document.domain is used
2011          }
2012          if (typeof dwr != "undefined") {
2013            var htmlResponse = contentDoc && contentDoc.documentElement ? contentDoc.documentElement.outerHTML : "(Could not extract HTML response: " + contentEx.message + ")";
2014            dwr.engine._handleError(batch, {name:"dwr.engine.textHtmlReply", message:"HTML reply from the server.", responseText:htmlResponse});
2015          }
2016        });
2017        // This needs to be after the event listener is added, for IE.
2018        // http://stackoverflow.com/questions/18414964/load-event-for-iframe-does-not-fire-in-ie
2019        document.body.appendChild(batch.div1);
2020        dwr.engine.transport.iframe.beginLoader(batch, idname);
2021      },
2022
2023      /**
2024       * Create a unique ID so multiple iframes can fire at the same time
2025       * @param {Object} batch A source of a unique number for the batch
2026       * @return {String} a name prefix for created elements
2027       */
2028      getId:function(batch) {
2029        return batch.isPoll ? "dwr-if-poll-" + dwr.engine._instanceId + "-" + batch.map.batchId : "dwr-if-" + dwr.engine._instanceId + "-" + batch.map.batchId;
2030      },
2031
2032      /**
2033       * Setup a form or construct a src attribute to use the iframe.
2034       * @param {Object} batch
2035       */
2036      beginLoader:function(batch, idname) {
2037        if (batch.isPoll) {
2038          batch.map.partialResponse = dwr.engine._partialResponseYes;
2039        }
2040        batch.mode = batch.isPoll ? dwr.engine._ModeHtmlPoll : dwr.engine._ModeHtmlCall;
2041        var request = dwr.engine.batch.constructRequest(batch, batch.httpMethod);
2042        if (batch.httpMethod === "GET") {
2043          batch.iframe.setAttribute("src", request.url);
2044        }
2045        else {
2046          // TODO: On firefox we can now get the values of file fields, maybe we should use this
2047          // See http://soakedandsoaped.com/articles/read/firefox-3-native-ajax-file-upload
2048          // setting enctype via the DOM does not work in IE, create the form using innerHTML instead
2049          batch.div2 = document.createElement("div");
2050          document.body.appendChild(batch.div2);
2051          batch.div2.innerHTML = "<form" + (batch.encType ? " encType='" + batch.encType + "' encoding='" + batch.encType + "'" : "") + "></form>";
2052          batch.form = batch.div2.firstChild;
2053          batch.form.setAttribute("action", request.url);
2054          batch.form.setAttribute("target", idname);
2055          batch.form.setAttribute("style", "display:none");
2056          batch.form.setAttribute("method", batch.httpMethod);
2057          for (var prop in batch.map) {
2058            var value = batch.map[prop];
2059            if (typeof value != "function") {
2060              if (value && value.tagName && value.tagName.toLowerCase() == "input" && value.type && value.type.toLowerCase() == "file") {
2061                // Since we can not set the value of a file object, we must post the actual file object
2062                // that the user clicked browse on. We will put a clone in it's place that we will restore later.
2063                // (note that the clone doesn't retain the selected file in most browsers)
2064                if (value.parentNode) {
2065                  var clone = value.cloneNode(true);
2066                  value.parentNode.replaceChild(clone, value);
2067                  batch.fileInputs.push({original:value, clone:clone});
2068                }
2069                value.removeAttribute("id");
2070                value.setAttribute("name", prop);
2071                value.style.display = "none";
2072                batch.form.appendChild(value);
2073              } else {
2074                var formInput = batch.document.createElement("input");
2075                formInput.setAttribute("type", "hidden");
2076                formInput.setAttribute("name", prop);
2077                formInput.setAttribute("value", value);
2078                batch.form.appendChild(formInput);
2079              }
2080            }
2081          }
2082          batch.loadingStarted = true;
2083          batch.form.submit();
2084        }
2085      },
2086
2087      /**
2088       * Functions designed to be called by the server
2089       */
2090      remote:{
2091        /**
2092         * Called by the server: An IFrame reply is about to start
2093         * @private
2094         * @param {Object} iframe
2095         * @param {int} batchId
2096         */
2097        beginIFrameResponse:function(iframe, batchId) {
2098        },
2099        
2100        /**
2101         * Called by the server: An IFrame script tag has completed
2102         * @private
2103         * @param {Object} iframe
2104         */
2105        endChunk:function(iframeWindow) {
2106          setTimeout(function() {
2107            // Delete the first script tag in the iframe
2108            var scriptTags = iframeWindow.document.body.getElementsByTagName("script");
2109            if (scriptTags.length > 0) {
2110              var s = scriptTags[0];
2111              s.parentNode.removeChild(s);
2112            }
2113          }, 0);
2114        },
2115
2116        /**
2117         * Called by the server: An IFrame reply is just completing
2118         * @private
2119         * @param {int} batchId
2120         */
2121        endIFrameResponse:function(batchId) {
2122          var batch = dwr.engine._batches[batchId];
2123          if (batch) dwr.engine.transport.complete(batch);
2124        }
2125      },
2126
2127      remove:function(batch) {
2128        // Safari 3 and Chrome 1 will show endless loading spinner if removing
2129        // iframe during execution of iframe script, so we delay it a bit
2130        setTimeout(function(){
2131          if (batch.iframe && batch.iframe.parentNode) {
2132            batch.iframe.parentNode.removeChild(batch.iframe);
2133            batch.iframe = null;
2134          }
2135          if (batch.div1 && batch.div1.parentNode) {
2136            batch.div1.parentNode.removeChild(batch.div1);
2137            batch.div1 = null;
2138          }
2139          if (batch.form && batch.form.parentNode) {
2140            batch.form.parentNode.removeChild(batch.form);
2141            batch.form = null;
2142          }
2143          if (batch.div2 && batch.div2.parentNode) {
2144            batch.div2.parentNode.removeChild(batch.div2);
2145            batch.div2 = null;
2146          }
2147        }, 100);
2148      }
2149    },
2150
2151    /**
2152     * Functions for remoting through Script Tags
2153     */
2154    scriptTag:{
2155      /**
2156       * Setup a batch for transfer through a script tag
2157       * @param {Object} batch The batch to alter for script tag transmit
2158       */
2159      send:function(batch) {
2160        if (batch.isPoll) {
2161          batch.map.partialResponse = dwr.engine._partialResponseNo;
2162        }
2163        batch.mode = batch.isPoll ? dwr.engine._ModePlainPoll : dwr.engine._ModePlainCall;
2164        var request = dwr.engine.batch.constructRequest(batch, "GET");
2165        // The best option is DOM manipulation
2166        batch.script = document.createElement("script");
2167        batch.script.id = "dwr-st-" + batch.map.batchId;
2168        batch.script.src = request.url;
2169        batch.script.type = "text/javascript";
2170        batch.script.async = true;
2171        dwr.engine.util.addEventListener(batch.script, "load", function(ev) {
2172          if (typeof dwr != "undefined") dwr.engine.transport.scriptTag.complete(batch);
2173        });
2174        dwr.engine.util.addEventListener(batch.script, "error", function(ev) {
2175          if (typeof dwr != "undefined") dwr.engine.transport.scriptTag.complete(batch);
2176        });
2177        dwr.engine.util.addEventListener(batch.script, "readystatechange", function(ev) {
2178          if (typeof dwr != "undefined") {
2179            if (batch.completed) return;
2180            if (batch.script.readyState == "complete" || batch.script.readyState == "loaded") {
2181              dwr.engine.transport.scriptTag.complete(batch);
2182            }
2183          }
2184        });
2185        document.getElementsByTagName("head")[0].appendChild(batch.script);
2186      },
2187
2188      /**
2189       * Notified when the script tag has been loaded and executed
2190       */
2191      complete:function(batch) {
2192        dwr.engine.transport.complete(batch);
2193      },
2194
2195      /**
2196       * Cleanup script tag
2197       */
2198      remove:function(batch) {
2199        // Bail out if we were already called
2200        if (!batch.script) return;
2201
2202        // Cleanup script tag
2203        batch.script.parentNode.removeChild(batch.script);
2204        batch.script = null;
2205      }
2206    }
2207  };
2208
2209  /**
2210   * Functions to manipulate batches
2211   * @private
2212   */
2213  dwr.engine.batch = {
2214    /**
2215     * Generate a new standard batch
2216     * @private
2217     */
2218    create:function() {
2219      var batch = {
2220        async:dwr.engine._async,
2221        charsProcessed:0,
2222        handlers:[],
2223        isPoll:false,
2224        map:{ callCount:0 },
2225        paramCount:0,
2226        preHooks:[],
2227        postHooks:[],
2228        timeout:dwr.engine._timeout,
2229        errorHandler:null,
2230        globalErrorHandler:dwr.engine._errorHandler,
2231        warningHandler:dwr.engine._warningHandler,
2232        textHtmlHandler:null,
2233        globalTextHtmlHandler:dwr.engine._textHtmlHandler
2234      };
2235      if (!dwr.engine._activeReverseAjax) batch.map.nextReverseAjaxIndex = dwr.engine._nextReverseAjaxIndex;
2236      
2237      if (dwr.engine._preHook) {
2238        batch.preHooks.push(dwr.engine._preHook);
2239      }
2240      if (dwr.engine._postHook) {
2241        batch.postHooks.push(dwr.engine._postHook);
2242      }
2243
2244      dwr.engine.batch.populateHeadersAndAttributes(batch);
2245      return batch;
2246    },
2247
2248    /**
2249     * Generate a new batch for polling
2250     * @private
2251     * @see dwr.engine.batch.create()
2252     */
2253    createPoll:function() {
2254      var batch = {
2255        async:true,
2256        charsProcessed:0,
2257        handlers:[{
2258          callback:function(pause) {
2259            dwr.engine._pollBatch = null;
2260            setTimeout(dwr.engine._poll, pause);
2261          }
2262        }],
2263        isPoll:true,
2264        map:{ callCount:1, nextReverseAjaxIndex:dwr.engine._nextReverseAjaxIndex},
2265        paramCount:0,
2266        preHooks:[],
2267        postHooks:[],
2268        timeout:dwr.engine._pollTimeout
2269      };
2270      dwr.engine.batch.populateHeadersAndAttributes(batch);
2271      return batch;
2272    },
2273
2274    /**
2275     * Copy the global headers and parameters into this batch object
2276     * @private
2277     * @param {Object} batch The destination
2278     */
2279    populateHeadersAndAttributes:function(batch) {
2280      var propname, data;
2281      batch.headers = {};
2282      if (dwr.engine._headers) {
2283        for (propname in dwr.engine._headers) {
2284          data = dwr.engine._headers[propname];
2285          if (typeof data != "function") batch.headers[propname] = data;
2286        }
2287      }
2288      batch.attributes = {}; // props to add as request attributes
2289      if (dwr.engine._attributes) {
2290        for (propname in dwr.engine._attributes) {
2291          data = dwr.engine._attributes[propname];
2292          if (typeof data != "function") batch.attributes[propname] = data;
2293        }
2294      }
2295    },
2296
2297    /**
2298     * Augment this batch with a new call
2299     * @private
2300     */
2301    addCall:function(batch, scriptName, methodName, args) {
2302      // From the other params, work out which is the function (or object with
2303      // call meta-data) and which is the call parameters
2304      var callData, stopAt;
2305      var lastArg = args[args.length - 1];
2306      if (lastArg == null || typeof lastArg == "function") {
2307        callData = { callback:lastArg };
2308        stopAt = args.length - 1;
2309      }
2310      else if (dwr.engine.util.isCallOptionArgument(lastArg)) {
2311        callData = lastArg;
2312        stopAt = args.length - 1;
2313      }
2314      else {
2315        callData = {};
2316        stopAt = args.length;
2317      }
2318
2319      // Merge from the callData into the batch
2320      if (dwr.engine._singleShot) dwr.engine.batch.merge(batch, callData);
2321      batch.handlers[batch.map.callCount] = {
2322        callback:callData.callbackHandler || callData.callback,
2323        callbackArg:callData.callbackArg || callData.arg,
2324        callbackScope:callData.callbackScope || callData.scope || window,
2325        exceptionHandler:callData.exceptionHandler,
2326        exceptionArg:callData.exceptionArg || callData.arg,
2327        exceptionScope:callData.exceptionScope || callData.scope || window,
2328        errorHandler:callData.errorHandler
2329      };
2330
2331      // Copy to the map the things that need serializing
2332      var prefix = "c" + batch.map.callCount + "-";
2333      batch.map[prefix + "scriptName"] = scriptName;
2334      batch.map[prefix + "methodName"] = methodName;
2335      batch.map[prefix + "id"] = batch.map.callCount;
2336      var directrefmap = {}, otherrefmap = {};
2337      for (var i = 0; i < stopAt; i++) {
2338        dwr.engine.serialize.convert(batch, directrefmap, otherrefmap, args[i], prefix + "param" + i, 0);
2339      }
2340      dwr.engine.serialize.cleanup(directrefmap);
2341    },
2342
2343    /**
2344     * Take further options and merge them into a batch
2345     * @private
2346     * @param {Object} batch The batch that we are altering
2347     * @param {Object}
2347 overrides The object containing properties to copy into batch
2348     */
2349    merge:function(batch, overrides) {
2350      var propname, data;
2351      for (var i = 0; i < dwr.engine._propnames.length; i++) {
2352        propname = dwr.engine._propnames[i];
2353        if (dwr.engine._singleShot && propname == "errorHandler") continue;
2354        if (overrides[propname] != null) batch[propname] = overrides[propname];
2355      }
2356      if (overrides.preHook != null) batch.preHooks.unshift(overrides.preHook);
2357      if (overrides.postHook != null) batch.postHooks.push(overrides.postHook);
2358      if (overrides.headers) {
2359        for (propname in overrides.headers) {
2360          data = overrides.headers[propname];
2361          if (typeof data != "function") batch.headers[propname] = data;
2362        }
2363      }
2364      var attrs = null;
2365      if (overrides.attributes) attrs = overrides.attributes;
2366      if (attrs) {
2367        for (propname in attrs) {
2368          data = attrs[propname];
2369          if (typeof data != "function") batch.attributes[propname] = data;
2370        }
2371      }
2372    },
2373
2374    /**
2375     * Executed just before a transport sends the batch
2376     * @private
2377     * @param {Object} batch The batch to prepare for sending
2378     */
2379    prepareToSend:function(batch) {
2380      batch.map.batchId = dwr.engine._nextBatchId;
2381      dwr.engine._nextBatchId++;
2382      dwr.engine._batches[batch.map.batchId] = batch;
2383      dwr.engine._batchesLength++;
2384      batch.completed = false;
2385      batch.map.instanceId = dwr.engine._instanceId;
2386
2387      // security details are filled in late so previous batches have completed
2388      batch.map.page = encodeURIComponent(window.location.pathname + window.location.search);
2389      batch.map.scriptSessionId = dwr.engine._scriptSessionId;
2390
2391      for (var i = 0; i < batch.preHooks.length; i++) {
2392        batch.preHooks[i]();
2393      }
2394      batch.preHooks = null;
2395      // Set a timeout
2396      if (batch.timeout && batch.timeout !== 0) {
2397        batch.timeoutId = setTimeout(function() { 
2398          dwr.engine.transport.abort(batch); 
2399          dwr.engine._handleError(batch, { name:"dwr.engine.timeout", message:"Timeout" });
2400        }, batch.timeout);
2401      }
2402    },
2403
2404    /**
2405     * Work out what the URL should look like
2406     * @private
2407     * @param {Object} batch the data that we are sending
2408     * @param {Object} httpMethod Are we using GET/POST etc?
2409     */
2410    constructRequest:function(batch, httpMethod) {
2411      // A quick string to help people that use web log analysers
2412      var urlBuffer = [];
2413      urlBuffer.push(batch.path);
2414      urlBuffer.push(batch.mode);
2415      if (batch.isPoll) {
2416        urlBuffer.push("ReverseAjax.dwr");
2417      }
2418      else if (batch.map.callCount == 1) {
2419        urlBuffer.push(batch.map["c0-scriptName"]);
2420        urlBuffer.push(".");
2421        urlBuffer.push(batch.map["c0-methodName"]);
2422        urlBuffer.push(".dwr");
2423      }
2424      else {
2425        urlBuffer.push("Multiple.");
2426        urlBuffer.push(batch.map.callCount);
2427        urlBuffer.push(".dwr");
2428      }
2429      // Play nice with url re-writing
2430      var sessionMatchExpr = new RegExp(
2431        "^" +            // start of string
2432        "[^;\\?#]+" +    // protocol, host, and path (up to first of ; ? or #)
2433        "(;[^\\?#]+)");  // group 1: ; and sessionid (up to first of ? or #)
2434      var sessionMatch = location.href.match(sessionMatchExpr);
2435      if (sessionMatch != null) {
2436        urlBuffer.push(sessionMatch[1]);
2437      }
2438
2439      // Add attributes to the output map
2440      if (batch.attributes) {
2441        for (var attrname in batch.attributes) {
2442          var data = batch.attributes[attrname];
2443          if (typeof data != "function") batch.map["a-" + attrname] = "" + data;
2444        }
2445      }
2446
2447      var request = {};
2448      var prop;
2449      if (httpMethod == "GET") {
2450        // Some browsers (Opera/Safari2) seem to fail to convert the callCount value
2451        // to a string in the loop below so we do it manually here.
2452        batch.map.callCount = "" + batch.map.callCount;
2453        urlBuffer.push("?");
2454        for (prop in batch.map) {
2455          if (typeof batch.map[prop] != "function") {
2456            urlBuffer.push(encodeURIComponent(prop));
2457            urlBuffer.push("=");
2458            urlBuffer.push(encodeURIComponent(batch.map[prop]));
2459            urlBuffer.push("&");
2460          }
2461        }
2462        urlBuffer.pop(); // remove the trailing &
2463        request.body = null;
2464      }
2465      else {
2466        // PERFORMANCE: for iframe mode this is thrown away.
2467        request.body = "";
2468        if (dwr.engine.util.ieCondition("if lte IE 7")) {
2469          // Use array joining on IE1-7 (fastest)
2470          var buf = [];
2471          for (prop in batch.map) {
2472            if (typeof batch.map[prop] != "function") {
2473              buf.push(prop + "=" + batch.map[prop] + dwr.engine._postSeperator);
2474            }
2475          }
2476          request.body = buf.join("");
2477        }
2478        else {
2479          // Use string concat on other browsers (fastest)
2480          for (prop in batch.map) {
2481            if (typeof batch.map[prop] != "function") {
2482              request.body += prop + "=" + batch.map[prop] + dwr.engine._postSeperator;
2483            }
2484          }
2485        }
2486        request.body = dwr.engine._contentRewriteHandler(request.body);
2487      }
2488      request.url = dwr.engine._urlRewriteHandler(urlBuffer.join(""));
2489      return request;
2490    },
2491
2492    /**
2493     * @private This function is invoked when a batch reply is received.
2494     * It checks that there is a response for every call in the batch. Otherwise,
2495     * an error will be signaled (a call without a response indicates that the
2496     * server failed to send complete batch response).
2497     */
2498    validate:function(batch) {
2499      if (!batch.completed) {
2500        var repliesReceived = 0;
2501        for (var i = 0; i < batch.map.callCount; i++) {
2502          if (batch.handlers[i].completed === true) {
2503            repliesReceived++;
2504          }
2505        }
2506        if (repliesReceived == 0 && dwr.engine._queuedBatchException) {
2507          dwr.engine._handleError(batch, dwr.engine._queuedBatchException);
2508          dwr.engine._queuedBatchException = null;
2509        } else if (repliesReceived < batch.map.callCount) {
2510          dwr.engine._handleError(batch, { name:"dwr.engine.incompleteReply", message:"Incomplete reply from server" });
2511        }
2512      }
2513    },
2514
2515    /**
2516     * A call has finished by whatever means and we need to shut it all down.
2517     * @private
2518     * @param {Object} batch The batch that we are altering
2519     */
2520    remove:function(batch) {
2521      if (!batch) {
2522        dwr.engine._debug("Warning: null batch in dwr.engine.batch.remove()", true);
2523        return;
2524      }
2525
2526      if (batch.completed) {
2527        return;
2528      }
2529      batch.completed = true;
2530
2531      // Transport tidyup
2532      dwr.engine.transport.remove(batch);
2533
2534      // Timeout tidyup
2535      if (batch.timeoutId != null) {
2536        clearTimeout(batch.timeoutId);
2537        delete batch.timeoutId;
2538      }
2539
2540      // TODO: co-locate all the functions that work on a set of batches
2541      if (batch.map && (batch.map.batchId != null)) {
2542        delete dwr.engine._batches[batch.map.batchId];
2543        dwr.engine._batchesLength--;
2544      }
2545      if (batch == dwr.engine._batch) dwr.engine._batch = null;
2546      if (batch == dwr.engine._pollBatch) dwr.engine._pollBatch = null;
2547
2548      // If there is anything on the queue waiting to go out, then send it.
2549      // We don't need to check for ordered mode, here because when ordered mode
2550      // gets turned off, we still process *waiting* batches in an ordered way.
2551      if (dwr.engine._batchQueue.length !== 0) {
2552        var sendbatch = dwr.engine._batchQueue.shift();
2553        dwr.engine.transport.send(sendbatch);
2554      }
2555    }
2556  };
2557
2558  /**
2559   * Various utility functions
2560   * @private
2561   */
2562  dwr.engine.util = {
2563    /**
2564     * Create one of a number of ActiveX strings
2565     * @param {Object} axarray An array of strings to attempt to create ActiveX objects from
2566     */
2567    newActiveXObject:function(axarray) {
2568      var returnValue;
2569      for (var i = 0; i < axarray.length; i++) {
2570        try {
2571          returnValue = new ActiveXObject(axarray[i]);
2572          break;
2573        }
2574        catch (ex) { /* ignore */ }
2575      }
2576      return returnValue;
2577    },
2578
2579    ieCondition:function(cond) {
2580      if (!(cond in dwr.engine._ieConditions)) {
2581        var div = document.createElement("div");
2582        div.innerHTML = "<!--[" + cond + "]><p><![endif]-->";
2583        dwr.engine._ieConditions[cond] = !!(div.getElementsByTagName("p").length);
2584      }
2585      return dwr.engine._ieConditions[cond];
2586    },
2587    
2588    /**
2589     * Transform a number into a token string suitable for ids
2590     */
2591    tokenify: function(number) {
2592      var tokenbuf = [];
2593      var charmap = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ*$";
2594      var remainder = number;
2595      while (remainder > 0)
2596      {
2597        tokenbuf.push(charmap.charAt(remainder & 0x3F));
2598        remainder = Math.floor(remainder / 64); // Can't use shift operator due to 32-bit limit in JS
2599      }
2600      return tokenbuf.join("");
2601    },
2602
2603    addEventListener: function(elem, name, func) {
2604      if (elem.addEventListener)
2605        elem.addEventListener(name, func, false);
2606      else
2607        elem.attachEvent("on" + name, func);
2608    },
2609
2610    isCallOptionArgument: function(lastArg) {
2611      return (typeof lastArg === "object" && (typeof lastArg.callback === "function" ||
2612        typeof lastArg.exceptionHandler === "function" || typeof lastArg.callbackHandler === "function" ||
2613        typeof lastArg.errorHandler === "function" || typeof lastArg.warningHandler === "function" || lastArg.hasOwnProperty("async")));
2614    },
2615
2616    logHandlerEx: function(func) {
2617      try {
2618        func();
2619      } catch(ex) {
2620        dwr.engine._debug("Exception occured in user-specified handler:");
2621        dwr.engine._debug(ex);
2622      }
2623    }
2624  };
2625
2626  // Initialize DWR.
2627  dwr.engine._initializer.init();
2628
2629  /**
2630   * Routines for the DWR pubsub hub
2631   */
2632  dwr.hub = {
2633    /**
2634     * Publish some data to a given topic
2635     * @param {Object} topicName The topic to publish to
2636     * @param {Object} data The data to publish
2637     */
2638    publish:function(topicName, data) {
2639      dwr.engine._execute(null, '__System', 'publish', topicName, data, {});
2640    },
2641
2642    /**
2643     * Subscribe to get notifications of publish events to a given topic
2644     * @param {String} topicName The topic to subscribe to
2645     * @param {Function} callback The function to call when a publish happens
2646     * @param {Object} scope The 'this' object on which the callback executes (optional)
2647     * @param {Object} subscriberData Data that the subscriber wishes to remember (optional)
2648     * @return An opaque type for use with unsubscribe
2649     */
2650    subscribe:function(topicName, callback, scope, subscriberData) {
2651      var subscription = "" + dwr.hub._subscriptionId;
2652      dwr.hub._subscriptionId++;
2653      dwr.hub._subscriptions[subscription] = {
2654        callback:callback,
2655        scope:scope,
2656        subscriberData:subscriberData
2657      };
2658      dwr.engine._execute(null, '__System', 'subscribe', topicName, subscription, {});
2659      return subscription;
2660    },
2661
2662    /**
2663     * Called by the server: A publish event has happened that we care about
2664     * @private
2665     * @param {Object} subscriptionId
2666     * @param {Object} publishData
2667     */
2668    _remotePublish:function(subscriptionId, publishData) {
2669      var subscriptionData = dwr.hub._subscriptions[subscriptionId];
2670      if (!subscriptionData) return;
2671      subscriptionData.callback.call(subscriptionData.scope, publishData, subscriptionData.subscriberData);
2672    },
2673
2674    /**
2675     * Each time we subscribe to something, we use a unique number
2676     */
2677    _subscriptionId:0,
2678
2679    /**
2680     * We need to remember what we are subscribed to so we can recall the callback
2681     */
2682    _subscriptions:{}
2683  };
2684
2685/**
2686 * High level data-sync API for use by Widget libraries like a Dojo-Data-Store.
2687 * For full documentation see org.directwebremoting.export.Data
2688 */
2689dwr.data = {
2690
2691  /**
2692   * This is just documentation that defines how the listener parameter must act
2693   * in order to receive asynchronous updates
2694   */
2695  StoreChangeListener:{
2696    /**
2697     * Something has removed an item from the store
2698     * @param {StoreProvider} source The store from which it was moved
2699     * @param {string} itemId The ID of the item
2700     */
2701    itemRemoved:function(source, itemId) { },
2702
2703    /**
2704     * Something has added an item to the store
2705     * @param {StoreProvider} source The store from which it was moved
2706     * @param {Item} item The thing that has changed
2707     */
2708    itemAdded:function(source, item) { },
2709
2710    /**
2711     * Something has updated an item in the store
2712     * @param {StoreProvider} source The store from which it was moved
2713     * @param {Item} item The thing that has changed
2714     * @param {string[]} changedAttributes A list of changed attributes. If null then
2715     * you should assume that everything has changed
2716     */
2717    itemChanged:function(source, item, changedAttributes) { }
2718  },
2719
2720  /**
2721   * Create a cache object containing the functions to interact with a server
2722   * side StoreProvider
2723   * @param {string} storeId ID of server provided storage
2724   * @param {dwr.data.StoreChangeListener} listener See server documentation
2725   * This is likely to be true if dwr.engine.activeReverseAjax == true
2726   */
2727  Cache:function(storeId, listener) {
2728    this.storeId = storeId;
2729    this.listener = listener;
2730  }
2731};
2732
2733  /**
2734   * Notes that there is a region of a page that wishes to subscribe to server
2735   * side data and registers a callback function to receive the data.
2736   * @param {Object} region filtering and sorting options. Includes:
2737   * - start: The beginning of the region of specific interest
2738   * - count: The number of items being viewed
2739   * - sort: The sort criteria
2740   * - query: The filter criteria
2741   * @param {function|object} callbackObj A standard DWR callback object
2742   * @return
2743   */
2744  dwr.data.Cache.prototype.viewRegion = function(region, callbackObj) {
2745    if (!region) region = { };
2746    if (!region.start) region.start = 0;
2747    if (!region.count) region.count = -1;
2748    if (!region.sort) region.sort = [];
2749    else {
2750      for (var index = 0; index < region.sort.length; index++) {
2751        if (typeof region.sort[index].descending == "undefined") {
2752          region.sort[index].descending = false;
2753        }
2754      }
2755    }
2756    if (!region.query) region.query = {};
2757
2758    return dwr.engine._execute(null, '__Data', 'viewRegion', [ this.storeId, region, this.listener, callbackObj ]);
2759  };
2760
2761  /**
2762   * As dwr.data.Cache.viewRegion() except that we only want to see a single item.
2763   * @param {string} itemId ID of object within the given store
2764   * @param {function|object} callbackObj A standard DWR callback object
2765   */
2766  dwr.data.Cache.prototype.viewItem = function(itemId, callbackObj) {
2767    return dwr.engine._execute(null, '__Data', 'viewItem', [ this.storeId, itemId, this.listener, callbackObj ]);
2768  };
2769
2770  /**
2771   * Undo the action of dwr.data.view()
2772   * @param {function|object} callbackObj A standard DWR callback object
2773   */
2774  dwr.data.Cache.prototype.unsubscribe = function(callbackObj) {
2775    if (this.listener) {
2776      return dwr.engine._execute(null, '__Data', 'unsubscribe', [ this.storeId, this.listener, callbackObj ]);
2777    }
2778  };
2779
2780  /**
2781   * Request an update to server side data
2782   * @param {Object} items An array of update descriptions
2783   * @param {function|object} callbackObj A standard DWR callback object
2784   */
2785  dwr.data.Cache.prototype.update = function(items, callbackObj) {
2786    return dwr.engine._execute(null, '__Data', 'update', [ this.storeId, items, callbackObj ]);
2787  };
2788
2789})();
2790
2791
2792
2793/* ==== INCLUDE: /js/weblets/FeaturedListingsWebletV2.js ==== */
2794
2795document.featuredListingsRefreshInterval = 5000;
2796document.featuredListingsPhotoRefreshInterval = 5000;
2797
2798try
2799{
2800	dwr.engine._allowGetForSafariButMakeForgeryEasier = true;
2801}
2802catch( e )
2803{	
2804}
2805
2806// Effect copied from rico
2807/**
2808  *
2809  *  Copyright 2005 Sabre Airline Solutions
2810  *
2811  *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
2812  *  file except in compliance with the License. You may obtain a copy of the License at
2813  *
2814  *         http://www.apache.org/licenses/LICENSE-2.0
2815  *
2816  *  Unless required by applicable law or agreed to in writing, software distributed under the
2817  *  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
2818  *  either express or implied. See the License for the specific language governing permissions
2819  *  and limitations under the License.
2820  **/
2821if ( window.Effect == undefined )
2822   Effect = {};
2823
2824Effect.FadeTo = function() {
2825	this.initialize.apply(this, arguments);
2826};
2827
2828Effect.FadeTo.prototype = {
2829
2830   initialize: function( element, opacity, duration, steps, options) {
2831	   if( typeof element == "string" ) {
2832		   this.element = document.getElementById( element );
2833	   }
2834	   else {
2835		   this.element  = element;
2836	   }
2837      
2838      this.opacity  = opacity;
2839      this.duration = duration;
2840      this.steps    = steps;
2841      this.options  = arguments[4] || {};
2842      this.fadeTo();
2843   },
2844
2845   fadeTo: function() {
2846      if (this.isFinished()) {
2847      	this.element.ricoOpacity = null;
2848         if(this.options.complete) this.options.complete(this);
2849         return;
2850      }
2851      if (this.timer)
2852         clearTimeout(this.timer);
2853
2854      var stepDuration = Math.round(this.duration/this.steps) ;
2855      var currentOpacity = this.getElementOpacity();
2856      var delta = this.steps > 0 ? (this.opacity - currentOpacity)/this.steps : 0;
2857
2858      this.changeOpacityBy(delta);
2859      this.duration -= stepDuration;
2860      this.steps--;
2861
2862      this.timer = setTimeout(this.fadeTo.bind(this), stepDuration);
2863   },
2864
2865   changeOpacityBy: function(v) {
2866      var currentOpacity = this.getElementOpacity();
2867      var newOpacity = Math.max(0, Math.min(currentOpacity+v, 1));
2868      this.element.ricoOpacity = newOpacity;
2869      // bill: bug note: in IE changing opacity appears to whack seemingly random elements
2870      // on page, disabling for IE, assining imgs[i].id == ... also seems to contribute
2871      // not sure what this is!!!, see another bug not below
2872      if( !browser.isIE ) {
2873      	//this.element.style.filter = "alpha(opacity:"+Math.round(newOpacity*100)+")";
2874      	this.element.style.opacity = newOpacity; /*//*/;
2875      }
2876   },
2877
2878   isFinished: function() {
2879      return this.steps <= 0;
2880   },
2881
2882   getElementOpacity: function() {
2883      if ( this.element.ricoOpacity == undefined ) {
2884         var opacity;
2885         if ( this.element.currentStyle ) {
2886            opacity = this.element.currentStyle.opacity;
2887         }
2888         else if ( document.defaultView.getComputedStyle != undefined ) {
2889            opacity = document.defaultView.getComputedStyle(this.element, null).getPropertyValue('opacity');
2890         }
2891
2892         this.element.ricoOpacity = opacity != undefined ? opacity : 1.0;
2893      }
2894
2895      return parseFloat(this.element.ricoOpacity);
2896   }
2897}
2898
2899
2900function rotateFeaturedListingsPhotos( id, interval )
2901{
2902	if( document.hidden ) {
2903		return;
2904	}
2905	if( !interval ) {
2906		interval = document.featuredListingsPhotoRefreshInterval;
2907	}
2908	for( var listingId in document.featuredListingsHash[id].images ) {
2909		var images = document.featuredListingsHash[id].images[listingId];
2910		if( images.length > 1 ) {
2911			setTimeout( "showFeaturedListingPhoto1('" + id + "', '" + listingId + 
2912				"', 1, " + interval + " )", interval );
2913		}
2914	}
2915}
2916
2917function showFeaturedListingPhoto1( id, listingId, index, interval )
2918{
2919	var w = document.getElementById(id);
2920	var imgId = id + "-" + listingId + "-image";
2921	var imgs = w.getElementsByTagName( "img" );
2922	var img = null;
2923	if( imgs && imgs.length > 0 ) {
2924		for( var i=0; i<imgs.length; ++i ) {
2925
2926			
2927			if( imgs[i].src && !imgs[i].classList.contains( "leadin_overlay" ) &&
2928					//imgs[i].src.indexOf( "/" + listingId + "/" ) != -1
2929					imgs[i].classList.contains("mrp-auto-image") &&
2930					imgs[i].closest('.mrp-leadin').querySelector('a').getAttribute('href').indexOf( listingId ) !== -1 &&
2931					imgs[i].getAttribute("id")==null ) {
2932				
2933				// if( imgs[i] && imgs[i].parentNode && imgs[i].parentNode.getAttribute( "data-auto-image" ) != "ready" ) {
2934				// 	setTimeout( function() {
2935				// 		showFeaturedListingPhoto1( id, listingId, index, interval );
2936				// 	}, 1000 );
2937				// 	return;
2938				// }
2939				
2940				// bill: bug note: instead of assining id, we are assigning to "rel"
2941				// connected to disappearing elements in IE bug, see above
2942				imgs[i].rel = imgId;
2943				img = imgs[i];	
2944				break;
2945			}
2946		}
2947	}
2948	if( !img ) {
2949		return;
2950	}
2951	// img.removeAttribute('srcset');
2952	// img.removeAttribute('sizes');
2953	var bg = document.getElementById(id + "-" + listingId + "-shadow");
2954	if (!bg) {
2955		bg = new Image();
2956		bg.setAttribute("id", id + "-" + listingId + "-shadow");
2957		bg.style.position = "absolute";
2958		bg.style.display = "block";
2959		bg.style.visibility = "visible";
2960		bg.style.margin = img.margin;
2961		bg.style.border = img.border;
2962		bg.className = "mrpl-image";
2963		img.parentNode.insertBefore( bg, img );
2964	}
2965	bg.style.left = img.style.left;
2966	bg.style.top = img.style.top;
2967	bg.style.width = img.style.width;
2968	bg.style.height = img.style.height;
2969	bg.style.opacity = "0"; // bill; this effectively negates teh bg trick, but it's due to flicker
2970	bg.src = img.src;
2971	// console.log( 'bg src', bg.src );
2972	new Effect.FadeTo( img, 0, 1, 1, {
2973		complete: function() { showFeaturedListingPhoto2( id, listingId, index, interval ); }
2974	} );
2975}
2976
2977function showFeaturedListingPhoto2( id, listingId, index, interval )
2978{
2979	if( !interval ) {
2980		interval = document.featuredListingsPhotoRefreshInterval;
2981	}
2982	
2983	var imgId = id + "-" + listingId + "-image";
2984	
2985	var images = document.featuredListingsHash[id].images[listingId];
2986	if( !images ) {
2987		return;
2988	}
2989	if( images.length <= index ) {
2990		index = 0;
2991	}
2992	
2993	var img = null;
2994	var imgId = id + "-" + listingId + "-image";
2995	var w =  document.getElementById(id);
2996	var imgs = w.getElementsByTagName( "img" );
2997	if( imgs && imgs.length > 0 ) {
2998		for( var i=0; i<imgs.length; ++i ) {
2999			if( imgs[i].rel == imgId ) {
3000				img = imgs[i];
3001				break;
3002			}
3003		}
3004	}
3005	
3006	//var img = $(id + "-" + listingId + "-image");
3007	if( !img ) {
3008		return;
3009	}
3010	img.onload = function() {
3011		new Effect.FadeTo( img, 1, 500, 50 );
3012
3013		setTimeout( "showFeaturedListingPhoto1('" + id + "', '" + listingId + "', " + index + ", " + interval + " )", interval );
3014	};
3015	index++;
3016	// console.log( 'img src before', img.src );
3017	setTimeout(function() {
3018		if( img.src != images[index]) {
3019			img.src = images[index];
3020		}
3021	}, 100 );
3022	// console.log( 'img src after', img.src );
3023
3024
3025}
3026
3027var prefetchedListingsNG = {};
3028
3029function rotateFeaturedListingsNG( id, listingIds, interval )
3030{
3031	if( document.hidden ) {
3032		return;
3033	}
3034	var w = document.getElementById(id);
3035	webletGateway.renderWeblet( document.pageName, id, 
3036		{ "ListingIds": listingIds, "ajaxGetAll" : "true" }, {
3037		callback: function( result ) {
3038			if( result.content ) {
3039			
3040				// strip the wrapper
3041				var content = result.content;
3042				var idx = content.indexOf( '>' );
3043				if( idx != -1 ) {
3044					content = content.substring( idx + 1 );
3045					idx = content.indexOf( '>' );
3046					if( idx != -1 ) {
3047						content = content.substring( idx + 1 );
3048					}
3049				}
3050				idx = content.lastIndexOf( "</div></div>" );
3051				if( idx != -1 ) {
3052					content = content.substring( 0, idx );
3053				}
3054			
3055				var tks = content.split( "\=\_\=\_\=\_\=\_\=" );
3056				prefetchedListingsNG[id] = tks;
3057				
3058				var pos = 1;
3059				if( tks.length == 1 ) {
3060					pos = 0;
3061				}
3062				
3063				new Effect.FadeTo( id, 0.1, 100, 10, { 
3064					complete: function() { rotateFeaturedListingsAfterFadeNG( id, pos, interval ); }
3065					});
3066			}
3067		},
3068		errorHandler: function( error ) {
3069			return;
3070		}
3071	});
3072}
3073
3074function getMatches(string, regex, index) {
3075	index || (index = 1); // default to the first capturing group
3076	var matches = [];
3077	var match;
3078	while (match = regex.exec(string)) {
3079		matches.push(match[index]);
3080	}
3081	return matches;
3082}
3083
3084function rotateFeaturedListingsAfterFadeNG( id, pos, interval )
3085{
3086	if( !prefetchedListingsNG[id] ) {
3087		return;
3088	}
3089	if( pos >= prefetchedListingsNG[id].length ) {
3090		return; // bail: something is wrong
3091	}
3092	var content = prefetchedListingsNG[id][pos];
3093	var scripts = getMatches(content, /<script[^>]*>(.*?)<\/script>/gmi).join('\n');
3094	content = content.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gmi, "")
3095	/*var idx = content.indexOf( "<script>" );
3096	if( idx != -1 ) {
3097		content = content.substring( 0, idx );
3098	}*/
3099	
3100	var elem = document.getElementById(id);
3101	
3102	elem = elem.children[0]; // inner-weblet
3103	
3104	var h2 = null;
3105	var viewAll = null;
3106	
3107	var h2s = elem.getElementsByTagName( "h2" );
3108	if( h2s && h2s.length > 0 && h2s[0] && h2s[0].className === "weblet_featured-listings-title" ) {
3109		h2 = h2s[0];
3110	}
3111	
3112	if( elem.children[elem.children.length-1] && 
3113			elem.children[elem.children.length-1].className === "weblet_featured-listings-view-all" ) {
3114		viewAll = elem.children[elem.children.length-1];
3115	}
3116	
3117	if( !elem.existingRRectId ) {
3118		var existingRRectId = null;
3119		var divs = elem.getElementsByTagName("div");
3120		for( var i=0; i<divs.length; ++i ) {
3121			if( divs[i].className && 
3122				divs[i].className.indexOf( "leadin_style" ) != -1 &&
3123				divs[i].id ) {
3124				existingRRectId = divs[i].id;
3125				break;
3126			}
3127		}
3128		elem.existingRRectId = existingRRectId;
3129	}
3130	
3131	elem.innerHTML = content;
3132	if( h2 ) {
3133		elem.insertBefore( h2, elem.children[0] );
3134	}
3135	
3136	if( viewAll ) {
3137		// no need to re-append what is already there
3138		//elem.appendChild( viewAll );
3139	}
3140	eval(scripts);
3141
3142	if( elem.existingRRectId ) {
3143		setTimeout( function() {
3144			var fx = allFx[elem.existingRRectId];
3145			if( fx && fx.applyOnResizeFx ) {
3146				var divs = elem.getElementsByTagName("div");
3147				for( var i=0; i<divs.length; ++i ) {
3148					if( divs[i].className && 
3149						divs[i].className.indexOf( "leadin_style" ) != -1 &&
3150						divs[i].id ) {
3151						fx.applyOnLoadFx( divs[i].id );
3152					}
3153				}
3154			}
3155		}, 102 );
3156	}
3157	
3158	new Effect.FadeTo( id, 1, 100, 10 );
3159	var newPos = pos+1;
3160	if( newPos >= prefetchedListingsNG[id].length ) {
3161		newPos = 0;
3162	}
3163	
3164	if( !interval ) {
3165		interval = document.featuredListingsRefreshInterval;
3166	}
3167	
3168	if( window.location.href.indexOf( 'm=__manage__' ) != -1 ) {
3169		return;
3170	}
3171	
3172	setTimeout( function() {
3173		new Effect.FadeTo( id, 0.1, 100, 10, { 
3174				complete: function() { rotateFeaturedListingsAfterFadeNG( id, newPos, interval ); }
3175				});
3176	}, interval );
3177}
3178
3179function rotateFeaturedListings( id, listingIds, interval )
3180{
3181	if( window.location.href.indexOf( 'm=__manage__' ) != -1 ) {
3182		return;
3183	}
3184
3185	if( true ) {
3186		rotateFeaturedListingsNG( id, listingIds, interval );
3187		return;
3188	}
3189}
3190
3191/* ==== INCLUDE: /js/weblets/responsive/leadins.js ==== */
3192
3193/* leadins js */
3194jQuery( function() {
3195	jQuery( document ).on( "click", ".mrp-leadin *", function(e) {
3196		var $p = jQuery( this ).closest( ".mrp-leadin" );
3197
3198		if( $(this).hasClass( 'ed3-editable') && $("body").hasClass( "ed3-inline-edit-on" ) ) {
3199			return false;
3200		}
3201		var $target = jQuery( e.target );
3202		if( $target && $target.length > 0 && "A" == $target.prop("tagName" ) || $target.closest( "a" ).length > 0 ) {
3203			return true;
3204		}
3205		var url = $p.attr( "data-link" );
3206		if( url ) {
3207			e.stopImmediatePropagation();
3208			if( $p.attr( "data-target" ) ) {
3209				window.open( url );
3210			}
3211			else {
3212				window.location = url;
3213			}
3214			console.log( url );
3215			return false;
3216		}
3217		return true;
3218	});
3219});
3220
3221/* ==== INCLUDE: /js/weblets/responsive/image-banner.js ==== */
3222
3223function mrp_image_banner_rotate( id, index ) {
3224
3225	var $weblet = jQuery( "#" + id );
3226	
3227	if( index >= 0 ) {
3228		var interval = $weblet.data( "animation-interval" );
3229		if( !isNaN( interval ) ) {
3230			clearInterval( interval );
3231		}
3232	}
3233	
3234	var $active = $weblet.find( "ul.images li.mrp-resp-banner-show" );
3235	if( isNaN( index ) || index < 0 ) {
3236		index = parseInt( $active.attr( "data-idx" ) );
3237		if( isNaN( index ) ) {
3238			return;
3239		}
3240		index++;
3241	}
3242	
3243	var $next = $weblet.find( "ul.images li[data-idx=" + index + "]" );
3244	if( $next.length == 0 ) {
3245		// first
3246		index = 0;
3247	}
3248	$next = $weblet.find( "ul.images li[data-idx=" + index + "]" );
3249	
3250	if( $next.length > 0 ) {
3251		$weblet.find( "ul.images li" ).removeClass( "mrp-resp-banner-show" );
3252		$next.addClass( "mrp-resp-banner-show" );
3253		
3254		$weblet.find( ".bullet-nav span.active" ).removeClass( "active" );
3255		$weblet.find( ".bullet-nav span[data-idx=" + index + "]" ).addClass( "active" );
3256	}
3257}
3258
3259function mrp_banner_nav_next( id ) {
3260
3261	var $weblet = jQuery( "#" + id );
3262	var $active = $weblet.find( "ul.images li.mrp-resp-banner-show" );
3263	var idx = parseInt( $active.attr( "data-idx" ) ) || 0;
3264	idx = idx + 1;
3265	if( idx > $weblet.find( ".images > li img" ).length - 1 ) {
3266		idx = 0;
3267	}
3268	mrp_image_banner_rotate( id, idx );
3269	
3270	try {
3271		var interval = $weblet.data( "animation-interval" );
3272		if( !isNaN( interval ) ) {
3273			clearInterval( interval );
3274		}
3275	}
3276	catch( e ) {}
3277}
3278
3279function mrp_banner_nav_prev( id ) {
3280	
3281	var $weblet = jQuery( "#" + id );
3282	var $active = $weblet.find( "ul.images li.mrp-resp-banner-show" );
3283	var idx = parseInt( $active.attr( "data-idx" ) ) || 0;
3284	idx = idx - 1;
3285	if( idx < 0 ) {
3286		idx = $weblet.find( ".images > li img" ).length - 1;
3287	}
3288	mrp_image_banner_rotate( id, idx );
3289	
3290
3291	try {
3292		var interval = $weblet.data( "animation-interval" );
3293		if( !isNaN( interval ) ) {
3294			clearInterval( interval );
3295		}
3296	}
3297	catch( e ) {}
3298}
3299
3300/* ==== INCLUDE: /js/manage/jquery.form.min.js ==== */
3301
3302!function(e){function t(){if(e.fn.ajaxSubmit.debug){var t="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(t):window.opera&&window.opera.postError&&window.opera.postError(t)}}e.fn.ajaxSubmit=function(a){if(!this.length)return t("ajaxSubmit: skipping submit process - no element selected"),this;"function"==typeof a&&(a={success:a});var r=e.trim(this.attr("action"));r&&(r=(r.match(/^([^#]+)/)||[])[1]),r=r||window.location.href||"",a=e.extend(!0,{url:r,type:this.attr("method")||"GET",iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},a);var n={};if(this.trigger("form-pre-serialize",[this,a,n]),n.veto)return t("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(a.beforeSerialize&&!1===a.beforeSerialize(this,a))return t("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var i,o,s=this.formToArray(a.semantic);if(a.data)for(i in a.extraData=a.data,a.data)if(a.data[i]instanceof Array)for(var l in a.data[i])s.push({name:i,value:a.data[i][l]});else o=a.data[i],o=e.isFunction(o)?o():o,s.push({name:i,value:o});if(a.beforeSubmit&&!1===a.beforeSubmit(s,this,a))return t("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[s,this,a,n]),n.veto)return t("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var u=e.param(s);"GET"==a.type.toUpperCase()?(a.url+=(a.url.indexOf("?")>=0?"&":"?")+u,a.data=null):a.data=u;var c=this,f=[];if(a.resetForm&&f.push(function(){c.resetForm()}
3302),a.clearForm&&f.push(function(){c.clearForm()}),!a.dataType&&a.target){var m=a.success||function(){};f.push(function(t){var r=a.replaceTarget?"replaceWith":"html";e(a.target)[r](t).each(m,arguments)})}else a.success&&f.push(a.success);a.success=function(e,t,r){for(var n=a.context||a,i=0,o=f.length;i<o;i++)f[i].apply(n,[e,t,r||c,c])};var d=e("input:file",this).length>0,p="multipart/form-data",h=c.attr("enctype")==p||c.attr("encoding")==p;return!1!==a.iframe&&(d||a.iframe||h)?a.closeKeepAlive?e.get(a.closeKeepAlive,v):v():e.ajax(a),this.trigger("form-submit-notify",[this,a]),this;function v(){var r=c[0];if(e(":input[name=submit],:input[id=submit]",r).length)alert('Error: Form elements must not have name or id of "submit".');else{var n=e.extend(!0,{},e.ajaxSettings,a);n.context=n.context||n;var i="jqFormIO"+(new Date).getTime(),o="_"+i;window[o]=function(){var e=s.data("form-plugin-onload");if(e){e(),window[o]=void 0;try{delete window[o]}catch(e){}}};var s=e('<iframe id="'+i+'" name="'+i+'" src="'+n.iframeSrc+'" onload="window[\'_\'+this.id]()" />'),l=s[0];s.css({position:"absolute",top:"-1000px",left:"-1000px"});var u={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(){this.aborted=1,s.attr("src",n.iframeSrc)}},f=n.global;if(f&&!e.active++&&e.event.trigger("ajaxStart"),f&&e.event.trigger("ajaxSend",[u,n]),n.beforeSend&&!1===n.beforeSend.call(n.context,u,n))n.global&&e.active--;else if(!u.aborted){var m=!1,d=0,p=r.clk;if(p){var h=p.name;h&&!p.disabled&&(n.extraData=n.extraData||{},n.extraData[h]=p.value,"image"==p.type&&(n.extraData[h+".x"]=r.clk_x,n.extraData[h+".y"]=r.clk_y))}n.forceSync?x():setTimeout(x,10);var v,g,b=50}}function x(){var t=c.attr("target"),a=c.attr("action");r.setAttribute("target",i),"POST"!=r.getAttribute("method")&&r.setAttribute("method","POST"),r.getAttribute("action")!=n.url&&r.setAttribute("action",n.url),n.skipEncodingOverride||c.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),n.timeout&&setTimeout(function(){d=!0,y()},n.timeout);var o=[];try{if(n.extraData)for(var l in n.extraData)o.push(e('<input type="hidden" name="'+l+'" value="'+n.extraData[l]+'" />').appendTo(r)[0]);s.appendTo("body"),s.data("form-plugin-onload",y),r.submit()}finally{r.setAttribute("action",a),t?r.setAttribute("target",t):c.removeAttr("target"),e(o).remove()}}function y(){if(!m){s.removeData("form-plugin-onload");var a=!0;try{if(d)throw"timeout";g=l.contentWindow?l.contentWindow.document:l.contentDocument?l.contentDocument:l.document;var r="xml"==n.dataType||g.XMLDocument||e.isXMLDoc(g);if(t("isXml="+r),!r&&window.opera&&(null==g.body||""==g.body.innerHTML)&&--b)return t("requeing onLoad callback, DOM not available"),void setTimeout(y,250);m=!0,u.responseText=g.documentElement?g.documentElement.innerHTML:null,u.responseXML=g.XMLDocument?g.XMLDocument:g,u.getResponseHeader=function(e){return{"content-type":n.dataType}[e]};
3302var i=/(json|script)/.test(n.dataType);if(i||n.textarea){var o=g.getElementsByTagName("textarea")[0];if(o)u.responseText=o.value;else if(i){var c=g.getElementsByTagName("pre")[0],p=g.getElementsByTagName("body")[0];c?u.responseText=c.innerHTML:p&&(u.responseText=p.innerHTML)}}else"xml"!=n.dataType||u.responseXML||null==u.responseText||(u.responseXML=function(e,t){window.ActiveXObject?((t=new ActiveXObject("Microsoft.XMLDOM")).async="false",t.loadXML(e)):t=(new DOMParser).parseFromString(e,"text/xml");return t&&t.documentElement&&"parsererror"!=t.documentElement.tagName?t:null}(u.responseText));v=e.httpData(u,n.dataType)}catch(r){t("error caught:",r),a=!1,u.error=r,e.handleError(n,u,"error",r)}a&&(n.success.call(n.context,v,"success",u),f&&e.event.trigger("ajaxSuccess",[u,n])),f&&e.event.trigger("ajaxComplete",[u,n]),f&&!--e.active&&e.event.trigger("ajaxStop"),n.complete&&n.complete.call(n.context,u,a?"success":"error"),setTimeout(function(){s.removeData("form-plugin-onload"),s.remove(),u.responseXML=null},100)}}}},e.fn.ajaxForm=function(a){if(0===this.length){var r={s:this.selector,c:this.context};return!e.isReady&&r.s?(t("DOM not ready, queuing ajaxForm"),e(function(){e(r.s,r.c).ajaxForm(a)}),this):(t("terminating; zero elements found by selector"+(e.isReady?"":" (DOM not ready)")),this)}return this.ajaxFormUnbind().bind("submit.form-plugin",function(t){t.isDefaultPrevented()||(t.preventDefault(),e(this).ajaxSubmit(a))}).bind("click.form-plugin",function(t){var a=t.target,r=e(a);if(!r.is(":submit,input:image")){var n=r.closest(":submit");if(0==n.length)return;a=n[0]}var i=this;if(i.clk=a,"image"==a.type)if(null!=t.offsetX)i.clk_x=t.offsetX,i.clk_y=t.offsetY;else if("function"==typeof e.fn.offset){var o=r.offset();i.clk_x=t.pageX-o.left,i.clk_y=t.pageY-o.top}else i.clk_x=t.pageX-a.offsetLeft,i.clk_y=t.pageY-a.offsetTop;setTimeout(function(){i.clk=i.clk_x=i.clk_y=null},100)})},e.fn.ajaxFormUnbind=function(){return this.unbind("submit.form-plugin click.form-plugin")},e.fn.formToArray=function(t){var a=[];if(0===this.length)return a;var r,n,i,o,s,l,u,c=this[0],f=t?c.getElementsByTagName("*"):c.elements;if(!f)return a;for(r=0,l=f.length;r<l;r++)if(i=(s=f[r]).name)if(t&&c.clk&&"image"==s.type)s.disabled||c.clk!=s||(a.push({name:i,value:e(s).val()}),a.push({name:i+".x",value:c.clk_x},{name:i+".y",value:c.clk_y}));else if((o=e.fieldValue(s,!0))&&o.constructor==Array)for(n=0,u=o.length;n<u;n++)a.push({name:i,value:o[n]});else null!=o&&a.push({name:i,value:o});if(!t&&c.clk){var m=e(c.clk),d=m[0];(i=d.name)&&!d.disabled&&"image"==d.type&&(a.push({name:i,value:m.val()}),a.push({name:i+".x",value:c.clk_x},{name:i+".y",value:c.clk_y}))}return a},e.fn.formSerialize=function(t){return e.param(this.formToArray(t))},e.fn.fieldSerialize=function(t){var a=[];return this.each(function(){var r=this.name;if(r){var n=e.fieldValue(this,t);if(n&&n.constructor==Array)for(var i=0,o=n.length;i<o;i++)a.push({name:r,value:n[i]});else null!=n&&a.push({name:this.name,value:n})}}),e.param(a)},e.fn.fieldValue=function(t){for(var a=[],r=0,n=this.length;r<n;r++){var i=this[r],o=e.fieldValue(i,t);null==o||o.constructor==Array&&!o.length||(o.constructor==Array?e.merge(a,o):a.push(o))}return a},e.fieldValue=function(t,a){var r=t.name,n=t.type,i=t.tagName.toLowerCase();if(void 0===a&&(a=!0),a&&(!r||t.disabled||"reset"==n||"button"==n||("checkbox"==n||"radio"==n)&&!t.checked||("submit"==n||"image"==n)&&t.form&&t.form.clk!=t||"select"==i&&-1==t.selectedIndex))return null;if("select"==i){var o=t.selectedIndex;if(o<0)return null;for(var s=[],l=t.options,u="select-one"==n,c=u?o+1:l.length,f=u?o:0;f<c;f++){var m=l[f];if(m.selected){var d=m.value;if(d||(d=m.attributes&&m.attributes.value&&!m.attributes.value.specified?m.text:m.value),u)return d;s.push(d)}}return s}return e(t).val()},e.fn.clearForm=function(){return this.each(function(){e("input,select,textarea",this).clearFields()})},e.fn.clearFields=e.fn.clearInputs=function(){return this.each(function(){var e=this.type,t=this.tagName.toLowerCase();"text"==e||"password"==e||"textarea"==t?this.value="":"checkbox"==e||"radio"==e?this.checked=!1:"select"==t&&(this.selectedIndex=-1)})},e.fn.resetForm=function(){return this.each(function(){("function"==typeof this.reset||"object"==typeof this.reset&&!this.reset.nodeType)&&this.reset()})},e.fn.enable=function(e){return void 0===e&&(e=!0),this.each(function(){this.disabled=!e})},e.fn.selected=function(t){return void 0===t&&(t=!0),this.each(function(){var a=this.type;if("checkbox"==a||"radio"==a)this.checked=t;else if("option"==this.tagName.toLowerCase()){var r=e(this).parent("select");t&&r[0]&&"select-one"==r[0].type&&r.find("option").selected(!1),this.selected=t}})}}(jQuery);
3303
3304/* ==== INCLUDE: /js/weblets/responsive/forms.js ==== */
3305
3306/* forms */
3307jQuery( function($) {
3308
3309	var $form = $( "form.mrp-dynamic-form" );
3310
3311	window.__hookupAjaxForm = function( $form ) {
3312		$form.ajaxForm({
3313			contentType: "application/x-www-form-urlencoded; charset=UTF-8",
3314			beforeSubmit: function(arr, $form, options) {
3315				//$form.find( ".sending-feedback" ).show();
3316				var $submit = $form.find( ".submit-button" );
3317				var submitText = $submit.text();
3318				$submit.attr( "data-orig-text", submitText || "");
3319				$submit.attr("disabled","disabled").text("Sending...");
3320				console.log( "SUBMITTING" );
3321				return true;
3322			},
3323			success : function( response, status, xhr, $form ) {
3324				//console.log( "SUCCESS", response );
3325				//$form.find( ".sending-feedback" ).hide();
3326				var $submit = $form.find( ".submit-button");
3327				var origText = $submit.attr("data-orig-text") || "Submit";
3328				$submit.removeAttr("disabled");
3329				$submit.text(origText);
3330				if( xhr.getResponseHeader( "Location" ) ) {
3331					window.location = xhr.getResponseHeader( "Location" );
3332					return;
3333				}
3334				var $doc = jQuery( response );
3335				var $inform = $doc.find( "#" + $form.attr( "id" ) );
3336				console.log( $inform.html() );
3337				//$form.empty();
3338				//$form.html( $inform.html() );
3339				var $message = $inform.find( ".form-success" );
3340				$message.remove();
3341
3342				var $error = $inform.find( ".form-error" );
3343
3344				// to support old <center> case, just in case
3345				var $center = $form.children( "center" );
3346				if( $center.length > 0 ) {
3347					$form.append( $center.contents() );
3348				}
3349
3350				$form.contents().filter( function() {
3351					if( $(this).attr( "name" ) == "__sh" ) {
3352						return false;
3353					}
3354					else if( $(this).attr( "name" ) == "__src_url" ) {
3355						return false;
3356					}
3357					return true;
3358				}).remove();
3359
3360				$inform.find( "script" ).remove();
3361
3362				var match = /.*name=\"__sh\" value=\"([^\"]*)\".*/gm.exec(response);
3363				var hash = match && match[1] ? match[1] : null
3364
3365				$form.append( $inform.contents().filter( function() {
3366					if( this.nodeName == "SCRIPT" || this.nodeName == "script" ) {
3367						return false;
3368					}
3369					return true;
3370				}));
3371
3372				if( hash ) {
3373					$form.find( "[name=__sh]").val(hash)
3374				}
3375
3376				if( $message.text() ) {
3377					showQuickMessage( $message.text() );
3378				}
3379				setTimeout(function() {
3380					if( $error.length > 0 ) {
3381						$error[0].scrollIntoView({
3382							behavior: 'smooth',
3383							block: 'center',
3384						})
3385					}
3386				}, 100 )
3387
3388				if( !$error.text() && window.dataLayer ) {
3389					window.dataLayer.push( {
3390						event: 'formSubmitted',
3391						formURL: window.location.href,
3392						title: document.title,
3393					})
3394				}
3395			},
3396			error : function() {
3397
3398			}
3399		});
3400
3401			// listen for `invalid` events on all form inputs
3402		$form.find(':input').on('invalid', function(event) {
3403
3404			var input = $(this);
3405
3406			// the first invalid element in the form
3407			var first = $form.find(':invalid').first();
3408
3409			// only handle if this is the first invalid input
3410			if (input[0] === first[0]) {
3411
3412				// schedule another submit on invalid to make popups show
3413				// otherwise, they disappear after scroll
3414
3415				if( !$form.validating ) {
3416					setTimeout( function() {
3417						$form[0].reportValidity();
3418						$form.validating = false;
3419					}, 500 );
3420				}
3421
3422				$form.validating = true;
3423			}
3424		});
3425	}
3426
3427	window.__hookupAjaxForm( $form );
3428
3429});

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