<commit_before>/**
 * Coverage visualization of Alignment sources.
 * @flow
 */
'use strict';

import type * as SamRead from './SamRead';
import type * as Interval from './Interval';
import type {TwoBitSource} from './TwoBitDataSource';
import type {BinSummary, BinSummaryWithLocation} from './types';

var React = require('./react-shim'),
    d3 = require('d3/minid3'),
    shallowEquals = require('shallow-equals'),
    types = require('./react-types'),
    d3utils = require('./d3utils'),
    _ = require("underscore"),
    dataCanvas = require('data-canvas'),
    {getOpInfo} = require('./pileuputils'),
    style = require('./style'),
    ContigInterval = require('./ContigInterval');

// Basic setup (TODO: make this configurable by the user)
var SHOW_MISMATCHES = true;
// Only show mismatch information when there are more than this many
// reads supporting that mismatch.
var MISMATCH_THRESHOLD = 1;

/**
 * Extract summary statistics from the read data.
 */
function extractSummaryStatistics(reads: Array<SamRead>,
                                  contig: string,
                                  referenceSource: TwoBitSource) {
  var binCounts = ({}: {[key: number]: BinSummary});

  // This is written in an imperative style (instead of with _.groupBy)
  // as an optimization.
  _.each(reads, read => {
    var interval = read.getInterval();

    var opInfo = getOpInfo(read, referenceSource);

    var start = interval.start(),
        stop = interval.stop();
    for (var j = start; j <= stop; j++) {
      if (!binCounts[j]) binCounts[j] = {count: 0, mismatches: []};
      binCounts[j].count += 1;
    }

    // Capture mismatches for future use
    _.each(opInfo.mismatches, m => {
      var binCount = binCounts[m.pos + 1];
      if (binCount) {
        binCounts[m.pos + 1].mismatches.push(m.basePair);
      } else {
        // do nothing, we don't info on this position yet
      }
    });
  });
  var maxCoverage = _.max(binCounts, bc => bc.count).count;

  var posCounts = _.map(binCounts,
                        (bc, position) => ({position: Number(position),
                                            count: bc.count,
                                            mismatches: bc.mismatches}));
  var sortedPosCounts = _.sortBy(posCounts, bin => bin.position);

  return {binCounts: sortedPosCounts, maxCoverage};
}

class CoverageTrack extends React.Component {
  constructor(props: Object) {
    super(props);
    this.state = {
      width: 0,
      height: 0,
      labelSize: {weight: 0, height: 0},  // for precise padding calculations
      reads: [],
      binCounts: [],
      maxCoverage: 0
    };
  }

  render(): any {
    return <canvas ref='canvas' />;
  }

  getScale() {
    return d3utils.getTrackScale(this.props.range, this.props.width);
  }

  componentDidMount() {
    var updateState = () => {
      var ci = new ContigInterval(this.props.range.contig, 0, Number.MAX_VALUE),
          reads = this.props.source.getAlignmentsInRange(ci),
          {binCounts, maxCoverage} = extractSummaryStatistics(reads, this.props.range.contig, this.props.referenceSource);

      this.setState({
        reads,
        binCounts,
        maxCoverage
      });
    };

    this.props.source.on('newdata', updateState);
    this.props.referenceSource.on('newdata', updateState);
  }

  componentDidUpdate(prevProps: any, prevState: any) {
    if (!shallowEquals(this.props, prevProps) ||
        !shallowEquals(this.state, prevState)) {
      this.visualizeCoverage();
    }
  }

  binsInRange(): BinSummaryWithLocation[] {
    var {start, stop} = this.props.range;
    return this.state.binCounts.filter(
        ({position}) => (position >= start - 1 && position <= stop + 1));
  }

  getContext(): CanvasRenderingContext2D {
    var canvas = (this.refs.canvas.getDOMNode() : HTMLCanvasElement);
    // The typecast through `any` is because getContext could return a WebGL context.
    var ctx = ((canvas.getContext('2d') : any) : CanvasRenderingContext2D);
    return ctx;
  }

  visualizeCoverage() {
    var canvas = (this.refs.canvas.getDOMNode() : HTMLCanvasElement),
        width = this.props.width,
        height = this.props.height,
        padding = 10,
        xScale = this.getScale();

    // Hold off until height & width are known.
    if (width === 0) return;
    d3utils.sizeCanvas(canvas, width, height);

    var yScale = d3.scale.linear()
      .domain([this.state.maxCoverage, 0])
      .range([padding, height - padding])
      .nice();
    // The nice() call on the axis will give us a new domain to work with
    // Let's get our domain max back from the nicified scale
    var axisMax = yScale.domain()[0];

    var ctx = dataCanvas.getDataContext(this.getContext());
    ctx.save();
    ctx.reset();
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

    var barWidth = xScale(1) - xScale(0),
        barPadding = barWidth * style.COVERAGE_BIN_PADDING_CONSTANT;

    // Draw coverage bins
    this.binsInRange().forEach(bin => {
      ctx.pushObject(bin);
      var barPosX = xScale(bin.position),
          barPosY = yScale(bin.count) - yScale(axisMax),
          barHeight = Math.max(0, yScale(axisMax - bin.count));
      // These are generic coverage bins
      ctx.fillStyle = style.COVERAGE_BIN_COLOR;
      ctx.fillRect(barPosX + barPadding,
                   barPosY,
                   barWidth - barPadding,
                   barHeight);

      // These are variant bars
      if (SHOW_MISMATCHES && bin.mismatches.length > 0) {
        var vBasePosY = yScale(0);  // the very bottom of the canvas
        _.chain(bin.mismatches)
          .countBy()
          .map((count, base) => ({count, base}))  // pull base into the object
          .sortBy(mc => -mc.count)  // the most common mismatch at the bottom
          .each(mc => {
            var {count, base} = mc;
            if (count <= MISMATCH_THRESHOLD) {
              // Don't show this as it doesn't have enough evidence
              return;
            }

            var misMatchObj = {position: bin.position, count, base};
            ctx.pushObject(misMatchObj);  // for debugging and click-tracking

            // Scale the height based on the percent of reads w/ this mismatch
            var vBarHeight = barHeight * (count / bin.count);
            vBasePosY -= vBarHeight;

            ctx.fillStyle = style.BASE_COLORS[base];
            ctx.fillRect(barPosX + barPadding,
                         vBasePosY,
                         barWidth - barPadding,
                         vBarHeight);

            ctx.popObject();
          });
      }

      ctx.popObject();
    });

    // Draw three ticks
    [0, Math.round(axisMax / 2), axisMax].forEach(tick => {
      // Draw a line indicating the tick
      ctx.pushObject({value: tick, type: 'tick'});
      ctx.beginPath();
      var tickPosY = yScale(tick);
      ctx.moveTo(0, tickPosY);
      ctx.lineTo(style.COVERAGE_TICK_LENGTH, tickPosY);
      ctx.stroke();
      ctx.popObject();

      var tickLabel = tick + 'X';
      ctx.pushObject({value: tick, label: tickLabel, type: 'label'});
      // Now print the coverage information
      ctx.lineWidth = 1;
      ctx.fillStyle = style.COVERAGE_FONT_COLOR;
      ctx.font = style.COVERAGE_FONT_STYLE;
      var textPosY = tickPosY + style.COVERAGE_TEXT_Y_OFFSET;
      ctx.fillText(tickLabel,
                   style.COVERAGE_TICK_LENGTH + style.COVERAGE_TEXT_PADDING,
                   textPosY);
      ctx.popObject();
      // Clean up with this tick
    });

    ctx.restore();
  }
}

CoverageTrack.propTypes = {
  range: types.GenomeRange.isRequired,
  source: React.PropTypes.object.isRequired,
  referenceSource: React.PropTypes.object.isRequired,
};
CoverageTrack.displayName = 'coverage';

module.exports = CoverageTrack;
<commit_msg>optimize mismatch count code<commit_after>/**
 * Coverage visualization of Alignment sources.
 * @flow
 */
'use strict';

import type * as SamRead from './SamRead';
import type * as Interval from './Interval';
import type {TwoBitSource} from './TwoBitDataSource';

var React = require('./react-shim'),
    d3 = require('d3/minid3'),
    shallowEquals = require('shallow-equals'),
    types = require('./react-types'),
    d3utils = require('./d3utils'),
    _ = require("underscore"),
    dataCanvas = require('data-canvas'),
    {getOpInfo} = require('./pileuputils'),
    style = require('./style'),
    ContigInterval = require('./ContigInterval');

type BinSummary = {
  count: number;
  mismatches: {[key: string]: number};
}

type BinSummaryWithLocation = {
  position: string;
  count:number;
  mismatches: {[key: string]: number};
}

// Basic setup (TODO: make this configurable by the user)
var SHOW_MISMATCHES = true;
// Only show mismatch information when there are more than this many
// reads supporting that mismatch.
var MISMATCH_THRESHOLD = 1;

/**
 * Extract summary statistics from the read data.
 */
function extractSummaryStatistics(reads: Array<SamRead>,
                                  contig: string,
                                  referenceSource: TwoBitSource) {
  var binCounts = ({}: {[key: number]: BinSummary});

  // This is written in an imperative style (instead of with _.groupBy)
  // as an optimization.
  _.each(reads, read => {
    var interval = read.getInterval();

    var opInfo = getOpInfo(read, referenceSource);

    var start = interval.start(),
        stop = interval.stop();
    for (var j = start; j <= stop; j++) {
      if (!binCounts[j]) binCounts[j] = {count: 0, mismatches: {}};
      binCounts[j].count += 1;
    }

    // Capture mismatches for future use
    _.each(opInfo.mismatches, m => {
      var binCount = binCounts[m.pos + 1];
      if (binCount) {
        var mismatches = binCount.mismatches;
        mismatches[m.basePair] = 1 + (mismatches[m.basePair] || 0);
      } else {
        // do nothing, we don't info on this position yet
      }
    });
  });
  var maxCoverage = _.max(binCounts, bc => bc.count).count;

  var posCounts = _.map(binCounts,
                        (bc, position) => ({position: Number(position),
                                            count: bc.count,
                                            mismatches: bc.mismatches}));
  var sortedPosCounts = _.sortBy(posCounts, bin => bin.position);

  return {binCounts: sortedPosCounts, maxCoverage};
}

class CoverageTrack extends React.Component {
  constructor(props: Object) {
    super(props);
    this.state = {
      width: 0,
      height: 0,
      labelSize: {weight: 0, height: 0},  // for precise padding calculations
      reads: [],
      binCounts: [],
      maxCoverage: 0
    };
  }

  render(): any {
    return <canvas ref='canvas' />;
  }

  getScale() {
    return d3utils.getTrackScale(this.props.range, this.props.width);
  }

  componentDidMount() {
    var updateState = () => {
      var ci = new ContigInterval(this.props.range.contig, 0, Number.MAX_VALUE),
          reads = this.props.source.getAlignmentsInRange(ci),
          {binCounts, maxCoverage} = extractSummaryStatistics(reads, this.props.range.contig, this.props.referenceSource);

      this.setState({
        reads,
        binCounts,
        maxCoverage
      });
    };

    this.props.source.on('newdata', updateState);
    this.props.referenceSource.on('newdata', updateState);
  }

  componentDidUpdate(prevProps: any, prevState: any) {
    if (!shallowEquals(this.props, prevProps) ||
        !shallowEquals(this.state, prevState)) {
      this.visualizeCoverage();
    }
  }

  binsInRange(): BinSummaryWithLocation[] {
    var {start, stop} = this.props.range;
    return this.state.binCounts.filter(
        ({position}) => (position >= start - 1 && position <= stop + 1));
  }

  getContext(): CanvasRenderingContext2D {
    var canvas = (this.refs.canvas.getDOMNode() : HTMLCanvasElement);
    // The typecast through `any` is because getContext could return a WebGL context.
    var ctx = ((canvas.getContext('2d') : any) : CanvasRenderingContext2D);
    return ctx;
  }

  visualizeCoverage() {
    var canvas = (this.refs.canvas.getDOMNode() : HTMLCanvasElement),
        width = this.props.width,
        height = this.props.height,
        padding = 10,
        xScale = this.getScale();

    // Hold off until height & width are known.
    if (width === 0) return;
    d3utils.sizeCanvas(canvas, width, height);

    var yScale = d3.scale.linear()
      .domain([this.state.maxCoverage, 0])
      .range([padding, height - padding])
      .nice();
    // The nice() call on the axis will give us a new domain to work with
    // Let's get our domain max back from the nicified scale
    var axisMax = yScale.domain()[0];

    var ctx = dataCanvas.getDataContext(this.getContext());
    ctx.save();
    ctx.reset();
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);

    var barWidth = xScale(1) - xScale(0),
        barPadding = barWidth * style.COVERAGE_BIN_PADDING_CONSTANT;

    // Draw coverage bins
    this.binsInRange().forEach(bin => {
      ctx.pushObject(bin);
      var barPosX = xScale(bin.position),
          barPosY = yScale(bin.count) - yScale(axisMax),
          barHeight = Math.max(0, yScale(axisMax - bin.count));
      // These are generic coverage bins
      ctx.fillStyle = style.COVERAGE_BIN_COLOR;
      ctx.fillRect(barPosX + barPadding,
                   barPosY,
                   barWidth - barPadding,
                   barHeight);

      // These are variant bars
      if (SHOW_MISMATCHES && !_.isEmpty(bin.mismatches)) {
        var vBasePosY = yScale(0);  // the very bottom of the canvas
        _.chain(bin.mismatches)
          .map((count, base) => ({count, base}))  // pull base into the object
          .sortBy(mc => -mc.count)  // the most common mismatch at the bottom
          .each(mc => {
            var {count, base} = mc;
            if (count <= MISMATCH_THRESHOLD) {
              // Don't show this as it doesn't have enough evidence
              return;
            }

            var misMatchObj = {position: bin.position, count, base};
            ctx.pushObject(misMatchObj);  // for debugging and click-tracking

            // Scale the height based on the percent of reads w/ this mismatch
            var vBarHeight = barHeight * (count / bin.count);
            vBasePosY -= vBarHeight;

            ctx.fillStyle = style.BASE_COLORS[base];
            ctx.fillRect(barPosX + barPadding,
                         vBasePosY,
                         barWidth - barPadding,
                         vBarHeight);

            ctx.popObject();
          });
      }

      ctx.popObject();
    });

    // Draw three ticks
    [0, Math.round(axisMax / 2), axisMax].forEach(tick => {
      // Draw a line indicating the tick
      ctx.pushObject({value: tick, type: 'tick'});
      ctx.beginPath();
      var tickPosY = yScale(tick);
      ctx.moveTo(0, tickPosY);
      ctx.lineTo(style.COVERAGE_TICK_LENGTH, tickPosY);
      ctx.stroke();
      ctx.popObject();

      var tickLabel = tick + 'X';
      ctx.pushObject({value: tick, label: tickLabel, type: 'label'});
      // Now print the coverage information
      ctx.lineWidth = 1;
      ctx.fillStyle = style.COVERAGE_FONT_COLOR;
      ctx.font = style.COVERAGE_FONT_STYLE;
      var textPosY = tickPosY + style.COVERAGE_TEXT_Y_OFFSET;
      ctx.fillText(tickLabel,
                   style.COVERAGE_TICK_LENGTH + style.COVERAGE_TEXT_PADDING,
                   textPosY);
      ctx.popObject();
      // Clean up with this tick
    });

    ctx.restore();
  }
}

CoverageTrack.propTypes = {
  range: types.GenomeRange.isRequired,
  source: React.PropTypes.object.isRequired,
  referenceSource: React.PropTypes.object.isRequired,
};
CoverageTrack.displayName = 'coverage';

module.exports = CoverageTrack;
<|endoftext|>


<commit_before>var rootAPIURL = "https://api.psd401.net/v1";
var screwIE=Math.floor(Math.random()*100001);

var populateRSSFeeds = {
    init: function() {
        populateRSSFeeds.loadWebsiteRSSData();
        populateRSSFeeds.loadTechblogRSSData();
        populateRSSFeeds.loadSupRSSData();
        console.log("Should be done loading RSS");
    },
    loadWebsiteRSSData: function() {
        //console.log($("#websiteRSS-container").rss("https://psd401.net/index.php?format=feed&type=rss"));
        $("#websiteRSS-container").rss("https://psd401.net/index.php?format=feed&type=rss",
            {
                limit: 2,
                layoutTemplate: "{entries}",
                entryTemplate: '
{title} {shortBody}

{date}
',
                effect: 'slideFastSynced',
                dateFormat: 'MMMM Do, YYYY',
                error: function(){
                    console.log("There was an error");
                },
            }
        );
    },

    loadTechblogRSSData: function() {
        //console.log($("#techblogRSS-container").rss("http://techblog.psd401.net/?feed=rss2"));
        $("#techblogRSS-container").rss("http://techblog.psd401.net/?feed=rss2",{
                limit: 2,
                layoutTemplate: "{entries}",
                entryTemplate: '
{title} {shortBody}

{date}
',
                effect: 'slideFastSynced',
                dateFormat: 'MMMM Do, YYYY',
                error: function(){
                    console.log("There was an error");
                }
            }
        );
    },

    loadSupRSSData: function() {
         //console.log($("#supRSS-container").rss("https://script.google.com/a/macros/krishagel.com/s/AKfycbxIvJLmswNQRctRQ3UrQqwad_1sOx_SIH5VrSugxXYU-ot2hsc/exec?action=timeline&q=psdsup"));
        $("#supRSS-container").rss("https://script.google.com/a/macros/krishagel.com/s/AKfycbxIvJLmswNQRctRQ3UrQqwad_1sOx_SIH5VrSugxXYU-ot2hsc/exec?action=timeline&q=psdsup",
            {
                limit: 2,
                layoutTemplate: "{entries}",
                entryTemplate: '
{title}

{date}
',
                dateFormat: 'MMMM Do, YYYY',
                effect: 'slideFastSynced',
                error: function(){
                    console.log("There was an error");
                }
            }
        );
    }
}

$(document).ready(function(){
	//populateRSSFeeds.init();
    $('[data-toggle="tooltip"]').tooltip();

    setTimeout(function(){
        $('.psd-login-submit').tooltip('show');
        $('.psd-login-forgot').tooltip('show');
    }, 1200);

    setTimeout(function(){
        $('.psd-login-submit').tooltip('hide');
        $('.psd-login-forgot').tooltip('hide');
    }, 7000);

    $('.psd-login-submit').click(function(){
      stripEmail();
      $('form[name=login]').submit();
    });

    $(".psd-login-form-input").keypress(function(event){
        if(event.which == 13){
            $(".psd-login-form-input-password").focus();
        }
    });

    $(".psd-login-form-input-password").keypress(function(event) {
        if (event.which == 13) {
            event.preventDefault();
            stripEmail();
            $("form[name=login]").submit();
        }
    });

    if($(".logout-success").length > 0) {
        var timer = 10;
	var redirect = location.search.split('url=')[1] ? location.search.split('url=')[1] : '/login?service=http%3A%2F%2Fmy.psd401.net';
        $(".logout-success").attr("href", redirect);
        setInterval(function(){
            $(".logout-success").html("Login " + timer);
            if(timer == 0){
                window.location.href = redirect;
            }
            timer --;
        }, 1000);
    }

    capsLock.observe(function (status) {
        if(status){
            $(".psd-login-form-input-password").tooltip("show");
        } else {
            $(".psd-login-form-input-password").tooltip("hide");
        }
    });
});

function stripEmail(){
    var username = $('.psd-login-form-input').val();
    username = username.toLowerCase().replace(/ /g, '');
    if (username.indexOf("@") != -1) {
        username = username.substring(0, username.indexOf('@'));
    }
    $('.psd-login-form-input').val(username);
}
<commit_msg>Update cas.js<commit_after>var rootAPIURL = "https://api.psd401.net/v1";
var screwIE=Math.floor(Math.random()*100001);

var populateRSSFeeds = {
    init: function() {
        populateRSSFeeds.loadWebsiteRSSData();
        populateRSSFeeds.loadTechblogRSSData();
        populateRSSFeeds.loadSupRSSData();
        console.log("Should be done loading RSS");
    },
    loadWebsiteRSSData: function() {
        //console.log($("#websiteRSS-container").rss("https://psd401.net/index.php?format=feed&type=rss"));
        $("#websiteRSS-container").rss("https://psd401.net/index.php?format=feed&type=rss",
            {
                limit: 2,
                layoutTemplate: "{entries}",
                entryTemplate: '
{title} {shortBody}

{date}
',
                effect: 'slideFastSynced',
                dateFormat: 'MMMM Do, YYYY',
                error: function(){
                    console.log("There was an error");
                },
            }
        );
    },

    loadTechblogRSSData: function() {
        //console.log($("#techblogRSS-container").rss("http://techblog.psd401.net/?feed=rss2"));
        $("#techblogRSS-container").rss("http://techblog.psd401.net/?feed=rss2",{
                limit: 2,
                layoutTemplate: "{entries}",
                entryTemplate: '
{title} {shortBody}

{date}
',
                effect: 'slideFastSynced',
                dateFormat: 'MMMM Do, YYYY',
                error: function(){
                    console.log("There was an error");
                }
            }
        );
    },

    loadSupRSSData: function() {
         //console.log($("#supRSS-container").rss("https://script.google.com/a/macros/krishagel.com/s/AKfycbxIvJLmswNQRctRQ3UrQqwad_1sOx_SIH5VrSugxXYU-ot2hsc/exec?action=timeline&q=psdsup"));
        $("#supRSS-container").rss("https://script.google.com/a/macros/krishagel.com/s/AKfycbxIvJLmswNQRctRQ3UrQqwad_1sOx_SIH5VrSugxXYU-ot2hsc/exec?action=timeline&q=psdsup",
            {
                limit: 2,
                layoutTemplate: "{entries}",
                entryTemplate: '
{title}

{date}
',
                dateFormat: 'MMMM Do, YYYY',
                effect: 'slideFastSynced',
                error: function(){
                    console.log("There was an error");
                }
            }
        );
    }
}

$(document).ready(function(){
	//populateRSSFeeds.init();
    $('[data-toggle="tooltip"]').tooltip();

    setTimeout(function(){
        $('.psd-login-submit').tooltip('show');
        $('.psd-login-forgot').tooltip('show');
    }, 1200);

    setTimeout(function(){
        $('.psd-login-submit').tooltip('hide');
        $('.psd-login-forgot').tooltip('hide');
    }, 7000);

    $('.psd-login-submit').click(function(){
      stripEmail();
      $('form[name=login]').submit();
    });

    $(".psd-login-form-input").keypress(function(event){
        if(event.which == 13){
            $(".psd-login-form-input-password").focus();
        }
    });

    $(".psd-login-form-input-password").keypress(function(event) {
        if (event.which == 13) {
            event.preventDefault();
            stripEmail();
            $("form[name=login]").submit();
        }
    });

    if($(".logout-success").length > 0) {
        var timer = 10;
	var redirect = location.search.split('url=')[1] ? location.search.split('url=')[1] : '/login?service=http%3A%2F%2Fmy.psd401.net';
        $(".logout-success").attr("href", decodeURIComponent(redirect));
        setInterval(function(){
            $(".logout-success").html("Login " + timer);
            if(timer == 0){
                window.location.href = redirect;
            }
            timer --;
        }, 1000);
    }

    capsLock.observe(function (status) {
        if(status){
            $(".psd-login-form-input-password").tooltip("show");
        } else {
            $(".psd-login-form-input-password").tooltip("hide");
        }
    });
});

function stripEmail(){
    var username = $('.psd-login-form-input').val();
    username = username.toLowerCase().replace(/ /g, '');
    if (username.indexOf("@") != -1) {
        username = username.substring(0, username.indexOf('@'));
    }
    $('.psd-login-form-input').val(username);
}
<|endoftext|>


<commit_before>String.prototype.startsWith = function(str) {
	return (this.match("^" + str) == str)
}

var stats = {};
var fieldShortNames;
var fieldLongNames;
var store = {};
var ns;
var webapp = "";
var RDF_TYPE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
var ONTOLOGY_ROOT = "http://www.w3.org/2002/07/owl#Thing";
var contextsToColour = []; // TODO populate from server.

var argString = window.location.href.split('?')[1];
var args = []; // URL arguments
if (argString != undefined) {
	args = parse(argString);
}

function getProviderName(sstring) {
	if (contextsToColour[sstring] === undefined)
		return getLocalName(sstring);
	else
		return contextsToColour[sstring];
}

function getLocalName(uri) {
	if (uri.indexOf('#') > 0) {
		return uri.substring(uri.lastIndexOf('#') + 1);
	} else if (uri.indexOf('/') > 0) {
		return uri.substring(uri.lastIndexOf('/') + 1);
	} else
		return uri;
}

function stripVersion(uri) {
	return uri.replace(/[0-9]+\.[0-9]+\.[0-9]+\//, "");
}

function encode(uri) {
	return uri.replace(/[^a-zA-Z0-9]+/g, "_");
}

function parse(qs, sep, eq) {
	sep = sep || "&";
	eq = eq || "=";
	for ( var obj = {}, i = 0, pieces = qs.split(sep), l = pieces.length, tuple; i < l; i++) {
		tuple = pieces[i].split(eq);
		if (tuple.length > 0) {
			obj[unescape(tuple.shift())] = unescape(tuple.join(eq));
		}
	}
	return obj;
};

function unescape(s) {
	return decodeURIComponent(s.replace(/\+/g, ' '));
};

YUI({
	gallery : 'gallery-2011.01.03-18-30'
})
		.use(
				'gallery-yui3treeview',
				'history',
				'tabview',
				'node',
				'datatable-scroll',
				'event',
				'datasource',
				'querystring-parse-simple',
				'autocomplete',
				'autocomplete-filters',
				'autocomplete-highlighters',
				function(Y) {
					var dataSource = new Y.DataSource.Get({
						source : webapp + "ajax/"
					});

					// A value (URI or Literal) to be rendered. URI optionally
					// has anchortext
					function renderValue(value, anchor) {

						if (value.startsWith("urn:uuid:")) {
							var label = value.substring(9);
							if (anchor != undefined && anchor != null)
								label = anchor;
							if (typeof (pubby) != "undefined" && pubby != null) {
								return '' + label + '';
							} else {
								var kbname = Y.one("#dataset").get('value');
								return '' + label + '';
							}
						} else if (anchor != undefined){
							return '' + anchor + '';
						} else {
							return '' + value + '';
						}
					}

					function renderResult(result, node) {
						var li = Y.Node.create("

");

						function predSort(a, b) {
							return (fieldLongNames.indexOf(encode(a.predicate)) - fieldLongNames.indexOf(encode(b.predicate)));
						}
						result.relations.sort(predSort);

						// Group the relations by predicate
						var map = [];
						var labels = [];
						var types = [];

						if (result.hasOwnProperty("relations")) {
							for (qid in result.relations) {
								if (map[result.relations[qid].predicate] == null) {
									map[result.relations[qid].predicate] = [ result.relations[qid] ];
								} else {
									map[result.relations[qid].predicate].push(result.relations[qid]);
								}
								if (result.relations[qid].hasOwnProperty("label") && result.relations[qid].label != null) {
									labels[result.relations[qid].object] = result.relations[qid].label;
								}
								if (result.relations[qid].predicate == RDF_TYPE) {
									types.push(stripVersion(result.relations[qid].object));
								}
							}
						}
						function typeSort(a, b) {
							return stats.classes[b].count - stats.classes[a].count;
						}
						types.sort(typeSort);

						if (result.hasOwnProperty("label") && result.label != null) {
							li.append('' + renderValue(result.label) + '');
						}
						li.append("
");
						for (type in types) {
							li.append(' ' + getLocalName(types[type]) + ' /');
						}
						li.append('' + renderValue(result.subject) + '');

						var table = Y.Node
								.create('
<col class=\"predicate-col\"/><col class=\"value-col\"/>Property	Value
');
						var i = 0;
						for ( var pred in map) {
							// alert(Object.getOwnPropertyNames(result.relations[qid]));
							if (pred == RDF_TYPE)
								continue;
							var row = "";
							if (i++ % 2 == 0) {
								row = row + '
';
							} else {
								row = row + '
';
							}
							row = row + "" + getLocalName(pred) + "	" + "";
							for (var qid in map[pred]) {
								if (labels[map[pred][qid].object] != null) {
									row = row + ''
											+ renderValue(map[pred][qid].object, labels[map[pred][qid].object]) + '
';
								} else {
									row = row + '' + renderValue(map[pred][qid].object) + '
';
								}
							}
							row = row + '
';
							table.append(row);
						}

						li.append(table);
						node.append(li);

					}

					function executeUnifiedSearch(e) {
						var query = Y.one("#ac-input").get('value');
						loadResults(query);
					}

					function executeSearchByClass(e) {
						var query = '';
						var params = Y.all(".class-property").each(function(thisNode) {
							if (thisNode.get('value') != '') {
								query = query + ' ';
								query = query + ns + thisNode.get('name') + ':' + thisNode.get('value');
							}
						});
						loadResults(query);
					}

					function executeSearchByID(e) {
						loadResults("subject=urn:uuid:" + Y.one('#id-text').get('value'));
					}

					function loadResults(query) {
						Y.one("#result-loader").show();

						dataSource.sendRequest({
							request : 'query?index=' + Y.one("#dataset").get('value') + '&query=' + query + '&pageSize=' + Y.one("#numresults").get('value')
									+ '&deref=' + Y.one("#dereference").get('checked'),
							callback : {

								success : function(e) {
									Y.one("#result-loader").hide();
									Y.one("#resultContainer").show();
									Y.one("#result-stats").setContent("Rendering...");

									var ol = Y.Node.create("

");

									var results = e.response.results[0].resultItems;
									var markers = [];
									for ( var result in results) {
										renderResult(results[result], ol);
									}

									Y.one("#results").setContent("").append(ol);
									Y.one("#result-stats").setContent(
											"Found " + e.response.results[0].numResults + " results in " + e.response.results[0].time + " ms.");

								},
								failure : function(e) {
									alert(e.error.message);
								}
							}
						});

					}
					;

					function changeProperties(clazz) {
						Y.one('#class-properties').setContent('');
						var frag = '
';
						for ( var i in stats.classes[clazz].properties) {
							frag = frag + '
' + getLocalName(stats.classes[clazz].properties[i])
									+ '	<input class="class-property yui3-hastooltip" type="text" title="' + /* TODO */'" name="'
									+ getLocalName(stats.classes[clazz].properties[i]) + '"/>
';
						}
						frag = frag + '
';
						Y.one('#class-properties').append(Y.Node.create(frag)).show();
					}

					function initDataSet() {

						fieldShortNames = [ "any" ];
						fieldLongNames = [ "any" ];
						Y.one("#results").setContent("");
						Y.one("#result-stats").setContent("");
						Y.one("#class-select").setContent("");
						Y.one("#resultContainer").hide();

						Y.one("#statistics-tree").setContent("");
						Y.one("#statistics-loader").show();

						dataSource.sendRequest({
							request : 'indexStatistics?index=' + Y.one("#dataset").get('value'),
							callback : {
								success : function(e) {
									stats = e.response.results[0];

									Y.one("#class-loader").hide();
									Y.one("#class-message").setContent("");

									Y.one("#statistics-loader").hide();

									var autocompletefields = [ 'OR' ];
									for ( var key in stats.fields) {
										fieldShortNames.push(key);
										fieldLongNames.push(stats.fields[key]);
										// fill up the autocomplete
										// suggestion box
										autocompletefields.push(key);
									}

									Y.one('#ac-input').plug(Y.Plugin.AutoComplete, {
										resultFilters : 'phraseMatch',
										queryDelimiter : ' ',
										tabSelect : 'true',
										typeAhead : 'true',
										source : autocompletefields
									});

									// Display class selection dropdown
									if (stats.classes.lenght > 0) {
										var frag = '<select>';
										var keys = [];
										for ( var key in stats.classes) {
											keys.push(key);
										}
										keys.sort();
										for (clazz in keys) {
											frag = frag + "<option value='" + keys[clazz] + "'>" + getLocalName(keys[clazz]) + "</option>";
										}

										frag = frag + '</select>';
										var fragNode = Y.Node.create(frag);
										Y.one('#class-select').append("I'm looking for a").append(fragNode).append("where");
										changeProperties(keys[0]);
										fragNode.on('change', function(e) {
											changeProperties(e.target.get('value'));
										});
									}

									var tree = [];
									function addClass(clazz) {
										var sub = [];
										var count = 0;
										if (stats.classes[clazz] != undefined) {
											count = stats.classes[clazz].count;
											for (uri in stats.classes[clazz].children) {
												var child = stats.classes[clazz].children[uri];
												if (stats.classes[child] != undefined)
													sub.push(addClass(child));
											}
										} else {
											// Class appears in the
											// ontology but no instances
											return [];
										}
										if (sub.length > 0) {
											return {
												label : getLocalName(clazz) + " (" + count + ") ",
												type : "TreeView",
												children : sub
											};
										} else {
											return {
												label : getLocalName(clazz) + " (" + count + ") "
											};
										}
									}

									// Render TreeView
									Y.one('#statistics-tree').setContent('

');
									tree.push(addClass(ONTOLOGY_ROOT));
									var treeview = new Y.TreeView({
										srcNode : '#statisticsTreeList',
										contentBox : null,
										type : "TreeView",
										children : tree
									});

									treeview.render();
									// Expand the top level of the tree
									var statisticsTree = Y.one('#statistics-tree').removeClass('yui3-tree-collapsed');

									// Render statistics box
									/*
									 * Y.one("#statistics").setContent(''); var
									 * sidestats = [];a for (clazz in keys) {
									 * sidestats.push({"Entity" :
									 * getLocalName(keys[clazz]), "Count":
									 * stats.classes[keys[clazz]].count}); } var
									 * dtScrollingY = new Y.DataTable.Base({
									 * columnset : [{ key : "Entity", label :
									 * "Entity" }, { key : "Count", label :
									 * "Count" }], recordset : sidestats,
									 * summary : "Y axis scrolling table" });
									 * dtScrollingY.plug(Y.Plugin.DataTableScroll, {
									 * height : "400px" });
									 * dtScrollingY.render("#statistics");
									 */

									// On load, check if there were any
									// query parameters
									if (args['subject'] != undefined && args['subject'] != null) {
										var queryNode = Y.one("#id-text");
										queryNode.set('value', args['subject']);
										executeSearchByID();
									}

								},
								failure : function(e) {
									alert("Failed to preload fields : " + e.error.message);
								}
							}
						});
					}

					function initDataSetList(selectedDataSetName) {
						dataSource.sendRequest({
							request : 'dataSetList?',
							callback : {
								success : function(e) {
									dataSetNames = e.response.results;

									for ( var i in dataSetNames) {
										var dataSetName = dataSetNames[i];
										Y.one("#dataset").append('<option value=\"' + dataSetName + '\">' + dataSetName + '</option>');
										if ((selectedDataSetName == null && i == 0) || dataSetName == selectedDataSetName) {
											Y.one("#dataset").set('value', dataSetName);
											// Load the fields for the dataset
											initDataSet();
										}
									}
									Y.one('#dataset').on('change', initDataSet);
								},
								failure : function(e) {
									alert("Failed to load data set list : " + e.error.message);
								}
							}
						});
					}

					// Everything below is run automatically upon loading the
					// page

					initDataSetList(args['kb']);

					// Add handlers

					// On submit, retrieve and display search results
					Y.one('#search-by-class').on('submit', executeSearchByClass);

					// On submit, retrieve and display search results
					Y.one('#search-by-id').on('submit', executeSearchByID);

					// On submit, retrieve and display search results
					Y.one('#unifiedsearchform').on('submit', executeUnifiedSearch);

					// Toggle ontology search box
					Y.one('#toggleonto').on('click', function(e) {
						var node = Y.one('#onto-hider');
						var link = Y.one('#toggleonto');
						if (link.getContent() == "hide") {
							node.hide();
							link.setContent("show");
						} else {
							node.show();
							link.setContent("hide");
						}
					});

					var tabview = new Y.TabView({
						srcNode : '#resultContainer'
					});
					tabview.render();

				});
<commit_msg>Fixed clickability of BNodes and results titles<commit_after>String.prototype.startsWith = function(str) {
	return (this.match("^" + str) == str)
}

var stats = {};
var fieldShortNames;
var fieldLongNames;
var store = {};
var ns;
var webapp = "";
var RDF_TYPE = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";
var ONTOLOGY_ROOT = "http://www.w3.org/2002/07/owl#Thing";
var contextsToColour = []; // TODO populate from server.

var argString = window.location.href.split('?')[1];
var args = []; // URL arguments
if (argString != undefined) {
	args = parse(argString);
}

function getProviderName(sstring) {
	if (contextsToColour[sstring] === undefined)
		return getLocalName(sstring);
	else
		return contextsToColour[sstring];
}

function getLocalName(uri) {
	if (uri.indexOf('#') > 0) {
		return uri.substring(uri.lastIndexOf('#') + 1);
	} else if (uri.indexOf('/') > 0) {
		return uri.substring(uri.lastIndexOf('/') + 1);
	} else
		return uri;
}

function stripVersion(uri) {
	return uri.replace(/[0-9]+\.[0-9]+\.[0-9]+\//, "");
}

function encode(uri) {
	return uri.replace(/[^a-zA-Z0-9]+/g, "_");
}

function parse(qs, sep, eq) {
	sep = sep || "&";
	eq = eq || "=";
	for ( var obj = {}, i = 0, pieces = qs.split(sep), l = pieces.length, tuple; i < l; i++) {
		tuple = pieces[i].split(eq);
		if (tuple.length > 0) {
			obj[unescape(tuple.shift())] = unescape(tuple.join(eq));
		}
	}
	return obj;
};

function unescape(s) {
	return decodeURIComponent(s.replace(/\+/g, ' '));
};

YUI({
	gallery : 'gallery-2011.01.03-18-30'
})
		.use(
				'gallery-yui3treeview',
				'history',
				'tabview',
				'node',
				'datatable-scroll',
				'event',
				'datasource',
				'querystring-parse-simple',
				'autocomplete',
				'autocomplete-filters',
				'autocomplete-highlighters',
				function(Y) {
					var dataSource = new Y.DataSource.Get({
						source : webapp + "ajax/"
					});

					// A value (URI or Literal) to be rendered. URI optionally
					// has anchortext
					function renderValue(ref, value) {

						if (ref.startsWith("urn:uuid:")) {
							ref = ref.substring(9);
							if (value == undefined) {
								value = ref;
							}
							var kbname = Y.one("#dataset").get('value');
							return '' + value + '';
						}

						if (value == undefined) {
							value = ref;
						}
						if (ref.startsWith("http:")) {
							return '' + value + '';
						} else {
							return value;
						}
					}

					function renderResult(result, node) {
						var li = Y.Node.create("

");

						function predSort(a, b) {
							return (fieldLongNames.indexOf(encode(a.predicate)) - fieldLongNames.indexOf(encode(b.predicate)));
						}
						result.relations.sort(predSort);

						// Group the relations by predicate
						var map = [];
						var labels = [];
						var types = [];

						if (result.hasOwnProperty("relations")) {
							for (qid in result.relations) {
								if (map[result.relations[qid].predicate] == null) {
									map[result.relations[qid].predicate] = [ result.relations[qid] ];
								} else {
									map[result.relations[qid].predicate].push(result.relations[qid]);
								}
								if (result.relations[qid].hasOwnProperty("label") && result.relations[qid].label != null) {
									labels[result.relations[qid].object] = result.relations[qid].label;
								}
								if (result.relations[qid].predicate == RDF_TYPE) {
									types.push(stripVersion(result.relations[qid].object));
								}
							}
						}
						function typeSort(a, b) {
							return stats.classes[b].count - stats.classes[a].count;
						}
						types.sort(typeSort);

						if (result.hasOwnProperty("label") && result.label != null) {
							li.append('' + result.label + '');
						}
						li.append("
");
						for (type in types) {
							li.append(' ' + getLocalName(types[type]) + ' /');
						}
						li.append('' + renderValue(result.subject) + '');

						var table = Y.Node
								.create('
<col class=\"predicate-col\"/><col class=\"value-col\"/>Property	Value
');
						var i = 0;
						for ( var pred in map) {
							// alert(Object.getOwnPropertyNames(result.relations[qid]));
							if (pred == RDF_TYPE)
								continue;
							var row = "";
							if (i++ % 2 == 0) {
								row = row + '
';
							} else {
								row = row + '
';
							}
							row = row + "" + getLocalName(pred) + "	" + "";
							for (var qid in map[pred]) {
								if (labels[map[pred][qid].object] != null) {
									row = row + ''
											+ renderValue(map[pred][qid].object, labels[map[pred][qid].object]) + '
';
								} else {
									row = row + '' + renderValue(map[pred][qid].object) + '
';
								}
							}
							row = row + '
';
							table.append(row);
						}

						li.append(table);
						node.append(li);

					}

					function executeUnifiedSearch(e) {
						var query = Y.one("#ac-input").get('value');
						loadResults(query);
					}

					function executeSearchByClass(e) {
						var query = '';
						var params = Y.all(".class-property").each(function(thisNode) {
							if (thisNode.get('value') != '') {
								query = query + ' ';
								query = query + ns + thisNode.get('name') + ':' + thisNode.get('value');
							}
						});
						loadResults(query);
					}

					function executeSearchByID(e) {
						loadResults("subject=urn:uuid:" + Y.one('#id-text').get('value'));
					}

					function loadResults(query) {
						Y.one("#result-loader").show();

						dataSource.sendRequest({
							request : 'query?index=' + Y.one("#dataset").get('value') + '&query=' + query + '&pageSize=' + Y.one("#numresults").get('value')
									+ '&deref=' + Y.one("#dereference").get('checked'),
							callback : {

								success : function(e) {
									Y.one("#result-loader").hide();
									Y.one("#resultContainer").show();
									Y.one("#result-stats").setContent("Rendering...");

									var ol = Y.Node.create("

");

									var results = e.response.results[0].resultItems;
									var markers = [];
									for ( var result in results) {
										renderResult(results[result], ol);
									}

									Y.one("#results").setContent("").append(ol);
									Y.one("#result-stats").setContent(
											"Found " + e.response.results[0].numResults + " results in " + e.response.results[0].time + " ms.");

								},
								failure : function(e) {
									alert(e.error.message);
								}
							}
						});

					}
					;

					function changeProperties(clazz) {
						Y.one('#class-properties').setContent('');
						var frag = '
';
						for ( var i in stats.classes[clazz].properties) {
							frag = frag + '
' + getLocalName(stats.classes[clazz].properties[i])
									+ '	<input class="class-property yui3-hastooltip" type="text" title="' + /* TODO */'" name="'
									+ getLocalName(stats.classes[clazz].properties[i]) + '"/>
';
						}
						frag = frag + '
';
						Y.one('#class-properties').append(Y.Node.create(frag)).show();
					}

					function initDataSet() {

						fieldShortNames = [ "any" ];
						fieldLongNames = [ "any" ];
						Y.one("#results").setContent("");
						Y.one("#result-stats").setContent("");
						Y.one("#class-select").setContent("");
						Y.one("#resultContainer").hide();

						Y.one("#statistics-tree").setContent("");
						Y.one("#statistics-loader").show();

						dataSource.sendRequest({
							request : 'indexStatistics?index=' + Y.one("#dataset").get('value'),
							callback : {
								success : function(e) {
									stats = e.response.results[0];

									Y.one("#class-loader").hide();
									Y.one("#class-message").setContent("");

									Y.one("#statistics-loader").hide();

									var autocompletefields = [ 'OR' ];
									for ( var key in stats.fields) {
										fieldShortNames.push(key);
										fieldLongNames.push(stats.fields[key]);
										// fill up the autocomplete
										// suggestion box
										autocompletefields.push(key);
									}

									Y.one('#ac-input').plug(Y.Plugin.AutoComplete, {
										resultFilters : 'phraseMatch',
										queryDelimiter : ' ',
										tabSelect : 'true',
										typeAhead : 'true',
										source : autocompletefields
									});

									// Display class selection dropdown
									if (stats.classes.lenght > 0) {
										var frag = '<select>';
										var keys = [];
										for ( var key in stats.classes) {
											keys.push(key);
										}
										keys.sort();
										for (clazz in keys) {
											frag = frag + "<option value='" + keys[clazz] + "'>" + getLocalName(keys[clazz]) + "</option>";
										}

										frag = frag + '</select>';
										var fragNode = Y.Node.create(frag);
										Y.one('#class-select').append("I'm looking for a").append(fragNode).append("where");
										changeProperties(keys[0]);
										fragNode.on('change', function(e) {
											changeProperties(e.target.get('value'));
										});
									}

									var tree = [];
									function addClass(clazz) {
										var sub = [];
										var count = 0;
										if (stats.classes[clazz] != undefined) {
											count = stats.classes[clazz].count;
											for (uri in stats.classes[clazz].children) {
												var child = stats.classes[clazz].children[uri];
												if (stats.classes[child] != undefined)
													sub.push(addClass(child));
											}
										} else {
											// Class appears in the
											// ontology but no instances
											return [];
										}
										if (sub.length > 0) {
											return {
												label : getLocalName(clazz) + " (" + count + ") ",
												type : "TreeView",
												children : sub
											};
										} else {
											return {
												label : getLocalName(clazz) + " (" + count + ") "
											};
										}
									}

									// Render TreeView
									Y.one('#statistics-tree').setContent('

');
									tree.push(addClass(ONTOLOGY_ROOT));
									var treeview = new Y.TreeView({
										srcNode : '#statisticsTreeList',
										contentBox : null,
										type : "TreeView",
										children : tree
									});

									treeview.render();
									// Expand the top level of the tree
									var statisticsTree = Y.one('#statistics-tree').removeClass('yui3-tree-collapsed');

									// Render statistics box
									/*
									 * Y.one("#statistics").setContent(''); var
									 * sidestats = [];a for (clazz in keys) {
									 * sidestats.push({"Entity" :
									 * getLocalName(keys[clazz]), "Count":
									 * stats.classes[keys[clazz]].count}); } var
									 * dtScrollingY = new Y.DataTable.Base({
									 * columnset : [{ key : "Entity", label :
									 * "Entity" }, { key : "Count", label :
									 * "Count" }], recordset : sidestats,
									 * summary : "Y axis scrolling table" });
									 * dtScrollingY.plug(Y.Plugin.DataTableScroll, {
									 * height : "400px" });
									 * dtScrollingY.render("#statistics");
									 */

									// On load, check if there were any
									// query parameters
									if (args['subject'] != undefined && args['subject'] != null) {
										var queryNode = Y.one("#id-text");
										queryNode.set('value', args['subject']);
										executeSearchByID();
									}

								},
								failure : function(e) {
									alert("Failed to preload fields : " + e.error.message);
								}
							}
						});
					}

					function initDataSetList(selectedDataSetName) {
						dataSource.sendRequest({
							request : 'dataSetList?',
							callback : {
								success : function(e) {
									dataSetNames = e.response.results;

									for ( var i in dataSetNames) {
										var dataSetName = dataSetNames[i];
										Y.one("#dataset").append('<option value=\"' + dataSetName + '\">' + dataSetName + '</option>');
										if ((selectedDataSetName == null && i == 0) || dataSetName == selectedDataSetName) {
											Y.one("#dataset").set('value', dataSetName);
											// Load the fields for the dataset
											initDataSet();
										}
									}
									Y.one('#dataset').on('change', initDataSet);
								},
								failure : function(e) {
									alert("Failed to load data set list : " + e.error.message);
								}
							}
						});
					}

					// Everything below is run automatically upon loading the
					// page

					initDataSetList(args['kb']);

					// Add handlers

					// On submit, retrieve and display search results
					Y.one('#search-by-class').on('submit', executeSearchByClass);

					// On submit, retrieve and display search results
					Y.one('#search-by-id').on('submit', executeSearchByID);

					// On submit, retrieve and display search results
					Y.one('#unifiedsearchform').on('submit', executeUnifiedSearch);

					// Toggle ontology search box
					Y.one('#toggleonto').on('click', function(e) {
						var node = Y.one('#onto-hider');
						var link = Y.one('#toggleonto');
						if (link.getContent() == "hide") {
							node.hide();
							link.setContent("show");
						} else {
							node.show();
							link.setContent("hide");
						}
					});

					var tabview = new Y.TabView({
						srcNode : '#resultContainer'
					});
					tabview.render();

				});
<|endoftext|>


<commit_before>(function(angular, undefined) {'use strict';
  angular
    .module('schemaForm')
    .config(materialDecoratorConfig)
    .directive('sfmExternalOptions', sfmExternalOptionsDirective)
    .filter('sfCamelKey', sfCamelKeyFilter);

  materialDecoratorConfig.$inject = [
    'schemaFormProvider', 'schemaFormDecoratorsProvider', 'sfBuilderProvider', 'sfPathProvider', '$injector'
  ];

  function materialDecoratorConfig(
      schemaFormProvider, decoratorsProvider, sfBuilderProvider, sfPathProvider, $injector) {
    var base = 'decorators/material/';

    var simpleTransclusion = sfBuilderProvider.builders.simpleTransclusion;
    var ngModelOptions     = sfBuilderProvider.builders.ngModelOptions;
    var ngModel            = sfBuilderProvider.builders.ngModel;
    var sfField            = sfBuilderProvider.builders.sfField;
    var condition          = sfBuilderProvider.builders.condition;
    var array              = sfBuilderProvider.builders.array;

    var sfLayout           = sfLayout;
    var sfMessagesNode     = sfMessagesNodeHandler();
    var sfMessages         = sfMessagesBuilder;
    var sfOptions          = sfOptionsBuilder;
    var mdAutocomplete     = mdAutocompleteBuilder;
    var mdSwitch           = mdSwitchBuilder;
    var mdDatepicker       = mdDatepickerBuilder;
    var mdTabs             = mdTabsBuilder;
    var textarea           = textareaBuilder;

    var core = [ sfField, ngModel, ngModelOptions, condition, sfLayout ];
    var defaults = core.concat(sfMessages);
    var arrays = core.concat(array);

    schemaFormProvider.defaults.string.unshift(dateDefault);

    decoratorsProvider.defineDecorator('materialDecorator', {
      actions: { template: base + 'actions.html', builder: [ sfField, simpleTransclusion, condition ] },
      array: { template: base + 'array.html', builder: arrays },
      autocomplete: { template: base + 'autocomplete.html', builder: defaults.concat(mdAutocomplete) },
      boolean: { template: base + 'checkbox.html', builder: defaults },
      button: { template: base + 'submit.html', builder: defaults },
      checkbox: { template: base + 'checkbox.html', builder: defaults },
      checkboxes: { template: base + 'checkboxes.html', builder: arrays },
      date: { template: base + 'date.html', builder: defaults.concat(mdDatepicker) },
      'default': { template: base + 'default.html', builder: defaults },
      fieldset: { template: base + 'fieldset.html', builder: [ sfField, simpleTransclusion, condition ] },
      help: { template: base + 'help.html', builder: defaults },
      number: { template: base + 'default.html', builder: defaults },
      password: { template: base + 'default.html', builder: defaults },
      radios: { template: base + 'radios.html', builder: defaults },
      'radios-inline': { template: base + 'radios-inline.html', builder: defaults },
      radiobuttons: { template: base + 'radio-buttons.html', builder: defaults },
      section: { template: base + 'section.html', builder: [ sfField, simpleTransclusion, condition, sfLayout ] },
      select: { template: base + 'select.html', builder: defaults.concat(sfOptions) },
      submit: { template: base + 'submit.html', builder: defaults },
      tabs: { template: base + 'tabs.html', builder: [ sfField, mdTabs, condition ] },
      tabarray: { template: base + 'tabarray.html', builder: arrays },
      textarea: { template: base + 'textarea.html', builder: defaults.concat(textarea) },
      switch: { template: base + 'switch.html', builder: defaults.concat(mdSwitch) }
    });

    function sfLayout(args) {
      var layoutDiv = args.fieldFrag.querySelector('[sf-layout]');

      if (args.form.grid) {
        Object.getOwnPropertyNames(args.form.grid).forEach(function(property, idx, array) {
          layoutDiv.setAttribute(property, args.form.grid[property]);
        });
      };
    };

    function sfMessagesNodeHandler() {
      var html = '

';
      var div = document.createElement('div');
      div.innerHTML = html;
      return div.firstChild;
    };

    function sfMessagesBuilder(args) {
      var messagesDiv = args.fieldFrag.querySelector('[sf-messages]');
      if (messagesDiv && sfMessagesNode) {
        var child = sfMessagesNode.cloneNode();
        messagesDiv.appendChild(child);
      }
    };

    function textareaBuilder(args) {
      var textareaFrag = args.fieldFrag.querySelector('textarea');
      var maxLength = args.form.maxlength || false;
      if (textareaFrag && maxLength) {
        textareaFrag.setAttribute('md-maxlength', maxLength);
      };
    };

    function mdAutocompleteBuilder(args) {
      var mdAutocompleteFrag = args.fieldFrag.querySelector('md-autocomplete');
      var minLength = args.form.minLength || 1;
      var maxLength = args.form.maxLength || false;
      var title = args.form.title || args.form.placeholder || args.form.key.slice(-1)[0];

      if (mdAutocompleteFrag) {
        if (args.form.onChange) {
          mdAutocompleteFrag.setAttribute('md-selected-item-change', 'args.form.onChange()');
          mdAutocompleteFrag.setAttribute('md-search-text-change', 'args.form.onChange(searchText)');
        };

        // mdAutocompleteFrag.setAttribute('md-items', 'item in $filter(''autocomplete'')(searchText);');
        mdAutocompleteFrag.setAttribute('md-min-length', minLength);
        if (maxLength) {
          mdAutocompleteFrag.setAttribute('md-max-length', maxLength);
        };

        if (title) {
          mdAutocompleteFrag.setAttribute('md-floating-label', title);
        };
      }
    };

    function mdSwitchBuilder(args) {
      var mdSwitchFrag = args.fieldFrag.querySelector('md-switch');
      if (args.form.schema.titleMap) {
        mdSwitchFrag.setAttribute('ng-true-value', args.form.schema.titleMap.true);
        mdSwitchFrag.setAttribute('ng-false-value', args.form.schema.titleMap.false);
      }
    };

    function sfOptionsBuilder(args) {
      var mdSelectFrag = args.fieldFrag.querySelector('md-select');
      var enumTitleMap = [];
      var i;
      var mdSelectFrag;

      args.form.selectOptions = [];
      args.form.getOptions = getOptionsHandler;

      if (args.form.schema.links && (typeof args.form.schema.links) === 'object') {
        var link;
        var related = /({)([^}]*)(})/gm;
        var source = /{{([^}]*)}}/gm;
        var matched;

        for (i = 0; i < args.form.schema.links.length; i++) {
          link = args.form.schema.links[i];
          if (link.rel === 'options') {
            // TODO enable filter to allow processing results
            // args.form.optionSource = link.href.replace(related, '$1$1 model.$2 | _externalOptionUri $3$3');
            args.form.optionSource = link.href.replace(related, '$1$1 model.$2 $3$3');
          };
        };

        mdSelectFrag.setAttribute('sfm-external-options', args.form.optionSource);
      }
      else {
        args.form.selectOptions = sfOptionsProcessor(args.form);
      };
    };

    function mdDatepickerBuilder(args) {
      var mdDatepickerFrag = args.fieldFrag.querySelector('md-datepicker');
      if (mdDatepickerFrag) {
        if (args.form.onChange) {
          mdDatepickerFrag.setAttribute('ng-change', 'args.form.onChange(searchText)');
        }
        // mdDatepickerFrag.setAttribute('md-items', 'item in $filter(''autocomplete'')(searchText);');
        var minDate = args.form.minimum || false;
        var maxDate = args.form.maximum || false;
        if (minDate) {
          mdDatepickerFrag.setAttribute('md-max-date', minDate);
        }
        if (maxDate) {
          mdDatepickerFrag.setAttribute('md-max-date', maxDate);
        }
      }
    };

    function mdTabsBuilder(args) {
      if (args.form.tabs && args.form.tabs.length > 0) {
        var mdTabsFrag = args.fieldFrag.querySelector('md-tabs');

        args.form.tabs.forEach(function(tab, index) {
          var mdTab = document.createElement('md-tab');
          mdTab.setAttribute('label', '{{' + args.path + '.tabs[' + index + '].title}}');
          var mdTabBody = document.createElement('md-tab-body');
          var childFrag = args.build(tab.items, args.path + '.tabs[' + index + '].items', args.state);
          mdTabBody.appendChild(childFrag);
          mdTab.appendChild(mdTabBody);
          mdTabsFrag.appendChild(mdTab);
        });
      }
    };

    /**
     * Material Datepicker
     */
    function dateDefault(name, schema, options) {
      if (schema.type === 'string' && (schema.format === 'date' || schema.format === 'date-time')) {
        var f = schemaFormProvider.stdFormObj(name, schema, options);
        f.key  = options.path;
        f.type = 'date';
        options.lookup[sfPathProvider.stringify(options.path)] = f;
        return f;
      }
    };
  };

  function getOptionsHandler(form, evalExpr) {
    if (form.optionData) {
      return evalExpr(form.optionData);
    };

    if (form.selectOptions) {
      return form.selectOptions;
    };

    return [];
  };

  function sfOptionsProcessor(data) {
    var enumTitleMap = [];

    if (data.titleMap) {
      return data.titleMap;
    }
    else if (data.enum && data.enum.length) {
      for (i = 0; i < data.enum.length; i++) {
        if (data.enum[i] && data.enum[i].length) {
          enumTitleMap.push({ name: data.enum[i], value: data.enum[i] });
        };
      };
    };

    return enumTitleMap;
  };

  sfmExternalOptionsDirective.$inject = [ '$http' ];

  function sfmExternalOptionsDirective($http) {
    var directive = {
      link: link,
      restrict: 'A'
    };

    return directive;

    function link(scope, element, attrs) {
      attrs.$observe('sfmExternalOptions', function(dataURI) {
        $http.get(dataURI)
          .then(function(response) {
            scope.form.selectOptions = sfOptionsProcessor(response.data);
          });
      });
    };
  };

  /**
   * sfCamelKey Filter
   */
  function sfCamelKeyFilter() {
    return function(formKey) {
      if (!formKey) { return ''; };
      var part, i, key;
      key = formKey.slice();
      for (i = 0; i < key.length; i++) {
        part = key[i].toLowerCase().split('');
        if (i && part.length) { part[0] = part[0].toUpperCase(); };
        key[i] = part.join('');
      };
      return key.join('');
    };
  };

})(angular, undefined);
/*
  TODO add default filter for autocomplete which allows form.optionFilter or 'autocompleteFilter' to override
  Something along the following lines...
  if ($injector.has('autocompleteFilter')) {
    result = $filter('autocomplete')(input);
  }
  else
  if ($injector.has(args.form.optionFilter + 'Filter')) {
    result = $filter(args.form.optionFilter)(input);
  }
  else {
    if (args.form.optionFilter) {
      mdAutocomplete.setAttribute('md-items',
        'item in evalExpr("this[\""+form.optionFilter+"\"](\""+searchText+"\")")');
    }
  }

  .filter('autocompleteMovieTest', function() {
    function autocompleteMovieTestFilter(array, input){
      var current = input;
      // You could also call multiple filters here using:
      // current = $filter('filterName')(input)
      if(typeof current === 'string') {
        current = current.replace(' ','-').toLowerCase();
      }
      current = (!current) ? '_undefined' : current;
      return current;
    }

    return externalOptionUriFilter;
  })
*/
<commit_msg>Correct assignment of the md-min-date attribute<commit_after>(function(angular, undefined) {'use strict';
  angular
    .module('schemaForm')
    .config(materialDecoratorConfig)
    .directive('sfmExternalOptions', sfmExternalOptionsDirective)
    .filter('sfCamelKey', sfCamelKeyFilter);

  materialDecoratorConfig.$inject = [
    'schemaFormProvider', 'schemaFormDecoratorsProvider', 'sfBuilderProvider', 'sfPathProvider', '$injector'
  ];

  function materialDecoratorConfig(
      schemaFormProvider, decoratorsProvider, sfBuilderProvider, sfPathProvider, $injector) {
    var base = 'decorators/material/';

    var simpleTransclusion = sfBuilderProvider.builders.simpleTransclusion;
    var ngModelOptions     = sfBuilderProvider.builders.ngModelOptions;
    var ngModel            = sfBuilderProvider.builders.ngModel;
    var sfField            = sfBuilderProvider.builders.sfField;
    var condition          = sfBuilderProvider.builders.condition;
    var array              = sfBuilderProvider.builders.array;

    var sfLayout           = sfLayout;
    var sfMessagesNode     = sfMessagesNodeHandler();
    var sfMessages         = sfMessagesBuilder;
    var sfOptions          = sfOptionsBuilder;
    var mdAutocomplete     = mdAutocompleteBuilder;
    var mdSwitch           = mdSwitchBuilder;
    var mdDatepicker       = mdDatepickerBuilder;
    var mdTabs             = mdTabsBuilder;
    var textarea           = textareaBuilder;

    var core = [ sfField, ngModel, ngModelOptions, condition, sfLayout ];
    var defaults = core.concat(sfMessages);
    var arrays = core.concat(array);

    schemaFormProvider.defaults.string.unshift(dateDefault);

    decoratorsProvider.defineDecorator('materialDecorator', {
      actions: { template: base + 'actions.html', builder: [ sfField, simpleTransclusion, condition ] },
      array: { template: base + 'array.html', builder: arrays },
      autocomplete: { template: base + 'autocomplete.html', builder: defaults.concat(mdAutocomplete) },
      boolean: { template: base + 'checkbox.html', builder: defaults },
      button: { template: base + 'submit.html', builder: defaults },
      checkbox: { template: base + 'checkbox.html', builder: defaults },
      checkboxes: { template: base + 'checkboxes.html', builder: arrays },
      date: { template: base + 'date.html', builder: defaults.concat(mdDatepicker) },
      'default': { template: base + 'default.html', builder: defaults },
      fieldset: { template: base + 'fieldset.html', builder: [ sfField, simpleTransclusion, condition ] },
      help: { template: base + 'help.html', builder: defaults },
      number: { template: base + 'default.html', builder: defaults },
      password: { template: base + 'default.html', builder: defaults },
      radios: { template: base + 'radios.html', builder: defaults },
      'radios-inline': { template: base + 'radios-inline.html', builder: defaults },
      radiobuttons: { template: base + 'radio-buttons.html', builder: defaults },
      section: { template: base + 'section.html', builder: [ sfField, simpleTransclusion, condition, sfLayout ] },
      select: { template: base + 'select.html', builder: defaults.concat(sfOptions) },
      submit: { template: base + 'submit.html', builder: defaults },
      tabs: { template: base + 'tabs.html', builder: [ sfField, mdTabs, condition ] },
      tabarray: { template: base + 'tabarray.html', builder: arrays },
      textarea: { template: base + 'textarea.html', builder: defaults.concat(textarea) },
      switch: { template: base + 'switch.html', builder: defaults.concat(mdSwitch) }
    });

    function sfLayout(args) {
      var layoutDiv = args.fieldFrag.querySelector('[sf-layout]');

      if (args.form.grid) {
        Object.getOwnPropertyNames(args.form.grid).forEach(function(property, idx, array) {
          layoutDiv.setAttribute(property, args.form.grid[property]);
        });
      };
    };

    function sfMessagesNodeHandler() {
      var html = '

';
      var div = document.createElement('div');
      div.innerHTML = html;
      return div.firstChild;
    };

    function sfMessagesBuilder(args) {
      var messagesDiv = args.fieldFrag.querySelector('[sf-messages]');
      if (messagesDiv && sfMessagesNode) {
        var child = sfMessagesNode.cloneNode();
        messagesDiv.appendChild(child);
      }
    };

    function textareaBuilder(args) {
      var textareaFrag = args.fieldFrag.querySelector('textarea');
      var maxLength = args.form.maxlength || false;
      if (textareaFrag && maxLength) {
        textareaFrag.setAttribute('md-maxlength', maxLength);
      };
    };

    function mdAutocompleteBuilder(args) {
      var mdAutocompleteFrag = args.fieldFrag.querySelector('md-autocomplete');
      var minLength = args.form.minLength || 1;
      var maxLength = args.form.maxLength || false;
      var title = args.form.title || args.form.placeholder || args.form.key.slice(-1)[0];

      if (mdAutocompleteFrag) {
        if (args.form.onChange) {
          mdAutocompleteFrag.setAttribute('md-selected-item-change', 'args.form.onChange()');
          mdAutocompleteFrag.setAttribute('md-search-text-change', 'args.form.onChange(searchText)');
        };

        // mdAutocompleteFrag.setAttribute('md-items', 'item in $filter(''autocomplete'')(searchText);');
        mdAutocompleteFrag.setAttribute('md-min-length', minLength);
        if (maxLength) {
          mdAutocompleteFrag.setAttribute('md-max-length', maxLength);
        };

        if (title) {
          mdAutocompleteFrag.setAttribute('md-floating-label', title);
        };
      }
    };

    function mdSwitchBuilder(args) {
      var mdSwitchFrag = args.fieldFrag.querySelector('md-switch');
      if (args.form.schema.titleMap) {
        mdSwitchFrag.setAttribute('ng-true-value', args.form.schema.titleMap.true);
        mdSwitchFrag.setAttribute('ng-false-value', args.form.schema.titleMap.false);
      }
    };

    function sfOptionsBuilder(args) {
      var mdSelectFrag = args.fieldFrag.querySelector('md-select');
      var enumTitleMap = [];
      var i;
      var mdSelectFrag;

      args.form.selectOptions = [];
      args.form.getOptions = getOptionsHandler;

      if (args.form.schema.links && (typeof args.form.schema.links) === 'object') {
        var link;
        var related = /({)([^}]*)(})/gm;
        var source = /{{([^}]*)}}/gm;
        var matched;

        for (i = 0; i < args.form.schema.links.length; i++) {
          link = args.form.schema.links[i];
          if (link.rel === 'options') {
            // TODO enable filter to allow processing results
            // args.form.optionSource = link.href.replace(related, '$1$1 model.$2 | _externalOptionUri $3$3');
            args.form.optionSource = link.href.replace(related, '$1$1 model.$2 $3$3');
          };
        };

        mdSelectFrag.setAttribute('sfm-external-options', args.form.optionSource);
      }
      else {
        args.form.selectOptions = sfOptionsProcessor(args.form);
      };
    };

    function mdDatepickerBuilder(args) {
      var mdDatepickerFrag = args.fieldFrag.querySelector('md-datepicker');
      if (mdDatepickerFrag) {
        if (args.form.onChange) {
          mdDatepickerFrag.setAttribute('ng-change', 'args.form.onChange(searchText)');
        }
        // mdDatepickerFrag.setAttribute('md-items', 'item in $filter(''autocomplete'')(searchText);');
        var minDate = args.form.minimum || false;
        var maxDate = args.form.maximum || false;
        if (minDate) {
          mdDatepickerFrag.setAttribute('md-min-date', minDate);
        }
        if (maxDate) {
          mdDatepickerFrag.setAttribute('md-max-date', maxDate);
        }
      }
    };

    function mdTabsBuilder(args) {
      if (args.form.tabs && args.form.tabs.length > 0) {
        var mdTabsFrag = args.fieldFrag.querySelector('md-tabs');

        args.form.tabs.forEach(function(tab, index) {
          var mdTab = document.createElement('md-tab');
          mdTab.setAttribute('label', '{{' + args.path + '.tabs[' + index + '].title}}');
          var mdTabBody = document.createElement('md-tab-body');
          var childFrag = args.build(tab.items, args.path + '.tabs[' + index + '].items', args.state);
          mdTabBody.appendChild(childFrag);
          mdTab.appendChild(mdTabBody);
          mdTabsFrag.appendChild(mdTab);
        });
      }
    };

    /**
     * Material Datepicker
     */
    function dateDefault(name, schema, options) {
      if (schema.type === 'string' && (schema.format === 'date' || schema.format === 'date-time')) {
        var f = schemaFormProvider.stdFormObj(name, schema, options);
        f.key  = options.path;
        f.type = 'date';
        options.lookup[sfPathProvider.stringify(options.path)] = f;
        return f;
      }
    };
  };

  function getOptionsHandler(form, evalExpr) {
    if (form.optionData) {
      return evalExpr(form.optionData);
    };

    if (form.selectOptions) {
      return form.selectOptions;
    };

    return [];
  };

  function sfOptionsProcessor(data) {
    var enumTitleMap = [];

    if (data.titleMap) {
      return data.titleMap;
    }
    else if (data.enum && data.enum.length) {
      for (i = 0; i < data.enum.length; i++) {
        if (data.enum[i] && data.enum[i].length) {
          enumTitleMap.push({ name: data.enum[i], value: data.enum[i] });
        };
      };
    };

    return enumTitleMap;
  };

  sfmExternalOptionsDirective.$inject = [ '$http' ];

  function sfmExternalOptionsDirective($http) {
    var directive = {
      link: link,
      restrict: 'A'
    };

    return directive;

    function link(scope, element, attrs) {
      attrs.$observe('sfmExternalOptions', function(dataURI) {
        $http.get(dataURI)
          .then(function(response) {
            scope.form.selectOptions = sfOptionsProcessor(response.data);
          });
      });
    };
  };

  /**
   * sfCamelKey Filter
   */
  function sfCamelKeyFilter() {
    return function(formKey) {
      if (!formKey) { return ''; };
      var part, i, key;
      key = formKey.slice();
      for (i = 0; i < key.length; i++) {
        part = key[i].toLowerCase().split('');
        if (i && part.length) { part[0] = part[0].toUpperCase(); };
        key[i] = part.join('');
      };
      return key.join('');
    };
  };

})(angular, undefined);
/*
  TODO add default filter for autocomplete which allows form.optionFilter or 'autocompleteFilter' to override
  Something along the following lines...
  if ($injector.has('autocompleteFilter')) {
    result = $filter('autocomplete')(input);
  }
  else
  if ($injector.has(args.form.optionFilter + 'Filter')) {
    result = $filter(args.form.optionFilter)(input);
  }
  else {
    if (args.form.optionFilter) {
      mdAutocomplete.setAttribute('md-items',
        'item in evalExpr("this[\""+form.optionFilter+"\"](\""+searchText+"\")")');
    }
  }

  .filter('autocompleteMovieTest', function() {
    function autocompleteMovieTestFilter(array, input){
      var current = input;
      // You could also call multiple filters here using:
      // current = $filter('filterName')(input)
      if(typeof current === 'string') {
        current = current.replace(' ','-').toLowerCase();
      }
      current = (!current) ? '_undefined' : current;
      return current;
    }

    return externalOptionUriFilter;
  })
*/
<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 * @author alteredq / http://alteredqualia.com/
 */

THREE.Material = function () {

	this.id = THREE.MaterialIdCount ++;

	this.name = '';

	this.side = THREE.FrontSide;

	this.opacity = 1;
	this.transparent = false;

	this.blending = THREE.NormalBlending;

	this.blendSrc = THREE.SrcAlphaFactor;
	this.blendDst = THREE.OneMinusSrcAlphaFactor;
	this.blendEquation = THREE.AddEquation;

	this.depthTest = true;
	this.depthWrite = true;

	this.polygonOffset = false;
	this.polygonOffsetFactor = 0;
	this.polygonOffsetUnits = 0;

	this.alphaTest = 0;

	this.overdraw = false; // Boolean for fixing antialiasing gaps in CanvasRenderer

	this.visible = true;

	this.needsUpdate = true;

};

THREE.Material.prototype = {

	constructor: THREE.Material,

	addEventListener: THREE.EventDispatcher.prototype.addEventListener,
	hasEventListener: THREE.EventDispatcher.prototype.hasEventListener,
	removeEventListener: THREE.EventDispatcher.prototype.removeEventListener,
	dispatchEvent: THREE.EventDispatcher.prototype.dispatchEvent,

	setValues: function ( values ) {

		if ( values === undefined ) return;

		for ( var key in values ) {

			var newValue = values[ key ];

			if ( newValue === undefined ) {

				console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' );
				continue;

			}

			if ( key in this ) {

				var currentValue = this[ key ];

				if ( currentValue instanceof THREE.Color && newValue instanceof THREE.Color ) {

					currentValue.copy( newValue );

				} else if ( currentValue instanceof THREE.Color ) {

					currentValue.set( newValue );

				} else if ( currentValue instanceof THREE.Vector3 && newValue instanceof THREE.Vector3 ) {

					currentValue.copy( newValue );

				} else {

					this[ key ] = newValue;

				}

			}

		}

	},

	clone: function ( material ) {

		if ( material === undefined ) material = new THREE.Material();

		material.name = this.name;

		material.side = this.side;

		material.opacity = this.opacity;
		material.transparent = this.transparent;

		material.blending = this.blending;

		material.blendSrc = this.blendSrc;
		material.blendDst = this.blendDst;
		material.blendEquation = this.blendEquation;

		material.depthTest = this.depthTest;
		material.depthWrite = this.depthWrite;

		material.polygonOffset = this.polygonOffset;
		material.polygonOffsetFactor = this.polygonOffsetFactor;
		material.polygonOffsetUnits = this.polygonOffsetUnits;

		material.alphaTest = this.alphaTest;

		material.overdraw = this.overdraw;

		material.visible = this.visible;

		return material;

	},

	dispose: function () {

		this.dispatchEvent( { type: 'dispose' } );

	}

};

THREE.MaterialIdCount = 0;
<commit_msg>Material: Remove unnecessary conditional branch. From @cjshannon. Sorry, I couldn't merge cleanly nor cherry-pick.<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 * @author alteredq / http://alteredqualia.com/
 */

THREE.Material = function () {

	this.id = THREE.MaterialIdCount ++;

	this.name = '';

	this.side = THREE.FrontSide;

	this.opacity = 1;
	this.transparent = false;

	this.blending = THREE.NormalBlending;

	this.blendSrc = THREE.SrcAlphaFactor;
	this.blendDst = THREE.OneMinusSrcAlphaFactor;
	this.blendEquation = THREE.AddEquation;

	this.depthTest = true;
	this.depthWrite = true;

	this.polygonOffset = false;
	this.polygonOffsetFactor = 0;
	this.polygonOffsetUnits = 0;

	this.alphaTest = 0;

	this.overdraw = false; // Boolean for fixing antialiasing gaps in CanvasRenderer

	this.visible = true;

	this.needsUpdate = true;

};

THREE.Material.prototype = {

	constructor: THREE.Material,

	addEventListener: THREE.EventDispatcher.prototype.addEventListener,
	hasEventListener: THREE.EventDispatcher.prototype.hasEventListener,
	removeEventListener: THREE.EventDispatcher.prototype.removeEventListener,
	dispatchEvent: THREE.EventDispatcher.prototype.dispatchEvent,

	setValues: function ( values ) {

		if ( values === undefined ) return;

		for ( var key in values ) {

			var newValue = values[ key ];

			if ( newValue === undefined ) {

				console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' );
				continue;

			}

			if ( key in this ) {

				var currentValue = this[ key ];

				if ( currentValue instanceof THREE.Color ) {

					currentValue.set( newValue );

				} else if ( currentValue instanceof THREE.Vector3 && newValue instanceof THREE.Vector3 ) {

					currentValue.copy( newValue );

				} else {

					this[ key ] = newValue;

				}

			}

		}

	},

	clone: function ( material ) {

		if ( material === undefined ) material = new THREE.Material();

		material.name = this.name;

		material.side = this.side;

		material.opacity = this.opacity;
		material.transparent = this.transparent;

		material.blending = this.blending;

		material.blendSrc = this.blendSrc;
		material.blendDst = this.blendDst;
		material.blendEquation = this.blendEquation;

		material.depthTest = this.depthTest;
		material.depthWrite = this.depthWrite;

		material.polygonOffset = this.polygonOffset;
		material.polygonOffsetFactor = this.polygonOffsetFactor;
		material.polygonOffsetUnits = this.polygonOffsetUnits;

		material.alphaTest = this.alphaTest;

		material.overdraw = this.overdraw;

		material.visible = this.visible;

		return material;

	},

	dispose: function () {

		this.dispatchEvent( { type: 'dispose' } );

	}

};

THREE.MaterialIdCount = 0;
<|endoftext|>


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 * @author alteredq / http://alteredqualia.com/
 */

THREE.Material = function () {

	Object.defineProperty( this, 'id', { value: THREE.MaterialIdCount ++ } );

	this.uuid = THREE.Math.generateUUID();

	this.name = '';
	this.type = 'Material';

	this.side = THREE.FrontSide;

	this.opacity = 1;
	this.transparent = false;

	this.blending = THREE.NormalBlending;

	this.blendSrc = THREE.SrcAlphaFactor;
	this.blendDst = THREE.OneMinusSrcAlphaFactor;
	this.blendEquation = THREE.AddEquation;
	this.blendSrcAlpha = null;
	this.blendDstAlpha = null;
	this.blendEquationAlpha = null;

	this.depthFunc = THREE.LessEqualDepth;
	this.depthTest = true;
	this.depthWrite = true;

	this.stencilTest = false;
	this.stencilWrite = false;

	this.colorWrite = true;

	this.precision = null; // override the renderer's default precision for this material

	this.polygonOffset = false;
	this.polygonOffsetFactor = 0;
	this.polygonOffsetUnits = 0;

	this.alphaTest = 0;

	this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer

	this.visible = true;

	this._needsUpdate = true;

};

THREE.Material.prototype = {

	constructor: THREE.Material,

	get needsUpdate () {

		return this._needsUpdate;

	},

	set needsUpdate ( value ) {

		if ( value === true ) this.update();

		this._needsUpdate = value;

	},

	setValues: function ( values ) {

		if ( values === undefined ) return;

		for ( var key in values ) {

			var newValue = values[ key ];

			if ( newValue === undefined ) {

				console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
				continue;

			}

			var currentValue = this[ key ];

			if ( currentValue === undefined ) {

				console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
				continue;

			}

			if ( currentValue instanceof THREE.Color ) {

				currentValue.set( newValue );

			} else if ( currentValue instanceof THREE.Vector3 && newValue instanceof THREE.Vector3 ) {

				currentValue.copy( newValue );

			} else if ( key === 'overdraw' ) {

				// ensure overdraw is backwards-compatible with legacy boolean type
				this[ key ] = Number( newValue );

			} else {

				this[ key ] = newValue;

			}

		}

	},

	toJSON: function ( meta ) {

		var isRoot = meta === undefined;

		if ( isRoot ) {

			meta = {
				textures: {},
				images: {}
			};

		}

		var data = {
			metadata: {
				version: 4.4,
				type: 'Material',
				generator: 'Material.toJSON'
			}
		};

		// standard Material serialization
		data.uuid = this.uuid;
		data.type = this.type;
		if ( this.name !== '' ) data.name = this.name;

		if ( this.color instanceof THREE.Color ) data.color = this.color.getHex();

		if ( this.roughness !== 0.5 ) data.roughness = this.roughness;
		if ( this.metalness > 0 ) data.metalness = this.metalness;

		if ( this.emissive instanceof THREE.Color ) data.emissive = this.emissive.getHex();
		if ( this.specular instanceof THREE.Color ) data.specular = this.specular.getHex();
		if ( this.shininess !== undefined ) data.shininess = this.shininess;

		if ( this.map instanceof THREE.Texture ) data.map = this.map.toJSON( meta ).uuid;
		if ( this.alphaMap instanceof THREE.Texture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
		if ( this.lightMap instanceof THREE.Texture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
		if ( this.bumpMap instanceof THREE.Texture ) {

			data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
			data.bumpScale = this.bumpScale;

		}
		if ( this.normalMap instanceof THREE.Texture ) {

			data.normalMap = this.normalMap.toJSON( meta ).uuid;
			data.normalScale = this.normalScale.toArray();

		}
		if ( this.displacementMap instanceof THREE.Texture ) {

			data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
			data.displacementScale = this.displacementScale;
			data.displacementBias = this.displacementBias;

		}
		if ( this.roughnessMap instanceof THREE.Texture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
		if ( this.metalnessMap instanceof THREE.Texture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;

		if ( this.emissiveMap instanceof THREE.Texture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
		if ( this.specularMap instanceof THREE.Texture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;

		if ( this.envMap instanceof THREE.Texture ) {

			data.envMap = this.envMap.toJSON( meta ).uuid;
			data.reflectivity = this.reflectivity; // Scale behind envMap

		}

		if ( this.size !== undefined ) data.size = this.size;
		if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;

		if ( this.vertexColors !== undefined && this.vertexColors !== THREE.NoColors ) data.vertexColors = this.vertexColors;
		if ( this.shading !== undefined && this.shading !== THREE.SmoothShading ) data.shading = this.shading;
		if ( this.blending !== undefined && this.blending !== THREE.NormalBlending ) data.blending = this.blending;
		if ( this.side !== undefined && this.side !== THREE.FrontSide ) data.side = this.side;

		if ( this.opacity < 1 ) data.opacity = this.opacity;
		if ( this.transparent === true ) data.transparent = this.transparent;
		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
		if ( this.wireframe === true ) data.wireframe = this.wireframe;
		if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;

		// TODO: Copied from Object3D.toJSON

		function extractFromCache ( cache ) {

			var values = [];

			for ( var key in cache ) {

				var data = cache[ key ];
				delete data.metadata;
				values.push( data );

			}

			return values;

		}

		if ( isRoot ) {

			var textures = extractFromCache( meta.textures );
			var images = extractFromCache( meta.images );

			if ( textures.length > 0 ) data.textures = textures;
			if ( images.length > 0 ) data.images = images;

		}

		return data;

	},

	clone: function () {

		return new this.constructor().copy( this );

	},

	copy: function ( source ) {

		this.name = source.name;

		this.side = source.side;

		this.opacity = source.opacity;
		this.transparent = source.transparent;

		this.blending = source.blending;

		this.blendSrc = source.blendSrc;
		this.blendDst = source.blendDst;
		this.blendEquation = source.blendEquation;
		this.blendSrcAlpha = source.blendSrcAlpha;
		this.blendDstAlpha = source.blendDstAlpha;
		this.blendEquationAlpha = source.blendEquationAlpha;

		this.depthFunc = source.depthFunc;
		this.depthTest = source.depthTest;
		this.depthWrite = source.depthWrite;

		this.stencilTest = source.stencilTest;
		this.stencilWrite = source.stencilWrite;

		this.colorWrite = source.colorWrite;

		this.precision = source.precision;

		this.polygonOffset = source.polygonOffset;
		this.polygonOffsetFactor = source.polygonOffsetFactor;
		this.polygonOffsetUnits = source.polygonOffsetUnits;

		this.alphaTest = source.alphaTest;

		this.overdraw = source.overdraw;

		this.visible = source.visible;

		return this;

	},

	update: function () {

		this.dispatchEvent( { type: 'update' } );

	},

	dispose: function () {

		this.dispatchEvent( { type: 'dispose' } );

	}

};

THREE.EventDispatcher.prototype.apply( THREE.Material.prototype );

THREE.MaterialIdCount = 0;
<commit_msg>Material: clean up.<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 * @author alteredq / http://alteredqualia.com/
 */

THREE.Material = function () {

	Object.defineProperty( this, 'id', { value: THREE.MaterialIdCount ++ } );

	this.uuid = THREE.Math.generateUUID();

	this.name = '';
	this.type = 'Material';

	this.side = THREE.FrontSide;

	this.opacity = 1;
	this.transparent = false;

	this.blending = THREE.NormalBlending;

	this.blendSrc = THREE.SrcAlphaFactor;
	this.blendDst = THREE.OneMinusSrcAlphaFactor;
	this.blendEquation = THREE.AddEquation;
	this.blendSrcAlpha = null;
	this.blendDstAlpha = null;
	this.blendEquationAlpha = null;

	this.depthFunc = THREE.LessEqualDepth;
	this.depthTest = true;
	this.depthWrite = true;

	this.colorWrite = true;

	this.stencilTest = false;
	this.stencilWrite = false;

	this.precision = null; // override the renderer's default precision for this material

	this.polygonOffset = false;
	this.polygonOffsetFactor = 0;
	this.polygonOffsetUnits = 0;

	this.alphaTest = 0;

	this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer

	this.visible = true;

	this._needsUpdate = true;

};

THREE.Material.prototype = {

	constructor: THREE.Material,

	get needsUpdate () {

		return this._needsUpdate;

	},

	set needsUpdate ( value ) {

		if ( value === true ) this.update();

		this._needsUpdate = value;

	},

	setValues: function ( values ) {

		if ( values === undefined ) return;

		for ( var key in values ) {

			var newValue = values[ key ];

			if ( newValue === undefined ) {

				console.warn( "THREE.Material: '" + key + "' parameter is undefined." );
				continue;

			}

			var currentValue = this[ key ];

			if ( currentValue === undefined ) {

				console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." );
				continue;

			}

			if ( currentValue instanceof THREE.Color ) {

				currentValue.set( newValue );

			} else if ( currentValue instanceof THREE.Vector3 && newValue instanceof THREE.Vector3 ) {

				currentValue.copy( newValue );

			} else if ( key === 'overdraw' ) {

				// ensure overdraw is backwards-compatible with legacy boolean type
				this[ key ] = Number( newValue );

			} else {

				this[ key ] = newValue;

			}

		}

	},

	toJSON: function ( meta ) {

		var isRoot = meta === undefined;

		if ( isRoot ) {

			meta = {
				textures: {},
				images: {}
			};

		}

		var data = {
			metadata: {
				version: 4.4,
				type: 'Material',
				generator: 'Material.toJSON'
			}
		};

		// standard Material serialization
		data.uuid = this.uuid;
		data.type = this.type;
		if ( this.name !== '' ) data.name = this.name;

		if ( this.color instanceof THREE.Color ) data.color = this.color.getHex();

		if ( this.roughness !== 0.5 ) data.roughness = this.roughness;
		if ( this.metalness > 0 ) data.metalness = this.metalness;

		if ( this.emissive instanceof THREE.Color ) data.emissive = this.emissive.getHex();
		if ( this.specular instanceof THREE.Color ) data.specular = this.specular.getHex();
		if ( this.shininess !== undefined ) data.shininess = this.shininess;

		if ( this.map instanceof THREE.Texture ) data.map = this.map.toJSON( meta ).uuid;
		if ( this.alphaMap instanceof THREE.Texture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
		if ( this.lightMap instanceof THREE.Texture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;
		if ( this.bumpMap instanceof THREE.Texture ) {

			data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
			data.bumpScale = this.bumpScale;

		}
		if ( this.normalMap instanceof THREE.Texture ) {

			data.normalMap = this.normalMap.toJSON( meta ).uuid;
			data.normalScale = this.normalScale.toArray();

		}
		if ( this.displacementMap instanceof THREE.Texture ) {

			data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
			data.displacementScale = this.displacementScale;
			data.displacementBias = this.displacementBias;

		}
		if ( this.roughnessMap instanceof THREE.Texture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
		if ( this.metalnessMap instanceof THREE.Texture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;

		if ( this.emissiveMap instanceof THREE.Texture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
		if ( this.specularMap instanceof THREE.Texture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;

		if ( this.envMap instanceof THREE.Texture ) {

			data.envMap = this.envMap.toJSON( meta ).uuid;
			data.reflectivity = this.reflectivity; // Scale behind envMap

		}

		if ( this.size !== undefined ) data.size = this.size;
		if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;

		if ( this.vertexColors !== undefined && this.vertexColors !== THREE.NoColors ) data.vertexColors = this.vertexColors;
		if ( this.shading !== undefined && this.shading !== THREE.SmoothShading ) data.shading = this.shading;
		if ( this.blending !== undefined && this.blending !== THREE.NormalBlending ) data.blending = this.blending;
		if ( this.side !== undefined && this.side !== THREE.FrontSide ) data.side = this.side;

		if ( this.opacity < 1 ) data.opacity = this.opacity;
		if ( this.transparent === true ) data.transparent = this.transparent;
		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
		if ( this.wireframe === true ) data.wireframe = this.wireframe;
		if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;

		// TODO: Copied from Object3D.toJSON

		function extractFromCache ( cache ) {

			var values = [];

			for ( var key in cache ) {

				var data = cache[ key ];
				delete data.metadata;
				values.push( data );

			}

			return values;

		}

		if ( isRoot ) {

			var textures = extractFromCache( meta.textures );
			var images = extractFromCache( meta.images );

			if ( textures.length > 0 ) data.textures = textures;
			if ( images.length > 0 ) data.images = images;

		}

		return data;

	},

	clone: function () {

		return new this.constructor().copy( this );

	},

	copy: function ( source ) {

		this.name = source.name;

		this.side = source.side;

		this.opacity = source.opacity;
		this.transparent = source.transparent;

		this.blending = source.blending;

		this.blendSrc = source.blendSrc;
		this.blendDst = source.blendDst;
		this.blendEquation = source.blendEquation;
		this.blendSrcAlpha = source.blendSrcAlpha;
		this.blendDstAlpha = source.blendDstAlpha;
		this.blendEquationAlpha = source.blendEquationAlpha;

		this.depthFunc = source.depthFunc;
		this.depthTest = source.depthTest;
		this.depthWrite = source.depthWrite;

		this.colorWrite = source.colorWrite;

		this.stencilTest = source.stencilTest;
		this.stencilWrite = source.stencilWrite;

		this.precision = source.precision;

		this.polygonOffset = source.polygonOffset;
		this.polygonOffsetFactor = source.polygonOffsetFactor;
		this.polygonOffsetUnits = source.polygonOffsetUnits;

		this.alphaTest = source.alphaTest;

		this.overdraw = source.overdraw;

		this.visible = source.visible;

		return this;

	},

	update: function () {

		this.dispatchEvent( { type: 'update' } );

	},

	dispose: function () {

		this.dispatchEvent( { type: 'dispose' } );

	}

};

THREE.EventDispatcher.prototype.apply( THREE.Material.prototype );

THREE.MaterialIdCount = 0;
<|endoftext|>


<commit_before>import 'whatwg-fetch'

const apiUrl = 'https://api.spotify.com/v1'

export default class SpotifyApi {
  constructor(token) {
    this.token = token
    this.headers = { Authorization: `Bearer ${this.token}` }
  }

  me() {
    return this.get('/me')
  }

  myTracks(opts) {
    const options = opts || {}
    const limit = options.limit || 10
    const offset = options.offset || 0
    return this.get(`/me/tracks?limit=${limit}&offset=${offset}`)
  }

  myTracksForPastMonths(numMonths) {
    const pastDate = new Date()
    pastDate.setMonth(pastDate.getMonth() - numMonths)
    pastDate.setHours(0, 0, 0, 0)

    return new Promise((resolve, reject) => {
      this.myTracksBeforeDate(pastDate, [], resolve, reject, 50, 0)
    })
  }

  audioFeatures(allIDs) {
    const chunkSize = 100
    if (allIDs.length <= chunkSize) {
      return this.audioFeaturesForIDs(allIDs)
    }
    return new Promise((resolve, reject) => {
      const batches = []
      for (let i = 0; i < allIDs.length; i += chunkSize) {
        batches.push(allIDs.slice(i, i + chunkSize))
      }
      this.audioFeaturesForBatch(batches, 0, [], resolve, reject)
    })
  }

  /* Internal: */

  myTracksBeforeDate(pastDate, items, resolve, reject, limit, offset) {
    this.myTracks({ limit, offset }).then(json => {
      const dates = []
      for (const item of json.items) {
        const date = new Date(item.added_at)
        dates.push(date)
        if (date >= pastDate) {
          items.push(item)
        }
      }
      dates.sort()
      const earliestDate = dates[0]
      if (earliestDate < pastDate) {
        resolve(items)
      } else {
        this.myTracksBeforeDate(pastDate, items, resolve, reject, limit, offset + limit)
      }
    }).catch(error => {
      reject(error)
    })
  }

  audioFeaturesForBatch(batches, index, prevFeatures, resolve, reject) {
    this.audioFeaturesForIDs(batches[index]).then(features => {
      const allFeatures = prevFeatures.concat(features)
      if (index < batches.length - 1) {
        this.audioFeaturesForBatch(batches, index + 1, allFeatures, resolve,
                                   reject)
      } else {
        resolve(allFeatures)
      }
    }).catch(error => {
      reject(error)
    })
  }

  audioFeaturesForIDs(ids) {
    return new Promise((resolve, reject) => {
      const idStr = ids.join(',')
      this.get(`/audio-features?ids=${idStr}`).then(json => {
        resolve(json.audio_features)
      }).catch(error => {
        reject(error)
      })
    })
  }

  checkStatus(response) {
    if (response.status >= 200 && response.status < 300) {
      return response
    }
    const error = new Error(response.statusText)
    error.response = response
    throw error
  }

  parseJson(response) {
    return response.json()
  }

  get(path) {
    const url = `${apiUrl}${path}`
    console.log('GET', url)
    return fetch(url, { headers: this.headers }).
      then(this.checkStatus).
      then(this.parseJson)
  }
}
<commit_msg>Don't output URLs being fetched<commit_after>import 'whatwg-fetch'

const apiUrl = 'https://api.spotify.com/v1'

export default class SpotifyApi {
  constructor(token) {
    this.token = token
    this.headers = { Authorization: `Bearer ${this.token}` }
  }

  me() {
    return this.get('/me')
  }

  myTracks(opts) {
    const options = opts || {}
    const limit = options.limit || 10
    const offset = options.offset || 0
    return this.get(`/me/tracks?limit=${limit}&offset=${offset}`)
  }

  myTracksForPastMonths(numMonths) {
    const pastDate = new Date()
    pastDate.setMonth(pastDate.getMonth() - numMonths)
    pastDate.setHours(0, 0, 0, 0)

    return new Promise((resolve, reject) => {
      this.myTracksBeforeDate(pastDate, [], resolve, reject, 50, 0)
    })
  }

  audioFeatures(allIDs) {
    const chunkSize = 100
    if (allIDs.length <= chunkSize) {
      return this.audioFeaturesForIDs(allIDs)
    }
    return new Promise((resolve, reject) => {
      const batches = []
      for (let i = 0; i < allIDs.length; i += chunkSize) {
        batches.push(allIDs.slice(i, i + chunkSize))
      }
      this.audioFeaturesForBatch(batches, 0, [], resolve, reject)
    })
  }

  /* Internal: */

  myTracksBeforeDate(pastDate, items, resolve, reject, limit, offset) {
    this.myTracks({ limit, offset }).then(json => {
      const dates = []
      for (const item of json.items) {
        const date = new Date(item.added_at)
        dates.push(date)
        if (date >= pastDate) {
          items.push(item)
        }
      }
      dates.sort()
      const earliestDate = dates[0]
      if (earliestDate < pastDate) {
        resolve(items)
      } else {
        this.myTracksBeforeDate(pastDate, items, resolve, reject, limit, offset + limit)
      }
    }).catch(error => {
      reject(error)
    })
  }

  audioFeaturesForBatch(batches, index, prevFeatures, resolve, reject) {
    this.audioFeaturesForIDs(batches[index]).then(features => {
      const allFeatures = prevFeatures.concat(features)
      if (index < batches.length - 1) {
        this.audioFeaturesForBatch(batches, index + 1, allFeatures, resolve,
                                   reject)
      } else {
        resolve(allFeatures)
      }
    }).catch(error => {
      reject(error)
    })
  }

  audioFeaturesForIDs(ids) {
    return new Promise((resolve, reject) => {
      const idStr = ids.join(',')
      this.get(`/audio-features?ids=${idStr}`).then(json => {
        resolve(json.audio_features)
      }).catch(error => {
        reject(error)
      })
    })
  }

  checkStatus(response) {
    if (response.status >= 200 && response.status < 300) {
      return response
    }
    const error = new Error(response.statusText)
    error.response = response
    throw error
  }

  parseJson(response) {
    return response.json()
  }

  get(path) {
    const url = `${apiUrl}${path}`
    return fetch(url, { headers: this.headers }).
      then(this.checkStatus).
      then(this.parseJson)
  }
}
<|endoftext|>