<commit_before>/* jshint node: true */
'use strict';

var path = require('path');

function ConfigJson(options) {

  var existsPathInOptions = !options || typeof options.path !== 'string',
      isPathToJsonFile;

  // Object properties
  this.path = null;
  this.defaultFilename = null;
  this.content = null;

  if (existsPathInOptions){
    throw new Error('You have to pass the "path" to JSON file.', 'config-json.js', 17);
  }

  this.path = options.path;
  this.defaultFilename =
    (typeof options.defaultFilename === 'string')?
    options.defaultFilename:
    null;

  isPathToJsonFile = /.+\.json$/.test(this.path);
  if (!isPathToJsonFile && this.defaultFilename === null) {
    throw new Error('"path" points to a directory, but I cannot find any "defaultFilename" in options.', 'config-json.js', 28);
  } else {
    this.path = path.join(this.path, this.defaultFilename);
  }

  try {
    this.content = require(this.path);
  } catch(e) {
    throw new Error('File not found: ' + this.path, 'config-json.js', 36);
  }

}

ConfigJson.prototype = {
  hasKeyword: function hasKeyword(keyword){
    for (var i = 0, length = (this.content.keywords)?this.content.keywords.length:0; i < length; i++){
      if (this.content.keywords[i] == keyword) {
        return true;
      }
    }
    return false;
  }
};

module.exports = ConfigJson;  <commit_msg>Bug fix<commit_after>/* jshint node: true */
'use strict';

var path = require('path');

function ConfigJson(options) {

  var existsPathInOptions = !options || typeof options.path !== 'string',
      isPathToJsonFile;

  // Object properties
  this.path = null;
  this.defaultFilename = null;
  this.content = null;

  if (existsPathInOptions){
    throw new Error('You have to pass the "path" to JSON file.', 'config-json.js', 17);
  }

  this.path = options.path;
  this.defaultFilename =
    (typeof options.defaultFilename === 'string')?
    options.defaultFilename:
    null;

  isPathToJsonFile = /.+json$/.test(this.path);
  if (!isPathToJsonFile) {
    if (this.defaultFilename === null) {
      throw new Error('"path" points to a directory, but I cannot find any "defaultFilename" in options.', 'config-json.js', 28);
    } else {
      this.path = path.join(this.path, this.defaultFilename);
    }
  }

  try {
    this.content = require(this.path);
  } catch(e) {
    throw new Error('File not found: ' + this.path, 'config-json.js', 36);
  }

}

ConfigJson.prototype = {
  hasKeyword: function hasKeyword(keyword){
    for (var i = 0, length = (this.content.keywords)?this.content.keywords.length:0; i < length; i++){
      if (this.content.keywords[i] == keyword) {
        return true;
      }
    }
    return false;
  }
};

module.exports = ConfigJson;  <|endoftext|>


<commit_before>// @flow
import {
  ACTIONS,
  Lbry,
  selectMyClaimsWithoutChannels,
  doNotify,
  MODALS,
  selectMyChannelClaims,
  STATUSES
} from 'lbry-redux';
import { selectPendingPublishes } from 'redux/selectors/publish';
import type {
  UpdatePublishFormData,
  UpdatePublishFormAction,
  PublishParams,
} from 'redux/reducers/publish';
import fs from 'fs';
import path from 'path';

type Action = UpdatePublishFormAction | { type: ACTIONS.CLEAR_PUBLISH };
type PromiseAction = Promise<Action>;
type Dispatch = (action: Action | PromiseAction | Array<Action>) => any;
type GetState = () => {};

export const doClearPublish = () => (dispatch: Dispatch): Action =>
  dispatch({ type: ACTIONS.CLEAR_PUBLISH });

export const doUpdatePublishForm = (publishFormValue: UpdatePublishFormData) => (
  dispatch: Dispatch
): UpdatePublishFormAction =>
  dispatch({
    type: ACTIONS.UPDATE_PUBLISH_FORM,
    data: { ...publishFormValue },
  });

export const doResetThumbnailStatus = () => (dispatch: Dispatch): Action =>
  fetch('https://spee.ch/api/channel/availability/@testing')
    .then(() =>
      dispatch({
        type: ACTIONS.UPDATE_PUBLISH_FORM,
        data: {
          uploadThumbnailStatus: STATUSES.READY,
          thumbnail: '',
          nsfw: false,
        },
      })
    )
    .catch(() =>
      dispatch({
        type: ACTIONS.UPDATE_PUBLISH_FORM,
        data: {
          uploadThumbnailStatus: STATUSES.API_DOWN,
          thumbnail: '',
          nsfw: false,
        },
      })
    );

export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch: Dispatch) => {
  const thumbnail = fs.readFileSync(filePath);
  const fileExt = path.extname(filePath);

  const makeid = () => {
    let text = '';
    const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    for (let i = 0; i < 24; i += 1) text += possible.charAt(Math.floor(Math.random() * 62));
    return text;
  };

  const uploadError = (error = '') =>
    dispatch(
      batchActions(
        {
          type: ACTIONS.UPDATE_PUBLISH_FORM,
          data: { uploadThumbnailStatus: STATUSES.API_DOWN },
        },
        doAlertError(error)
      )
    );

  dispatch({
    type: ACTIONS.UPDATE_PUBLISH_FORM,
    data: { uploadThumbnailStatus: STATUSES.IN_PROGRESS },
  });

  const data = new FormData();
  const name = makeid();
  const blob = new Blob([thumbnail], { type: `image/${fileExt.slice(1)}` });
  data.append('name', name);
  data.append('file', blob);
  data.append('nsfw', nsfw.toString());
  return fetch('https://spee.ch/api/claim/publish', {
    method: 'POST',
    body: data,
  })
    .then(response => response.json())
    .then(
      json =>
        json.success
          ? dispatch({
              type: ACTIONS.UPDATE_PUBLISH_FORM,
              data: {
                uploadThumbnailStatus: STATUSES.COMPLETE,
                thumbnail: `${json.data.url}${fileExt}`,
              },
            })
          : uploadError('Upload failed')
    )
    .catch(err => uploadError(err.message));
};

export const doPrepareEdit = (claim: any) => (dispatch: Dispatch) => {
  const { name, amount, channel_name: channelName, value: { stream: { metadata } } } = claim;

  const {
    author,
    description,
    // use same values as default state
    // fee will be undefined for free content
    fee = {
      amount: 0,
      currency: 'LBC',
    },
    language,
    license,
    licenseUrl,
    nsfw,
    thumbnail,
    title,
  } = metadata;

  const publishData = {
    name,
    channel: channelName,
    bid: amount,
    price: { amount: fee.amount, currency: fee.currency },
    contentIsFree: !fee.amount,
    author,
    description,
    fee,
    language,
    license,
    licenseUrl,
    nsfw,
    thumbnail,
    title,
    uri,
  };

  dispatch({ type: ACTIONS.DO_PREPARE_EDIT, data: publishData });
};

export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getState: () => {}) => {
  const state = getState();
  const myClaims = selectMyClaimsWithoutChannels(state);
  const myChannels = selectMyChannelClaims(state);

  const {
    name,
    bid,
    filePath,
    description,
    language,
    license,
    licenseUrl,
    thumbnail,
    nsfw,
    channel,
    title,
    contentIsFree,
    price,
    uri,
    sources,
  } = params;

  // get the claim id from the channel name, we will use that instead
  const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel);
  const channelId = namedChannelClaim ? namedChannelClaim.claim_id : '';

  let isEdit;
  const newPublishName = channel ? `${channel}/${name}` : name;
  for (let i = 0; i < myClaims.length; i += 1) {
    const { channel_name: claimChannelName, name: claimName } = myClaims[i];
    const contentName = claimChannelName ? `${claimChannelName}/${claimName}` : claimName;
    if (contentName === newPublishName) {
      isEdit = true;
      break;
    }
  }

  const fee = contentIsFree || !price.amount ? undefined : { ...price };

  const metadata = {
    title,
    nsfw,
    license,
    licenseUrl,
    language,
    thumbnail,
  };

  if (fee) {
    metadata.fee = fee;
  }

  if (description) {
    metadata.description = description;
  }

  const publishPayload = {
    name,
    channel_id: channelId,
    bid,
    metadata,
  };

  if (filePath) {
    publishPayload.file_path = filePath;
  } else {
    publishPayload.sources = sources;
  }

  dispatch({ type: ACTIONS.PUBLISH_START });

  const success = () => {
    dispatch({
      type: ACTIONS.PUBLISH_SUCCESS,
      data: { pendingPublish: { ...publishPayload, isEdit } },
    });
    dispatch(doNotify({ id: MODALS.PUBLISH }, { uri }));
  };

  const failure = error => {
    dispatch({ type: ACTIONS.PUBLISH_FAIL });
    dispatch(doNotify({ id: MODALS.ERROR, error: error.message }));
  };

  return Lbry.publish(publishPayload).then(success, failure);
};

// Calls claim_list_mine until any pending publishes are confirmed
export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetState) => {
  const state = getState();
  const pendingPublishes = selectPendingPublishes(state);
  const myClaims = selectMyClaimsWithoutChannels(state);

  let publishCheckInterval;

  const checkFileList = () => {
    Lbry.claim_list_mine().then(claims => {
      const claimsWithoutChannels = claims.filter(claim => !claim.name.match(/^@/));
      if (myClaims.length !== claimsWithoutChannels.length) {
        const pendingPublishMap = {};
        pendingPublishes.forEach(({ name }) => {
          pendingPublishMap[name] = name;
        });

        claims.forEach(claim => {
          if (pendingPublishMap[claim.name]) {
            dispatch({
              type: ACTIONS.REMOVE_PENDING_PUBLISH,
              data: {
                name: claim.name,
              },
            });
            dispatch({
              type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED,
              data: {
                claims,
              },
            });

            delete pendingPublishMap[claim.name];
          }
        });

        clearInterval(publishCheckInterval);
      }
    });
  };

  if (pendingPublishes.length) {
    checkFileList();
    publishCheckInterval = setInterval(() => {
      checkFileList();
    }, 10000);
  }
};
<commit_msg>add doResetThumbnailStatus and doUploadThumbnail actions<commit_after>// @flow
import {
  ACTIONS,
  Lbry,
  selectMyClaimsWithoutChannels,
  doNotify,
  MODALS,
  selectMyChannelClaims,
  STATUSES
} from 'lbry-redux';
import { selectPendingPublishes } from 'redux/selectors/publish';
import type {
  UpdatePublishFormData,
  UpdatePublishFormAction,
  PublishParams,
} from 'redux/reducers/publish';
import fs from 'fs';
import path from 'path';

type Action = UpdatePublishFormAction | { type: ACTIONS.CLEAR_PUBLISH };
type PromiseAction = Promise<Action>;
type Dispatch = (action: Action | PromiseAction | Array<Action>) => any;
type GetState = () => {};

export const doClearPublish = () => (dispatch: Dispatch): Action =>
  dispatch({ type: ACTIONS.CLEAR_PUBLISH });

export const doUpdatePublishForm = (publishFormValue: UpdatePublishFormData) => (
  dispatch: Dispatch
): UpdatePublishFormAction =>
  dispatch({
    type: ACTIONS.UPDATE_PUBLISH_FORM,
    data: { ...publishFormValue },
  });

export const doResetThumbnailStatus = () => (dispatch: Dispatch): Action =>
  fetch('https://spee.ch/api/channel/availability/@testing')
    .then(() =>
      dispatch({
        type: ACTIONS.UPDATE_PUBLISH_FORM,
        data: {
          uploadThumbnailStatus: STATUSES.READY,
          thumbnail: '',
          nsfw: false,
        },
      })
    )
    .catch(() =>
      dispatch({
        type: ACTIONS.UPDATE_PUBLISH_FORM,
        data: {
          uploadThumbnailStatus: STATUSES.API_DOWN,
          thumbnail: '',
          nsfw: false,
        },
      })
    );

export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch: Dispatch) => {
  const thumbnail = fs.readFileSync(filePath);
  const fileExt = path.extname(filePath);

  const makeid = () => {
    let text = '';
    const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    for (let i = 0; i < 24; i += 1) text += possible.charAt(Math.floor(Math.random() * 62));
    return text;
  };

  const uploadError = (error: string = '') =>
    dispatch(
      batchActions(
        {
          type: ACTIONS.UPDATE_PUBLISH_FORM,
          data: { uploadThumbnailStatus: STATUSES.API_DOWN },
        },
        doAlertError(error)
      )
    );

  dispatch({
    type: ACTIONS.UPDATE_PUBLISH_FORM,
    data: { uploadThumbnailStatus: STATUSES.IN_PROGRESS },
  });

  const data = new FormData();
  const name = makeid();
  const blob = new Blob([thumbnail], { type: `image/${fileExt.slice(1)}` });
  data.append('name', name);
  data.append('file', blob);
  data.append('nsfw', nsfw.toString());
  return fetch('https://spee.ch/api/claim/publish', {
    method: 'POST',
    body: data,
  })
    .then(response => response.json())
    .then(
      json =>
        json.success
          ? dispatch({
              type: ACTIONS.UPDATE_PUBLISH_FORM,
              data: {
                uploadThumbnailStatus: STATUSES.COMPLETE,
                thumbnail: `${json.data.url}${fileExt}`,
              },
            })
          : uploadError('Upload failed')
    )
    .catch(err => uploadError(err.message));
};

export const doPrepareEdit = (claim: any) => (dispatch: Dispatch) => {
  const { name, amount, channel_name: channelName, value: { stream: { metadata } } } = claim;

  const {
    author,
    description,
    // use same values as default state
    // fee will be undefined for free content
    fee = {
      amount: 0,
      currency: 'LBC',
    },
    language,
    license,
    licenseUrl,
    nsfw,
    thumbnail,
    title,
  } = metadata;

  const publishData = {
    name,
    channel: channelName,
    bid: amount,
    price: { amount: fee.amount, currency: fee.currency },
    contentIsFree: !fee.amount,
    author,
    description,
    fee,
    language,
    license,
    licenseUrl,
    nsfw,
    thumbnail,
    title,
    uri,
  };

  dispatch({ type: ACTIONS.DO_PREPARE_EDIT, data: publishData });
};

export const doPublish = (params: PublishParams) => (dispatch: Dispatch, getState: () => {}) => {
  const state = getState();
  const myClaims = selectMyClaimsWithoutChannels(state);
  const myChannels = selectMyChannelClaims(state);

  const {
    name,
    bid,
    filePath,
    description,
    language,
    license,
    licenseUrl,
    thumbnail,
    nsfw,
    channel,
    title,
    contentIsFree,
    price,
    uri,
    sources,
  } = params;

  // get the claim id from the channel name, we will use that instead
  const namedChannelClaim = myChannels.find(myChannel => myChannel.name === channel);
  const channelId = namedChannelClaim ? namedChannelClaim.claim_id : '';

  let isEdit;
  const newPublishName = channel ? `${channel}/${name}` : name;
  for (let i = 0; i < myClaims.length; i += 1) {
    const { channel_name: claimChannelName, name: claimName } = myClaims[i];
    const contentName = claimChannelName ? `${claimChannelName}/${claimName}` : claimName;
    if (contentName === newPublishName) {
      isEdit = true;
      break;
    }
  }

  const fee = contentIsFree || !price.amount ? undefined : { ...price };

  const metadata = {
    title,
    nsfw,
    license,
    licenseUrl,
    language,
    thumbnail,
  };

  if (fee) {
    metadata.fee = fee;
  }

  if (description) {
    metadata.description = description;
  }

  const publishPayload = {
    name,
    channel_id: channelId,
    bid,
    metadata,
  };

  if (filePath) {
    publishPayload.file_path = filePath;
  } else {
    publishPayload.sources = sources;
  }

  dispatch({ type: ACTIONS.PUBLISH_START });

  const success = () => {
    dispatch({
      type: ACTIONS.PUBLISH_SUCCESS,
      data: { pendingPublish: { ...publishPayload, isEdit } },
    });
    dispatch(doNotify({ id: MODALS.PUBLISH }, { uri }));
  };

  const failure = error => {
    dispatch({ type: ACTIONS.PUBLISH_FAIL });
    dispatch(doNotify({ id: MODALS.ERROR, error: error.message }));
  };

  return Lbry.publish(publishPayload).then(success, failure);
};

// Calls claim_list_mine until any pending publishes are confirmed
export const doCheckPendingPublishes = () => (dispatch: Dispatch, getState: GetState) => {
  const state = getState();
  const pendingPublishes = selectPendingPublishes(state);
  const myClaims = selectMyClaimsWithoutChannels(state);

  let publishCheckInterval;

  const checkFileList = () => {
    Lbry.claim_list_mine().then(claims => {
      const claimsWithoutChannels = claims.filter(claim => !claim.name.match(/^@/));
      if (myClaims.length !== claimsWithoutChannels.length) {
        const pendingPublishMap = {};
        pendingPublishes.forEach(({ name }) => {
          pendingPublishMap[name] = name;
        });

        claims.forEach(claim => {
          if (pendingPublishMap[claim.name]) {
            dispatch({
              type: ACTIONS.REMOVE_PENDING_PUBLISH,
              data: {
                name: claim.name,
              },
            });
            dispatch({
              type: ACTIONS.FETCH_CLAIM_LIST_MINE_COMPLETED,
              data: {
                claims,
              },
            });

            delete pendingPublishMap[claim.name];
          }
        });

        clearInterval(publishCheckInterval);
      }
    });
  };

  if (pendingPublishes.length) {
    checkFileList();
    publishCheckInterval = setInterval(() => {
      checkFileList();
    }, 10000);
  }
};
<|endoftext|>


<commit_before>var OPTION_MOUSEMOVE_PICKING = "renderer-mousemove-picking";
var OPTION_MOVEMENT_AWARE_CLICK_HANDLER = "renderer-movement-aware-click-handler";
XML3D.options.register(OPTION_MOUSEMOVE_PICKING, true);
XML3D.options.register(OPTION_MOVEMENT_AWARE_CLICK_HANDLER, false);

var EVENTS = ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mousewheel"];

/**
 *
 * @param {Element} defaultTarget
 * @param {AbstractCanvasHandler} canvasHandler
 * @constructor
 */
var MouseEventHandler = function(defaultTarget, canvasHandler) {
    this._defaultTarget = defaultTarget;
    this._canvasHandler = canvasHandler;
    this._lastMousePosition =  {x: 0, y: 0};
};

MouseEventHandler.prototype =  {

    /**
     * @param {MouseEvent} event  The original event
     * @param {Element} target  target to dispatch on
     * @param {object?}     opt    Options
     */
    dispatchMouseEvent: function (event, target, opt) {
        opt = opt || {};
        target = target || this._defaultTarget;
        var x = opt.x !== undefined ? opt.x : event.clientX;
        var y = opt.y !== undefined ? opt.y : event.clientY;
        var noCopy = opt.noCopy || false;
        // Copy event to avoid DOM dispatch errors (cannot dispatch event more
        // than once)
        event = noCopy ? event : this.copyMouseEvent(event);
        this.initExtendedMouseEvent(event, x, y);

        target.dispatchEvent(event);
    },

    /**
     * @param {MouseEvent} event the event to copy
     * @return {MouseEvent} the new event
     */
    copyMouseEvent: function (event) {
        var evt = document.createEvent("MouseEvents");
        evt.initMouseEvent(event.type, // canBubble, cancelable, view, detail
            event.bubbles, event.cancelable, event.view, event.detail, // screenX, screenY, clientX, clientY
            event.screenX, event.screenY, event.clientX, event.clientY, // ctrl, alt, shift, meta, button
            event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, event.button, // relatedTarget
            event.relatedTarget);
        if (event.dataTransfer)
            evt.data = {url: event.dataTransfer.getData("URL"), text: event.dataTransfer.getData("Text")};
        // override preventDefault to actually prevent the default of the original event
        evt.preventDefault = function () {
            event.preventDefault();
        };
        return evt;
    },

    createMouseEvent: function (type, opts) {
        opts = opts || {};
        var event = document.createEvent("MouseEvents");
        event.initMouseEvent(type, opts.canBubble !== undefined ? opts.canBubble : true, opts.cancelable !== undefined ? opts.cancelable : true, opts.view || window, opts.detail != undefined ? opts.detail : 0, opts.screenX != undefined ? opts.screenX : 0, opts.screenY != undefined ? opts.screenY : 0, opts.clientX != undefined ? opts.clientX : 0, opts.clientY != undefined ? opts.clientY : 0, opts.ctrl != undefined ? opts.ctrl : false, opts.alt != undefined ? opts.alt : false, opts.shift != undefined ? opts.shift : false, opts.meta != undefined ? opts.meta : false, opts.button != undefined ? opts.button : 0, opts.relatedTarget);
        return event;
    },

    /**
     * Adds position and normal attributes to the given event.
     *
     * @param {Event} event
     * @param {number} x
     * @param {number} y
     * @return {XML3DVec3}
     */
    initExtendedMouseEvent: function (event, x, y) {
        var handler = this._canvasHandler;

        (function () {
            var cachedPosition = undefined;
            var cachedNormal = undefined;

            event.__defineGetter__("normal", function () {
                if (cachedNormal !== undefined) return cachedNormal;
                var norm = (handler.getWorldSpaceNormalByPoint(x, y));
                cachedNormal = norm ? new window.XML3DVec3(norm[0], norm[1], norm[2]) : null;
                return cachedNormal;
            });
            event.__defineGetter__("position", function () {
                if (!cachedPosition) {
                    var pos = handler.getWorldSpacePositionByPoint(x, y);
                    cachedPosition = pos ? new window.XML3DVec3(pos[0], pos[1], pos[2]) : null;
                }
                return cachedPosition;
            });

        })();

    },

    /**
     * @param {MouseEvent} evt
     * @param {object?} opt
     */
    dispatchMouseEventOnPickedObject: function (evt, opt) {
        opt = opt || {};
        var pos = this.getMousePosition(evt);

        var picked = null;
        if (!opt.omitUpdate)
            picked = this._canvasHandler.getPickObjectByPoint(pos.x, pos.y);

        this.dispatchMouseEvent(evt, picked && picked.node, pos);
    },

    getMousePosition: function (evt) {
        return this._canvasHandler.getMousePosition(evt)
    },

    /**
     * @param {MouseEvent} evt
     */
    mouseup: function (evt) {
        this.dispatchMouseEventOnPickedObject(evt);
    },

    /**
     * @param {MouseEvent} evt
     */
    mousedown: function (evt) {
        this._lastMousePosition = this.getMousePosition(evt);
        this.dispatchMouseEventOnPickedObject(evt);
    },

    /**
     * @param {MouseEvent} evt
     */
    click: function (evt) {
        if (XML3D.options.getValue("renderer-movement-aware-click-handler") === true) {
            var pos = this.getMousePosition(evt);
            if (Math.abs(pos.x - this._lastMousePosition.x) > 4 || Math.abs(pos.y - this._lastMousePosition.y) > 4)
                return;
        }
        this.dispatchMouseEventOnPickedObject(evt);
    },

    /**
     * @param {MouseEvent} evt
     */
    dblclick: function (evt) {
        this.dispatchMouseEventOnPickedObject(evt);
    },

    /**
     * This method is called each time a mouseMove event is triggered on the
     * canvas.
     *
     * This method also triggers mouseover and mouseout events of objects in the
     * scene.
     *
     * @param {MouseEvent} evt
     */
    mousemove: function (evt) {
        var pos = this.getMousePosition(evt);

        var doMouseMovePick = XML3D.options.getValue(OPTION_MOUSEMOVE_PICKING);

        this.dispatchMouseEventOnPickedObject(evt, {omitUpdate: !doMouseMovePick});
        if (!doMouseMovePick)
            return;

        var curObj = this._canvasHandler.getPickedObject();

        // trigger mouseover and mouseout
        if (curObj !== this.lastPickObj) {
            if (this.lastPickObj) {
                // The mouse has left the last object
                this.dispatchMouseEvent(this.createMouseEvent("mouseout", {
                    clientX: pos.x, clientY: pos.y, button: evt.button
                }), this.lastPickObj);
                if (!curObj) { // Nothing picked, this means we enter the xml3d canvas
                    this.dispatchMouseEvent(this.createMouseEvent("mouseover", {
                        clientX: pos.x, clientY: pos.y, button: evt.button
                    }), this._defaultTarget);
                }
            }
            if (curObj) {
                // The mouse is now over a different object, so call the new
                // object's mouseover method
                this.dispatchMouseEvent(this.createMouseEvent("mouseover", {
                    clientX: pos.x, clientY: pos.y, button: evt.button
                }), curObj);
                if (!this.lastPickObj) { // Nothing was picked before, this means we leave the xml3d canvas
                    this.dispatchMouseEvent(this.createMouseEvent("mouseout", {
                        clientX: pos.x, clientY: pos.y, button: evt.button
                    }), this._defaultTarget);
                }
            }

            this.lastPickObj = curObj;
        }
    },

    /**
     * @param {MouseEvent} evt
     */
    mouseout: function (evt) {
        var pos = this.getMousePosition(evt);
        this.dispatchMouseEvent(evt, this.lastPickObj, pos);
    },

    /**
     * @param {MouseEvent} evt
     */
    mouseover: function (evt) {
        var doMouseMovePick = XML3D.options.getValue(OPTION_MOUSEMOVE_PICKING);
        this.dispatchMouseEventOnPickedObject(evt, {omitUpdate: !doMouseMovePick});
    },

    /**
     * @param {MouseEvent} evt
     */
    mousewheel: function (evt) {
        // note: mousewheel type is not W3C standard, used in WebKit!
        this.dispatchMouseEventOnPickedObject(evt);
    }

};

module.exports = {
    EVENTS: EVENTS, MouseEventHandler: MouseEventHandler
};
<commit_msg>Started mousefix<commit_after>var OPTION_MOUSEMOVE_PICKING = "renderer-mousemove-picking";
var OPTION_MOVEMENT_AWARE_CLICK_HANDLER = "renderer-movement-aware-click-handler";
XML3D.options.register(OPTION_MOUSEMOVE_PICKING, true);
XML3D.options.register(OPTION_MOVEMENT_AWARE_CLICK_HANDLER, false);

var EVENTS = ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "wheel"];

/**
 *
 * @param {Element} defaultTarget
 * @param {AbstractCanvasHandler} canvasHandler
 * @constructor
 */
var MouseEventHandler = function(defaultTarget, canvasHandler) {
    this._defaultTarget = defaultTarget;
    this._canvasHandler = canvasHandler;
    this._lastMousePosition =  {x: 0, y: 0};
};

MouseEventHandler.prototype =  {

    /**
     * @param {MouseEvent} event  The original event
     * @param {Element} target  target to dispatch on
     * @param {object?}     opt    Options
     */
    dispatchMouseEvent: function (event, target, opt) {
        opt = opt || {};
        target = target || this._defaultTarget;
        var x = opt.x !== undefined ? opt.x : event.clientX;
        var y = opt.y !== undefined ? opt.y : event.clientY;
        var noCopy = opt.noCopy || false;
        // Copy event to avoid DOM dispatch errors (cannot dispatch event more
        // than once)
        if (!noCopy) {
            event = this.copyMouseEvent(event);
        }
        this.initExtendedMouseEvent(event, x, y);

        target.dispatchEvent(event);
    },

    /**
     * @param {MouseEvent|WheelEvent} event the event to copy
     * @return {MouseEvent} the new event
     */
    copyMouseEvent: function (event) {
        var isWheel = event instanceof WheelEvent;
        event = isWheel = new WheelEvent(dict)
        var mouseEventInit = {
                screenX : event.screenX,
               screenY : event.screenY,
               clientX : event.clientX,
               clientY : event.clientY,
              button = button.;
      buttons = 0;
       relatedTarget = null;
        }
        console.log("MouseEvent:", event instanceof MouseEvent)
        console.log("WheelEvent:", event instanceof WheelEvent, event)
        var evt = document.createEvent("MouseEvents");
        evt.initMouseEvent(event.type, // canBubble, cancelable, view, detail
            event.bubbles, event.cancelable, event.view, event.detail, // screenX, screenY, clientX, clientY
            event.screenX, event.screenY, event.clientX, event.clientY, // ctrl, alt, shift, meta, button
            event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, event.button, // relatedTarget
            event.relatedTarget);
        if (event.dataTransfer)
            evt.data = {url: event.dataTransfer.getData("URL"), text: event.dataTransfer.getData("Text")};
        // override preventDefault to actually prevent the default of the original event
        evt.preventDefault = function () {
            event.preventDefault();
        };
        return evt;
    },

    createMouseEvent: function (type, opts) {
        opts = opts || {};
        var event = document.createEvent("MouseEvents");
        event.initMouseEvent(type, opts.canBubble !== undefined ? opts.canBubble : true, opts.cancelable !== undefined ? opts.cancelable : true, opts.view || window, opts.detail != undefined ? opts.detail : 0, opts.screenX != undefined ? opts.screenX : 0, opts.screenY != undefined ? opts.screenY : 0, opts.clientX != undefined ? opts.clientX : 0, opts.clientY != undefined ? opts.clientY : 0, opts.ctrl != undefined ? opts.ctrl : false, opts.alt != undefined ? opts.alt : false, opts.shift != undefined ? opts.shift : false, opts.meta != undefined ? opts.meta : false, opts.button != undefined ? opts.button : 0, opts.relatedTarget);
        return event;
    },

    /**
     * Adds position and normal attributes to the given event.
     *
     * @param {Event} event
     * @param {number} x
     * @param {number} y
     * @return {XML3DVec3}
     */
    initExtendedMouseEvent: function (event, x, y) {
        var handler = this._canvasHandler;

        (function () {
            var cachedPosition = undefined;
            var cachedNormal = undefined;

            event.__defineGetter__("normal", function () {
                if (cachedNormal !== undefined) return cachedNormal;
                var norm = (handler.getWorldSpaceNormalByPoint(x, y));
                cachedNormal = norm ? new window.XML3DVec3(norm[0], norm[1], norm[2]) : null;
                return cachedNormal;
            });
            event.__defineGetter__("position", function () {
                if (!cachedPosition) {
                    var pos = handler.getWorldSpacePositionByPoint(x, y);
                    cachedPosition = pos ? new window.XML3DVec3(pos[0], pos[1], pos[2]) : null;
                }
                return cachedPosition;
            });

        })();

    },

    /**
     * @param {MouseEvent} evt
     * @param {object?} opt
     */
    dispatchMouseEventOnPickedObject: function (evt, opt) {
        opt = opt || {};
        var pos = this.getMousePosition(evt);

        var picked = null;
        if (!opt.omitUpdate)
            picked = this._canvasHandler.getPickObjectByPoint(pos.x, pos.y);

        this.dispatchMouseEvent(evt, picked && picked.node, pos);
    },

    getMousePosition: function (evt) {
        return this._canvasHandler.getMousePosition(evt)
    },

    /**
     * @param {MouseEvent} evt
     */
    mouseup: function (evt) {
        this.dispatchMouseEventOnPickedObject(evt);
    },

    /**
     * @param {MouseEvent} evt
     */
    mousedown: function (evt) {
        this._lastMousePosition = this.getMousePosition(evt);
        this.dispatchMouseEventOnPickedObject(evt);
    },

    /**
     * @param {MouseEvent} evt
     */
    click: function (evt) {
        if (XML3D.options.getValue("renderer-movement-aware-click-handler") === true) {
            var pos = this.getMousePosition(evt);
            if (Math.abs(pos.x - this._lastMousePosition.x) > 4 || Math.abs(pos.y - this._lastMousePosition.y) > 4)
                return;
        }
        this.dispatchMouseEventOnPickedObject(evt);
    },

    /**
     * @param {MouseEvent} evt
     */
    dblclick: function (evt) {
        this.dispatchMouseEventOnPickedObject(evt);
    },

    /**
     * This method is called each time a mouseMove event is triggered on the
     * canvas.
     *
     * This method also triggers mouseover and mouseout events of objects in the
     * scene.
     *
     * @param {MouseEvent} evt
     */
    mousemove: function (evt) {
        var pos = this.getMousePosition(evt);

        var doMouseMovePick = XML3D.options.getValue(OPTION_MOUSEMOVE_PICKING);

        this.dispatchMouseEventOnPickedObject(evt, {omitUpdate: !doMouseMovePick});
        if (!doMouseMovePick)
            return;

        var curObj = this._canvasHandler.getPickedObject();

        // trigger mouseover and mouseout
        if (curObj !== this.lastPickObj) {
            if (this.lastPickObj) {
                // The mouse has left the last object
                this.dispatchMouseEvent(this.createMouseEvent("mouseout", {
                    clientX: pos.x, clientY: pos.y, button: evt.button
                }), this.lastPickObj);
                if (!curObj) { // Nothing picked, this means we enter the xml3d canvas
                    this.dispatchMouseEvent(this.createMouseEvent("mouseover", {
                        clientX: pos.x, clientY: pos.y, button: evt.button
                    }), this._defaultTarget);
                }
            }
            if (curObj) {
                // The mouse is now over a different object, so call the new
                // object's mouseover method
                this.dispatchMouseEvent(this.createMouseEvent("mouseover", {
                    clientX: pos.x, clientY: pos.y, button: evt.button
                }), curObj);
                if (!this.lastPickObj) { // Nothing was picked before, this means we leave the xml3d canvas
                    this.dispatchMouseEvent(this.createMouseEvent("mouseout", {
                        clientX: pos.x, clientY: pos.y, button: evt.button
                    }), this._defaultTarget);
                }
            }

            this.lastPickObj = curObj;
        }
    },

    /**
     * @param {MouseEvent} evt
     */
    mouseout: function (evt) {
        var pos = this.getMousePosition(evt);
        this.dispatchMouseEvent(evt, this.lastPickObj, pos);
    },

    /**
     * @param {MouseEvent} evt
     */
    mouseover: function (evt) {
        var doMouseMovePick = XML3D.options.getValue(OPTION_MOUSEMOVE_PICKING);
        this.dispatchMouseEventOnPickedObject(evt, {omitUpdate: !doMouseMovePick});
    },

    /**
     * @param {WheelEvent} evt
     */
    wheel: function (evt) {
        this.dispatchMouseEventOnPickedObject(evt, { type: "wheel" });
    }

};

module.exports = {
    EVENTS: EVENTS, MouseEventHandler: MouseEventHandler
};
<|endoftext|>


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

import { FrontSide, BackSide, DoubleSide, RGBAFormat, NearestFilter, PCFShadowMap, RGBADepthPacking, NoBlending } from '../../constants.js';
import { WebGLRenderTarget } from '../WebGLRenderTarget.js';
import { MeshDepthMaterial } from '../../materials/MeshDepthMaterial.js';
import { MeshDistanceMaterial } from '../../materials/MeshDistanceMaterial.js';
import { Vector4 } from '../../math/Vector4.js';
import { Vector3 } from '../../math/Vector3.js';
import { Vector2 } from '../../math/Vector2.js';
import { Matrix4 } from '../../math/Matrix4.js';
import { Frustum } from '../../math/Frustum.js';

function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {

	var _frustum = new Frustum(),
		_projScreenMatrix = new Matrix4(),

		_shadowMapSize = new Vector2(),
		_maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ),

		_lookTarget = new Vector3(),
		_lightPositionWorld = new Vector3(),

		_MorphingFlag = 1,
		_SkinningFlag = 2,

		_NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,

		_depthMaterials = new Array( _NumberOfMaterialVariants ),
		_distanceMaterials = new Array( _NumberOfMaterialVariants ),

		_materialCache = {};

	var shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };

	var cubeDirections = [
		new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
		new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
	];

	var cubeUps = [
		new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
		new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ),	new Vector3( 0, 0, - 1 )
	];

	var cube2DViewPorts = [
		new Vector4(), new Vector4(), new Vector4(),
		new Vector4(), new Vector4(), new Vector4()
	];

	// init

	for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {

		var useMorphing = ( i & _MorphingFlag ) !== 0;
		var useSkinning = ( i & _SkinningFlag ) !== 0;

		var depthMaterial = new MeshDepthMaterial( {

			depthPacking: RGBADepthPacking,

			morphTargets: useMorphing,
			skinning: useSkinning

		} );

		_depthMaterials[ i ] = depthMaterial;

		//

		var distanceMaterial = new MeshDistanceMaterial( {

			morphTargets: useMorphing,
			skinning: useSkinning

		} );

		_distanceMaterials[ i ] = distanceMaterial;

	}

	//

	var scope = this;

	this.enabled = false;

	this.autoUpdate = true;
	this.needsUpdate = false;

	this.type = PCFShadowMap;

	this.render = function ( lights, scene, camera ) {

		if ( scope.enabled === false ) return;
		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;

		if ( lights.length === 0 ) return;

		var currentRenderTarget = _renderer.getRenderTarget();

		var _state = _renderer.state;

		// Set GL state for depth map.
		_state.setBlending( NoBlending );
		_state.buffers.color.setClear( 1, 1, 1, 1 );
		_state.buffers.depth.setTest( true );
		_state.setScissorTest( false );

		// render depth map

		var faceCount;

		for ( var i = 0, il = lights.length; i < il; i ++ ) {

			var light = lights[ i ];
			var shadow = light.shadow;
			var isPointLight = light && light.isPointLight;

			if ( shadow === undefined ) {

				console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
				continue;

			}

			var shadowCamera = shadow.camera;

			_shadowMapSize.copy( shadow.mapSize );
			_shadowMapSize.min( _maxShadowMapSize );

			if ( isPointLight ) {

				var vpWidth = _shadowMapSize.x;
				var vpHeight = _shadowMapSize.y;

				// These viewports map a cube-map onto a 2D texture with the
				// following orientation:
				//
				//  xzXZ
				//   y Y
				//
				// X - Positive x direction
				// x - Negative x direction
				// Y - Positive y direction
				// y - Negative y direction
				// Z - Positive z direction
				// z - Negative z direction

				// positive X
				cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
				// negative X
				cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
				// positive Z
				cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
				// negative Z
				cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
				// positive Y
				cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
				// negative Y
				cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );

				_shadowMapSize.x *= 4.0;
				_shadowMapSize.y *= 2.0;

			}

			if ( shadow.map === null ) {

				var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };

				shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
				shadow.map.texture.name = light.name + ".shadowMap";

				shadowCamera.updateProjectionMatrix();

			}

			if ( shadow.isSpotLightShadow ) {

				shadow.update( light );

			}

			var shadowMap = shadow.map;
			var shadowMatrix = shadow.matrix;

			_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
			shadowCamera.position.copy( _lightPositionWorld );

			if ( isPointLight ) {

				faceCount = 6;

				// for point lights we set the shadow matrix to be a translation-only matrix
				// equal to inverse of the light's position

				shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );

			} else {

				faceCount = 1;

				_lookTarget.setFromMatrixPosition( light.target.matrixWorld );
				shadowCamera.lookAt( _lookTarget );
				shadowCamera.updateMatrixWorld();

				// compute shadow matrix

				shadowMatrix.set(
					0.5, 0.0, 0.0, 0.5,
					0.0, 0.5, 0.0, 0.5,
					0.0, 0.0, 0.5, 0.5,
					0.0, 0.0, 0.0, 1.0
				);

				shadowMatrix.multiply( shadowCamera.projectionMatrix );
				shadowMatrix.multiply( shadowCamera.matrixWorldInverse );

			}

			_renderer.setRenderTarget( shadowMap );
			_renderer.clear();

			// render shadow map for each cube face (if omni-directional) or
			// run a single pass if not

			for ( var face = 0; face < faceCount; face ++ ) {

				if ( isPointLight ) {

					_lookTarget.copy( shadowCamera.position );
					_lookTarget.add( cubeDirections[ face ] );
					shadowCamera.up.copy( cubeUps[ face ] );
					shadowCamera.lookAt( _lookTarget );
					shadowCamera.updateMatrixWorld();

					var vpDimensions = cube2DViewPorts[ face ];
					_state.viewport( vpDimensions );

				}

				// update camera matrices and frustum

				_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
				_frustum.setFromMatrix( _projScreenMatrix );

				// set object matrices & frustum culling

				renderObject( scene, camera, shadowCamera, isPointLight );

			}

		}

		scope.needsUpdate = false;

		_renderer.setRenderTarget( currentRenderTarget );

	};

	function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) {

		var geometry = object.geometry;

		var result = null;

		var materialVariants = _depthMaterials;
		var customMaterial = object.customDepthMaterial;

		if ( isPointLight ) {

			materialVariants = _distanceMaterials;
			customMaterial = object.customDistanceMaterial;

		}

		if ( ! customMaterial ) {

			var useMorphing = false;

			if ( material.morphTargets ) {

				if ( geometry && geometry.isBufferGeometry ) {

					useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;

				} else if ( geometry && geometry.isGeometry ) {

					useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;

				}

			}

			if ( object.isSkinnedMesh && material.skinning === false ) {

				console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );

			}

			var useSkinning = object.isSkinnedMesh && material.skinning;

			var variantIndex = 0;

			if ( useMorphing ) variantIndex |= _MorphingFlag;
			if ( useSkinning ) variantIndex |= _SkinningFlag;

			result = materialVariants[ variantIndex ];

		} else {

			result = customMaterial;

		}

		if ( _renderer.localClippingEnabled &&
				material.clipShadows === true &&
				material.clippingPlanes.length !== 0 ) {

			// in this case we need a unique material instance reflecting the
			// appropriate state

			var keyA = result.uuid, keyB = material.uuid;

			var materialsForVariant = _materialCache[ keyA ];

			if ( materialsForVariant === undefined ) {

				materialsForVariant = {};
				_materialCache[ keyA ] = materialsForVariant;

			}

			var cachedMaterial = materialsForVariant[ keyB ];

			if ( cachedMaterial === undefined ) {

				cachedMaterial = result.clone();
				materialsForVariant[ keyB ] = cachedMaterial;

			}

			result = cachedMaterial;

		}

		result.visible = material.visible;
		result.wireframe = material.wireframe;

		result.side = ( material.shadowSide != null ) ? material.shadowSide : shadowSide[ material.side ];

		result.clipShadows = material.clipShadows;
		result.clippingPlanes = material.clippingPlanes;
		result.clipIntersection = material.clipIntersection;

		result.wireframeLinewidth = material.wireframeLinewidth;
		result.linewidth = material.linewidth;

		if ( isPointLight && result.isMeshDistanceMaterial ) {

			result.referencePosition.copy( lightPositionWorld );
			result.nearDistance = shadowCameraNear;
			result.farDistance = shadowCameraFar;

		}

		return result;

	}

	function renderObject( object, camera, shadowCamera, isPointLight ) {

		if ( object.visible === false ) return;

		var visible = object.layers.test( camera.layers );

		if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {

			if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {

				object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );

				var geometry = _objects.update( object );
				var material = object.material;

				if ( Array.isArray( material ) ) {

					var groups = geometry.groups;

					for ( var k = 0, kl = groups.length; k < kl; k ++ ) {

						var group = groups[ k ];
						var groupMaterial = material[ group.materialIndex ];

						if ( groupMaterial && groupMaterial.visible ) {

							var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
							_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );

						}

					}

				} else if ( material.visible ) {

					var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
					_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );

				}

			}

		}

		var children = object.children;

		for ( var i = 0, l = children.length; i < l; i ++ ) {

			renderObject( children[ i ], camera, shadowCamera, isPointLight );

		}

	}

}

export { WebGLShadowMap };
<commit_msg>Fix: wrong face cull for shadows of freshly inserted mirrored objects.<commit_after>/**
 * @author alteredq / http://alteredqualia.com/
 * @author mrdoob / http://mrdoob.com/
 */

import { FrontSide, BackSide, DoubleSide, RGBAFormat, NearestFilter, PCFShadowMap, RGBADepthPacking, NoBlending } from '../../constants.js';
import { WebGLRenderTarget } from '../WebGLRenderTarget.js';
import { MeshDepthMaterial } from '../../materials/MeshDepthMaterial.js';
import { MeshDistanceMaterial } from '../../materials/MeshDistanceMaterial.js';
import { Vector4 } from '../../math/Vector4.js';
import { Vector3 } from '../../math/Vector3.js';
import { Vector2 } from '../../math/Vector2.js';
import { Matrix4 } from '../../math/Matrix4.js';
import { Frustum } from '../../math/Frustum.js';

function WebGLShadowMap( _renderer, _objects, maxTextureSize ) {

	var _frustum = new Frustum(),
		_projScreenMatrix = new Matrix4(),

		_shadowMapSize = new Vector2(),
		_maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ),

		_lookTarget = new Vector3(),
		_lightPositionWorld = new Vector3(),

		_MorphingFlag = 1,
		_SkinningFlag = 2,

		_NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,

		_depthMaterials = new Array( _NumberOfMaterialVariants ),
		_distanceMaterials = new Array( _NumberOfMaterialVariants ),

		_materialCache = {};

	var shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };

	var cubeDirections = [
		new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
		new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
	];

	var cubeUps = [
		new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
		new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ),	new Vector3( 0, 0, - 1 )
	];

	var cube2DViewPorts = [
		new Vector4(), new Vector4(), new Vector4(),
		new Vector4(), new Vector4(), new Vector4()
	];

	// init

	for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) {

		var useMorphing = ( i & _MorphingFlag ) !== 0;
		var useSkinning = ( i & _SkinningFlag ) !== 0;

		var depthMaterial = new MeshDepthMaterial( {

			depthPacking: RGBADepthPacking,

			morphTargets: useMorphing,
			skinning: useSkinning

		} );

		_depthMaterials[ i ] = depthMaterial;

		//

		var distanceMaterial = new MeshDistanceMaterial( {

			morphTargets: useMorphing,
			skinning: useSkinning

		} );

		_distanceMaterials[ i ] = distanceMaterial;

	}

	//

	var scope = this;

	this.enabled = false;

	this.autoUpdate = true;
	this.needsUpdate = false;

	this.type = PCFShadowMap;

	this.render = function ( lights, scene, camera ) {

		if ( scope.enabled === false ) return;
		if ( scope.autoUpdate === false && scope.needsUpdate === false ) return;

		if ( lights.length === 0 ) return;

		var currentRenderTarget = _renderer.getRenderTarget();

		var _state = _renderer.state;

		// Set GL state for depth map.
		_state.setBlending( NoBlending );
		_state.buffers.color.setClear( 1, 1, 1, 1 );
		_state.buffers.depth.setTest( true );
		_state.setScissorTest( false );

		// render depth map

		var faceCount;

		for ( var i = 0, il = lights.length; i < il; i ++ ) {

			var light = lights[ i ];
			var shadow = light.shadow;
			var isPointLight = light && light.isPointLight;

			if ( shadow === undefined ) {

				console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );
				continue;

			}

			var shadowCamera = shadow.camera;

			_shadowMapSize.copy( shadow.mapSize );
			_shadowMapSize.min( _maxShadowMapSize );

			if ( isPointLight ) {

				var vpWidth = _shadowMapSize.x;
				var vpHeight = _shadowMapSize.y;

				// These viewports map a cube-map onto a 2D texture with the
				// following orientation:
				//
				//  xzXZ
				//   y Y
				//
				// X - Positive x direction
				// x - Negative x direction
				// Y - Positive y direction
				// y - Negative y direction
				// Z - Positive z direction
				// z - Negative z direction

				// positive X
				cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight );
				// negative X
				cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight );
				// positive Z
				cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight );
				// negative Z
				cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight );
				// positive Y
				cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight );
				// negative Y
				cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight );

				_shadowMapSize.x *= 4.0;
				_shadowMapSize.y *= 2.0;

			}

			if ( shadow.map === null ) {

				var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };

				shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
				shadow.map.texture.name = light.name + ".shadowMap";

				shadowCamera.updateProjectionMatrix();

			}

			if ( shadow.isSpotLightShadow ) {

				shadow.update( light );

			}

			var shadowMap = shadow.map;
			var shadowMatrix = shadow.matrix;

			_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
			shadowCamera.position.copy( _lightPositionWorld );

			if ( isPointLight ) {

				faceCount = 6;

				// for point lights we set the shadow matrix to be a translation-only matrix
				// equal to inverse of the light's position

				shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );

			} else {

				faceCount = 1;

				_lookTarget.setFromMatrixPosition( light.target.matrixWorld );
				shadowCamera.lookAt( _lookTarget );
				shadowCamera.updateMatrixWorld();

				// compute shadow matrix

				shadowMatrix.set(
					0.5, 0.0, 0.0, 0.5,
					0.0, 0.5, 0.0, 0.5,
					0.0, 0.0, 0.5, 0.5,
					0.0, 0.0, 0.0, 1.0
				);

				shadowMatrix.multiply( shadowCamera.projectionMatrix );
				shadowMatrix.multiply( shadowCamera.matrixWorldInverse );

			}

			_renderer.setRenderTarget( shadowMap );
			_renderer.clear();

			// render shadow map for each cube face (if omni-directional) or
			// run a single pass if not

			for ( var face = 0; face < faceCount; face ++ ) {

				if ( isPointLight ) {

					_lookTarget.copy( shadowCamera.position );
					_lookTarget.add( cubeDirections[ face ] );
					shadowCamera.up.copy( cubeUps[ face ] );
					shadowCamera.lookAt( _lookTarget );
					shadowCamera.updateMatrixWorld();

					var vpDimensions = cube2DViewPorts[ face ];
					_state.viewport( vpDimensions );

				}

				// update camera matrices and frustum

				_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
				_frustum.setFromMatrix( _projScreenMatrix );

				// set object matrices & frustum culling

				renderObject( scene, camera, shadowCamera, isPointLight );

			}

		}

		scope.needsUpdate = false;

		_renderer.setRenderTarget( currentRenderTarget );

	};

	function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) {

		var geometry = object.geometry;

		var result = null;

		var materialVariants = _depthMaterials;
		var customMaterial = object.customDepthMaterial;

		if ( isPointLight ) {

			materialVariants = _distanceMaterials;
			customMaterial = object.customDistanceMaterial;

		}

		if ( ! customMaterial ) {

			var useMorphing = false;

			if ( material.morphTargets ) {

				if ( geometry && geometry.isBufferGeometry ) {

					useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;

				} else if ( geometry && geometry.isGeometry ) {

					useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;

				}

			}

			if ( object.isSkinnedMesh && material.skinning === false ) {

				console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );

			}

			var useSkinning = object.isSkinnedMesh && material.skinning;

			var variantIndex = 0;

			if ( useMorphing ) variantIndex |= _MorphingFlag;
			if ( useSkinning ) variantIndex |= _SkinningFlag;

			result = materialVariants[ variantIndex ];

		} else {

			result = customMaterial;

		}

		if ( _renderer.localClippingEnabled &&
				material.clipShadows === true &&
				material.clippingPlanes.length !== 0 ) {

			// in this case we need a unique material instance reflecting the
			// appropriate state

			var keyA = result.uuid, keyB = material.uuid;

			var materialsForVariant = _materialCache[ keyA ];

			if ( materialsForVariant === undefined ) {

				materialsForVariant = {};
				_materialCache[ keyA ] = materialsForVariant;

			}

			var cachedMaterial = materialsForVariant[ keyB ];

			if ( cachedMaterial === undefined ) {

				cachedMaterial = result.clone();
				materialsForVariant[ keyB ] = cachedMaterial;

			}

			result = cachedMaterial;

		}

		result.visible = material.visible;
		result.wireframe = material.wireframe;

		result.side = ( material.shadowSide != null ) ? material.shadowSide : shadowSide[ material.side ];

		result.clipShadows = material.clipShadows;
		result.clippingPlanes = material.clippingPlanes;
		result.clipIntersection = material.clipIntersection;

		result.wireframeLinewidth = material.wireframeLinewidth;
		result.linewidth = material.linewidth;

		if ( isPointLight && result.isMeshDistanceMaterial ) {

			result.referencePosition.copy( lightPositionWorld );
			result.nearDistance = shadowCameraNear;
			result.farDistance = shadowCameraFar;

		}

		return result;

	}

	function renderObject( object, camera, shadowCamera, isPointLight ) {

		if ( object.visible === false ) return;

		var visible = object.layers.test( camera.layers );

		if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {

			if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {

				object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
				object.normalMatrix.getNormalMatrix( object.modelViewMatrix );

				var geometry = _objects.update( object );
				var material = object.material;

				if ( Array.isArray( material ) ) {

					var groups = geometry.groups;

					for ( var k = 0, kl = groups.length; k < kl; k ++ ) {

						var group = groups[ k ];
						var groupMaterial = material[ group.materialIndex ];

						if ( groupMaterial && groupMaterial.visible ) {

							var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
							_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );

						}

					}

				} else if ( material.visible ) {

					var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far );
					_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );

				}

			}

		}

		var children = object.children;

		for ( var i = 0, l = children.length; i < l; i ++ ) {

			renderObject( children[ i ], camera, shadowCamera, isPointLight );

		}

	}

}

export { WebGLShadowMap };
<|endoftext|>


<commit_before>'use strict';

var async = require('async');
var got = require('got');
var cheerio = require('cheerio');

var common = require('../../common');

// turn js files in parsers/ to method of this object
var requireDir = require('require-dir');
var parsers = requireDir('./parsers');

module.exports = () => {

	var gotOptions = { headers: { 'user-agent': `SmonalimBot/0.0 (+http://smolan.im)` } };

	return new Promise((resolve, reject) => {
		getTasks().then(executeTasks).then(resolve, reject);
	});

	function getTasks(){
		return new Promise((resolve, reject) => {

			// turn parsers into tasks
			let tasks = [];
			for (let key in parsers){
				tasks.push(taskedParser(key));
			}

			resolve(tasks);

		});
	}

	function taskedParser(name){

		var parser = parsers[name];

		return done => {

			got(parser.headlinesSourceUrl, gotOptions)
				.then(parser)
				.then(parseIntoEach)
				.then(
					headlines => done(null, headlines),
					err => done(err)
			);

			function parseIntoEach(headlines){
				return Promise.all(headlines.map(populateDescription));
			}

			function populateDescription(headline){
				return new Promise((resolve, reject) => {

					got(headline.url, gotOptions, (err, resBody) => {
						if (err) return reject(err);

						var desc, $ = cheerio.load(resBody);

						if (parser.description.transform){
							desc = parser.description.transform($(parser.description.selector));

						} else {
							desc = $(parser.description.selector).text();
						}

						desc = desc.trim();

						// ensure a dot at the end of descrpition paragraph
						if (desc.charAt(desc.length-1) !== '.') desc += '.';

						// attach to headline object
						headline.description = desc;

						resolve(headline);
					});

				});
			}

		};
	}

	function executeTasks(tasks){
		return new Promise((resolve, reject) => {

			// scrap every site in parallel, parsing it with
			async.parallel(tasks, (err, arrays) => {
				if (err) return reject(err);

				//-=======================================================---
				//------------------ Flatten Arrays
				//-=======================================================---

				let results = [];

				// go through every magazine
				arrays.forEach(arr => {

					// go through every headline
					arr.forEach(item => {

						for (let key in item){
							if (!item[key]) return console.error(`Bad property ${key}`, item);
						}

						results.push(item);
					});
				});

				// output
				resolve(unique(results));
			});

			function unique(arr){

				var urls = [];
				return arr.filter(headline => {
					if (urls.indexOf(headline.url) > -1) return false;

					urls.push(headline.url);
					return true;
				});
			}

		});

	}

};<commit_msg>Fetcher: Added fallback for description parser<commit_after>'use strict';

var async = require('async');
var got = require('got');
var cheerio = require('cheerio');

var common = require('../../common');

// turn js files in parsers/ to method of this object
var requireDir = require('require-dir');
var parsers = requireDir('./parsers');

module.exports = () => {

	var gotOptions = { headers: { 'user-agent': `SmonalimBot/0.0 (+http://smolan.im)` } };

	return new Promise((resolve, reject) => {
		getTasks().then(executeTasks).then(resolve, reject);
	});

	function getTasks(){
		return new Promise((resolve, reject) => {

			// turn parsers into tasks
			let tasks = [];
			for (let key in parsers){
				tasks.push(taskedParser(key));
			}

			resolve(tasks);

		});
	}

	function taskedParser(name){

		var parser = parsers[name];

		return done => {

			got(parser.headlinesSourceUrl, gotOptions)
				.then(parser)
				.then(parseIntoEach)
				.then(
					headlines => done(null, headlines),
					err => done(err)
			);

			function parseIntoEach(headlines){
				return Promise.all(headlines.map(populateDescription));
			}

			function populateDescription(headline){
				return new Promise((resolve, reject) => {

					got(headline.url, gotOptions, (err, resBody) => {
						if (err) return reject(err);

						var desc, $ = cheerio.load(resBody);

						if (parser.description.transform){
							desc = parser.description.transform($(parser.description.selector));

						} else {
							desc = $(parser.description.selector).text();
						}

						if (desc){
							desc = desc.trim();

							// ensure a dot at the end of descrpition paragraph
							if (desc.charAt(desc.length-1) !== '.') desc += '.';

						} else {
							desc = '';
						}

						// attach to headline object
						headline.description = desc;

						resolve(headline);
					});

				});
			}

		};
	}

	function executeTasks(tasks){
		return new Promise((resolve, reject) => {

			// scrap every site in parallel, parsing it with
			async.parallel(tasks, (err, arrays) => {
				if (err) return reject(err);

				//-=======================================================---
				//------------------ Flatten Arrays
				//-=======================================================---

				let results = [];

				// go through every magazine
				arrays.forEach(arr => {

					// go through every headline
					arr.forEach(item => {

						for (let key in item){
							if (!item[key]) return console.error(`Bad property ${key}`, item);
						}

						results.push(item);
					});
				});

				// output
				resolve(unique(results));
			});

			function unique(arr){

				var urls = [];
				return arr.filter(headline => {
					if (urls.indexOf(headline.url) > -1) return false;

					urls.push(headline.url);
					return true;
				});
			}

		});

	}

};<|endoftext|>


<commit_before>module.exports = function (loaders) {
  return Object.keys(loaders).reduce(function (depLoaders, loader) {

    if (loader === 'babel') {
      depLoaders['babel-loader'] = '6.2.4';
      if (loaders[loader].es2015) {
        depLoaders['babel-preset-es2015'] = '6.6.0';
      }
      if (loaders[loader].react) {
        depLoaders['babel-preset-react'] = '6.5.0';
      }
      if (loaders[loader].stage0) {
        depLoaders['babel-preset-stage-0'] = '6.5.0';
      }
      if (loaders[loader].jsx) {
        depLoaders['babel-plugin-transform-react-jsx'] = '6.6.5';
      }
    }

    if (loader === 'css') {
      depLoaders['css-loader'] = '0.23.1';
    }

    if (loader === 'css' && loaders[loader].less) {
      depLoaders['less-loader'] = '2.2.2';
    }

    if (loader === 'css' && loaders[loader].sass) {
      depLoaders['sass-loader'] = '3.2.0';
    }

    if (loader === 'typescript') {
      depLoaders['ts-loader'] = '0.8.1';
      depLoaders['typescript'] = '1.8.9';
    }

    if (loader === 'coffeescript') {
      depLoaders['coffee-loader'] = '0.7.2';
    }

    if (loader === 'raw') {
      depLoaders['raw-loader'] = '0.5.1';
    }

    if (loader === 'json') {
      depLoaders['json-loader'] = '0.5.4';
    }

    if (loader === 'jade') {
      depLoaders['jade'] = '1.11.0';
      depLoaders['jade-loader'] = '0.8.0';
    }

    if (loader === 'handlebars') {
      depLoaders['handlebars'] = '4.0.5';
      depLoaders['handlebars-loader'] = '1.2.0';
    }

    if (loader === 'vue') {
      depLoaders['vue-loader'] = '8.2.1';
    }

  }, {});
};
<commit_msg>Fixed bug with attaching loaders to project zip<commit_after>module.exports = function (loaders) {
  return Object.keys(loaders).reduce(function (depLoaders, loader) {

    if (loader === 'babel') {
      depLoaders['babel-loader'] = '6.2.4';
      if (loaders[loader].es2015) {
        depLoaders['babel-preset-es2015'] = '6.6.0';
      }
      if (loaders[loader].react) {
        depLoaders['babel-preset-react'] = '6.5.0';
      }
      if (loaders[loader].stage0) {
        depLoaders['babel-preset-stage-0'] = '6.5.0';
      }
      if (loaders[loader].jsx) {
        depLoaders['babel-plugin-transform-react-jsx'] = '6.6.5';
      }
    }

    if (loader === 'css') {
      depLoaders['css-loader'] = '0.23.1';
    }

    if (loader === 'css' && loaders[loader].less) {
      depLoaders['less-loader'] = '2.2.2';
    }

    if (loader === 'css' && loaders[loader].sass) {
      depLoaders['sass-loader'] = '3.2.0';
    }

    if (loader === 'typescript') {
      depLoaders['ts-loader'] = '0.8.1';
      depLoaders['typescript'] = '1.8.9';
    }

    if (loader === 'coffeescript') {
      depLoaders['coffee-loader'] = '0.7.2';
    }

    if (loader === 'raw') {
      depLoaders['raw-loader'] = '0.5.1';
    }

    if (loader === 'json') {
      depLoaders['json-loader'] = '0.5.4';
    }

    if (loader === 'jade') {
      depLoaders['jade'] = '1.11.0';
      depLoaders['jade-loader'] = '0.8.0';
    }

    if (loader === 'handlebars') {
      depLoaders['handlebars'] = '4.0.5';
      depLoaders['handlebars-loader'] = '1.2.0';
    }

    if (loader === 'vue') {
      depLoaders['vue-loader'] = '8.2.1';
    }

    return depLoaders;

  }, {});
};
<|endoftext|>


<commit_before>'use strict';
/**
 * You know about the robot,
 * but make no assumptions about a `message`
 */

var Support = {},
    Queue,
    templates = require('./spotifyTemplates'),
    trackUriRE = /^spotify:track:[a-z\d]+$/i,
    currentResultReferenceRE = /^\[?(#|:)?(\d+)\]?$/,
    specificResultReferenceRE = /^\[?(\d+)\]?\[?(#|:)(\d+)\]?/,
    MetaData,
    manager,
    robot,
    url;
var $ = require('jquery');

function spotRequest(path, method, params, callback) {
    console.log('SPOT:' + method, url + path, params);
    robot.http(url + path).query(params)[method]()(callback);
}

function getCurrentTrackUri (callback) {
    spotRequest('/currently-playing', 'get', {}, function (err, res, body) {
        var uri;
        if (!err) {
            uri = String(body).replace(/^\s+/, '').replace(/\s+$/, '');
        }
        callback(err, uri);
    });
}

function determineTemplate (type) {
    switch (type) {
        case manager.types.ALBUMS:
            return templates.albumsLines;
        case manager.types.ARTISTS:
            return templates.artistsLines;
    }
    return templates.tracksLines;
}

function resultToString (data, type, userId, template) {
    var index = manager.persist(data, type, userId);
    return [templates.resultNumber(index), template(data)].join("\n");
}

function getDataHandler (userId, type, callback) {
    var rawTemplate = determineTemplate(type),
        template = function (data) {
            return rawTemplate(data, true);
        };
    return function handleData (err, data) {
        if (err) {
            callback(err);
            return;
        }
        callback(err, resultToString(data, type, userId, template));
    };
}

Support.isPlaying = function () {
    return Queue.somethingIsPlaying();
};

Support.purgeLists = function () {
    manager.purge();
};

Support.purgeMusicDataCache = function () {
    MetaData.clearCache();
};

function getInflatedAlbumHandler(callback, userId) {
    return function handleInflatedAlbum (err, album) {
        var index, tracks;
        if (!err) {
            tracks = album.getTracks();
            if (tracks.length) {
                index = manager.persist(tracks, manager.types.TRACKS, userId);
            }
        }
        callback(err, album, index);
    }
}

Support.translateToAlbum = function (str, userId, callback) {
    var resultNum, listItem, results,
        data, album, metaData, track,
        inflatedAlbumHandler = getInflatedAlbumHandler(callback, userId);
    if (str.match(currentResultReferenceRE)) {
        listItem = RegExp.$2;
        metaData = manager.getRelevantMetaData(void 0, userId, listItem);
        if (!metaData) {
            callback('Nothing found matching ' + str);
            return;
        }
        if (metaData.type === manager.types.ARTISTS) {
            callback('That\'s an artist list; use a track or album list');
            return;
        }
        if (metaData.type === manager.types.TRACKS) {
            track = new MetaData.Track(manager.getResult(metaData.index)[listItem]);
            track.getInflatedAlbum(inflatedAlbumHandler);
            return;
        }
        album = new MetaData.Album(manager.getResult(metaData.index)[listItem]);
        album.inflateTracks(inflatedAlbumHandler);
        return;
    }
    if (str.match(specificResultReferenceRE)) {
        resultNum = RegExp.$1;
        listItem = RegExp.$3;
        data = manager.getResultMetaData(resultNum);
        if (data.type === manager.types.ARTISTS) {
            callback('That\'s an artist list; use a track or album list');
            return;
        }
        results = manager.getResult(resultNum);
        if (!results || !results[listItem]) {
            callback('Item ' + listItem + ' not found for Result #' + resultNum);
            return;
        }
        if (data.type === manager.types.TRACKS) {
            track = new MetaData.Track(results[listItem]);
            track.getInflatedAlbum(inflatedAlbumHandler);
            return;
        }
        album = new MetaData.Album(results[listItem]);
        album.inflateTracks(inflatedAlbumHandler);
        return;
    }
    MetaData.findAlbums(str, 1, function (err, data) {
        if (err) {
            callback(err);
            return;
        }
        album = new MetaData.Album(data[0]);
        album.inflateTracks(inflatedAlbumHandler);
    });
};

Support.translateToTrack = function (str, userId, callback) {
    var resultNum, listItem, results, data;
    if (str.match(/\s*this\s*(track)?\s*$/)) {
        Support.getCurrentTrack(callback);
        return;
    }
    if (str.match(currentResultReferenceRE)) {
        listItem = RegExp.$2;
        results = manager.getRelevantResult(manager.types.TRACKS, userId, listItem);
        if (!results || !results.length) {
            callback('Nothing found matching ' + str);
            return;
        }
        callback(null, new MetaData.Track(results[listItem]));
        return;
    }
    if (str.match(specificResultReferenceRE)) {
        resultNum = RegExp.$1;
        listItem = RegExp.$3;
        data = manager.getResultMetaData(resultNum);
        if (data.type !== manager.types.TRACKS) {
            callback(templates.resultNumber(resultNum) + ' is not a track result list');
            return;
        }
        results = manager.getResult(resultNum);
        if (!results || !results[listItem]) {
            callback('Item ' + listItem + ' not found for ' + templates.resultNumber(resultNum));
            return;
        }
        callback(null, new MetaData.Track(results[listItem]));
        return;
    }
    if (str.match(trackUriRE)) {
        MetaData.fetchTrack(str, function (err, Track) {
            if (err) {
                Track = new MetaData.Track({href : str});
            }
            callback(null, Track);
        });
        return;
    }
    MetaData.findTracks(str, 1, function (err, data) {
        if (err) {
            callback(err);
            return;
        }
        callback(null, new MetaData.Track(data[0]));
    });
};

Support.translateToArtist = function (str, userId, callback) {
    var resultNum, listItem, results, data, datum, artists, metaData, track;
    if (str.match(currentResultReferenceRE)) {
        listItem = RegExp.$2;
        metaData = manager.getRelevantMetaData(void 0, userId, listItem);
        if (!metaData) {
            callback('Nothing found matching ' + str);
            return;
        }
        if (metaData.type === manager.types.ARTISTS) {
            callback(null, new MetaData.Artist(manager.getResult(metaData.index)[listItem]));
            return;
        }
        if (metaData.type === manager.types.TRACKS) {
            datum = new MetaData.Track(manager.getResult(metaData.index)[listItem]);
        } else {
            datum = new MetaData.Album(manager.getResult(metaData.index)[listItem]);
        }
        artists = datum.getArtists();
        if (!artists.length) {
            callback('It doesn\'t have an artist... :S');
            return;
        }
        callback(null, new MetaData.Artist(artists[0]));
        return;
    }
    if (str.match(specificResultReferenceRE)) {
        resultNum = RegExp.$1;
        listItem = RegExp.$3;
        data = manager.getResultMetaData(resultNum);
        results = manager.getResult(resultNum);
        if (!results || !results[listItem]) {
            callback('Item ' + listItem + ' not found for ' + templates.resultNumber(resultNum));
            return;
        }
        datum = results[listItem];
        if (data.type === manager.types.ALBUMS) {
            if (!datum.getArtists) {
                datum = new MetaData.Album(datum);
            }
            artists = datum.getArtists();
            if (!artists.length) {
                callback('Album has no artists :S');
                return;
            }
            callback(null, new MetaData.Artist(artists[0]));
            return;
        }
        if (data.type === manager.types.TRACKS) {
            if (!datum.getArtists) {
                datum = new MetaData.Track(datum);
            }
            artists = datum.getArtists();
            if (!artists.length) {
                callback('Track has no artists :S');
                return;
            }
            callback(null, artists[0]);
            return;
        }
        callback(null, new MetaData.Artist(results[listItem]));
        return;
    }
    if (str.match(/\s*this artist\s*$/)) {
        Support.getCurrentArtist(callback);
        return;
    }
    MetaData.findArtists(str, 1, function (err, data) {
        if (err) {
            callback(err);
            return;
        }
        callback(null, new MetaData.Artist(data[0]));
    });
};

Support.getCurrentTrack = function (callback) {
    getCurrentTrackUri(function (err, uri) {
        if (err) {
            callback(err);
            return;
        }
        MetaData.fetchTrack(uri, callback);
    });
};

Support.getCurrentArtist = function (callback) {
    Support.getCurrentTrack(function (err, track) {
        var artists;
        if (err) {
            callback(err);
            return;
        }
        artists = track.getArtists();
        if (artists && artists.length) {
            callback(null, artists[0]);
            return;
        }
        callback('This track doesn\'t have artists...');
    });
};

Support.getCurrentAlbum = function (callback) {
    Support.getCurrentTrack(function (err, track) {
        var album;
        if (err) {
            callback(err);
            return;
        }
        track.getInflatedAlbum(callback);
    });
};

Support.debug = function () {
    return 'debug';
};

Support.playUri = function (uri, callback) {
    spotRequest('/play-uri', 'post', {'uri' : uri}, function (err, res, body) {
        callback(err, body);
    });
};

Support.playTrack = function (track, callback) {
    return Support.playUri(track.href, callback);
};

Support.findTracks = function (query, userId, limit, callback) {
    var handler = getDataHandler(userId, manager.types.TRACKS, callback),
        aQuery;
    if (query.match(/^\s*by\s+(.+)/)) {
        aQuery = RegExp.$1;
        Support.translateToArtist(aQuery, userId, function (err, artist) {
            if (err) {
                callback(err);
                return;
            }
            MetaData.findTracksByArtist(artist, limit, handler);
        });
        return;
    }
    MetaData.findTracks(query, limit, handler);
};

Support.findAlbums = function (query, userId, limit, callback) {
    var handler = getDataHandler(userId, manager.types.ALBUMS, callback);
    if (query.match(/^\s*by\s+(.+)/)) {
        Support.translateToArtist(RegExp.$1, userId, function (err, artist) {
            if (err) {
                callback(err);
                return;
            }
            artist.inflateAlbums(function (err, albums) {
                if (!err) {
                    albums = albums.slice(0, limit);
                }
                handler(err, albums);
            });
        });
        return;
    }
    MetaData.findAlbums(query, limit, handler);
};

Support.findArtists = function (query, userId, limit, callback) {
    MetaData.findArtists(query, limit, getDataHandler(userId, manager.types.ARTISTS, callback));
};

module.exports = function (Robot, URL) {
    robot = Robot;
    url = URL;
    Queue = require('./spotifyQueue')(robot, URL);
    MetaData = require('./spotifyMetaData')(Robot);
    manager = require('./spotifyResultManager')(Robot);
    return Support;
};

<commit_msg>Rewrite spotify HTTP URLs to spotify URIs<commit_after>'use strict';
/**
 * You know about the robot,
 * but make no assumptions about a `message`
 */

var Support = {},
    Queue,
    templates = require('./spotifyTemplates'),
    trackUriRE = /^spotify:track:[a-z\d]+$/i,
    trackURLRE = /^https?:\/\/.*spotify.*\/track\/([a-z\d]+)\/?$/i,
    currentResultReferenceRE = /^\[?(#|:)?(\d+)\]?$/,
    specificResultReferenceRE = /^\[?(\d+)\]?\[?(#|:)(\d+)\]?/,
    MetaData,
    manager,
    robot,
    url;
var $ = require('jquery');

function spotRequest(path, method, params, callback) {
    console.log('SPOT:' + method, url + path, params);
    robot.http(url + path).query(params)[method]()(callback);
}

function getCurrentTrackUri (callback) {
    spotRequest('/currently-playing', 'get', {}, function (err, res, body) {
        var uri;
        if (!err) {
            uri = String(body).replace(/^\s+/, '').replace(/\s+$/, '');
        }
        callback(err, uri);
    });
}

function determineTemplate (type) {
    switch (type) {
        case manager.types.ALBUMS:
            return templates.albumsLines;
        case manager.types.ARTISTS:
            return templates.artistsLines;
    }
    return templates.tracksLines;
}

function resultToString (data, type, userId, template) {
    var index = manager.persist(data, type, userId);
    return [templates.resultNumber(index), template(data)].join("\n");
}

function getDataHandler (userId, type, callback) {
    var rawTemplate = determineTemplate(type),
        template = function (data) {
            return rawTemplate(data, true);
        };
    return function handleData (err, data) {
        if (err) {
            callback(err);
            return;
        }
        callback(err, resultToString(data, type, userId, template));
    };
}

Support.isPlaying = function () {
    return Queue.somethingIsPlaying();
};

Support.purgeLists = function () {
    manager.purge();
};

Support.purgeMusicDataCache = function () {
    MetaData.clearCache();
};

function getInflatedAlbumHandler(callback, userId) {
    return function handleInflatedAlbum (err, album) {
        var index, tracks;
        if (!err) {
            tracks = album.getTracks();
            if (tracks.length) {
                index = manager.persist(tracks, manager.types.TRACKS, userId);
            }
        }
        callback(err, album, index);
    }
}

Support.translateToAlbum = function (str, userId, callback) {
    var resultNum, listItem, results,
        data, album, metaData, track,
        inflatedAlbumHandler = getInflatedAlbumHandler(callback, userId);
    if (str.match(currentResultReferenceRE)) {
        listItem = RegExp.$2;
        metaData = manager.getRelevantMetaData(void 0, userId, listItem);
        if (!metaData) {
            callback('Nothing found matching ' + str);
            return;
        }
        if (metaData.type === manager.types.ARTISTS) {
            callback('That\'s an artist list; use a track or album list');
            return;
        }
        if (metaData.type === manager.types.TRACKS) {
            track = new MetaData.Track(manager.getResult(metaData.index)[listItem]);
            track.getInflatedAlbum(inflatedAlbumHandler);
            return;
        }
        album = new MetaData.Album(manager.getResult(metaData.index)[listItem]);
        album.inflateTracks(inflatedAlbumHandler);
        return;
    }
    if (str.match(specificResultReferenceRE)) {
        resultNum = RegExp.$1;
        listItem = RegExp.$3;
        data = manager.getResultMetaData(resultNum);
        if (data.type === manager.types.ARTISTS) {
            callback('That\'s an artist list; use a track or album list');
            return;
        }
        results = manager.getResult(resultNum);
        if (!results || !results[listItem]) {
            callback('Item ' + listItem + ' not found for Result #' + resultNum);
            return;
        }
        if (data.type === manager.types.TRACKS) {
            track = new MetaData.Track(results[listItem]);
            track.getInflatedAlbum(inflatedAlbumHandler);
            return;
        }
        album = new MetaData.Album(results[listItem]);
        album.inflateTracks(inflatedAlbumHandler);
        return;
    }
    MetaData.findAlbums(str, 1, function (err, data) {
        if (err) {
            callback(err);
            return;
        }
        album = new MetaData.Album(data[0]);
        album.inflateTracks(inflatedAlbumHandler);
    });
};

Support.translateToTrack = function (str, userId, callback) {
    var resultNum, listItem, results, data;
    if (str.match(/\s*this\s*(track)?\s*$/)) {
        Support.getCurrentTrack(callback);
        return;
    }
    if (str.match(currentResultReferenceRE)) {
        listItem = RegExp.$2;
        results = manager.getRelevantResult(manager.types.TRACKS, userId, listItem);
        if (!results || !results.length) {
            callback('Nothing found matching ' + str);
            return;
        }
        callback(null, new MetaData.Track(results[listItem]));
        return;
    }
    if (str.match(specificResultReferenceRE)) {
        resultNum = RegExp.$1;
        listItem = RegExp.$3;
        data = manager.getResultMetaData(resultNum);
        if (data.type !== manager.types.TRACKS) {
            callback(templates.resultNumber(resultNum) + ' is not a track result list');
            return;
        }
        results = manager.getResult(resultNum);
        if (!results || !results[listItem]) {
            callback('Item ' + listItem + ' not found for ' + templates.resultNumber(resultNum));
            return;
        }
        callback(null, new MetaData.Track(results[listItem]));
        return;
    }
    if (str.match(trackURLRE)) {
        //ReWrite to URI Style
        str = str.replace(trackURLRE, 'spotify:track:$1');
    }
    if (str.match(trackUriRE)) {
        MetaData.fetchTrack(str, function (err, Track) {
            if (err) {
                Track = new MetaData.Track({href : str});
            }
            callback(null, Track);
        });
        return;
    }
    MetaData.findTracks(str, 1, function (err, data) {
        if (err) {
            callback(err);
            return;
        }
        callback(null, new MetaData.Track(data[0]));
    });
};

Support.translateToArtist = function (str, userId, callback) {
    var resultNum, listItem, results, data, datum, artists, metaData, track;
    if (str.match(currentResultReferenceRE)) {
        listItem = RegExp.$2;
        metaData = manager.getRelevantMetaData(void 0, userId, listItem);
        if (!metaData) {
            callback('Nothing found matching ' + str);
            return;
        }
        if (metaData.type === manager.types.ARTISTS) {
            callback(null, new MetaData.Artist(manager.getResult(metaData.index)[listItem]));
            return;
        }
        if (metaData.type === manager.types.TRACKS) {
            datum = new MetaData.Track(manager.getResult(metaData.index)[listItem]);
        } else {
            datum = new MetaData.Album(manager.getResult(metaData.index)[listItem]);
        }
        artists = datum.getArtists();
        if (!artists.length) {
            callback('It doesn\'t have an artist... :S');
            return;
        }
        callback(null, new MetaData.Artist(artists[0]));
        return;
    }
    if (str.match(specificResultReferenceRE)) {
        resultNum = RegExp.$1;
        listItem = RegExp.$3;
        data = manager.getResultMetaData(resultNum);
        results = manager.getResult(resultNum);
        if (!results || !results[listItem]) {
            callback('Item ' + listItem + ' not found for ' + templates.resultNumber(resultNum));
            return;
        }
        datum = results[listItem];
        if (data.type === manager.types.ALBUMS) {
            if (!datum.getArtists) {
                datum = new MetaData.Album(datum);
            }
            artists = datum.getArtists();
            if (!artists.length) {
                callback('Album has no artists :S');
                return;
            }
            callback(null, new MetaData.Artist(artists[0]));
            return;
        }
        if (data.type === manager.types.TRACKS) {
            if (!datum.getArtists) {
                datum = new MetaData.Track(datum);
            }
            artists = datum.getArtists();
            if (!artists.length) {
                callback('Track has no artists :S');
                return;
            }
            callback(null, artists[0]);
            return;
        }
        callback(null, new MetaData.Artist(results[listItem]));
        return;
    }
    if (str.match(/\s*this artist\s*$/)) {
        Support.getCurrentArtist(callback);
        return;
    }
    MetaData.findArtists(str, 1, function (err, data) {
        if (err) {
            callback(err);
            return;
        }
        callback(null, new MetaData.Artist(data[0]));
    });
};

Support.getCurrentTrack = function (callback) {
    getCurrentTrackUri(function (err, uri) {
        if (err) {
            callback(err);
            return;
        }
        MetaData.fetchTrack(uri, callback);
    });
};

Support.getCurrentArtist = function (callback) {
    Support.getCurrentTrack(function (err, track) {
        var artists;
        if (err) {
            callback(err);
            return;
        }
        artists = track.getArtists();
        if (artists && artists.length) {
            callback(null, artists[0]);
            return;
        }
        callback('This track doesn\'t have artists...');
    });
};

Support.getCurrentAlbum = function (callback) {
    Support.getCurrentTrack(function (err, track) {
        var album;
        if (err) {
            callback(err);
            return;
        }
        track.getInflatedAlbum(callback);
    });
};

Support.debug = function () {
    return 'debug';
};

Support.playUri = function (uri, callback) {
    spotRequest('/play-uri', 'post', {'uri' : uri}, function (err, res, body) {
        callback(err, body);
    });
};

Support.playTrack = function (track, callback) {
    return Support.playUri(track.href, callback);
};

Support.findTracks = function (query, userId, limit, callback) {
    var handler = getDataHandler(userId, manager.types.TRACKS, callback),
        aQuery;
    if (query.match(/^\s*by\s+(.+)/)) {
        aQuery = RegExp.$1;
        Support.translateToArtist(aQuery, userId, function (err, artist) {
            if (err) {
                callback(err);
                return;
            }
            MetaData.findTracksByArtist(artist, limit, handler);
        });
        return;
    }
    MetaData.findTracks(query, limit, handler);
};

Support.findAlbums = function (query, userId, limit, callback) {
    var handler = getDataHandler(userId, manager.types.ALBUMS, callback);
    if (query.match(/^\s*by\s+(.+)/)) {
        Support.translateToArtist(RegExp.$1, userId, function (err, artist) {
            if (err) {
                callback(err);
                return;
            }
            artist.inflateAlbums(function (err, albums) {
                if (!err) {
                    albums = albums.slice(0, limit);
                }
                handler(err, albums);
            });
        });
        return;
    }
    MetaData.findAlbums(query, limit, handler);
};

Support.findArtists = function (query, userId, limit, callback) {
    MetaData.findArtists(query, limit, getDataHandler(userId, manager.types.ARTISTS, callback));
};

module.exports = function (Robot, URL) {
    robot = Robot;
    url = URL;
    Queue = require('./spotifyQueue')(robot, URL);
    MetaData = require('./spotifyMetaData')(Robot);
    manager = require('./spotifyResultManager')(Robot);
    return Support;
};

<|endoftext|>


<commit_before>var shufflemeHackathons = (function ($) {
  "use strict";
  let $grid = $("#about-hackathons #grid"); //locate what we want to sort
  let $filterMajorOptions = $("#portfolio-hackathon-major-sorting li"); //locate the filter categories
  let $filterMinorOptions = $("#portfolio-hackathon-minor-sorting li"); //locate the filter categories
  let $sizer = $grid.find(".shuffle_sizer"); //sizer stores the size of the items
  let shuffler;
  let init = function (onInit) {
    // None of these need to be executed synchronously
    setTimeout(function () {
      setupHackathonsFilters();
      onInit();
    }, 100);

    // instantiate the plugin
    shuffler = new Shuffle($grid[0], {
      itemSelector: '[class*="col-"][data-groups]',
      sizer: $sizer[0]
    });
  };

  // Set up button click
  let setupHackathonsFilters = function () {
    let $majorButtons = $filterMajorOptions.children();
    let $minorButtons = $filterMinorOptions.children();
    $majorButtons.on("click", function (e) {
      e.preventDefault();
      $("#portfolio-hackathon-major-sorting a").removeClass("active");
      $(this).addClass("active");
      const group = $(this).data("group");
      $filterMinorOptions.children(`[data-major-group*=${group}]`).show()
      $filterMinorOptions.children(`:not([data-major-group*=${group}])`).hide()
      $filterMinorOptions.children(`[data-major-group*=${group}]`).first().trigger("click")
    });
    $minorButtons.on("click", function (e) {
      e.preventDefault();
      const $this = $(this);
      const group = $this.data("group");

      loadImages(group);

      $("#portfolio-hackathon-minor-sorting a").removeClass("active");
      $this.addClass("active");

      // Filter elements
      shuffler.filter(group);

      $grid
        .find("li")
        .filter(function (i, e) {
          let $img = $(this).find("img");
          $img.removeAttr("data-bp");
          let groups = $(e).data("groups");
          if (!groups) return false;
          let isSelectedGrp = groups.indexOf(group) >= 0;
          if (isSelectedGrp && $img.length) {
            $img.attr(
              "data-bp",
              ($img.attr("src") || $img.data("src")).replace("Converted120", "Converted300")
            );
          }
          return isSelectedGrp;
        })
        .find(".portfolio-item a")
        .off("click.bigpicture")
        .on("click.bigpicture", function (e) {
          e.preventDefault();
          BigPicture({
            el: e.target,
            gallery: "#grid"
          });
        });
    });

    $majorButtons = null;
    $minorButtons = null;
  };
  // Re layout shuffle when images load. This is only needed
  // below 768 pixels because the .picture-item height is auto and therefore
  // the height of the picture-item is dependent on the image
  // I recommend using imagesloaded to determine when an image is loaded
  // but that doesn't support IE7
  let loadImages = function (insideGroup) {
    let debouncedLayout = $.throttle(300, function () {
      shuffler.update();
    });

    // Get all images inside shuffle selected group
    $grid
      .find("li")
      .filter(function (i, e) {
        let groups = $(e).data("groups");
        if (!groups) return false;
        return groups.indexOf(insideGroup) >= 0;
      })
      .find("img")
      .each(function () {
        // If none of the checks above matched, simulate loading on detached element.
        $(this).on("load", function () {
          $(this).off("load");
          debouncedLayout();
        });

        this.src = $(this).data("src");
      });

    // Because this method doesn't seem to be perfect.
    setTimeout(function () {
      debouncedLayout();
    }, 500);
  };

  return {
    init: init
  };
})(jQuery);

$(function () {

  $("#about-hackathons").one("inview", () => {
    $(this)
      .find(".container")
      .show();

    shufflemeHackathons.init(function () {
      $("#portfolio-hackathon-major-sorting a").first().trigger("click")
    });
  });
});
<commit_msg>CML-86: items align<commit_after>var shufflemeHackathons = (function ($) {
  "use strict";
  let $grid = $("#about-hackathons #grid"); //locate what we want to sort
  let $filterMajorOptions = $("#portfolio-hackathon-major-sorting li"); //locate the filter categories
  let $filterMinorOptions = $("#portfolio-hackathon-minor-sorting li"); //locate the filter categories
  let $sizer = $grid.find(".shuffle_sizer"); //sizer stores the size of the items
  let shuffler;
  let init = function (onInit) {
    // None of these need to be executed synchronously
    setTimeout(function () {
      setupHackathonsFilters();
      onInit();
    }, 100);

    // instantiate the plugin
    shuffler = new Shuffle($grid[0], {
      itemSelector: '[class*="col-"][data-groups]',
      sizer: $sizer[0]
    });
  };

  // Set up button click
  let setupHackathonsFilters = function () {
    let $majorButtons = $filterMajorOptions.children();
    let $minorButtons = $filterMinorOptions.children();
    $majorButtons.on("click", function (e) {
      e.preventDefault();
      $("#portfolio-hackathon-major-sorting a").removeClass("active");
      $(this).addClass("active");
      const group = $(this).data("group");
      $filterMinorOptions.children(`[data-major-group*=${group}]`).parent().show()
      $filterMinorOptions.children(`:not([data-major-group*=${group}])`).parent().hide()
      $filterMinorOptions.children(`[data-major-group*=${group}]`).first().trigger("click")
    });
    $minorButtons.on("click", function (e) {
      e.preventDefault();
      const $this = $(this);
      const group = $this.data("group");

      loadImages(group);

      $("#portfolio-hackathon-minor-sorting a").removeClass("active");
      $this.addClass("active");

      // Filter elements
      shuffler.filter(group);

      $grid
        .find("li")
        .filter(function (i, e) {
          let $img = $(this).find("img");
          $img.removeAttr("data-bp");
          let groups = $(e).data("groups");
          if (!groups) return false;
          let isSelectedGrp = groups.indexOf(group) >= 0;
          if (isSelectedGrp && $img.length) {
            $img.attr(
              "data-bp",
              ($img.attr("src") || $img.data("src")).replace("Converted120", "Converted300")
            );
          }
          return isSelectedGrp;
        })
        .find(".portfolio-item a")
        .off("click.bigpicture")
        .on("click.bigpicture", function (e) {
          e.preventDefault();
          BigPicture({
            el: e.target,
            gallery: "#grid"
          });
        });
    });

    $majorButtons = null;
    $minorButtons = null;
  };
  // Re layout shuffle when images load. This is only needed
  // below 768 pixels because the .picture-item height is auto and therefore
  // the height of the picture-item is dependent on the image
  // I recommend using imagesloaded to determine when an image is loaded
  // but that doesn't support IE7
  let loadImages = function (insideGroup) {
    let debouncedLayout = $.throttle(300, function () {
      shuffler.update();
    });

    // Get all images inside shuffle selected group
    $grid
      .find("li")
      .filter(function (i, e) {
        let groups = $(e).data("groups");
        if (!groups) return false;
        return groups.indexOf(insideGroup) >= 0;
      })
      .find("img")
      .each(function () {
        // If none of the checks above matched, simulate loading on detached element.
        $(this).on("load", function () {
          $(this).off("load");
          debouncedLayout();
        });

        this.src = $(this).data("src");
      });

    // Because this method doesn't seem to be perfect.
    setTimeout(function () {
      debouncedLayout();
    }, 500);
  };

  return {
    init: init
  };
})(jQuery);

$(function () {

  $("#about-hackathons").one("inview", () => {
    $(this)
      .find(".container")
      .show();

    shufflemeHackathons.init(function () {
      $("#portfolio-hackathon-major-sorting a").first().trigger("click")
    });
  });
});
<|endoftext|>