<commit_before>
var Drawing = Drawing || {};

Drawing.SimpleGraph = function(options) {
  var options = options || {};
  var layout = options.layout || "2d";
  var nodes_count = options.nodes || 20;
  var edges_count = options.edges || 10;

  var camera, scene, renderer, interaction, stats;
  var graph = new Graph({limit: options.limit});

  var geometries = [];
  var info;

  init();
  createGraph();
  animate();

  function init() {
    // Three.js initialization
    camera = new THREE.TrackballCamera({
      fov: 40,
      aspect: window.innerWidth / window.innerHeight,
      near: 1,
      far: 1000000,

      rotateSpeed: 0.5,
      zoomSpeed: 5.2,
      panSpeed: 1,

      noZoom: false,
      noPan: false,

      staticMoving: false,
      dynamicDampingFactor: 0.3,

      keys: [ 65, 83, 68 ]
    });
    camera.position.z = 5000;

    scene = new THREE.Scene();

    renderer = new THREE.WebGLRenderer({antialias: true});

    renderer.setSize( window.innerWidth, window.innerHeight );

    document.body.appendChild( renderer.domElement );

    // Stats.js
    stats = new Stats();
    stats.domElement.style.position = 'absolute';
    stats.domElement.style.top = '0px';
    document.body.appendChild( stats.domElement );

    info = document.createElement("div");
    info.style.position = 'absolute';
    info.style.top = '100px';

    document.body.appendChild( stats.domElement );
    document.body.appendChild( info );
  }

  function createGraph() {
    var node = new Node(0);
    graph.addNode(node);
    drawNode(node);

    var nodes = [];
    nodes.push(node);

    var steps = 1;
    do {
      var node = nodes.shift();

      var numEdges = randomFromTo(1, edges_count);
      for(var i=1; i <= numEdges; i++) {
        var target_node = new Node(i*steps);
        if(graph.addNode(target_node)) {
          drawNode(target_node);
          nodes.push(target_node);
          if(graph.addEdge(node, target_node)) {
            drawEdge(node, target_node);
          }
        }
      }
      steps++;
    } while(nodes.length != 0 && steps < nodes_count);

    if(layout === "3d") {
      graph.layout = new Layout.ForceDirected3D(graph, {width: 2000, height: 2000, iterations: 1000});
    } else {
      graph.layout = new Layout.ForceDirected(graph, {width: 2000, height: 2000, iterations: 1000});
    }
    graph.layout.init();
  }

  function drawNode(node) {
    var geometry;
    if(layout === "3d") {
      geometry = new THREE.CubeGeometry( 50, 50, 50 );
    } else {
      geometry = new THREE.CubeGeometry( 50, 50, 0 );
    }
    var draw_object = new THREE.Mesh( geometry, [ new THREE.MeshBasicMaterial( {  color: Math.random() * 0xffffff } ), new THREE.MeshBasicMaterial( { color: 0xffffff, opacity: 0.5, wireframe: true } ) ] );

    // label
    // var labelCanvas = document.createElement( "canvas" );
    // var xc = labelCanvas.getContext("2d");
    // labelCanvas.width = labelCanvas.height = 128;
    // // xc.shadowColor = "#000";
    // // xc.shadowBlur = 7;
    // // xc.fillStyle = "orange";
    // xc.font = "50pt arial bold";
    // xc.fillText("myText", 10, 64);
    //
    // var xm = new THREE.MeshBasicMaterial( { map: new THREE.Texture( labelCanvas ), transparent: true } );
    // xm.map.needsUpdate = true;

    var area = 2000;
    draw_object.position.x = Math.floor(Math.random() * (area + area + 1) - area);
    draw_object.position.y = Math.floor(Math.random() * (area + area + 1) - area);

    if(layout === "3d") {
      draw_object.position.z = Math.floor(Math.random() * (area + area + 1) - area);
    }

    // var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 100, 100 ), xm );
    // mesh.position.x = draw_object.position.x;
    // mesh.position.y = draw_object.position.y;
    // mesh.doubleSided = true;
    // mesh.draw_object = draw_object;
    // mesh.updateMatrix();
    // mesh.type = "label";
    // scene.addObject(mesh);

    draw_object.id = node.id;
    node.data.draw_object = draw_object;
    node.position = draw_object.position;
    scene.addObject( node.data.draw_object );
  }

  function drawEdge(source, target) {
      material = new THREE.LineBasicMaterial( { color: 0xff0000, opacity: 1, linewidth: 0.5 } );
      var tmp_geo = new THREE.Geometry();

      tmp_geo.vertices.push(new THREE.Vertex(source.data.draw_object.position));
      tmp_geo.vertices.push(new THREE.Vertex(target.data.draw_object.position));

      line = new THREE.Line( tmp_geo, material, THREE.LinePieces );
      line.scale.x = line.scale.y = line.scale.z = 1;
      line.originalScale = 1;

      geometries.push(tmp_geo);

      scene.addObject( line );
  }

  function animate() {
    requestAnimationFrame( animate );
    render();
  }

  function render() {
    if(graph.layout.generate()) {
      info.style.border = '10px solid red';
    } else {
      info.style.border = 'none';
    }

    for(var i=0; i<geometries.length; i++) {
      geometries[i].__dirtyVertices = true;
    }

    // scene.objects.forEach(function(obj) {
    //   if(obj.type === "label") {
    //     var delta_x = obj.position.x - obj.draw_object.position.x;
    //     var delta_y = obj.position.y - obj.draw_object.position.y;
    //     if(Math.sqrt(delta_x*delta_x) > 300) {
    //       obj.position.x = obj.draw_object.position.x;
    //     }
    //     if(Math.sqrt(delta_y*delta_y) > 300) {
    //       obj.position.y = obj.draw_object.position.y;
    //     }
    //     drawText(obj, obj.draw_object.position.y);
    //   }
    // });

    renderer.render( scene, camera );
    // interaction.update();
    stats.update();
  }

  function drawText(draw_object, text) {
    draw_object.materials[0].map.image = null;
    var textCanvas = document.createElement( "canvas" );
    var xc = textCanvas.getContext("2d");
    // xc.shadowColor = "#000";
    // xc.shadowBlur = 7;
    xc.font = "50pt arial bold";
    xc.fillText(text, 10, 64);
    draw_object.materials[0].map.image = textCanvas;
  }

  function randomFromTo(from, to) {
    return Math.floor(Math.random() * (to - from + 1) + from);
  }

}<commit_msg>Added object selection.<commit_after>
var Drawing = Drawing || {};

Drawing.SimpleGraph = function(options) {
  var options = options || {};
  var layout = options.layout || "2d";
  var selection = options.selection || false;
  var nodes_count = options.nodes || 20;
  var edges_count = options.edges || 10;

  var camera, scene, renderer, interaction, stats, geometry, object_selection;
  var graph = new Graph({limit: options.limit});

  var geometries = [];
  var info;

  init();
  createGraph();
  animate();

  function init() {
    // Three.js initialization
    camera = new THREE.TrackballCamera({
      fov: 40,
      aspect: window.innerWidth / window.innerHeight,
      near: 1,
      far: 1000000,

      rotateSpeed: 0.5,
      zoomSpeed: 5.2,
      panSpeed: 1,

      noZoom: false,
      noPan: false,

      staticMoving: false,
      dynamicDampingFactor: 0.3,

      keys: [ 65, 83, 68 ]
    });
    camera.position.z = 5000;

    scene = new THREE.Scene();

    // Node geometry
    if(layout === "3d") {
      geometry = new THREE.SphereGeometry( 50, 50, 50 );
    } else {
      geometry = new THREE.SphereGeometry( 50, 50, 0 );
    }

    if(selection) {
      object_selection = new THREE.ObjectSelection({selected: function(obj) {
        // display info
      }});
    }

    renderer = new THREE.WebGLRenderer({antialias: true});
    renderer.setSize( window.innerWidth, window.innerHeight );

    document.body.appendChild( renderer.domElement );

    // Stats.js
    stats = new Stats();
    stats.domElement.style.position = 'absolute';
    stats.domElement.style.top = '0px';
    document.body.appendChild( stats.domElement );

    info = document.createElement("div");
    info.style.position = 'absolute';
    info.style.top = '100px';

    document.body.appendChild( stats.domElement );
    document.body.appendChild( info );
  }

  function createGraph() {
    var node = new Node(0);
    graph.addNode(node);
    drawNode(node);

    var nodes = [];
    nodes.push(node);

    var steps = 1;
    do {
      var node = nodes.shift();

      var numEdges = randomFromTo(1, edges_count);
      for(var i=1; i <= numEdges; i++) {
        var target_node = new Node(i*steps);
        if(graph.addNode(target_node)) {
          drawNode(target_node);
          nodes.push(target_node);
          if(graph.addEdge(node, target_node)) {
            drawEdge(node, target_node);
          }
        }
      }
      steps++;
    } while(nodes.length != 0 && steps < nodes_count);

    if(layout === "3d") {
      graph.layout = new Layout.ForceDirected3D(graph, {width: 2000, height: 2000, iterations: 1000});
    } else {
      graph.layout = new Layout.ForceDirected(graph, {width: 2000, height: 2000, iterations: 1000});
    }
    graph.layout.init();
  }

  function drawNode(node) {

    var draw_object = new THREE.Mesh( geometry, [ new THREE.MeshBasicMaterial( {  color: Math.random() * 0xffffff, opacity: 0.5 } ) ] );

    // label
    // var labelCanvas = document.createElement( "canvas" );
    // var xc = labelCanvas.getContext("2d");
    // labelCanvas.width = labelCanvas.height = 128;
    // // xc.shadowColor = "#000";
    // // xc.shadowBlur = 7;
    // // xc.fillStyle = "orange";
    // xc.font = "50pt arial bold";
    // xc.fillText("myText", 10, 64);
    //
    // var xm = new THREE.MeshBasicMaterial( { map: new THREE.Texture( labelCanvas ), transparent: true } );
    // xm.map.needsUpdate = true;

    var area = 2000;
    draw_object.position.x = Math.floor(Math.random() * (area + area + 1) - area);
    draw_object.position.y = Math.floor(Math.random() * (area + area + 1) - area);

    if(layout === "3d") {
      draw_object.position.z = Math.floor(Math.random() * (area + area + 1) - area);
    }

    // var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 100, 100 ), xm );
    // mesh.position.x = draw_object.position.x;
    // mesh.position.y = draw_object.position.y;
    // mesh.doubleSided = true;
    // mesh.draw_object = draw_object;
    // mesh.updateMatrix();
    // mesh.type = "label";
    // scene.addObject(mesh);

    draw_object.id = node.id;
    node.data.draw_object = draw_object;
    node.position = draw_object.position;
    scene.addObject( node.data.draw_object );
  }

  function drawEdge(source, target) {
      material = new THREE.LineBasicMaterial( { color: 0xff0000, opacity: 1, linewidth: 0.5 } );
      var tmp_geo = new THREE.Geometry();

      tmp_geo.vertices.push(new THREE.Vertex(source.data.draw_object.position));
      tmp_geo.vertices.push(new THREE.Vertex(target.data.draw_object.position));

      line = new THREE.Line( tmp_geo, material, THREE.LinePieces );
      line.scale.x = line.scale.y = line.scale.z = 1;
      line.originalScale = 1;

      geometries.push(tmp_geo);

      scene.addObject( line );
  }

  function animate() {
    requestAnimationFrame( animate );
    render();
  }

  function render() {
    if(graph.layout.generate()) {
      info.style.border = '10px solid red';
    } else {
      info.style.border = 'none';
    }

    for(var i=0; i<geometries.length; i++) {
      geometries[i].__dirtyVertices = true;
    }

    // scene.objects.forEach(function(obj) {
    //   if(obj.type === "label") {
    //     var delta_x = obj.position.x - obj.draw_object.position.x;
    //     var delta_y = obj.position.y - obj.draw_object.position.y;
    //     if(Math.sqrt(delta_x*delta_x) > 300) {
    //       obj.position.x = obj.draw_object.position.x;
    //     }
    //     if(Math.sqrt(delta_y*delta_y) > 300) {
    //       obj.position.y = obj.draw_object.position.y;
    //     }
    //     drawText(obj, obj.draw_object.position.y);
    //   }
    // });

    if(selection) {
      object_selection.render(scene, camera);
    }
    renderer.render( scene, camera );
    // interaction.update();
    stats.update();
  }

  function drawText(draw_object, text) {
    draw_object.materials[0].map.image = null;
    var textCanvas = document.createElement( "canvas" );
    var xc = textCanvas.getContext("2d");
    // xc.shadowColor = "#000";
    // xc.shadowBlur = 7;
    xc.font = "50pt arial bold";
    xc.fillText(text, 10, 64);
    draw_object.materials[0].map.image = textCanvas;
  }

  function randomFromTo(from, to) {
    return Math.floor(Math.random() * (to - from + 1) + from);
  }

}<|endoftext|>


<commit_before>var src = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var map = {};
src.split("").forEach((s, i) => map[s] = i);
var encode62 = {
    src,
    map,
    time_delta: parseInt("zzzzz", 36),
    geta(string) {
        string = String(string)
        string = string.length + string + "2017-08-19";
        var buff = src.split('');
        for (var cx = 0, dx = buff.length + src.length, sl = string.length, cl = buff.length; cx < dx; cx++) {
            var s1 = string.charCodeAt(cx % sl) % cl;
            var s2 = cx % cl;
            var btemp = buff[s1];
            buff[s1] = buff[s2];
            buff[s2] = btemp;
        }
        return buff.join('');
    },
    timedecode(string) {
        var { time_delta } = this;
        var time_rest = string.slice(string.length - time_delta.toString(36).length, string.length);
        var time_start = parseInt((new Date() - parseInt(time_rest, 36)) / time_delta) * time_delta;
        var time_stamp = time_start + parseInt(time_rest, 36);
        string = this.encode(string.slice(0, string.length - time_delta.toString(36).length), time_stamp.toString(36)).replace(/\.\.?/g, a => a === '.' ? "%" : ".");
        return decodeURIComponent(string);
    },
    timeencode(string) {
        var { time_delta } = this;
        var time_free = time_delta / 6 | 0;
        var time_stamp = +new Date() - time_free;
        var time_rest = time_stamp % time_delta;
        var time_rest_str = time_rest.toString(36);
        var time_delta_str = time_delta.toString(36);
        string = encodeURIComponent(string).replace(/\./g, '..').replace(/[\!'\(\)~]/g, a => escape(a)).replace(/%/g, '.');
        return this.encode(string, time_stamp.toString(36)) + repeat("0", time_delta_str.length - time_rest_str.length) + time_rest_str;
    },
    timeupdate(string) {
        var { time_delta } = this;
        var time_rest = string.slice(string.length - time_delta.toString(36).length, string.length);
        var time_start = parseInt((new Date() - parseInt(time_rest, 36)) / time_delta) * time_delta;
        var time_stamp = time_start + parseInt(time_rest, 36);
        if (time_stamp + (time_delta >> 1) > +new Date()) {
            return string;
        } else {
            return this.timeencode(this.timedecode(string));
        }
    },
    encode(data, sign) {
        if (!sign) return data;
        var result = String(data);
        sign = String(sign);
        var src = this.src;
        var result = result.replace(/\w/g, function (w, cx) {
            var code = map[w];
            if (!isNumber(code)) return w;
            var s = code ^ (sign.charCodeAt(cx % sign.length) % src.length);
            if (s >= src.length) return w;
            return src[s];
        });
        return result;
    }
};
encode62.decode62 = encode62.encode62 = encode62.encode;<commit_msg>编码结果不再因页面刷新等非时间因素变化<commit_after>var src = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var map = {};
src.split("").forEach((s, i) => map[s] = i);
var encode62 = {
    src,
    map,
    time_delta: parseInt("zzzzz", 36),
    geta(string) {
        string = String(string)
        string = string.length + string + "2017-08-19";
        var buff = src.split('');
        for (var cx = 0, dx = buff.length + src.length, sl = string.length, cl = buff.length; cx < dx; cx++) {
            var s1 = string.charCodeAt(cx % sl) % cl;
            var s2 = cx % cl;
            var btemp = buff[s1];
            buff[s1] = buff[s2];
            buff[s2] = btemp;
        }
        return buff.join('');
    },
    timedecode(string) {
        var { time_delta } = this;
        var time_rest = string.slice(string.length - time_delta.toString(36).length, string.length);
        var time_start = parseInt((new Date() - parseInt(time_rest, 36)) / time_delta) * time_delta;
        var time_stamp = time_start + parseInt(time_rest, 36);
        string = this.encode(string.slice(0, string.length - time_delta.toString(36).length), time_stamp.toString(36)).replace(/\.\.?/g, a => a === '.' ? "%" : ".");
        return decodeURIComponent(string);
    },
    timeencode(string) {
        var { time_delta } = this;
        var time_free = time_delta / 6 | 0;
        var time = +new Date;
        time = time - time % (time_delta >> 2);
        var time_stamp = time - time_free;
        var time_rest = time_stamp % time_delta;
        var time_rest_str = time_rest.toString(36);
        var time_delta_str = time_delta.toString(36);
        string = encodeURIComponent(string).replace(/\./g, '..').replace(/[\!'\(\)~]/g, a => escape(a)).replace(/%/g, '.');
        return this.encode(string, time_stamp.toString(36)) + repeat("0", time_delta_str.length - time_rest_str.length) + time_rest_str;
    },
    timeupdate(string) {
        var { time_delta } = this;
        var time_rest = string.slice(string.length - time_delta.toString(36).length, string.length);
        var time = +new Date;
        var time_start = parseInt((time - parseInt(time_rest, 36)) / time_delta) * time_delta;
        var time_stamp = time_start + parseInt(time_rest, 36);
        if (time_stamp + (time_delta >> 1) > time) {
            return string;
        } else {
            return this.timeencode(this.timedecode(string));
        }
    },
    encode(data, sign) {
        if (!sign) return data;
        var result = String(data);
        sign = String(sign);
        var src = this.src;
        var result = result.replace(/\w/g, function (w, cx) {
            var code = map[w];
            if (!isNumber(code)) return w;
            var s = code ^ (sign.charCodeAt(cx % sign.length) % src.length);
            if (s >= src.length) return w;
            return src[s];
        });
        return result;
    }
};
encode62.decode62 = encode62.encode62 = encode62.encode;<|endoftext|>


<commit_before><commit_msg>Update reveal.js<commit_after><|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';

export class Tooltip extends React.PureComponent {
  static propTypes = {
    visible: PropTypes.bool,
    size: PropTypes.oneOf(['auto','sm', 'md', 'lg']),
    isSticky: PropTypes.bool
  };

  static defaultProps = {
    visible: true,
    size: 'auto',
    isSticky: false
  };

  constructor(props) {
    super(props);
  }

  componentDidMount() {
    require('../../css/tooltips');
  }

  render() {
    let {isSticky, visible, size, className, children, ...others} = this.props;

    const newClasses = classnames('tooltip-container', visible ? 'tooltip-container-visible' : 'tooltip-container-hidden',
                                  size === 'auto' ? null : `tooltip-${size}`,
                                  isSticky? 'tooltip-hoverable': null,
                                  className);

    return (

{children}

    );
  }
}

export class TooltipTrigger extends React.Component {
  static propTypes = {
    display: PropTypes.bool,
    tooltip: PropTypes.oneOfType([PropTypes.node, PropTypes.object]).isRequired,
    placement: PropTypes.oneOf(['left', 'right', 'bottom', 'top']),
    trigger: PropTypes.oneOf(['manual', 'hover', 'click']),
    clickHideDelay: PropTypes.number,
    onClick: PropTypes.func,
    onEntered: PropTypes.func,
    onExited: PropTypes.func,
    theme: PropTypes.oneOf(['dark', 'light']),
    size: PropTypes.oneOf(['auto', 'sm', 'md', 'lg']),
    isSticky: PropTypes.bool
  };

  static defaultProps = {
    display: false,
    placement: 'top',
    trigger: 'hover',
    clickHideDelay: 1000,
    onClick: () => {},
    onEntered: () => {},
    onExited: () => {},
    theme: 'dark',
    size: 'auto',
    isSticky: false
  };

  constructor(props) {
    super(props);
    this.state = {visible: props.trigger === 'manual' ? props.display : false};
    this.clickHandler = this.clickHandler.bind(this);
  }

  componentDidMount() {
    require('../../css/tooltips');
  }

  hoverHandler(e) {
    this.setState({visible: e.type === 'mouseenter'});
  }

  clickHandler(e, onClick) {
    this.setState({visible: true});
    onClick(e);
    setTimeout(() => {
      this.setState({visible: false});
    }, this.props.clickHideDelay);
  }

  componentWillReceiveProps(nextProps) {
    const triggerChanged = this.props.trigger !== nextProps.trigger;
    const displayChanged = this.props.display !== nextProps.display;

    if (triggerChanged && nextProps.trigger === 'manual') {
      this.setState({visible: nextProps.display});
    } else if (triggerChanged) {
      this.setState({visible: false});
    } else if (displayChanged) {
      this.setState({visible: nextProps.display});
    }
  }

  componentDidUpdate(prevProps, prevState) {
    if(prevState.visible && !this.state.visible) {
      this.props.onExited();
    } else if(!prevState.visible && this.state.visible) {
      this.props.onEntered();
    }
  }

  render() {
    const {isSticky, placement, tooltip, trigger, className, clickHideDelay, onEntered, onExited, theme, size, onClick, display, ...others} = this.props;
    const {visible} = this.state;

    let placementClass;
    if(placement !== 'top') {
      placementClass = `tooltip-${placement}`;
    }

    let triggerHandler;
    switch(trigger) {
      case 'click':
        triggerHandler = {onClick: e => this.clickHandler(e, onClick)};
        break;
      case 'manual':
        triggerHandler = {};
        break;
      default:
        triggerHandler = {
          onClick,
          onMouseEnter: this.hoverHandler.bind(this),
          onMouseLeave: this.hoverHandler.bind(this)
        };
        break;
    }

    const newClasses = classnames('tooltip', className, placementClass,
      theme === 'light' ? 'tooltip-light' : null);
    const newProps = Object.assign({className: newClasses}, triggerHandler, others);

    return (

        {this.props.children}
        <Tooltip {...{isSticky, size: this.props.size, visible}}>{tooltip}</Tooltip>

    );
  }
}
<commit_msg>Fix warning about calling setState on unmounted component in TooltipTrigger<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';

export class Tooltip extends React.PureComponent {
  static propTypes = {
    visible: PropTypes.bool,
    size: PropTypes.oneOf(['auto','sm', 'md', 'lg']),
    isSticky: PropTypes.bool
  };

  static defaultProps = {
    visible: true,
    size: 'auto',
    isSticky: false
  };

  constructor(props) {
    super(props);
  }

  componentDidMount() {
    require('../../css/tooltips');
  }

  render() {
    let {isSticky, visible, size, className, children, ...others} = this.props;

    const newClasses = classnames('tooltip-container', visible ? 'tooltip-container-visible' : 'tooltip-container-hidden',
                                  size === 'auto' ? null : `tooltip-${size}`,
                                  isSticky? 'tooltip-hoverable': null,
                                  className);

    return (

{children}

    );
  }
}

export class TooltipTrigger extends React.Component {
  static propTypes = {
    display: PropTypes.bool,
    tooltip: PropTypes.oneOfType([PropTypes.node, PropTypes.object]).isRequired,
    placement: PropTypes.oneOf(['left', 'right', 'bottom', 'top']),
    trigger: PropTypes.oneOf(['manual', 'hover', 'click']),
    clickHideDelay: PropTypes.number,
    onClick: PropTypes.func,
    onEntered: PropTypes.func,
    onExited: PropTypes.func,
    theme: PropTypes.oneOf(['dark', 'light']),
    size: PropTypes.oneOf(['auto', 'sm', 'md', 'lg']),
    isSticky: PropTypes.bool
  };

  static defaultProps = {
    display: false,
    placement: 'top',
    trigger: 'hover',
    clickHideDelay: 1000,
    onClick: () => {},
    onEntered: () => {},
    onExited: () => {},
    theme: 'dark',
    size: 'auto',
    isSticky: false
  };

  constructor(props) {
    super(props);
    this.state = {visible: props.trigger === 'manual' ? props.display : false};
    this.clickHandler = this.clickHandler.bind(this);
  }

  componentDidMount() {
    require('../../css/tooltips');
    this.mounted = true;
  }

  componentWillUnmount() {
    this.mounted = false;
  }

  hoverHandler(e) {
    this.setState({visible: e.type === 'mouseenter'});
  }

  clickHandler(e, onClick) {
    this.setState({visible: true});
    onClick(e);
    setTimeout(() => {
      this.mounted && this.setState({visible: false});
    }, this.props.clickHideDelay);
  }

  componentWillReceiveProps(nextProps) {
    const triggerChanged = this.props.trigger !== nextProps.trigger;
    const displayChanged = this.props.display !== nextProps.display;

    if (triggerChanged && nextProps.trigger === 'manual') {
      this.setState({visible: nextProps.display});
    } else if (triggerChanged) {
      this.setState({visible: false});
    } else if (displayChanged) {
      this.setState({visible: nextProps.display});
    }
  }

  componentDidUpdate(prevProps, prevState) {
    if(prevState.visible && !this.state.visible) {
      this.props.onExited();
    } else if(!prevState.visible && this.state.visible) {
      this.props.onEntered();
    }
  }

  render() {
    const {isSticky, placement, tooltip, trigger, className, clickHideDelay, onEntered, onExited, theme, size, onClick, display, ...others} = this.props;
    const {visible} = this.state;

    let placementClass;
    if(placement !== 'top') {
      placementClass = `tooltip-${placement}`;
    }

    let triggerHandler;
    switch(trigger) {
      case 'click':
        triggerHandler = {onClick: e => this.clickHandler(e, onClick)};
        break;
      case 'manual':
        triggerHandler = {};
        break;
      default:
        triggerHandler = {
          onClick,
          onMouseEnter: this.hoverHandler.bind(this),
          onMouseLeave: this.hoverHandler.bind(this)
        };
        break;
    }

    const newClasses = classnames('tooltip', className, placementClass,
      theme === 'light' ? 'tooltip-light' : null);
    const newProps = Object.assign({className: newClasses}, triggerHandler, others);

    return (

        {this.props.children}
        <Tooltip {...{isSticky, size: this.props.size, visible}}>{tooltip}</Tooltip>

    );
  }
}
<|endoftext|>


<commit_before>"use strict";
var getvariables = require("./compile/variables");
var esprima = require("./esprima/index");
var esmangle = require("./esmangle/esmangle");
var escodegen = require("./escodegen/escodegen");
var typescript = require("./typescript/typescript");
var less = require("./less/less-node")();
less.PluginLoader = function () { };
var fs = require("fs");
var path = require("path");
var cwd = process.cwd();
var bindLoadings = function (reg, data, fullpath, replacer = a => a) {
    data = String(data);
    if (!reg.test(data)) return data;
    var loadurls = {};
    data.replace(reg, function (match, quote, relative) {
        loadurls[relative] = true;
    });
    return new Promise(function (ok, oh) {
        var loaddingcount = 0;
        var accessready = function () {
            loaddingcount++;
            if (loaddingcount < loadings.length) return;
            var dataMap = {};
            var loaddings = Object.keys(loadurls).map(function (key) {
                var realpath = loadurls[key];
                return getFileData(realpath).then(function (data) {
                    dataMap[key] = data;
                });
            });
            Promise.all(loaddings).then(function () {
                data = data.replace(reg, function (match, quote, relative) {
                    var data = dataMap[relative];
                    var realPath = loadurls[relative];
                    if (data instanceof Buffer) {
                        return replacer(data.toString(), realPath);
                    }
                    console.warn(`没有处理${match}`, fullpath);
                    return match;
                });

                ok(data);
            });
        };
        var loadings = Object.keys(loadurls).map(function (relative) {
            var realPath = path.join(path.dirname(fullpath), relative);
            fs.access(realPath, function (err) {
                if (!err) {
                    loadurls[relative] = realPath;
                    accessready();
                    return;
                }
                realPath = path.join(__dirname, "..", relative);
                fs.access(realPath, function (err) {
                    if (!err) {
                        loadurls[relative] = realPath;
                    } else {
                        delete loadurls[relative];
                    }
                    accessready();
                })
            });
        });
    });
};
var loadUseBody = function (data, fullpath, watchurls, commName) {
    var useInternalReg = /^\s*(['"`])(?:(?:use|#?include)\b)\s*(.*?)\1(\s*;)?\s*$/i;
    var replacer = function (data, realPath) {
        watchurls.push(realPath);
        if (/module.exports\s*=/.test(data)) {
            return data.replace(/\bmodule.exports\s*=/g, commName ? "var " + commName : "return ");
        }
        var realName = path.basename(realPath).replace(/\..*$/, "");
        return data + `;var ${realName},${commName}=${realName};`;
    };
    return bindLoadings(useInternalReg, data, fullpath, replacer);
}
var getRequiredPaths = function (data) {
    var pathReg = /\b(?:go|popup)\(\s*(['"`])([^\{\}]+?)\1[\s\S]*?\)/g;
    var requiredPaths = {};
    var result = pathReg.exec(data);
    while (result) {
        requiredPaths[result[2].replace(/^[@#!]+/, "")] = true;
        result = pathReg.exec(data);
    };
    return Object.keys(requiredPaths);
};

var createExpression = function (expression) {
    return esprima.parse(expression).body;
};
var loadJsBody = function (data, filename, lessdata, commName, className) {
    data = data.replace(/\bDate\(\s*(['"`])(.*?)\1\s*\)/g, (match, quote, dateString) => `Date(${+new Date(dateString)})`);
    var destpaths = getRequiredPaths(data);
    data = typescript.transpile(data);
    var code = esprima.parse(data);
    var {
        DeclaredVariables: declares,
        unDeclaredVariables: undeclares
    } = getvariables(code);
    var globals = Object.keys(undeclares);
    var globalsmap = {};
    globals.forEach(g => globalsmap[g] = g);
    if (commName) {
        //如果声明了main方法或main对象，默认用main作为返回值
        if (declares.main) {
            commName = "main";
        } else if (declares.Main) {
            commName = "Main";
        } else if (declares.MAIN) {
            commName = "MAIN";
        } else if (!declares[commName]) {
            commName = commName[0].toUpperCase() + commName.slice(1);
            if (!declares[commName]) {
                commName = null;
            }
        }
    }
    var hasless = typeof lessdata === "string";
    if (hasless) {
        if (!declares.cless) {
            globalsmap.cless = "cless";
        } else {
            var random_variable;
            do {
                random_variable = "cless_" + Math.random().toString(36)
            } while (declares[random_variable]);
            globalsmap.cless = random_variable;
        }
    }
    var prepareCodeBody = [];
    if (destpaths.length) {
        var stringifiedpaths = destpaths.length === 1 ? JSON.stringify(destpaths[0]) : JSON.stringify(destpaths);
        if (!declares.prepare) {
            globalsmap.prepare = "prepare";
            prepareCodeBody = createExpression(`prepare(${stringifiedpaths});`);
        } else if (!declares.go) {
            globalsmap.go = "go";
            prepareCodeBody = createExpression(`go.prepare(${stringifiedpaths});`);
        } else if (!declares.state) {
            globalsmap.state = "state";
            prepareCodeBody = createExpression(`state.prepare(${stringifiedpaths});`);
        } else {
            console.warn(`将不处理此文件的页面自动预载${filename}`);
        }
    }
    var code_body;
    if (code.body.length === 1 && /(ExpressionStatement)$/.test(code.body[0].type)) {
        //如果整个函数只有一个表达式或一个变量，直接反回其本身
        code_body = [
            {
                "type": "ReturnStatement",
                "argument": hasless ? {
                    "type": "CallExpression",
                    "callee": {
                        "type": "Identifier",
                        "name": globalsmap.cless
                    },
                    "arguments": [
                        code.body[0].expression,
                        {
                            "type": "Literal",
                            "value": lessdata,
                            "raw": JSON.stringify(lessdata)
                        },
                        {
                            "type": "Literal",
                            "value": className,
                            "raw": JSON.stringify(className)
                        }
                    ]
                } : code.body[0].expression
            }];
    } else if (!commName) {
        if (filename !== "main") console.warn("缺少可导出的变量", `文件：${filename}`, `变量：${commName}`);
        code_body = code.body;
    } else {
        code_body = code.body.concat({
            "type": "ReturnStatement",
            "argument": hasless ? {
                "type": "CallExpression",
                "callee": {
                    "type": "Identifier",
                    "name": globalsmap.cless
                },
                "arguments": [
                    {
                        "type": "Identifier",
                        "name": commName
                    },
                    {
                        "type": "Literal",
                        "value": lessdata,
                        "raw": JSON.stringify(lessdata)
                    },
                    {
                        "type": "Literal",
                        "value": className,
                        "raw": JSON.stringify(className)
                    }
                ]
            } : {
                    "type": "Identifier",
                    "name": commName
                }
        });
    }
    code_body = prepareCodeBody.concat(code_body);
    globals = Object.keys(globalsmap);
    if (process.env.IN_TEST_MODE) {
        code = {
            "type": "Program",
            "sourceType": "script",
            body: code_body
        };
        data = escodegen.generate(code, {
            format: {
                renumber: true,
                hexadecimal: true, //十六进位
                escapeless: false,
                compact: false, //去空格
                semicolons: true, //分号
                parentheses: true //圆括号
            }
        });
        var params = globals.map(g => globalsmap[g]);
    } else {
        code = {
            type: "FunctionExpression",
            params: globals.map(n => ({
                type: "Identifier",
                name: globalsmap[n]
            })),
            body: {
                type: "BlockStatement",
                body: code_body
            },
            "generator": false,
            "expression": false
        }

        code = esmangle.optimize(code, null);
        code = esmangle.mangle(code);
        var params = code.params.map(id => id.name);
        code = {
            "type": "Program",
            "sourceType": "script",
            body: code.body.body
        };
        data = escodegen.generate(code, {
            format: {
                renumber: true,
                hexadecimal: true, //十六进位
                escapeless: true,
                compact: true, //去空格
                semicolons: false, //分号
                parentheses: false //圆括号
            }
        });
    }
    var _arguments = [...globals, ...params].join();
    var length = (_arguments.length << 1).toString(36);
    if (length.length === 1) {
        length = "00" + length;
    } else if (length.length === 2) {
        length = "0" + length;
    }
    data = (_arguments.length ? length + _arguments : "") + data.replace(/[\u0100-\uffff]/g, m => "\\u" + (m.charCodeAt(0) > 0x1000 ? m.charCodeAt(0).toString(16) : 0 + m.charCodeAt(0).toString(16)));
    return data;
};
var getFileData = function (fullpath) {
    return new Promise(function (ok, oh) {
        fs.exists(fullpath, function (exists) {
            if (!exists) return ok(false);
            fs.stat(fullpath, function (error, stat) {
                if (error) return ok(error);
                if (!stat.isFile()) return ok(false);
                fs.readFile(fullpath, function (error, buffer) {
                    if (error) return ok(error);
                    ok(buffer);
                });
            })
        });
    });
};
var renderLessData = function (data = '', lesspath, watchurls, className) {
    var importLessReg = /^\s*@(?:import)\s*(['"`]?)(.*?)\1(\s*;)?\s*$/im;
    var replacer = function (data, realpath) {
        if (watchurls.indexOf(realpath) < 0) {
            watchurls.push(realpath);
        }
        return data;
    };
    var lessresult = bindLoadings(importLessReg, data, lesspath, replacer);
    return Promise.resolve(lessresult).then(function (lessdata) {
        watchurls.push(lesspath);
        var lessData;
        less.render(`.${className}{${String(lessdata)}}`, {
            compress: !process.env.IN_TEST_MODE
        }, function (err, data) {
            if (err) return console.warn(err);
            lessData = data.css;
        });
        return lessData;
    });
};
module.exports = function commbuilder(buffer, filename, fullpath, watchurls) {
    var commName = fullpath.match(/(?:^|[^\w])([\$_\w][\w]*)\.(?:[tj]sx?|html?|json)$/i);
    if (!commName) console.warn("文件名无法生成导出变量！", fullpath);
    commName = commName && commName[1];
    var data = String(buffer);
    var className = filename.replace(/[\\\/\:\.]+/g, "-");
    var shortName = className.replace(/^.*?(\w*?)$/g, "$1");
    var lessName = /\s/.test(className) ? className.split(/\s+/)[0] : className;
    if (shortName !== className) className = className + " " + shortName;
    var lessData, jsData;
    var promise;
    if (/\.json$/.test(fullpath)) {
        data = "return " + JSON.stringify(new Function("return " + data.toString())());
    } else if (/\.html?$/i.test(fullpath)) {
        let lesspath = fullpath.replace(/\.html?$/i, ".less");
        jsData = "`\r\n" + data.replace(/>\s+</g, "><").replace(/(?<=[^\\]|^)\\['"]/g, "\\$&") + "`";
        promise = getFileData(lesspath).then(function (lessdata) {
            if (lessdata instanceof Buffer) {
                return renderLessData(lessdata, lesspath, watchurls, lessName).then(function (data) {
                    lessData = data;
                });
            }
        });
    } else if (/\.(?:[jt]sx?)$/i.test(fullpath)) {
        let htmlpath = fullpath.replace(/\.[jt]sx?$/i, ".html");
        let lesspath = fullpath.replace(/\.[jt]sx?$/i, ".less");
        let replace = loadUseBody(data, fullpath, watchurls, commName);
        promise = Promise.all([lesspath, htmlpath].map(getFileData).concat(replace)).then(function ([lessdata, htmldata, data]) {
            if (htmldata instanceof Buffer) {
                var commHtmlName;
                if (/^main/.test(commName)) {
                    commHtmlName = 'Main';
                } else {
                    commHtmlName = commName[0].toUpperCase() + commName.slice(1);
                    if (commHtmlName !== commName) {
                        commHtmlName = `${commName},${commHtmlName},${commHtmlName}=${commName}`;
                    }
                }
                htmldata = "`" + String(htmldata).replace(/>\s+</g, "><").replace(/(?<=[^\\]|^)\\['"]/g, "\\$&") + "`"
                htmldata = htmldata.replace(/\>\s+/g, ">").replace(/\s+\</g, "<").replace(/\<\!\-\-.*?\-\-\>/g, "");
                if (data) {
                    jsData = `\r\nvar ${commHtmlName}={toString:()=>${htmldata}};\r\n` + data;
                } else {
                    jsData = htmldata;
                }
                watchurls.push(htmlpath);
            } else {
                jsData = String(data);
            }
            if (lessdata instanceof Buffer) {
                return renderLessData(lessdata, lesspath, watchurls, lessName).then(data => lessData = data);
            }
        });
    }
    if (promise) {
        promise = promise.then(function () {
            try {
                var timeStart = new Date;
                var data = loadJsBody(jsData, filename, lessData, commName, className);
                data = Buffer.from(data);
                data.time = new Date - timeStart;
                return data;
            } catch (e) {
                console.error(fullpath, e);
            }
        });
    }
    return promise || data;
};<commit_msg>支持引入多个文件<commit_after>"use strict";
var getvariables = require("./compile/variables");
var esprima = require("./esprima/index");
var esmangle = require("./esmangle/esmangle");
var escodegen = require("./escodegen/escodegen");
var typescript = require("./typescript/typescript");
var less = require("./less/less-node")();
less.PluginLoader = function () { };
var fs = require("fs");
var path = require("path");
var cwd = process.cwd();
var bindLoadings = function (reg, data, fullpath, replacer = a => a) {
    data = String(data);
    if (!reg.test(data)) return data;
    var loadurls = {};
    data.replace(reg, function (match, quote, relative) {
        loadurls[relative] = true;
    });
    return new Promise(function (ok, oh) {
        var loaddingcount = 0;
        var accessready = function () {
            loaddingcount++;
            if (loaddingcount < loadings.length) return;
            var dataMap = {};
            var loaddings = Object.keys(loadurls).map(function (key) {
                var realpath = loadurls[key];
                return getFileData(realpath).then(function (data) {
                    dataMap[key] = data;
                });
            });
            Promise.all(loaddings).then(function () {
                data = data.replace(reg, function (match, quote, relative) {
                    var data = dataMap[relative];
                    var realPath = loadurls[relative];
                    if (data instanceof Buffer) {
                        return replacer(data.toString(), realPath);
                    }
                    console.warn(`没有处理${match}`, fullpath);
                    return match;
                });

                ok(data);
            });
        };
        var loadings = Object.keys(loadurls).map(function (relative) {
            var realPath = path.join(path.dirname(fullpath), relative);
            fs.access(realPath, function (err) {
                if (!err) {
                    loadurls[relative] = realPath;
                    accessready();
                    return;
                }
                realPath = path.join(__dirname, "..", relative);
                fs.access(realPath, function (err) {
                    if (!err) {
                        loadurls[relative] = realPath;
                    } else {
                        delete loadurls[relative];
                    }
                    accessready();
                })
            });
        });
    });
};
var loadUseBody = function (data, fullpath, watchurls, commName) {
    var useInternalReg = /^\s*(['"`])(?:(?:use|#?include)\b)\s*(.*?)\1(\s*;)?\s*$/img;
    var replacer = function (data, realPath) {
        watchurls.push(realPath);
        var realName = path.basename(realPath).replace(/\..*$/, "") || "main";
        if (!commName) commName = realName;
        if (/module.exports\s*=/.test(data)) {
            return data.replace(/\bmodule.exports\s*=/g, commName ? "var " + commName : "return ");
        }
        console.log(commName, realName);
        return data + `;var ${realName},${commName}=${realName};`;
    };
    return bindLoadings(useInternalReg, data, fullpath, replacer);
}
var getRequiredPaths = function (data) {
    var pathReg = /\b(?:go|popup)\(\s*(['"`])([^\{\}]+?)\1[\s\S]*?\)/g;
    var requiredPaths = {};
    var result = pathReg.exec(data);
    while (result) {
        requiredPaths[result[2].replace(/^[@#!]+/, "")] = true;
        result = pathReg.exec(data);
    };
    return Object.keys(requiredPaths);
};

var createExpression = function (expression) {
    return esprima.parse(expression).body;
};
var loadJsBody = function (data, filename, lessdata, commName, className) {
    data = data.replace(/\bDate\(\s*(['"`])(.*?)\1\s*\)/g, (match, quote, dateString) => `Date(${+new Date(dateString)})`);
    var destpaths = getRequiredPaths(data);
    data = typescript.transpile(data);
    var code = esprima.parse(data);
    var {
        DeclaredVariables: declares,
        unDeclaredVariables: undeclares
    } = getvariables(code);
    var globals = Object.keys(undeclares);
    var globalsmap = {};
    globals.forEach(g => globalsmap[g] = g);
    if (commName) {
        //如果声明了main方法或main对象，默认用main作为返回值
        if (declares.main) {
            commName = "main";
        } else if (declares.Main) {
            commName = "Main";
        } else if (declares.MAIN) {
            commName = "MAIN";
        } else if (!declares[commName]) {
            commName = commName[0].toUpperCase() + commName.slice(1);
            if (!declares[commName]) {
                commName = null;
            }
        }
    }
    var hasless = typeof lessdata === "string";
    if (hasless) {
        if (!declares.cless) {
            globalsmap.cless = "cless";
        } else {
            var random_variable;
            do {
                random_variable = "cless_" + Math.random().toString(36)
            } while (declares[random_variable]);
            globalsmap.cless = random_variable;
        }
    }
    var prepareCodeBody = [];
    if (destpaths.length) {
        var stringifiedpaths = destpaths.length === 1 ? JSON.stringify(destpaths[0]) : JSON.stringify(destpaths);
        if (!declares.prepare) {
            globalsmap.prepare = "prepare";
            prepareCodeBody = createExpression(`prepare(${stringifiedpaths});`);
        } else if (!declares.go) {
            globalsmap.go = "go";
            prepareCodeBody = createExpression(`go.prepare(${stringifiedpaths});`);
        } else if (!declares.state) {
            globalsmap.state = "state";
            prepareCodeBody = createExpression(`state.prepare(${stringifiedpaths});`);
        } else {
            console.warn(`将不处理此文件的页面自动预载${filename}`);
        }
    }
    var code_body;
    if (code.body.length === 1 && /(ExpressionStatement)$/.test(code.body[0].type)) {
        //如果整个函数只有一个表达式或一个变量，直接反回其本身
        code_body = [
            {
                "type": "ReturnStatement",
                "argument": hasless ? {
                    "type": "CallExpression",
                    "callee": {
                        "type": "Identifier",
                        "name": globalsmap.cless
                    },
                    "arguments": [
                        code.body[0].expression,
                        {
                            "type": "Literal",
                            "value": lessdata,
                            "raw": JSON.stringify(lessdata)
                        },
                        {
                            "type": "Literal",
                            "value": className,
                            "raw": JSON.stringify(className)
                        }
                    ]
                } : code.body[0].expression
            }];
    } else if (!commName) {
        if (filename !== "main") console.warn("缺少可导出的变量", `文件：${filename}`, `变量：${commName}`);
        code_body = code.body;
    } else {
        code_body = code.body.concat({
            "type": "ReturnStatement",
            "argument": hasless ? {
                "type": "CallExpression",
                "callee": {
                    "type": "Identifier",
                    "name": globalsmap.cless
                },
                "arguments": [
                    {
                        "type": "Identifier",
                        "name": commName
                    },
                    {
                        "type": "Literal",
                        "value": lessdata,
                        "raw": JSON.stringify(lessdata)
                    },
                    {
                        "type": "Literal",
                        "value": className,
                        "raw": JSON.stringify(className)
                    }
                ]
            } : {
                    "type": "Identifier",
                    "name": commName
                }
        });
    }
    code_body = prepareCodeBody.concat(code_body);
    globals = Object.keys(globalsmap);
    if (process.env.IN_TEST_MODE) {
        code = {
            "type": "Program",
            "sourceType": "script",
            body: code_body
        };
        data = escodegen.generate(code, {
            format: {
                renumber: true,
                hexadecimal: true, //十六进位
                escapeless: false,
                compact: false, //去空格
                semicolons: true, //分号
                parentheses: true //圆括号
            }
        });
        var params = globals.map(g => globalsmap[g]);
    } else {
        code = {
            type: "FunctionExpression",
            params: globals.map(n => ({
                type: "Identifier",
                name: globalsmap[n]
            })),
            body: {
                type: "BlockStatement",
                body: code_body
            },
            "generator": false,
            "expression": false
        }

        code = esmangle.optimize(code, null);
        code = esmangle.mangle(code);
        var params = code.params.map(id => id.name);
        code = {
            "type": "Program",
            "sourceType": "script",
            body: code.body.body
        };
        data = escodegen.generate(code, {
            format: {
                renumber: true,
                hexadecimal: true, //十六进位
                escapeless: true,
                compact: true, //去空格
                semicolons: false, //分号
                parentheses: false //圆括号
            }
        });
    }
    var _arguments = [...globals, ...params].join();
    var length = (_arguments.length << 1).toString(36);
    if (length.length === 1) {
        length = "00" + length;
    } else if (length.length === 2) {
        length = "0" + length;
    }
    data = (_arguments.length ? length + _arguments : "") + data.replace(/[\u0100-\uffff]/g, m => "\\u" + (m.charCodeAt(0) > 0x1000 ? m.charCodeAt(0).toString(16) : 0 + m.charCodeAt(0).toString(16)));
    return data;
};
var getFileData = function (fullpath) {
    return new Promise(function (ok, oh) {
        fs.exists(fullpath, function (exists) {
            if (!exists) return ok(false);
            fs.stat(fullpath, function (error, stat) {
                if (error) return ok(error);
                if (!stat.isFile()) return ok(false);
                fs.readFile(fullpath, function (error, buffer) {
                    if (error) return ok(error);
                    ok(buffer);
                });
            })
        });
    });
};
var renderLessData = function (data = '', lesspath, watchurls, className) {
    var importLessReg = /^\s*@(?:import)\s*(['"`]?)(.*?)\1(\s*;)?\s*$/im;
    var replacer = function (data, realpath) {
        if (watchurls.indexOf(realpath) < 0) {
            watchurls.push(realpath);
        }
        return data;
    };
    var lessresult = bindLoadings(importLessReg, data, lesspath, replacer);
    return Promise.resolve(lessresult).then(function (lessdata) {
        watchurls.push(lesspath);
        var lessData;
        less.render(`.${className}{${String(lessdata)}}`, {
            compress: !process.env.IN_TEST_MODE
        }, function (err, data) {
            if (err) return console.warn(err);
            lessData = data.css;
        });
        return lessData;
    });
};
module.exports = function commbuilder(buffer, filename, fullpath, watchurls) {
    var commName = fullpath.match(/(?:^|[^\w])([\$_\w][\w]*)\.(?:[tj]sx?|html?|json)$/i);
    if (!commName) console.warn("文件名无法生成导出变量！", fullpath);
    commName = commName && commName[1];
    var data = String(buffer);
    var className = filename.replace(/[\\\/\:\.]+/g, "-");
    var shortName = className.replace(/^.*?(\w*?)$/g, "$1");
    var lessName = /\s/.test(className) ? className.split(/\s+/)[0] : className;
    if (shortName !== className) className = className + " " + shortName;
    var lessData, jsData;
    var promise;
    if (/\.json$/.test(fullpath)) {
        data = "return " + JSON.stringify(new Function("return " + data.toString())());
    } else if (/\.html?$/i.test(fullpath)) {
        let lesspath = fullpath.replace(/\.html?$/i, ".less");
        jsData = "`\r\n" + data.replace(/>\s+</g, "><").replace(/(?<=[^\\]|^)\\['"]/g, "\\$&") + "`";
        promise = getFileData(lesspath).then(function (lessdata) {
            if (lessdata instanceof Buffer) {
                return renderLessData(lessdata, lesspath, watchurls, lessName).then(function (data) {
                    lessData = data;
                });
            }
        });
    } else if (/\.(?:[jt]sx?)$/i.test(fullpath)) {
        let htmlpath = fullpath.replace(/\.[jt]sx?$/i, ".html");
        let lesspath = fullpath.replace(/\.[jt]sx?$/i, ".less");
        let replace = loadUseBody(data, fullpath, watchurls, commName);
        promise = Promise.all([lesspath, htmlpath].map(getFileData).concat(replace)).then(function ([lessdata, htmldata, data]) {
            if (htmldata instanceof Buffer) {
                var commHtmlName;
                if (/^main/.test(commName)) {
                    commHtmlName = 'Main';
                } else {
                    commHtmlName = commName[0].toUpperCase() + commName.slice(1);
                    if (commHtmlName !== commName) {
                        commHtmlName = `${commName},${commHtmlName},${commHtmlName}=${commName}`;
                    }
                }
                htmldata = "`" + String(htmldata).replace(/>\s+</g, "><").replace(/(?<=[^\\]|^)\\['"]/g, "\\$&") + "`"
                htmldata = htmldata.replace(/\>\s+/g, ">").replace(/\s+\</g, "<").replace(/\<\!\-\-.*?\-\-\>/g, "");
                if (data) {
                    jsData = `\r\nvar ${commHtmlName}={toString:()=>${htmldata}};\r\n` + data;
                } else {
                    jsData = htmldata;
                }
                watchurls.push(htmlpath);
            } else {
                jsData = String(data);
            }
            if (lessdata instanceof Buffer) {
                return renderLessData(lessdata, lesspath, watchurls, lessName).then(data => lessData = data);
            }
        });
    }
    if (promise) {
        promise = promise.then(function () {
            try {
                var timeStart = new Date;
                var data = loadJsBody(jsData, filename, lessData, commName, className);
                data = Buffer.from(data);
                data.time = new Date - timeStart;
                return data;
            } catch (e) {
                console.error(fullpath, e);
            }
        });
    }
    return promise || data;
};<|endoftext|>


<commit_before>;((exports) => {
    "use strict";

    // https://www.mozilla.org/en-US/styleguide/identity/firefox/color/
    const FIREFOX_ORANGE = "#E66000";
    const FIREFOX_LIGHT_ORANGE = "#FF9500";
    const FIREFOX_YELLOW = "#FFCB00";
    const FIREFOX_BLUE = "#00539F";
    const FIREFOX_LIGHT_BLUE = "#0095DD";
    const FIREFOX_LIGHT_BLUE_GREY1 = "#EAEFF2";
    const FIREFOX_LIGHT_BLUE_GREY2 = "#D4DDE4";
    const FIREFOX_DARK_BLUE_GREY1 = "#424F5A";
    const FIREFOX_DARK_BLUE_GREY2 = "#6A7B86";

    const MS_PER_DAY = 24*60*60*1000;
    const MS_PER_WEEK = 7*MS_PER_DAY;
    const MS_PER_MONTH = 4*MS_PER_WEEK;

    const DEBUG = true;
    function debug(...args) { DEBUG && console.debug(...args); }

    function days(d) { return d * MS_PER_DAY; }
    function weeks(w) { return days(7 * w); }
    function months(m) { return weeks(4 * m); }

    const queryString = getQueryString();
    const chartStartDate = getChartStartDate();

    function getQueryString() {
        // e.g. "?foo=bar&baz=qux&/"
        let qs = window.location.search;
        if (qs.length <= 1) {
            return "";
        }
        const slash = (qs[qs.length - 1] === '/') ? -1 : undefined;
        return qs.slice(1, slash);
    }

    function getChartStartDate() {
      const CHART_START_PERIOD = months(3);
      const searchParams = parseQueryString(queryString);
      return searchParams.since ||
             yyyy_mm_dd(new Date(Date.now() - CHART_START_PERIOD));

      function parseQueryString(qs) {
          // e.g. "foo=bar&baz=qux&"
          const kvs = {};
          const params = qs.split("&");
          _.forEach(params, kv => {
              kv = kv.split("=", 2);
              const key = kv[0].toLowerCase();
              if (key.length === 0) {
                  return; // "&&"
              }
              const value = (kv.length > 1) ? decodeURIComponent(kv[1]) : null;
              kvs[key] = value;
          });
          return kvs;
      }
    }

    function getElementValue(id) {
        return document.getElementById(id).value;
    }

    function yyyy_mm_dd(date) {
        return date.toISOString().slice(0,10);
    }

    function drawChart(data) {
        c3.generate({
            data: {
                x: "x",
                columns: [
                    ["x", ...data.dates],
                    ["closedBugCounts", ...data.closedBugCounts],
                    ["openBugCounts", ...data.openBugCounts],
                ],
                names: {
                    openBugCounts: "Open Bugs",
                    closedBugCounts: "Closed Bugs",
                },
                types: {
                    openBugCounts: "area",
                    closedBugCounts: "area",
                },
                colors: {
                    openBugCounts: FIREFOX_LIGHT_ORANGE,
                    closedBugCounts: FIREFOX_LIGHT_BLUE,
                },
                groups: [
                    ["openBugCounts", "closedBugCounts"],
                ],
                order: null,
            },
            axis: {
                x: {
                    type: "timeseries",
                    tick: {
                        format: "%Y-%m-%d",
                    }
                }
            },
        });
    }

    function createElement(tag, child) {
        const element = document.createElement(tag);
        if (typeof child !== "undefined") {
            if (typeof child !== "object") {
                child = document.createTextNode(child.toString());
            }
            element.appendChild(child);
        }
        return element;
    }

    function createLink(text, url) {
        const element = createElement("a", text);
        element.setAttribute("href", url);
        return element;
    }

    function setErrorText(msg) {
        let chart = document.getElementById("chart");
        chart.innerText = msg;
    }

    function searchAndPlotBugs() {
        const t0 = Date.now();
        debug(`searchAndPlotBugs: ${queryString}`);

        $bugzilla.searchBugs(queryString, (error, bugs) => {
            const t1 = Date.now();
            debug(`searchAndPlotBugs: ${t1 - t0} ms`);

            if (error) {
                setErrorText(`☠ ${error.type}`);
                return;
            }

            if (bugs.length === 0) {
                setErrorText("🙈 Zarro boogs found");
                return;
            }

            let changes = {};

            function getChange(date) {
                date = yyyy_mm_dd(date);
                let change = changes[date];
                if (!change) {
                    change = {date: date, bugsOpened: [], bugsClosed: []};
                    changes[date] = change;
                }
                return change;
            }

            const bugList = document.getElementById("bugs");
            let listURL = `https://bugzilla.mozilla.org/buglist.cgi?bug_id=`;

            _.forEach(bugs, bug => {
                if (bug.open) {
                    const bugURL = $bugzilla.makeURL(bug.id);
                    //debug(`Bug ${bug.id} - ${bug.summary}`, bugURL);

                    const bugRow = createElement("div");
                    bugRow.appendChild(createLink(`bug ${bug.id} - ${bug.summary}`, bugURL));
                    bugList.appendChild(bugRow);
                    listURL += `${bug.id},`;
                }

                getChange(bug.reportedAt).bugsOpened.push(bug);

                if (!bug.open) {
                    // XXX pretend last change time is time of resolution
                    getChange(bug.lastModifiedAt).bugsClosed.push(bug);
                }
            });

            const openLink = createLink("Open bug list in Bugzilla", listURL);
            openLink.classList.add('open-bugzilla');
            bugList.appendChild(openLink);

            const bugDates = [];
            const openBugCounts = [];
            const closedBugCounts = [];

            let runningOpenBugCount = 0;
            let runningClosedBugCount = 0;

            changes = _.sortBy(changes, "date");

            _.forEach(changes, change => {
                // How many bugs were closed or opened today?
                const closedBugCountDelta = change.bugsClosed.length;
                const openBugCountDelta = change.bugsOpened.length - closedBugCountDelta;

                runningOpenBugCount += openBugCountDelta;
                runningClosedBugCount += closedBugCountDelta;

                if (change.date >= chartStartDate) {
                    bugDates.push(change.date);
                    openBugCounts.push(runningOpenBugCount);
                    closedBugCounts.push(runningClosedBugCount);
                }
            });

            if (bugDates.length > 0) {
                // Extend earliest bug count to beginning of chart start date.
                if (bugDates[0] > chartStartDate) {
                    bugDates.unshift(chartStartDate);
                    openBugCounts.unshift(_.head(openBugCounts));
                    closedBugCounts.unshift(_.head(closedBugCounts));
                }

                // Extend last bug count to today, so burndown ends on today.
                const today = yyyy_mm_dd(new Date());
                if (_.last(bugDates) < today) {
                    bugDates.push(today);
                    openBugCounts.push(_.last(openBugCounts));
                    closedBugCounts.push(_.last(closedBugCounts));
                }
            }

            drawChart({
                dates: bugDates,
                openBugCounts: openBugCounts,
                closedBugCounts: closedBugCounts,
            });
        });
    }

    searchAndPlotBugs();

    const title = queryString.split("&").join(", ");
    document.title = `Burning up: ${title}`;
})(this);
<commit_msg>vomiting face error<commit_after>;((exports) => {
    "use strict";

    // https://www.mozilla.org/en-US/styleguide/identity/firefox/color/
    const FIREFOX_ORANGE = "#E66000";
    const FIREFOX_LIGHT_ORANGE = "#FF9500";
    const FIREFOX_YELLOW = "#FFCB00";
    const FIREFOX_BLUE = "#00539F";
    const FIREFOX_LIGHT_BLUE = "#0095DD";
    const FIREFOX_LIGHT_BLUE_GREY1 = "#EAEFF2";
    const FIREFOX_LIGHT_BLUE_GREY2 = "#D4DDE4";
    const FIREFOX_DARK_BLUE_GREY1 = "#424F5A";
    const FIREFOX_DARK_BLUE_GREY2 = "#6A7B86";

    const MS_PER_DAY = 24*60*60*1000;
    const MS_PER_WEEK = 7*MS_PER_DAY;
    const MS_PER_MONTH = 4*MS_PER_WEEK;

    const DEBUG = true;
    function debug(...args) { DEBUG && console.debug(...args); }

    function days(d) { return d * MS_PER_DAY; }
    function weeks(w) { return days(7 * w); }
    function months(m) { return weeks(4 * m); }

    const queryString = getQueryString();
    const chartStartDate = getChartStartDate();

    function getQueryString() {
        // e.g. "?foo=bar&baz=qux&/"
        let qs = window.location.search;
        if (qs.length <= 1) {
            return "";
        }
        const slash = (qs[qs.length - 1] === '/') ? -1 : undefined;
        return qs.slice(1, slash);
    }

    function getChartStartDate() {
      const CHART_START_PERIOD = months(3);
      const searchParams = parseQueryString(queryString);
      return searchParams.since ||
             yyyy_mm_dd(new Date(Date.now() - CHART_START_PERIOD));

      function parseQueryString(qs) {
          // e.g. "foo=bar&baz=qux&"
          const kvs = {};
          const params = qs.split("&");
          _.forEach(params, kv => {
              kv = kv.split("=", 2);
              const key = kv[0].toLowerCase();
              if (key.length === 0) {
                  return; // "&&"
              }
              const value = (kv.length > 1) ? decodeURIComponent(kv[1]) : null;
              kvs[key] = value;
          });
          return kvs;
      }
    }

    function getElementValue(id) {
        return document.getElementById(id).value;
    }

    function yyyy_mm_dd(date) {
        return date.toISOString().slice(0,10);
    }

    function drawChart(data) {
        c3.generate({
            data: {
                x: "x",
                columns: [
                    ["x", ...data.dates],
                    ["closedBugCounts", ...data.closedBugCounts],
                    ["openBugCounts", ...data.openBugCounts],
                ],
                names: {
                    openBugCounts: "Open Bugs",
                    closedBugCounts: "Closed Bugs",
                },
                types: {
                    openBugCounts: "area",
                    closedBugCounts: "area",
                },
                colors: {
                    openBugCounts: FIREFOX_LIGHT_ORANGE,
                    closedBugCounts: FIREFOX_LIGHT_BLUE,
                },
                groups: [
                    ["openBugCounts", "closedBugCounts"],
                ],
                order: null,
            },
            axis: {
                x: {
                    type: "timeseries",
                    tick: {
                        format: "%Y-%m-%d",
                    }
                }
            },
        });
    }

    function createElement(tag, child) {
        const element = document.createElement(tag);
        if (typeof child !== "undefined") {
            if (typeof child !== "object") {
                child = document.createTextNode(child.toString());
            }
            element.appendChild(child);
        }
        return element;
    }

    function createLink(text, url) {
        const element = createElement("a", text);
        element.setAttribute("href", url);
        return element;
    }

    function setErrorText(msg) {
        let chart = document.getElementById("chart");
        chart.innerText = msg;
    }

    function searchAndPlotBugs() {
        const t0 = Date.now();
        debug(`searchAndPlotBugs: ${queryString}`);

        $bugzilla.searchBugs(queryString, (error, bugs) => {
            const t1 = Date.now();
            debug(`searchAndPlotBugs: ${t1 - t0} ms`);

            if (error) {
                setErrorText(`🤮 ${error.type}`);
                return;
            }

            if (bugs.length === 0) {
                setErrorText("🙈 Zarro boogs found");
                return;
            }

            let changes = {};

            function getChange(date) {
                date = yyyy_mm_dd(date);
                let change = changes[date];
                if (!change) {
                    change = {date: date, bugsOpened: [], bugsClosed: []};
                    changes[date] = change;
                }
                return change;
            }

            const bugList = document.getElementById("bugs");
            let listURL = `https://bugzilla.mozilla.org/buglist.cgi?bug_id=`;

            _.forEach(bugs, bug => {
                if (bug.open) {
                    const bugURL = $bugzilla.makeURL(bug.id);
                    //debug(`Bug ${bug.id} - ${bug.summary}`, bugURL);

                    const bugRow = createElement("div");
                    bugRow.appendChild(createLink(`bug ${bug.id} - ${bug.summary}`, bugURL));
                    bugList.appendChild(bugRow);
                    listURL += `${bug.id},`;
                }

                getChange(bug.reportedAt).bugsOpened.push(bug);

                if (!bug.open) {
                    // XXX pretend last change time is time of resolution
                    getChange(bug.lastModifiedAt).bugsClosed.push(bug);
                }
            });

            const openLink = createLink("Open bug list in Bugzilla", listURL);
            openLink.classList.add('open-bugzilla');
            bugList.appendChild(openLink);

            const bugDates = [];
            const openBugCounts = [];
            const closedBugCounts = [];

            let runningOpenBugCount = 0;
            let runningClosedBugCount = 0;

            changes = _.sortBy(changes, "date");

            _.forEach(changes, change => {
                // How many bugs were closed or opened today?
                const closedBugCountDelta = change.bugsClosed.length;
                const openBugCountDelta = change.bugsOpened.length - closedBugCountDelta;

                runningOpenBugCount += openBugCountDelta;
                runningClosedBugCount += closedBugCountDelta;

                if (change.date >= chartStartDate) {
                    bugDates.push(change.date);
                    openBugCounts.push(runningOpenBugCount);
                    closedBugCounts.push(runningClosedBugCount);
                }
            });

            if (bugDates.length > 0) {
                // Extend earliest bug count to beginning of chart start date.
                if (bugDates[0] > chartStartDate) {
                    bugDates.unshift(chartStartDate);
                    openBugCounts.unshift(_.head(openBugCounts));
                    closedBugCounts.unshift(_.head(closedBugCounts));
                }

                // Extend last bug count to today, so burndown ends on today.
                const today = yyyy_mm_dd(new Date());
                if (_.last(bugDates) < today) {
                    bugDates.push(today);
                    openBugCounts.push(_.last(openBugCounts));
                    closedBugCounts.push(_.last(closedBugCounts));
                }
            }

            drawChart({
                dates: bugDates,
                openBugCounts: openBugCounts,
                closedBugCounts: closedBugCounts,
            });
        });
    }

    searchAndPlotBugs();

    const title = queryString.split("&").join(", ");
    document.title = `Burning up: ${title}`;
})(this);
<|endoftext|>


<commit_before>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// @ts-nocheck
// TODO(crbug.com/1011811): Enable TypeScript compiler checks

import * as Common from '../common/common.js';
import * as Components from '../components/components.js';
import * as UI from '../ui/ui.js';
import * as Workspace from '../workspace/workspace.js';

import {FileSystemWorkspaceBinding} from './FileSystemWorkspaceBinding.js';
import {NetworkPersistenceManager} from './NetworkPersistenceManager.js';
import {Events, PersistenceBinding, PersistenceImpl} from './PersistenceImpl.js';  // eslint-disable-line no-unused-vars

export class PersistenceUtils {
  /**
   * @param {!Workspace.UISourceCode.UISourceCode} uiSourceCode
   * @return {string}
   */
  static tooltipForUISourceCode(uiSourceCode) {
    const binding = PersistenceImpl.instance().binding(uiSourceCode);
    if (!binding) {
      return '';
    }
    if (uiSourceCode === binding.network) {
      return FileSystemWorkspaceBinding.tooltipForUISourceCode(binding.fileSystem);
    }
    if (binding.network.contentType().isFromSourceMap()) {
      return Common.UIString.UIString('Linked to source map: %s', binding.network.url().trimMiddle(150));
    }
    return Common.UIString.UIString('Linked to %s', binding.network.url().trimMiddle(150));
  }

  /**
   * @param {!Workspace.UISourceCode.UISourceCode} uiSourceCode
   * @return {?UI.Icon.Icon}
   */
  static iconForUISourceCode(uiSourceCode) {
    const binding = PersistenceImpl.instance().binding(uiSourceCode);
    if (binding) {
      if (!binding.fileSystem.url().startsWith('file://')) {
        return null;
      }
      const icon = UI.Icon.Icon.create('mediumicon-file-sync');
      icon.title = PersistenceUtils.tooltipForUISourceCode(binding.network);
      // TODO(allada) This will not work properly with dark theme.
      if (NetworkPersistenceManager.instance().project() === binding.fileSystem.project()) {
        icon.style.filter = 'hue-rotate(160deg)';
      }
      return icon;
    }
    if (uiSourceCode.project().type() !== Workspace.Workspace.projectTypes.FileSystem ||
        !uiSourceCode.url().startsWith('file://')) {
      return null;
    }

    const icon = UI.Icon.Icon.create('mediumicon-file');
    icon.title = PersistenceUtils.tooltipForUISourceCode(uiSourceCode);
    return icon;
  }
}

/**
 * @extends {Common.ObjectWrapper.ObjectWrapper}
 * @implements {Components.Linkifier.LinkDecorator}
 */
export class LinkDecorator extends Common.ObjectWrapper.ObjectWrapper {
  /**
   * @param {!PersistenceImpl} persistence
   */
  constructor(persistence) {
    super();
    persistence.addEventListener(Events.BindingCreated, this._bindingChanged, this);
    persistence.addEventListener(Events.BindingRemoved, this._bindingChanged, this);
  }

  /**
   * @param {!Common.EventTarget.EventTargetEvent} event
   */
  _bindingChanged(event) {
    const binding = /** @type {!PersistenceBinding} */ (event.data);
    this.dispatchEventToListeners(Components.Linkifier.LinkDecorator.Events.LinkIconChanged, binding.network);
  }

  /**
   * @override
   * @param {!Workspace.UISourceCode.UISourceCode} uiSourceCode
   * @return {?UI.Icon.Icon}
   */
  linkIcon(uiSourceCode) {
    return PersistenceUtils.iconForUISourceCode(uiSourceCode);
  }
}
<commit_msg>Enable TypeScript for PersistenceUtils.js<commit_after>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import * as Common from '../common/common.js';
import * as Components from '../components/components.js';
import * as UI from '../ui/ui.js';
import * as Workspace from '../workspace/workspace.js';

import {FileSystemWorkspaceBinding} from './FileSystemWorkspaceBinding.js';
import {NetworkPersistenceManager} from './NetworkPersistenceManager.js';
import {Events, PersistenceBinding, PersistenceImpl} from './PersistenceImpl.js';  // eslint-disable-line no-unused-vars

export class PersistenceUtils {
  /**
   * @param {!Workspace.UISourceCode.UISourceCode} uiSourceCode
   * @return {string}
   */
  static tooltipForUISourceCode(uiSourceCode) {
    const binding = PersistenceImpl.instance().binding(uiSourceCode);
    if (!binding) {
      return '';
    }
    if (uiSourceCode === binding.network) {
      return FileSystemWorkspaceBinding.tooltipForUISourceCode(binding.fileSystem);
    }
    if (binding.network.contentType().isFromSourceMap()) {
      return Common.UIString.UIString('Linked to source map: %s', binding.network.url().trimMiddle(150));
    }
    return Common.UIString.UIString('Linked to %s', binding.network.url().trimMiddle(150));
  }

  /**
   * @param {!Workspace.UISourceCode.UISourceCode} uiSourceCode
   * @return {?UI.Icon.Icon}
   */
  static iconForUISourceCode(uiSourceCode) {
    const binding = PersistenceImpl.instance().binding(uiSourceCode);
    if (binding) {
      if (!binding.fileSystem.url().startsWith('file://')) {
        return null;
      }
      const icon = UI.Icon.Icon.create('mediumicon-file-sync');
      icon.title = PersistenceUtils.tooltipForUISourceCode(binding.network);
      // TODO(allada) This will not work properly with dark theme.
      if (NetworkPersistenceManager.instance().project() === binding.fileSystem.project()) {
        icon.style.filter = 'hue-rotate(160deg)';
      }
      return icon;
    }
    if (uiSourceCode.project().type() !== Workspace.Workspace.projectTypes.FileSystem ||
        !uiSourceCode.url().startsWith('file://')) {
      return null;
    }

    const icon = UI.Icon.Icon.create('mediumicon-file');
    icon.title = PersistenceUtils.tooltipForUISourceCode(uiSourceCode);
    return icon;
  }
}

/**
 * @extends {Common.ObjectWrapper.ObjectWrapper}
 * @implements {Components.Linkifier.LinkDecorator}
 */
export class LinkDecorator extends Common.ObjectWrapper.ObjectWrapper {
  /**
   * @param {!PersistenceImpl} persistence
   */
  constructor(persistence) {
    super();
    persistence.addEventListener(Events.BindingCreated, this._bindingChanged, this);
    persistence.addEventListener(Events.BindingRemoved, this._bindingChanged, this);
  }

  /**
   * @param {!Common.EventTarget.EventTargetEvent} event
   */
  _bindingChanged(event) {
    const binding = /** @type {!PersistenceBinding} */ (event.data);
    this.dispatchEventToListeners(Components.Linkifier.LinkDecorator.Events.LinkIconChanged, binding.network);
  }

  /**
   * @override
   * @param {!Workspace.UISourceCode.UISourceCode} uiSourceCode
   * @return {?UI.Icon.Icon}
   */
  linkIcon(uiSourceCode) {
    return PersistenceUtils.iconForUISourceCode(uiSourceCode);
  }
}
<|endoftext|>


<commit_before>// $Id$

// Borrowed nearly intact from QuirksMode:
// http://www.quirksmode.org/index.html?/js/display.html

// FIXME: clean this up, ticket #168
window.onload = function () {
    var x = document.getElementsByTagName('div');
    for (var i=0;i<x.length;i++)
    {
        if (x[i].className == 'label')
            x[i].onclick = clickNav;
    }
    closeNav();
    if (top.setNav)
        setNav(top.setNav,'currentPage');

    // Uncomment to remove debugging info
    //createLoggingPane(true);
}

function closeNav() {
    var x = document.getElementsByTagName('div');
    for (var i=0;i<x.length;i++)
    {
        if (x[i].className == 'hideable')
            x[i].style.display = 'none';
    }
}

function clickNav(e) {
    if (!e) var e = window.event;
    if (e.target) var tg = e.target;
    else if (e.srcElement) var tg = e.srcElement;
    while (tg.nodeName != 'DIV') // Safari GRRRRRRRRRR
        tg = tg.parentNode;
    var nextSib = tg.nextSibling;
    while (nextSib.nodeType != 1)
        nextSib = nextSib.nextSibling;
    var nextSibStatus = (nextSib.style.display == 'none') ? 'block' : 'none';
    nextSib.style.display = nextSibStatus;
}

function setNav(page, newID)
{
    // Added try/catch to avoid IE error dialogs (dchud)
    try {
        var test = page.indexOf('#')+1;
    } catch (e) {
        ;
    }
    if (test)
        page = page.substring(0,test-1);
    var x = document.getElementsByTagName('a');
    var i;
    for (i=0;i<x.length;i++)
    {
        if (x[i].href == page)
        {
            x[i].id = newID;
            break;
        }
    }
    if (i < x.length && newID == 'currentPage')
    {
        var parDiv = x[i];
        while (parDiv.parentNode.tagName == 'DIV')
        {
            parDiv = parDiv.parentNode;
            parDiv.style.display = 'block';
        }
    }
}

function hideItem(id)
{
    var item = document.getElementById(id);
    item.style.display='none';
}

function showItem(id)
{
    var item = document.getElementById(id);
    item.style.display='block';
}

// *visible() funcs are suggested code from MochiKit docs
function toggleVisible(elem) {
    toggleElementClass("invisible", elem);
}

function makeVisible(elem) {
    removeElementClass(elem, "invisible");
}

function makeInvisible(elem) {
    addElementClass(elem, "invisible");
}

function isVisible(elem) {
    // you may also want to check for
    // getElement(elem).style.display == "none"
    return !hasElementClass(elem, "invisible");
};

var succeeded = function (r) {
    if (r['status'] == '200') {
        ; // Success; maybe flash something?
    } else {
        alert(r['reason']);
    }
};

var failed = function (err) {
    alert('An error occurred, please try again.');
};

var hidewait = function (waitimage) {
    waitimage.innerHTML = '';
};

function record_has_sets (record_id) {
    var has_sets = 0;
    var record_set_checks = getElementsByTagAndClassName('input', 'checkbox');
    for (i=0; i<record_set_checks.length; i++) {
        var check = record_set_checks[i];
        var id = getNodeAttribute(check, 'id');
        if (id.indexOf('record-' + record_id + '-set') >= 0) {
            if (check.checked == true) {
                has_sets +=1;
            }
        }
    }
    return has_sets;
};

function recordClicked (record_id, user_id) {
    var recordsets = getElement('recordsets-' + record_id);
    var checkinput = getElement('recordcheckinput-' + record_id);
    var waitimage = getElement('waitimage-' + record_id);
    waitimage.innerHTML = '';
    var nowait = partial(hidewait, waitimage);
    var url = '';
    if (checkinput.checked == true) {
        url = '/user/add_record?record_id=' + record_id;
        makeVisible(recordsets);
    } else {
        var record_sets = record_has_sets(record_id);
        if (record_sets > 0) {
            if (!confirm("Drop record and its sets?")) {
                setNodeAttribute(checkinput, 'checked',  'CHECKED');
                waitimage.innerHTML = '';
                return;
            }
        }
        url = '/user/remove_record?record_id=' + record_id;
        makeInvisible(recordsets);
    }
    var d = loadJSONDoc(url);
    d.addCallbacks(succeeded, failed);
    d.addBoth(nowait);
};

function recordSetClicked (record_id, set_id) {
    var record_check = getElement('recordcheckinput-' + record_id)
    var rstr = 'record-' + record_id + '-set-' + set_id;
    var checkinput = getElement(rstr + '-checkinput');
    var waitimage = getElement('waitimage-' + record_id);
    waitimage.innerHTML = '';
    var nowait = partial(hidewait, waitimage);
    var url = '';
    if (checkinput.checked == true) {
        url = '/user/add_record_set?record_id=' + record_id + '&set_id=' + set_id;
        record_check.disabled = 'disabled';
    } else {
        url = '/user/remove_record_set?record_id=' + record_id + '&set_id=' + set_id;
        var record_sets = record_has_sets(record_id);
        if (record_sets == 0) {
            record_check.disabled = false;
            setNodeAttribute(record_check, 'checked',  'CHECKED');
        }
    }
    var d = loadJSONDoc(url);
    d.addCallbacks(succeeded, failed);
    d.addBoth(nowait);
}

function startCreateSet (id) {
    logDebug('Creating inputForm');
    var inputForm = FORM({'action': '/user/create-set',
        'method': 'get',
        'id': 'createsetform-' + id},
        INPUT(null, {'name': 'setname',
            'size': 30})
        );
    logDebug('Getting createuserset create-set-link-' + id);
    var createuserset = getElement('create-set-link-' + id);
    if (createuserset) {
        swapDOM(createuserset, inputForm);
    } else {
        logDebug('createuserset not found');
    }
}

function addUserSet (evt) {
    evt = (evt) ? evt : event;
    var charCode = (evt.charCode) ? evt.charCode :
        ((evt.which) ? evt.which : evt.keyCode);
    if (charCode == 13 || charCode == 3) {
        var waitimage = getElement('waitimage');
        waitimage.innerHTML = '';
        var nowait = partial(hidewait, waitimage);
        var set_name_input = getElement('set_name_input');
        var input = set_name_input.value;
        var url = '/user/create_set?set_name=' + input;
        var d = loadJSONDoc(url);
        var success = function (r) {
            if (r['status'] == '406') {
                alert(r['reason']);
            } else if (r['status'] == '200') {
                var uid = r['uid'];
                var newSet = TR({'id': 'usersetrow-' + uid,
                        'class': 'userset'},
                    TD({'class': 'userset',
                        'id': 'userset-' + uid},
                        A({'href': '/user/set/' + uid},
                            [input])),
                    TD(null, '0 records'),
                    TD(null,
                        ['[',
                        A({'href': '/user/set/' + uid + '/lock'},
                            ['lock']),
                        '] [',
                        A({'href': '/user/set/' + uid + '/delete'},
                            ['delete']),
                        ']']
                        )
                    );
                var addnewset = getElement('addnewset');
                removeElement(addnewset);
                var usersets = getElement('usersets');
                appendChildNodes(usersets, newSet, addnewset);
                set_name_input.value = '';
            }
        };
        d.addCallbacks(success, failed);
        d.addBoth(nowait);
    }
}
<commit_msg>Tweak properties.<commit_after>// $Id$

// FIXME: clean this up, ticket #168
// Uncomment to remove debugging info
createLoggingPane(true);

// *visible() funcs are suggested code from MochiKit docs
function toggleVisible(elem) {
    toggleElementClass("invisible", elem);
}

function makeVisible(elem) {
    removeElementClass(elem, "invisible");
}

function makeInvisible(elem) {
    addElementClass(elem, "invisible");
}

function isVisible(elem) {
    // you may also want to check for
    // getElement(elem).style.display == "none"
    return !hasElementClass(elem, "invisible");
};

var succeeded = function (r) {
    if (r['status'] == '200') {
        ; // Success; maybe flash something?
    } else {
        alert(r['reason']);
    }
};

var failed = function (err) {
    alert('An error occurred, please try again.');
};

var hidewait = function (waitimage) {
    waitimage.innerHTML = '';
};

function record_has_sets (record_id) {
    var has_sets = 0;
    var record_set_checks = getElementsByTagAndClassName('input', 'checkbox');
    for (i=0; i<record_set_checks.length; i++) {
        var check = record_set_checks[i];
        var id = getNodeAttribute(check, 'id');
        if (id.indexOf('record-' + record_id + '-set') >= 0) {
            if (check.checked == true) {
                has_sets +=1;
            }
        }
    }
    return has_sets;
};

function recordClicked (record_id, user_id) {
    var recordsets = getElement('recordsets-' + record_id);
    var checkinput = getElement('recordcheckinput-' + record_id);
    var waitimage = getElement('waitimage-' + record_id);
    waitimage.innerHTML = '';
    var nowait = partial(hidewait, waitimage);
    var url = '';
    if (checkinput.checked == true) {
        url = '/user/add_record?record_id=' + record_id;
        makeVisible(recordsets);
    } else {
        var record_sets = record_has_sets(record_id);
        if (record_sets > 0) {
            if (!confirm("Drop record and its sets?")) {
                setNodeAttribute(checkinput, 'checked',  'CHECKED');
                waitimage.innerHTML = '';
                return;
            }
        }
        url = '/user/remove_record?record_id=' + record_id;
        makeInvisible(recordsets);
    }
    var d = loadJSONDoc(url);
    d.addCallbacks(succeeded, failed);
    d.addBoth(nowait);
};

function recordSetClicked (record_id, set_id) {
    var record_check = getElement('recordcheckinput-' + record_id)
    var rstr = 'record-' + record_id + '-set-' + set_id;
    var checkinput = getElement(rstr + '-checkinput');
    var waitimage = getElement('waitimage-' + record_id);
    waitimage.innerHTML = '';
    var nowait = partial(hidewait, waitimage);
    var url = '';
    if (checkinput.checked == true) {
        url = '/user/add_record_set?record_id=' + record_id + '&set_id=' + set_id;
        record_check.disabled = 'disabled';
    } else {
        url = '/user/remove_record_set?record_id=' + record_id + '&set_id=' + set_id;
        var record_sets = record_has_sets(record_id);
        if (record_sets == 0) {
            record_check.disabled = false;
            setNodeAttribute(record_check, 'checked',  'CHECKED');
        }
    }
    var d = loadJSONDoc(url);
    d.addCallbacks(succeeded, failed);
    d.addBoth(nowait);
}

function startCreateSet (id) {
    logDebug('Creating inputForm');
    var inputForm = FORM({'action': '/user/create-set',
        'method': 'get',
        'id': 'createsetform-' + id},
        INPUT(null, {'name': 'setname',
            'size': 30})
        );
    logDebug('Getting createuserset create-set-link-' + id);
    var createuserset = getElement('create-set-link-' + id);
    if (createuserset) {
        swapDOM(createuserset, inputForm);
    } else {
        logDebug('createuserset not found');
    }
}

function addUserSet (evt) {
    evt = (evt) ? evt : event;
    var charCode = (evt.charCode) ? evt.charCode :
        ((evt.which) ? evt.which : evt.keyCode);
    logDebug('charCode: ' + charCode);
    if (charCode == 13 || charCode == 3) {
        var waitimage = getElement('waitimage');
        waitimage.innerHTML = '';
        var nowait = partial(hidewait, waitimage);
        var set_name_input = getElement('set_name_input');
        var input = set_name_input.value;
        var url = '/user/create_set?set_name=' + input;
        var d = loadJSONDoc(url);
        var success = function (r) {
            if (r['status'] == '406') {
                alert(r['reason']);
            } else if (r['status'] == '200') {
                var uid = r['uid'];
                var newSet = TR({'id': 'usersetrow-' + uid,
                        'class': 'userset'},
                    TD({'class': 'userset',
                        'id': 'userset-' + uid},
                        A({'href': '/user/set/' + uid},
                            [input])),
                    TD(null, '0 records'),
                    TD(null,
                        ['[',
                        A({'href': '/user/set/' + uid + '/lock'},
                            ['lock']),
                        '] [',
                        A({'href': '/user/set/' + uid + '/delete'},
                            ['delete']),
                        ']']
                        )
                    );
                var addnewset = getElement('addnewset');
                removeElement(addnewset);
                var usersets = getElement('usersets');
                appendChildNodes(usersets, newSet, addnewset);
                set_name_input.value = '';
            }
        };
        d.addCallbacks(success, failed);
        d.addBoth(nowait);
    }
}
<|endoftext|>