<commit_before>import React from 'react'
import Modal from 'app/components/modal'
import store from 'app/utils/store'
import i18n from 'app/utils/i18n'
import PropTypes from 'prop-types'

class EditUser extends React.Component{
  handleEditUser(ev){
    ev.preventDefault()
    const props=this.props
    const show_is_active = props.user.email != store.getState().auth.user.email
    let is_active = props.user.is_active
    if (show_is_active)
      is_active = $(this.refs.is_active).find('input').is(':checked')  ? true : false

    let $form = $(this.refs.form)
    props.onUpdateUser( props.user.email, {
      name: $form.find('[name=name]').val(),
      is_active,
    } )
    props.onClose()
  }
  componentDidMount(){
    let $form = $(this.refs.form)
    $form.form({
      on:'blur',
      fields:{
        email: 'email'
      }
    })
    $(this.refs.is_active).checkbox()
  }
  render(){
    const props=this.props

    // Only show if not current user
    const show_is_active = props.user.email != store.getState().auth.user.email

    return (
      <Modal onClose={props.onClose}>

Edit {props.user.name}

            {show_is_active ? (

                  Is active
                  <input type="checkbox" name="is_active" defaultChecked={props.user.is_active}/>

            ) : []}

              {i18n("Email")}
              <input disabled="true" type="email" name="email" defaultValue={props.user.email} placeholder={i18n("This will be used as the user identifier")}/>

              {i18n("First Name")}
              <input type="text" name="name" defaultValue={props.user.name}/>

            <button className="ui accept teal button" onClick={this.handleEditUser.bind(this)}>{i18n("Update user")}</button>

      </Modal>
    )
  }
}

EditUser.PropTypes = {
  onUpdateUser: PropTypes.func.isRequired,
  user: PropTypes.object.isRequired
}

export default EditUser
<commit_msg>Can modify users email<commit_after>import React from 'react'
import Modal from 'app/components/modal'
import store from 'app/utils/store'
import i18n from 'app/utils/i18n'
import PropTypes from 'prop-types'
import {has_perm} from 'app/utils/perms'

class EditUser extends React.Component{
  handleEditUser(ev){
    ev.preventDefault()
    const props=this.props
    const show_is_active = props.user.email != store.getState().auth.user.email
    let is_active = props.user.is_active
    if (show_is_active)
      is_active = $(this.refs.is_active).find('input').is(':checked')  ? true : false

    let $form = $(this.refs.form)
    let changes = {
      name: $form.find('[name=name]').val(),
      is_active,
    }
    if (has_perm("auth.modify_any"))
      changes.email = $form.find('[name=email]').val()

    props.onUpdateUser( props.user.email, changes )
    props.onClose()
  }
  componentDidMount(){
    let $form = $(this.refs.form)
    $form.form({
      on:'blur',
      fields:{
        email: 'email'
      }
    })
    $(this.refs.is_active).checkbox()
  }
  render(){
    const props=this.props

    // Only show if not current user
    const show_is_active = props.user.email != store.getState().auth.user.email

    return (
      <Modal onClose={props.onClose}>

Edit {props.user.name}

            {show_is_active ? (

                  Is active
                  <input type="checkbox" name="is_active" defaultChecked={props.user.is_active}/>

            ) : []}

              {i18n("Email")}
              <input disabled={!has_perm("auth.modify_any")} type="email" name="email" defaultValue={props.user.email} placeholder={i18n("This will be used as the user identifier")}/>

              {i18n("First Name")}
              <input type="text" name="name" defaultValue={props.user.name}/>

            <button className="ui accept teal button" onClick={this.handleEditUser.bind(this)}>{i18n("Update user")}</button>

      </Modal>
    )
  }
}

EditUser.PropTypes = {
  onUpdateUser: PropTypes.func.isRequired,
  user: PropTypes.object.isRequired
}

export default EditUser
<|endoftext|>


<commit_before>import { loadScript } from 'utils/deferred_load.js'
import { ChromecastMessageType, chromecastCustomMessageBus } from 'chromecast/messages.js'

const chromecastSdkReceiverJsUrl = '//www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js'

export const ReceiverEvent = {
  Ready: 'receiver-ready'
}

export default class ChromecastReceiver {

  constructor() {
    riot.observable(this)

    loadScript(chromecastSdkReceiverJsUrl)
      .then(() => this._initialize())

    this.on(ChromecastMessageType.Watch, data => riot.route(`/${data.channel}`))
  }

  _initialize() {
    cast.player.api.setLoggerLevel(cast.player.api.LoggerLevel.NONE)

    // The castManager allows communication with the sender application
    let castManager = cast.receiver.CastReceiverManager.getInstance()

    // Setting up a custom message bus to communicate with the sender application
    let customMessageBus = castManager.getCastMessageBus(chromecastCustomMessageBus)
    customMessageBus.onMessage = this._handleCustomMessages.bind(this)

    castManager.start()

    this.trigger(ReceiverEvent.Ready)
  }

  _handleCustomMessages(event) {
    let message = JSON.parse(event.data)

    this.trigger(message.type, message.data)
  }

}
<commit_msg>Removed a useless call to the media library in the receiver<commit_after>import { loadScript } from 'utils/deferred_load.js'
import { ChromecastMessageType, chromecastCustomMessageBus } from 'chromecast/messages.js'

const chromecastSdkReceiverJsUrl = '//www.gstatic.com/cast/sdk/libs/receiver/2.0.0/cast_receiver.js'

export const ReceiverEvent = {
  Ready: 'receiver-ready'
}

export default class ChromecastReceiver {

  constructor() {
    riot.observable(this)

    loadScript(chromecastSdkReceiverJsUrl)
      .then(() => this._initialize())

    this.on(ChromecastMessageType.Watch, data => riot.route(`/${data.channel}`))
  }

  _initialize() {
    // The castManager allows communication with the sender application
    let castManager = cast.receiver.CastReceiverManager.getInstance()

    // Setting up a custom message bus to communicate with the sender application
    let customMessageBus = castManager.getCastMessageBus(chromecastCustomMessageBus)
    customMessageBus.onMessage = this._handleCustomMessages.bind(this)

    castManager.start()

    this.trigger(ReceiverEvent.Ready)
  }

  _handleCustomMessages(event) {
    let message = JSON.parse(event.data)

    this.trigger(message.type, message.data)
  }

}
<|endoftext|>


<commit_before>// Create metadata graphics for a query
function metadataGraphics(item) {
    console.log("metadataGraphics()");

    dojo.xhrGet({
        url: "services/metadata/",
        handleAs: "json",
        // TODO: it's better not to pass the search parameters here. See also TODO in backend.
        content: item,
    }).then(function(response) {
        // Describe what is being visualised
        $('#metadata_top').text('Metadata for query "' + item.query + '"');

        // Add pie charts
        var filtered = {
            types: !(item.st_advert && item.st_article &&
                     item.st_family && item.st_illust),
            distrib: !(item.sd_antilles && item.sd_indonesia &&
                       item.sd_national && item.sd_regional && item.sd_surinam),
            pillars: !!(item.pillars.length)
        };
        addPieChart(
            filtered.types,
            response.articletype.buckets,
            "#chart_articletype"
        );
        addPieChart(
            filtered.distrib,
            response.distribution.buckets,
            "#chart_distribution"
        );
        addPieChart(
            filtered.pillars,
            response.pillar,
            "#chart_pillar"
        );

        // Create newspapers bar chart
        data_newspapers = [{
            "key": "Newspapers",
            "values": response.newspapers.buckets
        }];

        nv.addGraph(function() {
            var chart = nv.models.multiBarHorizontalChart()
                .x(function(d) {
                    return d.key;
                })
                .y(function(d) {
                    return d.doc_count;
                })
                .margin({
                    top: 30,
                    right: 20,
                    bottom: 50,
                    left: 175
                })
                .valueFormat(d3.format(",d"))
                .showValues(true)
                .tooltips(true);

            chart.yAxis
                .tickFormat(d3.format(",d"));

            d3.select("#chart_newspapers svg")
                .datum(data_newspapers)
                .call(chart);

            nv.utils.windowResize(chart.update);

            return chart;
        });
    }, function(err) {
        console.error(err);
    });
}

// Create a pie chart for a set of data points
function addPieChart(filtered, data, id) {
    nv.addGraph(function() {
        var chart = nv.models.pieChart()
            .x(function(d) {
                return d.key;
            })
            .y(function(d) {
                return d.doc_count;
            })
            .valueFormat(d3.format(",d"))
            .showLabels(true);

        if (filtered) {
            $(id).find('.filter-reset-btn').show();
        } else {
            chart.pie.dispatch.on('elementClick', filterSearch(id));
            $(id).find('.filter-reset-btn').hide();
        }

        d3.select(id + " svg")
            .datum(data)
            .transition().duration(1200)
            .call(chart);

        return chart;
    });
}

// Issue a new search when a pie segment is clicked, filtered by the segment
function filterSearch(id) {
    if (id === "#chart_articletype") return function(segmentData) {
        var selected = ES_REVERSE_MAPPING.st[segmentData.label].slice(3);
        for (key in config.search.type) {
            if (key === selected) {
                config.search.type[key] = true;
            } else {
                config.search.type[key] = false;
            }
        }
        searchSubmit();
    }; else if (id === "#chart_distribution") return function(segmentData) {
        var selected = ES_REVERSE_MAPPING.sd[segmentData.label].slice(3);
        for (key in config.search.distrib) {
            if (key === selected) {
                config.search.distrib[key] = true;
            } else {
                config.search.distrib[key] = false;
            }
        }
        searchSubmit();
    }; else /* id === "#chart_pillar" */ return function(segmentData) {
        getToolbarConfig();  // ensure that the checkboxes exist
        var selectedID = 'cb-pillar-' + segmentData.label;
        $('.pillar input').each(function(i) {
            var elem = $(this);
            if (elem.attr('id') === selectedID) {
                elem.prop('checked', true);
            } else {
                elem.prop('checked', false);
            }
        });
        searchSubmit();
    };
}
<commit_msg>Removing pop-ups, more room for newspapers, resolves #84<commit_after>// Create metadata graphics for a query
function metadataGraphics(item) {
    console.log("metadataGraphics()");

    dojo.xhrGet({
        url: "services/metadata/",
        handleAs: "json",
        // TODO: it's better not to pass the search parameters here. See also TODO in backend.
        content: item,
    }).then(function(response) {
        // Describe what is being visualised
        $('#metadata_top').text('Metadata for query "' + item.query + '"');

        // Add pie charts
        var filtered = {
            types: !(item.st_advert && item.st_article &&
                     item.st_family && item.st_illust),
            distrib: !(item.sd_antilles && item.sd_indonesia &&
                       item.sd_national && item.sd_regional && item.sd_surinam),
            pillars: !!(item.pillars.length)
        };
        addPieChart(
            filtered.types,
            response.articletype.buckets,
            "#chart_articletype"
        );
        addPieChart(
            filtered.distrib,
            response.distribution.buckets,
            "#chart_distribution"
        );
        addPieChart(
            filtered.pillars,
            response.pillar,
            "#chart_pillar"
        );

        // Create newspapers bar chart
        data_newspapers = [{
            "key": "Newspapers",
            "values": response.newspapers.buckets
        }];

        nv.addGraph(function() {
            var chart = nv.models.multiBarHorizontalChart()
                .x(function(d) {
                    return d.key;
                })
                .y(function(d) {
                    return d.doc_count;
                })
                .margin({
                    top: 30,
                    right: 20,
                    bottom: 50,
                    left: 200
                })
                .valueFormat(d3.format(",d"))
                .showValues(true)
                .showControls(false);

            chart.yAxis
                .tickFormat(d3.format(",d"));

            d3.select("#chart_newspapers svg")
                .datum(data_newspapers)
                .call(chart);

            nv.utils.windowResize(chart.update);

            return chart;
        });
    }, function(err) {
        console.error(err);
    });
}

// Create a pie chart for a set of data points
function addPieChart(filtered, data, id) {
    nv.addGraph(function() {
        var chart = nv.models.pieChart()
            .x(function(d) {
                return d.key;
            })
            .y(function(d) {
                return d.doc_count;
            })
            .valueFormat(d3.format(",d"))
            .showLabels(true);

        if (filtered) {
            $(id).find('.filter-reset-btn').show();
        } else {
            chart.pie.dispatch.on('elementClick', filterSearch(id));
            $(id).find('.filter-reset-btn').hide();
        }

        d3.select(id + " svg")
            .datum(data)
            .transition().duration(1200)
            .call(chart);

        return chart;
    });
}

// Issue a new search when a pie segment is clicked, filtered by the segment
function filterSearch(id) {
    if (id === "#chart_articletype") return function(segmentData) {
        var selected = ES_REVERSE_MAPPING.st[segmentData.label].slice(3);
        for (key in config.search.type) {
            if (key === selected) {
                config.search.type[key] = true;
            } else {
                config.search.type[key] = false;
            }
        }
        searchSubmit();
    }; else if (id === "#chart_distribution") return function(segmentData) {
        var selected = ES_REVERSE_MAPPING.sd[segmentData.label].slice(3);
        for (key in config.search.distrib) {
            if (key === selected) {
                config.search.distrib[key] = true;
            } else {
                config.search.distrib[key] = false;
            }
        }
        searchSubmit();
    }; else /* id === "#chart_pillar" */ return function(segmentData) {
        getToolbarConfig();  // ensure that the checkboxes exist
        var selectedID = 'cb-pillar-' + segmentData.label;
        $('.pillar input').each(function(i) {
            var elem = $(this);
            if (elem.attr('id') === selectedID) {
                elem.prop('checked', true);
            } else {
                elem.prop('checked', false);
            }
        });
        searchSubmit();
    };
}
<|endoftext|>


<commit_before>pc.extend(pc, function () {
    var id = 0;

    /**
     * @name pc.Material
     * @class A material.
     */
    var Material = function Material() {
        this.name = "Untitled";
        this.id = id++;
        this.shader = null;

        this.parameters = {};

        // Render states
        this.alphaTest = 0;

        this.blend = false;
        this.blendSrc = pc.BLENDMODE_ONE;
        this.blendDst = pc.BLENDMODE_ZERO;
        this.blendEquation = pc.BLENDEQUATION_ADD;

        this.cull = pc.CULLFACE_BACK;

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

        this.redWrite = true;
        this.greenWrite = true;
        this.blueWrite = true;
        this.alphaWrite = true;
        this.mask = 1;

        this.meshInstances = []; // The mesh instances referencing this material
    };

    Object.defineProperty(Material.prototype, 'blendType', {
        get: function () {
            if ((!this.blend) &&
                (this.blendSrc === pc.BLENDMODE_ONE) &&
                (this.blendDst === pc.BLENDMODE_ZERO) &&
                (this.blendEquation === pc.BLENDEQUATION_ADD)) {
                return pc.BLEND_NONE;
            } else if ((this.blend) &&
                       (this.blendSrc === pc.BLENDMODE_SRC_ALPHA) &&
                       (this.blendDst === pc.BLENDMODE_ONE_MINUS_SRC_ALPHA) &&
                       (this.blendEquation === pc.BLENDEQUATION_ADD)) {
                return pc.BLEND_NORMAL;
            } else if ((this.blend) &&
                       (this.blendSrc === pc.BLENDMODE_ONE) &&
                       (this.blendDst === pc.BLENDMODE_ONE) &&
                       (this.blendEquation === pc.BLENDEQUATION_ADD)) {
                return pc.BLEND_ADDITIVE;
            } else if ((this.blend) &&
                       (this.blendSrc === pc.BLENDMODE_DST_COLOR) &&
                       (this.blendDst === pc.BLENDMODE_ZERO) &&
                       (this.blendEquation === pc.BLENDEQUATION_ADD)) {
                return pc.BLEND_MULTIPLICATIVE;
            } else if ((this.blend) &&
                       (this.blendSrc === pc.BLENDMODE_ONE) &&
                       (this.blendDst === pc.BLENDMODE_ONE_MINUS_SRC_ALPHA) &&
                       (this.blendEquation === pc.BLENDEQUATION_ADD)) {
                return pc.BLEND_PREMULTIPLIED;
            } else {
                return pc.BLEND_NORMAL;
            }
        },
        set: function (type) {
            switch (type) {
                case pc.BLEND_NONE:
                    this.blend = false;
                    this.blendSrc = pc.BLENDMODE_ONE;
                    this.blendDst = pc.BLENDMODE_ZERO;
                    this.blendEquation = pc.BLENDEQUATION_ADD;
                    break;
                case pc.BLEND_NORMAL:
                    this.blend = true;
                    this.blendSrc = pc.BLENDMODE_SRC_ALPHA;
                    this.blendDst = pc.BLENDMODE_ONE_MINUS_SRC_ALPHA;
                    this.blendEquation = pc.BLENDEQUATION_ADD;
                    break;
                case pc.BLEND_PREMULTIPLIED:
                    this.blend = true;
                    this.blendSrc = pc.BLENDMODE_ONE;
                    this.blendDst = pc.BLENDMODE_ONE_MINUS_SRC_ALPHA;
                    this.blendEquation = pc.BLENDEQUATION_ADD;
                    break;
                case pc.BLEND_ADDITIVE:
                    this.blend = true;
                    this.blendSrc = pc.BLENDMODE_ONE;
                    this.blendDst = pc.BLENDMODE_ONE;
                    this.blendEquation = pc.BLENDEQUATION_ADD;
                    break;
                case pc.BLEND_MULTIPLICATIVE:
                    this.blend = true;
                    this.blendSrc = pc.BLENDMODE_DST_COLOR;
                    this.blendDst = pc.BLENDMODE_ZERO;
                    this.blendEquation = pc.BLENDEQUATION_ADD;
                    break;
            }
            this._updateMeshInstanceKeys();
        }
    });

    Material.prototype._cloneInternal = function (clone) {
        clone.name = this.name;
        clone.id = id++;

        // in case user assign some custom shader
        // we need copy a shader
        clone.shader = this.shader;

        clone.parameters = {};

        // and need copy parameters of that shader
        for(var parameterName in this.parameters) {
			if (!!this.parameters[parameterName])
				clone.parameters[parameterName] = { scopeId: null, data: this.parameters[parameterName].data };
		}

        // Render states
        clone.alphaTest = this.alphaTest;

        clone.blend = this.blend;
        clone.blendSrc = this.blendSrc;
        clone.blendDst = this.blendDst;
        clone.blendEquation = this.blendEquation;

        clone.cull = this.cull;

        clone.depthTest = this.depthTest;
        clone.depthWrite = this.depthWrite;

        clone.redWrite = this.redWrite;
        clone.greenWrite = this.greenWrite;
        clone.blueWrite = this.blueWrite;
        clone.alphaWrite = this.alphaWrite;
        clone.mask = this.mask;

        clone.meshInstances = [];
    },

    Material.prototype.clone = function () {
        var clone = new pc.Material();
        this._cloneInternal(clone);
        return clone;
    },

    Material.prototype._updateMeshInstanceKeys = function () {
        var i, meshInstances = this.meshInstances;
        for (var i = 0; i < meshInstances.length; i++) {
            meshInstances[i].updateKey();
        }
    };

    Material.prototype.updateShader = function (device, scene) {
        // For vanilla materials, the shader can only be set by the user
    }

    /**
     * @function
     * @name pc.Material#getName
     * @description Returns the string name of the specified material. This name is not
     * necessarily unique. Material names set by an artist within the modelling application
     * should be preserved in the PlayCanvas runtime.
     * @return {string} The name of the material.
     * @author Will Eastcott
     */
    Material.prototype.getName = function () {
        return this.name;
    };

    /**
     * @function
     * @name pc.Material#setName
     * @description Sets the string name of the specified material. This name does not
     * have to be unique.
     * @param {string} name The name of the material.
     * @author Will Eastcott
     */
    Material.prototype.setName = function (name) {
        this.name = name;
    };

    // Parameter management
    Material.prototype.clearParameters = function () {
        this.parameters = {};
    };

    Material.prototype.getParameters = function () {
        return this.parameters;
    };

    /**
     * @function
     * @name pc.Material#getParameter
     * @description Retrieves the specified shader parameter from a material.
     * @name {string} name The name of the parameter to query.
     * @returns {Object} The named parameter.
     * @author Will Eastcott
     */
    Material.prototype.getParameter = function (name) {
        return this.parameters[name];
    };

    /**
     * @function
     * @name pc.Material#setParameter
     * @description Sets a shader parameter on a material.
     * @name {string} name The name of the parameter to set.
     * @name {number|Array|pc.Texture} data The value for the specified parameter.
     * @author Will Eastcott
     */
    Material.prototype.setParameter = function (name, data) {
        var param = this.parameters[name];
        if (param) {
            param.data = data;
        } else {
            this.parameters[name] = {
                scopeId: null,
                data: data
            };
        }
    };

    /**
     * @function
     * @name pc.Material#deleteParameter
     * @description Deletes a shader parameter on a material.
     * @name {string} name The name of the parameter to delete.
     * @author Will Eastcott
     */
    Material.prototype.deleteParameter = function (name) {
        if (this.parameters[name]) {
            delete this.parameters[name];
        }
    };

    /**
     * @function
     * @name pc.Material#setParameters
     * @description Pushes all material parameters into scope.
     * @author Will Eastcott
     */
    Material.prototype.setParameters = function () {
        // Push each shader parameter into scope
        for (var paramName in this.parameters) {
            var parameter = this.parameters[paramName];
            if (!parameter.scopeId) {
                parameter.scopeId = device.scope.resolve(paramName);
            }
            parameter.scopeId.setValue(parameter.data);
        }
    };

    /**
     * @function
     * @name pc.Material#getShader
     * @description Retrieves the shader assigned to the specified material.
     * @returns {pc.Shader} The shader assigned to the material.
     * @author Will Eastcott
     */
    Material.prototype.getShader = function () {
        return this.shader;
    };

    /**
     * @function
     * @name pc.Material#setShader
     * @description Assigns a shader to the specified material.
     * @param {pc.Shader} shader The shader to assign to the material.
     * @author Will Eastcott
     */
    Material.prototype.setShader = function (shader) {
        this.shader = shader;
    };

    Material.prototype.update = function () {
        throw Error("Not Implemented in base class");
    };

    Material.prototype.init = function (data) {
        throw Error("Not Implemented in base class");
    };

    return {
        Material: Material
    };
}());
<commit_msg>Update scene_material.js<commit_after>pc.extend(pc, function () {
    var id = 0;

    /**
     * @name pc.Material
     * @class A material.
     */
    var Material = function Material() {
        this.name = "Untitled";
        this.id = id++;
        this.shader = null;

        this.parameters = {};

        // Render states
        this.alphaTest = 0;

        this.blend = false;
        this.blendSrc = pc.BLENDMODE_ONE;
        this.blendDst = pc.BLENDMODE_ZERO;
        this.blendEquation = pc.BLENDEQUATION_ADD;

        this.cull = pc.CULLFACE_BACK;

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

        this.redWrite = true;
        this.greenWrite = true;
        this.blueWrite = true;
        this.alphaWrite = true;
        this.mask = 1;

        this.meshInstances = []; // The mesh instances referencing this material
    };

    Object.defineProperty(Material.prototype, 'blendType', {
        get: function () {
            if ((!this.blend) &&
                (this.blendSrc === pc.BLENDMODE_ONE) &&
                (this.blendDst === pc.BLENDMODE_ZERO) &&
                (this.blendEquation === pc.BLENDEQUATION_ADD)) {
                return pc.BLEND_NONE;
            } else if ((this.blend) &&
                       (this.blendSrc === pc.BLENDMODE_SRC_ALPHA) &&
                       (this.blendDst === pc.BLENDMODE_ONE_MINUS_SRC_ALPHA) &&
                       (this.blendEquation === pc.BLENDEQUATION_ADD)) {
                return pc.BLEND_NORMAL;
            } else if ((this.blend) &&
                       (this.blendSrc === pc.BLENDMODE_ONE) &&
                       (this.blendDst === pc.BLENDMODE_ONE) &&
                       (this.blendEquation === pc.BLENDEQUATION_ADD)) {
                return pc.BLEND_ADDITIVE;
            } else if ((this.blend) &&
                       (this.blendSrc === pc.BLENDMODE_DST_COLOR) &&
                       (this.blendDst === pc.BLENDMODE_ZERO) &&
                       (this.blendEquation === pc.BLENDEQUATION_ADD)) {
                return pc.BLEND_MULTIPLICATIVE;
            } else if ((this.blend) &&
                       (this.blendSrc === pc.BLENDMODE_ONE) &&
                       (this.blendDst === pc.BLENDMODE_ONE_MINUS_SRC_ALPHA) &&
                       (this.blendEquation === pc.BLENDEQUATION_ADD)) {
                return pc.BLEND_PREMULTIPLIED;
            } else {
                return pc.BLEND_NORMAL;
            }
        },
        set: function (type) {
            switch (type) {
                case pc.BLEND_NONE:
                    this.blend = false;
                    this.blendSrc = pc.BLENDMODE_ONE;
                    this.blendDst = pc.BLENDMODE_ZERO;
                    this.blendEquation = pc.BLENDEQUATION_ADD;
                    break;
                case pc.BLEND_NORMAL:
                    this.blend = true;
                    this.blendSrc = pc.BLENDMODE_SRC_ALPHA;
                    this.blendDst = pc.BLENDMODE_ONE_MINUS_SRC_ALPHA;
                    this.blendEquation = pc.BLENDEQUATION_ADD;
                    break;
                case pc.BLEND_PREMULTIPLIED:
                    this.blend = true;
                    this.blendSrc = pc.BLENDMODE_ONE;
                    this.blendDst = pc.BLENDMODE_ONE_MINUS_SRC_ALPHA;
                    this.blendEquation = pc.BLENDEQUATION_ADD;
                    break;
                case pc.BLEND_ADDITIVE:
                    this.blend = true;
                    this.blendSrc = pc.BLENDMODE_ONE;
                    this.blendDst = pc.BLENDMODE_ONE;
                    this.blendEquation = pc.BLENDEQUATION_ADD;
                    break;
                case pc.BLEND_MULTIPLICATIVE:
                    this.blend = true;
                    this.blendSrc = pc.BLENDMODE_DST_COLOR;
                    this.blendDst = pc.BLENDMODE_ZERO;
                    this.blendEquation = pc.BLENDEQUATION_ADD;
                    break;
            }
            this._updateMeshInstanceKeys();
        }
    });

    Material.prototype._cloneInternal = function (clone) {
        clone.name = this.name;
        clone.id = id++;

        // in case user assign some custom shader
        // we need copy a shader
        clone.shader = this.shader;

        clone.parameters = {};

        // and need copy parameters of that shader
        for(var parameterName in this.parameters) {
	    if (!!this.parameters[parameterName])
	        clone.parameters[parameterName] = { scopeId: null, data: this.parameters[parameterName].data };
	}

        // Render states
        clone.alphaTest = this.alphaTest;

        clone.blend = this.blend;
        clone.blendSrc = this.blendSrc;
        clone.blendDst = this.blendDst;
        clone.blendEquation = this.blendEquation;

        clone.cull = this.cull;

        clone.depthTest = this.depthTest;
        clone.depthWrite = this.depthWrite;

        clone.redWrite = this.redWrite;
        clone.greenWrite = this.greenWrite;
        clone.blueWrite = this.blueWrite;
        clone.alphaWrite = this.alphaWrite;
        clone.mask = this.mask;

        clone.meshInstances = [];
    },

    Material.prototype.clone = function () {
        var clone = new pc.Material();
        this._cloneInternal(clone);
        return clone;
    },

    Material.prototype._updateMeshInstanceKeys = function () {
        var i, meshInstances = this.meshInstances;
        for (var i = 0; i < meshInstances.length; i++) {
            meshInstances[i].updateKey();
        }
    };

    Material.prototype.updateShader = function (device, scene) {
        // For vanilla materials, the shader can only be set by the user
    }

    /**
     * @function
     * @name pc.Material#getName
     * @description Returns the string name of the specified material. This name is not
     * necessarily unique. Material names set by an artist within the modelling application
     * should be preserved in the PlayCanvas runtime.
     * @return {string} The name of the material.
     * @author Will Eastcott
     */
    Material.prototype.getName = function () {
        return this.name;
    };

    /**
     * @function
     * @name pc.Material#setName
     * @description Sets the string name of the specified material. This name does not
     * have to be unique.
     * @param {string} name The name of the material.
     * @author Will Eastcott
     */
    Material.prototype.setName = function (name) {
        this.name = name;
    };

    // Parameter management
    Material.prototype.clearParameters = function () {
        this.parameters = {};
    };

    Material.prototype.getParameters = function () {
        return this.parameters;
    };

    /**
     * @function
     * @name pc.Material#getParameter
     * @description Retrieves the specified shader parameter from a material.
     * @name {string} name The name of the parameter to query.
     * @returns {Object} The named parameter.
     * @author Will Eastcott
     */
    Material.prototype.getParameter = function (name) {
        return this.parameters[name];
    };

    /**
     * @function
     * @name pc.Material#setParameter
     * @description Sets a shader parameter on a material.
     * @name {string} name The name of the parameter to set.
     * @name {number|Array|pc.Texture} data The value for the specified parameter.
     * @author Will Eastcott
     */
    Material.prototype.setParameter = function (name, data) {
        var param = this.parameters[name];
        if (param) {
            param.data = data;
        } else {
            this.parameters[name] = {
                scopeId: null,
                data: data
            };
        }
    };

    /**
     * @function
     * @name pc.Material#deleteParameter
     * @description Deletes a shader parameter on a material.
     * @name {string} name The name of the parameter to delete.
     * @author Will Eastcott
     */
    Material.prototype.deleteParameter = function (name) {
        if (this.parameters[name]) {
            delete this.parameters[name];
        }
    };

    /**
     * @function
     * @name pc.Material#setParameters
     * @description Pushes all material parameters into scope.
     * @author Will Eastcott
     */
    Material.prototype.setParameters = function () {
        // Push each shader parameter into scope
        for (var paramName in this.parameters) {
            var parameter = this.parameters[paramName];
            if (!parameter.scopeId) {
                parameter.scopeId = device.scope.resolve(paramName);
            }
            parameter.scopeId.setValue(parameter.data);
        }
    };

    /**
     * @function
     * @name pc.Material#getShader
     * @description Retrieves the shader assigned to the specified material.
     * @returns {pc.Shader} The shader assigned to the material.
     * @author Will Eastcott
     */
    Material.prototype.getShader = function () {
        return this.shader;
    };

    /**
     * @function
     * @name pc.Material#setShader
     * @description Assigns a shader to the specified material.
     * @param {pc.Shader} shader The shader to assign to the material.
     * @author Will Eastcott
     */
    Material.prototype.setShader = function (shader) {
        this.shader = shader;
    };

    Material.prototype.update = function () {
        throw Error("Not Implemented in base class");
    };

    Material.prototype.init = function (data) {
        throw Error("Not Implemented in base class");
    };

    return {
        Material: Material
    };
}());
<|endoftext|>


<commit_before>"use strict";

import React, {Component} from 'react';
import {
    AsyncStorage,
    Alert,
    StyleSheet,
    View,
    ScrollView,
} from 'react-native';
import {GoogleSignin} from 'react-native-google-signin';

import CONFIG from './../config';
import _, {LANGUAGES} from './../i18n';
import CloudStorage from './../CloudStorage';
import Items from './../Items';
import {
    Layout,
    Button,
    ButtonPicker,
} from './../components';
import Scene from './Scene';

export class SettingsScene extends Scene {
    constructor(props, context, updater) {
        super(props, context, updater);

        this.hardwareBackPress = () => this.navigationPop();

        this.state = {
            hasPlayServices: false,
            language: CONFIG.LANGUAGE,
            hqPreview: CONFIG.HQ_PREVIEW,
            includeIconsInProgress: CONFIG.INCLUDE_ICONS_IN_PROGRESS,
            profile: CONFIG.PROFILE || null,
        };
    }

    componentWillMount() {
        let configure = () => {
            GoogleSignin.configure(CONFIG.GOOGLE_SIGNIN).then(() => {
                this.setState({
                    hasPlayServices: true,
                });
            });
        };

        if (CONFIG.PLATFORM === 'android') {
            GoogleSignin.hasPlayServices({autoResolve: true,}).then(configure()).catch(error => null);
        } else {
            configure();
        }
    }

    setLanguage(language) {
        this.setState({
            language: language,
        }, () => {
            CONFIG.set('LANGUAGE', language).then(() => {
                this.forceUpdate();
            });
        });
    }

    switchHQPreview() {
        let values = [true, 'WIFI', false], index, value;

        index = values.indexOf(this.state.hqPreview);

        if ((index + 1) > (values.length - 1)) {
            index = 0;
        } else {
            index++;
        }

        value = values[index];

        CONFIG.set('HQ_PREVIEW', value).then(() => {
            this.setState({
                hqPreview: value,
            });
        });
    }

    toggleIncludeIcons() {
        CONFIG.set('INCLUDE_ICONS_IN_PROGRESS', !this.state.includeIconsInProgress).then(() => {
            this.setState({
                includeIconsInProgress: !this.state.includeIconsInProgress,
            });
        });
    }

    cloudSynchronization() {
        if (!this.state.hasPlayServices) {
            return;
        }

        if (this.state.profile) {
            Alert.alert(_('SETTINGS__CLOUD_SYNCHRONIZATION_TITLE'), `${ _('SETTINGS__CONNECTED_ACCOUNT')}: ${this.state.profile.name}`, [
                {text: _('BUTTON__CANCEL'), onPress: () => null, style: 'cancel'},
                {text: _('BUTTON__TURN_OFF'), onPress: async () => {
                    if (CONFIG.NETWORK === 'NONE') {
                        Alert.alert(_('ERROR__NO_INTERNET_CONNECTION'), '');

                        return;
                    }

                    await CloudStorage.remove('/items');
                    GoogleSignin.revokeAccess().then(() => {
                        CONFIG.remove(['SETTINGS__CLOUD_SYNCHRONIZATION_TITLE', 'PROFILE',]).then(() => {
                            this.setState({
                                profile: null,
                            }, () => Items.initialize());
                        });
                    }).catch(error => console.log(error));
                }},
            ]);

            return;
        }

        Alert.alert(_('SETTINGS__CLOUD_SYNCHRONIZATION_TITLE'), _('SETTINGS__CLOUD_SYNCHRONIZATION_CONFIRM'), [
            {text: _('BUTTON__CANCEL'), onPress: () => null, style: 'cancel'},
            {text: _('BUTTON__SIGN_IN'), onPress: () => {
                if (CONFIG.NETWORK === 'NONE') {
                    Alert.alert(_('ERROR__NO_INTERNET_CONNECTION'), '');

                    return;
                }

                GoogleSignin.signIn().then(user => {
                    let profile = {
                        id: user.id,
                        name: user.name,
                    };

                    CONFIG.set({
                        CLOUD_SYNCHRONIZATION: true,
                        PROFILE: profile,
                    }).then(() => {
                        this.setState({
                            profile: profile,
                        }, () => Items.initialize());
                    });
                }).catch(error => console.log(error));
            }},
        ]);
    }

    eraseData() {
        Alert.alert(_('SETTINGS__CLEARING_DATA_TITLE'), _('SETTINGS__CLEARING_DATA_CONFIRM'), [
            {text: _('BUTTON__CANCEL'), onPress: () => null, style: 'cancel'},
            {text: _('BUTTON__CLEAR'), onPress: () => {
                AsyncStorage.removeItem('TIPS_SHOWN');
                Items.clear();
            }},
        ]);
    }

    render() {
        let languages = [],
            btnHQPreviewTitle = `${_('SETTINGS__HQ_PREVIEW')}`,
            btnSync,
            btnSyncTitle = _('BUTTON__CLOUD_SYNCHRONIZATION');

        for (let i in LANGUAGES) if (LANGUAGES.hasOwnProperty(i)) {
            languages.push({label: LANGUAGES[i].name.toUpperCase(), value: i});
        }

        switch (this.state.hqPreview) {
            case true:
                btnHQPreviewTitle += `: ${_('SETTINGS__IS_ON')}`;
                break;
            case 'WIFI':
                btnHQPreviewTitle += `: ${_('SETTINGS__WIFI_ONLY')}`;
                break;
            case false:
                btnHQPreviewTitle += `: ${_('SETTINGS__IS_OFF')}`;
                break;
        }

        if (this.state.hasPlayServices) {
            if (this.state.profile) {
                btnSyncTitle += `: ${_('SETTINGS__IS_ON')}` ;
            } else {
                btnSyncTitle += `: ${_('SETTINGS__IS_OFF')}` ;
            }

            btnSync = (
                <View style={styles.section}>
                    <Button
                        title={btnSyncTitle.toUpperCase()}
                        onPress={() => this.cloudSynchronization()}
                    />
                </View>
            );
        }

        return (
            <Layout
                toolbarTitle={_('SETTINGS__SETTINGS_TITLE')}
                onToolbarIconPress={() => this.navigationPop()}
                styles={styles.container}
            >

                <View style={styles.top}>

                </View>
                <ScrollView style={styles.center} contentContainerStyle={styles.centerContentContainerStyle}>
                    <View style={styles.section}>
                        <ButtonPicker
                            values={languages}
                            selectedValue={this.state.language}
                            onValueChange={language => this.setLanguage(language)}
                            title={_('SETTINGS__LANGUAGE').toUpperCase()}
                            icon="close"
                        />
                    </View>
                    <View style={styles.section}>
                        <Button
                            title={btnHQPreviewTitle}
                            onPress={() => this.switchHQPreview()}
                        />
                    </View>
                    <View style={styles.section}>
                        <Button
                            title={`${_('SETTINGS__INCLUDE_ICONS_IN_PROGRESS')}: ${this.state.includeIconsInProgress ? _('SETTINGS__IS_ON') : _('SETTINGS__IS_OFF')}`.toUpperCase()}
                            onPress={() => this.toggleIncludeIcons()}
                        />
                    </View>
                    {btnSync}
                </ScrollView>
                <View style={styles.bottom}>
                    <View style={styles.section}>
                        <Button
                            title={_('BUTTON__CLEAR_DATA').toUpperCase()}
                            onPress={() => this.eraseData()}
                            color={CONFIG.COLORS.RED}
                            icon="close"
                        />
                    </View>
                </View>

            </Layout>
        );
    }
}

const styles = StyleSheet.create({
    container: {
    },
    top: {
        paddingHorizontal: 8,
    },
    center: {
        flex: 1,
    },
    centerContentContainerStyle: {
        paddingHorizontal: 8,
    },
    bottom: {
        paddingHorizontal: 8,
    },
    section: {
        paddingVertical: 8,
    },
    text: {
        color: '#F5F5F5',
    },
});
<commit_msg>change "clear data" button position<commit_after>"use strict";

import React, {Component} from 'react';
import {
    AsyncStorage,
    Alert,
    StyleSheet,
    View,
    ScrollView,
} from 'react-native';
import {GoogleSignin} from 'react-native-google-signin';

import CONFIG from './../config';
import _, {LANGUAGES} from './../i18n';
import CloudStorage from './../CloudStorage';
import Items from './../Items';
import {
    Layout,
    Button,
    ButtonPicker,
} from './../components';
import Scene from './Scene';

export class SettingsScene extends Scene {
    constructor(props, context, updater) {
        super(props, context, updater);

        this.hardwareBackPress = () => this.navigationPop();

        this.state = {
            hasPlayServices: false,
            language: CONFIG.LANGUAGE,
            hqPreview: CONFIG.HQ_PREVIEW,
            includeIconsInProgress: CONFIG.INCLUDE_ICONS_IN_PROGRESS,
            profile: CONFIG.PROFILE || null,
        };
    }

    componentWillMount() {
        let configure = () => {
            GoogleSignin.configure(CONFIG.GOOGLE_SIGNIN).then(() => {
                this.setState({
                    hasPlayServices: true,
                });
            });
        };

        if (CONFIG.PLATFORM === 'android') {
            GoogleSignin.hasPlayServices({autoResolve: true,}).then(configure()).catch(error => null);
        } else {
            configure();
        }
    }

    setLanguage(language) {
        this.setState({
            language: language,
        }, () => {
            CONFIG.set('LANGUAGE', language).then(() => {
                this.forceUpdate();
            });
        });
    }

    switchHQPreview() {
        let values = [true, 'WIFI', false], index, value;

        index = values.indexOf(this.state.hqPreview);

        if ((index + 1) > (values.length - 1)) {
            index = 0;
        } else {
            index++;
        }

        value = values[index];

        CONFIG.set('HQ_PREVIEW', value).then(() => {
            this.setState({
                hqPreview: value,
            });
        });
    }

    toggleIncludeIcons() {
        CONFIG.set('INCLUDE_ICONS_IN_PROGRESS', !this.state.includeIconsInProgress).then(() => {
            this.setState({
                includeIconsInProgress: !this.state.includeIconsInProgress,
            });
        });
    }

    cloudSynchronization() {
        if (!this.state.hasPlayServices) {
            return;
        }

        if (this.state.profile) {
            Alert.alert(_('SETTINGS__CLOUD_SYNCHRONIZATION_TITLE'), `${ _('SETTINGS__CONNECTED_ACCOUNT')}: ${this.state.profile.name}`, [
                {text: _('BUTTON__CANCEL'), onPress: () => null, style: 'cancel'},
                {text: _('BUTTON__TURN_OFF'), onPress: async () => {
                    if (CONFIG.NETWORK === 'NONE') {
                        Alert.alert(_('ERROR__NO_INTERNET_CONNECTION'), '');

                        return;
                    }

                    await CloudStorage.remove('/items');
                    GoogleSignin.revokeAccess().then(() => {
                        CONFIG.remove(['SETTINGS__CLOUD_SYNCHRONIZATION_TITLE', 'PROFILE',]).then(() => {
                            this.setState({
                                profile: null,
                            }, () => Items.initialize());
                        });
                    }).catch(error => console.log(error));
                }},
            ]);

            return;
        }

        Alert.alert(_('SETTINGS__CLOUD_SYNCHRONIZATION_TITLE'), _('SETTINGS__CLOUD_SYNCHRONIZATION_CONFIRM'), [
            {text: _('BUTTON__CANCEL'), onPress: () => null, style: 'cancel'},
            {text: _('BUTTON__SIGN_IN'), onPress: () => {
                if (CONFIG.NETWORK === 'NONE') {
                    Alert.alert(_('ERROR__NO_INTERNET_CONNECTION'), '');

                    return;
                }

                GoogleSignin.signIn().then(user => {
                    let profile = {
                        id: user.id,
                        name: user.name,
                    };

                    CONFIG.set({
                        CLOUD_SYNCHRONIZATION: true,
                        PROFILE: profile,
                    }).then(() => {
                        this.setState({
                            profile: profile,
                        }, () => Items.initialize());
                    });
                }).catch(error => console.log(error));
            }},
        ]);
    }

    eraseData() {
        Alert.alert(_('SETTINGS__CLEARING_DATA_TITLE'), _('SETTINGS__CLEARING_DATA_CONFIRM'), [
            {text: _('BUTTON__CANCEL'), onPress: () => null, style: 'cancel'},
            {text: _('BUTTON__CLEAR'), onPress: () => {
                AsyncStorage.removeItem('TIPS_SHOWN');
                Items.clear();
            }},
        ]);
    }

    render() {
        let languages = [],
            btnHQPreviewTitle = `${_('SETTINGS__HQ_PREVIEW')}`,
            btnSync,
            btnSyncTitle = _('BUTTON__CLOUD_SYNCHRONIZATION');

        for (let i in LANGUAGES) if (LANGUAGES.hasOwnProperty(i)) {
            languages.push({label: LANGUAGES[i].name.toUpperCase(), value: i});
        }

        switch (this.state.hqPreview) {
            case true:
                btnHQPreviewTitle += `: ${_('SETTINGS__IS_ON')}`;
                break;
            case 'WIFI':
                btnHQPreviewTitle += `: ${_('SETTINGS__WIFI_ONLY')}`;
                break;
            case false:
                btnHQPreviewTitle += `: ${_('SETTINGS__IS_OFF')}`;
                break;
        }

        if (this.state.hasPlayServices) {
            if (this.state.profile) {
                btnSyncTitle += `: ${_('SETTINGS__IS_ON')}` ;
            } else {
                btnSyncTitle += `: ${_('SETTINGS__IS_OFF')}` ;
            }

            btnSync = (
                <View style={styles.section}>
                    <Button
                        title={btnSyncTitle.toUpperCase()}
                        onPress={() => this.cloudSynchronization()}
                    />
                </View>
            );
        }

        return (
            <Layout
                toolbarTitle={_('SETTINGS__SETTINGS_TITLE')}
                onToolbarIconPress={() => this.navigationPop()}
                styles={styles.container}
            >

                <View style={styles.top}/>
                <ScrollView style={styles.center} contentContainerStyle={styles.centerContentContainerStyle}>
                    <View style={styles.section}>
                        <ButtonPicker
                            values={languages}
                            selectedValue={this.state.language}
                            onValueChange={language => this.setLanguage(language)}
                            title={_('SETTINGS__LANGUAGE').toUpperCase()}
                        />
                    </View>
                    <View style={styles.section}>
                        <Button
                            title={btnHQPreviewTitle}
                            onPress={() => this.switchHQPreview()}
                        />
                    </View>
                    <View style={styles.section}>
                        <Button
                            title={`${_('SETTINGS__INCLUDE_ICONS_IN_PROGRESS')}: ${this.state.includeIconsInProgress ? _('SETTINGS__IS_ON') : _('SETTINGS__IS_OFF')}`.toUpperCase()}
                            onPress={() => this.toggleIncludeIcons()}
                        />
                    </View>
                    {btnSync}
                    <View style={styles.section}>
                        <Button
                            title={_('BUTTON__CLEAR_DATA').toUpperCase()}
                            onPress={() => this.eraseData()}
                            color={CONFIG.COLORS.RED}
                        />
                    </View>
                </ScrollView>
                <View style={styles.bottom}/>

            </Layout>
        );
    }
}

const styles = StyleSheet.create({
    container: {
    },
    top: {
        paddingHorizontal: 8,
    },
    center: {
        flex: 1,
    },
    centerContentContainerStyle: {
        paddingHorizontal: 8,
    },
    bottom: {
        paddingHorizontal: 8,
    },
    section: {
        paddingVertical: 8,
    },
    text: {
        color: '#F5F5F5',
    },
});
<|endoftext|>


<commit_before>var mouseX = 0, mouseY = 0,
windowHalfX = window.innerWidth / 2,
windowHalfY = window.innerHeight / 2,
SEPARATION = 200,
AMOUNTX = 10,
AMOUNTY = 10,
camera, scene, renderer,earth;
var container = document.createElement('div');
document.body.appendChild(container)

init();
animate();

function init() {

  createPerspectiveCamera()
  createScene()
  createRenderer()
  createAmbientLight()
  createDirectionalLight()
  createEarth()

  document.addEventListener( 'mousemove', onDocumentMouseMove, false );
  document.addEventListener( 'touchstart', onDocumentTouchStart, false );
  document.addEventListener( 'touchmove', onDocumentTouchMove, false );
  window.addEventListener( 'resize', onWindowResize, false );
}

function createRenderer(){
  renderer = new THREE.CanvasRenderer({antialias:true,alpha: true  });
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  renderer.setClearColorHex(0x000000, 1.0);//设置
  container.appendChild( renderer.domElement );
}

function createScene(){
  scene = new THREE.Scene();
}

function createPerspectiveCamera(){
  camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
  camera.position.z = 100;
}

function createAmbientLight(){
  var ambientLight = new THREE.AmbientLight(0x050505, 1.0, 0);
  ambientLight.position.set( 200, 200, 200 );
  scene.add(ambientLight);
}

function createDirectionalLight(){
  var directionalLight = new THREE.DirectionalLight(0xffffff, 1.0, 0);
  directionalLight.position.set( 200, 200, 200 );
  scene.add(directionalLight);
}

function createEarth(){
  var loader = new THREE.TextureLoader();
  loader.load(
    'textures/land_ocean_ice_cloud_2048.jpg',
    function ( texture ) {
      alert('earth !')
      earth = new THREE.Mesh(
        new THREE.SphereGeometry(20,100,50),
        new THREE.MeshBasicMaterial({
          map: texture,
          //color: 0xffffff,
          overdraw:true}) //材质设定
      );
      earth.position.set(0,0,0);
    },
    function (progress){
      console.log(''+(progress.loaded / progress.total)*100 + '%')
    },
    function (err){
      alert('earth !!')
      earth = new THREE.Mesh(
        new THREE.SphereGeometry(20,100,50),
        new THREE.MeshLambertMaterial({color: 0xffffff,overdraw:true}) //材质设定
      );
      earth.position.set(0,0,0);
    }
  );

  scene.add(earth);
}

function onWindowResize() {
  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
}

function onDocumentMouseMove(event) {
  mouseX = event.clientX - windowHalfX;
  mouseY = event.clientY - windowHalfY;
}

function onDocumentTouchStart( event ) {
  if ( event.touches.length > 1 ) {
    event.preventDefault();
    mouseX = event.touches[ 0 ].pageX - windowHalfX;
    mouseY = event.touches[ 0 ].pageY - windowHalfY;
  }
}

function onDocumentTouchMove( event ) {
  if ( event.touches.length == 1 ) {
    event.preventDefault();
    mouseX = event.touches[ 0 ].pageX - windowHalfX;
    mouseY = event.touches[ 0 ].pageY - windowHalfY;
  }
}

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

function render() {
  renderer.clear();

  earth && earth.rotateOnAxis (new THREE.Vector3(0,1,0), 0.01)

  renderer.render( scene, camera );
}
<commit_msg>earth<commit_after>var mouseX = 0, mouseY = 0,
windowHalfX = window.innerWidth / 2,
windowHalfY = window.innerHeight / 2,
SEPARATION = 200,
AMOUNTX = 10,
AMOUNTY = 10,
camera, scene, renderer,earth,earth2;
var container = document.createElement('div');
document.body.appendChild(container)

init();
animate();

function init() {
  createPerspectiveCamera()
  createScene()
  createRenderer()
  createAmbientLight()
  createDirectionalLight()
  createEarth()

  document.addEventListener( 'mousemove', onDocumentMouseMove, false );
  document.addEventListener( 'touchstart', onDocumentTouchStart, false );
  document.addEventListener( 'touchmove', onDocumentTouchMove, false );
  window.addEventListener( 'resize', onWindowResize, false );
}

function createRenderer(){
  renderer = new THREE.CanvasRenderer({antialias:true,alpha: true  });
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  renderer.setClearColorHex(0x000000, 1.0);//设置
  container.appendChild( renderer.domElement );
}

function createScene(){
  scene = new THREE.Scene();
}

function createPerspectiveCamera(){
  camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
  camera.position.z = 100;
}

function createAmbientLight(){
  var ambientLight = new THREE.AmbientLight(0x050505, 1.0, 0);
  scene.add(ambientLight);
}

function createDirectionalLight(){
  var light = new THREE.DirectionalLight(0xffffff, 1);
  light.position.set(5,3,5);
  scene.add(light);
}

function loadTexture(name,url){
  var loader = new THREE.TextureLoader();
  loader.load(
    url,
    function ( texture ) {
      window.textures = window.textures || {}
      window.textures[name] = texture
      typeof window.onTexturesLoad === 'function' && window.onTexturesLoad(name,texture)
    },
    function (progress){
      console.log(name+': '+ progress.loaded + '/' + progress.total)
    },
    function (err){}
  );
}

function createEarth(){
  earth = new THREE.Mesh(
    new THREE.SphereGeometry(30,25,15),
    new THREE.MeshBasicMaterial({
      wireframe:true,
      wireframeLinewidth:1,
      overdraw:0.4,
    }) //材质设定
  );
  earth.position.set(0,0,0);
  scene.add(earth);
  window.onTexturesLoad = function(name,texture){
    if(
      window.textures['earth_map_normal'] &&
      window.textures['earth_map_bump'] &&
      window.textures['earth_map_specular']){
      earth.material = new THREE.MeshPhongMaterial({
        map: window.textures['earth_map_normal'],
        bumpMap   : window.textures['earth_map_bump'],
        specularMap: window.textures['earth_map_specular'],
        bumpScale :  1,
        specular: new THREE.Color('grey'),
        color: 0xffffff,
        overdraw:0.5
      })//材质设定
    }
  };
  loadTexture('earth_map_normal'  ,'https://gimhol.github.io/textures/earth_atmos_4096.jpg')
  loadTexture('earth_map_bump'    ,'https://gimhol.github.io/textures/earth_normal_2048.jpg')
  loadTexture('earth_map_specular','https://gimhol.github.io/textures/earth_specular_2048.jpg')
}

function onWindowResize() {
  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
}

function onDocumentMouseMove(event) {
  mouseX = event.clientX - windowHalfX;
  mouseY = event.clientY - windowHalfY;
}

function onDocumentTouchStart( event ) {
  if ( event.touches.length > 1 ) {
    event.preventDefault();
    mouseX = event.touches[ 0 ].pageX - windowHalfX;
    mouseY = event.touches[ 0 ].pageY - windowHalfY;
  }
}

function onDocumentTouchMove( event ) {
  if ( event.touches.length == 1 ) {
    event.preventDefault();
    mouseX = event.touches[ 0 ].pageX - windowHalfX;
    mouseY = event.touches[ 0 ].pageY - windowHalfY;
  }
}

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

function render() {
  renderer.clear();
  earth && earth.rotateOnAxis (new THREE.Vector3(0,1,0), 0.01)

  renderer.render( scene, camera );
}
<|endoftext|>


<commit_before>/*
   Libre.fm -- a free network service for sharing your music listening hab""s

   Copyright (C) 2009 Libre.fm Project

   @licstart  The following is the entire license notice for the
   JavaScript code in this page.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.

   @licend  The above is the entire license notice
   for the JavaScript code in this page.
*/

var scrobbled, now_playing;
var artist, album, track, session_key, radio_key;
var playlist = [], current_song = 0;
var player_ready = false;
var playable_songs = false;
var streaming = false;

function playerInit(list, sk, rk) {
	var audio = document.getElementById("audio");
	if (!list) {
		// We're playing a stream instead of a playlist
		streaming = true;
	}

	session_key = sk;
	radio_key = rk;

	if(typeof audio.duration == "undefined") {
		//Browser doesn't support <audio>
		if(streaming) {
			audio.replaceWith("
Sorry, you need a browser capable of using the HTML 5 <audio> element to enjoy the streaming service via the Javascript player.
");
		}
		return;
	}
	$("#fallbackembed").replaceWith(""); // Get rid of the fallback embed, otherwise some html5 browsers will play it in addition to the js player
	if (streaming) {
		// Get playlist from radio service
		getRadioPlaylist();
	} else {
		// Otherwise we have a static playlist
		playlist = list;
		playerReady();
	}
}

function playerReady() {
	var audio = document.getElementById("audio");

	populatePlaylist();
	if(!playable_songs) {
		return;
	}
	loadSong(0);
	audio.pause();
	audio.addEventListener("ended", songEnded, false);
	updateProgress();
	$("#play").fadeTo("normal", 1);
	$("#progressbar").progressbar({ value: 0 });
	$("#player > #interface").show();
	player_ready = true;
}

function play() {
	var audio = document.getElementById("audio");
	audio.play();
	if(!now_playing) {
		nowPlaying();
	}
	$("#play").fadeTo("normal", 0.5);
	$("#pause").fadeTo("normal", 1);
	$("#seekforward").fadeTo("normal", 1);
	$("#seekback").fadeTo("normal", 1);
}

function pause() {
	var audio = document.getElementById("audio");
	audio.pause();
	$("#play").fadeTo("normal", 1);
	$("#pause").fadeTo("normal", 0.5);
	$("#seekforward").fadeTo("normal", 0.5);
	$("#seekback").fadeTo("normal", 0.5);
}

function seekBack() {
	var audio = document.getElementById("audio");
	audio.currentTime = audio.currentTime - 10;
}

function seekForward() {
	var audio = document.getElementById("audio");
	audio.currentTime = audio.currentTime + 10;
}

function updateProgress() {
	var audio = document.getElementById("audio");
	if (audio.duration > 0) {
		$("#progressbar").progressbar('option', 'value', (audio.currentTime / audio.duration) * 100);
	}
	if (!scrobbled && audio.currentTime > audio.duration / 2) {
		scrobble();
	}
	$("#currenttime").text(friendlyTime(audio.currentTime));
	$("#duration").text(friendlyTime(audio.duration));
	setTimeout("updateProgress()", 900)
}

function songEnded() {
	var audio = document.getElementById("audio");
	if(current_song == playlist.length - 1) {
		pause();
	} else {
		loadSong(current_song+1);
		play();
	}
}

function populatePlaylist() {
	var i, url;
	//Clear the list
	$("#playlist > #songs").text("");
	for(i = 0; i < playlist.length; i++) {
		url = playlist[i]["url"];
		// Remove non-streamable tracks
		if (url == "") {
			playlist.pop(song); // hur, pop song.
		} else {
			playable_songs = true;
		}
		$("#playlist > #songs").append("
" + playlist[i]["artist"] + " - " + playlist[i]["track"] + "
");
	}
	$("#song-" + current_song).css({fontWeight : "bold"});
}

function togglePlaylist() {
	$("#playlist").toggle(1000);
	$("#showplaylist").toggle();
	$("#hideplaylist").toggle();
}

function scrobble() {
	var timestamp;
	scrobbled = true;
	if(!session_key) {
		//Not authenticated
		return;
	}
	timestamp = Math.round(new Date().getTime() / 1000);
	$.post("/scrobble-proxy.php?method=scrobble", { "a[0]" : artist, "b[0]" : album, "t[0]" : track, "i[0]" : timestamp, "s" : session_key },
		      	function(data){
				if(data.substring(0, 2) == "OK") {
					$("#scrobbled").fadeIn(5000, function() { $("#scrobbled").fadeOut(5000) } );
				} else {
					$("#scrobbled").text(data);
					$("#scrobbled").fadeIn(1000);
				}
		      	}, "text");
}

function nowPlaying() {
	var timestamp;
	var audio = document.getElementById("audio");
	now_playing = true;
	if(!session_key) {
		//Not authenticated
		return;
	}
	timestamp = Math.round(new Date().getTime() / 1000);
	$.post("/scrobble-proxy.php?method=nowplaying", { "a" : artist, "b" : album, "t" : track, "l" : audio.duration, "s" : session_key}, function(data) {}, "text");
}

function playSong(song) {
	var audio = document.getElementById("audio");
	loadSong(song);
	play();
}

function loadSong(song) {
	var url = playlist[song]["url"];
	var audio = document.getElementById("audio");
	artist = playlist[song]["artist"];
	album = playlist[song]["album"];
	track = playlist[song]["track"];

	// Highlight current song in the playlist
	$("#song-" + current_song).css({fontWeight : "normal"});
	$("#song-" + song).css({fontWeight : "bold"});

	current_song = song;
	scrobbled = false;
	now_playing = false;
	audio.src = url;
	audio.load();

	if(streaming && current_song > playlist.length - 3) {
		//Update the playlist before the user reaches the end
		getRadioPlaylist();
	}

	if(current_song > 0) {
		$("#skipback").fadeTo("normal", 1.0);
	} else {
		$("#skipback").fadeTo("normal", 0.5);
	}

	if(current_song < playlist.length - 1) {
		$("#skipforward").fadeTo("normal", 1.0);
	} else {
		$("#skipforward").fadeTo("normal", 0.5);
	}

	$("#trackinfo > #artistname").text(artist);
	$("#trackinfo > #trackname").text(track);
}

function getRadioPlaylist() {
	var tracks, artist, album, title, url, i;
	$.get("/radio/xspf.php", {'sk' : radio_key, 'desktop' : 0}, function(data) {
			parser=new DOMParser();
		      	xmlDoc=parser.parseFromString(data,"text/xml");
			tracks = xmlDoc.getElementsByTagName("track")
			for(i = 0; i < tracks.length; i++) {
				try {
					artist = tracks[i].getElementsByTagName("creator")[0].childNodes[0].nodeValue;
					title = tracks[i].getElementsByTagName("title")[0].childNodes[0].nodeValue;
					album = tracks[i].getElementsByTagName("album")[0].childNodes[0].nodeValue;
					url = tracks[i].getElementsByTagName("location")[0].childNodes[0].nodeValue;
					playlist.push({"artist" : artist, "album" : album, "track" : title, "url" : url});
				} catch(err) {
				}
			}
			if(!player_ready) {
				playerReady();
			} else {
				populatePlaylist();
				// Re-enable the skip forward button now that we have more tracks
				$("#skipforward").fadeTo("normal", 1.0);
			}
		}, "text");
}

function skipBack() {
	playSong(current_song - 1);
}

function skipForward() {
	playSong(current_song + 1);
}

function friendlyTime(timestamp) {
	mins = Math.floor(timestamp / 60);
	sec = String(Math.floor(timestamp % 60));
	if(sec.length == 1) { sec = "0" + sec }
	return mins + ":" + sec
}
<commit_msg>Improve the documentation of the javascript player<commit_after>/*
   Libre.fm -- a free network service for sharing your music listening hab""s

   Copyright (C) 2009 Libre.fm Project

   @licstart  The following is the entire license notice for the
   JavaScript code in this page.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.

   @licend  The above is the entire license notice
   for the JavaScript code in this page.
*/

var scrobbled, now_playing;
var artist, album, track, session_key, radio_key;
var playlist = [], current_song = 0;
var player_ready = false;
var playable_songs = false;
var streaming = false;

/**
 * Initialises the javascript player (player.tpl must also be included on the target page)
 *
 * @param array list A playlist in the form ([artist, album, track, trackurl], [...]) or false if playing a radio stream
 * @param string sk Scrobble session key or false if the user isn't logged in
 * @param string rk Radio session key or false if streaming isn't required
 */
function playerInit(list, sk, rk) {
	var audio = document.getElementById("audio");
	if (!list) {
		// We're playing a stream instead of a playlist
		streaming = true;
	}

	session_key = sk;
	radio_key = rk;

	if(typeof audio.duration == "undefined") {
		//Browser doesn't support <audio>
		if(streaming) {
			audio.replaceWith("
Sorry, you need a browser capable of using the HTML 5 <audio> element to enjoy the streaming service via the Javascript player.
");
		}
		return;
	}
	$("#fallbackembed").replaceWith(""); // Get rid of the fallback embed, otherwise some html5 browsers will play it in addition to the js player
	if (streaming) {
		// Get playlist from radio service
		getRadioPlaylist();
	} else {
		// Otherwise we have a static playlist
		playlist = list;
		playerReady();
	}
}

/**
 * Finishes the player initialisation when the playlist has been loaded
 */
function playerReady() {
	var audio = document.getElementById("audio");

	populatePlaylist();
	if(!playable_songs) {
		return;
	}
	loadSong(0);
	audio.pause();
	audio.addEventListener("ended", songEnded, false);
	updateProgress();
	$("#play").fadeTo("normal", 1);
	$("#progressbar").progressbar({ value: 0 });
	$("#player > #interface").show();
	player_ready = true;
}

/**
 * Begins playback
 */
function play() {
	var audio = document.getElementById("audio");
	audio.play();
	if(!now_playing) {
		nowPlaying();
	}
	$("#play").fadeTo("normal", 0.5);
	$("#pause").fadeTo("normal", 1);
	$("#seekforward").fadeTo("normal", 1);
	$("#seekback").fadeTo("normal", 1);
}

/**
 * Pauses playback
 */
function pause() {
	var audio = document.getElementById("audio");
	audio.pause();
	$("#play").fadeTo("normal", 1);
	$("#pause").fadeTo("normal", 0.5);
	$("#seekforward").fadeTo("normal", 0.5);
	$("#seekback").fadeTo("normal", 0.5);
}

/**
 * Seeks backwards 10 seconds in the current song
 */
function seekBack() {
	var audio = document.getElementById("audio");
	audio.currentTime = audio.currentTime - 10;
}

/**
 * Seeks forwards 10 seconds in the current song
 */
function seekForward() {
	var audio = document.getElementById("audio");
	audio.currentTime = audio.currentTime + 10;
}

/**
 * Updates the progress bar every 900 milliseconds
 */
function updateProgress() {
	var audio = document.getElementById("audio");
	if (audio.duration > 0) {
		$("#progressbar").progressbar('option', 'value', (audio.currentTime / audio.duration) * 100);
	}
	if (!scrobbled && audio.currentTime > audio.duration / 2) {
		scrobble();
	}
	$("#currenttime").text(friendlyTime(audio.currentTime));
	$("#duration").text(friendlyTime(audio.duration));
	setTimeout("updateProgress()", 900)
}

/**
 * Called automatically when a song finished. Loads the next song if there is one
 */
function songEnded() {
	var audio = document.getElementById("audio");
	if(current_song == playlist.length - 1) {
		pause();
	} else {
		loadSong(current_song+1);
		play();
	}
}

/**
 * Outputs the HTML playlist
 */
function populatePlaylist() {
	var i, url;
	//Clear the list
	$("#playlist > #songs").text("");
	for(i = 0; i < playlist.length; i++) {
		url = playlist[i]["url"];
		// Remove non-streamable tracks
		if (url == "") {
			playlist.pop(song); // hur, pop song.
		} else {
			playable_songs = true;
		}
		$("#playlist > #songs").append("
" + playlist[i]["artist"] + " - " + playlist[i]["track"] + "
");
	}
	$("#song-" + current_song).css({fontWeight : "bold"});
}

/**
 * Shows/Hides the HTML playlist display
 */
function togglePlaylist() {
	$("#playlist").toggle(1000);
	$("#showplaylist").toggle();
	$("#hideplaylist").toggle();
}

/**
 * Submits a scrobble for the current song if a scrobble session key has been
 * provided. Makes use of a simple proxy to support installations where the
 * gnukebox installation is at a different domain/sub-domain to the nixtape
 * installation.
 */
function scrobble() {
	var timestamp;
	scrobbled = true;
	if(!session_key) {
		//Not authenticated
		return;
	}
	timestamp = Math.round(new Date().getTime() / 1000);
	$.post("/scrobble-proxy.php?method=scrobble", { "a[0]" : artist, "b[0]" : album, "t[0]" : track, "i[0]" : timestamp, "s" : session_key },
		      	function(data){
				if(data.substring(0, 2) == "OK") {
					$("#scrobbled").fadeIn(5000, function() { $("#scrobbled").fadeOut(5000) } );
				} else {
					$("#scrobbled").text(data);
					$("#scrobbled").fadeIn(1000);
				}
		      	}, "text");
}

/**
 * Submits 'now playing' data to the gnukebox server. Like scrobble() this
 * makes use of a proxy.
 */
function nowPlaying() {
	var timestamp;
	var audio = document.getElementById("audio");
	now_playing = true;
	if(!session_key) {
		//Not authenticated
		return;
	}
	timestamp = Math.round(new Date().getTime() / 1000);
	$.post("/scrobble-proxy.php?method=nowplaying", { "a" : artist, "b" : album, "t" : track, "l" : audio.duration, "s" : session_key}, function(data) {}, "text");
}

/**
 * Loads a song and beings playing it.
 *
 * @param int song The song number in the playlist that should be played
 */
function playSong(song) {
	var audio = document.getElementById("audio");
	loadSong(song);
	play();
}

/**
 * Loads a song
 *
 * @param int song The song number in the playlist that should be loaded
 */
function loadSong(song) {
	var url = playlist[song]["url"];
	var audio = document.getElementById("audio");
	artist = playlist[song]["artist"];
	album = playlist[song]["album"];
	track = playlist[song]["track"];

	// Highlight current song in the playlist
	$("#song-" + current_song).css({fontWeight : "normal"});
	$("#song-" + song).css({fontWeight : "bold"});

	current_song = song;
	scrobbled = false;
	now_playing = false;
	audio.src = url;
	audio.load();

	if(streaming && current_song > playlist.length - 3) {
		//Update the playlist before the user reaches the end
		getRadioPlaylist();
	}

	if(current_song > 0) {
		$("#skipback").fadeTo("normal", 1.0);
	} else {
		$("#skipback").fadeTo("normal", 0.5);
	}

	if(current_song < playlist.length - 1) {
		$("#skipforward").fadeTo("normal", 1.0);
	} else {
		$("#skipforward").fadeTo("normal", 0.5);
	}

	$("#trackinfo > #artistname").text(artist);
	$("#trackinfo > #trackname").text(track);
}

/**
 * Retrieves a playlist from the radio streaming service.
 * A radio session key must be supplied when initialising
 * the play for this to work.
 */
function getRadioPlaylist() {
	var tracks, artist, album, title, url, i;
	$.get("/radio/xspf.php", {'sk' : radio_key, 'desktop' : 0}, function(data) {
			parser=new DOMParser();
		      	xmlDoc=parser.parseFromString(data,"text/xml");
			tracks = xmlDoc.getElementsByTagName("track")
			for(i = 0; i < tracks.length; i++) {
				try {
					artist = tracks[i].getElementsByTagName("creator")[0].childNodes[0].nodeValue;
					title = tracks[i].getElementsByTagName("title")[0].childNodes[0].nodeValue;
					album = tracks[i].getElementsByTagName("album")[0].childNodes[0].nodeValue;
					url = tracks[i].getElementsByTagName("location")[0].childNodes[0].nodeValue;
					playlist.push({"artist" : artist, "album" : album, "track" : title, "url" : url});
				} catch(err) {
				}
			}
			if(!player_ready) {
				playerReady();
			} else {
				populatePlaylist();
				// Re-enable the skip forward button now that we have more tracks
				$("#skipforward").fadeTo("normal", 1.0);
			}
		}, "text");
}

/**
 * Plays the song previous to the current one in the playlist
 */
function skipBack() {
	playSong(current_song - 1);
}

/**
 * Plays the song after the current one in the playlist
 */
function skipForward() {
	playSong(current_song + 1);
}

/**
 * Converts a timestamp to "MM:SS" format.
 *
 * @param int timestamp A timestamp in seconds.
 * @return string The provided time in "MM:SS" format
 */
function friendlyTime(timestamp) {
	mins = Math.floor(timestamp / 60);
	sec = String(Math.floor(timestamp % 60));
	if(sec.length == 1) { sec = "0" + sec }
	return mins + ":" + sec
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Denisov21. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*
 * Chinese Simplified String
 * Locale code: zh-cn
 * 简体中文字符串表
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */
define({
    "RIGHT_CLICK_MENU_CUT_NAME"          : "剪切",
    "RIGHT_CLICK_MENU_COPY_NAME"         : "复制",
    "RIGHT_CLICK_MENU_PASTE_NAME"        : "粘贴",
    "RIGHT_CLICK_MENU_UPPERCASE_NAME"    : "转换为大写字母",
    "RIGHT_CLICK_MENU_LOWERCASE_NAME"    : "转换为小写字母",
    "RIGHT_CLICK_MENU_CAMELCASE_NAME"    : "转换为驼峰风格",
    "RIGHT_CLICK_MENU_BLOCKCOMMENT_NAME" : "切换为代码块注释",
    "RIGHT_CLICK_MENU_LINECOMMENT_NAME"  : "切换为行注释",
    "RIGHT_CLICK_MENU_SAVEALL_NAME"      : "全部保存",
	"RIGHT_CLICK_MENU_CONVERTTO_NAME"    : "转换为",
	"RIGHT_CLICK_MENU_ENCODE_HTMLENTITY_NAME" : "编码HTML实体",
	"RIGHT_CLICK_MENU_ENCODE_NAMEDHTMLENTITY_NAME" : "编码为命名HTML实体",
	"RIGHT_CLICK_MENU_DECODE_HTMLENTITY_NAME" : "解码HTML实体",
	"RIGHT_CLICK_MENU_ENCODE_URI_NAME" : "编码URI",
	"RIGHT_CLICK_MENU_DECODE_URI_NAME" : "解码URI"
});
<commit_msg>Update strings.js<commit_after>/*
 * Copyright (c) 2014 Denisov21. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/*
 * Chinese Simplified String
 * Locale code: zh-cn
 * 简体中文字符串表
 */

/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define */
define({
    "RIGHT_CLICK_MENU_CUT_NAME"          : "剪切",
    "RIGHT_CLICK_MENU_COPY_NAME"         : "复制",
    "RIGHT_CLICK_MENU_PASTE_NAME"        : "粘贴",
    "RIGHT_CLICK_MENU_UPPERCASE_NAME"    : "转换为大写字母",
    "RIGHT_CLICK_MENU_LOWERCASE_NAME"    : "转换为小写字母",
    "RIGHT_CLICK_MENU_CAMELCASE_NAME"    : "转换为驼峰风格",
    "RIGHT_CLICK_MENU_BLOCKCOMMENT_NAME" : "切换为代码块注释",
    "RIGHT_CLICK_MENU_LINECOMMENT_NAME"  : "切换为行注释",
    "RIGHT_CLICK_MENU_SAVEALL_NAME"      : "全部保存",
	"RIGHT_CLICK_MENU_CONVERTTO_NAME"    : "转换为",
	"RIGHT_CLICK_MENU_ENCODE_HTMLENTITY_NAME" : "编码HTML实体",
	"RIGHT_CLICK_MENU_ENCODE_NAMEDHTMLENTITY_NAME" : "编码为命名HTML实体",
	"RIGHT_CLICK_MENU_DECODE_HTMLENTITY_NAME" : "解码HTML实体",
	"RIGHT_CLICK_MENU_ENCODE_URI_NAME" : "编码URI",
	"RIGHT_CLICK_MENU_DECODE_URI_NAME" : "解码URI",
    "RIGHT_CLICK_MENU_UNDO_NAME"  : "撤销"
});
<|endoftext|>