<commit_before>(function () {
    var root = window || {};
    root = root.GravJS = root.GravJS || {};

    root.clickedButton = null;
    $(document).on('click', 'button.task', function(e) {
        root.clickedButton = e.target;
    });

    function addTypes (form, factory) {
        var name = factory.getName(),
            types = factory.getTypes();

        for (var i = types.length - 1; i >= 0; i--) {
            form.types[types[i]] = name;

            if (form.scanned) {
                scan(form, type);
            }
        }
    }

    function scan (form, type) {
        for (var i = form.elements.length - 1; i >= 0; i--) {
            if (!type || form.elements[i].type === type) {
                form.elements.splice(i, 1);
            }
        }

        if (Object.keys(form.types).length === 0 || (type && !form.types[type])) {
            return;
        }

        form.findElements().each(function () {
            var el = $(this),
                type = el.data(form.dataIndicator);

            if (type == 'textarea' || type == 'toggleable' || type == 'datetime') {
                var processSpan = function processSpan(element, toggleable) {
                    var on = true;
                    if (!toggleable) {
                        on = $(element).find('input').is(':checked');
                    }

                    $(element).find('label').css('opacity', on ? 1 : 0.7);
                    $(element).siblings('label').css('opacity', on ? 1 : 0.7);

                    if (!on) {
                        $(element).find('input').attr('checked', false).prop('value', 0);
                    } else {
                        $(element).find('input').attr('checked', true).prop('value', 1);
                    }

                    var form_data = $(element).parent().siblings('.form-data');

                    if (on) {
                        form_data.addClass('checked');
                    } else {
                        form_data.removeClass('checked');
                    }

                    form_data.css('opacity', on ? 1 : 0.6);
                    form_data.find('textarea').css('opacity', on ? 1 : 0.6);
                    form_data.find('input').css('opacity', on ? 1 : 0.6);
                };

                var processToggleables = function processToggleables(element) {
                    var elType = $(element)[0].tagName.toLowerCase();

                    if (elType == 'checkbox') {
                        var on = $(element).is(':checked');

                        $(element).siblings('label').css('opacity', on ? 1 : 0.7);
                        $(element).parent().siblings('label').css('opacity', on ? 1 : 0.7);

                        if (!on) {
                            $(element).attr('checked', false).prop('value', 0);
                        } else {
                            $(element).attr('checked', true).prop('value', 1);
                        }

                        var form_data = $(element).parent().parent().siblings('.form-data')

                        form_data.css('opacity', on ? 1 : 0.6);
                        form_data.find('textarea').css('opacity', on ? 1 : 0.6);
                        form_data.find('input').css('opacity', on ? 1 : 0.6);
                    }

                    if (elType == 'span') {
                        processSpan(element);
                    }
                };

                el.on('change input propertychange', function() {
                    processToggleables(this);
                });

                el.find('input').on('change', function() {
                    processToggleables(this);
                });

                if ($(el)[0].className == 'checkboxes toggleable') {
                    var toggles = $(el).parent().siblings('.form-data').find('label');
                    toggles.on('click', function() {
                        processSpan(el, true);
                    });
                }

                processToggleables(this);
            }

            if (form.types[type]) {
                var factory = form.factories[form.types[type]],
                    element = new factory(el, form),
                    name = element.name();

                if (typeof form.toggleables[name] !== 'undefined') {
                    linkToggle(element, form.toggleables[name]);
                    delete form.toggleables[name];
                }

                el.data('grav-field-instance', element);

                form.elements.push({ type: type, element: element });
            }
        });
    }

    function scanToggleable (form) {
        form.toggleables = {};
        form.findElements('toggleable').each(function () {
            var el = $(this);
            form.toggleables[el.data('grav-field-name')] = el;
        });
    }

    function linkToggle (element, toggleable) {
        $(element).on('change', function (value) {
            toggleable.find('input').prop('checked', true);
            toggleable.siblings('label').css('opacity', 1);
            element.disabled(false);
        });

        toggleable.find('input').on('change', function () {
            var el = $(this),
                on = el.is(':checked');

            toggleable.siblings('label').css('opacity', on ? 1 : 0.7);
            element.disabled(!on);
            if (!on) {
                element.el.attr('checked', false).prop('value', 0);
            } else {
                element.el.attr('checked', true).prop('value', 1);
            }
        });

        var on = toggleable.find('input').is(':checked');
        toggleable.siblings('label').css('opacity', on ? 1 : 0.7);
        element.disabled(!on);

        if (!on) {
            element.el.attr('checked', false).prop('value', 0);
        } else {
            element.el.attr('checked', true).prop('value', 1);
        }
    }

    var Form = function (el, options) {
        options = options || {};

        this.form = $(el);
        this.form.data('grav-form-instance', this);
        this.form.on('submit', function (e) {
            this.submit(this.ajax);
            e.preventDefault();
            return false;
        }.bind(this));

        this.scanned = false;

        this.fieldIndicator = options.fieldIndicator || 'data-grav-field';
        this.dataIndicator = options.dataIndicator || (this.fieldIndicator.indexOf('data-') === 0 ? this.fieldIndicator.substr(5) : 'grav-field');
        this.ajax = options.ajax || false;

        this.elements = [];

        this.factories = {};
        this.types = {};

        if (typeof options.globalFactories === 'undefined' || options.globalFactories) {
            for (var name in Form.factories) { if (Form.factories.hasOwnProperty(name)) {
                    this.registerFactory(Form.factories[name]);
                }
            }
        }

        scanToggleable(this);
        scan(this);
        this.scanned = true;

        //Refresh root.currentValues as toggleables have been initialized
        root.currentValues = getState();
    };

    Form.factories = {};

    Form.findElements = function(el, selector, notIn, notSelf) {
        el = $(el);
        notIn = notIn || selector,
        notSelf = notSelf ? true : false;

        return el.find(selector).filter(function() {
            var parent = notSelf ? $(this) : $(this).parent();
                nearestMatch = parent.closest(notIn);
            return nearestMatch.length == 0 || el.find(nearestMatch).length == 0;
        });
    };

    Form.registerFactory = function (factory, context) {
        context = context || Form.factories;
        context[factory.getName()] = factory;
        return true;
    };

    Form.extendFactory = function (parentName, factory, context) {
        context = context || Form.factories;

        if (!context[parentName]) {
            return false;
        }

        return Form.registerFactory(factory.getName(), $.extend({}, context[parentName], factory));
    };

    Form.prototype.findElements = function(type) {
        var selector = '[' + this.fieldIndicator + (type ? '="' + type + '"' : '') + ']';

        return Form.findElements(this.form, selector);
    };

    Form.prototype.registerFactory = function(factory) {
        var registered = Form.registerFactory(factory, this.factories);

        if (registered) {
            addTypes(this, this.factories[factory.getName()]);
        }
    };

    Form.prototype.extendFactory = function(parentName, factory) {
        var registered = Form.extendFactory(parentN, factory, this.factories);

        if (registered) {
            addTypes(this, this.factories[factory.getName()]);
        }
    };

    Form.prototype.getElements = function() {
        if (!this.scanned) {
            scan(this);
            this.scanned = true;
        }

        return this.elements;
    };

    Form.prototype.getValues = function(all) {
        var elements = this.getElements(),
            values = {};

        for (var i = elements.length - 1; i >= 0; i--) {
            var e = elements[i].element;

            if (!all && (!e.valid() || e.disabled())) {
                continue;
            }

            $.extend(values, e.formValues());
        }

        return values;
    };

    Form.prototype.submit = function(ajax) {
        var action = this.form.attr('action') || document.location,
            method = this.form.attr('method') || 'POST',
            values = {};

        // Get form values that are not handled by JS framework
        Form.findElements(this.form, 'input, textarea', '', false).each(function(input) {
            var input = $(this),
                name = input.attr('name'),
                parent = input.parent('[data-grav-disabled]'),
                value = input.val();

            if (input.is(':disabled') || (parent && parent.data('grav-disabled') == 'true')) { return; }

            if (name) {
                values[name] = value;
            }
        });

        $.extend(values, this.getValues());

        if ($(root.clickedButton).attr('name') == 'task') {
            values.task = $(root.clickedButton).attr('value');
            if (values.task == 'saveas') {
                values.lang = $(root.clickedButton).attr('lang');
            }
        }

        if (!values.task) {
            values.task = 'save';
        }

        if (!ajax) {
            var form = $('<form>').attr({ method: method, action: action });

            for (var name in values) { if (values.hasOwnProperty(name)) {
                    $('<input>').attr({ type: 'hidden', name: name, value: values[name] }).appendTo(form);
                }
            }

            return form.appendTo('body').submit();
        } else {
            return $.ajax({ method: method, url: action, data: values });
        }
    };

    root.Form = Form;
})();
<commit_msg>Ensuring a form element exists in the DOM, otherwise discard it from cache. (fixes #79)<commit_after>(function () {
    var root = window || {};
    root = root.GravJS = root.GravJS || {};

    root.clickedButton = null;
    $(document).on('click', 'button.task', function(e) {
        root.clickedButton = e.target;
    });

    function addTypes (form, factory) {
        var name = factory.getName(),
            types = factory.getTypes();

        for (var i = types.length - 1; i >= 0; i--) {
            form.types[types[i]] = name;

            if (form.scanned) {
                scan(form, type);
            }
        }
    }

    function scan (form, type) {
        for (var i = form.elements.length - 1; i >= 0; i--) {
            if (!type || form.elements[i].type === type) {
                form.elements.splice(i, 1);
            }
        }

        if (Object.keys(form.types).length === 0 || (type && !form.types[type])) {
            return;
        }

        form.findElements().each(function () {
            var el = $(this),
                type = el.data(form.dataIndicator);

            if (type == 'textarea' || type == 'toggleable' || type == 'datetime') {
                var processSpan = function processSpan(element, toggleable) {
                    var on = true;
                    if (!toggleable) {
                        on = $(element).find('input').is(':checked');
                    }

                    $(element).find('label').css('opacity', on ? 1 : 0.7);
                    $(element).siblings('label').css('opacity', on ? 1 : 0.7);

                    if (!on) {
                        $(element).find('input').attr('checked', false).prop('value', 0);
                    } else {
                        $(element).find('input').attr('checked', true).prop('value', 1);
                    }

                    var form_data = $(element).parent().siblings('.form-data');

                    if (on) {
                        form_data.addClass('checked');
                    } else {
                        form_data.removeClass('checked');
                    }

                    form_data.css('opacity', on ? 1 : 0.6);
                    form_data.find('textarea').css('opacity', on ? 1 : 0.6);
                    form_data.find('input').css('opacity', on ? 1 : 0.6);
                };

                var processToggleables = function processToggleables(element) {
                    var elType = $(element)[0].tagName.toLowerCase();

                    if (elType == 'checkbox') {
                        var on = $(element).is(':checked');

                        $(element).siblings('label').css('opacity', on ? 1 : 0.7);
                        $(element).parent().siblings('label').css('opacity', on ? 1 : 0.7);

                        if (!on) {
                            $(element).attr('checked', false).prop('value', 0);
                        } else {
                            $(element).attr('checked', true).prop('value', 1);
                        }

                        var form_data = $(element).parent().parent().siblings('.form-data')

                        form_data.css('opacity', on ? 1 : 0.6);
                        form_data.find('textarea').css('opacity', on ? 1 : 0.6);
                        form_data.find('input').css('opacity', on ? 1 : 0.6);
                    }

                    if (elType == 'span') {
                        processSpan(element);
                    }
                };

                el.on('change input propertychange', function() {
                    processToggleables(this);
                });

                el.find('input').on('change', function() {
                    processToggleables(this);
                });

                if ($(el)[0].className == 'checkboxes toggleable') {
                    var toggles = $(el).parent().siblings('.form-data').find('label');
                    toggles.on('click', function() {
                        processSpan(el, true);
                    });
                }

                processToggleables(this);
            }

            if (form.types[type]) {
                var factory = form.factories[form.types[type]],
                    element = new factory(el, form),
                    name = element.name();

                if (typeof form.toggleables[name] !== 'undefined') {
                    linkToggle(element, form.toggleables[name]);
                    delete form.toggleables[name];
                }

                el.data('grav-field-instance', element);

                form.elements.push({ type: type, element: element });
            }
        });
    }

    function scanToggleable (form) {
        form.toggleables = {};
        form.findElements('toggleable').each(function () {
            var el = $(this);
            form.toggleables[el.data('grav-field-name')] = el;
        });
    }

    function linkToggle (element, toggleable) {
        $(element).on('change', function (value) {
            toggleable.find('input').prop('checked', true);
            toggleable.siblings('label').css('opacity', 1);
            element.disabled(false);
        });

        toggleable.find('input').on('change', function () {
            var el = $(this),
                on = el.is(':checked');

            toggleable.siblings('label').css('opacity', on ? 1 : 0.7);
            element.disabled(!on);
            if (!on) {
                element.el.attr('checked', false).prop('value', 0);
            } else {
                element.el.attr('checked', true).prop('value', 1);
            }
        });

        var on = toggleable.find('input').is(':checked');
        toggleable.siblings('label').css('opacity', on ? 1 : 0.7);
        element.disabled(!on);

        if (!on) {
            element.el.attr('checked', false).prop('value', 0);
        } else {
            element.el.attr('checked', true).prop('value', 1);
        }
    }

    var Form = function (el, options) {
        options = options || {};

        this.form = $(el);
        this.form.data('grav-form-instance', this);
        this.form.on('submit', function (e) {
            this.submit(this.ajax);
            e.preventDefault();
            return false;
        }.bind(this));

        this.scanned = false;

        this.fieldIndicator = options.fieldIndicator || 'data-grav-field';
        this.dataIndicator = options.dataIndicator || (this.fieldIndicator.indexOf('data-') === 0 ? this.fieldIndicator.substr(5) : 'grav-field');
        this.ajax = options.ajax || false;

        this.elements = [];

        this.factories = {};
        this.types = {};

        if (typeof options.globalFactories === 'undefined' || options.globalFactories) {
            for (var name in Form.factories) { if (Form.factories.hasOwnProperty(name)) {
                    this.registerFactory(Form.factories[name]);
                }
            }
        }

        scanToggleable(this);
        scan(this);
        this.scanned = true;

        //Refresh root.currentValues as toggleables have been initialized
        root.currentValues = getState();
    };

    Form.factories = {};

    Form.findElements = function(el, selector, notIn, notSelf) {
        el = $(el);
        notIn = notIn || selector,
        notSelf = notSelf ? true : false;

        return el.find(selector).filter(function() {
            var parent = notSelf ? $(this) : $(this).parent();
                nearestMatch = parent.closest(notIn);
            return nearestMatch.length == 0 || el.find(nearestMatch).length == 0;
        });
    };

    Form.registerFactory = function (factory, context) {
        context = context || Form.factories;
        context[factory.getName()] = factory;
        return true;
    };

    Form.extendFactory = function (parentName, factory, context) {
        context = context || Form.factories;

        if (!context[parentName]) {
            return false;
        }

        return Form.registerFactory(factory.getName(), $.extend({}, context[parentName], factory));
    };

    Form.prototype.findElements = function(type) {
        var selector = '[' + this.fieldIndicator + (type ? '="' + type + '"' : '') + ']';

        return Form.findElements(this.form, selector);
    };

    Form.prototype.registerFactory = function(factory) {
        var registered = Form.registerFactory(factory, this.factories);

        if (registered) {
            addTypes(this, this.factories[factory.getName()]);
        }
    };

    Form.prototype.extendFactory = function(parentName, factory) {
        var registered = Form.extendFactory(parentN, factory, this.factories);

        if (registered) {
            addTypes(this, this.factories[factory.getName()]);
        }
    };

    Form.prototype.getElements = function() {
        if (!this.scanned) {
            scan(this);
            this.scanned = true;
        }

        return this.elements;
    };

    Form.prototype.getValues = function(all) {
        var elements = this.getElements(),
            values = {};

        for (var i = elements.length - 1; i >= 0; i--) {
            var e = elements[i].element,
                isInDOM = $('body').find(e.el).length;

            if (!all && (!isInDOM || !e.valid() || e.disabled())) {
                continue;
            }

            $.extend(values, e.formValues());
        }

        return values;
    };

    Form.prototype.submit = function(ajax) {
        var action = this.form.attr('action') || document.location,
            method = this.form.attr('method') || 'POST',
            values = {};

        // Get form values that are not handled by JS framework
        Form.findElements(this.form, 'input, textarea', '', false).each(function(input) {
            var input = $(this),
                name = input.attr('name'),
                parent = input.parent('[data-grav-disabled]'),
                value = input.val();

            if (input.is(':disabled') || (parent && parent.data('grav-disabled') == 'true')) { return; }

            if (name) {
                values[name] = value;
            }
        });

        $.extend(values, this.getValues());

        if ($(root.clickedButton).attr('name') == 'task') {
            values.task = $(root.clickedButton).attr('value');
            if (values.task == 'saveas') {
                values.lang = $(root.clickedButton).attr('lang');
            }
        }

        if (!values.task) {
            values.task = 'save';
        }

        if (!ajax) {
            var form = $('<form>').attr({ method: method, action: action });

            for (var name in values) { if (values.hasOwnProperty(name)) {
                    $('<input>').attr({ type: 'hidden', name: name, value: values[name] }).appendTo(form);
                }
            }

            return form.appendTo('body').submit();
        } else {
            return $.ajax({ method: method, url: action, data: values });
        }
    };

    root.Form = Form;
})();
<|endoftext|>


<commit_before>export { ConcatShuffleSplit };

import * as TensorPlaceholder from "../TensorPlaceholder.js";
import * as BoundsArraySet from "../BoundsArraySet.js";
import * as ChannelShuffler from "../ChannelShuffler.js";
import { Base } from "./Operation_Base.js";

/**
 * Concatenate two tensor3d along depth (i.e. axis id 2) and then channel shuffling and splitting.
 *
 *   - Concatenate two tensor3d ( height x width x channel ) always along the last axis (i.e. axisId = 2, along the channel axis).
 *   - Shuffle. (may not exist.)
 *   - Split. (may not exist.)
 *
 * It could destroy one or two of the input tensors.
 *
 *
 * @member {ChannelShuffler.ConcatPointwiseConv} channelShuffler
 *   It must be implemented by ChannelShuffler.ConcatPointwiseConv with ( outputGroupCount == 2 ). It will not be disposed by
 * this object (i.e. it is supposed to be shared with outter callers).
 *
 *     - The channelShuffler.shuffleInfo.totalChannelCount should be the same as the channel count of the concatenated
 *         inputTensors[].
 *
 *     - The channelShuffler.filtersTensor4dArray[ 0 ] and channelShuffler.filtersTensor4dArray[ 1 ] will be used for
 *         channel shuffling and splitting.
 *
 * @member {boolean} bShuffleSplit
 *   If false, there will be no channel shuffling and not splitting after concatenation.
 *
 * @member {boolean} bKeepInputTensor0
 *   If false, the first input tensor will be disposed after concatenating. If true, the first input tensor will be kept after concatenating.
 *
 * @member {boolean} bKeepInputTensor1
 *   If false, the second input tensor will be disposed after concatenating. If true, the second input tensor will be kept after concatenating.
 *
 * @param {ActivationEscaping.ScaleBoundsArray} inputScaleBoundsArray0
 *   The element value bounds (per channel) of this concatenation operation's input0. It will be kept (not cloned) directly. So caller
 * should not modify them.
 *
 * @param {ActivationEscaping.ScaleBoundsArray} inputScaleBoundsArray1
 *   The element value bounds (per channel) of this concatenation operation's input1. It will be kept (not cloned) directly. So caller
 * should not modify them.
 *
 * @member {BoundsArraySet.InputsOutputs} boundsArraySet
 *   The element value bounds (per channel) of this concatenation operation.
 *
 * @member {function} apply
 *   This is a method. It processes this.input0.realTensor and this.input1.realTensor as inputTensors. It puts to this.output0.realTensor
 * as outputTensor. Both inputTensors are tf.tensor3d and represents an images ( height x width x channel ) which will be concatenated,
 * shuffle, split. They should have the same ( height x width ) but could have different channel count. The outputTensor (tf.tensor3d)
 * represents the result. The inputTensor may or may not be disposed. In fact, this method calls one of ConcatShuffleSplit_and_keep0_keep1(),
 * ConcatShuffleSplit_and_keep0_destroy1(), ConcatShuffleSplit_and_destroy0_keep1(), ConcatShuffleSplit_and_destroy0_destroy1() according
 * to the parameters.
 *
 */
class ConcatShuffleSplit extends Base() {

  /**
   * @param {Array} arrayTemp_forInterleave_asGrouptTwo
   *   A temporary array for placing the original elements temporarily. Provide this array could reduce memory re-allocation
   * and improve performance when doing Interleave_asGrouptTwo.
   *
   */
  constructor(
    inputTensorPlaceholder0, inputTensorPlaceholder1,
    channelShuffler, bShuffleSplit = true,
    inputScaleBoundsArray0, inputScaleBoundsArray1,
    arrayTemp_forInterleave_asGrouptTwo,
    bKeepInputTensor0, bKeepInputTensor1
  ) {

    // Note: outputs' TensorPlaceholder will be created later (in setup_outputs_TensorPlaceholder()).
    super( inputTensorPlaceholder0, inputTensorPlaceholder1, 0 );

    this.channelShuffler = channelShuffler;

    this.inputTensors = new Array( 2 ); // For reducing memory re-allocation.

//!!! (2022/06/01 Remaked)
// When bShuffleSplit is changed, the BoundsArraySet and outputs' TensorPlacehoder will also be changed.
//    this.setShuffleSplit_KeepInputTensor( bShuffleSplit, bKeepInputTensor0, bKeepInputTensor1 );

    // Note: If bShuffleSplit is changed, the BoundsArraySet and outputs' TensorPlacehoder will also be changed.
    //       Then the inputScaleBoundsArray0, inputScaleBoundsArray1, arrayTemp_forInterleave_asGrouptTwo will be
    //       required again. That is difficult. So forbid to change bShuffleSplit.
    //
    this.bShuffleSplit = bShuffleSplit;
    this.bShouldShuffleSplit = ( ( this.bShuffleSplit ) && ( this.channelShuffler ) ); // Want and could do channel shuffling and splitting.

    Base.adjust_pfn.call( this );
    Base.setup_BoundsArraySet.call( this, inputScaleBoundsArray0, inputScaleBoundsArray1, arrayTemp_forInterleave_asGrouptTwo );
    Base.setup_outputs_TensorPlaceholder.call( this );
  }

//!!! (2022/06/01 Remaked)
// When bShuffleSplit is changed, the BoundsArraySet and outputs' TensorPlacehoder will also be changed.
//   /**
//    * Set this.bShuffleSplit and adjust this.pfnShuffleSplit.
//    */
//   setShuffleSplit( bShuffleSplit, arrayTemp_forInterleave_asGrouptTwo ) {
//     this.bShuffleSplit = bShuffleSplit;
//     this.bShouldShuffleSplit = ( ( this.bShuffleSplit ) && ( this.channelShuffler ) ); // Want and could do channel shuffling and splitting.
//     Base.adjust_pfn.call( this );
//     Base.setup_BoundsArraySet.call( this, inputScaleBoundsArray0, inputScaleBoundsArray1, arrayTemp_forInterleave_asGrouptTwo );
//     Base.setup_output0_TensorPlaceholder.call( this );
//   }

  /**
   * Set this.bKeepInputTensor0 and adjust this.apply so that inputTensors[ 0 ] will or will not be disposed.
   */
  setKeepInputTensor0( bKeepInputTensor0 ) {
    this.bKeepInputTensor0 = bKeepInputTensor0;
    Base.adjust_apply.call( this );
  }

  /**
   * Set this.bKeepInputTensor1 and adjust this.apply so that inputTensors[ 1 ] will or will not be disposed.
   */
  setKeepInputTensor1( bKeepInputTensor1 ) {
    this.bKeepInputTensor1 = bKeepInputTensor1;
    Base.adjust_apply.call( this );
  }

  /**
   * Set this.bKeepInputTensor0 and this.bKeepInputTensor1, and adjust this.apply so that inputTensors[ 0 ]
   * and inputTensors[ 1 ] will or will not be disposed.
   */
  setKeepInputTensor( bKeepInputTensor0, bKeepInputTensor1 ) {
    this.bKeepInputTensor0 = bKeepInputTensor0;
    this.bKeepInputTensor1 = bKeepInputTensor1;
    Base.adjust_apply.call( this );
  }

//!!! (2022/06/01 Remaked)
// When bShuffleSplit is changed, the BoundsArraySet and outputs' TensorPlacehoder will also be changed.
//   /**
//    * Set this.bShuffleSplit, this.bKeepInputTensor0, this.bKeepInputTensor1, and then adjust this.pfnShuffleSplit and
//    * this.apply.
//    */
//   setShuffleSplit_KeepInputTensor( bShuffleSplit, bKeepInputTensor0, bKeepInputTensor1 ) {
//     this.setShuffleSplit( bShuffleSplit, arrayTemp_forInterleave_asGrouptTwo );
//
//     this.bKeepInputTensor0 = bKeepInputTensor0;
//     this.bKeepInputTensor1 = bKeepInputTensor1;
//     Base.adjust_apply.call( this );
//   }

  /** @return {number} Always return 0. */
  get tensorWeightCountExtracted() {
    return 0;
  }

  /** @return {number} Always return 0. */
  get tensorWeightCountTotal() {
    return 0;
  }

  /** Set this.pfnShuffleSplit according to this.bShuffleSplit, this.channelShuffler. */
  static adjust_pfn() {
    if ( this.bShouldShuffleSplit ) {

      tf.util.assert( ( this.channelShuffler instanceof ChannelShuffler.ConcatPointwiseConv ),
        `Operation.ConcatShuffleSplit.adjust_pfn(): `
          + `channelShuffler must be an instance of class ChannelShuffler.ConcatPointwiseConv.`
      );

      this.pfnShuffleSplit = Base.ShuffleSplit_do; // Want and could do channel shuffling and splitting.
    } else {
      this.pfnShuffleSplit = Base.ShuffleSplit_return_input_directly;
    }
  }

  /** Set this.apply according to this.bKeepInputTensor0 and this.bKeepInputTensor1. */
  static adjust_apply() {
    if ( this.bKeepInputTensor0 ) {
      if ( this.bKeepInputTensor1 ) {
        this.apply = Base.ConcatShuffleSplit_and_keep0_keep1;
      } else {
        this.apply = Base.ConcatShuffleSplit_and_keep0_destroy1;
      }
    } else {
      if ( this.bKeepInputTensor1 ) {
        this.apply = Base.ConcatShuffleSplit_and_destroy0_keep1;
      } else {
        this.apply = Base.ConcatShuffleSplit_and_destroy0_destroy1;
      }
    }
  }

  /** Create this.boundsArraySet. */
  static setup_BoundsArraySet( inputScaleBoundsArray0, inputScaleBoundsArray1, arrayTemp_forInterleave_asGrouptTwo ) {

    // Concatenated value bounds array set.
    let concatBoundsArraySet;
    {
      concatBoundsArraySet = new BoundsArraySet.InputsOutputs( inputScaleBoundsArray0, inputScaleBoundsArray1,
        1 // Arbitrarily set a legal (but temporary) outputChannelCount0. It will be adjusted later.
      );

      concatBoundsArraySet.set_outputs_all_by_concat_input0_input1(); // The outputChannelCount0 will be adjusted.
    }

    if ( this.bShouldShuffleSplit ) { // Want and could do channel shuffling and splitting.

      tf.util.assert( ( this.channelShuffler.outputGroupCount == 2 ),
        `Operation.ConcatShuffleSplit.setup_BoundsArraySet(): `
          + `channelShuffler.outputGroupCount ( ${this.channelShuffler.outputGroupCount} ) must be 2 `
          + `( other outputGroupCount does not supperted ).`
      );

      // Shuffled value bounds array set.
      let shuffledBoundsArraySet;
      {
        shuffledBoundsArraySet = new BoundsArraySet.InputsOutputs( concatBoundsArraySet.output0, null,
          concatBoundsArraySet.output0.channelCount );

        shuffledBoundsArraySet.output0.set_all_byScaleBoundsArray( concatBoundsArraySet.output0 );
        shuffledBoundsArraySet.set_outputs_all_byInterleave_asGrouptTwo( arrayTemp_forInterleave_asGrouptTwo );
      }

      // Splitted value bounds array set.
      let splittedBoundsArraySet;
      {
        splittedBoundsArraySet = new BoundsArraySet.InputsOutputs( shuffledBoundsArraySet.output0, null,
          1, 1  // Arbitrarily set a legal (but temporary) outputChannelCount0 and outputChannelCount1. It will be adjusted later.
        );

        splittedBoundsArraySet.set_outputs_all_byBoundsArray_split_input0();
      }

      this.boundsArraySet = splittedBoundsArraySet;

    } else { // Only concatenation is needed.
      this.boundsArraySet = concatBoundsArraySet;
    }
  }

  /** Setup this.output0 and this.output1. */
  static setup_outputs_TensorPlaceholder() {

    this.output0 = new TensorPlaceholder.Base();
    this.output0.height = this.input0.height;
    this.output0.width = this.input0.width;

    if ( this.bShouldShuffleSplit ) { // Only if splitting is required, the output1 does exist.
      this.output1 = new TensorPlaceholder.Base();
      this.output1.height = this.input0.height;
      this.output1.width = this.input0.width;

      // Because only tensor3d and ChannelShuffler.ConcatPointwiseConv and ( outputGroupCount == 2 ) are supported,
      // using the pointwise convolution filters' shape for output channel count.
      const outputChannelCount_filterAxisId = 3;
      this.output0.channelCount = this.channelShuffler.filtersTensor4dArray[ 0 ].shape[ outputChannelCount_filterAxisId ];
      this.output1.channelCount = this.channelShuffler.filtersTensor4dArray[ 1 ].shape[ outputChannelCount_filterAxisId ];

    } else { // Only concatenation.
      this.output0.channelCount = this.input0.channelCount + this.input1.channelCount;
    }
  }

  /**
   * Outputs are placed in this.output0.realTensor and this.output1.realTensor directly.
   *
   * @param {tf.tensor3d} inputTensor
   *   The tensor to be shuffled and splitted.
   */
  static ShuffleSplit_do( inputTensor ) {

    // Since there is only two output group (i.e. ( outputGroupCount == 2 ) ), do not use loop (i.e. use unrolled-loop)
    // so the performance could be better a little.
    this.output0.realTensor = tf.conv2d( inputTensor, this.channelShuffler.filtersTensor4dArray[ 0 ], 1, "valid" );
    this.output1.realTensor = tf.conv2d( inputTensor, this.channelShuffler.filtersTensor4dArray[ 1 ], 1, "valid" );

    // Always destroy input. Because tf.concat() has always been done before this method is called, the keep-input has already be
    // done by it.
    inputTensor.dispose();
  }

  /** Just return inputTensor at this.output0.realTensor. */
  static ShuffleSplit_return_input_directly( inputTensor ) {
    this.output0.realTensor = inputTensor;

    // Do not call inputTensor.dispose(). In fact, because inputTensor is returned directly, it is the same as been disposed already.
  }

  /** Concatenate along axis id 2. (Both the input0 and input1 will not be disposed.) */
  static ConcatShuffleSplit_and_keep0_keep1( inputTensors, outputTensors ) {
    this.inputTensors[ 0 ] = this.input0.realTensor;
    this.inputTensors[ 1 ] = this.input1.realTensor;
    let t0 = tf.concat( this.inputTensors, 2 ); // AxisId = 2

    this.pfnShuffleSplit( t0 );
  }

  /** Concatenate along axis id 2. (The input0 will not be disposed. The input1 will be disposed.) */
  static ConcatShuffleSplit_and_keep0_destroy1( inputTensors, outputTensors ) {
    this.inputTensors[ 0 ] = this.input0.realTensor;
    this.inputTensors[ 1 ] = this.input1.realTensor;
    let t0 = tf.concat( this.inputTensors, 2 ); // AxisId = 2
    this.input1.realTensor.dispose();

    this.pfnShuffleSplit( t0 );
  }

  /** Concatenate along axis id 2. (The input0 will be disposed. The input1 will not be disposed.) */
  static ConcatShuffleSplit_and_destroy0_keep1( inputTensors, outputTensors ) {
    this.inputTensors[ 0 ] = this.input0.realTensor;
    this.inputTensors[ 1 ] = this.input1.realTensor;
    let t0 = tf.concat( this.inputTensors, 2 ); // AxisId = 2
    this.input0.realTensor.dispose();

    this.pfnShuffleSplit( t0 );
  }

  /** Concatenate along axis id 2. (Both the input0 and input1 will be disposed.) */
  static ConcatShuffleSplit_and_destroy0_destroy1( inputTensors, outputTensors ) {
    this.inputTensors[ 0 ] = this.input0.realTensor;
    this.inputTensors[ 1 ] = this.input1.realTensor;
    let t0 = tf.concat( this.inputTensors, 2 ); // AxisId = 2
    this.input0.realTensor.dispose();
    this.input1.realTensor.dispose();

    this.pfnShuffleSplit( t0 );
  }

}
<commit_msg>Update Operation_ConcatShuffleSplit.js<commit_after>export { ConcatShuffleSplit };

import * as TensorPlaceholder from "../TensorPlaceholder.js";
import * as BoundsArraySet from "../BoundsArraySet.js";
import * as ChannelShuffler from "../ChannelShuffler.js";
import { Base } from "./Operation_Base.js";

/**
 * Concatenate two tensor3d along depth (i.e. axis id 2) and then channel shuffling and splitting.
 *
 *   - Concatenate two tensor3d ( height x width x channel ) always along the last axis (i.e. axisId = 2, along the channel axis).
 *   - Shuffle. (may not exist.)
 *   - Split. (may not exist.)
 *
 * It could destroy one or two of the input tensors.
 *
 *
 * @member {ChannelShuffler.ConcatPointwiseConv} channelShuffler
 *   It must be implemented by ChannelShuffler.ConcatPointwiseConv with ( outputGroupCount == 2 ). It will not be disposed by
 * this object (i.e. it is supposed to be shared with outter callers).
 *
 *     - The channelShuffler.shuffleInfo.totalChannelCount should be the same as the channel count of the concatenated
 *         inputTensors[].
 *
 *     - The channelShuffler.filtersTensor4dArray[ 0 ] and channelShuffler.filtersTensor4dArray[ 1 ] will be used for
 *         channel shuffling and splitting.
 *
 * @member {boolean} bShuffleSplit
 *   If false, there will be no channel shuffling and not splitting after concatenation.
 *
 * @member {boolean} bKeepInputTensor0
 *   If false, the first input tensor will be disposed after concatenating. If true, the first input tensor will be kept after concatenating.
 *
 * @member {boolean} bKeepInputTensor1
 *   If false, the second input tensor will be disposed after concatenating. If true, the second input tensor will be kept after concatenating.
 *
 * @param {ActivationEscaping.ScaleBoundsArray} inputScaleBoundsArray0
 *   The element value bounds (per channel) of this concatenation operation's input0. It will be kept (not cloned) directly. So caller
 * should not modify them.
 *
 * @param {ActivationEscaping.ScaleBoundsArray} inputScaleBoundsArray1
 *   The element value bounds (per channel) of this concatenation operation's input1. It will be kept (not cloned) directly. So caller
 * should not modify them.
 *
 * @member {BoundsArraySet.InputsOutputs} boundsArraySet
 *   The element value bounds (per channel) of this concatenation operation.
 *
 * @member {function} apply
 *   This is a method. It processes this.input0.realTensor and this.input1.realTensor as inputTensors. It puts to this.output0.realTensor
 * as outputTensor. Both inputTensors are tf.tensor3d and represents an images ( height x width x channel ) which will be concatenated,
 * shuffle, split. They should have the same ( height x width ) but could have different channel count. The outputTensor (tf.tensor3d)
 * represents the result. The inputTensor may or may not be disposed. In fact, this method calls one of ConcatShuffleSplit_and_keep0_keep1(),
 * ConcatShuffleSplit_and_keep0_destroy1(), ConcatShuffleSplit_and_destroy0_keep1(), ConcatShuffleSplit_and_destroy0_destroy1() according
 * to the parameters.
 *
 */
class ConcatShuffleSplit extends Base() {

  /**
   * @param {Array} arrayTemp_forInterleave_asGrouptTwo
   *   A temporary array for placing the original elements temporarily. Provide this array could reduce memory re-allocation
   * and improve performance when doing Interleave_asGrouptTwo.
   *
   */
  constructor(
    inputTensorPlaceholder0, inputTensorPlaceholder1,
    channelShuffler, bShuffleSplit = true,
    inputScaleBoundsArray0, inputScaleBoundsArray1,
    arrayTemp_forInterleave_asGrouptTwo,
    bKeepInputTensor0, bKeepInputTensor1
  ) {

    // Note: outputs' TensorPlaceholder will be created later (in setup_outputs_TensorPlaceholder()).
    super( inputTensorPlaceholder0, inputTensorPlaceholder1, 0 );

    this.channelShuffler = channelShuffler;

    this.inputTensors = new Array( 2 ); // For reducing memory re-allocation.

//!!! (2022/06/01 Remaked)
// When bShuffleSplit is changed, the BoundsArraySet and outputs' TensorPlacehoder will also be changed.
//    this.setShuffleSplit_KeepInputTensor( bShuffleSplit, bKeepInputTensor0, bKeepInputTensor1 );

    // Note: If bShuffleSplit is changed, the BoundsArraySet and outputs' TensorPlacehoder will also be changed.
    //       Then the inputScaleBoundsArray0, inputScaleBoundsArray1, arrayTemp_forInterleave_asGrouptTwo will be
    //       required again. That is difficult. So forbid to change bShuffleSplit.
    //
    this.bShuffleSplit = bShuffleSplit;
    this.bShouldShuffleSplit = ( ( this.bShuffleSplit ) && ( this.channelShuffler ) ); // Want and could do channel shuffling and splitting.

    Base.adjust_pfn.call( this );
    Base.setup_BoundsArraySet.call( this, inputScaleBoundsArray0, inputScaleBoundsArray1, arrayTemp_forInterleave_asGrouptTwo );
    Base.setup_outputs_TensorPlaceholder.call( this );
  }

//!!! (2022/06/01 Remaked)
// When bShuffleSplit is changed, the BoundsArraySet and outputs' TensorPlacehoder will also be changed.
//   /**
//    * Set this.bShuffleSplit and adjust this.pfnShuffleSplit.
//    */
//   setShuffleSplit( bShuffleSplit, arrayTemp_forInterleave_asGrouptTwo ) {
//     this.bShuffleSplit = bShuffleSplit;
//     this.bShouldShuffleSplit = ( ( this.bShuffleSplit ) && ( this.channelShuffler ) ); // Want and could do channel shuffling and splitting.
//     Base.adjust_pfn.call( this );
//     Base.setup_BoundsArraySet.call( this, inputScaleBoundsArray0, inputScaleBoundsArray1, arrayTemp_forInterleave_asGrouptTwo );
//     Base.setup_output0_TensorPlaceholder.call( this );
//   }

  /**
   * Set this.bKeepInputTensor0 and adjust this.apply so that inputTensors[ 0 ] will or will not be disposed.
   */
  setKeepInputTensor0( bKeepInputTensor0 ) {
    this.bKeepInputTensor0 = bKeepInputTensor0;
    Base.adjust_apply.call( this );
  }

  /**
   * Set this.bKeepInputTensor1 and adjust this.apply so that inputTensors[ 1 ] will or will not be disposed.
   */
  setKeepInputTensor1( bKeepInputTensor1 ) {
    this.bKeepInputTensor1 = bKeepInputTensor1;
    Base.adjust_apply.call( this );
  }

  /**
   * Set this.bKeepInputTensor0 and this.bKeepInputTensor1, and adjust this.apply so that inputTensors[ 0 ]
   * and inputTensors[ 1 ] will or will not be disposed.
   */
  setKeepInputTensor( bKeepInputTensor0, bKeepInputTensor1 ) {
    this.bKeepInputTensor0 = bKeepInputTensor0;
    this.bKeepInputTensor1 = bKeepInputTensor1;
    Base.adjust_apply.call( this );
  }

//!!! (2022/06/01 Remaked)
// When bShuffleSplit is changed, the BoundsArraySet and outputs' TensorPlacehoder will also be changed.
//   /**
//    * Set this.bShuffleSplit, this.bKeepInputTensor0, this.bKeepInputTensor1, and then adjust this.pfnShuffleSplit and
//    * this.apply.
//    */
//   setShuffleSplit_KeepInputTensor( bShuffleSplit, bKeepInputTensor0, bKeepInputTensor1 ) {
//     this.setShuffleSplit( bShuffleSplit, arrayTemp_forInterleave_asGrouptTwo );
//
//     this.bKeepInputTensor0 = bKeepInputTensor0;
//     this.bKeepInputTensor1 = bKeepInputTensor1;
//     Base.adjust_apply.call( this );
//   }

  /** Set this.pfnShuffleSplit according to this.bShuffleSplit, this.channelShuffler. */
  static adjust_pfn() {
    if ( this.bShouldShuffleSplit ) {

      tf.util.assert( ( this.channelShuffler instanceof ChannelShuffler.ConcatPointwiseConv ),
        `Operation.ConcatShuffleSplit.adjust_pfn(): `
          + `channelShuffler must be an instance of class ChannelShuffler.ConcatPointwiseConv.`
      );

      this.pfnShuffleSplit = Base.ShuffleSplit_do; // Want and could do channel shuffling and splitting.
    } else {
      this.pfnShuffleSplit = Base.ShuffleSplit_return_input_directly;
    }
  }

  /** Set this.apply according to this.bKeepInputTensor0 and this.bKeepInputTensor1. */
  static adjust_apply() {
    if ( this.bKeepInputTensor0 ) {
      if ( this.bKeepInputTensor1 ) {
        this.apply = Base.ConcatShuffleSplit_and_keep0_keep1;
      } else {
        this.apply = Base.ConcatShuffleSplit_and_keep0_destroy1;
      }
    } else {
      if ( this.bKeepInputTensor1 ) {
        this.apply = Base.ConcatShuffleSplit_and_destroy0_keep1;
      } else {
        this.apply = Base.ConcatShuffleSplit_and_destroy0_destroy1;
      }
    }
  }

  /** Create this.boundsArraySet. */
  static setup_BoundsArraySet( inputScaleBoundsArray0, inputScaleBoundsArray1, arrayTemp_forInterleave_asGrouptTwo ) {

    // Concatenated value bounds array set.
    let concatBoundsArraySet;
    {
      concatBoundsArraySet = new BoundsArraySet.InputsOutputs( inputScaleBoundsArray0, inputScaleBoundsArray1,
        1 // Arbitrarily set a legal (but temporary) outputChannelCount0. It will be adjusted later.
      );

      concatBoundsArraySet.set_outputs_all_by_concat_input0_input1(); // The outputChannelCount0 will be adjusted.
    }

    if ( this.bShouldShuffleSplit ) { // Want and could do channel shuffling and splitting.

      tf.util.assert( ( this.channelShuffler.outputGroupCount == 2 ),
        `Operation.ConcatShuffleSplit.setup_BoundsArraySet(): `
          + `channelShuffler.outputGroupCount ( ${this.channelShuffler.outputGroupCount} ) must be 2 `
          + `( other outputGroupCount does not supperted ).`
      );

      // Shuffled value bounds array set.
      let shuffledBoundsArraySet;
      {
        shuffledBoundsArraySet = new BoundsArraySet.InputsOutputs( concatBoundsArraySet.output0, null,
          concatBoundsArraySet.output0.channelCount );

        shuffledBoundsArraySet.output0.set_all_byScaleBoundsArray( concatBoundsArraySet.output0 );
        shuffledBoundsArraySet.set_outputs_all_byInterleave_asGrouptTwo( arrayTemp_forInterleave_asGrouptTwo );
      }

      // Splitted value bounds array set.
      let splittedBoundsArraySet;
      {
        splittedBoundsArraySet = new BoundsArraySet.InputsOutputs( shuffledBoundsArraySet.output0, null,
          1, 1  // Arbitrarily set a legal (but temporary) outputChannelCount0 and outputChannelCount1. It will be adjusted later.
        );

        splittedBoundsArraySet.set_outputs_all_byBoundsArray_split_input0();
      }

      this.boundsArraySet = splittedBoundsArraySet;

    } else { // Only concatenation is needed.
      this.boundsArraySet = concatBoundsArraySet;
    }
  }

  /** Setup this.output0 and this.output1. */
  static setup_outputs_TensorPlaceholder() {

    this.output0 = new TensorPlaceholder.Base();
    this.output0.height = this.input0.height;
    this.output0.width = this.input0.width;

    if ( this.bShouldShuffleSplit ) { // Only if splitting is required, the output1 does exist.
      this.output1 = new TensorPlaceholder.Base();
      this.output1.height = this.input0.height;
      this.output1.width = this.input0.width;

      // Because only tensor3d and ChannelShuffler.ConcatPointwiseConv and ( outputGroupCount == 2 ) are supported,
      // using the pointwise convolution filters' shape for output channel count.
      const outputChannelCount_filterAxisId = 3;
      this.output0.channelCount = this.channelShuffler.filtersTensor4dArray[ 0 ].shape[ outputChannelCount_filterAxisId ];
      this.output1.channelCount = this.channelShuffler.filtersTensor4dArray[ 1 ].shape[ outputChannelCount_filterAxisId ];

    } else { // Only concatenation.
      this.output0.channelCount = this.input0.channelCount + this.input1.channelCount;
    }
  }

  /**
   * Outputs are placed in this.output0.realTensor and this.output1.realTensor directly.
   *
   * @param {tf.tensor3d} inputTensor
   *   The tensor to be shuffled and splitted.
   */
  static ShuffleSplit_do( inputTensor ) {

    // Since there is only two output group (i.e. ( outputGroupCount == 2 ) ), do not use loop (i.e. use unrolled-loop)
    // so the performance could be better a little.
    this.output0.realTensor = tf.conv2d( inputTensor, this.channelShuffler.filtersTensor4dArray[ 0 ], 1, "valid" );
    this.output1.realTensor = tf.conv2d( inputTensor, this.channelShuffler.filtersTensor4dArray[ 1 ], 1, "valid" );

    // Always destroy input. Because tf.concat() has always been done before this method is called, the keep-input has already be
    // done by it.
    inputTensor.dispose();
  }

  /** Just return inputTensor at this.output0.realTensor. */
  static ShuffleSplit_return_input_directly( inputTensor ) {
    this.output0.realTensor = inputTensor;

    // Do not call inputTensor.dispose(). In fact, because inputTensor is returned directly, it is the same as been disposed already.
  }

  /** Concatenate along axis id 2. (Both the input0 and input1 will not be disposed.) */
  static ConcatShuffleSplit_and_keep0_keep1( inputTensors, outputTensors ) {
    this.inputTensors[ 0 ] = this.input0.realTensor;
    this.inputTensors[ 1 ] = this.input1.realTensor;
    let t0 = tf.concat( this.inputTensors, 2 ); // AxisId = 2

    this.pfnShuffleSplit( t0 );
  }

  /** Concatenate along axis id 2. (The input0 will not be disposed. The input1 will be disposed.) */
  static ConcatShuffleSplit_and_keep0_destroy1( inputTensors, outputTensors ) {
    this.inputTensors[ 0 ] = this.input0.realTensor;
    this.inputTensors[ 1 ] = this.input1.realTensor;
    let t0 = tf.concat( this.inputTensors, 2 ); // AxisId = 2
    this.input1.realTensor.dispose();

    this.pfnShuffleSplit( t0 );
  }

  /** Concatenate along axis id 2. (The input0 will be disposed. The input1 will not be disposed.) */
  static ConcatShuffleSplit_and_destroy0_keep1( inputTensors, outputTensors ) {
    this.inputTensors[ 0 ] = this.input0.realTensor;
    this.inputTensors[ 1 ] = this.input1.realTensor;
    let t0 = tf.concat( this.inputTensors, 2 ); // AxisId = 2
    this.input0.realTensor.dispose();

    this.pfnShuffleSplit( t0 );
  }

  /** Concatenate along axis id 2. (Both the input0 and input1 will be disposed.) */
  static ConcatShuffleSplit_and_destroy0_destroy1( inputTensors, outputTensors ) {
    this.inputTensors[ 0 ] = this.input0.realTensor;
    this.inputTensors[ 1 ] = this.input1.realTensor;
    let t0 = tf.concat( this.inputTensors, 2 ); // AxisId = 2
    this.input0.realTensor.dispose();
    this.input1.realTensor.dispose();

    this.pfnShuffleSplit( t0 );
  }

}
<|endoftext|>


<commit_before>$(document).ready(setUp);

function setUp() {
  $('nav span').click(loadGif);
}

function loadGif() {
  var search = $(this).text();
  $.get('http://api.giphy.com/v1/gifs/search', {
      q: search,
      api_key: 'dc6zaTOxFJmzC'
    },
    showGif
 )
}

function showGif(data) {
  image_url = data.data[0].images.fixed_width.url;
  $('#thegif img').attr('src', image_url);
}
<commit_msg>Randomize gifs that are shown<commit_after>$(document).ready(setUp);

function setUp() {
  $('nav span').click(loadGif);
}

function loadGif() {
  var search = $(this).text();
  $.get('http://api.giphy.com/v1/gifs/search', {
      q: search,
      api_key: 'dc6zaTOxFJmzC'
    },
    showGif
 )
}

function showGif(data) {
  var gifs = data.data;
  var numberOfGifs = gifs.length;
  if (numberOfGifs === 0) {
    alert('No gifs for you');
  } else {
    var randomIndex = Math.floor(Math.random() * numberOfGifs);
  }
  image_url = data.data[randomIndex].images.fixed_width.url;
  $('#thegif img').attr('src', image_url);
}
<|endoftext|>


<commit_before>import React from 'react';

import Analyzer from 'Parser/Core/Analyzer';
import Combatants from 'Parser/Core/Modules/Combatants';
import Enemies from 'Parser/Core/Modules/Enemies';

import SPELLS from 'common/SPELLS';
import StatisticBox, { STATISTIC_ORDER } from 'Main/StatisticBox';
import SpellIcon from 'common/SpellIcon';
import { formatNumber, formatPercentage } from 'common/format';

class Havoc extends Analyzer {
  static dependencies = {
    enemies: Enemies,
    combatants: Combatants,
  };

  damage = 0;

  on_byPlayer_damage(event) {
    const enemy = this.enemies.getEntity(event);
    if (!enemy || !enemy.hasBuff(SPELLS.HAVOC.id, event.timestamp)) {
      return;
    }

    this.damage += event.amount + (event.absorbed || 0);
  }

  // TODO: this could perhaps be reworked somehow to be more accurate but not sure how yet. Take it as a Havoc v1.0
  statistic() {
    return (
      <StatisticBox
        icon={<SpellIcon id={SPELLS.HAVOC.id} />}
        value={`${formatNumber(this.damage / this.owner.fightDuration * 1000)} DPS`}
        label="Damage cleaved"
        tooltip={`You cleaved ${formatNumber(this.damage)} damage (${formatPercentage(this.owner.getPercentageOfTotalDamageDone(this.damage))} %) to targets afflicted by your Havoc.

Note: This number might be higher than it should be, as it also counts the damage you did directly to the Havoc target (not just the cleaved damage).`}
      />
    );
  }

  statisticOrder = STATISTIC_ORDER.CORE(4);
}

export default Havoc;
<commit_msg>hide havoc<commit_after>import React from 'react';

import Analyzer from 'Parser/Core/Analyzer';
import Combatants from 'Parser/Core/Modules/Combatants';
import Enemies from 'Parser/Core/Modules/Enemies';

import SPELLS from 'common/SPELLS';
import StatisticBox, { STATISTIC_ORDER } from 'Main/StatisticBox';
import SpellIcon from 'common/SpellIcon';
import { formatNumber, formatPercentage } from 'common/format';

class Havoc extends Analyzer {
  static dependencies = {
    enemies: Enemies,
    combatants: Combatants,
  };

  damage = 0;

  on_byPlayer_damage(event) {
    const enemy = this.enemies.getEntity(event);
    if (!enemy || !enemy.hasBuff(SPELLS.HAVOC.id, event.timestamp)) {
      return;
    }

    this.damage += event.amount + (event.absorbed || 0);
  }

  // TODO: this could perhaps be reworked somehow to be more accurate but not sure how yet. Take it as a Havoc v1.0
  statistic() {
    if (this.damage===0){return;}
    return (
      <StatisticBox
        icon={<SpellIcon id={SPELLS.HAVOC.id} />}
        value={`${formatNumber(this.damage / this.owner.fightDuration * 1000)} DPS`}
        label="Damage cleaved"
        tooltip={`You cleaved ${formatNumber(this.damage)} damage (${formatPercentage(this.owner.getPercentageOfTotalDamageDone(this.damage))} %) to targets afflicted by your Havoc.

Note: This number might be higher than it should be, as it also counts the damage you did directly to the Havoc target (not just the cleaved damage).`}
      />
    );
  }

  statisticOrder = STATISTIC_ORDER.CORE(4);
}

export default Havoc;
<|endoftext|>


<commit_before>define(function() {
    return {
        "userSectionIndex" : 3,
        "sections" : [
            {
                "label" : "Academic",
                "links" : [
                    {
                        "id"   : "bspace",
                        "name" : "bSpace",
                        "url" : "http://bspace.berkeley.edu",
                        "popup_description": "Homework assignments, lecture slides, syllabi, and class resources."
                    },
                    {
                        "id"   : "campus_bookstore",
                        "name" : "Campus Bookstore",
                        "url"  : "http://www.bkstr.com/webapp/wcs/stores/servlet/StoreCatalogDisplay?storeId=10433",
                        "popup_description": "Find and purchase textbooks by course."
                    },
                    {
                        "id": "course_catalog",
                        "name": "Course Catalog",
                        "url": "http://sis.berkeley.edu/catalog/gcc_search_menu",
                        "popup_description": "Detailed course descriptions."
                    },
                    {
                        "id"   : "dars",
                        "name" : "DARS",
                        "url"  : "https://marin.berkeley.edu/darsweb/servlet/ListAuditsServlet",
                        "popup_description": "Track progress toward a major."
                    },
                    {
                        "id": "decal",
                        "name": "DeCal Courses",
                        "url": "http://www.decal.org",
                        "popup_description": "Explore student-taught courses."
                    },
                    {
                        "id": "future_campus_calendars",
                        "name": "Future Campus Calendars",
                        "url": "http://opa.berkeley.edu/AcademicCalendar",
                        "popup_description": "Look at campus calendars for upcoming semesters."
                    },
                    {
                        "id": "library",
                        "name": "Library",
                        "url": "http://www.lib.berkeley.edu",
                        "popup_description": "Search for materials in the UC library system."
                    },
                    {
                        "id": "class_schedule",
                        "name": "Schedule of Classes",
                        "url": "http://schedule.berkeley.edu",
                        "popup_description": "See current and upcoming courses."
                    },

                    {
                        "id": "schedule_planning",
                        "name": "Schedule Planning Tools",
                        "url": "http://asuc.org/newsite2010/resources/academic-resources/schedule-planning-tools/",
                        "popup_description": "Tools to help you plan your class schedule."
                    },
                    {
                        "id": "tele_bears",
                        "name": "Tele-BEARS",
                        "url": "http://telebears.berkeley.edu",
                        "popup_description": "Register for classes."
                    }
                ]
            },
            {
                "label" : "Administrative",
                "links" : [
                    {
                        "id": "bear_facts",
                        "name": "Bear Facts",
                        "url": "https://bearfacts.berkeley.edu/bearfacts/student/studentMain.do?bfaction=welcome",
                        "popup_description": "See your registration and financial info, grades, online bill, and personal data."
                    },
                    {
                        "id": "calmail",
                        "name": "CalMail",
                        "url": "http://calmail.berkeley.edu",
                        "popup_description": "Read and manage your university email."
                    },
                    {
                        "id": "campus_calendar",
                        "name": "Campus Events Calendar",
                        "url": "http://events.berkeley.edu",
                        "popup_description": "View upcoming events on campus."
                    },
                    {
                        "id": "career_center",
                        "name": "Career Center",
                        "url": "http://career.berkeley.edu",
                        "popup_description": "Find jobs, internships, and learn about career paths."
                    },
                    {
                        "id": "finaid",
                        "name": "Financial Aid",
                        "url": "http://students.berkeley.edu/finaid",
                        "popup_description": "Learn about financial aid and scholarships."
                    }
                ]
            },
            {
                "label" : "Campus Life",
                "links" : [
                    {
                        "id": "asuc",
                        "name": "ASUC",
                        "url": "http://www.asuc.org",
                        "popup_description": "UC Berkeley's student government home."
                    },
                    {
                        "id": "atoz_sites",
                        "name": "Berkeley Sites (A-Z)",
                        "url": "http://www.berkeley.edu/a-z/a.shtml",
                        "popup_description": "Comprehensive list of official campus websites."
                    },
                    {
                        "id": "cal1card",
                        "name": "Cal-1-Card",
                        "url": "http://services.housing.berkeley.edu/c1c/static/aboutc1c.htm",
                        "popup_description": "Manage and learn about your Cal 1 Card."
                    },
                    {
                        "id": "caldining",
                        "name": "CalDining",
                        "url": "http://caldining.berkeley.edu",
                        "popup_description": "View daily menus and check your meal points."
                    },
                    {
                        "id": "campus_map",
                        "name": "Campus Map",
                        "url": "http://berkeley.edu/map",
                        "popup_description": "View campus maps and find buildings using the interactive map."
                    },
                    {
                        "id": "campus_safety",
                        "name": "Campus Safety / Police",
                        "url": "http://police.berkeley.edu",
                        "popup_description": "Learn about UCPD services."
                    },
                    {
                        "id": "parking_and_transportation",
                        "name": "Parking & Transportation",
                        "url": "http://pt.berkeley.edu/park",
                        "popup_description": "Find and pay for parking."
                    },
                    {
                        "id": "public_service",
                        "name": "Public Service",
                        "url": "http://calcorps.berkeley.edu",
                        "popup_description": "Get involved in public service."
                    },
                    {
                        "id": "rsf",
                        "name": "Recreational Sports Facility",
                        "url": "http://www.recsports.berkeley.edu",
                        "popup_description": "Explore RSF programs and intramural sports."
                    },
                    {
                        "id": "rescomp",
                        "name": "Residential Computing",
                        "url": "http://rescomp.berkeley.edu",
                        "popup_description": "Computing help for the residence halls."
                    },
                    {
                        "id": "resource_guide",
                        "name": "Resource Guide for Students",
                        "url": "http://resource.berkeley.edu",
                        "popup_description": "Information about campus resources."
                    },

                    {
                        "id": "student_groups",
                        "name": "Student Groups and Programs",
                        "url": "http://students.berkeley.edu/osl",
                        "popup_description": "Student organizations, leadership programs, and GenEq."
                    },

                    {
                        "id": "student_services",
                        "name": "Student Services",
                        "url": "http://www.berkeley.edu/students",
                        "popup_description": "Several student sites grouped by function."
                    },
                    {
                        "id": "uhs",
                        "name": "UHS - Tang Center",
                        "url": "http://uhs.berkeley.edu",
                        "popup_description": "Health and medical services for students."
                    }
                ]
            },
            {
                "label" : "My Links",
                "links" : [],
                "isEditable" : true,
                "activeSection" : 0
            }
        ]
    };
});
<commit_msg>Added the GA link to Campus Life<commit_after>define(function() {
    return {
        "userSectionIndex" : 3,
        "sections" : [
            {
                "label" : "Academic",
                "links" : [
                    {
                        "id"   : "bspace",
                        "name" : "bSpace",
                        "url" : "http://bspace.berkeley.edu",
                        "popup_description": "Homework assignments, lecture slides, syllabi, and class resources."
                    },
                    {
                        "id"   : "campus_bookstore",
                        "name" : "Campus Bookstore",
                        "url"  : "http://www.bkstr.com/webapp/wcs/stores/servlet/StoreCatalogDisplay?storeId=10433",
                        "popup_description": "Find and purchase textbooks by course."
                    },
                    {
                        "id": "course_catalog",
                        "name": "Course Catalog",
                        "url": "http://sis.berkeley.edu/catalog/gcc_search_menu",
                        "popup_description": "Detailed course descriptions."
                    },
                    {
                        "id"   : "dars",
                        "name" : "DARS",
                        "url"  : "https://marin.berkeley.edu/darsweb/servlet/ListAuditsServlet",
                        "popup_description": "Track progress toward a major."
                    },
                    {
                        "id": "decal",
                        "name": "DeCal Courses",
                        "url": "http://www.decal.org",
                        "popup_description": "Explore student-taught courses."
                    },
                    {
                        "id": "future_campus_calendars",
                        "name": "Future Campus Calendars",
                        "url": "http://opa.berkeley.edu/AcademicCalendar",
                        "popup_description": "Look at campus calendars for upcoming semesters."
                    },
                    {
                        "id": "library",
                        "name": "Library",
                        "url": "http://www.lib.berkeley.edu",
                        "popup_description": "Search for materials in the UC library system."
                    },
                    {
                        "id": "class_schedule",
                        "name": "Schedule of Classes",
                        "url": "http://schedule.berkeley.edu",
                        "popup_description": "See current and upcoming courses."
                    },

                    {
                        "id": "schedule_planning",
                        "name": "Schedule Planning Tools",
                        "url": "http://asuc.org/newsite2010/resources/academic-resources/schedule-planning-tools/",
                        "popup_description": "Tools to help you plan your class schedule."
                    },
                    {
                        "id": "tele_bears",
                        "name": "Tele-BEARS",
                        "url": "http://telebears.berkeley.edu",
                        "popup_description": "Register for classes."
                    }
                ]
            },
            {
                "label" : "Administrative",
                "links" : [
                    {
                        "id": "bear_facts",
                        "name": "Bear Facts",
                        "url": "https://bearfacts.berkeley.edu/bearfacts/student/studentMain.do?bfaction=welcome",
                        "popup_description": "See your registration and financial info, grades, online bill, and personal data."
                    },
                    {
                        "id": "calmail",
                        "name": "CalMail",
                        "url": "http://calmail.berkeley.edu",
                        "popup_description": "Read and manage your university email."
                    },
                    {
                        "id": "campus_calendar",
                        "name": "Campus Events Calendar",
                        "url": "http://events.berkeley.edu",
                        "popup_description": "View upcoming events on campus."
                    },
                    {
                        "id": "career_center",
                        "name": "Career Center",
                        "url": "http://career.berkeley.edu",
                        "popup_description": "Find jobs, internships, and learn about career paths."
                    },
                    {
                        "id": "finaid",
                        "name": "Financial Aid",
                        "url": "http://students.berkeley.edu/finaid",
                        "popup_description": "Learn about financial aid and scholarships."
                    }
                ]
            },
            {
                "label" : "Campus Life",
                "links" : [
                    {
                        "id": "asuc",
                        "name": "ASUC",
                        "url": "http://www.asuc.org",
                        "popup_description": "UC Berkeley's student government home."
                    },
                    {
                        "id": "atoz_sites",
                        "name": "Berkeley Sites (A-Z)",
                        "url": "http://www.berkeley.edu/a-z/a.shtml",
                        "popup_description": "Comprehensive list of official campus websites."
                    },
                    {
                        "id": "cal1card",
                        "name": "Cal-1-Card",
                        "url": "http://services.housing.berkeley.edu/c1c/static/aboutc1c.htm",
                        "popup_description": "Manage and learn about your Cal 1 Card."
                    },
                    {
                        "id": "caldining",
                        "name": "CalDining",
                        "url": "http://caldining.berkeley.edu",
                        "popup_description": "View daily menus and check your meal points."
                    },
                    {
                        "id": "campus_map",
                        "name": "Campus Map",
                        "url": "http://berkeley.edu/map",
                        "popup_description": "View campus maps and find buildings using the interactive map."
                    },
                    {
                        "id": "campus_safety",
                        "name": "Campus Safety / Police",
                        "url": "http://police.berkeley.edu",
                        "popup_description": "Learn about UCPD services."
                    },
                    {
                        "id": "graduate_assembly",
                        "name": "Graduate Assembly",
                        "url": "http://ga.berkeley.edu",
                        "popup_description": "The Graduate Assembly sponsors projects and provides resources to improve the lives of graduate students and foster a vibrant, inclusive graduate student community."
                    },
                    {
                        "id": "parking_and_transportation",
                        "name": "Parking & Transportation",
                        "url": "http://pt.berkeley.edu/park",
                        "popup_description": "Find and pay for parking."
                    },
                    {
                        "id": "public_service",
                        "name": "Public Service",
                        "url": "http://calcorps.berkeley.edu",
                        "popup_description": "Get involved in public service."
                    },
                    {
                        "id": "rsf",
                        "name": "Recreational Sports Facility",
                        "url": "http://www.recsports.berkeley.edu",
                        "popup_description": "Explore RSF programs and intramural sports."
                    },
                    {
                        "id": "rescomp",
                        "name": "Residential Computing",
                        "url": "http://rescomp.berkeley.edu",
                        "popup_description": "Computing help for the residence halls."
                    },
                    {
                        "id": "resource_guide",
                        "name": "Resource Guide for Students",
                        "url": "http://resource.berkeley.edu",
                        "popup_description": "Information about campus resources."
                    },

                    {
                        "id": "student_groups",
                        "name": "Student Groups and Programs",
                        "url": "http://students.berkeley.edu/osl",
                        "popup_description": "Student organizations, leadership programs, and GenEq."
                    },

                    {
                        "id": "student_services",
                        "name": "Student Services",
                        "url": "http://www.berkeley.edu/students",
                        "popup_description": "Several student sites grouped by function."
                    },
                    {
                        "id": "uhs",
                        "name": "UHS - Tang Center",
                        "url": "http://uhs.berkeley.edu",
                        "popup_description": "Health and medical services for students."
                    }
                ]
            },
            {
                "label" : "My Links",
                "links" : [],
                "isEditable" : true,
                "activeSection" : 0
            }
        ]
    };
});
<|endoftext|>


<commit_before>/*
  may I be willing to rewrite the quick-log fcns, the following hack accept the
  browser syntax to apply styling to the output
*/

Myconsolelog = function(messageStr){
  var args = Array.prototype.slice.call(arguments, 1);
  for(var i=0; i < args.length; i++){
    var nodeStyle = '';
    //args[i].indexOf('color:') > -1 ? nodeStyle += args[i].substr(args[i].indexOf('color:')+7, args[i].indexOf(';')+1 ) : '';
    //args[i].indexOf('background:') > -1 ? nodeStyle += args[i].substr(args[i].indexOf('background:')+12, args[i].indexOf(';')+1 ) : '';
    var styleArgs = args[i].split(';');
    for(var j=0; j < styleArgs.length; j++){
      console.log('j: ' + ' data: ' + styleArgs[j])
      var styleArg = styleArgs[j];
      styleArg[0] === ' ' ? styleArg = styleArg.substr(1) : '';
      console.log('j: ' + ' data: ' + styleArg)
      if(styleArg){
        styleArg.indexOf('color:') > -1 ? nodeStyle += styleArg.substr(styleArg.indexOf('color:')+7) : ''; // TODO: replace by call to helper fcn that translates the color passed ( #XXXXXX ) to a nodejs format ( \x1b[XXm )
        styleArg.indexOf('background:') > -1 ? nodeStyle += styleArg.substr(styleArg.indexOf('background:')+12 ) : ''; // TODO: same as above ( R/Nb: '\e[33m' & '\x1b' both works using 'echo -e ' in teminal )
      }
    }
    messageStr = messageStr.replace('%c', nodeStyle)
    //messageStr = messageStr.replace('%c', 'LOL')
  }
  //_console.log(messageStr)
  console.log(messageStr)
}

/* == R: coloring scheme to find a match in terminal ANSI colors ==*/
// == general coloring scheme ==
var resColorsMap = {
  silver: '#C0C0C0',
  gold:   '#B8860B',
  black:  '#000000',
  brown:  '#A0522D',
  red:    '#FF0000',
  orange: '#FF8C00',
  yellow: '#FFD700',
  green:  '#008000',
  blue:   '#0000CD',
  purple: '#800080',
  gray:   '#808080',
  white:  '#F8F8FF',
};
<commit_msg>Update Resistor_nodeModule_consoleLogColorsHack.js<commit_after>/*
  may I be willing to rewrite the quick-log fcns, the following hack accept the
  browser syntax to apply styling to the output
*/

Myconsolelog = function(messageStr){
  var args = Array.prototype.slice.call(arguments, 1);
  for(var i=0; i < args.length; i++){
    var nodeStyle = '';
    //args[i].indexOf('color:') > -1 ? nodeStyle += args[i].substr(args[i].indexOf('color:')+7, args[i].indexOf(';')+1 ) : '';
    //args[i].indexOf('background:') > -1 ? nodeStyle += args[i].substr(args[i].indexOf('background:')+12, args[i].indexOf(';')+1 ) : '';
    var styleArgs = args[i].split(';');
    for(var j=0; j < styleArgs.length; j++){
      console.log('j: ' + ' data: ' + styleArgs[j])
      var styleArg = styleArgs[j];
      styleArg[0] === ' ' ? styleArg = styleArg.substr(1) : '';
      console.log('j: ' + ' data: ' + styleArg)
      if(styleArg){
        styleArg.indexOf('color:') > -1 ? nodeStyle += styleArg.substr(styleArg.indexOf('color:')+7) : ''; // TODO: replace by call to helper fcn that translates the color passed ( #XXXXXX ) to a nodejs format ( \x1b[XXm )
        styleArg.indexOf('background:') > -1 ? nodeStyle += styleArg.substr(styleArg.indexOf('background:')+12 ) : ''; // TODO: same as above ( R/Nb: '\e[33m' & '\x1b' both works using 'echo -e ' in teminal )
      }
    }
    messageStr = messageStr.replace('%c', nodeStyle)
    //messageStr = messageStr.replace('%c', 'LOL')
  }
  //_console.log(messageStr)
  console.log(messageStr)
}

/* == R: coloring scheme to find a match in terminal ANSI colors ==*/
// == general coloring scheme ==
var resColorsMap = {
  silver: '#C0C0C0', // \e[38;5;7m
  gold:   '#B8860B', // \e[38;5;3m
  black:  '#000000', // \e[38;5;16m
  brown:  '#A0522D', // \e[38;5;95m
  red:    '#FF0000', // \e[38;5;1m
  orange: '#FF8C00', // \e[38;5;166m
  yellow: '#FFD700', // \e[38;5;11m
  green:  '#008000', // \e[38;5;2m
  blue:   '#0000CD', // \e[38;5;20m
  purple: '#800080', // \e[38;5;54m
  gray:   '#808080', // \e[38;5;59m
  white:  '#F8F8FF', // \e[38;5;255m
};

var termColorsMap = {
  resColorsMap.silver: ['\x1b[38;5;7m', '\x1b[48;5;7m'],     // #C0C0C0
  resColorsMap.gold:   ['\x1b[38;5;3m', '\x1b[48;5;3m'],     // #B8860B
  resColorsMap.black:  ['\x1b[38;5;16m', '\x1b[48;5;16m'],   // #000000
  resColorsMap.brown:  ['\x1b[38;5;95m', '\x1b[48;5;95m'],   // #A0522D
  resColorsMap.red:    ['\x1b[38;5;1m', '\x1b[48;5;1m'],     // #FF0000
  resColorsMap.orange: ['\x1b[38;5;166m', '\x1b[48;5;166m'], // #FF8C00
  resColorsMap.yellow: ['\x1b[38;5;11m', '\x1b[48;5;11m'],   // #FFD700
  resColorsMap.green:  ['\x1b[38;5;2m', '\x1b[48;5;2m'],     // #008000
  resColorsMap.blue:   ['\x1b[38;5;20m', '\x1b[48;5;20m'],   // #0000CD
  resColorsMap.purple: ['\x1b[38;5;54m', '\x1b[48;5;54m'],   // #800080
  resColorsMap.gray:   ['\x1b[38;5;59m', '\x1b[48;5;59m'],   // #808080
  resColorsMap.white:  ['\x1b[38;5;255m', '\x1b[48;5;255m'], // #F8F8FF
};
// quick helper fcn to get a corresponding ansi color from hex one, or none if not found
function termColor(hexColor){
  Object.keys( termColorsMap ).forEach(function(index){
    if(hexColor === index) return index
  })
  return ''
}

/* R: I have to find a way to deduce available(s)/nearest corresponding colors */
//visually listing the above colors
Object.keys( resColorsMap ).forEach(function(index){
  console.log('index: ' + index + '\t' + resColorsMap[index] + '\t%c⬛⬛⬛⬛⬛⬛', 'color: ' + resColorsMap[index] + ';')
})
// getting the foreground colors available in my term'
for code in {0..255}; do echo -e "\e[38;5;${code}m"'\\e[38;5;'"$code"m"\e[0m"; done
// getting thr abckground colors available in my term'
for code in {0..255}; do echo -e "\e[48;5;${code}m"'\\e[48;5;'"$code"m"\e[0m"; done
<|endoftext|>


<commit_before>// pages/QrCode/QrCode.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    qrCodeImg:'',
    codeType:'1',
    sceneCode:null
  },

  /* 预览图片 */
  viewQrCode:function (e) {
      console.log('注意：base64编码的图片无法使用预览，必须使用文件地址');
      var src = e.currentTarget.dataset.src;//获取data-src  循环单个图片链接
      var imgList = [];
      imgList.push(src);
      wx.previewImage({
        current: src, // 当前显示图片的http链接
        urls: imgList // 需要预览的图片http链接列表
      })
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (query) {
    var that = this;

    if (query.codeType) {
      that.setData({
        codeType: query.codeType
      });
    }

    // scene 需要使用 decodeURIComponent 才能获取到生成二维码时传入的 scene
    if (query.scene)
    {
      const scene = decodeURIComponent(query.scene);
      var sceneData = scene.split('#');
      var sceneCode = sceneData[0];
      var sceneCodeType = sceneData[1];
      that.setData({
        sceneCode: sceneCode
      });
      that.setData({
        codeType: sceneCodeType
      });
    }

    console.log('codeType', query.codeType);

    //使用图片文件流直接加载图片
    that.setData({
      qrCodeImg: wx.getStorageSync('domainName')
                  + '/WxOpen/GetQrCode?sessionId=' + wx.getStorageSync('sessionId')
        + '&codeType=' + that.data.codeType
    });

    //使用 base64 方式加载图片
    // wx.request({
    //   url: wx.getStorageSync('domainName') + '/WxOpen/GetQrCode?useBase64=1',
    //   data: {
    //     sessionId:,
    //   },
    //   method: 'POST',
    //   header: { 'content-type': 'application/x-www-form-urlencoded' },
    //   success: function (res) {
    //     if (res.data.success===false) {
    //       wx.showModal({
    //         title: '获取二维码失败',
    //         content: res.data.msg,
    //         showCancel: false
    //       });

    //     } else {
    //       console.log('获取二维码成功：' + res.data.msg);
    //       that.setData({
    //         qrCodeImg: 'data:image/jpeg;base64,' + res.data.msg,  // data 为接口返回的base64字符串
    //       });
    //       console.log(that.data.qrCodeImg);
    //     }
    //   }
    // });
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {

  }
})<commit_msg>修改小程序js代码<commit_after>// pages/QrCode/QrCode.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    qrCodeImg: '',
    codeType: '1',
    sceneCode: null
  },

  /* 预览图片 */
  viewQrCode: function(e) {
    console.log('注意：base64编码的图片无法使用预览，必须使用文件地址');
    var src = e.currentTarget.dataset.src; //获取data-src  循环单个图片链接
    var imgList = [];
    imgList.push(src);
    wx.previewImage({
      current: src, // 当前显示图片的http链接
      urls: imgList // 需要预览的图片http链接列表
    })
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(query) {
    var that = this;

    if (query.codeType) {
      that.setData({
        codeType: query.codeType
      });
    }

    // scene 需要使用 decodeURIComponent 才能获取到生成二维码时传入的 scene
    if (query.scene) {
      const scene = decodeURIComponent(query.scene);
      var sceneData = scene.split('#');
      var sceneCode = sceneData[0];
      var sceneCodeType = sceneData[1];
      that.setData({
        sceneCode: sceneCode
      });
      that.setData({
        codeType: sceneCodeType
      });
    }

    console.log('codeType', query.codeType);

    //使用图片文件流直接加载图片
    that.setData({
      qrCodeImg: wx.getStorageSync('domainName') +
        '/WxOpen/GetQrCode?sessionId=' + wx.getStorageSync('sessionId') +
        '&codeType=' + that.data.codeType
    });

    //使用 base64 方式加载图片
    // wx.request({
    //   url: wx.getStorageSync('domainName') + '/WxOpen/GetQrCode?useBase64=1',
    //   data: {
    //     sessionId:,
    //   },
    //   method: 'POST',
    //   header: { 'content-type': 'application/x-www-form-urlencoded' },
    //   success: function (res) {
    //     if (res.data.success===false) {
    //       wx.showModal({
    //         title: '获取二维码失败',
    //         content: res.data.msg,
    //         showCancel: false
    //       });

    //     } else {
    //       console.log('获取二维码成功：' + res.data.msg);
    //       that.setData({
    //         qrCodeImg: 'data:image/jpeg;base64,' + res.data.msg,  // data 为接口返回的base64字符串
    //       });
    //       console.log(that.data.qrCodeImg);
    //     }
    //   }
    // });
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function() {

  }
})<|endoftext|>