PageSourceSearch

https://wanglongqi.github.io/public/js/htmlwidgets-0.8/htmlwidgets.js

js wanglongqi.github.io collected 2026-10-03 10:09:29 UTC 30,901 bytes, 836 lines download raw bytes

1(function() {
2  // If window.HTMLWidgets is already defined, then use it; otherwise create a
3  // new object. This allows preceding code to set options that affect the
4  // initialization process (though none currently exist).
5  window.HTMLWidgets = window.HTMLWidgets || {};
6
7  // See if we're running in a viewer pane. If not, we're in a web browser.
8  var viewerMode = window.HTMLWidgets.viewerMode =
9      /\bviewer_pane=1\b/.test(window.location);
10
11  // See if we're running in Shiny mode. If not, it's a static document.
12  // Note that static widgets can appear in both Shiny and static modes, but
13  // obviously, Shiny widgets can only appear in Shiny apps/documents.
14  var shinyMode = window.HTMLWidgets.shinyMode =
15      typeof(window.Shiny) !== "undefined" && !!window.Shiny.outputBindings;
16
17  // We can't count on jQuery being available, so we implement our own
18  // version if necessary.
19  function querySelectorAll(scope, selector) {
20    if (typeof(jQuery) !== "undefined" && scope instanceof jQuery) {
21      return scope.find(selector);
22    }
23    if (scope.querySelectorAll) {
24      return scope.querySelectorAll(selector);
25    }
26  }
27
28  function asArray(value) {
29    if (value === null)
30      return [];
31    if ($.isArray(value))
32      return value;
33    return [value];
34  }
35
36  // Implement jQuery's extend
37  function extend(target /*, ... */) {
38    if (arguments.length == 1) {
39      return target;
40    }
41    for (var i = 1; i < arguments.length; i++) {
42      var source = arguments[i];
43      for (var prop in source) {
44        if (source.hasOwnProperty(prop)) {
45          target[prop] = source[prop];
46        }
47      }
48    }
49    return target;
50  }
51
52  // IE8 doesn't support Array.forEach.
53  function forEach(values, callback, thisArg) {
54    if (values.forEach) {
55      values.forEach(callback, thisArg);
56    } else {
57      for (var i = 0; i < values.length; i++) {
58        callback.call(thisArg, values[i], i, values);
59      }
60    }
61  }
62
63  // Replaces the specified method with the return value of funcSource.
64  //
65  // Note that funcSource should not BE the new method, it should be a function
66  // that RETURNS the new method. funcSource receives a single argument that is
67  // the overridden method, it can be called from the new method. The overridden
68  // method can be called like a regular function, it has the target permanently
69  // bound to it so "this" will work correctly.
70  function overrideMethod(target, methodName, funcSource) {
71    var superFunc = target[methodName] || function() {};
72    var superFuncBound = function() {
73      return superFunc.apply(target, arguments);
74    };
75    target[methodName] = funcSource(superFuncBound);
76  }
77
78  // Add a method to delegator that, when invoked, calls
79  // delegatee.methodName. If there is no such method on
80  // the delegatee, but there was one on delegator before
81  // delegateMethod was called, then the original version
82  // is invoked instead.
83  // For example:
84  //
85  // var a = {
86  //   method1: function() { console.log('a1'); }
87  //   method2: function() { console.log('a2'); }
88  // };
89  // var b = {
90  //   method1: function() { console.log('b1'); }
91  // };
92  // delegateMethod(a, b, "method1");
93  // delegateMethod(a, b, "method2");
94  // a.method1();
95  // a.method2();
96  //
97  // The output would be "b1", "a2".
98  function delegateMethod(delegator, delegatee, methodName) {
99    var inherited = delegator[methodName];
100    delegator[methodName] = function() {
101      var target = delegatee;
102      var method = delegatee[methodName];
103
104      // The method doesn't exist on the delegatee. Instead,
105      // call the method on the delegator, if it exists.
106      if (!method) {
107        target = delegator;
108        method = inherited;
109      }
110
111      if (method) {
112        return method.apply(target, arguments);
113      }
114    };
115  }
116
117  // Implement a vague facsimilie of jQuery's data method
118  function elementData(el, name, value) {
119    if (arguments.length == 2) {
120      return el["htmlwidget_data_" + name];
121    } else if (arguments.length == 3) {
122      el["htmlwidget_data_" + name] = value;
123      return el;
124    } else {
125      throw new Error("Wrong number of arguments for elementData: " +
126        arguments.length);
127    }
128  }
129
130  // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
131  function escapeRegExp(str) {
132    return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
133  }
134
135  function hasClass(el, className) {
136    var re = new RegExp("\\b" + escapeRegExp(className) + "\\b");
137    return re.test(el.className);
138  }
139
140  // elements - array (or array-like object) of HTML elements
141  // className - class name to test for
142  // include - if true, only return elements with given className;
143  //   if false, only return elements *without* given className
144  function filterByClass(elements, className, include) {
145    var results = [];
146    for (var i = 0; i < elements.length; i++) {
147      if (hasClass(elements[i], className) == include)
148        results.push(elements[i]);
149    }
150    return results;
151  }
152
153  function on(obj, eventName, func) {
154    if (obj.addEventListener) {
155      obj.addEventListener(eventName, func, false);
156    } else if (obj.attachEvent) {
157      obj.attachEvent(eventName, func);
158    }
159  }
160
161  function off(obj, eventName, func) {
162    if (obj.removeEventListener)
163      obj.removeEventListener(eventName, func, false);
164    else if (obj.detachEvent) {
165      obj.detachEvent(eventName, func);
166    }
167  }
168
169  // Translate array of values to top/right/bottom/left, as usual with
170  // the "padding" CSS property
171  // https://developer.mozilla.org/en-US/docs/Web/CSS/padding
172  function unpackPadding(value) {
173    if (typeof(value) === "number")
174      value = [value];
175    if (value.length === 1) {
176      return {top: value[0], right: value[0], bottom: value[0], left: value[0]};
177    }
178    if (value.length === 2) {
179      return {top: value[0], right: value[1], bottom: value[0], left: value[1]};
180    }
181    if (value.length === 3) {
182      return {top: value[0], right: value[1], bottom: value[2], left: value[1]};
183    }
184    if (value.length === 4) {
185      return {top: value[0], right: value[1], bottom: value[2], left: value[3]};
186    }
187  }
188
189  // Convert an unpacked padding object to a CSS value
190  function paddingToCss(paddingObj) {
191    return paddingObj.top + "px " + paddingObj.right + "px " + paddingObj.bottom + "px " + paddingObj.left + "px";
192  }
193
194  // Makes a number suitable for CSS
195  function px(x) {
196    if (typeof(x) === "number")
197      return x + "px";
198    else
199      return x;
200  }
201
202  // Retrieves runtime widget sizing information for an element.
203  // The return value is either null, or an object with fill, padding,
204  // defaultWidth, defaultHeight fields.
205  function sizingPolicy(el) {
206    var sizingEl = document.querySelector("script[data-for='" + el.id + "'][type='application/htmlwidget-sizing']");
207    if (!sizingEl)
208      return null;
209    var sp = JSON.parse(sizingEl.textContent || sizingEl.text || "{}");
210    if (viewerMode) {
211      return sp.viewer;
212    } else {
213      return sp.browser;
214    }
215  }
216
217  // @param tasks Array of strings (or falsy value, in which case no-op).
218  //   Each element must be a valid JavaScript expression that yields a
219  //   function. Or, can be an array of objects with "code" and "data"
220  //   properties; in this case, the "code" property should be a string
221  //   of JS that's an expr that yields a function, and "data" should be
222  //   an object that will be added as an additional argument when that
223  //   function is called.
224  // @param target The object that will be "this" for each function
225  //   execution.
226  // @param args Array of arguments to be passed to the functions. (The
227  //   same arguments will be passed to all functions.)
228  function evalAndRun(tasks, target, args) {
229    if (tasks) {
230      forEach(tasks, function(task) {
231        var theseArgs = args;
232        if (typeof(task) === "object") {
233          theseArgs = theseArgs.concat([task.data]);
234          task = task.code;
235        }
236        var taskFunc = eval("(" + task + ")");
237        if (typeof(taskFunc) !== "function") {
238          throw new Error("Task must be a function! Source:\n" + task);
239        }
240        taskFunc.apply(target, theseArgs);
241      });
242    }
243  }
244
245  function initSizing(el) {
246    var sizing = sizingPolicy(el);
247    if (!sizing)
248      return;
249
250    var cel = document.getElementById("htmlwidget_container");
251    if (!cel)
252      return;
253
254    if (typeof(sizing.padding) !== "undefined") {
255      document.body.style.margin = "0";
256      document.body.style.padding = paddingToCss(unpackPadding(sizing.padding));
257    }
258
259    if (sizing.fill) {
260      document.body.style.overflow = "hidden";
261      document.body.style.width = "100%";
262      document.body.style.height = "100%";
263      document.documentElement.style.width = "100%";
264      document.documentElement.style.height = "100%";
265      if (cel) {
266        cel.style.position = "absolute";
267        var pad = unpackPadding(sizing.padding);
268        cel.style.top = pad.top + "px";
269        cel.style.right = pad.right + "px";
270        cel.style.bottom = pad.bottom + "px";
271        cel.style.left = pad.left + "px";
272        el.style.width = "100%";
273        el.style.height = "100%";
274      }
275
276      return {
277        getWidth: function() { return cel.offsetWidth; },
278        getHeight: function() { return cel.offsetHeight; }
279      };
280
281    } else {
282      el.style.width = px(sizing.width);
283      el.style.height = px(sizing.height);
284
285      return {
286        getWidth: function() { return el.offsetWidth; },
287        getHeight: function() { return el.offsetHeight; }
288      };
289    }
290  }
291
292  // Default implementations for methods
293  var defaults = {
294    find: function(scope) {
295      return querySelectorAll(scope, "." + this.name);
296    },
297    renderError: function(el, err) {
298      var $el = $(el);
299
300      this.clearError(el);
301
302      // Add all these error classes, as Shiny does
303      var errClass = "shiny-output-error";
304      if (err.type !== null) {
305        // use the classes of the error condition as CSS class names
306        errClass = errClass + " " + $.map(asArray(err.type), function(type) {
307          return errClass + "-" + type;
308        }).join(" ");
309      }
310      errClass = errClass + " htmlwidgets-error";
311
312      // Is el inline or block? If inline or inline-block, just display:none it
313      // and add an inline error.
314      var display = $el.css("display");
315      $el.data("restore-display-mode", display);
316
317      if (display === "inline" || display === "inline-block") {
318        $el.hide();
319        if (err.message !== "") {
320          var errorSpan = $("<span>").addClass(errClass);
321          errorSpan.text(err.message);
322          $el.after(errorSpan);
323        }
324      } else if (display === "block") {
325        // If block, add an error just after the el, set visibility:none on the
326        // el, and position the error to be on top of the el.
327        // Mark it with a unique ID and CSS class so we can remove it later.
328        $el.css("visibility", "hidden");
329        if (err.message !== "") {
330          var errorDiv = $("<div>").addClass(errClass).css("position", "absolute")
331            .css("top", el.offsetTop)
332            .css("left", el.offsetLeft)
333            // setting width can push out the page size, forcing otherwise
334            // unnecessary scrollbars to appear and making it impossible for
335            // the element to shrink; so use max-width instead
336            .css("maxWidth", el.offsetWidth)
337            .css("height", el.offsetHeight);
338          errorDiv.text(err.message);
339          $el.after(errorDiv);
340
341          // Really dumb way to keep the size/position of the error in sync with
342          // the parent element as the window is resized or whatever.
343          var intId = setInterval(function() {
344            if (!errorDiv[0].parentElement) {
345              clearInterval(intId);
346              return;
347            }
348            errorDiv
349              .css("top", el.offsetTop)
350              .css("left", el.offsetLeft)
351              .css("maxWidth", el.offsetWidth)
352              .css("height", el.offsetHeight);
353          }, 500);
354        }
355      }
356    },
357    clearError: function(el) {
358      var $el = $(el);
359      var display = $el.data("restore-display-mode");
360      $el.data("restore-display-mode", null);
361
362      if (display === "inline" || display === "inline-block") {
363        if (display)
364          $el.css("display", display);
365        $(el.nextSibling).filter(".htmlwidgets-error").remove();
366      } else if (display === "block"){
367        $el.css("visibility", "inherit");
368        $(el.nextSibling).filter(".htmlwidgets-error").remove();
369      }
370    },
371    sizing: {}
372  };
373
374  // Called by widget bindings to register a new type of widget. The definition
375  // object can contain the following properties:
376  // - name (required) - A string indicating the binding name, which will be
377  //   used by default as the CSS classname to look for.
378  // - initialize (optional) - A function(el) that will be called once per
379  //   widget element; if a value is returned, it will be passed as the third
380  //   value to renderValue.
381  // - renderValue (required) - A function(el, data, initValue) that will be
382  //   called with data. Static contexts will cause this to be called once per
383  //   element; Shiny apps will cause this to be called multiple times per
384  //   element, as the data changes.
385  window.HTMLWidgets.widget = function(definition) {
386    if (!definition.name) {
387      throw new Error("Widget must have a name");
388    }
389    if (!definition.type) {
390      throw new Error("Widget must have a type");
391    }
392    // Currently we only support output widgets
393    if (definition.type !== "output") {
394      throw new Error("Unrecognized widget type '" + definition.type + "'");
395    }
396    // TODO: Verify that .name is a valid CSS classname
397
398    // Support new-style instance-bound definitions. Old-style class-bound
399    // definitions have one widget "object" per widget per type/class of
400    // widget; the renderValue and resize methods on such widget objects
401    // take el and instance arguments, because the widget object can't
402    // store them. New-style instance-bound definitions have one widget
403    // object per widget instance; the definition that's passed in doesn't
404    // provide renderValue or resize methods at all, just the single method
405    //   factory(el, width, height)
406    // which returns an object that has renderValue(x) and resize(w, h).
407    // This enables a far more natural programming style for the widget
408    // author, who can store per-instance state using either OO-style
409    // instance fields or functional-style closure variables (I guess this
410    // is in contrast to what can only be called C-style pseudo-OO which is
411    // what we required before).
412    if (definition.factory) {
413      definition = createLegacyDefinitionAdapter(definition);
414    }
415
416    if (!definition.renderValue) {
417      throw new Error("Widget must have a renderValue function");
418    }
419
420    // For static rendering (non-Shiny), use a simple widget registration
421    // scheme. We also use this scheme for Shiny apps/documents that also
422    // contain static widgets.
423    window.HTMLWidgets.widgets = window.HTMLWidgets.widgets || [];
424    // Merge defaults into the definition; don't mutate the original definition.
425    var staticBinding = extend({}, defaults, definition);
426    overrideMethod(staticBinding, "find", function(superfunc) {
427      return function(scope) {
428        var results = superfunc(scope);
429        // Filter out Shiny outputs, we only want the static kind
430        return filterByClass(results, "html-widget-output", false);
431      };
432    });
433    window.HTMLWidgets.widgets.push(staticBinding);
434
435    if (shinyMode) {
436      // Shiny is running. Register the definition with an output binding.
437      // The definition itself will not be the output binding, instead
438      // we will make an output binding object that delegates to the
439      // definition. This is because we foolishly used the same method
440      // name (renderValue) for htmlwidgets definition and Shiny bindings
441      // but they actually have quite different semantics (the Shiny
442      // bindings receive data that includes lots of metadata that it
443      // strips off before calling htmlwidgets renderValue). We can't
444      // just ignore the difference because in some widgets it's helpful
445      // to call this.renderValue() from inside of resize(), and if
446      // we're not delegating, then that call will go to the Shiny
447      // version instead of the htmlwidgets version.
448
449      // Merge defaults with definition, without mutating either.
450      var bindingDef = extend({}, defaults, definition);
451
452      // This object will be our actual Shiny binding.
453      var shinyBinding = new Shiny.OutputBinding();
454
455      // With a few exceptions, we'll want to simply use the bindingDef's
456      // version of methods if they are available, otherwise fall back to
457      // Shiny's defaults. NOTE: If Shiny's output bindings gain additional
458      // methods in the future, and we want them to be overrideable by
459      // HTMLWidget binding definitions, then we'll need to add them to this
460      // list.
461      delegateMethod(shinyBinding, bindingDef, "getId");
462      delegateMethod(shinyBinding, bindingDef, "onValueChange");
463      delegateMethod(shinyBinding, bindingDef, "onValueError");
464      delegateMethod(shinyBinding, bindingDef, "renderError");
465      delegateMethod(shinyBinding, bindingDef, "clearError");
466      delegateMethod(shinyBinding, bindingDef, "showProgress");
467
468      // The find, renderValue, and resize are handled differently, because we
469      // want to actually decorate the behavior of the bindingDef methods.
470
471      shinyBinding.find = function(scope) {
472        var results = bindingDef.find(scope);
473
474        // Only return elements that are Shiny outputs, not static ones
475        var dynamicResults = results.filter(".html-widget-output");
476
477        // It's possible that whatever caused Shiny to think there might be
478        // new dynamic outputs, also caused there to be new static outputs.
479        // Since there might be lots of different htmlwidgets bindings, we
480        // schedule execution for later--no need to staticRender multiple
481        // times.
482        if (results.length !== dynamicResults.length)
483          scheduleStaticRender();
484
485        return dynamicResults;
486      };
487
488      // Wrap renderValue to handle initialization, which unfortunately isn't
489      // supported natively by Shiny at the time of this writing.
490
491      shinyBinding.renderValue = function(el, data) {
492        // Resolve strings marked as javascript literals to objects
493        if (!(data.evals instanceof Array)) data.evals = [data.evals];
494        for (var i = 0; data.evals && i < data.evals.length; i++) {
495          window.HTMLWidgets.evaluateStringMember(data.x, data.evals[i]);
496        }
497        if (!bindingDef.renderOnNullValue) {
498          if (data.x === null) {
499            el.style.visibility = "hidden";
500            return;
501          } else {
502            el.style.visibility = "inherit";
503          }
504        }
505        if (!elementData(el, "initialized")) {
506          initSizing(el);
507
508          elementData(el, "initialized", true);
509          if (bindingDef.initialize) {
510            var result = bindingDef.initialize(el, el.offsetWidth,
511              el.offsetHeight);
512            elementData(el, "init_result", result);
513          }
514        }
515        Shiny.renderDependencies(data.deps);
516        bindingDef.renderValue(el, data.x, elementData(el, "init_result"));
517        evalAndRun(data.jsHooks.render, elementData(el, "init_result"), [el, data.x]);
518      };
519
520      // Only override resize if bindingDef implements it
521      if (bindingDef.resize) {
522        shinyBinding.resize = function(el, width, height) {
523          // Shiny can call resize before initialize/renderValue have been
524          // called, which doesn't make sense for widgets.
525          if (elementData(el, "initialized")) {
526            bindingDef.resize(el, width, height, elementData(el, "init_result"));
527          }
528        };
529      }
530
531      Shiny.outputBindings.register(shinyBinding, bindingDef.name);
532    }
533  };
534
535  var scheduleStaticRenderTimerId = null;
536  function scheduleStaticRender() {
537    if (!scheduleStaticRenderTimerId) {
538      scheduleStaticRenderTimerId = setTimeout(function() {
539        scheduleStaticRenderTimerId = null;
540        window.HTMLWidgets.staticRender();
541      }, 1);
542    }
543  }
544
545  // Render static widgets after the document finishes loading
546  // Statically render all elements that are of this widget's class
547  window.HTMLWidgets.staticRender = function() {
548    var bindings = window.HTMLWidgets.widgets || [];
549    forEach(bindings, function(binding) {
550      var matches = binding.find(document.documentElement);
551      forEach(matches, function(el) {
552        var sizeObj = initSizing(el, binding);
553
554        if (hasClass(el, "html-widget-static-bound"))
555          return;
556        el.className = el.className + " html-widget-static-bound";
557
558        var initResult;
559        if (binding.initialize) {
560          initResult = binding.initialize(el,
561            sizeObj ? sizeObj.getWidth() : el.offsetWidth,
562            sizeObj ? sizeObj.getHeight() : el.offsetHeight
563          );
564          elementData(el, "init_result", initResult);
565        }
566
567        if (binding.resize) {
568          var lastSize = {};
569          var resizeHandler = function(e) {
570            var size = {
571              w: sizeObj ? sizeObj.getWidth() : el.offsetWidth,
572              h: sizeObj ? sizeObj.getHeight() : el.offsetHeight
573            };
574            if (size.w === 0 && size.h === 0)
575              return;
576            if (size.w === lastSize.w && size.h === lastSize.h)
577              return;
578            lastSize = size;
579            binding.resize(el, size.w, size.h, initResult);
580          };
581
582          on(window, "resize", resizeHandler);
583
584          // This is needed for cases where we're running in a Shiny
585          // app, but the widget itself is not a Shiny output, but
586          // rather a simple static widget. One example of this is
587          // an rmarkdown document that has runtime:shiny and widget
588          // that isn't in a render function. Shiny only knows to
589          // call resize handlers for Shiny outputs, not for static
590          // widgets, so we do it ourselves.
591          if (window.jQuery) {
592            window.jQuery(document).on(
593              "shown.htmlwidgets shown.bs.tab.htmlwidgets shown.bs.collapse.htmlwidgets",
594              resizeHandler
595            );
596            window.jQuery(document).on(
597              "hidden.htmlwidgets hidden.bs.tab.htmlwidgets hidden.bs.collapse.htmlwidgets",
598              resizeHandler
599            );
600          }
601
602          // This is needed for the specific case of ioslides, which
603          // flips slides between display:none and display:block.
604          // Ideally we would not have to have ioslide-specific code
605          // here, but rather have ioslides raise a generic event,
606          // but the rmarkdown package just went to CRAN so the
607          // window to getting that fixed may be long.
608          if (window.addEventListener) {
609            // It's OK to limit this to window.addEventListener
610            // browsers because ioslides itself only supports
611            // such browsers.
612            on(document, "slideenter", resizeHandler);
613            on(document, "slideleave", resizeHandler);
614          }
615        }
616
617        var scriptData = document.querySelector("script[data-for='" + el.id + "'][type='application/json']");
618        if (scriptData) {
619          var data = JSON.parse(scriptData.textContent || scriptData.text);
620          // Resolve strings marked as javascript literals to objects
621          if (!(data.evals instanceof Array)) data.evals = [data.evals];
622          for (var k = 0; data.evals && k < data.evals.length; k++) {
623            window.HTMLWidgets.evaluateStringMember(data.x, data.evals[k]);
624          }
625          binding.renderValue(el, data.x, initResult);
626          evalAndRun(data.jsHooks.render, initResult, [el, data.x]);
627        }
628      });
629    });
630
631    invokePostRenderHandlers();
632  }
633
634  // Wait until after the document has loaded to render the widgets.
635  if (document.addEventListener) {
636    document.addEventListener("DOMContentLoaded", function() {
637      document.removeEventListener("DOMContentLoaded", arguments.callee, false);
638      window.HTMLWidgets.staticRender();
639    }, false);
640  } else if (document.attachEvent) {
641    document.attachEvent("onreadystatechange", function() {
642      if (document.readyState === "complete") {
643        document.detachEvent("onreadystatechange", arguments.callee);
644        window.HTMLWidgets.staticRender();
645      }
646    });
647  }
648
649
650  window.HTMLWidgets.getAttachmentUrl = function(depname, key) {
651    // If no key, default to the first item
652    if (typeof(key) === "undefined")
653      key = 1;
654
655    var link = document.getElementById(depname + "-" + key + "-attachment");
656    if (!link) {
657      throw new Error("Attachment " + depname + "/" + key + " not found in document");
658    }
659    return link.getAttribute("href");
660  };
661
662  window.HTMLWidgets.dataframeToD3 = function(df) {
663    var names = [];
664    var length;
665    for (var name in df) {
666        if (df.hasOwnProperty(name))
667            names.push(name);
668        if (typeof(df[name]) !== "object" || typeof(df[name].length) === "undefined") {
669            throw new Error("All fields must be arrays");
670        } else if (typeof(length) !== "undefined" && length !== df[name].length) {
671            throw new Error("All fields must be arrays of the same length");
672        }
673        length = df[name].length;
674    }
675    var results = [];
676    var item;
677    for (var row = 0; row < length; row++) {
678        item = {};
679        for (var col = 0; col < names.length; col++) {
680            item[names[col]] = df[names[col]][row];
681        }
682        results.push(item);
683    }
684    return results;
685  };
686
687  window.HTMLWidgets.transposeArray2D = function(array) {
688      if (array.length === 0) return array;
689      var newArray = array[0].map(function(col, i) {
690          return array.map(function(row) {
691              return row[i]
692          })
693      });
694      return newArray;
695  };
696  // Split value at splitChar, but allow splitChar to be escaped
697  // using escapeChar. Any other characters escaped by escapeChar
698  // will be included as usual (including escapeChar itself).
699  function splitWithEscape(value, splitChar, escapeChar) {
700    var results = [];
701    var escapeMode = false;
702    var currentResult = "";
703    for (var pos = 0; pos < value.length; pos++) {
704      if (!escapeMode) {
705        if (value[pos] === splitChar) {
706          results.push(currentResult);
707          currentResult = "";
708        } else if (value[pos] === escapeChar) {
709          escapeMode = true;
710        } else {
711          currentResult += value[pos];
712        }
713      } else {
714        currentResult += value[pos];
715        escapeMode = false;
716      }
717    }
718    if (currentResult !== "") {
719      results.push(currentResult);
720    }
721    return results;
722  }
723  // Function authored by Yihui/JJ Allaire
724  window.HTMLWidgets.evaluateStringMember = function(o, member) {
725    var parts = splitWithEscape(member, '.', '\\');
726    for (var i = 0, l = parts.length; i < l; i++) {
727      var part = parts[i];
728      // part may be a character or 'numeric' member name
729      if (o !== null && typeof o === "object" && part in o) {
730        if (i == (l - 1)) { // if we are at the end of the line then evalulate
731          if (typeof o[part] === "string")
732            o[part] = eval("(" + o[part] + ")");
733        } else { // otherwise continue to next embedded object
734          o = o[part];
735        }
736      }
737    }
738  };
739
740  // Retrieve the HTMLWidget instance (i.e. the return value of an
741  // HTMLWidget binding's initialize() or factory() function)
742  // associated with an element, or null if none.
743  window.HTMLWidgets.getInstance = function(el) {
744    return elementData(el, "init_result");
745  };
746
747  // Finds the first element in the scope that matches the selector,
748  // and returns the HTMLWidget instance (i.e. the return value of
749  // an HTMLWidget binding's initialize() or factory() function)
750  // associated with that element, if any. If no element matches the
751  // selector, or the first matching element has no HTMLWidget
752  // instance associated with it, then null is returned.
753  //
754  // The scope argument is optional, and defaults to window.document.
755  window.HTMLWidgets.find = function(scope, selector) {
756    if (arguments.length == 1) {
757      selector = scope;
758      scope = document;
759    }
760
761    var el = scope.querySelector(selector);
762    if (el === null) {
763      return null;
764    } else {
765      return window.HTMLWidgets.getInstance(el);
766    }
767  };
768
769  // Finds all elements in the scope that match the selector, and
770  // returns the HTMLWidget instances (i.e. the return values of
771  // an HTMLWidget binding's initialize() or factory() function)
772  // associated with the elements, in an array. If elements that
773  // match the selector don't have an associated HTMLWidget
774  // instance, the returned array will contain nulls.
775  //
776  // The scope argument is optional, and defaults to window.document.
777  window.HTMLWidgets.findAll = function(scope, selector) {
778    if (arguments.length == 1) {
779      selector = scope;
780      scope = document;
781    }
782
783    var nodes = scope.querySelectorAll(selector);
784    var results = [];
785    for (var i = 0; i < nodes.length; i++) {
786      results.push(window.HTMLWidgets.getInstance(nodes[i]));
787    }
788    return results;
789  };
790
791  var postRenderHandlers = [];
792  function invokePostRenderHandlers() {
793    while (postRenderHandlers.length) {
794      var handler = postRenderHandlers.shift();
795      if (handler) {
796        handler();
797      }
798    }
799  }
800
801  // Register the given callback function to be invoked after the
802  // next time static widgets are rendered.
803  window.HTMLWidgets.addPostRenderHandler = function(callback) {
804    postRenderHandlers.push(callback);
805  };
806
807  // Takes a new-style instance-bound definition, and returns an
808  // old-style class-bound definition. This saves us from having
809  // to rewrite all the logic in this file to accomodate both
810  // types of definitions.
811  function createLegacyDefinitionAdapter(defn) {
812    var result = {
813      name: defn.name,
814      type: defn.type,
815      initialize: function(el, width, height) {
816        return defn.factory(el, width, height);
817      },
818      renderValue: function(el, x, instance) {
819        return instance.renderValue(x);
820      },
821      resize: function(el, width, height, instance) {
822        return instance.resize(width, height);
823      }
824    };
825
826    if (defn.find)
827      result.find = defn.find;
828    if (defn.renderError)
829      result.renderError = defn.renderError;
830    if (defn.clearError)
831      result.clearError = defn.clearError;
832
833    return result;
834  }
835})();
836

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.