<commit_before>/**
 * @license
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * JSONUtil -- Provides JSON++ marshalling support.
 *
 * Like regular JSON, with the following differences:
 *  1. Marshalls to/from FOAM Objects, rather than maps.
 *  2. Object Model information is encoded as 'model: "ModelName"'
 *  3. Default Values are not marshalled, saving disk space and network bandwidth.
 *  4. Support for marshalling functions.
 *  5. Support for property filtering, ie. only output non-transient properties.
 *  6. Support for 'pretty' and 'compact' modes.
 *
 *  TODO:
 *    Replace with JSONParser.js, when finished.
 *    Maybe rename to FON (FOAM Object Notation, pronounced 'phone') to avoid
 *    confusion with regular JSON syntax.
 **/

var AbstractFormatter = {
  keyify: function(str) { return '"' + str + '"'; },

  stringify: function(obj) {
    var buf = '';

    this.output(function() {
      for (var i = 0; i < arguments.length; i++)
        buf += arguments[i];
    }, obj);

    return buf;
  },

  stringifyObject: function(obj, opt_defaultModel) {
    var buf = '';

    this.outputObject_(function() {
      for (var i = 0; i < arguments.length; i++)
        buf += arguments[i];
    }, obj, opt_defaultModel);

    return buf;
  },

  /** @param p a predicate function or an mLang **/
  where: function(p) {
    return {
      __proto__: this,
      p: ( p.f && p.f.bind(p) ) || p
    };
  },

  p: function() { return true; }
};

var JSONUtil = {

  escape: function(str) {
    return str
      .replace(/\\/g, '\\\\')
      .replace(/"/g, '\\"')
      .replace(/[\x00-\x1f]/g, function(c) {
        return "\\u00" + ((c.charCodeAt(0) < 0x10) ?
                          '0' + c.charCodeAt(0).toString(16) :
                          c.charCodeAt(0).toString(16));
      });
  },

  parseToMap: function(str) {
    return eval('(' + str + ')');
  },

  parse: function(X, str, seq) {
    return this.mapToObj(X, this.parseToMap(str), undefined, seq);
  },

  arrayToObjArray: function(X, a, opt_defaultModel, seq) {
    for ( var i = 0 ; i < a.length ; i++ ) {
      a[i] = this.mapToObj(X, a[i], opt_defaultModel, seq);
    }
    return a;
  },

  /**
   * Convert JS-Maps which contain the 'model_' property, into
   * instances of that model.
   **/
  mapToObj: function(X, obj, opt_defaultModel, seq) {
    if ( ! obj || typeof obj.model_ === 'object' ) return obj;

    if ( Array.isArray(obj) ) return this.arrayToObjArray(X, obj, undefined, seq);

    if ( obj instanceof Function ) return obj;

    if ( obj instanceof Date ) return obj;

    if ( obj instanceof Object ) {
      var j = 0;
      for ( var key in obj ) {
        if ( key != 'model_' && key != 'prototype_' ) obj[key] = this.mapToObj(X, obj[key], null, seq);
        j++;
      }
/*      var keys = Object.keys(obj);
      for ( var j = 0, key; key = keys[j]; j++ ) {
        if ( key != 'model_' && key != 'prototype_' ) obj[key] = this.mapToObj(obj[key]);
      }
      */

      if ( opt_defaultModel && ! obj.model_ ) return opt_defaultModel.create(obj);

      if ( obj.model_ ) {
        var newObj = X.lookup(obj.model_);
        if ( ( ! newObj || ! newObj.finished__ ) ) {
          var future = afuture();
          seq && seq.push(future.get);

          arequire(obj.model_)(function(model) {
            if ( ! model ) {
               if ( DEBUG && obj.model_ !== 'Template' && obj.model_ !== 'ArrayProperty' && obj.model_ !== 'ViewFactoryProperty' && obj.model_ !== 'Documentation' && obj.model_ !== 'DocumentationProperty' && obj.model_ !== 'CSSProperty' && obj.model_ !== 'FunctionProperty' )
                 console.warn('Failed to dynamically load: ', obj.model_);
              future.set(obj);
              return;
            }
            var tmp = model.create(obj);
            obj.become(tmp);
            future.set(obj);
          });

          return obj;
        }
        return newObj ? newObj.create(obj, X) : obj;
      }
      return obj
    }

    return obj;
  },

  compact: {
    __proto__: AbstractFormatter,

    output: function(out, obj) {
      if ( Array.isArray(obj) ) {
        this.outputArray_(out, obj);
      }
      else if ( typeof obj === 'string' ) {
        out('"');
        out(JSONUtil.escape(obj));
        out('"');
      }
      else if ( obj instanceof Function ) {
        this.outputFunction_(out, obj);
      }
      else if ( obj instanceof Date ) {
        out(obj.getTime());
      }
      else if ( obj instanceof Object ) {
        if ( obj.model_ )
          this.outputObject_(out, obj);
        else
          this.outputMap_(out, obj);
      }
      else if ( typeof obj === 'number' ) {
        if ( ! isFinite(obj) ) obj = null;
        out(obj);
      }
      else {
        if ( obj === undefined ) obj = null;
        out(obj);
      }
    },

    outputObject_: function(out, obj, opt_defaultModel) {
      var str   = '';
      var first = true;

      out('{');
      if ( obj.model_.id !== opt_defaultModel ) {
        this.outputModel_(out, obj);
        first = false;
     }

      var properties = obj.model_.getRuntimeProperties();
      for ( var key in properties ) {
        var prop = properties[key];

        if ( ! this.p(prop) ) continue;

        if ( prop.name in obj.instance_ ) {
          var val = obj[prop.name];
          if ( Array.isArray(val) && ! val.length ) continue;
          if ( ! first ) out(',');
          out(this.keyify(prop.name), ': ');
          if ( Array.isArray(val) && prop.subType ) {
            this.outputArray_(out, val, prop.subType);
          } else {
            this.output(out, val);
          }
          first = false;
        }
      }

      out('}');
    },

    outputModel_: function(out, obj) {
      out('model_:"')
      if ( obj.model_.package ) out(obj.model_.package, '.')
      out(obj.model_.name, '"');
    },

    outputMap_: function(out, obj) {
      var str   = '';
      var first = true;

      out('{');

      for ( var key in obj ) {
        var val = obj[key];

        if ( ! first ) out(',');
        out(this.keyify(key), ': ');
        this.output(out, val);

        first = false;
      }

      out('}');
    },

    outputArray_: function(out, a, opt_defaultModel) {
      if ( a.length == 0 ) { out('[]'); return out; }

      var str   = '';
      var first = true;

      out('[');

      for ( var i = 0 ; i < a.length ; i++, first = false ) {
        var obj = a[i];

        if ( ! first ) out(',');

        if ( typeof obj === 'string' || typeof obj === 'number' ) {
          this.output(out, obj);
        } else if ( Array.isArray(obj) ) {
          this.outputArray_(out, obj);
        } else {
          if ( obj.model_ )
            this.outputObject_(out, obj, opt_defaultModel);
          else
            this.outputMap_(out, obj);
        }
      }

      out(']');
    },

    outputFunction_: function(out, obj) { out(obj); }
  },

  pretty: {
    __proto__: AbstractFormatter,

    output: function(out, obj, opt_indent) {
      var indent = opt_indent || '';

      if ( Array.isArray(obj) ) {
        this.outputArray_(out, obj, null, indent);
      }
      else if ( typeof obj == 'string' ) {
        out('"');
        out(JSONUtil.escape(obj));
        out('"');
      }
      else if ( obj instanceof Function ) {
        this.outputFunction_(out, obj, indent);
      }
      else if ( obj instanceof Date ) {
        out("new Date('", obj, "')");
      }
      else if ( obj instanceof Object ) {
        if ( obj.model_ )
          this.outputObject_(out, obj, null, indent);
        else
          this.outputMap_(out, obj, indent);
      } else if ( typeof obj === 'number' ) {
        if ( ! isFinite(obj) ) obj = null;
        out(obj);
      } else {
        if ( obj === undefined ) obj = null;
        out(obj);
      }
    },

    outputObject_: function(out, obj, opt_defaultModel, opt_indent) {
      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out(/*"\n", */indent, '{\n');
      if ( obj.model_.id && obj.model_.id !== opt_defaultModel ) {
        this.outputModel_(out, obj, nestedIndent);
        first = false;
      }

      var properties = obj.model_.getRuntimeProperties();
      for ( var key in properties ) {
        var prop = properties[key];

        if ( ! this.p(prop) ) continue;

        if ( prop.name === 'parent' ) continue;
        if ( prop.name in obj.instance_ ) {
          var val = obj[prop.name];
          if ( Array.isArray(val) && ! val.length ) continue;
          if ( ! first ) out(',\n');
          out(nestedIndent, this.keyify(prop.name), ': ');
          if ( Array.isArray(val) && prop.subType ) {
            this.outputArray_(out, val, prop.subType, nestedIndent);
          } else {
            this.output(out, val, nestedIndent);
          }
          first = false;
        }
      }

      out('\n', indent, '}');
    },

    outputModel_: function(out, obj, indent) {
      out(indent, '"model_": "', obj.model_.id, '"');
    },

    outputMap_: function(out, obj, opt_indent) {
      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out(/*"\n",*/ indent, '{\n', nestedIndent);

      for ( var key in obj ) {
        var val = obj[key];

        if ( ! first ) out(',\n');
        out(nestedIndent, this.keyify(key), ': ');
        this.output(out, val, nestedIndent);

        first = false;
      }

      out('\n', indent, '}');
    },

    outputArray_: function(out, a, opt_defaultModel, opt_indent) {
      if ( a.length == 0 ) { out('[]'); return out; }

      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out('[\n');

      for ( var i = 0 ; i < a.length ; i++, first = false ) {
        var obj = a[i];

        if ( ! first ) out(',\n');

        if ( typeof obj === 'string' || typeof obj === 'number' ) {
          out(nestedIndent);
          this.output(out, obj, nestedIndent);
        } else {
          if ( obj.model_ )
            this.outputObject_(out, obj, opt_defaultModel, nestedIndent);
          else if ( Array.isArray(obj) )
            this.outputArray_(out, obj, undefined, nestedIndent);
          else
            this.outputMap_(out, obj, nestedIndent);
        }
      }

      out('\n', indent, ']');
    },

    outputFunction_: function(out, obj, indent) {
      var str = obj.toString();
      var lines = str.split('\n');

      if ( lines.length == 1 ) { out(str); return; }

      var minIndent = 10000;
      for ( var i = 0 ; i < lines.length ; i++ ) {
        var j = 0;
        for ( ; j < lines[i].length && lines[i].charAt(j) === ' ' && j < minIndent ; j++ );
        if ( j > 0 && j < minIndent ) minIndent = j;
      }

      if ( minIndent === 10000 ) { out(str); return; }

      for ( var i = 0 ; i < lines.length ; i++ ) {
        if ( lines[i].length && lines[i].charAt(0) === ' ' ) {
          lines[i] = indent + lines[i].substring(minIndent);
        }
        out(lines[i]);
        if ( i < lines.length-1 ) out('\n');
      }
    }
  },

  moreCompact: {
    __proto__: AbstractFormatter,
    // TODO: use short-names
  },

  compressed: {
    __proto__: AbstractFormatter,

    stringify: function(obj) {
      return Iuppiter.Base64.encode(Iuppiter.compress(JSONUtil.compact.stringify(obj),true));
    }
  }

};

JSONUtil.prettyModel = {
  __proto__: JSONUtil.pretty,

  outputModel_: function(out, obj, indent) {
    out(indent, 'model_: "', obj.model_.id, '"');
  },

  keys_: {},

  keyify: function(str) {
    if ( ! this.keys_.hasOwnProperty(str) ) {
      this.keys_[str] =
        /^[a-zA-Z\$_][0-9a-zA-Z$_]*$/.test(str) ?
        str :
        '"' + str + '"';
    }

    return this.keys_[str];
  }
};

JSONUtil.stringify       = JSONUtil.pretty.stringify.bind(JSONUtil.pretty);
JSONUtil.stringifyObject = JSONUtil.pretty.stringifyObject.bind(JSONUtil.pretty);
JSONUtil.output          = JSONUtil.pretty.output.bind(JSONUtil.pretty);;
JSONUtil.where           = JSONUtil.pretty.where.bind(JSONUtil.pretty);;

var NOT_TRANSIENT = function(prop) { return ! prop.transient; };
<commit_msg>Removed commented out code.<commit_after>/**
 * @license
 * Copyright 2012 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * JSONUtil -- Provides JSON++ marshalling support.
 *
 * Like regular JSON, with the following differences:
 *  1. Marshalls to/from FOAM Objects, rather than maps.
 *  2. Object Model information is encoded as 'model: "ModelName"'
 *  3. Default Values are not marshalled, saving disk space and network bandwidth.
 *  4. Support for marshalling functions.
 *  5. Support for property filtering, ie. only output non-transient properties.
 *  6. Support for 'pretty' and 'compact' modes.
 *
 *  TODO:
 *    Replace with JSONParser.js, when finished.
 *    Maybe rename to FON (FOAM Object Notation, pronounced 'phone') to avoid
 *    confusion with regular JSON syntax.
 **/

var AbstractFormatter = {
  keyify: function(str) { return '"' + str + '"'; },

  stringify: function(obj) {
    var buf = '';

    this.output(function() {
      for (var i = 0; i < arguments.length; i++)
        buf += arguments[i];
    }, obj);

    return buf;
  },

  stringifyObject: function(obj, opt_defaultModel) {
    var buf = '';

    this.outputObject_(function() {
      for (var i = 0; i < arguments.length; i++)
        buf += arguments[i];
    }, obj, opt_defaultModel);

    return buf;
  },

  /** @param p a predicate function or an mLang **/
  where: function(p) {
    return {
      __proto__: this,
      p: ( p.f && p.f.bind(p) ) || p
    };
  },

  p: function() { return true; }
};

var JSONUtil = {

  escape: function(str) {
    return str
      .replace(/\\/g, '\\\\')
      .replace(/"/g, '\\"')
      .replace(/[\x00-\x1f]/g, function(c) {
        return "\\u00" + ((c.charCodeAt(0) < 0x10) ?
                          '0' + c.charCodeAt(0).toString(16) :
                          c.charCodeAt(0).toString(16));
      });
  },

  parseToMap: function(str) {
    return eval('(' + str + ')');
  },

  parse: function(X, str, seq) {
    return this.mapToObj(X, this.parseToMap(str), undefined, seq);
  },

  arrayToObjArray: function(X, a, opt_defaultModel, seq) {
    for ( var i = 0 ; i < a.length ; i++ ) {
      a[i] = this.mapToObj(X, a[i], opt_defaultModel, seq);
    }
    return a;
  },

  /**
   * Convert JS-Maps which contain the 'model_' property, into
   * instances of that model.
   **/
  mapToObj: function(X, obj, opt_defaultModel, seq) {
    if ( ! obj || typeof obj.model_ === 'object' ) return obj;

    if ( Array.isArray(obj) ) return this.arrayToObjArray(X, obj, undefined, seq);

    if ( obj instanceof Function ) return obj;

    if ( obj instanceof Date ) return obj;

    if ( obj instanceof Object ) {
      var j = 0;
      for ( var key in obj ) {
        if ( key != 'model_' && key != 'prototype_' ) obj[key] = this.mapToObj(X, obj[key], null, seq);
        j++;
      }

      if ( opt_defaultModel && ! obj.model_ ) return opt_defaultModel.create(obj);

      if ( obj.model_ ) {
        var newObj = X.lookup(obj.model_);
        if ( ( ! newObj || ! newObj.finished__ ) ) {
          var future = afuture();
          seq && seq.push(future.get);

          arequire(obj.model_)(function(model) {
            if ( ! model ) {
               if ( DEBUG && obj.model_ !== 'Template' && obj.model_ !== 'ArrayProperty' && obj.model_ !== 'ViewFactoryProperty' && obj.model_ !== 'Documentation' && obj.model_ !== 'DocumentationProperty' && obj.model_ !== 'CSSProperty' && obj.model_ !== 'FunctionProperty' )
                 console.warn('Failed to dynamically load: ', obj.model_);
              future.set(obj);
              return;
            }
            var tmp = model.create(obj);
            obj.become(tmp);
            future.set(obj);
          });

          return obj;
        }
        return newObj ? newObj.create(obj, X) : obj;
      }
      return obj
    }

    return obj;
  },

  compact: {
    __proto__: AbstractFormatter,

    output: function(out, obj) {
      if ( Array.isArray(obj) ) {
        this.outputArray_(out, obj);
      }
      else if ( typeof obj === 'string' ) {
        out('"');
        out(JSONUtil.escape(obj));
        out('"');
      }
      else if ( obj instanceof Function ) {
        this.outputFunction_(out, obj);
      }
      else if ( obj instanceof Date ) {
        out(obj.getTime());
      }
      else if ( obj instanceof Object ) {
        if ( obj.model_ )
          this.outputObject_(out, obj);
        else
          this.outputMap_(out, obj);
      }
      else if ( typeof obj === 'number' ) {
        if ( ! isFinite(obj) ) obj = null;
        out(obj);
      }
      else {
        if ( obj === undefined ) obj = null;
        out(obj);
      }
    },

    outputObject_: function(out, obj, opt_defaultModel) {
      var str   = '';
      var first = true;

      out('{');
      if ( obj.model_.id !== opt_defaultModel ) {
        this.outputModel_(out, obj);
        first = false;
     }

      var properties = obj.model_.getRuntimeProperties();
      for ( var key in properties ) {
        var prop = properties[key];

        if ( ! this.p(prop) ) continue;

        if ( prop.name in obj.instance_ ) {
          var val = obj[prop.name];
          if ( Array.isArray(val) && ! val.length ) continue;
          if ( ! first ) out(',');
          out(this.keyify(prop.name), ': ');
          if ( Array.isArray(val) && prop.subType ) {
            this.outputArray_(out, val, prop.subType);
          } else {
            this.output(out, val);
          }
          first = false;
        }
      }

      out('}');
    },

    outputModel_: function(out, obj) {
      out('model_:"')
      if ( obj.model_.package ) out(obj.model_.package, '.')
      out(obj.model_.name, '"');
    },

    outputMap_: function(out, obj) {
      var str   = '';
      var first = true;

      out('{');

      for ( var key in obj ) {
        var val = obj[key];

        if ( ! first ) out(',');
        out(this.keyify(key), ': ');
        this.output(out, val);

        first = false;
      }

      out('}');
    },

    outputArray_: function(out, a, opt_defaultModel) {
      if ( a.length == 0 ) { out('[]'); return out; }

      var str   = '';
      var first = true;

      out('[');

      for ( var i = 0 ; i < a.length ; i++, first = false ) {
        var obj = a[i];

        if ( ! first ) out(',');

        if ( typeof obj === 'string' || typeof obj === 'number' ) {
          this.output(out, obj);
        } else if ( Array.isArray(obj) ) {
          this.outputArray_(out, obj);
        } else {
          if ( obj.model_ )
            this.outputObject_(out, obj, opt_defaultModel);
          else
            this.outputMap_(out, obj);
        }
      }

      out(']');
    },

    outputFunction_: function(out, obj) { out(obj); }
  },

  pretty: {
    __proto__: AbstractFormatter,

    output: function(out, obj, opt_indent) {
      var indent = opt_indent || '';

      if ( Array.isArray(obj) ) {
        this.outputArray_(out, obj, null, indent);
      }
      else if ( typeof obj == 'string' ) {
        out('"');
        out(JSONUtil.escape(obj));
        out('"');
      }
      else if ( obj instanceof Function ) {
        this.outputFunction_(out, obj, indent);
      }
      else if ( obj instanceof Date ) {
        out("new Date('", obj, "')");
      }
      else if ( obj instanceof Object ) {
        if ( obj.model_ )
          this.outputObject_(out, obj, null, indent);
        else
          this.outputMap_(out, obj, indent);
      } else if ( typeof obj === 'number' ) {
        if ( ! isFinite(obj) ) obj = null;
        out(obj);
      } else {
        if ( obj === undefined ) obj = null;
        out(obj);
      }
    },

    outputObject_: function(out, obj, opt_defaultModel, opt_indent) {
      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out(/*"\n", */indent, '{\n');
      if ( obj.model_.id && obj.model_.id !== opt_defaultModel ) {
        this.outputModel_(out, obj, nestedIndent);
        first = false;
      }

      var properties = obj.model_.getRuntimeProperties();
      for ( var key in properties ) {
        var prop = properties[key];

        if ( ! this.p(prop) ) continue;

        if ( prop.name === 'parent' ) continue;
        if ( prop.name in obj.instance_ ) {
          var val = obj[prop.name];
          if ( Array.isArray(val) && ! val.length ) continue;
          if ( ! first ) out(',\n');
          out(nestedIndent, this.keyify(prop.name), ': ');
          if ( Array.isArray(val) && prop.subType ) {
            this.outputArray_(out, val, prop.subType, nestedIndent);
          } else {
            this.output(out, val, nestedIndent);
          }
          first = false;
        }
      }

      out('\n', indent, '}');
    },

    outputModel_: function(out, obj, indent) {
      out(indent, '"model_": "', obj.model_.id, '"');
    },

    outputMap_: function(out, obj, opt_indent) {
      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out(/*"\n",*/ indent, '{\n', nestedIndent);

      for ( var key in obj ) {
        var val = obj[key];

        if ( ! first ) out(',\n');
        out(nestedIndent, this.keyify(key), ': ');
        this.output(out, val, nestedIndent);

        first = false;
      }

      out('\n', indent, '}');
    },

    outputArray_: function(out, a, opt_defaultModel, opt_indent) {
      if ( a.length == 0 ) { out('[]'); return out; }

      var indent       = opt_indent || '';
      var nestedIndent = indent + '   ';
      var str          = '';
      var first        = true;

      out('[\n');

      for ( var i = 0 ; i < a.length ; i++, first = false ) {
        var obj = a[i];

        if ( ! first ) out(',\n');

        if ( typeof obj === 'string' || typeof obj === 'number' ) {
          out(nestedIndent);
          this.output(out, obj, nestedIndent);
        } else {
          if ( obj.model_ )
            this.outputObject_(out, obj, opt_defaultModel, nestedIndent);
          else if ( Array.isArray(obj) )
            this.outputArray_(out, obj, undefined, nestedIndent);
          else
            this.outputMap_(out, obj, nestedIndent);
        }
      }

      out('\n', indent, ']');
    },

    outputFunction_: function(out, obj, indent) {
      var str = obj.toString();
      var lines = str.split('\n');

      if ( lines.length == 1 ) { out(str); return; }

      var minIndent = 10000;
      for ( var i = 0 ; i < lines.length ; i++ ) {
        var j = 0;
        for ( ; j < lines[i].length && lines[i].charAt(j) === ' ' && j < minIndent ; j++ );
        if ( j > 0 && j < minIndent ) minIndent = j;
      }

      if ( minIndent === 10000 ) { out(str); return; }

      for ( var i = 0 ; i < lines.length ; i++ ) {
        if ( lines[i].length && lines[i].charAt(0) === ' ' ) {
          lines[i] = indent + lines[i].substring(minIndent);
        }
        out(lines[i]);
        if ( i < lines.length-1 ) out('\n');
      }
    }
  },

  moreCompact: {
    __proto__: AbstractFormatter,
    // TODO: use short-names
  },

  compressed: {
    __proto__: AbstractFormatter,

    stringify: function(obj) {
      return Iuppiter.Base64.encode(Iuppiter.compress(JSONUtil.compact.stringify(obj),true));
    }
  }

};

JSONUtil.prettyModel = {
  __proto__: JSONUtil.pretty,

  outputModel_: function(out, obj, indent) {
    out(indent, 'model_: "', obj.model_.id, '"');
  },

  keys_: {},

  keyify: function(str) {
    if ( ! this.keys_.hasOwnProperty(str) ) {
      this.keys_[str] =
        /^[a-zA-Z\$_][0-9a-zA-Z$_]*$/.test(str) ?
        str :
        '"' + str + '"';
    }

    return this.keys_[str];
  }
};

JSONUtil.stringify       = JSONUtil.pretty.stringify.bind(JSONUtil.pretty);
JSONUtil.stringifyObject = JSONUtil.pretty.stringifyObject.bind(JSONUtil.pretty);
JSONUtil.output          = JSONUtil.pretty.output.bind(JSONUtil.pretty);;
JSONUtil.where           = JSONUtil.pretty.where.bind(JSONUtil.pretty);;

var NOT_TRANSIENT = function(prop) { return ! prop.transient; };
<|endoftext|>


<commit_before>/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import styled from 'styled-components';
import { useLayoutEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { rgba } from 'polished';

/**
 * Internal dependencies
 */
import { ArrowDown } from '../../../../button/index';
import CategoryPill from './categoryPill';

// Pills have a margin of 4, so the l/r padding is 24-4=20.
const CategorySection = styled.div`
  background-color: ${({ theme }) => rgba(theme.colors.bg.workspace, 0.8)};
  min-height: 94px;
  padding: 16px 32px 30px 32px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  flex: 1 0 auto;
  position: relative;
`;

// This hides the category pills unless expanded
const CategoryPillContainer = styled.div`
  height: 36px;
  overflow: hidden;
  transition: height 0.2s;
`;

const CategoryPillInnerContainer = styled.div`
  display: flex;
  flex-wrap: wrap;
`;

// Flips the button upside down when expanded;
// Important: the visibily is 'inherit' when props.visible because otherwise
// it gets shown even when the provider is not the selectedProvider!
const ExpandButton = styled(ArrowDown)`
  display: flex;
  position: absolute;
  bottom: -12px;
  background: ${({ theme }) => theme.colors.fg.gray16};
  max-height: none;
  width: 32px;
  height: 32px;
  border-radius: 16px;
  ${({ isExpanded }) => isExpanded && 'transform: matrix(1, 0, 0, -1, 0, 0);'}
  visibility: ${({ visible }) => (visible ? 'inherit' : 'hidden')};
  align-self: center;
  justify-content: center;
  align-items: center;
`;

const Media3pCategories = ({
  categories,
  selectedCategoryId,
  selectCategory,
  deselectCategory,
}) => {
  const [isExpanded, setIsExpanded] = useState(false);

  function renderCategories() {
    return (selectedCategoryId
      ? [categories.find((e) => e.id === selectedCategoryId)]
      : categories
    ).map((e, i) => {
      const selected = e.id === selectedCategoryId;
      return (
        <CategoryPill
          index={i}
          isSelected={selected}
          key={e.id}
          title={e.displayName}
          onClick={() => {
            if (selected) {
              deselectCategory();
            } else {
              setIsExpanded(false);
              selectCategory(e.id);
            }
          }}
        />
      );
    });
  }

  const containerRef = useRef();
  const innerContainerRef = useRef();

  // We calculate the actual height of the categories list, and set its explicit
  // height if it's expanded, in order to have a CSS height transition.
  useLayoutEffect(() => {
    if (!containerRef.current || !innerContainerRef.current) {
      return;
    }
    if (!isExpanded) {
      containerRef.current.style.height = '36px';
    } else {
      containerRef.current.style.height = `${innerContainerRef.current.offsetHeight}px`;
    }
  }, [containerRef, innerContainerRef, isExpanded]);

  return (
    <CategorySection hasCategories={Boolean(categories.length)}>
      {categories.length ? (
        <>
          <CategoryPillContainer
            id="category-pill-container"
            ref={containerRef}
            isExpanded={isExpanded}
            role="tablist"
          >
            <CategoryPillInnerContainer ref={innerContainerRef}>
              {renderCategories()}
            </CategoryPillInnerContainer>
          </CategoryPillContainer>
          <ExpandButton
            data-testid="category-expand-button"
            onClick={() => setIsExpanded(!isExpanded)}
            visible={!selectedCategoryId}
            isExpanded={isExpanded}
            aria-controls="category-pill-container"
            aria-expanded={isExpanded}
          />
        </>
      ) : null}
    </CategorySection>
  );
};

Media3pCategories.propTypes = {
  categories: PropTypes.array.isRequired,
  selectedCategoryId: PropTypes.string,
  selectCategory: PropTypes.func,
  deselectCategory: PropTypes.func,
};

export default Media3pCategories;
<commit_msg>Fixed import path<commit_after>/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import styled from 'styled-components';
import { useLayoutEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { rgba } from 'polished';

/**
 * Internal dependencies
 */
import { ArrowDown } from '../../../../button';
import CategoryPill from './categoryPill';

// Pills have a margin of 4, so the l/r padding is 24-4=20.
const CategorySection = styled.div`
  background-color: ${({ theme }) => rgba(theme.colors.bg.workspace, 0.8)};
  min-height: 94px;
  padding: 16px 32px 30px 32px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  flex: 1 0 auto;
  position: relative;
`;

// This hides the category pills unless expanded
const CategoryPillContainer = styled.div`
  height: 36px;
  overflow: hidden;
  transition: height 0.2s;
`;

const CategoryPillInnerContainer = styled.div`
  display: flex;
  flex-wrap: wrap;
`;

// Flips the button upside down when expanded;
// Important: the visibily is 'inherit' when props.visible because otherwise
// it gets shown even when the provider is not the selectedProvider!
const ExpandButton = styled(ArrowDown)`
  display: flex;
  position: absolute;
  bottom: -12px;
  background: ${({ theme }) => theme.colors.fg.gray16};
  max-height: none;
  width: 32px;
  height: 32px;
  border-radius: 16px;
  ${({ isExpanded }) => isExpanded && 'transform: matrix(1, 0, 0, -1, 0, 0);'}
  visibility: ${({ visible }) => (visible ? 'inherit' : 'hidden')};
  align-self: center;
  justify-content: center;
  align-items: center;
`;

const Media3pCategories = ({
  categories,
  selectedCategoryId,
  selectCategory,
  deselectCategory,
}) => {
  const [isExpanded, setIsExpanded] = useState(false);

  function renderCategories() {
    return (selectedCategoryId
      ? [categories.find((e) => e.id === selectedCategoryId)]
      : categories
    ).map((e, i) => {
      const selected = e.id === selectedCategoryId;
      return (
        <CategoryPill
          index={i}
          isSelected={selected}
          key={e.id}
          title={e.displayName}
          onClick={() => {
            if (selected) {
              deselectCategory();
            } else {
              setIsExpanded(false);
              selectCategory(e.id);
            }
          }}
        />
      );
    });
  }

  const containerRef = useRef();
  const innerContainerRef = useRef();

  // We calculate the actual height of the categories list, and set its explicit
  // height if it's expanded, in order to have a CSS height transition.
  useLayoutEffect(() => {
    if (!containerRef.current || !innerContainerRef.current) {
      return;
    }
    if (!isExpanded) {
      containerRef.current.style.height = '36px';
    } else {
      containerRef.current.style.height = `${innerContainerRef.current.offsetHeight}px`;
    }
  }, [containerRef, innerContainerRef, isExpanded]);

  return (
    <CategorySection hasCategories={Boolean(categories.length)}>
      {categories.length ? (
        <>
          <CategoryPillContainer
            id="category-pill-container"
            ref={containerRef}
            isExpanded={isExpanded}
            role="tablist"
          >
            <CategoryPillInnerContainer ref={innerContainerRef}>
              {renderCategories()}
            </CategoryPillInnerContainer>
          </CategoryPillContainer>
          <ExpandButton
            data-testid="category-expand-button"
            onClick={() => setIsExpanded(!isExpanded)}
            visible={!selectedCategoryId}
            isExpanded={isExpanded}
            aria-controls="category-pill-container"
            aria-expanded={isExpanded}
          />
        </>
      ) : null}
    </CategorySection>
  );
};

Media3pCategories.propTypes = {
  categories: PropTypes.array.isRequired,
  selectedCategoryId: PropTypes.string,
  selectCategory: PropTypes.func,
  deselectCategory: PropTypes.func,
};

export default Media3pCategories;
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2014, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

var s = require('underscore.string');

/**
 * Get a function that deserializes a specific type of protobuf.
 * @param {function()} cls The constructor of the message type to deserialize
 * @return {function(Buffer):cls} The deserialization function
 */
function deserializeCls(cls) {
  /**
   * Deserialize a buffer to a message object
   * @param {Buffer} arg_buf The buffer to deserialize
   * @return {cls} The resulting object
   */
  return function deserialize(arg_buf) {
    return cls.decode(arg_buf);
  };
}

/**
 * Get a function that serializes objects to a buffer by protobuf class.
 * @param {function()} Cls The constructor of the message type to serialize
 * @return {function(Cls):Buffer} The serialization function
 */
function serializeCls(Cls) {
  /**
   * Serialize an object to a Buffer
   * @param {Object} arg The object to serialize
   * @return {Buffer} The serialized object
   */
  return function serialize(arg) {
    return new Buffer(new Cls(arg).encode().toBuffer());
  };
}

/**
 * Get the fully qualified (dotted) name of a ProtoBuf.Reflect value.
 * @param {ProtoBuf.Reflect.Namespace} value The value to get the name of
 * @return {string} The fully qualified name of the value
 */
function fullyQualifiedName(value) {
  if (value === null || value === undefined) {
    return '';
  }
  var name = value.name;
  if (value.className === 'Service.RPCMethod') {
    name = s(name).capitalize().value();
  }
  if (value.hasOwnProperty('parent')) {
    var parent_name = fullyQualifiedName(value.parent);
    if (parent_name !== '') {
      name = parent_name + '.' + name;
    }
  }
  return name;
}

/**
 * See docs for deserializeCls
 */
exports.deserializeCls = deserializeCls;

/**
 * See docs for serializeCls
 */
exports.serializeCls = serializeCls;

/**
 * See docs for fullyQualifiedName
 */
exports.fullyQualifiedName = fullyQualifiedName;
<commit_msg>Fixed casing functionality in common.js<commit_after>/*
 *
 * Copyright 2014, Google Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

var capitalize = require('underscore.string/capitalize');

/**
 * Get a function that deserializes a specific type of protobuf.
 * @param {function()} cls The constructor of the message type to deserialize
 * @return {function(Buffer):cls} The deserialization function
 */
function deserializeCls(cls) {
  /**
   * Deserialize a buffer to a message object
   * @param {Buffer} arg_buf The buffer to deserialize
   * @return {cls} The resulting object
   */
  return function deserialize(arg_buf) {
    return cls.decode(arg_buf);
  };
}

/**
 * Get a function that serializes objects to a buffer by protobuf class.
 * @param {function()} Cls The constructor of the message type to serialize
 * @return {function(Cls):Buffer} The serialization function
 */
function serializeCls(Cls) {
  /**
   * Serialize an object to a Buffer
   * @param {Object} arg The object to serialize
   * @return {Buffer} The serialized object
   */
  return function serialize(arg) {
    return new Buffer(new Cls(arg).encode().toBuffer());
  };
}

/**
 * Get the fully qualified (dotted) name of a ProtoBuf.Reflect value.
 * @param {ProtoBuf.Reflect.Namespace} value The value to get the name of
 * @return {string} The fully qualified name of the value
 */
function fullyQualifiedName(value) {
  if (value === null || value === undefined) {
    return '';
  }
  var name = value.name;
  if (value.className === 'Service.RPCMethod') {
    name = capitalize(name);
  }
  if (value.hasOwnProperty('parent')) {
    var parent_name = fullyQualifiedName(value.parent);
    if (parent_name !== '') {
      name = parent_name + '.' + name;
    }
  }
  return name;
}

/**
 * See docs for deserializeCls
 */
exports.deserializeCls = deserializeCls;

/**
 * See docs for serializeCls
 */
exports.serializeCls = serializeCls;

/**
 * See docs for fullyQualifiedName
 */
exports.fullyQualifiedName = fullyQualifiedName;
<|endoftext|>


<commit_before>( function( mw, $ ) {"use strict";
	mw.PluginManager.add( 'largePlayBtn', mw.KBaseComponent.extend({
		//indicates we were explicitly asked to show the button (will be used when re-enabling the button)
		shouldShow : false,
		isDisabled: false,
		defaultConfig: {
			'parent': 'videoHolder',
			'togglePause': true,
			'order': 1
		},
		setup: function() {
			this.addBindings();
		},
		/**
		 * Checks if the play button should stay on screen during playback,
		 * cases where a native player is dipalyed such as iPhone.
		 */
		isPersistantPlayBtn: function(){
			return mw.isAndroid2() || this.getPlayer().isLinkPlayer() ||
					( mw.isIphone() && mw.getConfig( 'EmbedPlayer.iPhoneShowHTMLPlayScreen' ) );
		},
		addBindings: function() {
			var _this = this;
			this.bind('showInlineDownloadLink', function(e, linkUrl){
				_this.getComponent().attr({
					'href': linkUrl,
					'target': '_blank'
				});
			});

			this.bind('onChangeMediaDone playerReady onpause onEndedDone onRemovePlayerSpinner', function(){
				if( !_this.embedPlayer.isPlaying() && !_this.embedPlayer.isInSequence() ){
					_this.$el.removeClass("icon-pause").addClass("icon-play");
					_this.show();
				}
			});

			this.bind('onShowControlBar', function(){
				if( !mw.isIE8() && _this.getConfig("togglePause") && _this.embedPlayer.isPlaying() && !_this.embedPlayer.isInSequence() ){
					_this.$el.removeClass("icon-play").addClass("icon-pause");
					_this.show();
				}
			});
			this.bind('playing AdSupport_StartAdPlayback onAddPlayerSpinner onHideControlBar', function(){
				_this.hide();
			});
			this.bind('onPlayerStateChange', function(e, newState, oldState){
				if( newState == 'load' ){
					_this.hide(true);
				}
				if( newState == 'pause' && _this.getPlayer().isPauseLoading ){
					_this.hide();
				}
			});
		},
		show: function(){
			if ( !this.isDisabled ) {
				this.getComponent().show();
			}
			this.shouldShow = true;
		},
		hide: function( force ){
			this.hideComponent( force );
			this.shouldShow = false;
		},
		hideComponent: function( force ) {
			if( force || !this.isPersistantPlayBtn() ) {
				this.getComponent().hide();
			}
		},
		clickButton: function( event ){
			// If link player, only trigger events
			if( this.getPlayer().isLinkPlayer() ) {
				this.getPlayer().triggerHelper( 'firstPlay' ); // To send stats event for play
				this.getPlayer().triggerHelper( 'playing' );
				return;
			}

			event.preventDefault();
			event.stopPropagation();
			if ( this.getConfig("togglePause") && this.getPlayer().isPlaying() ){
				this.getPlayer().sendNotification('doPause');
			}else{
				this.getPlayer().triggerHelper( 'goingtoplay' );
				this.getPlayer().sendNotification('doPlay');
			}
		},
		onEnable: function(){
			this.isDisabled = false;
			if ( this.shouldShow ) {
				this.getComponent().show();
			}
		},
		onDisable: function(){
			this.isDisabled = true;
			this.hideComponent();
		},
		getComponent: function() {
			var _this = this;
			var eventName = 'click';
			if (mw.isMobileDevice() && !mw.isWindowsPhone()){
				eventName = 'touchstart';
			}
			if( !this.$el ) {
				this.$el = $( '<a />' )
							.attr( {
								'tabindex': '-1',
								'href' : '#',
								'title' : gM( 'mwe-embedplayer-play_clip' ),
								'class'	: "icon-play " + this.getCssClass()
							} )
							.hide()
							// Add play hook:
							.on(eventName, function(e) {
								_this.clickButton(e);
							} );
				if ( !mw.isWindowsPhone() ){
					this.$el.addClass("largePlayBtnBorder");
				}
			}
			return this.$el;
		}
	})
	);

} )( window.mw, window.jQuery );<commit_msg>SUPPS-305 #time 1h #comment call getComponent instead of accessing $el directly<commit_after>( function( mw, $ ) {"use strict";
	mw.PluginManager.add( 'largePlayBtn', mw.KBaseComponent.extend({
		//indicates we were explicitly asked to show the button (will be used when re-enabling the button)
		shouldShow : false,
		isDisabled: false,
		defaultConfig: {
			'parent': 'videoHolder',
			'togglePause': true,
			'order': 1
		},
		setup: function() {
			this.addBindings();
		},
		/**
		 * Checks if the play button should stay on screen during playback,
		 * cases where a native player is dipalyed such as iPhone.
		 */
		isPersistantPlayBtn: function(){
			return mw.isAndroid2() || this.getPlayer().isLinkPlayer() ||
					( mw.isIphone() && mw.getConfig( 'EmbedPlayer.iPhoneShowHTMLPlayScreen' ) );
		},
		addBindings: function() {
			var _this = this;
			this.bind('showInlineDownloadLink', function(e, linkUrl){
				_this.getComponent().attr({
					'href': linkUrl,
					'target': '_blank'
				});
			});

			this.bind('onChangeMediaDone playerReady onpause onEndedDone onRemovePlayerSpinner', function(){
				if( !_this.embedPlayer.isPlaying() && !_this.embedPlayer.isInSequence() ){
					_this.getComponent().removeClass("icon-pause").addClass("icon-play");
					_this.show();
				}
			});

			this.bind('onShowControlBar', function(){
				if( !mw.isIE8() && _this.getConfig("togglePause") && _this.embedPlayer.isPlaying() && !_this.embedPlayer.isInSequence() ){
					_this.$el.removeClass("icon-play").addClass("icon-pause");
					_this.show();
				}
			});
			this.bind('playing AdSupport_StartAdPlayback onAddPlayerSpinner onHideControlBar', function(){
				_this.hide();
			});
			this.bind('onPlayerStateChange', function(e, newState, oldState){
				if( newState == 'load' ){
					_this.hide(true);
				}
				if( newState == 'pause' && _this.getPlayer().isPauseLoading ){
					_this.hide();
				}
			});
		},
		show: function(){
			if ( !this.isDisabled ) {
				this.getComponent().show();
			}
			this.shouldShow = true;
		},
		hide: function( force ){
			this.hideComponent( force );
			this.shouldShow = false;
		},
		hideComponent: function( force ) {
			if( force || !this.isPersistantPlayBtn() ) {
				this.getComponent().hide();
			}
		},
		clickButton: function( event ){
			// If link player, only trigger events
			if( this.getPlayer().isLinkPlayer() ) {
				this.getPlayer().triggerHelper( 'firstPlay' ); // To send stats event for play
				this.getPlayer().triggerHelper( 'playing' );
				return;
			}

			event.preventDefault();
			event.stopPropagation();
			if ( this.getConfig("togglePause") && this.getPlayer().isPlaying() ){
				this.getPlayer().sendNotification('doPause');
			}else{
				this.getPlayer().triggerHelper( 'goingtoplay' );
				this.getPlayer().sendNotification('doPlay');
			}
		},
		onEnable: function(){
			this.isDisabled = false;
			if ( this.shouldShow ) {
				this.getComponent().show();
			}
		},
		onDisable: function(){
			this.isDisabled = true;
			this.hideComponent();
		},
		getComponent: function() {
			var _this = this;
			var eventName = 'click';
			if (mw.isMobileDevice() && !mw.isWindowsPhone()){
				eventName = 'touchstart';
			}
			if( !this.$el ) {
				this.$el = $( '<a />' )
							.attr( {
								'tabindex': '-1',
								'href' : '#',
								'title' : gM( 'mwe-embedplayer-play_clip' ),
								'class'	: "icon-play " + this.getCssClass()
							} )
							.hide()
							// Add play hook:
							.on(eventName, function(e) {
								_this.clickButton(e);
							} );
				if ( !mw.isWindowsPhone() ){
					this.$el.addClass("largePlayBtnBorder");
				}
			}
			return this.$el;
		}
	})
	);

} )( window.mw, window.jQuery );<|endoftext|>


<commit_before>

let path = require('path')
let clone = require('clone')
let shell_quote = require('shell-quote')

let os = require('../util/os')
let spawn = require('../util/spawn')

let log = require('../util/log')('tasks/launch')
let configure = require('./configure')

let CaveStore = require('../stores/cave-store')
let Crash = require('./errors').Crash

let self = {
  sh: async function (exe_path, full_command, opts) {
    log(opts, `sh ${full_command}`)

    // pretty weak but oh well.
    let forbidden = [';', '&']
    for (let bidden of forbidden) {
      if (full_command.indexOf(bidden) !== -1) {
        throw new Error(`Command-line contains forbidden characters: ${full_command}`)
      }
    }

    let cwd = path.dirname(exe_path)
    log(opts, `Working directory: ${cwd}`)

    let args = shell_quote.parse(full_command)
    let command = args.shift()

    let res = await spawn({
      command,
      args,
      ontoken: (tok) => log(opts, `stdout: ${tok}`),
      onerrtoken: (tok) => log(opts, `stderr: ${tok}`),
      opts: { cwd }
    })

    if (res.code !== 0) {
      let error = `process exited with code ${res.code}`
      throw new Crash({ exe_path, error })
    }
    return `child completed successfully`
  },

  escape: function (arg) {
    return `"${arg.replace(/"/g, '\\"')}"`
  },

  sort_by_depth: function (execs) {
    let depths = {}
    for (let exe of execs) {
      depths[exe] = path.normalize(exe).split(path.sep).length
    }
    return clone(execs).sort((a, b) => depths[a] - depths[b])
  },

  sort_by_score: function (execs) {
    let scores = {}
    for (let exe of execs) {
      let score = 100
      if (/unins/.test(exe)) {
        score = 0
      }
      scores[exe] = score
    }
    return clone(execs).sort((a, b) => scores[b] - scores[a])
  },

  launch: function (exe_path, args, opts) {
    let platform = os.platform()
    log(opts, `launching '${exe_path}' on '${platform}' with args '${args.join(' ')}'`)
    let arg_string = args.map((x) => self.escape(x)).join(' ')

    if (platform === 'darwin' && /\.app\/?$/.test(exe_path.toLowerCase())) {
      // '-W' waits for app to quit
      // potentially easy to inject something into the command line
      // here but then again we are running executables downloaded
      // from the internet.
      let cmd = `open -W ${self.escape(exe_path)}`
      if (arg_string.length > 0) {
        cmd += ` --args ${arg_string}`
      }
      return self.sh(exe_path, cmd, opts)
    } else {
      let cmd = `${self.escape(exe_path)}`
      if (arg_string.length > 0) {
        cmd += ` ${arg_string}`
      }
      return self.sh(exe_path, cmd, opts)
    }
  },

  launch_cave: function (opts, cave) {
    let by_score = self.sort_by_score(cave.executables)
    let by_depth = self.sort_by_depth(by_score)
    let sorted = by_depth

    log(opts, `executables (from best to worst): ${JSON.stringify(sorted, null, 2)}`)
    let app_path = CaveStore.app_path(cave.install_location, opts.id)
    let exe_path = path.join(app_path, sorted[0])
    return self.launch(exe_path, [], opts)
  },

  valid_cave: function (cave) {
    return cave.executables && cave.executables.length > 0
  },

  start: async function (opts) {
    let id = opts.id

    let cave = await CaveStore.find(id)
    if (!self.valid_cave(cave)) {
      await configure.start(opts)
      cave = await CaveStore.find(id)
    }

    if (!self.valid_cave(cave)) {
      throw new Error('No executables found')
    }

    await self.launch_cave(opts, cave)
  }
}

module.exports = self
<commit_msg>:bug: fix bug introduced in 90164b2195a789ae924e17cfde5a38d728af2f67 that marked games as broken<commit_after>

let path = require('path')
let clone = require('clone')
let shell_quote = require('shell-quote')

let os = require('../util/os')
let spawn = require('../util/spawn')

let log = require('../util/log')('tasks/launch')
let configure = require('./configure')

let CaveStore = require('../stores/cave-store')
let Crash = require('./errors').Crash

let self = {
  sh: async function (exe_path, full_command, opts) {
    log(opts, `sh ${full_command}`)

    // pretty weak but oh well.
    let forbidden = [';', '&']
    for (let bidden of forbidden) {
      if (full_command.indexOf(bidden) !== -1) {
        throw new Error(`Command-line contains forbidden characters: ${full_command}`)
      }
    }

    let cwd = path.dirname(exe_path)
    log(opts, `Working directory: ${cwd}`)

    let args = shell_quote.parse(full_command)
    let command = args.shift()

    let code = await spawn({
      command,
      args,
      ontoken: (tok) => log(opts, `stdout: ${tok}`),
      onerrtoken: (tok) => log(opts, `stderr: ${tok}`),
      opts: { cwd }
    })

    if (code !== 0) {
      let error = `process exited with code ${code}`
      throw new Crash({ exe_path, error })
    }
    return `child completed successfully`
  },

  escape: function (arg) {
    return `"${arg.replace(/"/g, '\\"')}"`
  },

  sort_by_depth: function (execs) {
    let depths = {}
    for (let exe of execs) {
      depths[exe] = path.normalize(exe).split(path.sep).length
    }
    return clone(execs).sort((a, b) => depths[a] - depths[b])
  },

  sort_by_score: function (execs) {
    let scores = {}
    for (let exe of execs) {
      let score = 100
      if (/unins/.test(exe)) {
        score = 0
      }
      scores[exe] = score
    }
    return clone(execs).sort((a, b) => scores[b] - scores[a])
  },

  launch: function (exe_path, args, opts) {
    let platform = os.platform()
    log(opts, `launching '${exe_path}' on '${platform}' with args '${args.join(' ')}'`)
    let arg_string = args.map((x) => self.escape(x)).join(' ')

    if (platform === 'darwin' && /\.app\/?$/.test(exe_path.toLowerCase())) {
      // '-W' waits for app to quit
      // potentially easy to inject something into the command line
      // here but then again we are running executables downloaded
      // from the internet.
      let cmd = `open -W ${self.escape(exe_path)}`
      if (arg_string.length > 0) {
        cmd += ` --args ${arg_string}`
      }
      return self.sh(exe_path, cmd, opts)
    } else {
      let cmd = `${self.escape(exe_path)}`
      if (arg_string.length > 0) {
        cmd += ` ${arg_string}`
      }
      return self.sh(exe_path, cmd, opts)
    }
  },

  launch_cave: function (opts, cave) {
    let by_score = self.sort_by_score(cave.executables)
    let by_depth = self.sort_by_depth(by_score)
    let sorted = by_depth

    log(opts, `executables (from best to worst): ${JSON.stringify(sorted, null, 2)}`)
    let app_path = CaveStore.app_path(cave.install_location, opts.id)
    let exe_path = path.join(app_path, sorted[0])
    return self.launch(exe_path, [], opts)
  },

  valid_cave: function (cave) {
    return cave.executables && cave.executables.length > 0
  },

  start: async function (opts) {
    let id = opts.id

    let cave = await CaveStore.find(id)
    if (!self.valid_cave(cave)) {
      await configure.start(opts)
      cave = await CaveStore.find(id)
    }

    if (!self.valid_cave(cave)) {
      throw new Error('No executables found')
    }

    await self.launch_cave(opts, cave)
  }
}

module.exports = self
<|endoftext|>


<commit_before>'use strict';

angular.module('myApp')
    .service('UsersService', ['store', function (store) {

        this.ceo = {
            "email": "ivan@handyassist.com",
            "email_verified": false,
            "user_id": "auth0|56c886e1ad96ed90125bf95a",
            "picture": "https://s.gravatar.com/avatar/32d4917d14c2d3d5d9724b2ef86e988b?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fiv.png",
            "nickname": null,
            "identities": [
                {
                    "connection": "Username-Password-Authentication",
                    "user_id": "56c886e1ad96ed90125bf95a",
                    "provider": "auth0",
                    "isSocial": false
                }
            ],
            "updated_at": "2016-02-21T12:28:44.795Z",
            "created_at": "2016-02-20T15:31:45.743Z",
            "user_metadata": {
                "photoUrl": "https://pbs.twimg.com/profile_images/2606822886/v3v58lx1a6n91uzjh5ep.jpeg",
                "skypeName": "hej.ivan",
                "phone": "+79817727449",
                "name": "Ivan Alyakskin",
                "clientId": "56ca635abd49800ea1b30255",
                "role": "0"
            }
        };

        this.pm = {
            "email": "stas@handyassist.com",
            "email_verified": false,
            "user_id": "auth0|56c88f00ad96ed90125bf9f4",
            "picture": "https://s.gravatar.com/avatar/44ec7a2bed98a42ce52030de604c9253?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fst.png",
            "nickname": null,
            "identities": [
                {
                    "connection": "Username-Password-Authentication",
                    "user_id": "56c88f00ad96ed90125bf9f4",
                    "provider": "auth0",
                    "isSocial": false
                }
            ],
            "updated_at": "2016-02-20T16:42:35.615Z",
            "created_at": "2016-02-20T16:06:24.698Z",
            "user_metadata": {
                "photoUrl": "https://pbs.twimg.com/profile_images/1143717167/x_eb3b3f88.jpg",
                "skypeName": "casper1149",
                "phone": "+79219262241",
                "name": "Stas Smirnov",
                "clientId": "56ca635abd49800ea1b30255",
                "role": "1"
            }
        };

        this.employee = {
            "email": "tanya@handyassit.com",
            "email_verified": false,
            "user_id": "auth0|56c88f1aad96ed90125bf9f6",
            "picture": "https://s.gravatar.com/avatar/8290cdea6f40bd06dc74e34b165c60cc?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fta.png",
            "nickname": null,
            "identities": [
                {
                    "connection": "Username-Password-Authentication",
                    "user_id": "56c88f1aad96ed90125bf9f6",
                    "provider": "auth0",
                    "isSocial": false
                }
            ],
            "updated_at": "2016-02-20T19:39:18.140Z",
            "created_at": "2016-02-20T16:06:50.151Z",
            "user_metadata": {
                "photoUrl": "https://pbs.twimg.com/profile_images/2060238222/myspace.png",
                "skypeName": "zzzlayaspb",
                "phone": "+79211234567",
                "name": "Tatiana Trubitcyna",
                "clientId": "56ca635abd49800ea1b30255",
                "role": "2"
            }
        };

        this.setCurrentUser = function (roleId) {
            var currentUser;
            switch (roleId) {
                case '0':
                    currentUser = this.ceo;
                    break;
                case '1':
                    currentUser = this.pm;
                    break;
                case '2':
                    currentUser = this.employee;
                    break;
            }

            store.set('currentUser', currentUser);
        };

        this.getCurrentUser = function () {
            return store.get('currentUser');
        };

    }]);<commit_msg>updated client id<commit_after>'use strict';

angular.module('myApp')
    .service('UsersService', ['store', function (store) {

        this.ceo = {
            "email": "ivan@handyassist.com",
            "email_verified": false,
            "user_id": "auth0|56c886e1ad96ed90125bf95a",
            "picture": "https://s.gravatar.com/avatar/32d4917d14c2d3d5d9724b2ef86e988b?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fiv.png",
            "nickname": null,
            "identities": [
                {
                    "connection": "Username-Password-Authentication",
                    "user_id": "56c886e1ad96ed90125bf95a",
                    "provider": "auth0",
                    "isSocial": false
                }
            ],
            "updated_at": "2016-02-21T12:28:44.795Z",
            "created_at": "2016-02-20T15:31:45.743Z",
            "user_metadata": {
                "photoUrl": "https://pbs.twimg.com/profile_images/2606822886/v3v58lx1a6n91uzjh5ep.jpeg",
                "skypeName": "hej.ivan",
                "phone": "+79817727449",
                "name": "Ivan Alyakskin",
                "clientId": client,
                "role": "0"
            }
        };

        this.pm = {
            "email": "stas@handyassist.com",
            "email_verified": false,
            "user_id": "auth0|56c88f00ad96ed90125bf9f4",
            "picture": "https://s.gravatar.com/avatar/44ec7a2bed98a42ce52030de604c9253?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fst.png",
            "nickname": null,
            "identities": [
                {
                    "connection": "Username-Password-Authentication",
                    "user_id": "56c88f00ad96ed90125bf9f4",
                    "provider": "auth0",
                    "isSocial": false
                }
            ],
            "updated_at": "2016-02-20T16:42:35.615Z",
            "created_at": "2016-02-20T16:06:24.698Z",
            "user_metadata": {
                "photoUrl": "https://pbs.twimg.com/profile_images/1143717167/x_eb3b3f88.jpg",
                "skypeName": "casper1149",
                "phone": "+79219262241",
                "name": "Stas Smirnov",
                "clientId": client,
                "role": "1"
            }
        };

        this.employee = {
            "email": "tanya@handyassit.com",
            "email_verified": false,
            "user_id": "auth0|56c88f1aad96ed90125bf9f6",
            "picture": "https://s.gravatar.com/avatar/8290cdea6f40bd06dc74e34b165c60cc?s=480&r=pg&d=https%3A%2F%2Fcdn.auth0.com%2Favatars%2Fta.png",
            "nickname": null,
            "identities": [
                {
                    "connection": "Username-Password-Authentication",
                    "user_id": "56c88f1aad96ed90125bf9f6",
                    "provider": "auth0",
                    "isSocial": false
                }
            ],
            "updated_at": "2016-02-20T19:39:18.140Z",
            "created_at": "2016-02-20T16:06:50.151Z",
            "user_metadata": {
                "photoUrl": "https://pbs.twimg.com/profile_images/2060238222/myspace.png",
                "skypeName": "zzzlayaspb",
                "phone": "+79211234567",
                "name": "Tatiana Trubitcyna",
                "clientId": client,
                "role": "2"
            }
        };

        this.setCurrentUser = function (roleId) {
            var currentUser;
            switch (roleId) {
                case '0':
                    currentUser = this.ceo;
                    break;
                case '1':
                    currentUser = this.pm;
                    break;
                case '2':
                    currentUser = this.employee;
                    break;
            }

            store.set('currentUser', currentUser);
        };

        this.getCurrentUser = function () {
            return store.get('currentUser');
        };

    }]);<|endoftext|>


<commit_before>export const entryPointType = 'al_empezar_a_ejecutar'

export function isFlying(block) {
  return block.getRootBlock() === block
}

export function allProcedures(workspace = Blockly.mainWorkspace) {
  return workspace.getTopBlocks().filter(isProcedure)
}

export function allProcedureNames(workspace) {
  return allProcedures(workspace).map(getName)
}

export function declarationWithName(name, workspace = Blockly.mainWorkspace) {
  return entryPointType == name
  ? workspace.getAllBlocks().find(b => b.type === entryPointType) //TODO: Move to gral place
  : allProcedures(workspace).find(p => getName(p) == name)
}

// TODO: No acoplarse a la categoria
export function isOperator(block) {
  return block.categoryId == "operators"
}
export function isValue(block) {
  return block.categoryId == "values"
}

export function isProcedure(block){
  return Blockly.isProcedure(block.type)
}

export function isProcedureCall(block) {
  return !!block.defType_
}

export function isInsideProcedureDef(paramBlock) {
  return paramBlock.getRootBlock().id === paramBlock.$parent
}

export function hasParam(procedureBlock, paramBlock) {
  return getParams(procedureBlock).includes(paramBlock.getFieldValue('VAR'))
}

export function getName(procedureBlock) {
  return procedureBlock.getProcedureDef()[0]
}

export function getParams(procedureBlock) {
  return procedureBlock.getProcedureDef()[1]
}

export function getBlockSiblings(block) {
  const siblings = [];
  while (block.getNextBlock()){
    block = block.getNextBlock()
    siblings.push(block);
  }
  return siblings;
}

export function getChild(block) {
  return block.getChildren()[0]
}

// Agrega un required shadow a todos los input que sean para encastrar otros bloques
export function requiredAllInputs(block) {
  block.inputList
  .filter(input => input.connection && shouldAddRequiredShadow(input.connection))
  .forEach(input => requiredInput(block, input.name))
}

function shouldAddRequiredShadow(connection) {
  return  connection.getShadowDom() == null // Should have not a shadow block
  &&      [Blockly.INPUT_VALUE, Blockly.NEXT_STATEMENT].includes(connection.type) // Should be a "block hole"
}

function requiredInput(block, inputName) {
  let connection = block.getInput(inputName).connection
  let shadowType =  (connection.type == Blockly.INPUT_VALUE)
                    ? "required_value"
                    : "required_statement"
  var shadowValue = Blockly.Xml.textToDom(`<shadow type="${shadowType}"></shadow>`)
  connection.setShadowDom(shadowValue)
  if (!connection.targetConnection)
    connection.respawnShadow_()
}

export function clearValidations(workspace = Blockly.mainWorkspace) {
  workspace.getAllBlocks().filter(b => b.warning).forEach(clearValidationsFor)
}

export function clearValidationsFor(block) {
  block.setWarningText(null)
}

export function addWarning(block, message, index, itemChar = '☆ ') {
  block.setWarningText(itemChar + lineWrap(message), index)
  block.warning.setVisible(true)
  block.warning.bubble_.setColour('yellow')
}

export function addError(block, message, index) {
  addWarning(block, message, index, '★ ')
  block.warning.bubble_.setColour('red')
}

function lineWrap(message){
  const lineLen = 75
  return message.split(' ').reduce((lines, word) => {
      const lastLine = lines[lines.length-1]
      if(lastLine.length + word.length > lineLen)
        lines.push(word)
      else
        lines.push(lines.pop() + ' ' + word)
      return lines
    },
    [""]
  ).join('\n  ')
}<commit_msg>Fixing bubble colours<commit_after>export const entryPointType = 'al_empezar_a_ejecutar'

export function isFlying(block) {
  return block.getRootBlock() === block
}

export function allProcedures(workspace = Blockly.mainWorkspace) {
  return workspace.getTopBlocks().filter(isProcedure)
}

export function allProcedureNames(workspace) {
  return allProcedures(workspace).map(getName)
}

export function declarationWithName(name, workspace = Blockly.mainWorkspace) {
  return entryPointType == name
  ? workspace.getAllBlocks().find(b => b.type === entryPointType) //TODO: Move to gral place
  : allProcedures(workspace).find(p => getName(p) == name)
}

// TODO: No acoplarse a la categoria
export function isOperator(block) {
  return block.categoryId == "operators"
}
export function isValue(block) {
  return block.categoryId == "values"
}

export function isProcedure(block){
  return Blockly.isProcedure(block.type)
}

export function isProcedureCall(block) {
  return !!block.defType_
}

export function isInsideProcedureDef(paramBlock) {
  return paramBlock.getRootBlock().id === paramBlock.$parent
}

export function hasParam(procedureBlock, paramBlock) {
  return getParams(procedureBlock).includes(paramBlock.getFieldValue('VAR'))
}

export function getName(procedureBlock) {
  return procedureBlock.getProcedureDef()[0]
}

export function getParams(procedureBlock) {
  return procedureBlock.getProcedureDef()[1]
}

export function getBlockSiblings(block) {
  const siblings = [];
  while (block.getNextBlock()){
    block = block.getNextBlock()
    siblings.push(block);
  }
  return siblings;
}

export function getChild(block) {
  return block.getChildren()[0]
}

// Agrega un required shadow a todos los input que sean para encastrar otros bloques
export function requiredAllInputs(block) {
  block.inputList
  .filter(input => input.connection && shouldAddRequiredShadow(input.connection))
  .forEach(input => requiredInput(block, input.name))
}

function shouldAddRequiredShadow(connection) {
  return  connection.getShadowDom() == null // Should have not a shadow block
  &&      [Blockly.INPUT_VALUE, Blockly.NEXT_STATEMENT].includes(connection.type) // Should be a "block hole"
}

function requiredInput(block, inputName) {
  let connection = block.getInput(inputName).connection
  let shadowType =  (connection.type == Blockly.INPUT_VALUE)
                    ? "required_value"
                    : "required_statement"
  var shadowValue = Blockly.Xml.textToDom(`<shadow type="${shadowType}"></shadow>`)
  connection.setShadowDom(shadowValue)
  if (!connection.targetConnection)
    connection.respawnShadow_()
}

export function clearValidations(workspace = Blockly.mainWorkspace) {
  workspace.getAllBlocks().filter(b => b.warning).forEach(clearValidationsFor)
}

export function clearValidationsFor(block) {
  block.setWarningText(null)
}

const setWarningBubbleColour = (block, colour) => {
  const unBoundedSetVisible = Blockly.Warning.prototype.setVisible
  const boundedSetVisible = unBoundedSetVisible.bind(block.warning)
  block.warning.setVisible = (visible) => { boundedSetVisible(visible); if (visible) block.warning.bubble_.setColour(colour) }
}

const addWarningToBlock = (block, itemChar, message, index, bubbleColour) => {
  const text = `${itemChar} ${lineWrap(message)}`
  block.setWarningText(text, index)
  setWarningBubbleColour(block, bubbleColour)
  block.warning.setVisible(true)
}

export function addWarning(block, message, index) {
  addWarningToBlock(block, '☆', message, index, 'yellow')
}

export function addError(block, message, index) {
  addWarningToBlock(block, '★', message, index, 'red')
}

function lineWrap(message){
  const lineLen = 75
  return message.split(' ').reduce((lines, word) => {
      const lastLine = lines[lines.length-1]
      if(lastLine.length + word.length > lineLen)
        lines.push(word)
      else
        lines.push(lines.pop() + ' ' + word)
      return lines
    },
    [""]
  ).join('\n  ')
}<|endoftext|>


<commit_before><commit_msg>Enable multi row select with key Ctrl key modifier<commit_after><|endoftext|>


<commit_before>export const white = '#ffffff'
export const blue = '#2196f3'
export const yellow = '#ffeb3b'
export const orange = '#ff9800'
export const grey = '#9e9e9e'
export const black = '#000000'
export const blueGrey = '#607d8b'
export const amber = '#ffc107'
export const deepOrange = '#ff5722'
export const red = '#f44336'
export const pink = '#e91e63'
export const brown = '#795548'
export const lime = '#cddc39'
export const lightGreen = '#8bc34a'
export const green = '#4caf50'
export const teal = '#009688'
export const lightBlue = '#03a9f4'
export const purple = '#9c27b0'
export const deepPurple = '#673ab7'
export const cyan = '#00bcd4'

export const colorSet = [white, yellow, orange, pink, green, blue]
export const textColorSet = [white, grey, blueGrey, black, lightGreen, green, teal, yellow, orange, pink, red, brown, blue, purple]
<commit_msg>change pink to standard<commit_after>export const white = '#ffffff'
export const blue = '#2196f3'
export const yellow = '#ffeb3b'
export const orange = '#ff9800'
export const grey = '#9e9e9e'
export const black = '#000000'
export const blueGrey = '#607d8b'
export const amber = '#ffc107'
export const deepOrange = '#ff5722'
export const red = '#f44336'
export const pink = '#FFC0CB'
export const brown = '#795548'
export const lime = '#cddc39'
export const lightGreen = '#8bc34a'
export const green = '#4caf50'
export const teal = '#009688'
export const lightBlue = '#03a9f4'
export const purple = '#9c27b0'
export const deepPurple = '#673ab7'
export const cyan = '#00bcd4'

export const colorSet = [white, yellow, orange, pink, green, blue]
export const textColorSet = [white, grey, blueGrey, black, lightGreen, green, teal, yellow, orange, pink, red, brown, blue, purple]
<|endoftext|>


<commit_before><commit_msg>Fixed issue with volume set to 0<commit_after><|endoftext|>


<commit_before>import React, { Component } from 'react';

class DropdownContainer extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isClicked: false
    };
  }

  onClick = () => {
    this.setState({
      isClicked: !this.state.isClicked
    });
  };
  handleBodyClick = () => {
    this.setState({ isClicked: false });
  };

  componentDidMount() {
    document
      .getElementById('app')
      .addEventListener('click', this.handleBodyClick);
  }

  componentWillUnmount() {
    document
      .getElementById('app')
      .removeEventListener('click', this.handleBodyClick);
  }

  render() {
    return (

        <DropdownTrigger
          isClicked={this.state.isClicked}
          onSelect={() => this.onClick()}
        />
        <DropdownItems visible={this.state.isClicked} />

    );
  }
}

class DropdownTrigger extends Component {
  render() {
    const triggerStyle = this.props.isClicked
      ? { backgroundColor: '#EEEEEE', width: '86.5px', display: 'flex' }
      : {};
    return (

          Dropdown

    );
  }
}
class DropdownItems extends Component {
  render() {
    const itemContent = ['Action', 'Another action', 'Something else here'];
    const itemStyle = {
      marginLeft: '0px',
      marginTop: '4px',
      marginRight: '0px',
      marginBottom: '4px',
      paddingLeft: '15px',
      verticalAlign: 'middle',
      paddingTop: '4px',
      paddingBottom: '4px'
    };
    if (this.props.visible) {
      return (

          {itemContent.map((value, key) => {
            return (

{value}

            );
          })}

Separated link

      );
    } else {
      return
;
    }
  }
}

export default DropdownContainer;
<commit_msg>new dropdown issue added<commit_after>import React, { Component } from 'react';

class DropdownContainer extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isClicked: false
    };
  }

  onClick = () => {
    this.setState({
      isClicked: !this.state.isClicked
    });
  };
  handleBodyClick = () => {
    this.setState({ isClicked: false });
  };

  componentDidUpdate() {
    document
      .getElementById('root')
      .addEventListener('click', this.handleBodyClick);
  }

  componentWillUpdate() {
    document
      .getElementById('root')
      .removeEventListener('click', this.handleBodyClick);
  }

  render() {
    return (

        <DropdownTrigger
          isClicked={this.state.isClicked}
          onSelect={() => this.onClick()}
        />
        <DropdownItems visible={this.state.isClicked} />

    );
  }
}

class DropdownTrigger extends Component {
  render() {
    const triggerStyle = this.props.isClicked
      ? { backgroundColor: '#EEEEEE', width: '86.5px', display: 'flex' }
      : {};
    return (

          Dropdown

    );
  }
}
class DropdownItems extends Component {
  render() {
    const itemContent = ['Action', 'Another action', 'Something else here'];
    const itemStyle = {
      marginLeft: '0px',
      marginTop: '4px',
      marginRight: '0px',
      marginBottom: '4px',
      paddingLeft: '15px',
      verticalAlign: 'middle',
      paddingTop: '4px',
      paddingBottom: '4px'
    };
    if (this.props.visible) {
      return (

          {itemContent.map((value, key) => {
            return (

{value}

            );
          })}

Separated link

      );
    } else {
      return
;
    }
  }
}

export default DropdownContainer;
<|endoftext|>


<commit_before>/**
 keyevent.js
 Copyright (c) 2015 NTT DOCOMO,INC.
 Released under the MIT license
 http://opensource.org/licenses/mit-license.php
 */

/**
 * Key Event
 */
function showKeyEvent(serviceId) {
  initAll();
  setTitle('Key Event Profile(Event)');

  var sessionKey = currentClientId;
  var btnStr = getBackButton('Device Top', 'doKeyEventBack', serviceId,
                 sessionKey);
  reloadHeader(btnStr);
  reloadFooter(btnStr);

  var str = '';
  str += '
Show Key(onDown)
';
  str += '
Show Key(onUp)
';
  str += '
Key Event(onDown)
';
  str += '
Key Event(onUp)
';
  reloadList(str);
}

/**
 * Show OnDown
 *
 * @param {String}serviceId サービスID
 */
function showOnDown(serviceId) {
  initAll();
  setTitle('Show Down');

  var sessionKey = currentClientId;

  var btnStr = getBackButton('Device Top', 'doKeyBack', serviceId, sessionKey);
  reloadHeader(btnStr);
  reloadFooter(btnStr);

  var str = '';
  str += '<form name="ondownForm">';
  str += 'Down
';
  str += '<input type="button" name="getButton" id="getButton" value="Get"' +
           ' onclick="doGetOnDown(\'' + serviceId + '\');"/>';
  str += '<input type="text" id="idD" width="100%">';
  str += '<input type="text" id="configD" width="100%">';
  str += '</form>';
  reloadContent(str);
}

/**
 * Get OnDown
 *
 * @param {String}serviceId サービスID
 */
function doGetOnDown(serviceId) {
  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('ondown');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri: ' + uri);
  }

  dConnect.get(uri, null, null, function(json) {
    if (DEBUG) {
      console.log('Response: ', json);
    }

    closeLoading();
    if (json.keyevent) {
      $('#idD').val('KeyID: ' + json.keyevent.id);
      $('#configD').val('config: ' + json.keyevent.config);
    }
  }, function(errorCode, errorMessage) {
    showError('GET ondown', errorCode, errorMessage);
  });
}

/**
 * Show Down Event
 *
 * @param {String}serviceId サービスID
 */
function showDownEvent(serviceId) {
  initAll();
  setTitle('Down Event');

  var sessionKey = currentClientId;

  var btnStr = getBackButton('Device Top', 'doDownEventBack', serviceId,
                 sessionKey);
  reloadHeader(btnStr);
  reloadFooter(btnStr);

  var str = '';
  str += '<form name="downForm">';
  str += 'Down
';
  str += '<input type="text" id="idD" width="100%">';
  str += '<input type="text" id="configD" width="100%">';
  str += '</form>';
  reloadContent(str);

  doDownRegist(serviceId, sessionKey);
  dConnect.connectWebSocket(sessionKey, function(errorCode, errorMessage) {});
}

/**
 * Show OnUp
 *
 * @param {String}serviceId サービスID
 */
function showOnUp(serviceId) {
  initAll();
  setTitle('Show Up');

  var sessionKey = currentClientId;

  var btnStr = getBackButton('Device Top', 'doKeyBack', serviceId, sessionKey);
  reloadHeader(btnStr);
  reloadFooter(btnStr);

  var str = '';
  str += '<form name="onupForm">';
  str += 'Up
';
  str += '<input type="button" name="getButton" id="getButton" value="Get"' +
           ' onclick="doGetOnUp(\'' + serviceId + '\');"/>';
  str += '<input type="text" id="idU" width="100%">';
  str += '<input type="text" id="configU" width="100%">';
  str += '</form>';
  reloadContent(str);
}

/**
 * Get OnUp
 *
 * @param {String}serviceId サービスID
 */
function doGetOnUp(serviceId) {
  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('onup');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri: ' + uri);
  }

  dConnect.get(uri, null, null, function(json) {
    if (DEBUG) {
      console.log('Response: ', json);
    }

    closeLoading();
    if (json.keyevent) {
      $('#idU').val('KeyID: ' + json.keyevent.id);
      $('#configU').val('config: ' + json.keyevent.config);
    }
  }, function(errorCode, errorMessage) {
    showError('GET ondown', errorCode, errorMessage);
  });
}

/**
 * Show Up Event
 *
 * @param {String}serviceId サービスID
 */
function showUpEvent(serviceId) {
  initAll();
  setTitle('Up Event');

  var sessionKey = currentClientId;

  var btnStr = getBackButton('Device Top', 'doUpEventBack', serviceId,
                 sessionKey);
  reloadHeader(btnStr);
  reloadFooter(btnStr);

  var str = '';
  str += '<form name="upForm">';
  str += 'Up
';
  str += '<input type="text" id="idU" width="100%">';
  str += '<input type="text" id="configU" width="100%">';
  str += '</form>';
  reloadContent(str);

  doUpRegist(serviceId, sessionKey);
  dConnect.connectWebSocket(sessionKey, function(errorCode, errorMessage) {});
}

/**
 * Backボタン
 *
 * serviceId サービスID
 * sessionKey セッションKEY
 */
function doKeyEventBack(serviceId, sessionKey) {
  searchSystem(serviceId);
}

/**
 * Backボタン
 *
 * serviceId サービスID
 * sessionKey セッションKEY
 */
function doKeyBack(serviceId, sessionKey) {
  showKeyEvent(serviceId);
}

/**
 * Backボタン
 *
 * serviceId サービスID
 * sessionKey セッションKEY
 */
function doDownEventBack(serviceId, sessionKey) {
  doDownUnregister(serviceId, sessionKey);
  showKeyEvent(serviceId);
}

/**
 * Backボタン
 *
 * serviceId サービスID
 * sessionKey セッションKEY
 */
function doUpEventBack(serviceId, sessionKey) {
  doUpUnregister(serviceId, sessionKey);
  showKeyEvent(serviceId);
}

/**
 * Down Event Regist
 */
function doDownRegist(serviceId, sessionKey) {
  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('ondown');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  builder.setSessionKey(sessionKey);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri: ' + uri);
  }

  dConnect.addEventListener(uri, function(message) {
    // イベントメッセージが送られてくる
    if (DEBUG) {
      console.log('Event-Message:' + message)
    }

    var json = JSON.parse(message);
    if (json.keyevent) {
      $('#idD').val('KeyID: ' + json.keyevent.id);
      $('#configD').val('config: ' + json.keyevent.config);
    }
  }, null, function(errorCode, errorMessage) {
    alert(errorMessage);
  });
}

/**
 * Up Event Regist
 */
function doUpRegist(serviceId, sessionKey) {
  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('onup');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  builder.setSessionKey(sessionKey);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri: ' + uri);
  }

  dConnect.addEventListener(uri, function(message) {
    // イベントメッセージが送られてくる
    if (DEBUG) {
      console.log('Event-Message:' + message);
    }

    var json = JSON.parse(message);
    if (json.keyevent) {
      $('#idU').val('KeyID: ' + json.keyevent.id);
      $('#configU').val('config: ' + json.keyevent.config);
    }
  }, null, function(errorCode, errorMessage) {
    alert(errorMessage);
  });
}

/**
 * Down Event Unregist
 */
function doDownUnregister(serviceId, sessionKey) {

  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('ondown');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  builder.setSessionKey(sessionKey);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri : ' + uri);
  }

  dConnect.removeEventListener(uri, null, function(errorCode, errorMessage) {
    alert(errorMessage);
  });
}

/**
 * Up Event Unregist
 */
function doUpUnregister(serviceId, sessionKey) {

  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('onup');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  builder.setSessionKey(sessionKey);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri : ' + uri);
  }

  dConnect.removeEventListener(uri, null, function(errorCode, errorMessage) {
    alert(errorMessage);
  });
}
<commit_msg>Modify GET process.<commit_after>/**
 keyevent.js
 Copyright (c) 2015 NTT DOCOMO,INC.
 Released under the MIT license
 http://opensource.org/licenses/mit-license.php
 */

/**
 * Key Event
 */
function showKeyEvent(serviceId) {
  initAll();
  setTitle('Key Event Profile(Event)');

  var sessionKey = currentClientId;
  var btnStr = getBackButton('Device Top', 'doKeyEventBack', serviceId,
                 sessionKey);
  reloadHeader(btnStr);
  reloadFooter(btnStr);

  var str = '';
  str += '
Show Key(onDown)
';
  str += '
Show Key(onUp)
';
  str += '
Key Event(onDown)
';
  str += '
Key Event(onUp)
';
  reloadList(str);
}

/**
 * Show OnDown
 *
 * @param {String}serviceId サービスID
 */
function showOnDown(serviceId) {
  initAll();
  setTitle('Show Down');

  var sessionKey = currentClientId;

  var btnStr = getBackButton('Device Top', 'doKeyBack', serviceId, sessionKey);
  reloadHeader(btnStr);
  reloadFooter(btnStr);

  var str = '';
  str += '<form name="ondownForm">';
  str += 'Down
';
  str += '<input type="button" name="getButton" id="getButton" value="Get"' +
           ' onclick="doGetOnDown(\'' + serviceId + '\');"/>';
  str += '<input type="text" id="idD" width="100%">';
  str += '<input type="text" id="configD" width="100%">';
  str += '</form>';
  reloadContent(str);
}

/**
 * Get OnDown
 *
 * @param {String}serviceId サービスID
 */
function doGetOnDown(serviceId) {
  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('ondown');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri: ' + uri);
  }

  dConnect.get(uri, null, function(json) {
    if (DEBUG) {
      console.log('Response: ', json);
    }

    closeLoading();
    $('#idD').val('');
    $('#configD').val('');

    if (json.keyevent) {
      $('#idD').val('KeyID: ' + json.keyevent.id);
      $('#configD').val('config: ' + json.keyevent.config);
    }
  }, function(errorCode, errorMessage) {
    showError('GET ondown', errorCode, errorMessage);
  });
}

/**
 * Show Down Event
 *
 * @param {String}serviceId サービスID
 */
function showDownEvent(serviceId) {
  initAll();
  setTitle('Down Event');

  var sessionKey = currentClientId;

  var btnStr = getBackButton('Device Top', 'doDownEventBack', serviceId,
                 sessionKey);
  reloadHeader(btnStr);
  reloadFooter(btnStr);

  var str = '';
  str += '<form name="downForm">';
  str += 'Down
';
  str += '<input type="text" id="idD" width="100%">';
  str += '<input type="text" id="configD" width="100%">';
  str += '</form>';
  reloadContent(str);

  doDownRegist(serviceId, sessionKey);
  dConnect.connectWebSocket(sessionKey, function(errorCode, errorMessage) {});
}

/**
 * Show OnUp
 *
 * @param {String}serviceId サービスID
 */
function showOnUp(serviceId) {
  initAll();
  setTitle('Show Up');

  var sessionKey = currentClientId;

  var btnStr = getBackButton('Device Top', 'doKeyBack', serviceId, sessionKey);
  reloadHeader(btnStr);
  reloadFooter(btnStr);

  var str = '';
  str += '<form name="onupForm">';
  str += 'Up
';
  str += '<input type="button" name="getButton" id="getButton" value="Get"' +
           ' onclick="doGetOnUp(\'' + serviceId + '\');"/>';
  str += '<input type="text" id="idU" width="100%">';
  str += '<input type="text" id="configU" width="100%">';
  str += '</form>';
  reloadContent(str);
}

/**
 * Get OnUp
 *
 * @param {String}serviceId サービスID
 */
function doGetOnUp(serviceId) {
  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('onup');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri: ' + uri);
  }

  dConnect.get(uri, null, function(json) {
    if (DEBUG) {
      console.log('Response: ', json);
    }

    closeLoading();

    $('#idU').val('');
    $('#configU').val('');

    if (json.keyevent) {
      $('#idU').val('KeyID: ' + json.keyevent.id);
      $('#configU').val('config: ' + json.keyevent.config);
    }
  }, function(errorCode, errorMessage) {
    showError('GET ondown', errorCode, errorMessage);
  });
}

/**
 * Show Up Event
 *
 * @param {String}serviceId サービスID
 */
function showUpEvent(serviceId) {
  initAll();
  setTitle('Up Event');

  var sessionKey = currentClientId;

  var btnStr = getBackButton('Device Top', 'doUpEventBack', serviceId,
                 sessionKey);
  reloadHeader(btnStr);
  reloadFooter(btnStr);

  var str = '';
  str += '<form name="upForm">';
  str += 'Up
';
  str += '<input type="text" id="idU" width="100%">';
  str += '<input type="text" id="configU" width="100%">';
  str += '</form>';
  reloadContent(str);

  doUpRegist(serviceId, sessionKey);
  dConnect.connectWebSocket(sessionKey, function(errorCode, errorMessage) {});
}

/**
 * Backボタン
 *
 * serviceId サービスID
 * sessionKey セッションKEY
 */
function doKeyEventBack(serviceId, sessionKey) {
  searchSystem(serviceId);
}

/**
 * Backボタン
 *
 * serviceId サービスID
 * sessionKey セッションKEY
 */
function doKeyBack(serviceId, sessionKey) {
  showKeyEvent(serviceId);
}

/**
 * Backボタン
 *
 * serviceId サービスID
 * sessionKey セッションKEY
 */
function doDownEventBack(serviceId, sessionKey) {
  doDownUnregister(serviceId, sessionKey);
  showKeyEvent(serviceId);
}

/**
 * Backボタン
 *
 * serviceId サービスID
 * sessionKey セッションKEY
 */
function doUpEventBack(serviceId, sessionKey) {
  doUpUnregister(serviceId, sessionKey);
  showKeyEvent(serviceId);
}

/**
 * Down Event Regist
 */
function doDownRegist(serviceId, sessionKey) {
  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('ondown');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  builder.setSessionKey(sessionKey);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri: ' + uri);
  }

  dConnect.addEventListener(uri, function(message) {
    // イベントメッセージが送られてくる
    if (DEBUG) {
      console.log('Event-Message:' + message)
    }

    var json = JSON.parse(message);
    if (json.keyevent) {
      $('#idD').val('KeyID: ' + json.keyevent.id);
      $('#configD').val('config: ' + json.keyevent.config);
    }
  }, null, function(errorCode, errorMessage) {
    alert(errorMessage);
  });
}

/**
 * Up Event Regist
 */
function doUpRegist(serviceId, sessionKey) {
  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('onup');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  builder.setSessionKey(sessionKey);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri: ' + uri);
  }

  dConnect.addEventListener(uri, function(message) {
    // イベントメッセージが送られてくる
    if (DEBUG) {
      console.log('Event-Message:' + message);
    }

    var json = JSON.parse(message);
    if (json.keyevent) {
      $('#idU').val('KeyID: ' + json.keyevent.id);
      $('#configU').val('config: ' + json.keyevent.config);
    }
  }, null, function(errorCode, errorMessage) {
    alert(errorMessage);
  });
}

/**
 * Down Event Unregist
 */
function doDownUnregister(serviceId, sessionKey) {

  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('ondown');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  builder.setSessionKey(sessionKey);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri : ' + uri);
  }

  dConnect.removeEventListener(uri, null, function(errorCode, errorMessage) {
    alert(errorMessage);
  });
}

/**
 * Up Event Unregist
 */
function doUpUnregister(serviceId, sessionKey) {

  var builder = new dConnect.URIBuilder();
  builder.setProfile('keyevent');
  builder.setAttribute('onup');
  builder.setServiceId(serviceId);
  builder.setAccessToken(accessToken);
  builder.setSessionKey(sessionKey);
  var uri = builder.build();
  if (DEBUG) {
    console.log('Uri : ' + uri);
  }

  dConnect.removeEventListener(uri, null, function(errorCode, errorMessage) {
    alert(errorMessage);
  });
}
<|endoftext|>