<commit_before>//'use strict';
import * as widgets from '@jupyter-widgets/base';
import _ from 'lodash';
import $ from 'jquery';
import { new_id } from './base';
import { elementReady } from './es6-element-ready';
//import * as colormaps from './colormaps';
import * as d3 from 'd3';
import History from './history';
import '../css/scatterplot.css';

const DEFAULT_SIGMA = 0;
const DEFAULT_FILTER = 'default';
const MAX_PREV_IMAGES = 3;

export const PrevImagesModel = widgets.DOMWidgetModel.extend({
  defaults: _.extend(widgets.DOMWidgetModel.prototype.defaults(), {
    _model_name: 'PrevImagesModel',
    _view_name: 'PrevImagesView',
    _model_module: 'progressivis-nb-widgets',
    _view_module: 'progressivis-nb-widgets',
    _model_module_version: '0.1.0',
    _view_module_version: '0.1.0',
    hists: ndarray([]),
    samples: ndarray([]),
    target: '',
  }),
});

// Custom View. Renders the widget model.
export const PrevImagesView = widgets.DOMWidgetView.extend({
  // Defines how the widget gets rendered into the DOM
  render: function () {
    this.id = 'view_' + new_id();
    const previmgs = PrevImages(this);
    this.previmgs = previmgs;
    this.previmgs.template(this.el);
    let that = this;
    elementReady('#' + previmgs.with_id('prevImages')).then(() =>

      previmgs.ready(that.model.get('target'))
    );
    this.model.on('msg:custom', this.data_changed, this);
  },
  data_changed: function () {
    console.log('data_changed');
    const target = this.model.get('target');
    console.log(target);
    this.previmgs.update_vis(target);
  },
});

function PrevImages(ipyView) {
  const id = ipyView.id;
    let dataURL = null;
    let firstTime = true;
    let zoomable;
    let transform = d3.zoomIdentity;
  //const margin = { top: 20, right: 20, bottom: 30, left: 40 };
  //const width = 960 - margin.left - margin.right;
  //const height = 500 - margin.top - margin.bottom;
    let svg;
    let bounds = null;
  const imageHistory = new History(MAX_PREV_IMAGES);
  function with_id(prefix) {
    return prefix + '_' + id;
  }
  function s(id) {
    return '#' + id;
  }
  function swith_id(id) {
    return s(with_id(id));
  }

  function template(element) {
    let temp = document.querySelector('#PrevImages');
    if (temp === null) {
      // Install the template as a dom template node
      temp = document.createElement('template');
      temp.setAttribute('id', 'PrevImages');
      temp.innerHTML = `

            History

Blur radius	<input class="form-control" id="filterSlider" type="range" value="0" min="0" max="5" step="0.1"></input>

`;
      document.body.appendChild(temp);
    }
    const templateClone = temp.content.cloneNode(true);
    // Rename all the ids to be unique
    const with_ids = templateClone.querySelectorAll('[id]');
    const ids = new Set();

    for (const element of with_ids) {
      const eid = element.id ? with_id(element.id) : with_id('PrevImages');
      if (ids.has(eid)) {
        console.log(`Error in PrevImages.template(), duplicate id '${eid}'`);
        // TODO fix it
      }
      element.id = eid;
    }

    element.appendChild(templateClone);
  }
  //https://github.com/jupyter-widgets/ipywidgets/issues/1840
    function _update_vis(target) {
	let targetP  = '.'+target;
	let targetCanvas = targetP + ' canvas';
	let targetSvg = targetP + ' svg';
	elementReady(targetCanvas).then((that) => {
	    if(firstTime){
		bounds = $(targetCanvas)[0].getBoundingClientRect();
		_createSvg(target);
		firstTime = false;

	    } else {

		zoomable.attr('transform', transform);
	    }
	    dataURL = $(that)[0].toDataURL();
	    $(targetCanvas).hide();
      imageHistory.enqueueUnique(dataURL);
        svg
          .select(targetSvg+' .heatmap')
          //.attr('x', ix)
          //.attr('y', iy)
          //.attr('width', iw)
          //.attr('height', ih)
          .attr('xlink:href', dataURL);

      const prevImgElements = d3
        .select(swith_id('prevImages'))
        .selectAll('img')
        .data(imageHistory.getItems(), (d) => d);

      prevImgElements
        .enter()
        .append('img')
        .attr('width', 50)
        .attr('height', 50)
        .on('mouseover', (d) => {
          d3.select(`${targetP} .heatmapCompare`)
            .attr('xlink:href', d)
            .attr('visibility', 'inherit');
        })
        .on('mouseout', () => {
          d3.select(`${targetP} .heatmapCompare`).attr(
            'visibility',
            'hidden'
          );
        });
      prevImgElements
        .transition()
        .duration(50000)
        .attr('src', (d) => d)
        .attr('width', 100)
        .attr('height', 100);

      prevImgElements
        .exit()
        .transition()
        .duration(500)
        .attr('width', 5)
        .attr('height', 5)
        .remove();
    }); //end elementReady
  }
    function _createSvg(target) {
	console.log("calling ready", target);
	let svgClass = target+'_svg';
	let svgClassP = '.'+svgClass;
	let targetP = '.'+target
	let gaussianBlurElement = target+'_gaussianBlurElement';
	let filterId = target+'_filter';
	let svgHtml = `<svg class=${svgClass}>
          <filter id="${filterId}" width="100%" height="100%" x="0" y="0">
            <feGaussianBlur id="${gaussianBlurElement}" in="SourceGraphic" stdDeviation="0" />
            <feComponentTransfer id="colorMap">
              <feFuncR type="table" tableValues="1 1 1"/>
              <feFuncG type="table" tableValues="0.93 0.001 0"/>
              <feFuncB type="table" tableValues="0.63 0.001 0"/>
            </feComponentTransfer>
          </filter>
        </svg>`;
	elementReady(targetP).then(() =>
				   $(targetP).append('<svg class="'+svgClass+'"></svg>')
				   //$(targetP).append(svgHtml)
				  );
	elementReady(svgClassP).then(() =>{
	console.log("le svg", target, svgClassP, $(svgClassP));							     svg = d3
		.select(svgClassP).attr('width', bounds.width).attr('height', bounds.height);
          //.attr('x', bounds.x)
          //.attr('y', bounds.y);
	 zoomable = svg
          .append('g')
          .attr('id', with_id('zoomable'))
          /*.attr(
            'transform',
            'translate(' + margin.left + ',' + margin.top + ')'
          );

        const ix = x(bounds.xmin);
        const iy = y(bounds.ymax);
        const iw = x(bounds.xmax) - ix;
        const ih = y(bounds.ymin) - iy;
*/
        zoomable
          .append('image')
          .attr('class', 'heatmap')
		.style('pointer-events', 'none')
		//.style('z-index', 1)
          .attr('xlink:href', dataURL)
		.attr('preserveAspectRatio', 'none')
	   // .attr('opacity', 0.5)
          //.attr('x', bounds.x)
          //.attr('y', bounds.y)
          .attr('width', bounds.width)
		.attr('height', bounds.height).attr('filter','blur(5px)');
          //.attr('filter', `url(filterId})`);
	 svg.append('image')
          .attr('class', 'heatmapCompare')
          .style('pointer-events', 'none')
          .attr('preserveAspectRatio', 'none')
          .attr('opacity', 0.5)
          //.attr('x', bounds.x)
        //.attr('y', bounds.y)
		//	.style('z-index', 2)
          .attr('width', bounds.width)
		.attr('height', bounds.height);
	    /*
    const gaussianBlur = document.getElementById(
      gaussianBlurElement
    );
    const filterSlider = $(filterId);
    filterSlider.change(function () {
      const value = this.value;
      gaussianBlur.setStdDeviation(value, value);
    });
    filterSlider.get(0).value = DEFAULT_SIGMA;
    gaussianBlur.setStdDeviation(DEFAULT_SIGMA, DEFAULT_SIGMA);
*/
	    //.attr('width', width + margin.left + margin.right)
      //.attr('height', height + margin.top + margin.bottom);
	    //svg.call(d3.zoom());
	});
    }
    function _ready(t) {

    }
  return {
    ready: _ready,
    update_vis: _update_vis,
    template: template,
    with_id: with_id,
  };
}
<commit_msg>a more better draft<commit_after>//'use strict';
import * as widgets from '@jupyter-widgets/base';
import _ from 'lodash';
import $ from 'jquery';
import { new_id } from './base';
import { elementReady } from './es6-element-ready';
import * as colormaps from './colormaps';
import * as d3 from 'd3';
import History from './history';
import '../css/scatterplot.css';

const DEFAULT_SIGMA = 0;
const DEFAULT_FILTER = 'default';
const MAX_PREV_IMAGES = 3;

export const PrevImagesModel = widgets.DOMWidgetModel.extend({
  defaults: _.extend(widgets.DOMWidgetModel.prototype.defaults(), {
    _model_name: 'PrevImagesModel',
    _view_name: 'PrevImagesView',
    _model_module: 'progressivis-nb-widgets',
    _view_module: 'progressivis-nb-widgets',
    _model_module_version: '0.1.0',
    _view_module_version: '0.1.0',
    hists: ndarray([]),
    samples: ndarray([]),
    target: '',
  }),
});

// Custom View. Renders the widget model.
export const PrevImagesView = widgets.DOMWidgetView.extend({
  // Defines how the widget gets rendered into the DOM
  render: function () {
    this.id = 'view_' + new_id();
    const previmgs = PrevImages(this);
    this.previmgs = previmgs;
    this.previmgs.template(this.el);
    let that = this;
    elementReady('#' + previmgs.with_id('prevImages')).then(() =>

      previmgs.ready(that.model.get('target'))
    );
    this.model.on('msg:custom', this.data_changed, this);
  },
  data_changed: function () {
    console.log('data_changed');
    const target = this.model.get('target');
    console.log(target);
    this.previmgs.update_vis(target);
  },
});

function PrevImages(ipyView) {
  const id = ipyView.id;
    let dataURL = null;
    let firstTime = true;
    let zoomable;
    let transform = d3.zoomIdentity;
  //const margin = { top: 20, right: 20, bottom: 30, left: 40 };
  //const width = 960 - margin.left - margin.right;
  //const height = 500 - margin.top - margin.bottom;
    let svg;
    let bounds = null;
  const imageHistory = new History(MAX_PREV_IMAGES);
  function with_id(prefix) {
    return prefix + '_' + id;
  }
  function s(id) {
    return '#' + id;
  }
  function swith_id(id) {
    return s(with_id(id));
  }

  function template(element) {
    let temp = document.querySelector('#PrevImages');
    if (temp === null) {
      // Install the template as a dom template node
      temp = document.createElement('template');
      temp.setAttribute('id', 'PrevImages');
      temp.innerHTML = `

        <svg>
          <filter id="gaussianBlur" width="100%" height="100%" x="0" y="0">
            <feGaussianBlur id="gaussianBlurElement" in="SourceGraphic" stdDeviation="0" />
            <feComponentTransfer id="colorMap">
              <feFuncR type="table" tableValues="1 1 1"/>
              <feFuncG type="table" tableValues="0.93 0.001 0"/>
              <feFuncB type="table" tableValues="0.63 0.001 0"/>
            </feComponentTransfer>
          </filter>
        </svg>

            History

Blur radius	<input class="form-control" id="filterSlider" type="range" value="0" min="0" max="5" step="0.1"></input>
Color map	<select id="colorMapSelect" class="form-control"></select>

`;
      document.body.appendChild(temp);
    }
    const templateClone = temp.content.cloneNode(true);
    // Rename all the ids to be unique
    const with_ids = templateClone.querySelectorAll('[id]');
    const ids = new Set();

    for (const element of with_ids) {
      const eid = element.id ? with_id(element.id) : with_id('PrevImages');
      if (ids.has(eid)) {
        console.log(`Error in PrevImages.template(), duplicate id '${eid}'`);
        // TODO fix it
      }
      element.id = eid;
    }

    element.appendChild(templateClone);
  }
  //https://github.com/jupyter-widgets/ipywidgets/issues/1840
    function _update_vis(target) {
	let targetP  = '.'+target;
	let targetCanvas = targetP + ' canvas';
	let targetSvg = targetP + ' svg';
	elementReady(targetCanvas).then((that) => {
	    if(firstTime){
		bounds = $(targetCanvas)[0].getBoundingClientRect();
		_createSvg(target);
		firstTime = false;

	    } else {

		zoomable.attr('transform', transform);
	    }
	    dataURL = $(that)[0].toDataURL();
	    $(targetCanvas).hide();
	    imageHistory.enqueueUnique(dataURL);
	          let svgQry = swith_id('PrevImages') + ' svg'
        svg
          .select(svgQry+' .heatmap')
          //.attr('x', ix)
          //.attr('y', iy)
          //.attr('width', iw)
          //.attr('height', ih)
          .attr('xlink:href', dataURL);

      const prevImgElements = d3
        .select(swith_id('prevImages'))
        .selectAll('img')
        .data(imageHistory.getItems(), (d) => d);
      prevImgElements
        .enter()
        .append('img')
        .attr('width', 50)
        .attr('height', 50)
        .on('mouseover', (d) => {
          d3.select(`${svgQry} .heatmapCompare`)
            .attr('xlink:href', d)
            .attr('visibility', 'inherit');
        })
        .on('mouseout', () => {
          d3.select(`${svgQry} .heatmapCompare`).attr(
            'visibility',
            'hidden'
          );
        });
      prevImgElements
        .transition()
        .duration(50000)
        .attr('src', (d) => d)
        .attr('width', 100)
        .attr('height', 100);

      prevImgElements
        .exit()
        .transition()
        .duration(500)
        .attr('width', 5)
        .attr('height', 5)
        .remove();
    }); //end elementReady
    }

      /**
   * @param select - a select element that will be mutated
   * @param names - list of option names (the value of an option is set to its name)
   */
  function makeOptions(select, names) {
    if (!select) {
      console.warn('makeOptions requires an existing select element');
      return;
    }
    names.forEach((name) => {
      const option = document.createElement('option');
      option.setAttribute('value', name);
      option.innerHTML = name;
      select.appendChild(option);
    });
  }

    function _createSvg(target) {
	console.log("calling ready", target);
	let svgClass = target+'_svg';
	let svgClassP = '.'+svgClass;
	let targetP = '.'+target
	let gaussianBlurElement = target+'_gaussianBlurElement';
	let filterId = target+'_filter';
	let svgHtml = `<svg class=${svgClass}>
          <filter id="${filterId}" width="100%" height="100%" x="0" y="0">
            <feGaussianBlur id="${gaussianBlurElement}" in="SourceGraphic" stdDeviation="0" />
            <feComponentTransfer id="colorMap">
              <feFuncR type="table" tableValues="1 1 1"/>
              <feFuncG type="table" tableValues="0.93 0.001 0"/>
              <feFuncB type="table" tableValues="0.63 0.001 0"/>
            </feComponentTransfer>
          </filter>
        </svg>`;
	/*
	elementReady(targetP).then(() =>
				   $(targetP).append('<svg class="'+svgClass+'"></svg>')
				   //$(targetP).append(svgHtml)
				  );*/
	//elementReady(svgClassP).then(() =>{
	console.log("le svg", target, svgClassP, $(svgClassP));							     svg = d3
		.select(swith_id('PrevImages') + ' svg').attr('width', bounds.width).attr('height', bounds.height);
          //.attr('x', bounds.x)
          //.attr('y', bounds.y);
	 zoomable = svg
          .append('g')
          .attr('id', with_id('zoomable'))
          /*.attr(
            'transform',
            'translate(' + margin.left + ',' + margin.top + ')'
          );

        const ix = x(bounds.xmin);
        const iy = y(bounds.ymax);
        const iw = x(bounds.xmax) - ix;
        const ih = y(bounds.ymin) - iy;
*/
        zoomable
          .append('image')
          .attr('class', 'heatmap')
		.style('pointer-events', 'none')
		//.style('z-index', 1)
          .attr('xlink:href', dataURL)
		.attr('preserveAspectRatio', 'none')
	   // .attr('opacity', 0.5)
          //.attr('x', bounds.x)
          //.attr('y', bounds.y)
          .attr('width', bounds.width)
	//	.attr('height', bounds.height).attr('filter','blur(5px)');
          .attr('filter', `url(${swith_id('gaussianBlur')})`);
	 svg.append('image')
          .attr('class', 'heatmapCompare')
          .style('pointer-events', 'none')
          .attr('preserveAspectRatio', 'none')
          .attr('opacity', 0.5)
          //.attr('x', bounds.x)
        //.attr('y', bounds.y)
		//	.style('z-index', 2)
          .attr('width', bounds.width)
		.attr('height', bounds.height);
    const gaussianBlur = document.getElementById(
      with_id('gaussianBlurElement')
    );
    const filterSlider = $(swith_id('filterSlider'));
    filterSlider.change(function () {
      const value = this.value;
      gaussianBlur.setStdDeviation(value, value);
    });
    filterSlider.get(0).value = DEFAULT_SIGMA;
    gaussianBlur.setStdDeviation(DEFAULT_SIGMA, DEFAULT_SIGMA);
    const colorMap = document.getElementById(with_id('colorMap'));
    const colorMapSelect = $(swith_id('colorMapSelect'));
    colorMapSelect.change(function() {
      colormaps.makeTableFilter(colorMap, this.value);
    });
    colorMapSelect.get(0).value = DEFAULT_FILTER;
    makeOptions(colorMapSelect.get(0), colormaps.getTableNames());
    colormaps.makeTableFilter(colorMap, 'Default');
	    //.attr('width', width + margin.left + margin.right)
      //.attr('height', height + margin.top + margin.bottom);
	    //svg.call(d3.zoom());
	//});
    }
    function _ready(t) {

    }
  return {
    ready: _ready,
    update_vis: _update_vis,
    template: template,
    with_id: with_id,
  };
}
<|endoftext|>


<commit_before>import * as core from '../../../core';
import LightQuad from './LightQuad';
import Light from './lights/light/Light';

const WebGLRenderer = core.WebGLRenderer;
const Texture = core.Texture;
// const RenderTexture = core.RenderTexture;

export default class LightSpriteRenderer extends core.ObjectRenderer
{
    onContextChange()
    {
        this.gl = this.renderer.gl;
        this.quad = new LightQuad(this.gl, this.renderer.state.attribState);
        Light.shaderCache = {};
        this.contextChanged = true;
    }

    render(sprite)
    {
        if (!sprite._texture._uvs || !sprite.lights)
        {
            return;
        }

        const renderer = this.renderer;
        const gl = renderer.gl;

        const lights = sprite.lights;
        const lightCount = lights.length;

        const vertexData = sprite.computedGeometry ? sprite.computedGeometry.vertices : sprite.vertexData;
        const diffuseTexture = sprite.diffuseTexture ? sprite.diffuseTexture : sprite._texture;
        const normalTexture = sprite.normalTexture ? sprite.normalTexture : LightSpriteRenderer.defaultNormalTexture;

        const uvsData = diffuseTexture._uvs;
        const uvsDataNormal = normalTexture._uvs;

        const uSamplerLocation = renderer.bindTexture(diffuseTexture, 1, true);
        let uNormalSamplerLocation;

        if (diffuseTexture.baseTexture === normalTexture.baseTexture)
        {
            uNormalSamplerLocation = uSamplerLocation;
        }
        else
        {
            uNormalSamplerLocation = renderer.bindTexture(normalTexture, 2, true);
        }

        let lastShader = null;

        for (let i = 0; i < lightCount; i++)
        {
            const light = lights[i];

            light.init(renderer, this.contextChanged);

            const shader = light.shader;

            if (i === 0)
            {
                const quad = this.quad;
                const vertices = quad.vertices;
                const uvs = quad.uvs;

                renderer.bindVao(null);
                quad.initVao(shader);

                for (let i = 0; i < 8; i++)
                {
                    vertices[i] = vertexData[i];
                }

                uvs[0] = uvsData.x0;
                uvs[1] = uvsData.y0;
                uvs[2] = uvsData.x1;
                uvs[3] = uvsData.y1;
                uvs[4] = uvsData.x2;
                uvs[5] = uvsData.y2;
                uvs[6] = uvsData.x3;
                uvs[7] = uvsData.y3;
                uvs[8] = uvsDataNormal.x0;
                uvs[9] = uvsDataNormal.y0;
                uvs[10] = uvsDataNormal.x1;
                uvs[11] = uvsDataNormal.y1;
                uvs[12] = uvsDataNormal.x2;
                uvs[13] = uvsDataNormal.y2;
                uvs[14] = uvsDataNormal.x3;
                uvs[15] = uvsDataNormal.y3;
                quad.upload();
                renderer.bindVao(quad.vao);
            }

            if (lastShader !== shader)
            {
                lastShader = shader;
                renderer.bindShader(shader);
            }
            shader.uniforms.uSampler = uSamplerLocation;
            shader.uniforms.uNormalSampler = uNormalSamplerLocation;
            light.syncShader(sprite);

            renderer.state.setBlendMode(light.blendMode);

            gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
        }

        this.contextChanged = false;
    }

    destroy()
    {
        super.destroy();
        // TODO
    }

    static applyTo(sprite)
    {
        sprite.pluginName = LightSpriteRenderer.pluginName;
        sprite.diffuseTexture = sprite.diffuseTexture || sprite._texture;
        /* eslint-disable camelcase */
        sprite._bak_pluginName_LightSprite = sprite.pluginName;
        sprite._bak_renderWebGL_LightSprite = sprite._renderWebGL;
        sprite._renderWebGL = LightSpriteRenderer.__renderWebGL_Sprite;
        /* eslint-enable camelcase */
    }

    static unapplyTo(sprite)
    {
        /* eslint-disable camelcase */
        sprite.pluginName = sprite._bak_pluginName_LightSprite;
        sprite.diffuseTexture = null;
        if (sprite._bak_renderWebGL_LightSprite)
        {
            sprite._renderWebGL = sprite._bak_renderWebGL_LightSprite;
            sprite._bak_renderWebGL_LightSprite = null;
        }
        /* eslint-enable camelcase */
    }

    static __renderWebGL_Sprite(renderer) // eslint-disable-line camelcase
    {
        const sprite = this;

        sprite.calculateVertices();

        if (renderer.renderingDiffuses)
        {
            // const originalTexture = sprite._texture;
            const diffuseTexture = sprite.diffuseTexture || sprite._texture;

            sprite._texture = diffuseTexture;

            renderer.setObjectRenderer(renderer.plugins.sprite);
            renderer.plugins.sprite.render(sprite);

            return;
        }

        if (renderer.renderingNormals)
        {
            // const originalTexture = sprite._texture;
            const normalTexture = sprite.normalTexture || LightSpriteRenderer.defaultNormalTexture;

            sprite._texture = normalTexture;

            renderer.setObjectRenderer(renderer.plugins.sprite);
            renderer.plugins.sprite.render(sprite);

            return;
        }

        renderer.setObjectRenderer(renderer.plugins.lightSprite);
        renderer.plugins.lightSprite.render(sprite);
    }
}

const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');

canvas.width = canvas.height = 10;
context.fillStyle = '#8080FF';
context.fillRect(0, 0, canvas.width, canvas.height);
LightSpriteRenderer.defaultNormalTexture = Texture.from(canvas);
LightSpriteRenderer.pluginName = 'lightSprite';
WebGLRenderer.registerPlugin(LightSpriteRenderer.pluginName, LightSpriteRenderer);

<commit_msg>update applyTo/unapplyTo of Light Renderer<commit_after>import * as core from '../../../core';
import LightQuad from './LightQuad';
import Light from './lights/light/Light';

const WebGLRenderer = core.WebGLRenderer;
const Texture = core.Texture;
// const RenderTexture = core.RenderTexture;

export default class LightSpriteRenderer extends core.ObjectRenderer
{
    onContextChange()
    {
        this.gl = this.renderer.gl;
        this.quad = new LightQuad(this.gl, this.renderer.state.attribState);
        Light.shaderCache = {};
        this.contextChanged = true;
    }

    render(sprite)
    {
        if (!sprite._texture._uvs || !sprite.lights)
        {
            return;
        }

        const renderer = this.renderer;
        const gl = renderer.gl;

        const lights = sprite.lights;
        const lightCount = lights.length;

        const vertexData = sprite.computedGeometry ? sprite.computedGeometry.vertices : sprite.vertexData;
        const diffuseTexture = sprite.diffuseTexture ? sprite.diffuseTexture : sprite._texture;
        const normalTexture = sprite.normalTexture ? sprite.normalTexture : LightSpriteRenderer.defaultNormalTexture;

        const uvsData = diffuseTexture._uvs;
        const uvsDataNormal = normalTexture._uvs;

        const uSamplerLocation = renderer.bindTexture(diffuseTexture, 1, true);
        let uNormalSamplerLocation;

        if (diffuseTexture.baseTexture === normalTexture.baseTexture)
        {
            uNormalSamplerLocation = uSamplerLocation;
        }
        else
        {
            uNormalSamplerLocation = renderer.bindTexture(normalTexture, 2, true);
        }

        let lastShader = null;

        for (let i = 0; i < lightCount; i++)
        {
            const light = lights[i];

            light.init(renderer, this.contextChanged);

            const shader = light.shader;

            if (i === 0)
            {
                const quad = this.quad;
                const vertices = quad.vertices;
                const uvs = quad.uvs;

                renderer.bindVao(null);
                quad.initVao(shader);

                for (let i = 0; i < 8; i++)
                {
                    vertices[i] = vertexData[i];
                }

                uvs[0] = uvsData.x0;
                uvs[1] = uvsData.y0;
                uvs[2] = uvsData.x1;
                uvs[3] = uvsData.y1;
                uvs[4] = uvsData.x2;
                uvs[5] = uvsData.y2;
                uvs[6] = uvsData.x3;
                uvs[7] = uvsData.y3;
                uvs[8] = uvsDataNormal.x0;
                uvs[9] = uvsDataNormal.y0;
                uvs[10] = uvsDataNormal.x1;
                uvs[11] = uvsDataNormal.y1;
                uvs[12] = uvsDataNormal.x2;
                uvs[13] = uvsDataNormal.y2;
                uvs[14] = uvsDataNormal.x3;
                uvs[15] = uvsDataNormal.y3;
                quad.upload();
                renderer.bindVao(quad.vao);
            }

            if (lastShader !== shader)
            {
                lastShader = shader;
                renderer.bindShader(shader);
            }
            shader.uniforms.uSampler = uSamplerLocation;
            shader.uniforms.uNormalSampler = uNormalSamplerLocation;
            light.syncShader(sprite);

            renderer.state.setBlendMode(light.blendMode);

            gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
        }

        this.contextChanged = false;
    }

    destroy()
    {
        super.destroy();
        // TODO
    }

    static applyTo(sprite)
    {
        /* eslint-disable camelcase */
        sprite._bak_pluginName_LightSprite = sprite.pluginName;
        sprite._bak_diffuseTexture_LightSprite = sprite.diffuseTexture;
        sprite._bak__renderWebGL_LightSprite = sprite._renderWebGL;

        sprite.pluginName = LightSpriteRenderer.pluginName;
        sprite.diffuseTexture = sprite.diffuseTexture || sprite._texture;
        sprite._renderWebGL = LightSpriteRenderer.__renderWebGL_Sprite;
        /* eslint-enable camelcase */
    }

    static unapplyTo(sprite)
    {
        /* eslint-disable camelcase */
        if (sprite._bak__renderWebGL_LightSprite)
        {
            sprite.pluginName = sprite._bak_pluginName_LightSprite;
            sprite.diffuseTexture = sprite._bak_diffuseTexture_LightSprite;
            sprite._renderWebGL = sprite._bak__renderWebGL_LightSprite;

            sprite._bak_pluginName_LightSprite = null;
            sprite._bak_diffuseTexture_LightSprite = null;
            sprite._bak__renderWebGL_LightSprite = null;
        }
        /* eslint-enable camelcase */
    }

    static __renderWebGL_Sprite(renderer) // eslint-disable-line camelcase
    {
        const sprite = this;

        sprite.calculateVertices();

        if (renderer.renderingDiffuses)
        {
            // const originalTexture = sprite._texture;
            const diffuseTexture = sprite.diffuseTexture || sprite._texture;

            sprite._texture = diffuseTexture;

            renderer.setObjectRenderer(renderer.plugins.sprite);
            renderer.plugins.sprite.render(sprite);

            return;
        }

        if (renderer.renderingNormals)
        {
            // const originalTexture = sprite._texture;
            const normalTexture = sprite.normalTexture || LightSpriteRenderer.defaultNormalTexture;

            sprite._texture = normalTexture;

            renderer.setObjectRenderer(renderer.plugins.sprite);
            renderer.plugins.sprite.render(sprite);

            return;
        }

        renderer.setObjectRenderer(renderer.plugins.lightSprite);
        renderer.plugins.lightSprite.render(sprite);
    }
}

const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');

canvas.width = canvas.height = 10;
context.fillStyle = '#8080FF';
context.fillRect(0, 0, canvas.width, canvas.height);
LightSpriteRenderer.defaultNormalTexture = Texture.from(canvas);
LightSpriteRenderer.pluginName = 'lightSprite';
WebGLRenderer.registerPlugin(LightSpriteRenderer.pluginName, LightSpriteRenderer);

<|endoftext|>


<commit_before>describe('ui.grid.moveColumns', function () {

  var scope, element, timeout, gridUtil, document, uiGridConstants;

  var data = [
    { "name": "Ethel Price", "gender": "female", "age": 25, "company": "Enersol", phone: '111'},
    { "name": "Claudine Neal", "gender": "female", "age": 30, "company": "Sealoud", phone: '111'},
    { "name": "Beryl Rice", "gender": "female", "age": 35, "company": "Velity", phone: '111'},
    { "name": "Wilder Gonzales", "gender": "male", "age": 40, "company": "Geekko", phone: '111'}
  ];

  beforeEach(module('ui.grid.moveColumns'));

  beforeEach(inject(function (_$compile_, $rootScope, $timeout, _gridUtil_, $document, _uiGridConstants_) {

    var $compile = _$compile_;
    scope = $rootScope;
    timeout = $timeout;
    gridUtil = _gridUtil_;
    document = $document;
    uiGridConstants = _uiGridConstants_;

    scope.gridOptions = {};
    scope.gridOptions.data = data;
    scope.gridOptions.columnDefs = [
      { field: 'name', width: 200 },
      { field: 'gender', width: 200 },
      { field: 'age', width: 200, visible: false},
      { field: 'company', enableColumnMoving: false, width: 200 },
      { field: 'phone', width: 200 }
    ];

    scope.gridOptions.onRegisterApi = function (gridApi) {
      scope.gridApi = gridApi;
      scope.grid = gridApi.grid;
    };

    element = angular.element('

');

    $timeout(function () {
      $compile(element)(scope);
    });
    $timeout.flush();
  }));

  it('grid api for columnMovable should be defined', function () {
    expect(scope.gridApi.colMovable).toBeDefined();
    expect(scope.gridApi.colMovable.on.columnPositionChanged).toBeDefined();
    expect(scope.gridApi.colMovable.raise.columnPositionChanged).toBeDefined();
    expect(scope.gridApi.colMovable.moveColumn).toBeDefined();
  });

  it('expect enableColumnMoving to be true by default', function () {
    expect(scope.grid.options.enableColumnMoving).toBe(true);
    expect(scope.grid.columns[0].colDef.enableColumnMoving).toBe(true);
    expect(scope.grid.columns[1].colDef.enableColumnMoving).toBe(true);
    expect(scope.grid.columns[2].colDef.enableColumnMoving).toBe(true);
    expect(scope.grid.columns[3].colDef.enableColumnMoving).toBe(false);
    expect(scope.grid.columns[4].colDef.enableColumnMoving).toBe(true);
  });

  it('expect moveColumn() to change position of columns', function () {
    scope.gridApi.colMovable.moveColumn(0, 1);
    expect(scope.grid.columns[0].name).toBe('gender');
    expect(scope.grid.columns[1].name).toBe('name');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
    scope.gridApi.colMovable.moveColumn(0, 3);
    expect(scope.grid.columns[0].name).toBe('name');
    expect(scope.grid.columns[1].name).toBe('age');
    expect(scope.grid.columns[2].name).toBe('company');
    expect(scope.grid.columns[3].name).toBe('phone');
    expect(scope.grid.columns[4].name).toBe('gender');
  });

  it('expect moveColumn() to persist after adding additional column', function () {
    scope.gridApi.colMovable.moveColumn(0, 1);
    scope.gridOptions.columnDefs.push({ field: 'name', displayName: 'name2', width: 200 });
    scope.gridApi.core.notifyDataChange( uiGridConstants.COLUMN );
    timeout.flush();
    scope.$digest();

    expect(scope.grid.columns[0].name).toBe('gender');
    expect(scope.grid.columns[1].name).toBe('name');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
    expect(scope.grid.columns[5].displayName).toBe('name2');
  });

  it('expect moveColumn() to not change position of columns if enableColumnMoving is false', function () {
    scope.gridApi.colMovable.moveColumn(2, 1);
    expect(scope.grid.columns[0].name).toBe('name');
    expect(scope.grid.columns[1].name).toBe('gender');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
  });

  it('expect moveColumn() to not change position of columns if column position given is wrong', function () {
    spyOn(gridUtil, 'logError').andCallFake(function() {});
    scope.gridApi.colMovable.moveColumn(4, 5);
    expect(scope.grid.columns[0].name).toBe('name');
    expect(scope.grid.columns[1].name).toBe('gender');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
    expect(gridUtil.logError).toHaveBeenCalledWith('MoveColumn: Invalid values for originalPosition, finalPosition');
  });

  it('expect event columnPositionChanged to be called when column position is changed', function () {
    var functionCalled = false;
    scope.gridApi.colMovable.on.columnPositionChanged(scope, function (colDef, newPos, oldPos) {
      functionCalled = true;
    });
    scope.gridApi.colMovable.moveColumn(0, 1);
    timeout.flush();
    expect(functionCalled).toBe(true);
  });

  it('expect column to move right when dragged right', function () {
    var event = jQuery.Event("mousedown", {
      pageX: 0
    });
    var columnHeader = angular.element(element.find('.ui-grid-cell-contents')[0]);
    columnHeader.trigger(event);
    event = jQuery.Event("mousemove", {
      pageX: 200
    });
    document.trigger(event);
    document.trigger(event);
    event = jQuery.Event("mouseup");
    document.trigger(event);
    expect(scope.grid.columns[0].name).toBe('gender');
    expect(scope.grid.columns[1].name).toBe('age');
    expect(scope.grid.columns[2].name).toBe('name');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
  });

  it('expect column to move left when dragged left', function () {
    var event = jQuery.Event("mousedown", {
      pageX: 0
    });
    var columnHeader = angular.element(element.find('.ui-grid-cell-contents')[1]);
    columnHeader.trigger(event);
    event = jQuery.Event("mousemove", {
      pageX: -200
    });
    document.trigger(event);
    document.trigger(event);
    event = jQuery.Event("mouseup");
    document.trigger(event);
    expect(scope.grid.columns[0].name).toBe('gender');
    expect(scope.grid.columns[1].name).toBe('name');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
  });

  it('expect column movement to not happen if enableColumnMoving is false', function () {
    var event = jQuery.Event("mousedown", {
      pageX: 0
    });
    var columnHeader = angular.element(element.find('.ui-grid-cell-contents')[3]);
    columnHeader.trigger(event);
    event = jQuery.Event("mousemove", {
      pageX: 200
    });
    document.trigger(event);
    document.trigger(event);
    event = jQuery.Event("mouseup");
    document.trigger(event);
    expect(scope.grid.columns[0].name).toBe('name');
    expect(scope.grid.columns[1].name).toBe('gender');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
  });

  it('expect column movement to not happen if enableColumnMoving is changed to false', function() {
    scope.grid.options.enableColumnMoving = false;
    scope.gridApi.colMovable.moveColumn(0, 1);
    expect(scope.grid.columns[0].name).toBe('name');
    expect(scope.grid.columns[1].name).toBe('gender');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
  });

  it('expect column movement to happen if enableColumnMoving is changed to true', function() {
    scope.grid.options.enableColumnMoving = false;
    scope.grid.options.enableColumnMoving = true;
    scope.gridApi.colMovable.moveColumn(0, 1);
    expect(scope.grid.columns[0].name).toBe('gender');
    expect(scope.grid.columns[1].name).toBe('name');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
  });
});
<commit_msg>Disabled 2 tests that have issues since scrolling has been fixed.<commit_after>describe('ui.grid.moveColumns', function () {

  var scope, element, timeout, gridUtil, document, uiGridConstants;

  var data = [
    { "name": "Ethel Price", "gender": "female", "age": 25, "company": "Enersol", phone: '111'},
    { "name": "Claudine Neal", "gender": "female", "age": 30, "company": "Sealoud", phone: '111'},
    { "name": "Beryl Rice", "gender": "female", "age": 35, "company": "Velity", phone: '111'},
    { "name": "Wilder Gonzales", "gender": "male", "age": 40, "company": "Geekko", phone: '111'}
  ];

  beforeEach(module('ui.grid.moveColumns'));

  beforeEach(inject(function (_$compile_, $rootScope, $timeout, _gridUtil_, $document, _uiGridConstants_) {

    var $compile = _$compile_;
    scope = $rootScope;
    timeout = $timeout;
    gridUtil = _gridUtil_;
    document = $document;
    uiGridConstants = _uiGridConstants_;

    scope.gridOptions = {};
    scope.gridOptions.data = data;
    scope.gridOptions.columnDefs = [
      { field: 'name', width: 200 },
      { field: 'gender', width: 200 },
      { field: 'age', width: 200, visible: false},
      { field: 'company', enableColumnMoving: false, width: 200 },
      { field: 'phone', width: 200 }
    ];

    scope.gridOptions.onRegisterApi = function (gridApi) {
      scope.gridApi = gridApi;
      scope.grid = gridApi.grid;
    };

    element = angular.element('

');

    $timeout(function () {
      $compile(element)(scope);
    });
    $timeout.flush();
  }));

  it('grid api for columnMovable should be defined', function () {
    expect(scope.gridApi.colMovable).toBeDefined();
    expect(scope.gridApi.colMovable.on.columnPositionChanged).toBeDefined();
    expect(scope.gridApi.colMovable.raise.columnPositionChanged).toBeDefined();
    expect(scope.gridApi.colMovable.moveColumn).toBeDefined();
  });

  it('expect enableColumnMoving to be true by default', function () {
    expect(scope.grid.options.enableColumnMoving).toBe(true);
    expect(scope.grid.columns[0].colDef.enableColumnMoving).toBe(true);
    expect(scope.grid.columns[1].colDef.enableColumnMoving).toBe(true);
    expect(scope.grid.columns[2].colDef.enableColumnMoving).toBe(true);
    expect(scope.grid.columns[3].colDef.enableColumnMoving).toBe(false);
    expect(scope.grid.columns[4].colDef.enableColumnMoving).toBe(true);
  });

  it('expect moveColumn() to change position of columns', function () {
    scope.gridApi.colMovable.moveColumn(0, 1);
    expect(scope.grid.columns[0].name).toBe('gender');
    expect(scope.grid.columns[1].name).toBe('name');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
    scope.gridApi.colMovable.moveColumn(0, 3);
    expect(scope.grid.columns[0].name).toBe('name');
    expect(scope.grid.columns[1].name).toBe('age');
    expect(scope.grid.columns[2].name).toBe('company');
    expect(scope.grid.columns[3].name).toBe('phone');
    expect(scope.grid.columns[4].name).toBe('gender');
  });

  it('expect moveColumn() to persist after adding additional column', function () {
    scope.gridApi.colMovable.moveColumn(0, 1);
    scope.gridOptions.columnDefs.push({ field: 'name', displayName: 'name2', width: 200 });
    scope.gridApi.core.notifyDataChange( uiGridConstants.COLUMN );
    timeout.flush();
    scope.$digest();

    expect(scope.grid.columns[0].name).toBe('gender');
    expect(scope.grid.columns[1].name).toBe('name');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
    expect(scope.grid.columns[5].displayName).toBe('name2');
  });

  it('expect moveColumn() to not change position of columns if enableColumnMoving is false', function () {
    scope.gridApi.colMovable.moveColumn(2, 1);
    expect(scope.grid.columns[0].name).toBe('name');
    expect(scope.grid.columns[1].name).toBe('gender');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
  });

  it('expect moveColumn() to not change position of columns if column position given is wrong', function () {
    spyOn(gridUtil, 'logError').andCallFake(function() {});
    scope.gridApi.colMovable.moveColumn(4, 5);
    expect(scope.grid.columns[0].name).toBe('name');
    expect(scope.grid.columns[1].name).toBe('gender');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
    expect(gridUtil.logError).toHaveBeenCalledWith('MoveColumn: Invalid values for originalPosition, finalPosition');
  });

  it('expect event columnPositionChanged to be called when column position is changed', function () {
    var functionCalled = false;
    scope.gridApi.colMovable.on.columnPositionChanged(scope, function (colDef, newPos, oldPos) {
      functionCalled = true;
    });
    scope.gridApi.colMovable.moveColumn(0, 1);
    timeout.flush();
    expect(functionCalled).toBe(true);
  });

  // NOTE (nsartor) this test fails since scrolling is fixed. I believe it's caused by the
  // viewport size = 0, the elements want to scroll immediately.
  //it('expect column to move right when dragged right', function () {
    //var event = jQuery.Event("mousedown", {
      //pageX: 0
    //});
    //var columnHeader = angular.element(element.find('.ui-grid-cell-contents')[0]);
    //columnHeader.trigger(event);
    //event = jQuery.Event("mousemove", {
      //pageX: 200
    //});
    //document.trigger(event);
    //document.trigger(event);
    //event = jQuery.Event("mouseup");
    //document.trigger(event);
    //expect(scope.grid.columns[0].name).toBe('gender');
    //expect(scope.grid.columns[1].name).toBe('age');
    //expect(scope.grid.columns[2].name).toBe('name');
    //expect(scope.grid.columns[3].name).toBe('company');
    //expect(scope.grid.columns[4].name).toBe('phone');
  //});

  // NOTE (nsartor) same as above, I believe the cause is the viewport.
  //it('expect column to move left when dragged left', function () {
    //var event = jQuery.Event("mousedown", {
      //pageX: 0
    //});
    //var columnHeader = angular.element(element.find('.ui-grid-cell-contents')[1]);
    //columnHeader.trigger(event);
    //event = jQuery.Event("mousemove", {
      //pageX: -200
    //});
    //document.trigger(event);
    //document.trigger(event);
    //event = jQuery.Event("mouseup");
    //document.trigger(event);
    //expect(scope.grid.columns[0].name).toBe('gender');
    //expect(scope.grid.columns[1].name).toBe('name');
    //expect(scope.grid.columns[2].name).toBe('age');
    //expect(scope.grid.columns[3].name).toBe('company');
    //expect(scope.grid.columns[4].name).toBe('phone');
  //});

  it('expect column movement to not happen if enableColumnMoving is false', function () {
    var event = jQuery.Event("mousedown", {
      pageX: 0
    });
    var columnHeader = angular.element(element.find('.ui-grid-cell-contents')[3]);
    columnHeader.trigger(event);
    event = jQuery.Event("mousemove", {
      pageX: 200
    });
    document.trigger(event);
    document.trigger(event);
    event = jQuery.Event("mouseup");
    document.trigger(event);
    expect(scope.grid.columns[0].name).toBe('name');
    expect(scope.grid.columns[1].name).toBe('gender');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
  });

  it('expect column movement to not happen if enableColumnMoving is changed to false', function() {
    scope.grid.options.enableColumnMoving = false;
    scope.gridApi.colMovable.moveColumn(0, 1);
    expect(scope.grid.columns[0].name).toBe('name');
    expect(scope.grid.columns[1].name).toBe('gender');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
  });

  it('expect column movement to happen if enableColumnMoving is changed to true', function() {
    scope.grid.options.enableColumnMoving = false;
    scope.grid.options.enableColumnMoving = true;
    scope.gridApi.colMovable.moveColumn(0, 1);
    expect(scope.grid.columns[0].name).toBe('gender');
    expect(scope.grid.columns[1].name).toBe('name');
    expect(scope.grid.columns[2].name).toBe('age');
    expect(scope.grid.columns[3].name).toBe('company');
    expect(scope.grid.columns[4].name).toBe('phone');
  });
});
<|endoftext|>


<commit_before>/* globals _, bowser */
'use strict';

angular.module('metadatamanagementApp').controller('AttachmentDialogController',
  function(dialogConfig, isoLanguages, CommonDialogsService, LanguageService,
            SimpleMessageToastService, $scope, $mdDialog) {
    $scope.bowser = bowser;
    var ctrl = this;
    var isInitialisingSelectedLanguage = false;
    var uploadFile = dialogConfig.uploadCallback;

    ctrl.isCreateMode = dialogConfig.attachmentMetadata === undefined ||
        dialogConfig.attachmentMetadata === null;
    ctrl.attachmentForm = $scope.attachmentForm;
    ctrl.currentLanguage = LanguageService.getCurrentInstantly();
    ctrl.attachmentTypes = dialogConfig.attachmentTypes;
    ctrl.labels = dialogConfig.labels;
    ctrl.titleParams = ctrl.isCreateMode ?
        _.get(ctrl, 'labels.createTitle.params') :
        _.get(ctrl, 'labels.editTitle.params');
    ctrl.excludedMetadataFields = dialogConfig.exclude;

    ctrl.translationKeys = {
      title: 'data-package-management.detail.label.attachments.authors',
      tooltips: {
        delete: 'data-package-management.edit.delete-author-tooltip',
        add: 'data-package-management.edit.add-author-tooltip',
        moveUp: 'data-package-management.edit.move-author-up-tooltip',
        moveDown: 'data-package-management.edit.move-author-down-tooltip'
      },
      hints: {
        firstName: 'data-package-management.edit.hints.authors.first-name',
        middleName: 'data-package-management.edit.hints.authors.middle-name',
        lastName: 'data-package-management.edit.hints.authors.last-name'
      }
    };

    var isoLanguagesArray = Object.keys(isoLanguages).map(function(key) {
      return {
        code: key,
        'displayLanguage': isoLanguages[key]
      };
    });

    var initSelectedLanguage = function() {
      isInitialisingSelectedLanguage = true;
      ctrl.selectedLanguage = _.filter(isoLanguagesArray,
        function(isoLanguage) {
          return isoLanguage.code === ctrl.attachmentMetadata.language;
        })[0];
    };

    if (dialogConfig.attachmentMetadata) {
      ctrl.attachmentMetadata = angular.copy(dialogConfig.attachmentMetadata);
      ctrl.originalAttachmentMetadata = dialogConfig.attachmentMetadata;
      initSelectedLanguage();
    } else {
      ctrl.attachmentMetadata = {};
    }

    ctrl.cancel = function() {
      if ($scope.attachmentForm.$dirty) {
        CommonDialogsService.showConfirmOnDirtyDialog().then($mdDialog.cancel);
      } else {
        $mdDialog.cancel();
      }
    };

    ctrl.searchLanguages = function(searchText) {
      if (!searchText || searchText === '') {
        return isoLanguagesArray;
      }
      var lowerCasedSearchText = searchText.toLowerCase();
      return _.filter(isoLanguagesArray, function(isoLanguage) {
        return isoLanguage.displayLanguage[ctrl.currentLanguage]
          .toLowerCase().indexOf(lowerCasedSearchText) > -1;
      });
    };

    ctrl.setTitleForMethodReports = function() {
      if (ctrl.attachmentMetadata.language === 'de') {
        ctrl.attachmentMetadata.title =
          'Daten- und Methodenbericht des Datenpakets "' +
          dialogConfig.dataPackageTitle.de + '"';
      } else {
        ctrl.attachmentMetadata.title =
          'Data and Methods Report of the data package "' +
          dialogConfig.dataPackageTitle.en + '"';
      }
    };

    ctrl.selectedLanguageChanged = function() {
      if (ctrl.selectedLanguage) {
        ctrl.attachmentMetadata.language = ctrl.selectedLanguage.code;
        if (ctrl.titleParams.dataPackageId) {
          if (ctrl.attachmentMetadata.type.en === 'Method Report') {
            ctrl.setTitleForMethodReports();
          }
        }
      } else {
        delete ctrl.attachmentMetadata.language;
      }
      if (!isInitialisingSelectedLanguage) {
        $scope.attachmentForm.$setDirty();
      }
      isInitialisingSelectedLanguage = false;
    };

    ctrl.upload = function(file) {
      if (file.name !== ctrl.attachmentMetadata.fileName &&
        !ctrl.isCreateMode) {
        CommonDialogsService.showConfirmFilenameChangedDialog(
          ctrl.attachmentMetadata.fileName, file.name).then(
          function() {
            ctrl.isCreateMode = true;
            ctrl.selectedFile = file;
            ctrl.attachmentMetadata.fileName = file.name;
            $scope.attachmentForm.filename.$setDirty();
            $scope.attachmentForm.filename.$setValidity(
              'valid', true);
            $scope.attachmentForm.filename.$setValidity(
              'unique', true);
          }
        );
      } else {
        ctrl.selectedFile = file;
        ctrl.attachmentMetadata.fileName = file.name;
        $scope.attachmentForm.filename.$setDirty();
        $scope.attachmentForm.filename.$setValidity(
          'valid', true);
        $scope.attachmentForm.filename.$setValidity(
          'unique', true);
      }
    };

    ctrl.saveAttachment = function() {
      if ($scope.attachmentForm.$valid) {
        if (!ctrl.selectedFile) {
          ctrl.attachmentMetadata.$save().then(ctrl.onSavedSuccessfully);
        } else {
          if (ctrl.originalAttachmentMetadata) {
            ctrl.originalAttachmentMetadata.$delete().then(function() {
              uploadFile(ctrl.selectedFile, ctrl.attachmentMetadata)
                .then(ctrl.onSavedSuccessfully).catch(ctrl.onUploadFailed);
            });
          } else {
            uploadFile(ctrl.selectedFile, ctrl.attachmentMetadata)
                .then(ctrl.onSavedSuccessfully).catch(ctrl.onUploadFailed);
          }
        }
      } else {
        // ensure that all validation errors are visible
        angular.forEach($scope.attachmentForm.$error, function(field) {
          angular.forEach(field, function(errorField) {
            errorField.$setTouched();
          });
        });
        SimpleMessageToastService.openAlertMessageToast(
          'attachment.error.attachment-has-validation-errors-toast');
      }
    };

    ctrl.onSavedSuccessfully = function() {
      $mdDialog.hide(ctrl.attachmentMetadata);
      SimpleMessageToastService.openSimpleMessageToast(
        'attachment.attachment-saved-toast',
        {
          filename: ctrl.attachmentMetadata.fileName
        });
    };

    ctrl.onUploadFailed = function(response) {
      if (response.invalidFile) {
        SimpleMessageToastService.openAlertMessageToast(
          'attachment.error.file-not-found',
          {
            filename: ctrl.attachmentMetadata.fileName
          });
        $scope.attachmentForm.filename.$setValidity(
          'valid', false);
      }
      if (response.errors && response.errors.length > 0) {
        SimpleMessageToastService.openAlertMessageToast(
          response.errors[0].message,
          {
            filename: ctrl.attachmentMetadata.fileName
          });
        $scope.attachmentForm.filename.$setValidity(
          'unique', false);
      }
    };

    ctrl.openRestorePreviousVersionDialog = function(event) {
      $mdDialog.show({
        controller: 'ChoosePreviousAttachmentVersionController',
        templateUrl: 'scripts/common/dialogs/choose-previous-attachment' +
            '-version/choose-attachment-version.html.tmpl',
        clickOutsideToClose: false,
        fullscreen: true,
        locals: {
          domainId: ctrl.attachmentMetadata[dialogConfig
              .attachmentDomainIdAttribute],
          filename: dialogConfig.attachmentMetadata.fileName,
          getAttachmentVersionsCallback: dialogConfig
              .getAttachmentVersionsCallback
        },
        multiple: true,
        targetEvent: event
      })
      .then(function(attachmentWrapper) {
        ctrl.attachmentMetadata = dialogConfig
            .createAttachmentResource(attachmentWrapper);
        initSelectedLanguage();
        if (ctrl.attachmentMetadata.type.en === 'Method Report') {
          ctrl.attachmentMetadata.citationDetails =
            ctrl.attachmentMetadata.citationDetails || {};
          ctrl.attachmentMetadata.citationDetails.authors =
            ctrl.attachmentMetadata.citationDetails.authors || [];
          if (ctrl.attachmentMetadata.citationDetails.authors.length === 0) {
            ctrl.attachmentMetadata.citationDetails.authors.push({
              firstName: '',
              lastName: ''
            });
          }
        }
        if (attachmentWrapper.isCurrentVersion) {
          SimpleMessageToastService.openSimpleMessageToast(
              'attachment.current-version-restored-toast',
              {
                filename: ctrl.attachmentMetadata.fileName
              });
          $scope.attachmentForm.$setPristine();
        } else {
          $scope.attachmentForm.$setDirty();
          SimpleMessageToastService.openSimpleMessageToast(
              'attachment.previous-version-restored-toast',
              {
                filename: ctrl.attachmentMetadata.fileName
              });
        }
      });
    };

    ctrl.onTypeChanged = function() {
      if (ctrl.titleParams.dataPackageId) {
        if (ctrl.attachmentMetadata.type.en === 'Method Report') {
          ctrl.setTitleForMethodReports();
          ctrl.attachmentMetadata.description = {
            de: 'Der Bericht umfasst Datennutzungshinweise und weitere' +
            ' Informationen zum Datenpaket.',
            en: 'The report includes data usage notes and further ' +
            'information on the data package.'
          };
        } else {
          delete ctrl.attachmentMetadata.citationDetails;
        }
        if (ctrl.attachmentMetadata.type.en === 'Release Notes') {
          ctrl.attachmentMetadata.title = 'Release Notes';
          ctrl.attachmentMetadata.language = 'de';
          ctrl.selectedLanguage = _.filter(isoLanguagesArray,
            function(isoLanguage) {
              return isoLanguage.code === ctrl.attachmentMetadata.language;
            })[0];
          ctrl.attachmentMetadata.description = {
            de: 'Die Release Notes enthalten Informationen zur aktuellen ' +
            'Version und zu Veränderungen im Vergleich zu vorherigen' +
            ' Versionen.',
            en: 'The release notes contain information about the current' +
            ' version and changes compared to previous versions. '
          };
        }
      }
    };
  });
<commit_msg>#2979 fix toasts and save button<commit_after>/* globals _, bowser */
'use strict';

angular.module('metadatamanagementApp').controller('AttachmentDialogController',
  function(dialogConfig, isoLanguages, CommonDialogsService, LanguageService,
            SimpleMessageToastService, $scope, $mdDialog) {
    $scope.bowser = bowser;
    var ctrl = this;
    var isInitialisingSelectedLanguage = false;
    var uploadFile = dialogConfig.uploadCallback;

    ctrl.isCreateMode = dialogConfig.attachmentMetadata === undefined ||
        dialogConfig.attachmentMetadata === null;
    ctrl.attachmentForm = $scope.attachmentForm;
    ctrl.currentLanguage = LanguageService.getCurrentInstantly();
    ctrl.attachmentTypes = dialogConfig.attachmentTypes;
    ctrl.labels = dialogConfig.labels;
    ctrl.titleParams = ctrl.isCreateMode ?
        _.get(ctrl, 'labels.createTitle.params') :
        _.get(ctrl, 'labels.editTitle.params');
    ctrl.excludedMetadataFields = dialogConfig.exclude;

    ctrl.translationKeys = {
      title: 'data-package-management.detail.label.attachments.authors',
      tooltips: {
        delete: 'data-package-management.edit.delete-author-tooltip',
        add: 'data-package-management.edit.add-author-tooltip',
        moveUp: 'data-package-management.edit.move-author-up-tooltip',
        moveDown: 'data-package-management.edit.move-author-down-tooltip'
      },
      hints: {
        firstName: 'data-package-management.edit.hints.authors.first-name',
        middleName: 'data-package-management.edit.hints.authors.middle-name',
        lastName: 'data-package-management.edit.hints.authors.last-name'
      }
    };

    var isoLanguagesArray = Object.keys(isoLanguages).map(function(key) {
      return {
        code: key,
        'displayLanguage': isoLanguages[key]
      };
    });

    var initSelectedLanguage = function() {
      isInitialisingSelectedLanguage = true;
      ctrl.selectedLanguage = _.filter(isoLanguagesArray,
        function(isoLanguage) {
          return isoLanguage.code === ctrl.attachmentMetadata.language;
        })[0];
    };

    if (dialogConfig.attachmentMetadata) {
      ctrl.attachmentMetadata = angular.copy(dialogConfig.attachmentMetadata);
      ctrl.originalAttachmentMetadata = dialogConfig.attachmentMetadata;
      initSelectedLanguage();
    } else {
      ctrl.attachmentMetadata = {};
    }

    ctrl.cancel = function() {
      if ($scope.attachmentForm.$dirty) {
        CommonDialogsService.showConfirmOnDirtyDialog().then($mdDialog.cancel);
      } else {
        $mdDialog.cancel();
      }
    };

    ctrl.searchLanguages = function(searchText) {
      if (!searchText || searchText === '') {
        return isoLanguagesArray;
      }
      var lowerCasedSearchText = searchText.toLowerCase();
      return _.filter(isoLanguagesArray, function(isoLanguage) {
        return isoLanguage.displayLanguage[ctrl.currentLanguage]
          .toLowerCase().indexOf(lowerCasedSearchText) > -1;
      });
    };

    ctrl.setTitleForMethodReports = function() {
      if (ctrl.attachmentMetadata.language === 'de') {
        ctrl.attachmentMetadata.title =
          'Daten- und Methodenbericht des Datenpakets "' +
          dialogConfig.dataPackageTitle.de + '"';
      } else {
        ctrl.attachmentMetadata.title =
          'Data and Methods Report of the data package "' +
          dialogConfig.dataPackageTitle.en + '"';
      }
    };

    ctrl.selectedLanguageChanged = function() {
      if (ctrl.selectedLanguage) {
        ctrl.attachmentMetadata.language = ctrl.selectedLanguage.code;
        if (ctrl.titleParams.dataPackageId) {
          if (ctrl.attachmentMetadata.type.en === 'Method Report') {
            ctrl.setTitleForMethodReports();
          }
        }
      } else {
        delete ctrl.attachmentMetadata.language;
      }
      if (!isInitialisingSelectedLanguage) {
        $scope.attachmentForm.$setDirty();
      }
      isInitialisingSelectedLanguage = false;
    };

    ctrl.upload = function(file) {
      if (file.name !== ctrl.attachmentMetadata.fileName &&
        !ctrl.isCreateMode) {
        CommonDialogsService.showConfirmFilenameChangedDialog(
          ctrl.attachmentMetadata.fileName, file.name).then(
          function() {
            ctrl.isCreateMode = true;
            ctrl.selectedFile = file;
            ctrl.attachmentMetadata.fileName = file.name;
            $scope.attachmentForm.filename.$setDirty();
            $scope.attachmentForm.filename.$setValidity(
              'valid', true);
            $scope.attachmentForm.filename.$setValidity(
              'unique', true);
          }
        );
      } else {
        ctrl.selectedFile = file;
        ctrl.attachmentMetadata.fileName = file.name;
        $scope.attachmentForm.filename.$setDirty();
        $scope.attachmentForm.filename.$setValidity(
          'valid', true);
        $scope.attachmentForm.filename.$setValidity(
          'unique', true);
      }
    };

    ctrl.saveAttachment = function() {
      if ($scope.attachmentForm.$valid) {
        if (!ctrl.selectedFile) {
          ctrl.attachmentMetadata.$save().then(ctrl.onSavedSuccessfully);
        } else {
          if (ctrl.originalAttachmentMetadata) {
            ctrl.originalAttachmentMetadata.$delete().then(function() {
              uploadFile(ctrl.selectedFile, ctrl.attachmentMetadata)
                .then(ctrl.onSavedSuccessfully).catch(ctrl.onUploadFailed);
            });
          } else {
            uploadFile(ctrl.selectedFile, ctrl.attachmentMetadata)
                .then(ctrl.onSavedSuccessfully).catch(ctrl.onUploadFailed);
          }
        }
      } else {
        // ensure that all validation errors are visible
        angular.forEach($scope.attachmentForm.$error, function(field) {
          angular.forEach(field, function(errorField) {
            errorField.$setTouched();
          });
        });
        SimpleMessageToastService.openAlertMessageToast(
          'attachment.error.attachment-has-validation-errors-toast');
      }
    };

    ctrl.onSavedSuccessfully = function() {
      $mdDialog.hide(ctrl.attachmentMetadata);
      SimpleMessageToastService.openSimpleMessageToast(
        'attachment.attachment-saved-toast',
        {
          filename: ctrl.attachmentMetadata.fileName
        });
    };

    ctrl.onUploadFailed = function(response) {
      if (response.invalidFile) {
        SimpleMessageToastService.openAlertMessageToast(
          'attachment.error.file-not-found',
          {
            filename: ctrl.attachmentMetadata.fileName
          });
        $scope.attachmentForm.filename.$setValidity(
          'valid', false);
      }
      if (response.errors && response.errors.length > 0) {
        SimpleMessageToastService.openAlertMessageToast(
          response.errors[0].message,
          {
            filename: ctrl.attachmentMetadata.fileName
          });
        $scope.attachmentForm.filename.$setValidity(
          'unique', false);
      }
    };

    ctrl.openRestorePreviousVersionDialog = function(event) {
      $mdDialog.show({
        controller: 'ChoosePreviousAttachmentVersionController',
        templateUrl: 'scripts/common/dialogs/choose-previous-attachment' +
            '-version/choose-attachment-version.html.tmpl',
        clickOutsideToClose: false,
        fullscreen: true,
        locals: {
          domainId: ctrl.attachmentMetadata[dialogConfig
              .attachmentDomainIdAttribute],
          filename: dialogConfig.attachmentMetadata.fileName,
          getAttachmentVersionsCallback: dialogConfig
              .getAttachmentVersionsCallback
        },
        multiple: true,
        targetEvent: event
      })
      .then(function(attachmentWrapper) {
        ctrl.attachmentMetadata = dialogConfig
            .createAttachmentResource(attachmentWrapper);
        initSelectedLanguage();
        if (ctrl.attachmentMetadata.type &&
          ctrl.attachmentMetadata.type.en === 'Method Report') {
          ctrl.attachmentMetadata.citationDetails =
            ctrl.attachmentMetadata.citationDetails || {};
          ctrl.attachmentMetadata.citationDetails.authors =
            ctrl.attachmentMetadata.citationDetails.authors || [];
          if (ctrl.attachmentMetadata.citationDetails.authors.length === 0) {
            ctrl.attachmentMetadata.citationDetails.authors.push({
              firstName: '',
              lastName: ''
            });
          }
        }
        if (attachmentWrapper.isCurrentVersion) {
          SimpleMessageToastService.openSimpleMessageToast(
              'attachment.current-version-restored-toast',
              {
                filename: ctrl.attachmentMetadata.fileName
              });
          $scope.attachmentForm.$setPristine();
        } else {
          $scope.attachmentForm.$setDirty();
          SimpleMessageToastService.openSimpleMessageToast(
              'attachment.previous-version-restored-toast',
              {
                filename: ctrl.attachmentMetadata.fileName
              });
        }
      });
    };

    ctrl.onTypeChanged = function() {
      if (ctrl.titleParams.dataPackageId) {
        if (ctrl.attachmentMetadata.type.en === 'Method Report') {
          ctrl.setTitleForMethodReports();
          ctrl.attachmentMetadata.description = {
            de: 'Der Bericht umfasst Datennutzungshinweise und weitere' +
            ' Informationen zum Datenpaket.',
            en: 'The report includes data usage notes and further ' +
            'information on the data package.'
          };
        } else {
          delete ctrl.attachmentMetadata.citationDetails;
        }
        if (ctrl.attachmentMetadata.type.en === 'Release Notes') {
          ctrl.attachmentMetadata.title = 'Release Notes';
          ctrl.attachmentMetadata.language = 'de';
          ctrl.selectedLanguage = _.filter(isoLanguagesArray,
            function(isoLanguage) {
              return isoLanguage.code === ctrl.attachmentMetadata.language;
            })[0];
          ctrl.attachmentMetadata.description = {
            de: 'Die Release Notes enthalten Informationen zur aktuellen ' +
            'Version und zu Veränderungen im Vergleich zu vorherigen' +
            ' Versionen.',
            en: 'The release notes contain information about the current' +
            ' version and changes compared to previous versions. '
          };
        }
      }
    };
  });
<|endoftext|>


<commit_before>// ==UserScript==
// @name         10wallpaper downloader
// @namespace    http://baivong.github.io/
// @version      2.1.0
// @description  1-Click download on 10wallpaper. You should select the resolution before downloading.
// @icon         http://i.imgur.com/08zfJez.png
// @author       Zzbaivong
// @oujs:author  baivong
// @license      MIT; https://baivong.mit-license.org/license.txt
// @match        http://10wallpaper.com/*
// @match        http://www.10wallpaper.com/*
// @match        https://10wallpaper.com/*
// @match        https://www.10wallpaper.com/*
// @require      https://unpkg.com/file-saver@1.3.8/FileSaver.min.js
// @require      https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js?v=a834d46
// @noframes
// @supportURL   https://github.com/lelinhtinh/Userscript/issues
// @run-at       document-idle
// @grant        GM.xmlHttpRequest
// @grant        GM.openInTab
// ==/UserScript==

(function () {
    'use strict';

    /**
     * Resolution config
     * @type {String} // Eg: 1920x1200, 1366x768, 1280x1024, ...
     */
    var resolution = '';

    // Do not change the code below this line, unless you know how.
    var list = document.querySelectorAll('a[href^="/view/"]'),
        res = location.pathname.match(/\d+x\d+/);
    if (!/\d+x\d+/.test(resolution)) resolution = screen.width + 'x' + screen.height;
    res = !res ? resolution : res[0];

    [].forEach.call(list, function (link) {
        var info = link.querySelector('span'),
            infoContent = info.innerHTML,
            img = link.querySelector('img'),
            imgName;

        if (!img) return;
        img = img.src.replace(/(\/|_)(small|medium)(\/|\.)/g, '$1' + res + '$3');
        imgName = img.replace(/.*\//, '');

        link.addEventListener('click', function (e) {
            e.preventDefault();
            info.innerHTML = 'Downloading...';

            GM.xmlHttpRequest({
                method: 'GET',
                url: img,
                responseType: 'blob',
                onprogress: function (e) {
                    var percent = Math.round((e.loaded / e.total) * 100);
                    info.innerHTML = percent + ' %';
                },
                onload: function (response) {
                    var blob = response.response;

                    info.innerHTML = infoContent;
                    link.setAttribute('href', URL.createObjectURL(blob));
                    link.setAttribute('download', imgName);

                    saveAs(blob, imgName);
                },
                onerror: function (err) {
                    console.error(err);
                }
            });
        });

        link.addEventListener('contextmenu', function (e) {
            e.preventDefault();
            GM.openInTab(img);
        });

        link.setAttribute('title', 'Click to download this image\nRight Click to open in new tab');
    });
})();
<commit_msg>Update 10wallpaper_downloader.user.js<commit_after>// ==UserScript==
// @name         10wallpaper downloader
// @namespace    http://baivong.github.io/
// @version      2.1.1
// @description  1-Click download on 10wallpaper. You should select the resolution before downloading.
// @icon         http://i.imgur.com/08zfJez.png
// @author       Zzbaivong
// @oujs:author  baivong
// @license      MIT; https://baivong.mit-license.org/license.txt
// @match        http://10wallpaper.com/*
// @match        http://www.10wallpaper.com/*
// @match        https://10wallpaper.com/*
// @match        https://www.10wallpaper.com/*
// @require      https://unpkg.com/file-saver@1.3.8/FileSaver.min.js
// @require      https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js?v=a834d46
// @noframes
// @connect      self
// @supportURL   https://github.com/lelinhtinh/Userscript/issues
// @run-at       document-idle
// @grant        GM.xmlHttpRequest
// @grant        GM.openInTab
// ==/UserScript==

(function () {
    'use strict';

    /**
     * Resolution config
     * @type {String} // Eg: 1920x1200, 1366x768, 1280x1024, ...
     */
    var resolution = '';

    // Do not change the code below this line, unless you know how.
    var list = document.querySelectorAll('a[href^="/view/"]'),
        res = location.pathname.match(/\d+x\d+/);
    if (!/\d+x\d+/.test(resolution)) resolution = screen.width + 'x' + screen.height;
    res = !res ? resolution : res[0];

    [].forEach.call(list, function (link) {
        var info = link.querySelector('span'),
            infoContent = info.innerHTML,
            img = link.querySelector('img'),
            imgName;

        if (!img) return;
        img = img.src.replace(/(\/|_)(small|medium)(\/|\.)/g, '$1' + res + '$3');
        imgName = img.replace(/.*\//, '');

        link.addEventListener('click', function (e) {
            e.preventDefault();
            info.innerHTML = 'Downloading...';

            GM.xmlHttpRequest({
                method: 'GET',
                url: img,
                responseType: 'blob',
                onprogress: function (e) {
                    var percent = Math.round((e.loaded / e.total) * 100);
                    info.innerHTML = percent + ' %';
                },
                onload: function (response) {
                    var blob = response.response;

                    info.innerHTML = infoContent;
                    link.setAttribute('href', URL.createObjectURL(blob));
                    link.setAttribute('download', imgName);

                    saveAs(blob, imgName);
                },
                onerror: function (err) {
                    console.error(err);
                }
            });
        });

        link.addEventListener('contextmenu', function (e) {
            e.preventDefault();
            GM.openInTab(img);
        });

        link.setAttribute('title', 'Click to download this image\nRight Click to open in new tab');
    });
})();
<|endoftext|>