<commit_before>
// ----------------------------------------------------------------
// Static classes

class Log {
  // Common line setting
  static get LOG_LENGTH() { return 96; }
  static get LOG_CHARACTER() { return '-'; }

  // View permission
  static get LOG_VIEW() { return true; }
  static get LOG_VIEW_OBJECT() { return true; }
  static get LOG_VIEW_CLASS() { return true; }
  static get LOG_VIEW_CLASS_KEY() { return true; }
  static get LOG_VIEW_ERROR() { return true; }
  static get LOG_VIEW_CAUTION() { return true; }

  // Align definition
  static get ALIGN_LEFT() { return 0; }
  static get ALIGN_CENTER() { return 1; }
  static get ALIGN_RIGHT() { return 2; }

  // Arrow definition
  static get ARROW_OUTPUT() { return ' ---> '; }
  static get ARROW_INPUT() { return ' <--- '; }

  // Length definition
  static get CLASS_LENGTH() { return 24; }
  static get KEY_LENGTH() { return 24; }

  // Style definition
  static get STYLE_COLOR_RED() { return 'color:#f00;'; }
  static get STYLE_COLOR_GREEN() { return 'color:#0f0;'; }
  static get STYLE_COLOR_BLUE() { return 'color:#00f;'; }
  static get STYLE_COLOR_YELLOW() { return 'color:#ff0;'; }
  static get STYLE_COLOR_MAGENTA() { return 'color:#f0f;'; }
  static get STYLE_COLOR_CYAN() { return 'color:#0ff;'; }

  static get STYLE_CLASS() { return 'color:#222;'; }
  static get STYLE_KEY() { return 'color:#828;'; }
  static get STYLE_VALUE() { return 'color:#228;'; }

  static get STYLE_ERROR_LINE() { return 'color:#f00;'; }
  static get STYLE_ERROR_HEADER() { return 'color:#a00;'; }
  static get STYLE_ERROR_CONTENT() { return 'color:#111;'; }

  static get STYLE_CAUTION_LINE() { return 'color:#aa0;'; }
  static get STYLE_CAUTION_HEADER() { return 'color:#440;'; }
  static get STYLE_CAUTION_CONTENT() { return 'color:#111;'; }

  static logError(...array) {
    // View permission
    if (this.LOG_VIEW_ERROR) {
      // Draw line
      this.log(null, null, this.STYLE_ERROR_LINE);
      // Write title
      this.log('ERROR', this.ALIGN_CENTER, this.STYLE_ERROR_HEADER);
      // Write array
      for (let i = 0; i < array.length; i++) {
        this.log(array[i], this.ALIGN_LEFT, this.STYLE_ERROR_CONTENT);
      }
      // Draw line
      this.log(null, null, this.STYLE_ERROR_LINE);
    }
  }

  static logCaution(...array) {
    // View permission
    if (this.LOG_VIEW_CAUTION) {
      // Draw line
      this.log(null, null, this.STYLE_CAUTION_LINE);
      // Write title
      this.log('CAUTION', this.ALIGN_CENTER, this.STYLE_CAUTION_HEADER);
      // Write array
      for (let i = 0; i < array.length; i++) {
        this.log(array[i], this.ALIGN_LEFT, this.STYLE_CAUTION_CONTENT);
      }
      // Draw line
      this.log(null, null, this.STYLE_CAUTION_LINE);
    }
  }

  static logObj(_obj) {
    // View permission
    if (this.LOG_VIEW_OBJECT) {
      // Write object
      console.log(_obj);
    }
  }

  static logClass(_class = 'Class', _value = 'value', _style1 = this.STYLE_CLASS, _style2 = this.STYLE_VALUE) {
    // View permission
    if (this.LOG_VIEW_CLASS) {
      // Set style
      let result = '%c';
      // Write class
      result += _class;
      // Set spacing
      const classLength = _class.length;
      for (let i = 0; i < this.CLASS_LENGTH - classLength; i++) {
        result += ' ';
      }
      // Set style
      result += ': %c';
      // Write value
      result += _value;

      // Write result
      console.log(result, _style1, _style2);
    }
  }

  static logClassKey(_class = 'Class', _key = 'key', _value = 'value', _arrow = Log.ARROW_OUTPUT, _style1 = this.STYLE_CLASS, _style2 = this.STYLE_KEY, _style3 = this.STYLE_VALUE) {
    // View permission
    if (this.LOG_VIEW_CLASS_KEY) {
      // Set style
      let result = '%c';
      // Write class
      result += _class;
      // Set spacing
      const classLength = _class.length;
      for (let i = 0; i < this.CLASS_LENGTH - classLength; i++) {
        result += ' ';
      }
      // Set style
      result += ': %c';
      // Write key
      result += _key;
      // Set spacing
      const keyLength = _key.length;
      for (let i = 0; i < this.KEY_LENGTH - keyLength; i++) {
        result += ' ';
      }
      // Set style
      result += '%c';
      // Write arrow
      result += _arrow;
      // Set style
      result += '%c';
      // Write value
      result += _value;

      // Write result
      console.log(result, _style1, _style2, this.STYLE_RESET, _style3);
    }
  }

  static log(_string, _align = this.ALIGN_LEFT, _style = this.STYLE_RESET) {
    // View permission
    if (this.LOG_VIEW) {
      let result = '';

      // String is null
      if (_string == null) {
        // Draw line
        for (let i = 0; i < this.LOG_LENGTH; i++) {
          result += this.LOG_CHARACTER;

        }
        // String exists
      } else {
        // Align left
        if (_align == this.ALIGN_LEFT) {
          // Write string
          result = _string;

          // Align center
        } else if (_align == this.ALIGN_CENTER) {
          // Set spacing
          const strLength = _string.length;
          for (let i = 0; i < (this.LOG_LENGTH / 2) - (strLength / 2); i++) {
            result += ' ';
          }
          // Write string
          result += _string;

          // Align right
        } else if (_align == this.ALIGN_RIGHT) {
          // Set spacing
          const strLength = _string.length;
          for (let i = 0; i < this.LOG_LENGTH - strLength; i++) {
            result += ' ';
          }
          // Write string
          result += _string;
        }
      }

      // Set style
      // Write result
      console.log(`%c${result}`, _style);
    }
  }
}

class LocalStorage {
  // Check localStorage support
  static get SUPPORT() {
    let result = true;
    if (!localStorage) {
      result = false;
    }
    return result;
  }

  // Build key
  static buildKey(_key) {
      return `${Project.NAME_KEY}.${_key}`;
  }

  // All clear localStorage
  static clear() {
    // Check support
    if (this.SUPPORT) {
      Log.logClass('Local Storage', 'All Clear.');
      // Clear
      localStorage.clear();
    }
  }

  // getItem from localStorage
  static getItem(_key = 'key') {
    _key = this.buildKey(_key);
    // Check support
    if (this.SUPPORT) {
      const _val = localStorage.getItem(_key);
      Log.logClassKey('Local Storage', _key, _val, Log.ARROW_OUTPUT);
      // Get
      return _val;
    }
  }

  // setItem from localStorage
  static setItem(_key = 'key', _val = 'value') {
    _key = this.buildKey(_key);
    // Check support
    if (this.SUPPORT) {
      Log.logClassKey('Local Storage', _key, _val, Log.ARROW_INPUT);
      // Set
      localStorage.setItem(_key, _val);
    }
  }

  // removeItem from localStorage
  static removeItem(_key = 'key') {
    _key = this.buildKey(_key);
    // Check support
    if (this.SUPPORT) {
      Log.logClassKey('Local Storage', _key, 'null', Log.ARROW_INPUT);
      // Remove
      localStorage.removeItem(_key);
    }
  }
}

class SHA256 {
  static getHash(_string = null) {
    if (_string != null) {
      let shaObject = new jsSHA("SHA-256", "TEXT", 1);
      shaObject.update(_string);
      return shaObject.getHash("HEX");
    }
    return null;
  }
}

class Validate {
  static checkMaxLength(
    _string = null,
    _digit = null
  ) {
    if (_string != null && _digit != null) {
      if (_string.length <= _digit) {
        return true;
      }
    }
    return false;
  }

  static checkMinLength(
    _string = null,
    _digit = null
  ) {
    if (_string != null && _digit != null) {
      if (_string.length >= _digit) {
        return true;
      }
    }
    return false;
  }

  static checkIncludeNumber(
    _string = null
  ) {
    if (_string != null) {
      if (_string.match(/[0-9]/)) {
        return true;
      }
    }
    return false;
  }
}
<commit_msg>Add function checkIncludeAlphabet to Validate<commit_after>
// ----------------------------------------------------------------
// Static classes

class Log {
  // Common line setting
  static get LOG_LENGTH() { return 96; }
  static get LOG_CHARACTER() { return '-'; }

  // View permission
  static get LOG_VIEW() { return true; }
  static get LOG_VIEW_OBJECT() { return true; }
  static get LOG_VIEW_CLASS() { return true; }
  static get LOG_VIEW_CLASS_KEY() { return true; }
  static get LOG_VIEW_ERROR() { return true; }
  static get LOG_VIEW_CAUTION() { return true; }

  // Align definition
  static get ALIGN_LEFT() { return 0; }
  static get ALIGN_CENTER() { return 1; }
  static get ALIGN_RIGHT() { return 2; }

  // Arrow definition
  static get ARROW_OUTPUT() { return ' ---> '; }
  static get ARROW_INPUT() { return ' <--- '; }

  // Length definition
  static get CLASS_LENGTH() { return 24; }
  static get KEY_LENGTH() { return 24; }

  // Style definition
  static get STYLE_COLOR_RED() { return 'color:#f00;'; }
  static get STYLE_COLOR_GREEN() { return 'color:#0f0;'; }
  static get STYLE_COLOR_BLUE() { return 'color:#00f;'; }
  static get STYLE_COLOR_YELLOW() { return 'color:#ff0;'; }
  static get STYLE_COLOR_MAGENTA() { return 'color:#f0f;'; }
  static get STYLE_COLOR_CYAN() { return 'color:#0ff;'; }

  static get STYLE_CLASS() { return 'color:#222;'; }
  static get STYLE_KEY() { return 'color:#828;'; }
  static get STYLE_VALUE() { return 'color:#228;'; }

  static get STYLE_ERROR_LINE() { return 'color:#f00;'; }
  static get STYLE_ERROR_HEADER() { return 'color:#a00;'; }
  static get STYLE_ERROR_CONTENT() { return 'color:#111;'; }

  static get STYLE_CAUTION_LINE() { return 'color:#aa0;'; }
  static get STYLE_CAUTION_HEADER() { return 'color:#440;'; }
  static get STYLE_CAUTION_CONTENT() { return 'color:#111;'; }

  static logError(...array) {
    // View permission
    if (this.LOG_VIEW_ERROR) {
      // Draw line
      this.log(null, null, this.STYLE_ERROR_LINE);
      // Write title
      this.log('ERROR', this.ALIGN_CENTER, this.STYLE_ERROR_HEADER);
      // Write array
      for (let i = 0; i < array.length; i++) {
        this.log(array[i], this.ALIGN_LEFT, this.STYLE_ERROR_CONTENT);
      }
      // Draw line
      this.log(null, null, this.STYLE_ERROR_LINE);
    }
  }

  static logCaution(...array) {
    // View permission
    if (this.LOG_VIEW_CAUTION) {
      // Draw line
      this.log(null, null, this.STYLE_CAUTION_LINE);
      // Write title
      this.log('CAUTION', this.ALIGN_CENTER, this.STYLE_CAUTION_HEADER);
      // Write array
      for (let i = 0; i < array.length; i++) {
        this.log(array[i], this.ALIGN_LEFT, this.STYLE_CAUTION_CONTENT);
      }
      // Draw line
      this.log(null, null, this.STYLE_CAUTION_LINE);
    }
  }

  static logObj(_obj) {
    // View permission
    if (this.LOG_VIEW_OBJECT) {
      // Write object
      console.log(_obj);
    }
  }

  static logClass(_class = 'Class', _value = 'value', _style1 = this.STYLE_CLASS, _style2 = this.STYLE_VALUE) {
    // View permission
    if (this.LOG_VIEW_CLASS) {
      // Set style
      let result = '%c';
      // Write class
      result += _class;
      // Set spacing
      const classLength = _class.length;
      for (let i = 0; i < this.CLASS_LENGTH - classLength; i++) {
        result += ' ';
      }
      // Set style
      result += ': %c';
      // Write value
      result += _value;

      // Write result
      console.log(result, _style1, _style2);
    }
  }

  static logClassKey(_class = 'Class', _key = 'key', _value = 'value', _arrow = Log.ARROW_OUTPUT, _style1 = this.STYLE_CLASS, _style2 = this.STYLE_KEY, _style3 = this.STYLE_VALUE) {
    // View permission
    if (this.LOG_VIEW_CLASS_KEY) {
      // Set style
      let result = '%c';
      // Write class
      result += _class;
      // Set spacing
      const classLength = _class.length;
      for (let i = 0; i < this.CLASS_LENGTH - classLength; i++) {
        result += ' ';
      }
      // Set style
      result += ': %c';
      // Write key
      result += _key;
      // Set spacing
      const keyLength = _key.length;
      for (let i = 0; i < this.KEY_LENGTH - keyLength; i++) {
        result += ' ';
      }
      // Set style
      result += '%c';
      // Write arrow
      result += _arrow;
      // Set style
      result += '%c';
      // Write value
      result += _value;

      // Write result
      console.log(result, _style1, _style2, this.STYLE_RESET, _style3);
    }
  }

  static log(_string, _align = this.ALIGN_LEFT, _style = this.STYLE_RESET) {
    // View permission
    if (this.LOG_VIEW) {
      let result = '';

      // String is null
      if (_string == null) {
        // Draw line
        for (let i = 0; i < this.LOG_LENGTH; i++) {
          result += this.LOG_CHARACTER;

        }
        // String exists
      } else {
        // Align left
        if (_align == this.ALIGN_LEFT) {
          // Write string
          result = _string;

          // Align center
        } else if (_align == this.ALIGN_CENTER) {
          // Set spacing
          const strLength = _string.length;
          for (let i = 0; i < (this.LOG_LENGTH / 2) - (strLength / 2); i++) {
            result += ' ';
          }
          // Write string
          result += _string;

          // Align right
        } else if (_align == this.ALIGN_RIGHT) {
          // Set spacing
          const strLength = _string.length;
          for (let i = 0; i < this.LOG_LENGTH - strLength; i++) {
            result += ' ';
          }
          // Write string
          result += _string;
        }
      }

      // Set style
      // Write result
      console.log(`%c${result}`, _style);
    }
  }
}

class LocalStorage {
  // Check localStorage support
  static get SUPPORT() {
    let result = true;
    if (!localStorage) {
      result = false;
    }
    return result;
  }

  // Build key
  static buildKey(_key) {
      return `${Project.NAME_KEY}.${_key}`;
  }

  // All clear localStorage
  static clear() {
    // Check support
    if (this.SUPPORT) {
      Log.logClass('Local Storage', 'All Clear.');
      // Clear
      localStorage.clear();
    }
  }

  // getItem from localStorage
  static getItem(_key = 'key') {
    _key = this.buildKey(_key);
    // Check support
    if (this.SUPPORT) {
      const _val = localStorage.getItem(_key);
      Log.logClassKey('Local Storage', _key, _val, Log.ARROW_OUTPUT);
      // Get
      return _val;
    }
  }

  // setItem from localStorage
  static setItem(_key = 'key', _val = 'value') {
    _key = this.buildKey(_key);
    // Check support
    if (this.SUPPORT) {
      Log.logClassKey('Local Storage', _key, _val, Log.ARROW_INPUT);
      // Set
      localStorage.setItem(_key, _val);
    }
  }

  // removeItem from localStorage
  static removeItem(_key = 'key') {
    _key = this.buildKey(_key);
    // Check support
    if (this.SUPPORT) {
      Log.logClassKey('Local Storage', _key, 'null', Log.ARROW_INPUT);
      // Remove
      localStorage.removeItem(_key);
    }
  }
}

class SHA256 {
  static getHash(_string = null) {
    if (_string != null) {
      let shaObject = new jsSHA("SHA-256", "TEXT", 1);
      shaObject.update(_string);
      return shaObject.getHash("HEX");
    }
    return null;
  }
}

class Validate {
  static checkMaxLength(
    _string = null,
    _digit = null
  ) {
    if (_string != null && _digit != null) {
      if (_string.length <= _digit) {
        return true;
      }
    }
    return false;
  }

  static checkMinLength(
    _string = null,
    _digit = null
  ) {
    if (_string != null && _digit != null) {
      if (_string.length >= _digit) {
        return true;
      }
    }
    return false;
  }

  static checkIncludeNumber(
    _string = null
  ) {
    if (_string != null) {
      if (_string.match(/[0-9]/)) {
        return true;
      }
    }
    return false;
  }

  static checkIncludeAlphabet(
    _string = null
  ) {
    if (_string != null) {
      if (_string.match(/[a-zA-Z]/)) {
        return true;
      }
    }
    return false;
  }
}
<|endoftext|>


<commit_before>$(function(){

  $( document ).ready(function(){
    //code to call the github api and get the files from the "projects" folder

    path = "projects";

    projects_count = 0;
    projects_content = new Array();

    /* PERSONALIZE THIS CONTENT FOR YOUR FORKED COPY */
    // List of repositories in the format ["repository_user", "repository_name"]
    // EG:  ["gscardine", "Projects"] and ["OpenInnovationNetwork", "Projects"],
    // Example: in github.com/OpenInnovationNetwork/Projects/, it is "OpenInnovationNetwork"
    //     repository_user = "OpenInnovationNetwork"
    //     repository_name = "Projects"
    repository_list = [
      ["StandardLaw", "Projects"],
      ["CIVICS", "Projects"],
      ["natashanelson", "Projects"]

    ];

    // int i = 0;
    for (var i = 0; i < repository_list.length; i++) {
      repository_user = repository_list[i][0];
      repository_name = repository_list[i][1];

      // FIND ALL THE FILES INSIDE THE FOLDER
      $.ajax({
        url: "https://api.github.com/repos/"+repository_user+"/"+repository_name+"/contents/"+path,
        method: "get"
      })
      .success(function(allFiles){

        $.each(allFiles, function (index, value) {
          // GET CONTENT OF EACH JSON FILE
          if ((value.type == "file") && (value.name.split('.').pop() == "json")) {

            projects_count++;

            $.ajax({
              url: value.url,
              method: "get"
            })
            .success(function( fileResponse ) {
              // PARSE CONTENT
              base64decoded = atob(fileResponse.content);

              try {
                json_content = jQuery.parseJSON(base64decoded);

                // Add to list of contents
                if (json_content.project_name && json_content.project_blurb) {
                  projects_content.push(json_content);
                }
              } catch (e) {
                // invalid json
              }
            })
            .fail(function($xhr) {
                var data = $xhr.responseJSON;
                console.log(data);
            });
          }
        });
      });
    }

    // THE CONTENT OF ALL FILES WAS RETRIEVED
    $(document).ajaxStop(function() {
      console.log('All '+ projects_count +' projects retrieved');

      // Remove preloader image
      $('#projects-list').empty();

      // SHOW CONTENT AS CARDS
      $.each(projects_content, function (index, json_content) {
        template = new Array();
        if (index % 3 == 0) {
          $('#projects-list').append('
');
        }

        project_people = project_thumbnail = project_url = project_demo_url = "";

    		if ((json_content.project_people != undefined) && (json_content.project_people != "")) {
          project_people = '

People: '+json_content.project_people+'
';
        }

    		if ((json_content.project_demo_url) && (json_content.project_demo_url != undefined)) {
          project_demo_url = '

Demo: '+json_content.project_demo_url+'
';
        }

    		if ((json_content.project_thumbnail != undefined) && (json_content.project_thumbnail != "")) {
          project_thumbnail = '';
        }

        if ((json_content.project_url != undefined) && (json_content.project_url != "")) {
          project_url = '
Project: '+json_content.project_url+'
';
        }

        $('#projects-list').append(
            '
 '+
              '
 ' +
                '
 ' +
					        project_thumbnail+
                  '
'+json_content.project_name+'
 '+
                  '
'+json_content.project_blurb+'
'+
        				  '

' +
        					  project_people +
        					  project_url +
        					  project_demo_url +
        				  '
 '+
                '
 '+
              '
 '+
            '
'
        );

        if (index % 3 == 2) {
          $('#projects-list').append('
');
        }

      });
    });

  });
});
<commit_msg>Update projects_retrieval.js<commit_after>$(function(){

  $( document ).ready(function(){
    //code to call the github api and get the files from the "projects" folder

    path = "projects";

    projects_count = 0;
    projects_content = new Array();

    /* PERSONALIZE THIS CONTENT FOR YOUR FORKED COPY */
    // List of repositories in the format ["repository_user", "repository_name"]
    // EG:  ["gscardine", "Projects"] and ["OpenInnovationNetwork", "Projects"],
    // Example: in github.com/OpenInnovationNetwork/Projects/, it is "OpenInnovationNetwork"
    //     repository_user = "OpenInnovationNetwork"
    //     repository_name = "Projects"
    repository_list = [
      ["StandardLaw", "Projects"],
      ["CIVICS", "Projects"],
      ["LawasCode", "Projects"],
      ["natashanelson", "Projects"]

    ];

    // int i = 0;
    for (var i = 0; i < repository_list.length; i++) {
      repository_user = repository_list[i][0];
      repository_name = repository_list[i][1];

      // FIND ALL THE FILES INSIDE THE FOLDER
      $.ajax({
        url: "https://api.github.com/repos/"+repository_user+"/"+repository_name+"/contents/"+path,
        method: "get"
      })
      .success(function(allFiles){

        $.each(allFiles, function (index, value) {
          // GET CONTENT OF EACH JSON FILE
          if ((value.type == "file") && (value.name.split('.').pop() == "json")) {

            projects_count++;

            $.ajax({
              url: value.url,
              method: "get"
            })
            .success(function( fileResponse ) {
              // PARSE CONTENT
              base64decoded = atob(fileResponse.content);

              try {
                json_content = jQuery.parseJSON(base64decoded);

                // Add to list of contents
                if (json_content.project_name && json_content.project_blurb) {
                  projects_content.push(json_content);
                }
              } catch (e) {
                // invalid json
              }
            })
            .fail(function($xhr) {
                var data = $xhr.responseJSON;
                console.log(data);
            });
          }
        });
      });
    }

    // THE CONTENT OF ALL FILES WAS RETRIEVED
    $(document).ajaxStop(function() {
      console.log('All '+ projects_count +' projects retrieved');

      // Remove preloader image
      $('#projects-list').empty();

      // SHOW CONTENT AS CARDS
      $.each(projects_content, function (index, json_content) {
        template = new Array();
        if (index % 3 == 0) {
          $('#projects-list').append('
');
        }

        project_people = project_thumbnail = project_url = project_demo_url = "";

    		if ((json_content.project_people != undefined) && (json_content.project_people != "")) {
          project_people = '

People: '+json_content.project_people+'
';
        }

    		if ((json_content.project_demo_url) && (json_content.project_demo_url != undefined)) {
          project_demo_url = '

Demo: '+json_content.project_demo_url+'
';
        }

    		if ((json_content.project_thumbnail != undefined) && (json_content.project_thumbnail != "")) {
          project_thumbnail = '';
        }

        if ((json_content.project_url != undefined) && (json_content.project_url != "")) {
          project_url = '
Project: '+json_content.project_url+'
';
        }

        $('#projects-list').append(
            '
 '+
              '
 ' +
                '
 ' +
					        project_thumbnail+
                  '
'+json_content.project_name+'
 '+
                  '
'+json_content.project_blurb+'
'+
        				  '

' +
        					  project_people +
        					  project_url +
        					  project_demo_url +
        				  '
 '+
                '
 '+
              '
 '+
            '
'
        );

        if (index % 3 == 2) {
          $('#projects-list').append('
');
        }

      });
    });

  });
});
<|endoftext|>


<commit_before>// twister_formatpost.js
// 2013 Miguel Freitas
//
// Format JSON posts and DMs to HTML.

// format "userpost" to html element
// kind = "original"/"ancestor"/"descendant"
function postToElem( post, kind, promoted ) {
    /*
    "userpost" :
    {
            "n" : username,
            "k" : seq number,
            "t" : "post" / "dm" / "rt"
            "msg" : message (post/rt)
            "time" : unix utc
            "height" : best height at user
            "dm" : encrypted message (dm) -opt
            "rt" : original userpost - opt
            "sig_rt" : sig of rt - opt
            "reply" : - opt
            {
                    "n" : reference username
                    "k" : reference k
            }
    }
    "sig_userpost" : signature by userpost.n
    */

    // Obtain data from userpost
    var postJson = $.toJSON(post);
    var userpost = post["userpost"];
    if( "rt" in userpost ) {
        var rt = userpost["rt"];
        var n = rt["n"];
        var k = rt["k"];
        var t = rt["time"];
        var msg = rt["msg"];
        var content_to_rt = $.toJSON(rt);
        var content_to_sigrt = userpost["sig_rt"];
        var retweeted_by = userpost["n"];
    } else {
        var n = userpost["n"];
        var k = userpost["k"];
        var t = userpost["time"];
        var msg = userpost["msg"]
        var content_to_rt = $.toJSON(userpost);
        var content_to_sigrt = post["sig_userpost"];
        var retweeted_by = undefined;
    }

    // Now create the html elements
    var elem = $.MAL.getPostTemplate().clone(true);
    elem.removeAttr('id');
    elem.addClass(kind);
    elem.attr('data-time', t);

    if( post["isNew"] )
        elem.addClass('new');

    var postData = elem.find(".post-data");
    postData.addClass(kind);
    postData.attr('data-userpost', postJson);
    postData.attr('data-content_to_rt', content_to_rt);
    postData.attr('data-content_to_sigrt', content_to_sigrt);
    postData.attr('data-screen-name', n);
    postData.attr('data-id', k);
    postData.attr('data-lastk', userpost["lastk"]);
    postData.attr('data-text', msg);
    if( "reply" in userpost ) {
        postData.attr('data-replied-to-screen-name', userpost["reply"]["n"]);
        postData.attr('data-replied-to-id', userpost["reply"]["k"]);

        postData.find('.post-expand').text(polyglot.t("Show conversation"));
    } else if ( "rt" in userpost && "reply" in userpost["rt"] ) {
        postData.attr('data-replied-to-screen-name', userpost["rt"]["reply"]["n"]);
        postData.attr('data-replied-to-id', userpost["rt"]["reply"]["k"]);

        postData.find('.post-expand').text(polyglot.t("Show conversation"));
    }

    var postInfoName = elem.find(".post-info-name");
    postInfoName.attr('href',$.MAL.userUrl(n));
    postInfoName.text(n);
    getFullname( n, postInfoName );
    elem.find(".post-info-tag").text = "@" + n;
    getAvatar( n, elem.find(".avatar") );
    elem.find(".post-info-time").text(timeGmtToText(t));
    elem.find(".post-info-time").attr("title",timeSincePost(t));

    var mentions = [];
    htmlFormatMsg( msg, elem.find(".post-text"), mentions);
    postData.attr('data-text-mentions', mentions);

    var replyTo = "";
    if( n != defaultScreenName )
        replyTo += "@" + n + " ";
    for( var i = 0; i < mentions.length; i++ ) {
        if( mentions[i] != n && mentions[i] != defaultScreenName ) {
            replyTo += "@" + mentions[i] + " ";
        }
    }
    if(!defaultScreenName)
    {
	elem.find(".post-area-new textarea").attr("placeholder", polyglot.t("You have to log in to post replies."));
    }
    else
    {
	elem.find(".post-area-new textarea").attr("placeholder", polyglot.t("reply_to", { fullname: replyTo })+ "...");
    }
    elem.find(".post-area-new textarea").attr("data-reply-to",replyTo);
    postData.attr("data-reply-to",replyTo);

    if( retweeted_by != undefined ) {
        elem.find(".post-context").show();
        var retweetedByElem = elem.find(".post-retransmited-by");
        retweetedByElem.attr("href", $.MAL.userUrl(retweeted_by));
        retweetedByElem.text('@'+retweeted_by);
    }

    if (typeof(promoted) !== 'undefined' && promoted)
        elem.find('.post-propagate').remove();

    return elem;
}

// format dmdata (returned by getdirectmsgs) to display in "snippet" per user list
function dmDataToSnippetItem(dmData, remoteUser) {
    var dmItem = $("#dm-snippet-template").clone(true);
    dmItem.removeAttr('id');
    dmItem.attr("data-dm-screen-name",remoteUser);
    dmItem.attr("data-last_id", dmData.id);
    dmItem.attr("data-time", dmData.time);

    dmItem.find(".post-info-tag").text("@" + remoteUser);
    dmItem.find("a.post-info-name").attr("href", $.MAL.userUrl(remoteUser));
    dmItem.find("a.dm-chat-link").attr("href", $.MAL.dmchatUrl(remoteUser));
    getAvatar( remoteUser, dmItem.find(".post-photo").find("img") );
    getFullname( remoteUser, dmItem.find("a.post-info-name") );
    dmItem.find(".post-text").html(escapeHtmlEntities(dmData.text));
    dmItem.find(".post-info-time").text(timeGmtToText(dmData.time));
    dmItem.find(".post-info-time").attr("title",timeSincePost(dmData.time));

    return dmItem;
}

// format dmdata (returned by getdirectmsgs) to display in conversation thread
function dmDataToConversationItem(dmData, localUser, remoteUser) {
    var classDm = dmData.fromMe ? "sent" : "received";
    var dmItem = $("#dm-chat-template").clone(true);
    dmItem.removeAttr('id');
    dmItem.addClass(classDm);
    getAvatar(dmData.fromMe ? localUser : remoteUser, dmItem.find(".post-photo").find("img") );
    dmItem.find(".post-info-time").text(timeGmtToText(dmData.time));
    dmItem.find(".post-info-time").attr("title",timeSincePost(dmData.time));
    var mentions = [];
    htmlFormatMsg( dmData.text, dmItem.find(".post-text"), mentions);
    return dmItem;
}

// convert message text to html, featuring @users and links formating.
// todo: hashtags
function htmlFormatMsg( msg, output, mentions ) {
    var tmp;
    var match = null;
    var index;
    var strUrlRegexp = "http[s]?://";
    var strEmailRegexp = "\\S+@\\S+\\.\\S+";
    var strSplitCounterR = "\\(\\d{1,2}\\/\\d{1,2}\\)$";
    var reAll = new RegExp("(?:^|[ \\n\\t.,:\\/?!])(#|@|" + strUrlRegexp + "|" + strEmailRegexp + "|" + strSplitCounterR + ")");
    var reHttp = new RegExp(strUrlRegexp);
    var reEmail = new RegExp(strEmailRegexp);
    var reSplitCounter = new RegExp(strSplitCounterR);

    msg = escapeHtmlEntities(msg);

    while( msg != undefined && msg.length ) {

        match = reAll.exec(msg);
        if( match ) {
            index = (match[0] === match[1]) ? match.index : match.index + 1;
            if( match[1] == "@" ) {
                output.append(_formatText(msg.substr(0, index)));
                tmp = msg.substr(index+1);
                var username = _extractUsername(tmp);
                if( username.length ) {
                    if( mentions.indexOf(username) < 0 )
                        mentions.push(username);
                    var userLinkTemplate = $("#msg-user-link-template").clone(true);
                    userLinkTemplate.removeAttr("id");
                    userLinkTemplate.attr("href",$.MAL.userUrl(username));
                    userLinkTemplate.text("@"+username);
                    output.append(userLinkTemplate);
                    msg = tmp.substr(String(username).length);
                    continue;
                }
                output.append('@');
                msg = tmp;
                continue;
            }

            if( reHttp.exec(match[1]) ) {
                output.append(_formatText(msg.substr(0, index)));
                tmp = msg.substring(index);
                var space = tmp.search(/[ \n\t]/);
                var url;
                if( space != -1 ) url = tmp.substring(0,space); else url = tmp;
                if( url.length ) {
                    msg = tmp.substr(String(url).length);
                    url = reverseHtmlEntities(url);
                    var extLinkTemplate = $("#external-page-link-template").clone(true);
                    extLinkTemplate.removeAttr("id");

                    if ($.Options.getUseProxyOpt() !== 'disable' && !$.Options.getUseProxyForImgOnlyOpt()){
                        //proxy alternatives may be added to options page...
                        if ($.Options.getUseProxyOpt() === 'ssl-proxy-my-addr') {
                            extLinkTemplate.attr('href', 'https://ssl-proxy.my-addr.org/myaddrproxy.php/' +
                                                         url.substring(0, url.indexOf(':')) +
                                                         url.substr(url.indexOf('/') + 1));
                        } else if ($.Options.getUseProxyOpt() ==='anonymouse') {
                            extLinkTemplate.attr('href', 'http://anonymouse.org/cgi-bin/anon-www.cgi/' + url);
                        }
                    } else {
                        extLinkTemplate.attr("href",url);
                    }

                    extLinkTemplate.text(url);
                    extLinkTemplate.attr("title",url);
                    output.append(extLinkTemplate);
                    continue;
                }
            }

            if( reEmail.exec(match[1]) ) {
                output.append(_formatText(msg.substr(0, index)));
                tmp = msg.substring(index);
                var space = tmp.search(/[ \n\t]/);
                var email;
                if( space != -1 ) email = tmp.substring(0,space); else email = tmp;
                if( email.length ) {
                    var extLinkTemplate = $("#external-page-link-template").clone(true);
                    extLinkTemplate.removeAttr("id");
                    extLinkTemplate.attr("href","mailto:" + email);
                    extLinkTemplate.text(email);
                    extLinkTemplate.attr("title",email);
                    output.append(extLinkTemplate);
                    msg = tmp.substr(String(email).length);
                    continue;
                }
            }

            if( match[1] == "#" ) {
                output.append(_formatText(msg.substr(0, index)));
                tmp = msg.substr(index+1);
                var hashtag = _extractHashtag(tmp);
                if( hashtag.length ) {
                    var hashtag_lc='';
                    for( var i = 0; i < hashtag.length; i++ ) {
                        var c = hashtag[i];
                        hashtag_lc += (c >= 'A' && c <= 'Z') ? c.toLowerCase() : c;
                    }
                    var hashtagLinkTemplate = $("#hashtag-link-template").clone(true);
                    hashtagLinkTemplate.removeAttr("id");
                    hashtagLinkTemplate.attr("href",$.MAL.hashtagUrl(hashtag_lc));
                    hashtagLinkTemplate.text("#"+hashtag);
                    output.append(hashtagLinkTemplate);
                    msg = tmp.substr(String(hashtag).length);
                    continue;
                }
                output.append('#');
                msg = tmp;
                continue;
            }

            if (reSplitCounter.exec(match[1])) {
                output.append(_formatText(msg.substr(0, index)));
                tmp = msg.substring(index);
                if( tmp.length ) {
                    var splitCounter = $('');
                    splitCounter.text(tmp);
                    output.append(splitCounter);
                    msg = "";
                    continue;
                }
            }
        }

        output.append(_formatText(msg));
        msg = "";
    }
}

// internal function for htmlFormatMsg
function _formatText(msg)
{
    // TODO: add options for emotions and linefeeds
    //msg = $.emotions(msg);
    if( $.Options.getLineFeedsOpt() == "enable" )
        msg = msg.replace(/\n/g, '
');
    return msg;
}

function _extractUsername(s) {
    var username = "";
    for( var i = 0; i < s.length; i++ ) {
        var c = s.charCodeAt(i);
        if( (c >= 'a'.charCodeAt(0) && c <= 'z'.charCodeAt(0)) ||
            (c >= 'A'.charCodeAt(0) && c <= 'Z'.charCodeAt(0)) ||
            (c >= '0'.charCodeAt(0) && c <= '9'.charCodeAt(0)) ||
            c == '_'.charCodeAt(0) ) {
            username += s[i];
        } else {
            break;
        }
    }
    return username.toLowerCase();
}

// internal function for htmlFormatMsg
function _extractHashtag(s) {
    var hashtag = "";
    s = reverseHtmlEntities(s);
    for( var i = 0; i < s.length; i++ ) {
        if( " \n\t.,:/?!;'\"()[]{}*#".indexOf(s[i]) < 0 ) {
            hashtag += s[i];
        } else {
            break;
        }
    }
    return hashtag;
}

function escapeHtmlEntities(str) {
    return str
                .replace(/&/g, '&')
                .replace(/</g, '<')
                .replace(/>/g, '>')
                .replace(/"/g, '"')
                .replace(/'/g, ''');
}

function reverseHtmlEntities(str) {
    return str
                .replace(/&/g, '&')
                .replace(/</g, '<')
                .replace(/>/g, '>')
                .replace(/"/g, '"')
                .replace(/'/g, "'");
}

<commit_msg>& should be reversed last (to correctly transform "&lt;" to "<" and not to "<")<commit_after>// twister_formatpost.js
// 2013 Miguel Freitas
//
// Format JSON posts and DMs to HTML.

// format "userpost" to html element
// kind = "original"/"ancestor"/"descendant"
function postToElem( post, kind, promoted ) {
    /*
    "userpost" :
    {
            "n" : username,
            "k" : seq number,
            "t" : "post" / "dm" / "rt"
            "msg" : message (post/rt)
            "time" : unix utc
            "height" : best height at user
            "dm" : encrypted message (dm) -opt
            "rt" : original userpost - opt
            "sig_rt" : sig of rt - opt
            "reply" : - opt
            {
                    "n" : reference username
                    "k" : reference k
            }
    }
    "sig_userpost" : signature by userpost.n
    */

    // Obtain data from userpost
    var postJson = $.toJSON(post);
    var userpost = post["userpost"];
    if( "rt" in userpost ) {
        var rt = userpost["rt"];
        var n = rt["n"];
        var k = rt["k"];
        var t = rt["time"];
        var msg = rt["msg"];
        var content_to_rt = $.toJSON(rt);
        var content_to_sigrt = userpost["sig_rt"];
        var retweeted_by = userpost["n"];
    } else {
        var n = userpost["n"];
        var k = userpost["k"];
        var t = userpost["time"];
        var msg = userpost["msg"]
        var content_to_rt = $.toJSON(userpost);
        var content_to_sigrt = post["sig_userpost"];
        var retweeted_by = undefined;
    }

    // Now create the html elements
    var elem = $.MAL.getPostTemplate().clone(true);
    elem.removeAttr('id');
    elem.addClass(kind);
    elem.attr('data-time', t);

    if( post["isNew"] )
        elem.addClass('new');

    var postData = elem.find(".post-data");
    postData.addClass(kind);
    postData.attr('data-userpost', postJson);
    postData.attr('data-content_to_rt', content_to_rt);
    postData.attr('data-content_to_sigrt', content_to_sigrt);
    postData.attr('data-screen-name', n);
    postData.attr('data-id', k);
    postData.attr('data-lastk', userpost["lastk"]);
    postData.attr('data-text', msg);
    if( "reply" in userpost ) {
        postData.attr('data-replied-to-screen-name', userpost["reply"]["n"]);
        postData.attr('data-replied-to-id', userpost["reply"]["k"]);

        postData.find('.post-expand').text(polyglot.t("Show conversation"));
    } else if ( "rt" in userpost && "reply" in userpost["rt"] ) {
        postData.attr('data-replied-to-screen-name', userpost["rt"]["reply"]["n"]);
        postData.attr('data-replied-to-id', userpost["rt"]["reply"]["k"]);

        postData.find('.post-expand').text(polyglot.t("Show conversation"));
    }

    var postInfoName = elem.find(".post-info-name");
    postInfoName.attr('href',$.MAL.userUrl(n));
    postInfoName.text(n);
    getFullname( n, postInfoName );
    elem.find(".post-info-tag").text = "@" + n;
    getAvatar( n, elem.find(".avatar") );
    elem.find(".post-info-time").text(timeGmtToText(t));
    elem.find(".post-info-time").attr("title",timeSincePost(t));

    var mentions = [];
    htmlFormatMsg( msg, elem.find(".post-text"), mentions);
    postData.attr('data-text-mentions', mentions);

    var replyTo = "";
    if( n != defaultScreenName )
        replyTo += "@" + n + " ";
    for( var i = 0; i < mentions.length; i++ ) {
        if( mentions[i] != n && mentions[i] != defaultScreenName ) {
            replyTo += "@" + mentions[i] + " ";
        }
    }
    if(!defaultScreenName)
    {
	elem.find(".post-area-new textarea").attr("placeholder", polyglot.t("You have to log in to post replies."));
    }
    else
    {
	elem.find(".post-area-new textarea").attr("placeholder", polyglot.t("reply_to", { fullname: replyTo })+ "...");
    }
    elem.find(".post-area-new textarea").attr("data-reply-to",replyTo);
    postData.attr("data-reply-to",replyTo);

    if( retweeted_by != undefined ) {
        elem.find(".post-context").show();
        var retweetedByElem = elem.find(".post-retransmited-by");
        retweetedByElem.attr("href", $.MAL.userUrl(retweeted_by));
        retweetedByElem.text('@'+retweeted_by);
    }

    if (typeof(promoted) !== 'undefined' && promoted)
        elem.find('.post-propagate').remove();

    return elem;
}

// format dmdata (returned by getdirectmsgs) to display in "snippet" per user list
function dmDataToSnippetItem(dmData, remoteUser) {
    var dmItem = $("#dm-snippet-template").clone(true);
    dmItem.removeAttr('id');
    dmItem.attr("data-dm-screen-name",remoteUser);
    dmItem.attr("data-last_id", dmData.id);
    dmItem.attr("data-time", dmData.time);

    dmItem.find(".post-info-tag").text("@" + remoteUser);
    dmItem.find("a.post-info-name").attr("href", $.MAL.userUrl(remoteUser));
    dmItem.find("a.dm-chat-link").attr("href", $.MAL.dmchatUrl(remoteUser));
    getAvatar( remoteUser, dmItem.find(".post-photo").find("img") );
    getFullname( remoteUser, dmItem.find("a.post-info-name") );
    dmItem.find(".post-text").html(escapeHtmlEntities(dmData.text));
    dmItem.find(".post-info-time").text(timeGmtToText(dmData.time));
    dmItem.find(".post-info-time").attr("title",timeSincePost(dmData.time));

    return dmItem;
}

// format dmdata (returned by getdirectmsgs) to display in conversation thread
function dmDataToConversationItem(dmData, localUser, remoteUser) {
    var classDm = dmData.fromMe ? "sent" : "received";
    var dmItem = $("#dm-chat-template").clone(true);
    dmItem.removeAttr('id');
    dmItem.addClass(classDm);
    getAvatar(dmData.fromMe ? localUser : remoteUser, dmItem.find(".post-photo").find("img") );
    dmItem.find(".post-info-time").text(timeGmtToText(dmData.time));
    dmItem.find(".post-info-time").attr("title",timeSincePost(dmData.time));
    var mentions = [];
    htmlFormatMsg( dmData.text, dmItem.find(".post-text"), mentions);
    return dmItem;
}

// convert message text to html, featuring @users and links formating.
// todo: hashtags
function htmlFormatMsg( msg, output, mentions ) {
    var tmp;
    var match = null;
    var index;
    var strUrlRegexp = "http[s]?://";
    var strEmailRegexp = "\\S+@\\S+\\.\\S+";
    var strSplitCounterR = "\\(\\d{1,2}\\/\\d{1,2}\\)$";
    var reAll = new RegExp("(?:^|[ \\n\\t.,:\\/?!])(#|@|" + strUrlRegexp + "|" + strEmailRegexp + "|" + strSplitCounterR + ")");
    var reHttp = new RegExp(strUrlRegexp);
    var reEmail = new RegExp(strEmailRegexp);
    var reSplitCounter = new RegExp(strSplitCounterR);

    msg = escapeHtmlEntities(msg);

    while( msg != undefined && msg.length ) {

        match = reAll.exec(msg);
        if( match ) {
            index = (match[0] === match[1]) ? match.index : match.index + 1;
            if( match[1] == "@" ) {
                output.append(_formatText(msg.substr(0, index)));
                tmp = msg.substr(index+1);
                var username = _extractUsername(tmp);
                if( username.length ) {
                    if( mentions.indexOf(username) < 0 )
                        mentions.push(username);
                    var userLinkTemplate = $("#msg-user-link-template").clone(true);
                    userLinkTemplate.removeAttr("id");
                    userLinkTemplate.attr("href",$.MAL.userUrl(username));
                    userLinkTemplate.text("@"+username);
                    output.append(userLinkTemplate);
                    msg = tmp.substr(String(username).length);
                    continue;
                }
                output.append('@');
                msg = tmp;
                continue;
            }

            if( reHttp.exec(match[1]) ) {
                output.append(_formatText(msg.substr(0, index)));
                tmp = msg.substring(index);
                var space = tmp.search(/[ \n\t]/);
                var url;
                if( space != -1 ) url = tmp.substring(0,space); else url = tmp;
                if( url.length ) {
                    msg = tmp.substr(String(url).length);
                    url = reverseHtmlEntities(url);
                    var extLinkTemplate = $("#external-page-link-template").clone(true);
                    extLinkTemplate.removeAttr("id");

                    if ($.Options.getUseProxyOpt() !== 'disable' && !$.Options.getUseProxyForImgOnlyOpt()){
                        //proxy alternatives may be added to options page...
                        if ($.Options.getUseProxyOpt() === 'ssl-proxy-my-addr') {
                            extLinkTemplate.attr('href', 'https://ssl-proxy.my-addr.org/myaddrproxy.php/' +
                                                         url.substring(0, url.indexOf(':')) +
                                                         url.substr(url.indexOf('/') + 1));
                        } else if ($.Options.getUseProxyOpt() ==='anonymouse') {
                            extLinkTemplate.attr('href', 'http://anonymouse.org/cgi-bin/anon-www.cgi/' + url);
                        }
                    } else {
                        extLinkTemplate.attr("href",url);
                    }

                    extLinkTemplate.text(url);
                    extLinkTemplate.attr("title",url);
                    output.append(extLinkTemplate);
                    continue;
                }
            }

            if( reEmail.exec(match[1]) ) {
                output.append(_formatText(msg.substr(0, index)));
                tmp = msg.substring(index);
                var space = tmp.search(/[ \n\t]/);
                var email;
                if( space != -1 ) email = tmp.substring(0,space); else email = tmp;
                if( email.length ) {
                    var extLinkTemplate = $("#external-page-link-template").clone(true);
                    extLinkTemplate.removeAttr("id");
                    extLinkTemplate.attr("href","mailto:" + email);
                    extLinkTemplate.text(email);
                    extLinkTemplate.attr("title",email);
                    output.append(extLinkTemplate);
                    msg = tmp.substr(String(email).length);
                    continue;
                }
            }

            if( match[1] == "#" ) {
                output.append(_formatText(msg.substr(0, index)));
                tmp = msg.substr(index+1);
                var hashtag = _extractHashtag(tmp);
                if( hashtag.length ) {
                    var hashtag_lc='';
                    for( var i = 0; i < hashtag.length; i++ ) {
                        var c = hashtag[i];
                        hashtag_lc += (c >= 'A' && c <= 'Z') ? c.toLowerCase() : c;
                    }
                    var hashtagLinkTemplate = $("#hashtag-link-template").clone(true);
                    hashtagLinkTemplate.removeAttr("id");
                    hashtagLinkTemplate.attr("href",$.MAL.hashtagUrl(hashtag_lc));
                    hashtagLinkTemplate.text("#"+hashtag);
                    output.append(hashtagLinkTemplate);
                    msg = tmp.substr(String(hashtag).length);
                    continue;
                }
                output.append('#');
                msg = tmp;
                continue;
            }

            if (reSplitCounter.exec(match[1])) {
                output.append(_formatText(msg.substr(0, index)));
                tmp = msg.substring(index);
                if( tmp.length ) {
                    var splitCounter = $('');
                    splitCounter.text(tmp);
                    output.append(splitCounter);
                    msg = "";
                    continue;
                }
            }
        }

        output.append(_formatText(msg));
        msg = "";
    }
}

// internal function for htmlFormatMsg
function _formatText(msg)
{
    // TODO: add options for emotions and linefeeds
    //msg = $.emotions(msg);
    if( $.Options.getLineFeedsOpt() == "enable" )
        msg = msg.replace(/\n/g, '
');
    return msg;
}

function _extractUsername(s) {
    var username = "";
    for( var i = 0; i < s.length; i++ ) {
        var c = s.charCodeAt(i);
        if( (c >= 'a'.charCodeAt(0) && c <= 'z'.charCodeAt(0)) ||
            (c >= 'A'.charCodeAt(0) && c <= 'Z'.charCodeAt(0)) ||
            (c >= '0'.charCodeAt(0) && c <= '9'.charCodeAt(0)) ||
            c == '_'.charCodeAt(0) ) {
            username += s[i];
        } else {
            break;
        }
    }
    return username.toLowerCase();
}

// internal function for htmlFormatMsg
function _extractHashtag(s) {
    var hashtag = "";
    s = reverseHtmlEntities(s);
    for( var i = 0; i < s.length; i++ ) {
        if( " \n\t.,:/?!;'\"()[]{}*#".indexOf(s[i]) < 0 ) {
            hashtag += s[i];
        } else {
            break;
        }
    }
    return hashtag;
}

function escapeHtmlEntities(str) {
    return str
                .replace(/&/g, '&')
                .replace(/</g, '<')
                .replace(/>/g, '>')
                .replace(/"/g, '"')
                .replace(/'/g, ''');
}

function reverseHtmlEntities(str) {
    return str
                .replace(/</g, '<')
                .replace(/>/g, '>')
                .replace(/"/g, '"')
                .replace(/'/g, "'")
                .replace(/&/g, '&');
}

<|endoftext|>


<commit_before>const crypto = require('crypto');

const defaults = {
  idField: 'id',
  name: 'challenge-request',
  userService: 'users'
};

/**
 * Creates a new challenge and adds it to the user record.
 */
module.exports = function (options = {}) {
  options = Object.assign({}, defaults, options);

  return function (hook) {
    return new Promise(function (resolve, reject) {
      // Only run this hook for the 'challenge-request' strategy.
      if (hook.data.strategy === options.name) {
        let userService = hook.app.service(options.userService);
        let user = hook.params.user;
        let userId = user[options.idField];

        // An accessToken should not be returned.
        delete hook.result.accessToken;

        userService.patch(userId, { challenge: undefined })
        .then(user => {
          return resolve(hook);
        })
        .catch(error => {
          console.log(error);
          // TODO: prevent leaks through this error.
          return reject(error);
        });
      } else {
        resolve(hook);
      }
    });
  };
};
<commit_msg>Don’t remove the accessToken in the challenge strategy.<commit_after>const crypto = require('crypto');

const defaults = {
  idField: 'id',
  name: 'challenge-request',
  userService: 'users'
};

/**
 * Creates a new challenge and adds it to the user record.
 */
module.exports = function (options = {}) {
  options = Object.assign({}, defaults, options);

  return function (hook) {
    return new Promise(function (resolve, reject) {
      // Only run this hook for the 'challenge-request' strategy.
      if (hook.data.strategy === options.name) {
        let userService = hook.app.service(options.userService);
        let user = hook.params.user;
        let userId = user[options.idField];

        userService.patch(userId, { challenge: undefined })
        .then(user => {
          return resolve(hook);
        })
        .catch(error => {
          console.log(error);
          // TODO: prevent leaks through this error.
          return reject(error);
        });
      } else {
        resolve(hook);
      }
    });
  };
};
<|endoftext|>


<commit_before>var Component = new Brick.Component();
Component.requires = {
    yui: ['datatype'],
    mod: [
        {name: 'sys', files: ['widgets.js']},
        {name: 'widget', files: ['period.js']},
        {name: '{C#MODNAME}', files: ['category.js']}
    ]
};
Component.entryPoint = function(NS){
    var Y = Brick.YUI,
        COMPONENT = this,
        SYS = Brick.mod.sys;

    NS.OperListWidget = Y.Base.create('operListWidget', SYS.AppWidget, [
        NS.GroupByIdExt
    ], {
        onBeforeLoadGroupData: function(err, appInstance){
            this.publish('rowClick');
            this.publish('menuClick');

            this.on('periodChange', this._onPeriodChange, this);
        },
        onLoadGroupData: function(err, group, options){
            this.reloadOperList();
            this.get('appInstance').on('appResponses', this._onAppResponses, this);
        },
        destructor: function(){
            this.get('appInstance').detach('appResponses', this._onAppResponses, this);
        },
        _onAppResponses: function(e){
            if (e.err || !e.result.balanceList){
                return;
            }
            this.reloadOperList(null, true);
        },
        reloadOperList: function(period, isUpdate){
            period = period || this.get('period');
            var config = {
                    groupid: this.get('groupid'),
                    period: [period[0] / 1000, period[1] / 1000]
                },
                operList = this.get('operList'),
                operMoveList = this.get('operMoveList');

            isUpdate = isUpdate && operList;

            if (isUpdate){
                var lastUpdate = 0;
                operList.each(function(oper){
                    lastUpdate = Math.max(lastUpdate, oper.get('upddate'));
                });
                config.upddate = lastUpdate;
            }

            this.set('waiting', true);
            this.get('appInstance').operList(config, function(err, result){
                this.set('waiting', true);
                if (!err){
                    if (isUpdate){
                        operList.add(result.operList);
                        operMoveList.add(result.operMoveList); // TODO: update list if not new records
                    } else {
                        this.set('operList', result.operList);
                        this.set('operMoveList', result.operMoveList);
                    }
                    this.renderOperList();
                }
            }, this);
        },
        renderOperList: function(){
            var app = this.get('appInstance'),
                accountList = app.get('accountList'),
                operList = this.get('operList'),
                operMoveList = this.get('operMoveList'),
                group = this.get('group'),
                isMenuVisible = this.get('menuVisible');

            if (!operList || !group){
                return;
            }

            var tp = this.template, lst = "", sum = {},
                filter = this.get('filter'),
                dmets = {},
                roundDay = function(d){
                    d = new Date(d * 1000);
                    return new Date(d.getFullYear(), d.getMonth(), d.getDate());
                };

            operList.each(function(oper){
                var attrs = oper.toJSON(),
                    account = accountList.getById(attrs.accountid),
                    currency = account ? NS.currencyList.getById(account.get('currency')) : null,
                    sign = currency ? currency.get('sign') : '',
                    cat = group.get('categories').getById(attrs.categoryid),
                    val = attrs.value,
                    ccid = account.get('currency');

                // метод перемещения состоит из двух/трех операций
                // показать нужно только всю операцию
                if (attrs.methodid > 0){
                    if (dmets[attrs.methodid]){
                        return;
                    }
                    dmets[attrs.methodid] = true;
                }

                // проверка на фильтр
                var v = "";
                for (var n in filter){
                    v = filter[n];

                    switch (n) {
                        case 'account':
                        case 'category':
                            if (attrs.methodid > 0){
                                return;
                            }
                            break;
                    }
                    if (n == 'date' && roundDay(attrs.date).getTime() != roundDay(v).getTime()){
                        return;
                    }
                    if (n == 'type' && attrs.isexpense !== v){
                        return;
                    }
                    if (n == 'account' && attrs.accountid !== v){
                        return;
                    }
                    if (n == 'category' && attrs.categoryid !== v){
                        return;
                    }
                    if (n === 'tag'){
                        if (attrs.tags === ''){
                            return;
                        }
                        var aTags = attrs.tags.split(','),
                            find = false;
                        for (var i = 0; i < aTags.length; i++){
                            if (aTags[i] == v){
                                find = true;
                                break;
                            }
                        }
                        if (!find){
                            return;
                        }
                    }
                }

                if (attrs.methodid === 0){
                    if (!sum[ccid]){
                        sum[ccid] = 0;
                    }
                    sum[ccid] += val;
                }

                var std = "";
                if (attrs.methodid === 0){
                    std = tp.replace('rowTDBase', {
                        id: attrs.id,
                        expcls: attrs.isexpense ? 'red' : 'green',
                        tp: attrs.isexpense ? '-' : '+',
                        v: NS.numberFormat(val),
                        cc: sign,
                        acc: account ? account.getTitle() : '',
                        cat: cat ? cat.get('title') : ''
                    });
                } else {
                    var opMove = oper.move = operMoveList.getById(attrs.methodid),
                        fAcc = accountList.getById(opMove.get('srcid')),
                        tAcc = accountList.getById(opMove.get('destid'));

                    std = tp.replace('rowtdmove', {
                        'facc': !fAcc ? '' : fAcc.getTitle(),
                        'tacc': !tAcc ? '' : tAcc.getTitle(),
                        'cc': sign,
                        'v': NS.numberFormat(Math.abs(val))
                    });
                }
                var btns = '';
                if (isMenuVisible){
                    btns = tp.replace(account.isOperRole() ? 'rbtns' : 'rbtnsn', {
                        'id': attrs.id
                    })
                }
                var sTags = '';
                if (NS.TAG){
                    var aTags = attrs.tags.split(','),
                        lstTag = [];
                    for (var iTag = 0; iTag < aTags.length; iTag++){
                        lstTag[lstTag.length] = tp.replace('tag', {
                            id: attrs.id,
                            tag: aTags[iTag]
                        });
                    }
                    sTags = tp.replace('rowTDTag', {
                        tags: lstTag.join(', ')
                    });
                }

                lst += tp.replace('row', {
                    id: attrs.id,
                    d: Brick.dateExt.convert(attrs.date, 2, true),
                    dtl: Brick.dateExt.convert(attrs.date, 0, true),
                    dsc: attrs.descript,
                    btns: btns,
                    td: std,
                    tdTag: sTags
                });

            }, this);

            var first = true;
            for (var n in sum){
                var val = sum[n],
                    currency = NS.currencyList.getById(n);
                lst += tp.replace('rowsum', {
                    'first': first ? 'first' : '',
                    'expcls': val < 0 ? 'red' : 'green',
                    'v': NS.numberFormat(val),
                    'cc': currency ? currency.get('sign') : ''
                });
                first = false;
            }

            var isFilter = false,
                fdv = {
                    'd': '', 'tp': '', 'v': '', 'acc': '', 'cat': '',
                    tagHead: NS.TAG ? tp.replace('filterTagHead') : '',
                    menuHead: isMenuVisible ? tp.replace('filterMenuHead') : ''
                };

            for (var n in filter){
                isFilter = true;
                var v = filter[n];

                switch (n) {
                    case 'date':
                        fdv['d'] = tp.replace('filterval', {
                            'tp': n,
                            'v': Brick.dateExt.convert(v, 2, true)
                        });
                        break;
                    case 'type':
                        fdv['tp'] = tp.replace('filterval', {
                            'tp': n,
                            'v': v ? '-' : '+'
                        });
                        break;
                    case 'account':
                        var acc = accountList.getById(v);
                        if (acc){
                            fdv['acc'] = tp.replace('filterval', {
                                'tp': n,
                                'v': acc.getTitle()
                            });
                        }
                        break;
                    case 'category':
                        var cat = group.get('categories').getById(v);
                        if (cat){
                            fdv['cat'] = tp.replace('filterval', {
                                'tp': n,
                                'v': cat.get('title')
                            });
                        }
                        break;
                    case 'tag':
                        fdv['tag'] = tp.replace('filterval', {
                            'tp': n,
                            'v': v
                        });
                        break;
                }
            }

            tp.setHTML('table', tp.replace('table', {
                menuHead: isMenuVisible ? tp.replace('menuHead') : '',
                tagHead: NS.TAG ? tp.replace('tagHead') : '',
                filter: isFilter ? tp.replace('rowFilter', fdv) : '',
                rows: lst
            }));
        },
        addFilter: function(action, oper, value){
            if (!oper){
                return;
            }
            var val = "", attrs = oper.toJSON();
            switch (action) {
                case 'date':
                    val = attrs.date;
                    break;
                case 'type':
                    val = attrs.isexpense;
                    break;
                case 'account':
                    val = attrs.accountid;
                    break;
                case 'category':
                    val = attrs.categoryid;
                    break;
                case 'tag':
                    val = value;
                    break;
            }
            this.get('filter')[action] = val;
            this.renderOperList();
        },
        removeFilter: function(action){
            delete this.get('filter')[action];
            this.renderOperList();
        },
        clearFilter: function(){
            this.set('filter', {});
            this.renderOperList();
        },
        _actionNode: function(operid){
            var tp = this.template,
                elid = tp.gelid('row.action'),
                el = Y.Node.one('#' + elid + '-' + operid);
            return el;
        },
        closeRemoveWidget: function(){
            var w = this._removeWidget;
            if (!w){
                return;
            }
            w._actionNode.addClass('hide');
            w.destroy();
            this._removeWidget = null;
        },
        showRemoveWidget: function(operid){
            this.closeRemoveWidget();

            var el = this._actionNode(operid);
            if (!el){
                return;
            }
            el.removeClass('hide');
            var w = this._removeWidget = new NS.OperListWidget.RemoveWidget({
                srcNode: el.appendChild('

'),
                CLICKS: {
                    cancel: {
                        event: this.closeRemoveWidget, context: this
                    },
                    remove: {
                        event: this.removeOper, context: this
                    }
                }
            });
            w._actionNode = el;
            w._operid = operid;
        },
        removeOper: function(){
            var w = this._removeWidget;
            if (!w){
                return;
            }
            w.set('waiting', true);
            this.get('appInstance').operRemove(w._operid, function(err, result){
                if (!err){
                    this.get('operList').removeById(w._operid);
                    this.closeRemoveWidget();
                    this.renderOperList();
                }
            }, this);

        },
        _onPeriodChange: function(e){
            this.reloadOperList(e.newVal);
        },
        onClick: function(e){
            switch (e.dataClick) {
                case 'clear-filter':
                    this.fire('menuClick', {
                        action: e.dataClick,
                        filter: e.target.getData('id')
                    });
                    return true;
                case 'filter-date':
                case 'filter-type':
                case 'filter-account':
                case 'filter-category':
                case 'filter-tag':
                case 'edit':
                    var oper = this.get('operList').getById(e.target.getData('id') | 0);
                    this.fire('rowClick', {
                        action: e.dataClick,
                        oper: oper,
                        value: e.target.getData('value')
                    });
                    return true;
                case 'remove':
                    this.showRemoveWidget(e.target.getData('id') | 0);
                    return true;
            }
        }
    }, {
        ATTRS: {
            component: {value: COMPONENT},
            templateBlockName: {
                value: 'list,table,menuHead,tagHead,filterMenuHead,filterTagHead,rowFilter,' +
                'row,rowTDBase,rowTDTag,tag,rowtdmove,rowsum,rbtns,rbtnsn,filterval'
            },
            operList: {},
            filter: {value: {}},
            fromDate: {
                setter: function(val){
                    this.set('period', [val, this.get('endDate')]);
                },
                getter: function(){
                    return this.get('period')[0];
                }
            },
            endDate: {
                setter: function(val){
                    this.set('period', [this.get('fromDate'), val]);
                },
                getter: function(){
                    return this.get('period')[1];
                }
            },
            period: {
                validator: function(val){
                    return (Y.Lang.isArray(val) &&
                    val.length == 2 &&
                    (val[0] instanceof Date) && (val[1] instanceof Date));
                }
            },
            operList: {value: null},
            operMoveList: {value: null},
            menuVisible: {
                writeOnce: true,
                value: false
            }
        }
    });

    NS.OperListWidget.RemoveWidget = Y.Base.create('removeWidget', SYS.AppWidget, [], {}, {
        ATTRS: {
            component: {value: COMPONENT},
            templateBlockName: {value: 'remove'},
        }
    });

    NS.OperLogWidget = Y.Base.create('operLogWidget', SYS.AppWidget, [
        NS.GroupByIdExt
    ], {
        buildTData: function(){
            return {groupid: this.get('groupid')}
        },
        onLoadGroupData: function(err, group){
            if (!group){
                return;
            }

            this.publish('rowMenuClick');

            var tp = this.template,
                groupid = group.get('id');

            tp.setHTML('title', group.getTitle());

            this.periodWidget = new Brick.mod.widget.PeriodWidget(tp.gel('period'));
            this.periodWidget.getPeriod = function(){
                var period = this.getValue();
                return [period['fdt'], period['edt']];
            }
            this.periodWidget.selectType('week');
            this.periodWidget.periodChangedEvent.subscribe(this.onPeriodChanged, this, true);

            this.listWidget = new NS.OperListWidget({
                srcNode: tp.gel('list'),
                groupid: groupid,
                period: this.periodWidget.getPeriod(),
                menuVisible: this.get('rowMenuVisible')
            });
            this.listWidget.on('menuClick', this._onOperListMenuClick, this);
            this.listWidget.on('rowClick', this._onOperRowClick, this);
        },
        destructor: function(){
            this.listWidget.destroy();
        },
        onPeriodChanged: function(){
            this.listWidget.set('period', this.periodWidget.getPeriod());
        },
        addFilter: function(type, oper, value){
            this.listWidget.addFilter(type, oper, value);
        },
        removeFilter: function(type){
            this.listWidget.removeFilter(type);
        },
        _onOperRowClick: function(e){
            switch (e.action) {
                case 'filter-date':
                case 'filter-type':
                case 'filter-account':
                case 'filter-category':
                case 'filter-tag':
                    return this.addFilter(e.action.replace('filter-', ''), e.oper, e.value);
            }
            this.fire('rowMenuClick', {
                action: e.action,
                oper: e.oper
            });
        },
        _onOperListMenuClick: function(e){
            switch (e.action) {
                case 'clear-filter':
                    this.removeFilter(e.filter);
                    break;
            }
        },
    }, {
        ATTRS: {
            component: {value: COMPONENT},
            templateBlockName: {value: 'widget'},
            rowMenuVisible: {
                writeOnce: true,
                value: false
            }
        }
    });

    NS.OperLogWidget.parseURLParam = function(args){
        args = args || [];
        return {
            groupid: (args[0] | 0)
        };
    };

};<commit_msg>bugfix: value colors close#11<commit_after>var Component = new Brick.Component();
Component.requires = {
    yui: ['datatype'],
    mod: [
        {name: 'sys', files: ['widgets.js']},
        {name: 'widget', files: ['period.js']},
        {name: '{C#MODNAME}', files: ['category.js']}
    ]
};
Component.entryPoint = function(NS){
    var Y = Brick.YUI,
        COMPONENT = this,
        SYS = Brick.mod.sys;

    NS.OperListWidget = Y.Base.create('operListWidget', SYS.AppWidget, [
        NS.GroupByIdExt
    ], {
        onBeforeLoadGroupData: function(err, appInstance){
            this.publish('rowClick');
            this.publish('menuClick');

            this.on('periodChange', this._onPeriodChange, this);
        },
        onLoadGroupData: function(err, group, options){
            this.reloadOperList();
            this.get('appInstance').on('appResponses', this._onAppResponses, this);
        },
        destructor: function(){
            this.get('appInstance').detach('appResponses', this._onAppResponses, this);
        },
        _onAppResponses: function(e){
            if (e.err || !e.result.balanceList){
                return;
            }
            this.reloadOperList(null, true);
        },
        reloadOperList: function(period, isUpdate){
            period = period || this.get('period');
            var config = {
                    groupid: this.get('groupid'),
                    period: [period[0] / 1000, period[1] / 1000]
                },
                operList = this.get('operList'),
                operMoveList = this.get('operMoveList');

            isUpdate = isUpdate && operList;

            if (isUpdate){
                var lastUpdate = 0;
                operList.each(function(oper){
                    lastUpdate = Math.max(lastUpdate, oper.get('upddate'));
                });
                config.upddate = lastUpdate;
            }

            this.set('waiting', true);
            this.get('appInstance').operList(config, function(err, result){
                this.set('waiting', true);
                if (!err){
                    if (isUpdate){
                        operList.add(result.operList);
                        operMoveList.add(result.operMoveList); // TODO: update list if not new records
                    } else {
                        this.set('operList', result.operList);
                        this.set('operMoveList', result.operMoveList);
                    }
                    this.renderOperList();
                }
            }, this);
        },
        renderOperList: function(){
            var app = this.get('appInstance'),
                accountList = app.get('accountList'),
                operList = this.get('operList'),
                operMoveList = this.get('operMoveList'),
                group = this.get('group'),
                isMenuVisible = this.get('menuVisible');

            if (!operList || !group){
                return;
            }

            var tp = this.template, lst = "", sum = {},
                filter = this.get('filter'),
                dmets = {},
                roundDay = function(d){
                    d = new Date(d * 1000);
                    return new Date(d.getFullYear(), d.getMonth(), d.getDate());
                };

            operList.each(function(oper){
                var attrs = oper.toJSON(),
                    account = accountList.getById(attrs.accountid),
                    currency = account ? NS.currencyList.getById(account.get('currency')) : null,
                    sign = currency ? currency.get('sign') : '',
                    cat = group.get('categories').getById(attrs.categoryid),
                    val = attrs.value,
                    ccid = account.get('currency');

                // метод перемещения состоит из двух/трех операций
                // показать нужно только всю операцию
                if (attrs.methodid > 0){
                    if (dmets[attrs.methodid]){
                        return;
                    }
                    dmets[attrs.methodid] = true;
                }

                // проверка на фильтр
                var v = "";
                for (var n in filter){
                    v = filter[n];

                    switch (n) {
                        case 'account':
                        case 'category':
                            if (attrs.methodid > 0){
                                return;
                            }
                            break;
                    }
                    if (n == 'date' && roundDay(attrs.date).getTime() != roundDay(v).getTime()){
                        return;
                    }
                    if (n == 'type' && attrs.isexpense !== v){
                        return;
                    }
                    if (n == 'account' && attrs.accountid !== v){
                        return;
                    }
                    if (n == 'category' && attrs.categoryid !== v){
                        return;
                    }
                    if (n === 'tag'){
                        if (attrs.tags === ''){
                            return;
                        }
                        var aTags = attrs.tags.split(','),
                            find = false;
                        for (var i = 0; i < aTags.length; i++){
                            if (aTags[i] == v){
                                find = true;
                                break;
                            }
                        }
                        if (!find){
                            return;
                        }
                    }
                }

                if (attrs.methodid === 0){
                    if (!sum[ccid]){
                        sum[ccid] = 0;
                    }
                    sum[ccid] += val;
                }

                var std = "";
                if (attrs.methodid === 0){
                    std = tp.replace('rowTDBase', {
                        id: attrs.id,
                        expcls: attrs.isexpense ? 'text-danger' : 'text-success',
                        tp: attrs.isexpense ? '-' : '+',
                        v: NS.numberFormat(val),
                        cc: sign,
                        acc: account ? account.getTitle() : '',
                        cat: cat ? cat.get('title') : ''
                    });
                } else {
                    var opMove = oper.move = operMoveList.getById(attrs.methodid),
                        fAcc = accountList.getById(opMove.get('srcid')),
                        tAcc = accountList.getById(opMove.get('destid'));

                    std = tp.replace('rowtdmove', {
                        'facc': !fAcc ? '' : fAcc.getTitle(),
                        'tacc': !tAcc ? '' : tAcc.getTitle(),
                        'cc': sign,
                        'v': NS.numberFormat(Math.abs(val))
                    });
                }
                var btns = '';
                if (isMenuVisible){
                    btns = tp.replace(account.isOperRole() ? 'rbtns' : 'rbtnsn', {
                        'id': attrs.id
                    })
                }
                var sTags = '';
                if (NS.TAG){
                    var aTags = attrs.tags.split(','),
                        lstTag = [];
                    for (var iTag = 0; iTag < aTags.length; iTag++){
                        lstTag[lstTag.length] = tp.replace('tag', {
                            id: attrs.id,
                            tag: aTags[iTag]
                        });
                    }
                    sTags = tp.replace('rowTDTag', {
                        tags: lstTag.join(', ')
                    });
                }

                lst += tp.replace('row', {
                    id: attrs.id,
                    d: Brick.dateExt.convert(attrs.date, 2, true),
                    dtl: Brick.dateExt.convert(attrs.date, 0, true),
                    dsc: attrs.descript,
                    btns: btns,
                    td: std,
                    tdTag: sTags
                });

            }, this);

            var first = true;
            for (var n in sum){
                var val = sum[n],
                    currency = NS.currencyList.getById(n);
                lst += tp.replace('rowsum', {
                    'first': first ? 'first' : '',
                    'expcls': val < 0 ? 'text-danger' : 'text-success',
                    'v': NS.numberFormat(val),
                    'cc': currency ? currency.get('sign') : ''
                });
                first = false;
            }

            var isFilter = false,
                fdv = {
                    'd': '', 'tp': '', 'v': '', 'acc': '', 'cat': '',
                    tagHead: NS.TAG ? tp.replace('filterTagHead') : '',
                    menuHead: isMenuVisible ? tp.replace('filterMenuHead') : ''
                };

            for (var n in filter){
                isFilter = true;
                var v = filter[n];

                switch (n) {
                    case 'date':
                        fdv['d'] = tp.replace('filterval', {
                            'tp': n,
                            'v': Brick.dateExt.convert(v, 2, true)
                        });
                        break;
                    case 'type':
                        fdv['tp'] = tp.replace('filterval', {
                            'tp': n,
                            'v': v ? '-' : '+'
                        });
                        break;
                    case 'account':
                        var acc = accountList.getById(v);
                        if (acc){
                            fdv['acc'] = tp.replace('filterval', {
                                'tp': n,
                                'v': acc.getTitle()
                            });
                        }
                        break;
                    case 'category':
                        var cat = group.get('categories').getById(v);
                        if (cat){
                            fdv['cat'] = tp.replace('filterval', {
                                'tp': n,
                                'v': cat.get('title')
                            });
                        }
                        break;
                    case 'tag':
                        fdv['tag'] = tp.replace('filterval', {
                            'tp': n,
                            'v': v
                        });
                        break;
                }
            }

            tp.setHTML('table', tp.replace('table', {
                menuHead: isMenuVisible ? tp.replace('menuHead') : '',
                tagHead: NS.TAG ? tp.replace('tagHead') : '',
                filter: isFilter ? tp.replace('rowFilter', fdv) : '',
                rows: lst
            }));
        },
        addFilter: function(action, oper, value){
            if (!oper){
                return;
            }
            var val = "", attrs = oper.toJSON();
            switch (action) {
                case 'date':
                    val = attrs.date;
                    break;
                case 'type':
                    val = attrs.isexpense;
                    break;
                case 'account':
                    val = attrs.accountid;
                    break;
                case 'category':
                    val = attrs.categoryid;
                    break;
                case 'tag':
                    val = value;
                    break;
            }
            this.get('filter')[action] = val;
            this.renderOperList();
        },
        removeFilter: function(action){
            delete this.get('filter')[action];
            this.renderOperList();
        },
        clearFilter: function(){
            this.set('filter', {});
            this.renderOperList();
        },
        _actionNode: function(operid){
            var tp = this.template,
                elid = tp.gelid('row.action'),
                el = Y.Node.one('#' + elid + '-' + operid);
            return el;
        },
        closeRemoveWidget: function(){
            var w = this._removeWidget;
            if (!w){
                return;
            }
            w._actionNode.addClass('hide');
            w.destroy();
            this._removeWidget = null;
        },
        showRemoveWidget: function(operid){
            this.closeRemoveWidget();

            var el = this._actionNode(operid);
            if (!el){
                return;
            }
            el.removeClass('hide');
            var w = this._removeWidget = new NS.OperListWidget.RemoveWidget({
                srcNode: el.appendChild('

'),
                CLICKS: {
                    cancel: {
                        event: this.closeRemoveWidget, context: this
                    },
                    remove: {
                        event: this.removeOper, context: this
                    }
                }
            });
            w._actionNode = el;
            w._operid = operid;
        },
        removeOper: function(){
            var w = this._removeWidget;
            if (!w){
                return;
            }
            w.set('waiting', true);
            this.get('appInstance').operRemove(w._operid, function(err, result){
                if (!err){
                    this.get('operList').removeById(w._operid);
                    this.closeRemoveWidget();
                    this.renderOperList();
                }
            }, this);

        },
        _onPeriodChange: function(e){
            this.reloadOperList(e.newVal);
        },
        onClick: function(e){
            switch (e.dataClick) {
                case 'clear-filter':
                    this.fire('menuClick', {
                        action: e.dataClick,
                        filter: e.target.getData('id')
                    });
                    return true;
                case 'filter-date':
                case 'filter-type':
                case 'filter-account':
                case 'filter-category':
                case 'filter-tag':
                case 'edit':
                    var oper = this.get('operList').getById(e.target.getData('id') | 0);
                    this.fire('rowClick', {
                        action: e.dataClick,
                        oper: oper,
                        value: e.target.getData('value')
                    });
                    return true;
                case 'remove':
                    this.showRemoveWidget(e.target.getData('id') | 0);
                    return true;
            }
        }
    }, {
        ATTRS: {
            component: {value: COMPONENT},
            templateBlockName: {
                value: 'list,table,menuHead,tagHead,filterMenuHead,filterTagHead,rowFilter,' +
                'row,rowTDBase,rowTDTag,tag,rowtdmove,rowsum,rbtns,rbtnsn,filterval'
            },
            operList: {},
            filter: {value: {}},
            fromDate: {
                setter: function(val){
                    this.set('period', [val, this.get('endDate')]);
                },
                getter: function(){
                    return this.get('period')[0];
                }
            },
            endDate: {
                setter: function(val){
                    this.set('period', [this.get('fromDate'), val]);
                },
                getter: function(){
                    return this.get('period')[1];
                }
            },
            period: {
                validator: function(val){
                    return (Y.Lang.isArray(val) &&
                    val.length == 2 &&
                    (val[0] instanceof Date) && (val[1] instanceof Date));
                }
            },
            operList: {value: null},
            operMoveList: {value: null},
            menuVisible: {
                writeOnce: true,
                value: false
            }
        }
    });

    NS.OperListWidget.RemoveWidget = Y.Base.create('removeWidget', SYS.AppWidget, [], {}, {
        ATTRS: {
            component: {value: COMPONENT},
            templateBlockName: {value: 'remove'},
        }
    });

    NS.OperLogWidget = Y.Base.create('operLogWidget', SYS.AppWidget, [
        NS.GroupByIdExt
    ], {
        buildTData: function(){
            return {groupid: this.get('groupid')}
        },
        onLoadGroupData: function(err, group){
            if (!group){
                return;
            }

            this.publish('rowMenuClick');

            var tp = this.template,
                groupid = group.get('id');

            tp.setHTML('title', group.getTitle());

            this.periodWidget = new Brick.mod.widget.PeriodWidget(tp.gel('period'));
            this.periodWidget.getPeriod = function(){
                var period = this.getValue();
                return [period['fdt'], period['edt']];
            }
            this.periodWidget.selectType('week');
            this.periodWidget.periodChangedEvent.subscribe(this.onPeriodChanged, this, true);

            this.listWidget = new NS.OperListWidget({
                srcNode: tp.gel('list'),
                groupid: groupid,
                period: this.periodWidget.getPeriod(),
                menuVisible: this.get('rowMenuVisible')
            });
            this.listWidget.on('menuClick', this._onOperListMenuClick, this);
            this.listWidget.on('rowClick', this._onOperRowClick, this);
        },
        destructor: function(){
            this.listWidget.destroy();
        },
        onPeriodChanged: function(){
            this.listWidget.set('period', this.periodWidget.getPeriod());
        },
        addFilter: function(type, oper, value){
            this.listWidget.addFilter(type, oper, value);
        },
        removeFilter: function(type){
            this.listWidget.removeFilter(type);
        },
        _onOperRowClick: function(e){
            switch (e.action) {
                case 'filter-date':
                case 'filter-type':
                case 'filter-account':
                case 'filter-category':
                case 'filter-tag':
                    return this.addFilter(e.action.replace('filter-', ''), e.oper, e.value);
            }
            this.fire('rowMenuClick', {
                action: e.action,
                oper: e.oper
            });
        },
        _onOperListMenuClick: function(e){
            switch (e.action) {
                case 'clear-filter':
                    this.removeFilter(e.filter);
                    break;
            }
        },
    }, {
        ATTRS: {
            component: {value: COMPONENT},
            templateBlockName: {value: 'widget'},
            rowMenuVisible: {
                writeOnce: true,
                value: false
            }
        }
    });

    NS.OperLogWidget.parseURLParam = function(args){
        args = args || [];
        return {
            groupid: (args[0] | 0)
        };
    };

};<|endoftext|>


<commit_before>(function(){

  // Set AudioContext to vendor version
  this.AudioContext = this.AudioContext || this.webkitAudioContext
                                        || this.mozAudioContext
                                        || this.oAudioContext
                                        || this.msAudioContext;

  if (!this.AudioContext) throw "Theremin Error: The Web Audio API is not available in this environment";

  // Create Theremin object and private variables
  this.Theremin = {};
  var context, version = "0.0.1";

  // Theremin object methods
  Theremin.getVersion = function() {
    return version;
  };

  Theremin.setContext = function(audio_context){
    return context = audio_context;
  };

  Theremin.getContext = function(){
    return context;
  };

  // Theremin Player Constructor
  Theremin.Player = (function() {

    var Player = function(loop){
      this.loop = loop;
      this.accumulated_duration = 0;
    };

    var getAjaxBufferPromise = function(url) {

      if(typeof Promise === "undefined") throw "Theremin unable to load buffer because your environment does not support Promises";

      return new Promise(function(resolve, reject) {

        var request = new XMLHttpRequest();

        request.open('GET', url, true);
        request.responseType = 'arraybuffer';

        request.onload = function() {
          request.status === 200 ? resolve(request.response) : reject(Error(request.statusText));
        };

        request.onerror = function(){
          reject(Error("Theremin Error: AJAX request Network Error "));
        };

        request.send();
      });
    };

    var createSourceAndPlay = function() {
      var source = this.source;

      this.play_start = context.currentTime;
      source = context.createBufferSource();
      source.buffer = this.buffer;
      source.loop = this.loop;
      source.connect(context.destination);
      source.start(0, this.accumulated_duration);
    };

    var resetPlayer = function() {
      var source = this.source;

      if (source) {
        source.stop();
        source = null;
      }
      this.accumulated_duration = 0;
    };

    Player.prototype.loadBuffer = function(url){

      var _this = this;

      getAjaxBufferPromise(url).then(function(response) {
        context.decodeAudioData(response, function(loaded_buffer){
          _this.buffer = loaded_buffer;
        });
      }, function(error) {
        console.error("Theremin Error: Error loading buffer, " + error);
      });
    };

    Player.prototype.play = function(){

      if (!this.buffer) throw "No buffer loaded for this player";

      var accumulated_duration = this.accumulated_duration;
      var buffer_duration = this.buffer.duration;
      var source = this.source;

      if (this.loop) {
        accumulated_duration = accumulated_duration % buffer_duration;
      } else {
        var duration = source ? context.currentTime - this.play_start : 0;
        if (accumulated_duration + duration > buffer_duration) resetPlayer.call(this);
      }

      if (!source) createSourceAndPlay.call(this);
    };

    Player.prototype.pause = function(){

      var source = this.source;

      if (source) {
        var duration = context.currentTime - this.play_start;
        this.accumulated_duration += duration;
        source.stop();
        source = null;
      }
    };

    Player.prototype.jumpTo = function(seconds, play) {

      var source = this.source;

      if (source) {
        source.stop();
        source = null;
      }
      this.accumulated_duration = seconds;
      if (play) this.play();
    };

    return Player;
  })();
}());
<commit_msg>comment<commit_after>(function(){

  // Set AudioContext to vendor version
  this.AudioContext = this.AudioContext || this.webkitAudioContext
                                        || this.mozAudioContext
                                        || this.oAudioContext
                                        || this.msAudioContext;

  if (!this.AudioContext) throw "Theremin Error: The Web Audio API is not available in this environment";

  // Create Theremin object and private variables
  this.Theremin = {};
  var context, version = "0.0.1";

  // Theremin object methods
  Theremin.getVersion = function() {
    return version;
  };

  Theremin.setContext = function(audio_context){
    return context = audio_context;
  };

  Theremin.getContext = function(){
    return context;
  };

  // Theremin Player constructor
  Theremin.Player = (function() {

    var Player = function(loop){
      this.loop = loop;
      this.accumulated_duration = 0;
    };

    var getAjaxBufferPromise = function(url) {

      if(typeof Promise === "undefined") throw "Theremin unable to load buffer because your environment does not support Promises";

      return new Promise(function(resolve, reject) {

        var request = new XMLHttpRequest();

        request.open('GET', url, true);
        request.responseType = 'arraybuffer';

        request.onload = function() {
          request.status === 200 ? resolve(request.response) : reject(Error(request.statusText));
        };

        request.onerror = function(){
          reject(Error("Theremin Error: AJAX request Network Error "));
        };

        request.send();
      });
    };

    var createSourceAndPlay = function() {
      var source = this.source;

      this.play_start = context.currentTime;
      source = context.createBufferSource();
      source.buffer = this.buffer;
      source.loop = this.loop;
      source.connect(context.destination);
      source.start(0, this.accumulated_duration);
    };

    var resetPlayer = function() {
      var source = this.source;

      if (source) {
        source.stop();
        source = null;
      }
      this.accumulated_duration = 0;
    };

    Player.prototype.loadBuffer = function(url){

      var _this = this;

      getAjaxBufferPromise(url).then(function(response) {
        context.decodeAudioData(response, function(loaded_buffer){
          _this.buffer = loaded_buffer;
        });
      }, function(error) {
        console.error("Theremin Error: Error loading buffer, " + error);
      });
    };

    Player.prototype.play = function(){

      if (!this.buffer) throw "No buffer loaded for this player";

      var accumulated_duration = this.accumulated_duration;
      var buffer_duration = this.buffer.duration;
      var source = this.source;

      if (this.loop) {
        accumulated_duration = accumulated_duration % buffer_duration;
      } else {
        var duration = source ? context.currentTime - this.play_start : 0;
        if (accumulated_duration + duration > buffer_duration) resetPlayer.call(this);
      }

      if (!source) createSourceAndPlay.call(this);
    };

    Player.prototype.pause = function(){

      var source = this.source;

      if (source) {
        var duration = context.currentTime - this.play_start;
        this.accumulated_duration += duration;
        source.stop();
        source = null;
      }
    };

    Player.prototype.jumpTo = function(seconds, play) {

      var source = this.source;

      if (source) {
        source.stop();
        source = null;
      }
      this.accumulated_duration = seconds;
      if (play) this.play();
    };

    return Player;
  })();
}());
<|endoftext|>