<commit_before>
carto_quotables = [
  'text-face-name'
];

carto_variables = [
  'text-name'
];

var carto_functionMap= {
  'Equal Interval': 'quartiles',
  //'Jenks': 'jenkBins',
  'Heads/Tails': 'headTails',
  'Quantile': 'quantileBins'
};

//DEFAULT_QFUNCTION = carto_functionMap['Jenks']
DEFAULT_QFUNCTION = carto_functionMap['Equal Interval']

/**
 * some carto properties depends on others, this function
 * remove or add properties needed to carto works
 */
function manage_carto_properies(props) {
  if(/none/i.test(props['text-name'])) {
    // remove all text-* properties
    for(var p in props) {
      if(isTextProperty(p)) {
        delete props[p];
      }
    }
  }

  if(/none/i.test(props['polygon-comp-op'])) {
    delete props['polygon-comp-op'];
  }
  if(/none/i.test(props['line-comp-op'])) {
    delete props['line-comp-op'];
  }
  if(/none/i.test(props['marker-comp-op'])) {
    delete props['marker-comp-op'];
  }
}

function isTextProperty(p) {
  return /^text-/.test(p);
}

function generate_carto_properties(props) {
  return _(props).map(function(v, k) {
    if(_.include(carto_quotables, k)) {
      v = "'" + v + "'";
    }
    if(_.include(carto_variables, k)) {
      v = "[" + v + "]";
    }
    return "  " + k + ": " + v + ";";
  });
}

function filter_props(props, fn) {
  var p = {};
  for(var k in props) {
    var v = props[k];
    if(fn(k, v)) {
      p[k] = v;
    }
  }
  return p;
}

function simple_polygon_generator(table, props, callback) {

  // remove unnecesary properties, for example
  // if the text-name is not present remove all the
  // properties related to text
  manage_carto_properies(props);

  var text_properties = filter_props(props, function(k, v) { return isTextProperty(k); });
  var general_properties = filter_props(props, function(k, v) { return !isTextProperty(k); });

  generalLayerProps = generate_carto_properties(general_properties);
  textLayerProps = generate_carto_properties(text_properties);

  // layer with non-text properties
  var generalLayer = "#" + table.get('name') + "{\n" + generalLayerProps.join('\n') + "\n}";
  var textLayer = '';
  if(_.size(textLayerProps)) {
    textLayer = "\n\n#" + table.get('name') + "::labels {\n" + textLayerProps.join('\n') + "\n}\n";
  }

  // text properties layer
  callback(generalLayer + textLayer);
}

function intensity_generator(table, props, callback) {
  var table_name = table.get('name');

  // remove unnecesary properties, for example
  // if the text-name is not present remove all the
  // properties related to text
  manage_carto_properies(props);

  var carto_props = {
    'marker-fill': props['marker-fill'],
    'marker-width': props['marker-width'],
    'marker-line-color': props['marker-line-color'],
    'marker-line-width': props['marker-line-width'],
    'marker-line-opacity': props['marker-line-opacity'],
    'marker-comp-op': 'multiply',
    'marker-type': 'ellipse',
    'marker-placement': 'point',
    'marker-allow-overlap': true,
    'marker-clip': false,
    'marker-multi-policy': 'largest'
  };

  var css = "\n#" + table_name +"{\n";

  _(carto_props).each(function(prop, name) {
    css += "  " + name + ": " + prop + "; \n";
  });

  css += "}";
  callback(css);

}

function bubble_generator(table, props, callback) {
  var table_name = table.get('name');
  var carto_props = {
   'marker-fill': props['marker-fill'],
   'marker-line-color': props['marker-line-color'],
   'marker-line-width': props['marker-line-width'],
   'marker-line-opacity': props['marker-line-opacity'],
   'marker-opacity': props['marker-opacity'],
   'marker-comp-op': props['marker-comp-op'],
   'marker-placement': 'point',
   'marker-type': 'ellipse',
   'marker-allow-overlap': true,
   'marker-clip':false,
   'marker-multi-policy':'largest'
  };
  var prop = props['property'];
  var min = props['radius_min'];
  var max = props['radius_max'];
  var fn = carto_functionMap[props['qfunction'] || DEFAULT_QFUNCTION];

  if(/none/i.test(props['marker-comp-op'])) {
    delete carto_props['marker-comp-op'];
  }
  var values = [];

  var NPOINS = 10;
  // TODO: make this related to the quartiles size
  // instead of linear. The circle area should be related
  // to the data and a little correction due to the problems
  // humans have to measure the area of a circle

  //calculate the bubles sizes
  for(var i = 0; i < NPOINS; ++i) {
    var t = i/(NPOINS-1);
    values.push(min + t*(max - min));
  }

  // generate carto
  simple_polygon_generator(table, carto_props, function(css) {
    table.originalData()[fn](NPOINS, prop, function(quartiles)  {
      for(var i = NPOINS - 1; i >= 0; --i) {
        if(quartiles[i] !== undefined) {
          css += "\n#" + table_name +" [ " + prop + " <= " + quartiles[i] + "] {\n"
          css += "   marker-width: " + values[i].toFixed(1) + ";\n}"
        }
      }
      callback(css);
    });
  });
}

/**
 * when quartiles are greater than 1<<31 cast to float added .01
 * at the end. If you append only .0 it is casted to int and it
 * does not work
 */
function normalizeQuartiles(quartiles) {
  var maxNumber = 2147483648; // unsigned (1<<31);
  var normalized = [];
  for(var i = 0;  i < quartiles.length; ++i) {
    var q = quartiles[i];
    if(q > Math.abs(maxNumber)) {
      q = q + ".01";
    }
    normalized.push(q);
  }
  return normalized;
}

function choropleth_generator(table, props, callback) {
  var type = table.geomColumnTypes() && table.geomColumnTypes()[0] || "polygon";

  var carto_props = {
   'line-color': props['line-color'],
   'line-opacity': props['line-opacity'],
   'line-width': props['line-width'],
   'polygon-opacity': type == "line" ? 0 : props['polygon-opacity'],
   'text-name': props['text-name'],
   'text-halo-fill': props['text-halo-fill'],
   'text-halo-radius': props['text-halo-radius'],
   'text-face-name': props['text-face-name'],
   'text-size': props['text-size'],
   'text-fill': props['text-fill']
  }

  if(props['polygon-comp-op'] && !/none/i.test(props['polygon-comp-op'])) {
    carto_props['polygon-comp-op'] = props['polygon-comp-op'];
  }
  if(props['line-comp-op'] && !/none/i.test(props['line-comp-op'])) {
    carto_props['line-comp-op'] = props['line-comp-op'];
  }
  if(props['marker-comp-op'] && !/none/i.test(props['marker-comp-op'])) {
    carto_props['marker-comp-op'] = props['marker-comp-op'];
  }

  var methodMap = {
    '3 Buckets': 3,
    '5 Buckets': 5,
    '7 Buckets': 7
  };

  if(!props['color_ramp']) {
    return;
  }

  var fn = carto_functionMap[props['qfunction'] || DEFAULT_QFUNCTION];
  var prop = props['property'];
  var nquartiles = methodMap[props['method']];
  var ramp = cdb.admin.color_ramps[props['color_ramp']][nquartiles];
  var table_name = table.get('name');

  if(!ramp) {
    cdb.log.error("no color ramp defined for " + nquartiles + " quartiles");
  }

  simple_polygon_generator(table, carto_props, function(css) {
    table.originalData()[fn](nquartiles, prop, function(quartiles)  {
      quartiles = normalizeQuartiles(quartiles);
      for(var i = nquartiles - 1; i >= 0; --i) {
        if(quartiles[i] !== undefined) {
          css += "\n#" + table_name +" [ " + prop + " <= " + quartiles[i] + "] {\n";

          if (type == "line") {
            css += "   line-color: " + ramp[i] + ";\n}"
          } else {
            css += "   polygon-fill: " + ramp[i] + ";\n}"
          }
        }
      }
      callback(css);
    });
  });
}

/*
 *
 */
function density_generator(table, props, callback) {
  var carto_props = {
   'line-color': props['line-color'],
   'line-opacity': props['line-opacity'],
   'line-width': props['line-width'],
   'polygon-opacity': props['polygon-opacity'],
   'polygon-comp-op': props['polygon-comp-op']
  }

  if(/none/i.test(props['polygon-comp-op'])) {
    delete carto_props['polygon-comp-op'];
  }

  var methodMap = {
    '3 Buckets': 3,
    '5 Buckets': 5,
    '7 Buckets': 7
  };

  var polygon_size = props['polygon-size'];
  var nquartiles = methodMap[props['method']];
  var ramp = cdb.admin.color_ramps[props['color_ramp']][nquartiles];
  var table_name = table.get('name');

  if(!ramp) {
    cdb.log.error("no color ramp defined for " + nquartiles + " quartiles");
  }

  carto_props['polygon-fill'] = ramp[ramp.length - 1];

  simple_polygon_generator(table, carto_props, function(css) {

    // density
    var tmpl = _.template("" +
    "WITH clusters as ( " +
    "SELECT  " +
        "cartodb_id,   " +
        "st_snaptogrid(the_geom_webmercator, <%= polygon_size %>*CDB_XYZ_Resolution(<%= z %>)) as center  " +
    "FROM <%= table_name %>" +
    "), " +
    "points as ( " +
        "SELECT  " +
            "count(cartodb_id) as npoints,  " +
            "count(cartodb_id)/power( <%= polygon_size %> * CDB_XYZ_Resolution(<%= z %>), 2 ) as density  " +
        "FROM  " +
            "clusters  " +
        "group by  " +
            "center " +
    "), " +
    "stats as ( " +
        "SELECT  " +
            "npoints,  " +
            "density,  " +
            "ntile(<%= slots %>) over (order by density) as quartile  " +
        "FROM points  " +
    ")  " +
    "SELECT  " +
        "quartile,  " +
        "max(npoints) as maxAmount,  " +
        "max(density) as maxDensity   " +
    "FROM stats  " +
    "GROUP BY quartile ORDER BY quartile ");

    var sql = tmpl({
        slots: nquartiles,
        table_name: table.get('name'),
        polygon_size: polygon_size,
        z: props.zoom
    });

    table.originalData()._sqlQuery(sql, function(data) {
      // extract quartiles by zoom level
      var rows = data.rows;
      var quartiles = [];
      for(var i = 0; i < rows.length; ++i) {
        quartiles.push(rows[i].maxdensity);
      }

      quartiles = normalizeQuartiles(quartiles);

      css += "\n#" + table_name + "{\n"
      for(var i = nquartiles - 1; i >= 0; --i) {
        if(quartiles[i] !== undefined) {
          css += "  [points_density <= " + quartiles[i] + "] { polygon-fill: " + ramp[i] + ";  }\n";
        }
      }
      css += "\n}"
      callback(css);
    });
  });
}

cdb.admin.CartoStyles = Backbone.Model.extend({

    defaults: {
      type: 'polygon',
      properties: {
        'polygon-fill': '#FF6600',
        'line-color': '#FFFFFF',
        'line-width': 1,
        'polygon-opacity': 0.7,
        'line-opacity':1
      }
    },

    initialize: function() {
      this.table = this.get('table');

      if (!this.table) {
        throw "table must be passed as param"
        return;
      }

      this.bind('change:properties', this._generateCarto, this);

      this.generators = {};
      this.registerGenerator('polygon',    simple_polygon_generator);
      this.registerGenerator('bubble',     bubble_generator);
      this.registerGenerator('intensity',  intensity_generator);
      this.registerGenerator('choropleth', choropleth_generator);
      this.registerGenerator('density',    density_generator); // the same generator than choroplet
    },

    // change a property attribute
    attr: function(name, val) {
      var old = this.attributes.properties[name];
      this.attributes.properties[name] = val;
      if(old != val) {
        this.trigger('change:properties', this, this.attributes.properties);
        this.trigger('changes', this);
      }
    },

    registerGenerator: function(name, gen) {
      this.generators[name] = gen;
    },

    /**
     * generate a informative header
     */
    _generateHeader: function() {
      var typeMap = {
        'polygon': 'simple'
      }
      var t = this.get('type');
      t = typeMap[t] || t;
      var c = "/** " + t + " visualization */\n\n";
      return c;
    },

    _generateCarto: function(){
      var self = this;
      var gen = this.generators[this.get('type')];
      if(!gen) {
        cdb.log.error("can't get style generator for " + this.get('type'));
        return;
      }

      gen(this.table, this.get('properties'), function(style) {
        self.set({
          style: self._generateHeader() + style
        }, { silence: true});
        self.change({ changes: {'style': ''}});

      })
    },

    /**
     * when cartocss is rendered the generator and properties are written in a comment.
     * This function try to load params from that comment.
     *
     * return true if it is able to load style
     */
    loadFromCartoCSS: function(carto) {
      var genType, params;
      if(!carto)  return false;
      var g = carto.match(/genetor type: (\w+)/);
      if(g) {
        genType = g[1];
      }
      g = carto.match(/params: \{(.*)\}/);
      if(g) {
        try {
          params = JSON.parse("{" + g[1] + "}");
        } catch(e) {
          cdb.log.info("can't parse css options");
        }
      }

      if(params && genType && this.generators[genType]) {
        this.set({
          type: genType,
          properties: params
        });
        return true;
      }
      return false;

    }

});
<commit_msg>Fix marker opacity for the intensity wizard<commit_after>
carto_quotables = [
  'text-face-name'
];

carto_variables = [
  'text-name'
];

var carto_functionMap= {
  'Equal Interval': 'quartiles',
  //'Jenks': 'jenkBins',
  'Heads/Tails': 'headTails',
  'Quantile': 'quantileBins'
};

//DEFAULT_QFUNCTION = carto_functionMap['Jenks']
DEFAULT_QFUNCTION = carto_functionMap['Equal Interval']

/**
 * some carto properties depends on others, this function
 * remove or add properties needed to carto works
 */
function manage_carto_properies(props) {
  if(/none/i.test(props['text-name'])) {
    // remove all text-* properties
    for(var p in props) {
      if(isTextProperty(p)) {
        delete props[p];
      }
    }
  }

  if(/none/i.test(props['polygon-comp-op'])) {
    delete props['polygon-comp-op'];
  }
  if(/none/i.test(props['line-comp-op'])) {
    delete props['line-comp-op'];
  }
  if(/none/i.test(props['marker-comp-op'])) {
    delete props['marker-comp-op'];
  }
}

function isTextProperty(p) {
  return /^text-/.test(p);
}

function generate_carto_properties(props) {
  return _(props).map(function(v, k) {
    if(_.include(carto_quotables, k)) {
      v = "'" + v + "'";
    }
    if(_.include(carto_variables, k)) {
      v = "[" + v + "]";
    }
    return "  " + k + ": " + v + ";";
  });
}

function filter_props(props, fn) {
  var p = {};
  for(var k in props) {
    var v = props[k];
    if(fn(k, v)) {
      p[k] = v;
    }
  }
  return p;
}

function simple_polygon_generator(table, props, callback) {

  // remove unnecesary properties, for example
  // if the text-name is not present remove all the
  // properties related to text
  manage_carto_properies(props);

  var text_properties = filter_props(props, function(k, v) { return isTextProperty(k); });
  var general_properties = filter_props(props, function(k, v) { return !isTextProperty(k); });

  generalLayerProps = generate_carto_properties(general_properties);
  textLayerProps = generate_carto_properties(text_properties);

  // layer with non-text properties
  var generalLayer = "#" + table.get('name') + "{\n" + generalLayerProps.join('\n') + "\n}";
  var textLayer = '';
  if(_.size(textLayerProps)) {
    textLayer = "\n\n#" + table.get('name') + "::labels {\n" + textLayerProps.join('\n') + "\n}\n";
  }

  // text properties layer
  callback(generalLayer + textLayer);
}

function intensity_generator(table, props, callback) {
  var table_name = table.get('name');

  // remove unnecesary properties, for example
  // if the text-name is not present remove all the
  // properties related to text
  manage_carto_properies(props);

  var carto_props = {
    'marker-fill': props['marker-fill'],
    'marker-width': props['marker-width'],
    'marker-line-color': props['marker-line-color'],
    'marker-line-width': props['marker-line-width'],
    'marker-line-opacity': props['marker-line-opacity'],
    'marker-opacity': props['marker-opacity'],
    'marker-comp-op': 'multiply',
    'marker-type': 'ellipse',
    'marker-placement': 'point',
    'marker-allow-overlap': true,
    'marker-clip': false,
    'marker-multi-policy': 'largest'
  };

  var css = "\n#" + table_name +"{\n";

  _(carto_props).each(function(prop, name) {
    css += "  " + name + ": " + prop + "; \n";
  });

  css += "}";
  callback(css);

}

function bubble_generator(table, props, callback) {
  var table_name = table.get('name');
  var carto_props = {
   'marker-fill': props['marker-fill'],
   'marker-line-color': props['marker-line-color'],
   'marker-line-width': props['marker-line-width'],
   'marker-line-opacity': props['marker-line-opacity'],
   'marker-opacity': props['marker-opacity'],
   'marker-comp-op': props['marker-comp-op'],
   'marker-placement': 'point',
   'marker-type': 'ellipse',
   'marker-allow-overlap': true,
   'marker-clip':false,
   'marker-multi-policy':'largest'
  };
  var prop = props['property'];
  var min = props['radius_min'];
  var max = props['radius_max'];
  var fn = carto_functionMap[props['qfunction'] || DEFAULT_QFUNCTION];

  if(/none/i.test(props['marker-comp-op'])) {
    delete carto_props['marker-comp-op'];
  }
  var values = [];

  var NPOINS = 10;
  // TODO: make this related to the quartiles size
  // instead of linear. The circle area should be related
  // to the data and a little correction due to the problems
  // humans have to measure the area of a circle

  //calculate the bubles sizes
  for(var i = 0; i < NPOINS; ++i) {
    var t = i/(NPOINS-1);
    values.push(min + t*(max - min));
  }

  // generate carto
  simple_polygon_generator(table, carto_props, function(css) {
    table.originalData()[fn](NPOINS, prop, function(quartiles)  {
      for(var i = NPOINS - 1; i >= 0; --i) {
        if(quartiles[i] !== undefined) {
          css += "\n#" + table_name +" [ " + prop + " <= " + quartiles[i] + "] {\n"
          css += "   marker-width: " + values[i].toFixed(1) + ";\n}"
        }
      }
      callback(css);
    });
  });
}

/**
 * when quartiles are greater than 1<<31 cast to float added .01
 * at the end. If you append only .0 it is casted to int and it
 * does not work
 */
function normalizeQuartiles(quartiles) {
  var maxNumber = 2147483648; // unsigned (1<<31);
  var normalized = [];
  for(var i = 0;  i < quartiles.length; ++i) {
    var q = quartiles[i];
    if(q > Math.abs(maxNumber)) {
      q = q + ".01";
    }
    normalized.push(q);
  }
  return normalized;
}

function choropleth_generator(table, props, callback) {
  var type = table.geomColumnTypes() && table.geomColumnTypes()[0] || "polygon";

  var carto_props = {
   'line-color': props['line-color'],
   'line-opacity': props['line-opacity'],
   'line-width': props['line-width'],
   'polygon-opacity': type == "line" ? 0 : props['polygon-opacity'],
   'text-name': props['text-name'],
   'text-halo-fill': props['text-halo-fill'],
   'text-halo-radius': props['text-halo-radius'],
   'text-face-name': props['text-face-name'],
   'text-size': props['text-size'],
   'text-fill': props['text-fill']
  }

  if(props['polygon-comp-op'] && !/none/i.test(props['polygon-comp-op'])) {
    carto_props['polygon-comp-op'] = props['polygon-comp-op'];
  }
  if(props['line-comp-op'] && !/none/i.test(props['line-comp-op'])) {
    carto_props['line-comp-op'] = props['line-comp-op'];
  }
  if(props['marker-comp-op'] && !/none/i.test(props['marker-comp-op'])) {
    carto_props['marker-comp-op'] = props['marker-comp-op'];
  }

  var methodMap = {
    '3 Buckets': 3,
    '5 Buckets': 5,
    '7 Buckets': 7
  };

  if(!props['color_ramp']) {
    return;
  }

  var fn = carto_functionMap[props['qfunction'] || DEFAULT_QFUNCTION];
  var prop = props['property'];
  var nquartiles = methodMap[props['method']];
  var ramp = cdb.admin.color_ramps[props['color_ramp']][nquartiles];
  var table_name = table.get('name');

  if(!ramp) {
    cdb.log.error("no color ramp defined for " + nquartiles + " quartiles");
  }

  simple_polygon_generator(table, carto_props, function(css) {
    table.originalData()[fn](nquartiles, prop, function(quartiles)  {
      quartiles = normalizeQuartiles(quartiles);
      for(var i = nquartiles - 1; i >= 0; --i) {
        if(quartiles[i] !== undefined) {
          css += "\n#" + table_name +" [ " + prop + " <= " + quartiles[i] + "] {\n";

          if (type == "line") {
            css += "   line-color: " + ramp[i] + ";\n}"
          } else {
            css += "   polygon-fill: " + ramp[i] + ";\n}"
          }
        }
      }
      callback(css);
    });
  });
}

/*
 *
 */
function density_generator(table, props, callback) {
  var carto_props = {
   'line-color': props['line-color'],
   'line-opacity': props['line-opacity'],
   'line-width': props['line-width'],
   'polygon-opacity': props['polygon-opacity'],
   'polygon-comp-op': props['polygon-comp-op']
  }

  if(/none/i.test(props['polygon-comp-op'])) {
    delete carto_props['polygon-comp-op'];
  }

  var methodMap = {
    '3 Buckets': 3,
    '5 Buckets': 5,
    '7 Buckets': 7
  };

  var polygon_size = props['polygon-size'];
  var nquartiles = methodMap[props['method']];
  var ramp = cdb.admin.color_ramps[props['color_ramp']][nquartiles];
  var table_name = table.get('name');

  if(!ramp) {
    cdb.log.error("no color ramp defined for " + nquartiles + " quartiles");
  }

  carto_props['polygon-fill'] = ramp[ramp.length - 1];

  simple_polygon_generator(table, carto_props, function(css) {

    // density
    var tmpl = _.template("" +
    "WITH clusters as ( " +
    "SELECT  " +
        "cartodb_id,   " +
        "st_snaptogrid(the_geom_webmercator, <%= polygon_size %>*CDB_XYZ_Resolution(<%= z %>)) as center  " +
    "FROM <%= table_name %>" +
    "), " +
    "points as ( " +
        "SELECT  " +
            "count(cartodb_id) as npoints,  " +
            "count(cartodb_id)/power( <%= polygon_size %> * CDB_XYZ_Resolution(<%= z %>), 2 ) as density  " +
        "FROM  " +
            "clusters  " +
        "group by  " +
            "center " +
    "), " +
    "stats as ( " +
        "SELECT  " +
            "npoints,  " +
            "density,  " +
            "ntile(<%= slots %>) over (order by density) as quartile  " +
        "FROM points  " +
    ")  " +
    "SELECT  " +
        "quartile,  " +
        "max(npoints) as maxAmount,  " +
        "max(density) as maxDensity   " +
    "FROM stats  " +
    "GROUP BY quartile ORDER BY quartile ");

    var sql = tmpl({
        slots: nquartiles,
        table_name: table.get('name'),
        polygon_size: polygon_size,
        z: props.zoom
    });

    table.originalData()._sqlQuery(sql, function(data) {
      // extract quartiles by zoom level
      var rows = data.rows;
      var quartiles = [];
      for(var i = 0; i < rows.length; ++i) {
        quartiles.push(rows[i].maxdensity);
      }

      quartiles = normalizeQuartiles(quartiles);

      css += "\n#" + table_name + "{\n"
      for(var i = nquartiles - 1; i >= 0; --i) {
        if(quartiles[i] !== undefined) {
          css += "  [points_density <= " + quartiles[i] + "] { polygon-fill: " + ramp[i] + ";  }\n";
        }
      }
      css += "\n}"
      callback(css);
    });
  });
}

cdb.admin.CartoStyles = Backbone.Model.extend({

    defaults: {
      type: 'polygon',
      properties: {
        'polygon-fill': '#FF6600',
        'line-color': '#FFFFFF',
        'line-width': 1,
        'polygon-opacity': 0.7,
        'line-opacity':1
      }
    },

    initialize: function() {
      this.table = this.get('table');

      if (!this.table) {
        throw "table must be passed as param"
        return;
      }

      this.bind('change:properties', this._generateCarto, this);

      this.generators = {};
      this.registerGenerator('polygon',    simple_polygon_generator);
      this.registerGenerator('bubble',     bubble_generator);
      this.registerGenerator('intensity',  intensity_generator);
      this.registerGenerator('choropleth', choropleth_generator);
      this.registerGenerator('density',    density_generator); // the same generator than choroplet
    },

    // change a property attribute
    attr: function(name, val) {
      var old = this.attributes.properties[name];
      this.attributes.properties[name] = val;
      if(old != val) {
        this.trigger('change:properties', this, this.attributes.properties);
        this.trigger('changes', this);
      }
    },

    registerGenerator: function(name, gen) {
      this.generators[name] = gen;
    },

    /**
     * generate a informative header
     */
    _generateHeader: function() {
      var typeMap = {
        'polygon': 'simple'
      }
      var t = this.get('type');
      t = typeMap[t] || t;
      var c = "/** " + t + " visualization */\n\n";
      return c;
    },

    _generateCarto: function(){
      var self = this;
      var gen = this.generators[this.get('type')];
      if(!gen) {
        cdb.log.error("can't get style generator for " + this.get('type'));
        return;
      }

      gen(this.table, this.get('properties'), function(style) {
        self.set({
          style: self._generateHeader() + style
        }, { silence: true});
        self.change({ changes: {'style': ''}});

      })
    },

    /**
     * when cartocss is rendered the generator and properties are written in a comment.
     * This function try to load params from that comment.
     *
     * return true if it is able to load style
     */
    loadFromCartoCSS: function(carto) {
      var genType, params;
      if(!carto)  return false;
      var g = carto.match(/genetor type: (\w+)/);
      if(g) {
        genType = g[1];
      }
      g = carto.match(/params: \{(.*)\}/);
      if(g) {
        try {
          params = JSON.parse("{" + g[1] + "}");
        } catch(e) {
          cdb.log.info("can't parse css options");
        }
      }

      if(params && genType && this.generators[genType]) {
        this.set({
          type: genType,
          properties: params
        });
        return true;
      }
      return false;

    }

});
<|endoftext|>


<commit_before>Package.describe({
  name: "ecmascript-containers",
  version: "0.1.2",
  summary: "Polyfills for ECMAScript 2015 Map and Set",
  git: "https://github.com/meteor/ecmascript-containers",
  documentation: "README.md"
});

Npm.depends({
  "ecmascript-containers": "0.1.2"
});

Package.onUse(function(api) {
  api.addFiles("containers.js", "server");

  api.addFiles(
    ".npm/package/node_modules/ecmascript-containers/client.js",
    "client",
    { bare: true }
  );

  api.export("Map");
  api.export("Set");
});

Package.onTest(function(api) {
  api.use("tinytest");
  api.use("ecmascript-containers");
  api.addFiles("containers-tests.js");
});
<commit_msg>Upgrade ecmascript-containers to the latest NPM version.<commit_after>Package.describe({
  name: "ecmascript-containers",
  version: "0.1.3",
  summary: "Polyfills for ECMAScript 2015 Map and Set",
  git: "https://github.com/meteor/ecmascript-containers",
  documentation: "README.md"
});

Npm.depends({
  "ecmascript-containers": "0.1.3"
});

Package.onUse(function(api) {
  api.addFiles("containers.js", "server");

  api.addFiles(
    ".npm/package/node_modules/ecmascript-containers/client.js",
    "client",
    { bare: true }
  );

  api.export("Map");
  api.export("Set");
});

Package.onTest(function(api) {
  api.use("tinytest");
  api.use("ecmascript-containers");
  api.addFiles("containers-tests.js");
});
<|endoftext|>


<commit_before>/**
 * @license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.html or http://ckeditor.com/license
 */

CKEDITOR.editorConfig = function( config ) {
	// Define changes to default configuration here. For example:
	// config.language = 'fr';
	// config.uiColor = '#AADC6E';
};
<commit_msg>do not strip html<commit_after>/**
 * @license Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.html or http://ckeditor.com/license
 */

CKEDITOR.editorConfig = function( config ) {
	// Define changes to default configuration here. For example:
	// config.language = 'fr';
	// config.uiColor = '#AADC6E';
	config.allowedContent = true;
};
<|endoftext|>


<commit_before>var Docker = require('../lib/docker');

var docker = new Docker({
  socketPath: '/var/run/docker.sock'
});

docker.createContainer({
  Image: 'ubuntu',
  Cmd: ['/bin/ls', '/stuff'],
  'Volumes': {
    '/stuff': {}
  }
}, function(err, container) {
  container.attach({
    stream: true,
    stdout: true,
    stderr: true,
    tty: true
  }, function(err, stream) {
    stream.pipe(process.stdout);

    container.start({
      'Binds': ['/home/vagrant:/stuff']
    }, function(err, data) {
      console.log(data);
    });
  });
});
<commit_msg>Fixes https://github.com/apocas/dockerode/issues/359<commit_after>var Docker = require('../lib/docker');

var docker = new Docker({
  socketPath: '/var/run/docker.sock'
});

docker.createContainer({
  Image: 'ubuntu',
  Cmd: ['/bin/ls', '/stuff'],
  'Volumes': {
    '/stuff': {}
  },
  'Hostconfig': {
    'Binds': ['/home/vagrant:/stuff']
  }
}, function(err, container) {
  container.attach({
    stream: true,
    stdout: true,
    stderr: true,
    tty: true
  }, function(err, stream) {
    stream.pipe(process.stdout);

    container.start(function(err, data) {
      console.log(data);
    });
  });
});
<|endoftext|>


<commit_before>/* eslint-disable @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
// <% if (typescript) { %>
/// <% if (module) { %>
import fs from 'fs';
// <% } else { %>const fs = require('fs');<% } %>

const lintTSConfig = 'tsconfig.lint.json';

const generateTSConfig = (stagedFilenames) => {
  const tsconfig = JSON.parse(fs.readFileSync('tsconfig.json', 'utf8'));
  tsconfig.include = stagedFilenames;
  fs.writeFileSync(lintTSConfig, JSON.stringify(tsconfig));
  return 'tsc --noEmit --project tsconfig.lint.json';
};

const deleteTSConfig = (stagedFilenames) => {
  // eslint-disable-next-line no-param-reassign
  stagedFilenames.length = 0;
  if (fs.existsSync(lintTSConfig)) {
    fs.unlinkSync(lintTSConfig);
  }
  return '';
};
// <% } %>

/// <% if (module) { %>
export default {
  // <% } else { %>module.exports = {<% } %>
  // <% if (prettier) { %>
  '*': ['prettier --check'],
  // <% } %>
  // <% if (jsTarget) { %>
  '<%= jsTarget %>': [
    // <% if (eslint) { %>
    'eslint',
    // <% } %>
    // <% if (typescript) { %>
    generateTSConfig,
    deleteTSConfig,
    // <% } %>
    // <% if (jest) { %>
    'jest --bail --findRelatedTests',
    // <% } %>
  ],
  // <% } %>
  // <% if (cssTarget && stylelint) { %>
  '<%= cssTarget %>': ['stylelint<% if (scss) { %> --syntax=scss<% } %>'],
  // <% } %>
};
<commit_msg>fix: lint staged config newline<commit_after>/* eslint-disable @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
/// <% if (typescript) { %><% if (module) { -%>
import fs from 'fs';
// <% } else { %>const fs = require('fs');<% } %>

const lintTSConfig = 'tsconfig.lint.json';

const generateTSConfig = (stagedFilenames) => {
  const tsconfig = JSON.parse(fs.readFileSync('tsconfig.json', 'utf8'));
  tsconfig.include = stagedFilenames;
  fs.writeFileSync(lintTSConfig, JSON.stringify(tsconfig));
  return 'tsc --noEmit --project tsconfig.lint.json';
};

const deleteTSConfig = (stagedFilenames) => {
  // eslint-disable-next-line no-param-reassign
  stagedFilenames.length = 0;
  if (fs.existsSync(lintTSConfig)) {
    fs.unlinkSync(lintTSConfig);
  }
  return '';
};
// <% } %>

/// <% if (module) { %>
export default {
  // <% } else { %>module.exports = {<% } %>
  // <% if (prettier) { %>
  '*': ['prettier --check'],
  // <% } %>
  // <% if (jsTarget) { %>
  '<%= jsTarget %>': [
    // <% if (eslint) { %>
    'eslint',
    // <% } %>
    // <% if (typescript) { %>
    generateTSConfig,
    deleteTSConfig,
    // <% } %>
    // <% if (jest) { %>
    'jest --bail --findRelatedTests',
    // <% } %>
  ],
  // <% } %>
  // <% if (cssTarget && stylelint) { %>
  '<%= cssTarget %>': ['stylelint<% if (scss) { %> --syntax=scss<% } %>'],
  // <% } %>
};
<|endoftext|>


<commit_before>// ==UserScript==
// @name        douban4btbbt
// @grant       GM_xmlhttpRequest
// @description douban score for btbbt.cc movie
// @include     /^http://(www.)*btbbt.cc/thread-.*$/
// @downloadURL https://raw.githubusercontent.com/goorockey/greasemonkey-scripts/master/douban4btbbt.user.js
// @updateURL   https://raw.githubusercontent.com/goorockey/greasemonkey-scripts/master/douban4btbbt.user.js
// @version     1.0.1
// author       kelvingu616@gmail.com
// github       github.com/goorockey
// ==/UserScript==

var DOUBAN_SEARCH_URL = 'https://api.douban.com/v2/movie/search?count=10&q=';
var DOUBAN_MOVIE_URL = 'http://movie.douban.com/subject/';

var getDoubanScore = function (movie_name, callback) {
  GM_xmlhttpRequest({
    method: 'GET',
    headers: { 'Accept': 'application/json' },
    url: DOUBAN_SEARCH_URL + movie_name,
    onerror: function(err) {
      console.log(err);
    },
    onload: function (res) {
      if (res.status !== 200) {
        console.log('Failed to fetch douban api.');
        return;
      }
      try {
        var data = JSON.parse(res.responseText);
        if (!data || !data.subjects) {
          return callback();
        }

        return callback(data.subjects);
      } catch (e) {
        console.log(e);
      }
    },
  });
};

var insertDataToNode = function(douban_data, targetNode) {
  if (!douban_data || !targetNode) {
    return;
  }

  var score = douban_data.rating.average;
  var link = DOUBAN_MOVIE_URL + douban_data.id;

  var a = document.createElement('a');
  a.appendChild(document.createTextNode(' (豆瓣评分: ' + score + ')'));
  a.href = link;
  a.style.color = 'red';
  a.style.textDecoration = 'underline';

  targetNode.appendChild(a);
};

var insertDoubanScore = function(movie_name, parseDoubanData, targetNode) {
  if (!movie_name) {
    console.log('No movie name get.')
    return;
  }

  if (!targetNode) {
    console.log('No target node to insert data.');
    return;
  }

  getDoubanScore(movie_name, function(data) {
    if (!data) {
      console.log('Failed to fetch douban score data.');
      return;
    }

    var douban_data = parseDoubanData(data);
    if (!douban_data) {
      console.log('Failed to parse douban data.');
      return;
    }

    return insertDataToNode(douban_data, targetNode);
  });
};

//////////////////////////////////////////////

var getMovieName = function () {
    var title = document.querySelector('#nav td.center span:last-child a').innerHTML;
    var re = /\[([^\]]*)\]/g; // 格式: [电影名/电影名2/...]
    while (1) {
      var m = re.exec(title);
      if (!m) {
        break;
      }

      if (m[1].indexOf('BT') < 0 || m[1].indexOf('下载') < 0) {
        return m[1].split('/')[0];
      }
    }
}

var movie_name = getMovieName();

var parseDoubanData = function (data) {
    if (!data) {
        return;
    }

    for (var i = 0; i < data.length; i++) {
        if (data[i].title == movie_name) {
            return data[i];
        }
    }
};

insertDoubanScore(movie_name,
                  parseDoubanData,
                  document.getElementsByClassName('post')[0].children[0]);
<commit_msg>upgrade douban4btbbt<commit_after>// ==UserScript==
// @name        douban4btbbt
// @grant       GM_xmlhttpRequest
// @description douban score for btbbt.cc movie
// @include     /^http://(www.)*btbbt.cc/thread-.*$/
// @include     /^http://(www.)*btbbt.la/thread-.*$/
// @downloadURL https://raw.githubusercontent.com/goorockey/greasemonkey-scripts/master/douban4btbbt.user.js
// @updateURL   https://raw.githubusercontent.com/goorockey/greasemonkey-scripts/master/douban4btbbt.user.js
// @version     1.0.2
// author       kelvingu616@gmail.com
// github       github.com/goorockey
// ==/UserScript==

var DOUBAN_SEARCH_URL = 'https://api.douban.com/v2/movie/search?count=10&q=';
var DOUBAN_MOVIE_URL = 'http://movie.douban.com/subject/';

var getDoubanScore = function (movie_name, callback) {
  GM_xmlhttpRequest({
    method: 'GET',
    headers: { 'Accept': 'application/json' },
    url: DOUBAN_SEARCH_URL + movie_name,
    onerror: function(err) {
      console.log(err);
    },
    onload: function (res) {
      if (res.status !== 200) {
        console.log('Failed to fetch douban api.');
        return;
      }
      try {
        var data = JSON.parse(res.responseText);
        if (!data || !data.subjects) {
          return callback();
        }

        return callback(data.subjects);
      } catch (e) {
        console.log(e);
      }
    },
  });
};

var insertDataToNode = function(douban_data, targetNode) {
  if (!douban_data || !targetNode) {
    return;
  }

  var score = douban_data.rating.average;
  var link = DOUBAN_MOVIE_URL + douban_data.id;

  var a = document.createElement('a');
  a.appendChild(document.createTextNode(' (豆瓣评分: ' + score + ')'));
  a.href = link;
  a.style.color = 'red';
  a.style.textDecoration = 'underline';

  targetNode.appendChild(a);
};

var insertDoubanScore = function(movie_name, parseDoubanData, targetNode) {
  if (!movie_name) {
    console.log('No movie name get.')
    return;
  }

  if (!targetNode) {
    console.log('No target node to insert data.');
    return;
  }

  getDoubanScore(movie_name, function(data) {
    if (!data) {
      console.log('Failed to fetch douban score data.');
      return;
    }

    var douban_data = parseDoubanData(data);
    if (!douban_data) {
      console.log('Failed to parse douban data.');
      return;
    }

    return insertDataToNode(douban_data, targetNode);
  });
};

//////////////////////////////////////////////

var getMovieName = function () {
    var title = document.querySelector('#nav td.center span:last-child a').innerHTML;
    var re = /\[([^\]]*)\]/g; // 格式: [电影名/电影名2/...]
    while (1) {
      var m = re.exec(title);
      if (!m) {
        break;
      }

      if (m[1].indexOf('BT') < 0 || m[1].indexOf('下载') < 0) {
        return m[1].split('/')[0];
      }
    }
}

var movie_name = getMovieName();

var parseDoubanData = function (data) {
    if (!data) {
        return;
    }

    for (var i = 0; i < data.length; i++) {
        if (data[i].title == movie_name) {
            return data[i];
        }
    }
};

insertDoubanScore(movie_name,
                  parseDoubanData,
                  document.getElementsByClassName('post')[0].children[0]);
<|endoftext|>


<commit_before>function init(){
     if (onload_func)
          onload_func();
     win = document.all?true:false;
     textContent = win?'innerText':'textContent';
}
var win = false;
var textContent = 'textContent'

onload_func = window.onload;
window.onload = init;

function sort_table(e){
     e = win?window.event:e;
     var target = win?e.srcElement:e.target;
     var rev = false;
     if (target.style.backgroundColor){
          target.style.backgroundColor = '';
          rev = true;
     } else {
          var brothers = target.parentNode.childNodes;
          for (var i = 0; i < brothers.length; i++){
               brothers[i].style.backgroundColor = '';
          }
          target.style.backgroundColor = 'pink';
     }
     var table = find_parent(target, 'TABLE');
     var headers = table.rows.item(0).cells;

     var pos = target.cellIndex;
     var rows = table.rows;
     var rows_ = new Array;
     for (var i = 1; i < rows.length; i++) {
          rows_[i-1] = rows.item(i);
     }

     rows_ = rows_.sort(function(x,y){
                             var x_var = x.cells.item(pos).getAttribute('value');
                             var y_var = y.cells.item(pos).getAttribute('value');
                             if (x_var == y_var)
                                  return 0;
                             else if (x_var > y_var)
                                  return rev?1:-1;
                             else
                                  return rev?-1:1;
                        });

     var newbody = document.createElement('tbody');

     var tbody = table.getElementsByTagName('TBODY').item(0);

     for (var i = 0; i<rows_.length; i++) {
          newbody.appendChild(rows_[i]);
     }
     table.replaceChild(newbody, tbody);
}

function filter_table(select, id, all_text, pos){

     var table = document.getElementById(id);
     var options = select.options;
     var option;

     var option_list = new Array;
     var select_text_list = new Array;

     /* find selected text */
     for (var i=0; i<options.length; i++) {
          option = options.item(i)
          if (option.selected) {
               option_list.push(option);
               select_text_list.push(option.text);
          }
     }
     /* highlight selected option */
     var prev_options = select.prev_options;
     if (prev_options != undefined)
          for (var i=0; i<prev_options.length; i++) {
               prev_options[i].style.backgroundColor = '';
          }
     for (var i=0; i<option_list.length; i++) {
          option_list[i].style.backgroundColor = 'lightblue';
     }
     select.prev_options = option_list;

     var all = has_item(select_text_list,all_text)?true:false;

     var row;
     /* reset previous filter */
     if (select.filterd_rows != undefined) {
          for (var i = 0; i<select.filterd_rows.length; i++) {
               row = select.filterd_rows[i];
               row.filterd -= 1;
          }
     }
     var cell;
     var rows = table.rows;
     var filterd_rows = new Array;

     var tbody = table.getElementsByTagName('TBODY').item(0);
     var newbody = document.createElement('tbody');
     table.style.display='none'
     /* filter loop */
     for (var i = 1; i < rows.length; i++) {
          row = rows.item(i);
          cell = row.cells.item(pos);
          /* initialize filter count */
          if (row.filterd == undefined) {
               row.filterd = 0;
          }
          /* count up */
          if (!all && !has_item(select_text_list, cell[textContent])) {
               filterd_rows.push(row)
               row.filterd += 1;
          }

          /* check count and set visibility */
          if (!all && row.filterd > 0) {
               row.style.display = "none";
          } else if (row.filterd == 0) {
               row.style.display = '';
          }
     }
     table.style.display=''
     /* save filterd_rows for next select */
     select.filterd_rows = filterd_rows;
     find_parent(select, 'TABLE').rows.item(0).cells.item(select.parentNode.cellIndex).style.color = all?'':'red';

     return true;
}

function filter_this(e){
     e = win?window.event:e;
     var target = win?e.srcElement:e.target;
     var target_text = target[textContent];
     var table = find_parent(target,'TABLE');
     var head = table.tHead.rows.item(0).cells.item(target.cellIndex);
     var pos = head.getAttribute('for');
     var filter = document.getElementById('table_filter');
     var select = filter.rows.item(1).cells.item(pos).getElementsByTagName('SELECT').item(0);
     var opt;
     for (var i=0; i<select.options.length; i++) {
          opt = select.options[i];
          if (opt[textContent] == target_text) {
               opt.selected = true;
          }
     }
     select.onchange()

//      var rows = table.rows;
//      var filterd_rows = new Array;
}

function find_parent(ele, tagname){
     while (ele.tagName != tagname) {
          ele = ele.parentNode;
          if (ele == document) {
               return false;
          }
     }
     return ele;
}

function toggle_select_mode(e){
     e = win?window.event:e;
     var target = win?e.srcElement:e.target;
     if (target.className != 'clickable')
          return false;
     target = find_parent(target, 'TH');
     var pos = target.cellIndex;
     var td = target.parentNode.nextSibling.cells.item(pos);
     var select = td.getElementsByTagName('SELECT').item(0);
     select.multiple = select.size>1?false:true;
     select.size = select.size>1?1:5;
     return false;
}

function has_item(array, value){
     for (var i=0; i<array.length; i++) {
          if (array[i] == value){
               return true;
          }
     }
     return false;
}

function up_select(button,id){
     var select = document.getElementById(id);
     var options = select.options;
     var prev = options.item(0);
     var opt;
     for (var i=0; i<options.length; i++) {
          opt = options.item(i);
          if (opt.selected) {
               select.insertBefore(opt,prev);
          }
          else {
               prev = opt;
          }
     }
}

function down_select(button,id){
     var select = document.getElementById(id);
     var options = select.options;
     var prev = options.item(options.length-1);
     var opt;
     for (var i=options.length-1; i>=0; i--) {
          opt = options.item(i);
          if (opt.selected) {
               select.insertBefore(prev,opt);
          }
          else {
               prev = opt;
          }
     }
}

function toggle_fulllist(e){
     e = win?window.event:e;
     var target = win?e.srcElement:e.target;
     if (target.className != 'clickable')
          return false;
     target = find_parent(target, 'TH');
     var pos = target.cellIndex;
     var td = target.parentNode.nextSibling.cells.item(pos*2);
     var select = td.getElementsByTagName('SELECT').item(0);
     if (select.prev_size != undefined) {
          select.size = select.prev_size;
          select.prev_size = undefined;
     } else {
          select.prev_size = select.size;
          select.size = select.length;
     }
}<commit_msg>added incremental search.<commit_after>function init(){
     if (onload_func)
          onload_func();
     win = document.all?true:false;
     textContent = win?'innerText':'textContent';
}
var win = false;
var textContent = 'textContent'

onload_func = window.onload;
window.onload = init;

function sort_table(e){
     e = win?window.event:e;
     var target = win?e.srcElement:e.target;
     var rev = false;
     if (target.style.backgroundColor){
          target.style.backgroundColor = '';
          rev = true;
     } else {
          var brothers = target.parentNode.childNodes;
          for (var i = 0; i < brothers.length; i++){
               brothers[i].style.backgroundColor = '';
          }
          target.style.backgroundColor = 'pink';
     }
     var table = find_parent(target, 'TABLE');
     var headers = table.rows.item(0).cells;

     var pos = target.cellIndex;
     var rows = table.rows;
     var rows_ = new Array;
     for (var i = 1; i < rows.length; i++) {
          rows_[i-1] = rows.item(i);
     }

     rows_ = rows_.sort(function(x,y){
                             var x_var = x.cells.item(pos).getAttribute('value');
                             var y_var = y.cells.item(pos).getAttribute('value');
                             if (x_var == y_var)
                                  return 0;
                             else if (x_var > y_var)
                                  return rev?1:-1;
                             else
                                  return rev?-1:1;
                        });

     var newbody = document.createElement('tbody');

     var tbody = table.getElementsByTagName('TBODY').item(0);

     for (var i = 0; i<rows_.length; i++) {
          newbody.appendChild(rows_[i]);
     }
     table.replaceChild(newbody, tbody);
}

function filter_table(select, id, all_text, pos){

     var table = document.getElementById(id);
     var options = select.options;
     var option;

     var option_list = new Array;
     var select_text_list = new Array;

     /* find selected text */
     for (var i=0; i<options.length; i++) {
          option = options.item(i)
          if (option.selected) {
               option_list.push(option);
               select_text_list.push(option.text);
          }
     }
     /* highlight selected option */
     var prev_options = select.prev_options;
     if (prev_options != undefined)
          for (var i=0; i<prev_options.length; i++) {
               prev_options[i].style.backgroundColor = '';
          }
     for (var i=0; i<option_list.length; i++) {
          option_list[i].style.backgroundColor = 'lightblue';
     }
     select.prev_options = option_list;

     var all = has_item(select_text_list,all_text)?true:false;

     var row;
     /* reset previous filter */
     if (select.filterd_rows != undefined) {
          for (var i = 0; i<select.filterd_rows.length; i++) {
               row = select.filterd_rows[i];
               row.filterd -= 1;
          }
     }
     var cell;
     var rows = table.rows;
     var filterd_rows = new Array;

     var tbody = table.getElementsByTagName('TBODY').item(0);
     var newbody = document.createElement('tbody');
     table.style.display='none';
     /* filter loop */
     for (var i = 1; i < rows.length; i++) {
          row = rows.item(i);
          cell = row.cells.item(pos);
          /* initialize filter count */
          if (row.filterd == undefined) {
               row.filterd = 0;
          }
          /* count up */
          if (!all && !has_item(select_text_list, cell[textContent])) {
               filterd_rows.push(row)
               row.filterd += 1;
          }

          /* check count and set visibility */
          if (!all && row.filterd > 0) {
               row.style.display = "none";
          } else if (row.filterd == 0) {
               row.style.display = '';
          }
     }
     table.style.display=''
     /* save filterd_rows for next select */
     select.filterd_rows = filterd_rows;
     find_parent(select, 'TABLE').rows.item(0).cells.item(select.parentNode.cellIndex).style.color = all?'':'red';

     return true;
}

function filter_this(e){
     e = win?window.event:e;
     var target = win?e.srcElement:e.target;
     var target_text = target[textContent];
     var table = find_parent(target,'TABLE');
     var head = table.tHead.rows.item(0).cells.item(target.cellIndex);
     var pos = head.getAttribute('for');
     var filter = document.getElementById('table_filter');
     var select = filter.rows.item(1).cells.item(pos).getElementsByTagName('SELECT').item(0);
     var opt;
     for (var i=0; i<select.options.length; i++) {
          opt = select.options[i];
          if (opt[textContent] == target_text) {
               opt.selected = true;
          }
     }
     select.onchange()

//      var rows = table.rows;
//      var filterd_rows = new Array;
}

function find_parent(ele, tagname){
     while (ele.tagName != tagname) {
          ele = ele.parentNode;
          if (ele == document) {
               return false;
          }
     }
     return ele;
}

function toggle_select_mode(e){
     e = win?window.event:e;
     var target = win?e.srcElement:e.target;
     if (target.className != 'clickable')
          return false;
     target = find_parent(target, 'TH');
     var pos = target.cellIndex;
     var td = target.parentNode.nextSibling.cells.item(pos);
     var select = td.getElementsByTagName('SELECT').item(0);
     select.multiple = select.size>1?false:true;
     select.size = select.size>1?1:5;
     return false;
}

function has_item(array, value){
     for (var i=0; i<array.length; i++) {
          if (array[i] == value){
               return true;
          }
     }
     return false;
}

function up_select(button,id){
     var select = document.getElementById(id);
     var options = select.options;
     var prev = options.item(0);
     var opt;
     for (var i=0; i<options.length; i++) {
          opt = options.item(i);
          if (opt.selected) {
               select.insertBefore(opt,prev);
          }
          else {
               prev = opt;
          }
     }
}

function down_select(button,id){
     var select = document.getElementById(id);
     var options = select.options;
     var prev = options.item(options.length-1);
     var opt;
     for (var i=options.length-1; i>=0; i--) {
          opt = options.item(i);
          if (opt.selected) {
               select.insertBefore(prev,opt);
          }
          else {
               prev = opt;
          }
     }
}

function toggle_fulllist(e){
     e = win?window.event:e;
     var target = win?e.srcElement:e.target;
     if (target.className != 'clickable')
          return false;
     target = find_parent(target, 'TH');
     var pos = target.cellIndex;
     var td = target.parentNode.nextSibling.cells.item(pos*2);
     var select = td.getElementsByTagName('SELECT').item(0);
     if (select.prev_size != undefined) {
          select.size = select.prev_size;
          select.prev_size = undefined;
     } else {
          select.prev_size = select.size;
          select.size = select.length;
     }
}

var search_delay = null;
var search_key = null;

function wait_search(value){

     if (search_delay)
     {
          clearTimeout(search_delay);
     }
     search_delay = setTimeout("search_musume('"
                               +
                               value
                               +
                               "');search_delay=null",300);
}

function search_musume(value)
{
     var table = document.getElementById('musume_list');
     if (value == search_key){
          return false;
     }
     search_key = value;
     var showall=value==""?true:false

     var tbody = table.getElementsByTagName('TBODY').item(0);
     var newbody = document.createElement('tbody');
     table.style.display='none';
     var rows = table.rows;
     var matcher = new RegExp(value,'i');

     for (var i = 1; i < rows.length; i++) {
          row = rows.item(i);
          cell0 = row.cells.item(0);
          cell1 = row.cells.item(1);
          if (showall ||
              (cell0[textContent]+cell1[textContent]).match(matcher)) {
               row.style.display = '';
          }
          else {
               row.style.display = "none";
          }
     }
     table.style.display=''
     search_delay = null;
}

<|endoftext|>


<commit_before>/*
	A simple class for displaying file information and progress
	Note: This is a demonstration only and not part of SWFUpload.
	Note: Some have had problems adapting this class in IE7. It may not be suitable for your application.
*/

// Constructor
// file is a SWFUpload file object
// targetID is the HTML element id attribute that the FileProgress HTML structure will be added to.
// Instantiating a new FileProgress object with an existing file will reuse/update the existing DOM elements
function FileProgress(file, targetID) {
	this.fileProgressID = file.id;

	this.opacity = 100;
	this.height = 0;

	this.fileProgressWrapper = document.getElementById(this.fileProgressID);
	if (!this.fileProgressWrapper) {
		this.fileProgressWrapper = document.createElement("div");
		this.fileProgressWrapper.className = "progressWrapper";
		this.fileProgressWrapper.id = this.fileProgressID;

		this.fileProgressElement = document.createElement("div");
		this.fileProgressElement.className = "progressContainer";

		var progressCancel = document.createElement("a");
		progressCancel.className = "progressCancel";
		progressCancel.href = "#";
		progressCancel.style.visibility = "hidden";
		progressCancel.appendChild(document.createTextNode(" "));

		var progressText = document.createElement("div");
		progressText.className = "progressName";
		progressText.appendChild(document.createTextNode(file.name));

		var progressBarContainer = document.createElement("div");
		progressBarContainer.className = "progressBarContainer";

		var progressBar = document.createElement("div");
		progressBar.className = "progressBarInProgress";

		var progressStatus = document.createElement("div");
		progressStatus.className = "progressBarStatus";
		progressStatus.innerHTML = " ";

		this.fileProgressElement.appendChild(progressCancel);
		this.fileProgressElement.appendChild(progressText);
		this.fileProgressElement.appendChild(progressStatus);
		this.fileProgressElement.appendChild(progressBarContainer);
		progressBarContainer.appendChild(progressBar);

		this.fileProgressWrapper.appendChild(this.fileProgressElement);

		document.getElementById(targetID).appendChild(this.fileProgressWrapper);
	} else {
		this.fileProgressElement = this.fileProgressWrapper.firstChild;
		this.reset();
	}

	this.height = this.fileProgressWrapper.offsetHeight;
	this.setTimer(null);

}

FileProgress.prototype.setTimer = function (timer) {
	this.fileProgressElement["FP_TIMER"] = timer;
};
FileProgress.prototype.getTimer = function (timer) {
	return this.fileProgressElement["FP_TIMER"] || null;
};

FileProgress.prototype.reset = function () {
	this.fileProgressElement.className = "progressContainer";
	this.fileProgressElement.childNodes[2].innerHTML = " ";
	this.fileProgressElement.childNodes[2].className = "progressBarStatus";
	this.fileProgressElement.childNodes[3].className = "progressBarContainer";
	this.fileProgressElement.childNodes[3].childNodes[0].className = "progressBarInProgress";
	this.fileProgressElement.childNodes[3].childNodes[0].style.width = "0%";
	this.appear();
};

FileProgress.prototype.setProgress = function (percentage) {
	this.fileProgressElement.className = "progressContainer";
	this.fileProgressElement.childNodes[3].className = "progressBarContainer";
	this.fileProgressElement.childNodes[3].childNodes[0].style.width = percentage + "%";
	this.fileProgressElement.childNodes[3].childNodes[0].className = "progressBarInProgress";
	this.appear();
};

FileProgress.prototype.setComplete = function () {
	this.fileProgressElement.className = "progressContainer";
	this.fileProgressElement.childNodes[3].className = "progressBarContainer";
	this.fileProgressElement.childNodes[3].childNodes[0].style.width = "100%";
	this.fileProgressElement.childNodes[3].childNodes[0].className = "progressBarComplete";
	var oSelf = this;
	this.setTimer(setTimeout(function () {
		oSelf.disappear();
	}, 1500));
};

FileProgress.prototype.setError = function () {
	this.fileProgressElement.className = "progressContainer";
	this.fileProgressElement.childNodes[3].className = "progressBarContainer";
	this.fileProgressElement.childNodes[3].childNodes[0].style.width = "100%";
	this.fileProgressElement.childNodes[3].childNodes[0].className = "progressBarError";
};

FileProgress.prototype.setCancelled = function () {
	this.fileProgressElement.childNodes[3].className = "progressBarContainer";
	this.fileProgressElement.childNodes[3].childNodes[0].style.width = "100%";
	this.fileProgressElement.childNodes[3].childNodes[0].className = "progressBarCanceled";
	this.setTimer(setTimeout(function () {
		oSelf.disappear();
	}, 1500));
};

FileProgress.prototype.setStatus = function (status) {
	this.fileProgressElement.childNodes[2].innerHTML = status;
};

// Show/Hide the cancel button
FileProgress.prototype.toggleCancel = function (show, swfUploadInstance) {
	this.fileProgressElement.childNodes[0].style.visibility = show ? "visible" : "hidden";
	if (swfUploadInstance) {
		var fileID = this.fileProgressID;
		this.fileProgressElement.childNodes[0].onclick = function () {
			swfUploadInstance.cancelUpload(fileID);
			return false;
		};
	}
};

FileProgress.prototype.appear = function () {
	if (this.getTimer() !== null) {
		clearTimeout(this.getTimer());
		this.setTimer(null);
	}

	if (this.fileProgressWrapper.filters) {
		try {
			this.fileProgressWrapper.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 100;
		} catch (e) {
			// If it is not set initially, the browser will throw an error.  This will set it if it is not set yet.
			this.fileProgressWrapper.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=100)";
		}
	} else {
		this.fileProgressWrapper.style.opacity = 1;
	}

	this.fileProgressWrapper.style.height = "";

	this.height = this.fileProgressWrapper.offsetHeight;
	this.opacity = 100;
	this.fileProgressWrapper.style.display = "";

};

// Fades out and clips away the FileProgress box.
FileProgress.prototype.disappear = function () {

	var reduceOpacityBy = 15;
	var reduceHeightBy = 8;
	var rate = 30;// 15 fps

	if (this.opacity > 0) {
		this.opacity -= reduceOpacityBy;
		if (this.opacity < 0) {
			this.opacity = 0;
		}

		if (this.fileProgressWrapper.filters) {
			try {
				this.fileProgressWrapper.filters.item("DXImageTransform.Microsoft.Alpha").opacity = this.opacity;
			} catch (e) {
				// If it is not set initially, the browser will throw an error.  This will set it if it is not set yet.
				this.fileProgressWrapper.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + this.opacity + ")";
			}
		} else {
			this.fileProgressWrapper.style.opacity = this.opacity / 100;
		}
	}

	if (this.height > 0) {
		this.height -= reduceHeightBy;
		if (this.height < 0) {
			this.height = 0;
		}

		this.fileProgressWrapper.style.height = this.height + "px";
	}

	if (this.height > 0 || this.opacity > 0) {
		var oSelf = this;
		this.setTimer(setTimeout(function () {
			oSelf.disappear();
		}, rate));
	} else {
		this.fileProgressWrapper.style.display = "none";
		this.setTimer(null);
	}
};<commit_msg>Fixed upload cancel<commit_after>/*
	A simple class for displaying file information and progress
	Note: This is a demonstration only and not part of SWFUpload.
	Note: Some have had problems adapting this class in IE7. It may not be suitable for your application.
*/

// Constructor
// file is a SWFUpload file object
// targetID is the HTML element id attribute that the FileProgress HTML structure will be added to.
// Instantiating a new FileProgress object with an existing file will reuse/update the existing DOM elements
function FileProgress(file, targetID) {
	this.fileProgressID = file.id;

	this.opacity = 100;
	this.height = 0;

	this.fileProgressWrapper = document.getElementById(this.fileProgressID);
	if (!this.fileProgressWrapper) {
		this.fileProgressWrapper = document.createElement("div");
		this.fileProgressWrapper.className = "progressWrapper";
		this.fileProgressWrapper.id = this.fileProgressID;

		this.fileProgressElement = document.createElement("div");
		this.fileProgressElement.className = "progressContainer";

		var progressCancel = document.createElement("a");
		progressCancel.className = "progressCancel";
		progressCancel.href = "#";
		progressCancel.style.visibility = "hidden";
		progressCancel.appendChild(document.createTextNode(" "));

		var progressText = document.createElement("div");
		progressText.className = "progressName";
		progressText.appendChild(document.createTextNode(file.name));

		var progressBarContainer = document.createElement("div");
		progressBarContainer.className = "progressBarContainer";

		var progressBar = document.createElement("div");
		progressBar.className = "progressBarInProgress";

		var progressStatus = document.createElement("div");
		progressStatus.className = "progressBarStatus";
		progressStatus.innerHTML = " ";

		this.fileProgressElement.appendChild(progressCancel);
		this.fileProgressElement.appendChild(progressText);
		this.fileProgressElement.appendChild(progressStatus);
		this.fileProgressElement.appendChild(progressBarContainer);
		progressBarContainer.appendChild(progressBar);

		this.fileProgressWrapper.appendChild(this.fileProgressElement);

		document.getElementById(targetID).appendChild(this.fileProgressWrapper);
	} else {
		this.fileProgressElement = this.fileProgressWrapper.firstChild;
		this.reset();
	}

	this.height = this.fileProgressWrapper.offsetHeight;
	this.setTimer(null);

}

FileProgress.prototype.setTimer = function (timer) {
	this.fileProgressElement["FP_TIMER"] = timer;
};
FileProgress.prototype.getTimer = function (timer) {
	return this.fileProgressElement["FP_TIMER"] || null;
};

FileProgress.prototype.reset = function () {
	this.fileProgressElement.className = "progressContainer";
	this.fileProgressElement.childNodes[2].innerHTML = " ";
	this.fileProgressElement.childNodes[2].className = "progressBarStatus";
	this.fileProgressElement.childNodes[3].className = "progressBarContainer";
	this.fileProgressElement.childNodes[3].childNodes[0].className = "progressBarInProgress";
	this.fileProgressElement.childNodes[3].childNodes[0].style.width = "0%";
	this.appear();
};

FileProgress.prototype.setProgress = function (percentage) {
	this.fileProgressElement.className = "progressContainer";
	this.fileProgressElement.childNodes[3].className = "progressBarContainer";
	this.fileProgressElement.childNodes[3].childNodes[0].style.width = percentage + "%";
	this.fileProgressElement.childNodes[3].childNodes[0].className = "progressBarInProgress";
	this.appear();
};

FileProgress.prototype.setComplete = function () {
	this.fileProgressElement.className = "progressContainer";
	this.fileProgressElement.childNodes[3].className = "progressBarContainer";
	this.fileProgressElement.childNodes[3].childNodes[0].style.width = "100%";
	this.fileProgressElement.childNodes[3].childNodes[0].className = "progressBarComplete";
	var oSelf = this;
	this.setTimer(setTimeout(function () {
		oSelf.disappear();
	}, 1500));
};

FileProgress.prototype.setError = function () {
	this.fileProgressElement.className = "progressContainer";
	this.fileProgressElement.childNodes[3].className = "progressBarContainer";
	this.fileProgressElement.childNodes[3].childNodes[0].style.width = "100%";
	this.fileProgressElement.childNodes[3].childNodes[0].className = "progressBarError";
};

FileProgress.prototype.setCancelled = function () {
	this.fileProgressElement.childNodes[3].className = "progressBarContainer";
	this.fileProgressElement.childNodes[3].childNodes[0].style.width = "100%";
	this.fileProgressElement.childNodes[3].childNodes[0].className = "progressBarCanceled";
	var oSelf = this;
	this.setTimer(setTimeout(function () {
		oSelf.disappear();
	}, 1500));
};

FileProgress.prototype.setStatus = function (status) {
	this.fileProgressElement.childNodes[2].innerHTML = status;
};

// Show/Hide the cancel button
FileProgress.prototype.toggleCancel = function (show, swfUploadInstance) {
	this.fileProgressElement.childNodes[0].style.visibility = show ? "visible" : "hidden";
	if (swfUploadInstance) {
		var fileID = this.fileProgressID;
		this.fileProgressElement.childNodes[0].onclick = function () {
			swfUploadInstance.cancelUpload(fileID);
			return false;
		};
	}
};

FileProgress.prototype.appear = function () {
	if (this.getTimer() !== null) {
		clearTimeout(this.getTimer());
		this.setTimer(null);
	}

	if (this.fileProgressWrapper.filters) {
		try {
			this.fileProgressWrapper.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 100;
		} catch (e) {
			// If it is not set initially, the browser will throw an error.  This will set it if it is not set yet.
			this.fileProgressWrapper.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=100)";
		}
	} else {
		this.fileProgressWrapper.style.opacity = 1;
	}

	this.fileProgressWrapper.style.height = "";

	this.height = this.fileProgressWrapper.offsetHeight;
	this.opacity = 100;
	this.fileProgressWrapper.style.display = "";

};

// Fades out and clips away the FileProgress box.
FileProgress.prototype.disappear = function () {

	var reduceOpacityBy = 15;
	var reduceHeightBy = 8;
	var rate = 30;// 15 fps

	if (this.opacity > 0) {
		this.opacity -= reduceOpacityBy;
		if (this.opacity < 0) {
			this.opacity = 0;
		}

		if (this.fileProgressWrapper.filters) {
			try {
				this.fileProgressWrapper.filters.item("DXImageTransform.Microsoft.Alpha").opacity = this.opacity;
			} catch (e) {
				// If it is not set initially, the browser will throw an error.  This will set it if it is not set yet.
				this.fileProgressWrapper.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + this.opacity + ")";
			}
		} else {
			this.fileProgressWrapper.style.opacity = this.opacity / 100;
		}
	}

	if (this.height > 0) {
		this.height -= reduceHeightBy;
		if (this.height < 0) {
			this.height = 0;
		}

		this.fileProgressWrapper.style.height = this.height + "px";
	}

	if (this.height > 0 || this.opacity > 0) {
		var oSelf = this;
		this.setTimer(setTimeout(function () {
			oSelf.disappear();
		}, rate));
	} else {
		this.fileProgressWrapper.style.display = "none";
		this.setTimer(null);
	}
};<|endoftext|>


<commit_before>/*
 * react pattern engine for patternlab-node - v0.1.0 - 2016
 *
 * Geoffrey Pursell, Brian Muenzenmeyer, and the web community.
 * Licensed under the MIT license.
 *
 * Many thanks to Brad Frost and Dave Olsen for inspiration, encouragement, and advice.
 *
 */
'use strict';

const fs = require('fs');
const path = require('path');
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const Babel = require('babel-core');
const Hogan = require('hogan.js');
const beautify = require('js-beautify');
const cheerio = require('cheerio');
const _require = require;

var errorStyling = `

`;

// This holds the config from from core. The core has to call
// usePatternLabConfig() at load time for this to be populated.
let patternLabConfig = {};

let enableRuntimeCode = true;

const outputTemplate = Hogan.compile(
  fs.readFileSync(path.join(__dirname, './outputTemplate.mustache'), 'utf8')
);

let registeredComponents = {
  byPatternPartial: {},
};

function moduleCodeString(pattern) {
  return pattern.template || pattern.extendedTemplate;
}

function babelTransform(pattern) {
  let transpiledModule = Babel.transform(moduleCodeString(pattern), {
    presets: [require('babel-preset-react')],
    plugins: [require('babel-plugin-transform-es2015-modules-commonjs')],
  });

  // eval() module code in this little scope that injects our
  // custom wrap of require();
  (require => {
    /* eslint-disable no-eval */
    transpiledModule = eval(transpiledModule.code);
  })(customRequire);

  return transpiledModule;
}

function customRequire(id) {
  const registeredPattern = registeredComponents.byPatternPartial[id];

  if (registeredPattern) {
    return babelTransform(registeredPattern);
  } else {
    return _require(id);
  }
}

var engine_react = {
  engine: React,
  engineName: 'react',
  engineFileExtension: ['.jsx', '.js'],

  // hell no
  expandPartials: false,

  // regexes, stored here so they're only compiled once
  findPartialsRE: /import .* from '[^']+'/g,
  findPartialsWithStyleModifiersRE: null,
  findPartialsWithPatternParametersRE: null,
  findListItemsRE: null,
  findPartialRE: /from '([^']+)'/,

  // render it
  renderPattern(pattern, data, partials) {
    let renderedHTML = '';
    const transpiledModule = babelTransform(pattern);

    const staticMarkup = ReactDOMServer.renderToStaticMarkup(
      React.createFactory(transpiledModule)(data)
    );

    renderedHTML = outputTemplate.render({
      htmlOutput: staticMarkup,
    });

    return Promise.resolve(renderedHTML).catch(e => {
      var errorMessage = `Error rendering React pattern "${
        pattern.patternName
      }" (${pattern.relPath}): [${e.toString()}]`;
      console.log(errorMessage);
      renderedHTML = `${errorStyling}

Error rendering React pattern "${pattern.patternName}"

Message

${e.toString()}

Partial name

${pattern.patternName}

Template path

${pattern.relPath}

        `;
    });
  },

  registerPartial(pattern) {
    // add to registry
    registeredComponents.byPatternPartial[pattern.patternPartial] = pattern;
  },

  /**
   * Find regex matches within both pattern strings and pattern objects.
   *
   * @param {string|object} pattern Either a string or a pattern object.
   * @param {object} regex A JavaScript RegExp object.
   * @returns {array|null} An array if a match is found, null if not.
   */
  patternMatcher(pattern, regex) {
    var matches;
    if (typeof pattern === 'string') {
      matches = pattern.match(regex);
    } else if (
      typeof pattern === 'object' &&
      typeof pattern.template === 'string'
    ) {
      matches = pattern.template.match(regex);
    }
    return matches;
  },

  // find and return any `import X from 'template-name'` within pattern
  findPartials(pattern) {
    const self = this;
    const matches = pattern.template.match(this.findPartialsRE);
    if (!matches) {
      return [];
    }

    // Remove unregistered imports from the matches
    matches.map(m => {
      const key = self.findPartial(m);
      if (!registeredComponents.byPatternPartial[key]) {
        const i = matches.indexOf(m);
        if (i > -1) {
          matches.splice(i, 1);
        }
      }
    });

    return matches;
  },

  findPartialsWithStyleModifiers(pattern) {
    return [];
  },

  // returns any patterns that match {{> value(foo:'bar') }} or {{>
  // value:mod(foo:'bar') }} within the pattern
  findPartialsWithPatternParameters(pattern) {
    return [];
  },
  findListItems(pattern) {
    return [];
  },

  // given a pattern, and a partial string, tease out the "pattern key" and
  // return it.
  findPartial(partialString) {
    let partial = partialString.match(this.findPartialRE)[1];
    return partial;
  },

  rawTemplateCodeFormatter(unformattedString) {
    return beautify(unformattedString, { e4x: true, indent_size: 2 });
  },

  renderedCodeFormatter(unformattedString) {
    return unformattedString;
  },

  markupOnlyCodeFormatter(unformattedString, pattern) {
    // const $ = cheerio.load(unformattedString);
    // return beautify.html($('.reactPatternContainer').html(), {indent_size: 2});
    return unformattedString;
  },

  /**
   * Add custom output files to the pattern output
   * @param {object} patternlab - the global state object
   * @returns {(object|object[])} - an object or array of objects,
   * each with two properties: path, and content
   */
  addOutputFiles(paths, patternlab) {
    return [];
  },

  /**
   * Accept a Pattern Lab config object from the core and put it in
   * this module's closure scope so we can configure engine behavior.
   *
   * @param {object} config - the global config object from core
   */
  usePatternLabConfig: function(config) {
    patternLabConfig = config;

    try {
      enableRuntimeCode = patternLabConfig.engines.react.enableRuntimeCode;
    } catch (error) {
      console.log(
        'You’re missing the engines.react.enableRuntimeCode setting in your config file.'
      );
    }
  },
};

module.exports = engine_react;
<commit_msg>Fix Hogan module name. How did this ever work?<commit_after>/*
 * react pattern engine for patternlab-node - v0.1.0 - 2016
 *
 * Geoffrey Pursell, Brian Muenzenmeyer, and the web community.
 * Licensed under the MIT license.
 *
 * Many thanks to Brad Frost and Dave Olsen for inspiration, encouragement, and advice.
 *
 */
'use strict';

const fs = require('fs');
const path = require('path');
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const Babel = require('babel-core');
const Hogan = require('hogan');
const beautify = require('js-beautify');
const cheerio = require('cheerio');
const _require = require;

var errorStyling = `

`;

// This holds the config from from core. The core has to call
// usePatternLabConfig() at load time for this to be populated.
let patternLabConfig = {};

let enableRuntimeCode = true;

const outputTemplate = Hogan.compile(
  fs.readFileSync(path.join(__dirname, './outputTemplate.mustache'), 'utf8')
);

let registeredComponents = {
  byPatternPartial: {},
};

function moduleCodeString(pattern) {
  return pattern.template || pattern.extendedTemplate;
}

function babelTransform(pattern) {
  let transpiledModule = Babel.transform(moduleCodeString(pattern), {
    presets: [require('babel-preset-react')],
    plugins: [require('babel-plugin-transform-es2015-modules-commonjs')],
  });

  // eval() module code in this little scope that injects our
  // custom wrap of require();
  (require => {
    /* eslint-disable no-eval */
    transpiledModule = eval(transpiledModule.code);
  })(customRequire);

  return transpiledModule;
}

function customRequire(id) {
  const registeredPattern = registeredComponents.byPatternPartial[id];

  if (registeredPattern) {
    return babelTransform(registeredPattern);
  } else {
    return _require(id);
  }
}

var engine_react = {
  engine: React,
  engineName: 'react',
  engineFileExtension: ['.jsx', '.js'],

  // hell no
  expandPartials: false,

  // regexes, stored here so they're only compiled once
  findPartialsRE: /import .* from '[^']+'/g,
  findPartialsWithStyleModifiersRE: null,
  findPartialsWithPatternParametersRE: null,
  findListItemsRE: null,
  findPartialRE: /from '([^']+)'/,

  // render it
  renderPattern(pattern, data, partials) {
    let renderedHTML = '';
    const transpiledModule = babelTransform(pattern);

    const staticMarkup = ReactDOMServer.renderToStaticMarkup(
      React.createFactory(transpiledModule)(data)
    );

    renderedHTML = outputTemplate.render({
      htmlOutput: staticMarkup,
    });

    return Promise.resolve(renderedHTML).catch(e => {
      var errorMessage = `Error rendering React pattern "${
        pattern.patternName
      }" (${pattern.relPath}): [${e.toString()}]`;
      console.log(errorMessage);
      renderedHTML = `${errorStyling}

Error rendering React pattern "${pattern.patternName}"

Message

${e.toString()}

Partial name

${pattern.patternName}

Template path

${pattern.relPath}

        `;
    });
  },

  registerPartial(pattern) {
    // add to registry
    registeredComponents.byPatternPartial[pattern.patternPartial] = pattern;
  },

  /**
   * Find regex matches within both pattern strings and pattern objects.
   *
   * @param {string|object} pattern Either a string or a pattern object.
   * @param {object} regex A JavaScript RegExp object.
   * @returns {array|null} An array if a match is found, null if not.
   */
  patternMatcher(pattern, regex) {
    var matches;
    if (typeof pattern === 'string') {
      matches = pattern.match(regex);
    } else if (
      typeof pattern === 'object' &&
      typeof pattern.template === 'string'
    ) {
      matches = pattern.template.match(regex);
    }
    return matches;
  },

  // find and return any `import X from 'template-name'` within pattern
  findPartials(pattern) {
    const self = this;
    const matches = pattern.template.match(this.findPartialsRE);
    if (!matches) {
      return [];
    }

    // Remove unregistered imports from the matches
    matches.map(m => {
      const key = self.findPartial(m);
      if (!registeredComponents.byPatternPartial[key]) {
        const i = matches.indexOf(m);
        if (i > -1) {
          matches.splice(i, 1);
        }
      }
    });

    return matches;
  },

  findPartialsWithStyleModifiers(pattern) {
    return [];
  },

  // returns any patterns that match {{> value(foo:'bar') }} or {{>
  // value:mod(foo:'bar') }} within the pattern
  findPartialsWithPatternParameters(pattern) {
    return [];
  },
  findListItems(pattern) {
    return [];
  },

  // given a pattern, and a partial string, tease out the "pattern key" and
  // return it.
  findPartial(partialString) {
    let partial = partialString.match(this.findPartialRE)[1];
    return partial;
  },

  rawTemplateCodeFormatter(unformattedString) {
    return beautify(unformattedString, { e4x: true, indent_size: 2 });
  },

  renderedCodeFormatter(unformattedString) {
    return unformattedString;
  },

  markupOnlyCodeFormatter(unformattedString, pattern) {
    // const $ = cheerio.load(unformattedString);
    // return beautify.html($('.reactPatternContainer').html(), {indent_size: 2});
    return unformattedString;
  },

  /**
   * Add custom output files to the pattern output
   * @param {object} patternlab - the global state object
   * @returns {(object|object[])} - an object or array of objects,
   * each with two properties: path, and content
   */
  addOutputFiles(paths, patternlab) {
    return [

    ];
  },

  /**
   * Accept a Pattern Lab config object from the core and put it in
   * this module's closure scope so we can configure engine behavior.
   *
   * @param {object} config - the global config object from core
   */
  usePatternLabConfig: function(config) {
    patternLabConfig = config;

    try {
      enableRuntimeCode = patternLabConfig.engines.react.enableRuntimeCode;
    } catch (error) {
      console.log(
        'You’re missing the engines.react.enableRuntimeCode setting in your config file.'
      );
    }
  },
};

module.exports = engine_react;
<|endoftext|>


<commit_before>/**
 * Example script getting pages from "Bosons" category on English Wikipedia
 *
 * @see http://en.wikipedia.org/wiki/Category:Bosons
 * @see http://en.wikipedia.org/w/api.php?action=query&list=categorymembers&cmtitle=Category%3ABosons&cmlimit=500&format=json
 */

var bot = require('../lib/bot'),
	client = new bot({
		server: 'pl.wikipedia.org',
		path: '/w',
		debug: !true
	});

client.getPagesInCategory('Polskie_ofiary_represji_stalinowskich', function(pages) {
	console.log(JSON.stringify(pages, null, '\t'));

	pages.forEach(function(page) {
		client.getArticle(page.title, function(content) {
			if (content.indexOf('Poznan') > -1) {
				console.log('* [[wikipedia:pl:' + page.title.replace(/ /g, '_') + '|' + page.title + ']]');
			}
		});
	});
});
<commit_msg>pagesInCategory: modify the example<commit_after>/**
 * Example script getting pages from "Bosons" category on English Wikipedia
 *
 * @see http://en.wikipedia.org/wiki/Category:Bosons
 * @see http://en.wikipedia.org/w/api.php?action=query&list=categorymembers&cmtitle=Category%3ABosons&cmlimit=500&format=json
 */

var bot = require('../lib/bot'),
	client = new bot({
		server: 'en.wikipedia.org',
		path: '/w',
		debug: !true
	});

client.getPagesInCategory('Bosons', function(pages) {
	console.log(JSON.stringify(pages, null, '\t'));

	pages.forEach(function(page) {
		client.getArticle(page.title, function(content) {
			console.log(page.title + ': ' + content.substr(0, 75).replace(/\n/g, ' '));
		});
	});
});
<|endoftext|>