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

/**
 * Simple template system modelled after JSP's.
 *
 * Syntax:
 *    <% code %>: code inserted into template, but nothing implicitly output
 *    <%= comma-separated-values %>: all values are appended to template output
 *    <%# expression %>: dynamic (auto-updating) expression is output
 *    \<new-line>: ignored
 *    %%value(<whitespace>|<): output a single value to the template output
 *    $$feature(<whitespace>|<): output the View or Action for the current Value
 */

MODEL({
  name: 'TemplateParser',
  extendsModel: 'grammar',

  methods: {
    START: sym('markup'),

    markup: repeat0(alt(
      sym('comment'),
      sym('foamTag'),
      sym('create child'),
      sym('simple value'),
      sym('live value tag'),
      sym('raw values tag'),
      sym('values tag'),
      sym('code tag'),
      sym('ignored newline'),
      sym('newline'),
      sym('single quote'),
      sym('text')
    )),

    'comment': seq1(1, '<!--', repeat0(not('-->', anyChar)), '-->'),

    'foamTag': sym('foamTag_'),
    'foamTag_': function() { }, // placeholder until gets filled in after HTMLParser is built

    'create child': seq(
      '$$',
      repeat(notChars(' $\n<{')),
      optional(JSONParser.export('objAsString'))),

    'simple value': seq('%%', repeat(notChars(' -"\n><:;,'))),

    'live value tag': seq('<%#', repeat(not('%>', anyChar)), '%>'),

    'raw values tag': alt(
      seq('<%=', repeat(not('%>', anyChar)), '%>'),
      seq('{{{', repeat(not('}}}', anyChar)), '}}}')
    ),

    'values tag': seq('{{', repeat(not('}}', anyChar)), '}}'),

    'code tag': seq('<%', repeat(not('%>', anyChar)), '%>'),
    'ignored newline': literal('\\\n'),
    newline: literal('\n'),
    'single quote': literal("'"),
    text: anyChar
  }
});

var TemplateOutput = {
  /**
   * obj - Parent object.  If objects are output and have an initHTML() method, then they
   * are added to the parent by calling obj.addChild().
   **/
  // TODO(kgr): redesign, I think this is actually broken.  If we call appendHTML() of
  // a sub-view then it will be added to the wrong parent.
  create: function(obj) {
    var buf = [];
    var f = function templateOut(/* arguments */) {
      for ( var i = 0 ; i < arguments.length ; i++ ) {
        var o = arguments[i];
        if ( typeof o === 'string' ) {
          buf.push(o);
        } else {
          if ( o && o.toView_ ) o = o.toView_();
          if ( ! ( o === null || o === undefined ) ) {
            if ( o.appendHTML ) {
              o.appendHTML(this);
            } else if ( o.toHTML ) {
              buf.push(o.toHTML());
            } else {
              buf.push(o);
            }
            if ( o.initHTML && obj.addChild ) obj.addChild(o);
          }
        }
      }
    };

    f.toString = function() {
      if ( buf.length === 0 ) return '';
      if ( buf.length > 1 ) buf = [buf.join('')];
      return buf[0];
    }

    return f;
  }
};

// Called from generated template code.
function elementFromString(str) {
  return str.element || ( str.element = HTMLParser.create().parseString(str).children[0] );
}

var ConstantTemplate = function(str) {
  var TemplateOutputCreate = TemplateOutput.create.bind(TemplateOutput);
  var f = function(opt_out) {
    var out = opt_out ? opt_out : TemplateOutputCreate(this);
    out(str);
    return out.toString();
  };

  f.toString = function() {
    return 'ConstantTemplate("' + str.replace(/\n/g, "\\n").replace(/"/g, '\\"') + '")';
  };

  return f;
};

var TemplateCompiler = {
  __proto__: TemplateParser,

  out: [],

  simple: true, // True iff the template is just one string literal.

  push: function() { this.simple = false; this.pushSimple.apply(this, arguments); },

  pushSimple: function() { this.out.push.apply(this.out, arguments); },

  header: 'var self = this, X = this.X, Y = this.Y;' +
    'var out = opt_out ? opt_out : TOC(this);' +
    "out('",

  footer: "');" +
    "return out.toString();"

}.addActions({
  markup: function (v) {
    var wasSimple = this.simple;
    var ret = wasSimple ? null : this.header + this.out.join('') + this.footer ;
    this.out = [];
    this.simple = true;
    return [wasSimple, ret];
  },

  'create child': function(v) {
    var name = v[1].join('');
    this.push(
      "', self.createTemplateView('", name, "'",
      v[2] ? ', ' + v[2] : '',
      "),\n'");
  },
  foamTag: function(e) {
    // A Feature
    var fName = e.getAttribute('f');
    if ( fName ) {
      this.push("', self.createTemplateView('", fName, "',{}).fromElement(FOAM(");
      this.push(JSONUtil.where(NOT_TRANSIENT).stringify(e));
      this.push('))');
    }
    // A Model
    else {
      this.push("', (function() { var tagView = X.foam.ui.FoamTagView.create({element: FOAM(");
      this.push(JSONUtil.where(NOT_TRANSIENT).stringify(e));
      this.push(')}, Y); self.addDataChild(tagView); return tagView; })() ');
    }

    this.push(",\n'");
  },
  'simple value': function(v) { this.push("',\n self.", v[1].join(''), ",\n'"); },
  'raw values tag': function (v) { this.push("',\n", v[1].join(''), ",\n'"); },
  'values tag':     function (v) { this.push("',\nescapeHTML(", v[1].join(''), "),\n'"); },
  'live value tag': function (v) { this.push("',\nself.dynamicTag('span', function() { return ", v[1].join(''), "; }.bind(this)),\n'"); },
  'code tag': function (v) { this.push("');\n", v[1].join(''), ";out('"); },
  'single quote': function () { this.pushSimple("\\'"); },
  newline: function () { this.pushSimple('\\n'); },
  text: function(v) { this.pushSimple(v); }
});

MODEL({
  name: 'TemplateUtil',

  methods: {
    /** Create a method which only compiles the template when first used. **/
    lazyCompile: function(t) {
      var delegate;

      var f = function() {
        if ( ! delegate ) {
          if ( ! t.template )
            throw 'Must arequire() template model before use for ' + this.name_ + '.' + t.name;
          else
            delegate = TemplateUtil.compile(Template.isInstance(t) ? t : Template.create(t));
        }

        return delegate.apply(this, arguments);
      };

      f.toString = function() { return delegate ? delegate.toString() : t.toString(); };

      return f;
    },

    compile_: function(t, code) {
      var args = ['opt_out'];
      for ( var i = 0 ; i < t.args.length ; i++ ) {
        args.push(t.args[i].name);
      }
      return eval('(function() { var escapeHTML = XMLUtil.escape, TOC = TemplateOutput.create.bind(TemplateOutput); return function(' + args.join(',') + '){' + code + '};})()');
    },
    compile: function(t) {
      // console.time('parse-template-' + t.name);
      var code = TemplateCompiler.parseString(t.template);
      // console.timeEnd('parse-template-' + t.name);

      // Simple case, just a string literal
      if ( code[0] ) return ConstantTemplate(t.template);

      // Need to compile an actual method
      try {
        return this.compile_(t, code[1]);
      } catch (err) {
        console.log('Template Error: ', err);
        console.log(code);
        return function() {};
      }
    },

    /**
     * Combinator which takes a template which expects an output parameter and
     * converts it into a function which returns a string.
     */
    stringifyTemplate: function (template) {
      return function() {
        var buf = [];

        this.output(buf.push.bind(buf), obj);

        return buf.join('');
      };
    },

    expandTemplate: function(self, t, opt_X) {
      /*
       * If a template is supplied as a function, treat it as a multiline string.
       * Parse function arguments to populate template.args.
       * Load template from file if external.
       * Setup template future.
       */
      var X = opt_X || self.X;

      if ( typeof t === 'function' ) {
        t = X.Template.create({
          name: t.name,
          // ignore first argument, which should be 'opt_out'
          args: t.toString().match(/\((.*?)\)/)[1].split(',').slice(1).map(function(a) {
            return X.Arg.create({name: a.trim()});
          }),
          template: multiline(t)});
      } else if ( typeof t === 'string' ) {
        t = docTemplate = X.Template.create({
          name: 'body',
          template: t
        });
      } else if ( ! t.template && ! t.code ) {
        var future = afuture();
        var path   = self.sourcePath;

        t.futureTemplate = future.get;
        path = path.substring(0, path.lastIndexOf('/')+1);
        path += self.name + '_' + t.name + '.ft';

        if ( window.XMLHttpRequest ) {
          var xhr = new XMLHttpRequest();
          xhr.open("GET", path);
          xhr.asend(function(data) {
            t.template = data;
            future.set(Template.create(t));
          });
        } else {
          var fs = require('fs');
          fs.readFile(path, function(err, data) {
            t.template = data.toString();
            future.set(Template.create(t));
          });
        }
      } else if ( typeof t.template === 'function' ) {
        t.template = multiline(t.template);
      }

      if ( ! t.futureTemplate ) t.futureTemplate = aconstant(t);

      // We haven't FOAMalized the template, and there's no crazy multiline functions.
      // Note that Model and boostrappy models must use this case, as Template is not
      // yet defined at bootstrap time. Use a Template object definition with a bare
      // string template body in those cases.
      if ( ! t.template$ ) {
        t = ( typeof X.Template !== 'undefined' ) ? JSONUtil.mapToObj(X, t, X.Template) : t ;
      }

      return t;
    },

    expandModelTemplates: function(self) {
      var templates = self.templates;
      for ( var i = 0; i < templates.length; i++ ) {
        templates[i] = TemplateUtil.expandTemplate(self, templates[i]);
      }
    }
  }
});

/** Is actually synchronous but is replaced in ChromeApp with an async version. **/
var aeval = function(src) {
  return aconstant(eval('(' + src + ')'));
};

var aevalTemplate = function(t, model) {
  return aseq(
    t.futureTemplate,
    function(ret, t) {
      ret(TemplateUtil.lazyCompile(t));
    });
};

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

/**
 * Simple template system modelled after JSP's.
 *
 * Syntax:
 *    <% code %>: code inserted into template, but nothing implicitly output
 *    <%= comma-separated-values %>: all values are appended to template output
 *    <%# expression %>: dynamic (auto-updating) expression is output
 *    \<new-line>: ignored
 *    %%value(<whitespace>|<): output a single value to the template output
 *    $$feature(<whitespace>|<): output the View or Action for the current Value
 */

MODEL({
  name: 'TemplateParser',
  extendsModel: 'grammar',

  methods: {
    START: sym('markup'),

    markup: repeat0(alt(
      sym('comment'),
      sym('foamTag'),
      sym('create child'),
      sym('simple value'),
      sym('live value tag'),
      sym('raw values tag'),
      sym('values tag'),
      sym('code tag'),
      sym('ignored newline'),
      sym('newline'),
      sym('single quote'),
      sym('text')
    )),

    'comment': seq1(1, '<!--', repeat0(not('-->', anyChar)), '-->'),

    'foamTag': sym('foamTag_'),
    'foamTag_': function() { }, // placeholder until gets filled in after HTMLParser is built

    'create child': seq(
      '$$',
      repeat(notChars(' $\n<{')),
      optional(JSONParser.export('objAsString'))),

    'simple value': seq('%%', repeat(notChars(' ()-"\n><:;,'))),

    'live value tag': seq('<%#', repeat(not('%>', anyChar)), '%>'),

    'raw values tag': alt(
      seq('<%=', repeat(not('%>', anyChar)), '%>'),
      seq('{{{', repeat(not('}}}', anyChar)), '}}}')
    ),

    'values tag': seq('{{', repeat(not('}}', anyChar)), '}}'),

    'code tag': seq('<%', repeat(not('%>', anyChar)), '%>'),
    'ignored newline': literal('\\\n'),
    newline: literal('\n'),
    'single quote': literal("'"),
    text: anyChar
  }
});

var TemplateOutput = {
  /**
   * obj - Parent object.  If objects are output and have an initHTML() method, then they
   * are added to the parent by calling obj.addChild().
   **/
  // TODO(kgr): redesign, I think this is actually broken.  If we call appendHTML() of
  // a sub-view then it will be added to the wrong parent.
  create: function(obj) {
    var buf = [];
    var f = function templateOut(/* arguments */) {
      for ( var i = 0 ; i < arguments.length ; i++ ) {
        var o = arguments[i];
        if ( typeof o === 'string' ) {
          buf.push(o);
        } else {
          if ( o && o.toView_ ) o = o.toView_();
          if ( ! ( o === null || o === undefined ) ) {
            if ( o.appendHTML ) {
              o.appendHTML(this);
            } else if ( o.toHTML ) {
              buf.push(o.toHTML());
            } else {
              buf.push(o);
            }
            if ( o.initHTML && obj.addChild ) obj.addChild(o);
          }
        }
      }
    };

    f.toString = function() {
      if ( buf.length === 0 ) return '';
      if ( buf.length > 1 ) buf = [buf.join('')];
      return buf[0];
    }

    return f;
  }
};

// Called from generated template code.
function elementFromString(str) {
  return str.element || ( str.element = HTMLParser.create().parseString(str).children[0] );
}

var ConstantTemplate = function(str) {
  var TemplateOutputCreate = TemplateOutput.create.bind(TemplateOutput);
  var f = function(opt_out) {
    var out = opt_out ? opt_out : TemplateOutputCreate(this);
    out(str);
    return out.toString();
  };

  f.toString = function() {
    return 'ConstantTemplate("' + str.replace(/\n/g, "\\n").replace(/"/g, '\\"') + '")';
  };

  return f;
};

var TemplateCompiler = {
  __proto__: TemplateParser,

  out: [],

  simple: true, // True iff the template is just one string literal.

  push: function() { this.simple = false; this.pushSimple.apply(this, arguments); },

  pushSimple: function() { this.out.push.apply(this.out, arguments); },

  header: 'var self = this, X = this.X, Y = this.Y;' +
    'var out = opt_out ? opt_out : TOC(this);' +
    "out('",

  footer: "');" +
    "return out.toString();"

}.addActions({
  markup: function (v) {
    var wasSimple = this.simple;
    var ret = wasSimple ? null : this.header + this.out.join('') + this.footer ;
    this.out = [];
    this.simple = true;
    return [wasSimple, ret];
  },

  'create child': function(v) {
    var name = v[1].join('');
    this.push(
      "', self.createTemplateView('", name, "'",
      v[2] ? ', ' + v[2] : '',
      "),\n'");
  },
  foamTag: function(e) {
    // A Feature
    var fName = e.getAttribute('f');
    if ( fName ) {
      this.push("', self.createTemplateView('", fName, "',{}).fromElement(FOAM(");
      this.push(JSONUtil.where(NOT_TRANSIENT).stringify(e));
      this.push('))');
    }
    // A Model
    else {
      this.push("', (function() { var tagView = X.foam.ui.FoamTagView.create({element: FOAM(");
      this.push(JSONUtil.where(NOT_TRANSIENT).stringify(e));
      this.push(')}, Y); self.addDataChild(tagView); return tagView; })() ');
    }

    this.push(",\n'");
  },
  'simple value': function(v) { this.push("',\n self.", v[1].join(''), ",\n'"); },
  'raw values tag': function (v) { this.push("',\n", v[1].join(''), ",\n'"); },
  'values tag':     function (v) { this.push("',\nescapeHTML(", v[1].join(''), "),\n'"); },
  'live value tag': function (v) { this.push("',\nself.dynamicTag('span', function() { return ", v[1].join(''), "; }.bind(this)),\n'"); },
  'code tag': function (v) { this.push("');\n", v[1].join(''), ";out('"); },
  'single quote': function () { this.pushSimple("\\'"); },
  newline: function () { this.pushSimple('\\n'); },
  text: function(v) { this.pushSimple(v); }
});

MODEL({
  name: 'TemplateUtil',

  methods: {
    /** Create a method which only compiles the template when first used. **/
    lazyCompile: function(t) {
      var delegate;

      var f = function() {
        if ( ! delegate ) {
          if ( ! t.template )
            throw 'Must arequire() template model before use for ' + this.name_ + '.' + t.name;
          else
            delegate = TemplateUtil.compile(Template.isInstance(t) ? t : Template.create(t));
        }

        return delegate.apply(this, arguments);
      };

      f.toString = function() { return delegate ? delegate.toString() : t.toString(); };

      return f;
    },

    compile_: function(t, code) {
      var args = ['opt_out'];
      for ( var i = 0 ; i < t.args.length ; i++ ) {
        args.push(t.args[i].name);
      }
      return eval('(function() { var escapeHTML = XMLUtil.escape, TOC = TemplateOutput.create.bind(TemplateOutput); return function(' + args.join(',') + '){' + code + '};})()');
    },
    compile: function(t) {
      // console.time('parse-template-' + t.name);
      var code = TemplateCompiler.parseString(t.template);
      // console.timeEnd('parse-template-' + t.name);

      // Simple case, just a string literal
      if ( code[0] ) return ConstantTemplate(t.template);

      // Need to compile an actual method
      try {
        return this.compile_(t, code[1]);
      } catch (err) {
        console.log('Template Error: ', err);
        console.log(code);
        return function() {};
      }
    },

    /**
     * Combinator which takes a template which expects an output parameter and
     * converts it into a function which returns a string.
     */
    stringifyTemplate: function (template) {
      return function() {
        var buf = [];

        this.output(buf.push.bind(buf), obj);

        return buf.join('');
      };
    },

    expandTemplate: function(self, t, opt_X) {
      /*
       * If a template is supplied as a function, treat it as a multiline string.
       * Parse function arguments to populate template.args.
       * Load template from file if external.
       * Setup template future.
       */
      var X = opt_X || self.X;

      if ( typeof t === 'function' ) {
        t = X.Template.create({
          name: t.name,
          // ignore first argument, which should be 'opt_out'
          args: t.toString().match(/\((.*?)\)/)[1].split(',').slice(1).map(function(a) {
            return X.Arg.create({name: a.trim()});
          }),
          template: multiline(t)});
      } else if ( typeof t === 'string' ) {
        t = docTemplate = X.Template.create({
          name: 'body',
          template: t
        });
      } else if ( ! t.template && ! t.code ) {
        var future = afuture();
        var path   = self.sourcePath;

        t.futureTemplate = future.get;
        path = path.substring(0, path.lastIndexOf('/')+1);
        path += self.name + '_' + t.name + '.ft';

        if ( window.XMLHttpRequest ) {
          var xhr = new XMLHttpRequest();
          xhr.open("GET", path);
          xhr.asend(function(data) {
            t.template = data;
            future.set(Template.create(t));
          });
        } else {
          var fs = require('fs');
          fs.readFile(path, function(err, data) {
            t.template = data.toString();
            future.set(Template.create(t));
          });
        }
      } else if ( typeof t.template === 'function' ) {
        t.template = multiline(t.template);
      }

      if ( ! t.futureTemplate ) t.futureTemplate = aconstant(t);

      // We haven't FOAMalized the template, and there's no crazy multiline functions.
      // Note that Model and boostrappy models must use this case, as Template is not
      // yet defined at bootstrap time. Use a Template object definition with a bare
      // string template body in those cases.
      if ( ! t.template$ ) {
        t = ( typeof X.Template !== 'undefined' ) ? JSONUtil.mapToObj(X, t, X.Template) : t ;
      }

      return t;
    },

    expandModelTemplates: function(self) {
      var templates = self.templates;
      for ( var i = 0; i < templates.length; i++ ) {
        templates[i] = TemplateUtil.expandTemplate(self, templates[i]);
      }
    }
  }
});

/** Is actually synchronous but is replaced in ChromeApp with an async version. **/
var aeval = function(src) {
  return aconstant(eval('(' + src + ')'));
};

var aevalTemplate = function(t, model) {
  return aseq(
    t.futureTemplate,
    function(ret, t) {
      ret(TemplateUtil.lazyCompile(t));
    });
};

var escapeHTML = XMLUtil.escape, TOC = TemplateOutput.create.bind(TemplateOutput);
<|endoftext|>


<commit_before>CY = null;
gPrefs = null;
gLayout = null;
gDb = null;
gIComments = null;
gSync = null;
gGETValues = null;

gConf = {'iCommentLeftPadding':4,
		'iCommentThreadPadding':12,
        'defaultCommentFormat':'markdown',
        'sliderFixedMin':.9,
        'sliderFixedMax':.1,
        'iCommentsInitAlloc':2,
        'defaultPrefs':{'text':{'style':'text-modern-style'}, 'user' : {'name' : '','email' : ''},'general': {'animduration' : '0.4'},'comments': {'threadpad' : '1'},'layout': {'comments_col_width' : '25'  /* out of 100 */}}
};

//available text styles in c-text-styles.css
//classname(key) : will be added to #textcontainer, name(value) : the name to display in style dropdown choice"
gTextStyles = {'text-modern-style':gettext('modern'), 'text-classic-style':gettext('classic'), 'text-code-style':gettext('code')};

YUI( {
	base :sv_media_url + "/js/lib/yui/" + c_yui_base + "/build/",
	// filter: '{% if CLIENT_DEBUG %}debug{% else %}raw{% endif %}',
	// filter :'raw',
	timeout :10000
}).use(
	    "text-modern-style",
		"cookie",
		"json",
		"overlay",
		"io-form",
		"async-queue",
		"event-mouseenter",
		"anim",
		"collection",
		function(Y) {
	        CY = Y;

            gPrefs = new Preferences() ;
            gPrefs.init() ;

            gLayout = new Layout() ;
            gLayout.init() ;

    		if (sv_withComments) {
	            gDb = new Db() ;
	            gDb.init() ;

	            gIComments = new IComments() ;
	            gIComments.init() ;
    		}

            gSync = new Sync() ;
            gSync.init() ;

			CY.on("domready", onDomReady, this);

		});

_reinit = function(filterRes) {
	gIComments.hide();
	gDb.initComments(filterRes['commentIds']);

	unpaintAllComments();
	renderCommentScopes();

	updateFilterResultsCount(filterRes['nbDiscussions'], filterRes['nbComments'], filterRes['nbReplies']);
};

reinit = function(filterGETValues) {
	var filterRes = gDb.computeFilterResults(filterGETValues);
	_reinit(filterRes);
};

hideAll = function() {
	_reinit({'commentIds':[],'nbDiscussions':0, 'nbComments':0, 'nbReplies':0});
};

updateFilterResultsCount = function(nbDiscussions, nbComments, nbReplies) {
	var r = gDb.getCommentsAndRepliesCounts(true);
	var nbAllComments = r[0], nbAllReplies = r[1];
	var detailedResults = (nbComments != 0 || nbReplies != 0) && (nbAllComments != nbComments || nbAllReplies != nbReplies) ;
	if (gLayout.isInFrame()) {
		parent.f_updateFilterCountDetailed(detailedResults) ;
		parent.f_updateFilterCountResult(nbDiscussions, nbComments, nbReplies, nbAllComments, nbAllReplies);
	}
};

updateResetFilterResultsCount = function() {
	var counts = gDb.getCommentsAndRepliesCounts(false)
	var nbComments = counts[0], nbReplies = counts[1];

	var nbDiscussions = nbComments;
	updateFilterResultsCount(nbDiscussions, nbComments, nbReplies);
};

// TODO MOVE
renderCommentScopes = function() {
	for (var i = 0 ; i < gDb.comments.length ; i++) {
		var comment = gDb.comments[i] ;
		paintCommentScope(comment) ;
	}
} ;

onTextMouseUp = function(e) {
	if (readyForAction()) {
		var selection = getSelectionInfo() ;
		if (selection != null) {
			updateICommentFormSelection(selection) ;
			if (gEditICommentHost != null) {
				var modifyScope = CY.get("#"+gEdit['ids']['changeScopeInputId']+" input").get('checked') ;
				if (modifyScope) {
					gEditICommentHost.scrollIntoView() ;
				}
			}
		}
		else {
			var node = e.target ;
			if (node.hasClass('c-c')) {
				var elt = CY.Node.getDOMNode(node) ;
				var commentIds = getCommentIdsFromClasses(elt) ;
				if (commentIds.length > 0) {
					checkForOpenedDialog(null, function() { // will only check for reply
						gSync.showComments(commentIds, [e.pageX, e.pageY], false) ;
					}) ;
				}
			}
		}
//// FIRST UPDATE SELECTION IF ANY AND SCROLL TO EDITION IF ANY
//		if (isICommentFormVisible() || gEditICommentHost != null) {
//			CY.log(selection) ;
//			updateICommentFormSelection(selection) ;
//
//			if (gEditICommentHost != null) {
//				var modifyScope = CY.get("#"+gEdit['ids']['changeScopeInputId']+" input").get('checked') ;
//				if (modifyScope) {
//					gEditICommentHost.scrollIntoView() ;
//					didSomething = true ;
//				}
//			}
//			if (isICommentFormVisible())
//			didSomething = true ;
//		}
//		else {
//			checkForOpenedDialog(null, function() { // will only check for reply
//					var node = e.target ;
//					if (node.hasClass('c-c')) {
//						var elt = CY.Node.getDOMNode(node) ;
//						var commentIds = getCommentIdsFromClasses(elt) ;
//						if (commentIds.length > 0) {
//							//hideOverlay(gICommentForm) ;
//							// gIComments.hide() ;20080814 moved it to gSync._showComments
//							gSync.showComments(commentIds, [e.pageX, e.pageY]) ;
//						}
//					}
//				}) ;
//		}
	}
} ;

gLastScrollTime = null ;
checkForAlignement = function () {
	var now = (new Date()).getTime() ;
	if ((gLastScrollTime != null) && (now - gLastScrollTime) > 200) {
		positionICommentForm() ;
		gLastScrollTime = null ;
	}
};

onFrameScroll = function () {
	gLastScrollTime = (new Date()).getTime() ;
};

browse = function(order, whereto) {
	gSync.browse(order, whereto) ;
};

initialConnect = function() {
	CY.on("mouseup", onTextMouseUp, "#textcontainer");
	gTimer = CY.Lang.later(200, this, checkForAlignement, [], true) ;
	CY.on('scroll', onFrameScroll, window, this, true);
	CY.on('resize', onFrameScroll, window, this, true);
};

preventLinksInText = function() {
	var interceptLink = function(e) {
		var a = e.target;
		var href = null;
		while (a != null && href == null) {
			a = a.get('parentNode');
			href = a.get("href");
		}

		if (a != null && href != null) {
			//alert(window.location) ;
			var clean_window_location = window.location.href ;

			var ind = clean_window_location.indexOf('#') ;
			if (ind != -1)
				clean_window_location = clean_window_location.substring(0, ind) ;

			if (href.indexOf(clean_window_location) == -1 ) {
				window.open(a.get("href"));
				e.preventDefault(); ;
			}
		}
	} ;

	CY.all("#textcontainer a").on("click", interceptLink);
};

onDomReady = function(arg1) {
	preventLinksInText();
	var q1 = new CY.AsyncQueue(); //
	// doesn't behave like the doc says :
	// no timeout -> seems in blocking mode
	q1.add( {
		fn : function() {

			if (gLayout.isInComentSite()) {
				parent.toInitialSize();
			}
			if (sv_withComments) {
				instanciateICommentForm();
			}
		},
		timeout :5
	}, {
		fn : function() {

			gGETValues = CY.JSON.parse(sv_get_params);

			CY.get('#maincontainer').setStyle('display', 'block');
			CY.get('#textcontainer').setStyle('display', 'block');

			var val = (sv_withComments) ? gPrefs.get('layout','comments_col_width') : 0 ;
			var colWidth = sliderValToPx(val) ;
			gLayout.setLeftColumnWidth(colWidth) ;

			if (gLayout.isInFrame()) {
				parent.f_initFrame();
				parent.f_layoutFrames();

				if (sv_withComments) {
					parent.f_fillTopToolbar() ;
					if (hasPerm("can_create_comment"))
						parent.$("#add_comment_btn").removeClass('initially_hidden');
					//parent.enqueueLoadingMsg(); // no more loading message ? TODO

					parent.f_fillFilterTab() ;
					parent.f_fillPreferencesTab() ;

//					parent.f_fillBrowseSection() ;

					var firstTimeFilterData = CY.JSON.parse(sv_filter_data);
					parent.f_updateFilterData(firstTimeFilterData);

					parent.f_setFilterValue(gGETValues) ;
				}
				parent.f_fillTextPreferencesTab() ;
			}

			if (gLayout.isInComentSite())
				parent.$("#c_fullscreen_btn").show();
			else {
				parent.$("#c_fullscreen_btn").hide();
			}

		},
		timeout :5
	}, {
		fn : function() {
			if (sv_withComments) {

				reinit(gGETValues);
				initialConnect();
			}
		},
		timeout :5
	}, {
		fn : function() {
			if (gLayout.isInFrame()) {
				parent.f_interfaceUnfreeze() ;
				parent.f_removeLoadingMsg();
			}
			// if there is a comment id in the url display it
			if ("comment_id_key" in gGETValues) {
				var id_key = gGETValues["comment_id_key"] ;
				var comment = gDb.getCommentByIdKey(id_key) ;
				if (comment != null) {
					var path = gDb.getPath(comment) ;
					var topParentComment = path[path.length - 1] ;
					gSync.showSingleComment(topParentComment) ;
				}
			}

//			else {
//			gSync.showAllComments() ;// show all
//			}
		}
	});
	q1.run();
};

<commit_msg>add comments_auto_display parameter to embed to auto expand comments<commit_after>CY = null;
gPrefs = null;
gLayout = null;
gDb = null;
gIComments = null;
gSync = null;
gGETValues = null;

gConf = {'iCommentLeftPadding':4,
		'iCommentThreadPadding':12,
        'defaultCommentFormat':'markdown',
        'sliderFixedMin':.9,
        'sliderFixedMax':.1,
        'iCommentsInitAlloc':2,
        'defaultPrefs':{'text':{'style':'text-modern-style'}, 'user' : {'name' : '','email' : ''},'general': {'animduration' : '0.4'},'comments': {'threadpad' : '1'},'layout': {'comments_col_width' : '25'  /* out of 100 */}}
};

//available text styles in c-text-styles.css
//classname(key) : will be added to #textcontainer, name(value) : the name to display in style dropdown choice"
gTextStyles = {'text-modern-style':gettext('modern'), 'text-classic-style':gettext('classic'), 'text-code-style':gettext('code')};

YUI( {
	base :sv_media_url + "/js/lib/yui/" + c_yui_base + "/build/",
	// filter: '{% if CLIENT_DEBUG %}debug{% else %}raw{% endif %}',
	// filter :'raw',
	timeout :10000
}).use(
	    "text-modern-style",
		"cookie",
		"json",
		"overlay",
		"io-form",
		"async-queue",
		"event-mouseenter",
		"anim",
		"collection",
		function(Y) {
	        CY = Y;

            gPrefs = new Preferences() ;
            gPrefs.init() ;

            gLayout = new Layout() ;
            gLayout.init() ;

    		if (sv_withComments) {
	            gDb = new Db() ;
	            gDb.init() ;

	            gIComments = new IComments() ;
	            gIComments.init() ;
    		}

            gSync = new Sync() ;
            gSync.init() ;

			CY.on("domready", onDomReady, this);

		});

_reinit = function(filterRes) {
	gIComments.hide();
	gDb.initComments(filterRes['commentIds']);

	unpaintAllComments();
	renderCommentScopes();

	updateFilterResultsCount(filterRes['nbDiscussions'], filterRes['nbComments'], filterRes['nbReplies']);
};

reinit = function(filterGETValues) {
	var filterRes = gDb.computeFilterResults(filterGETValues);
	_reinit(filterRes);
};

hideAll = function() {
	_reinit({'commentIds':[],'nbDiscussions':0, 'nbComments':0, 'nbReplies':0});
};

updateFilterResultsCount = function(nbDiscussions, nbComments, nbReplies) {
	var r = gDb.getCommentsAndRepliesCounts(true);
	var nbAllComments = r[0], nbAllReplies = r[1];
	var detailedResults = (nbComments != 0 || nbReplies != 0) && (nbAllComments != nbComments || nbAllReplies != nbReplies) ;
	if (gLayout.isInFrame()) {
		parent.f_updateFilterCountDetailed(detailedResults) ;
		parent.f_updateFilterCountResult(nbDiscussions, nbComments, nbReplies, nbAllComments, nbAllReplies);
	}
};

updateResetFilterResultsCount = function() {
	var counts = gDb.getCommentsAndRepliesCounts(false)
	var nbComments = counts[0], nbReplies = counts[1];

	var nbDiscussions = nbComments;
	updateFilterResultsCount(nbDiscussions, nbComments, nbReplies);
};

// TODO MOVE
renderCommentScopes = function() {
	for (var i = 0 ; i < gDb.comments.length ; i++) {
		var comment = gDb.comments[i] ;
		paintCommentScope(comment) ;
	}
} ;

onTextMouseUp = function(e) {
	if (readyForAction()) {
		var selection = getSelectionInfo() ;
		if (selection != null) {
			updateICommentFormSelection(selection) ;
			if (gEditICommentHost != null) {
				var modifyScope = CY.get("#"+gEdit['ids']['changeScopeInputId']+" input").get('checked') ;
				if (modifyScope) {
					gEditICommentHost.scrollIntoView() ;
				}
			}
		}
		else {
			var node = e.target ;
			if (node.hasClass('c-c')) {
				var elt = CY.Node.getDOMNode(node) ;
				var commentIds = getCommentIdsFromClasses(elt) ;
				if (commentIds.length > 0) {
					checkForOpenedDialog(null, function() { // will only check for reply
						gSync.showComments(commentIds, [e.pageX, e.pageY], false) ;
					}) ;
				}
			}
		}
//// FIRST UPDATE SELECTION IF ANY AND SCROLL TO EDITION IF ANY
//		if (isICommentFormVisible() || gEditICommentHost != null) {
//			CY.log(selection) ;
//			updateICommentFormSelection(selection) ;
//
//			if (gEditICommentHost != null) {
//				var modifyScope = CY.get("#"+gEdit['ids']['changeScopeInputId']+" input").get('checked') ;
//				if (modifyScope) {
//					gEditICommentHost.scrollIntoView() ;
//					didSomething = true ;
//				}
//			}
//			if (isICommentFormVisible())
//			didSomething = true ;
//		}
//		else {
//			checkForOpenedDialog(null, function() { // will only check for reply
//					var node = e.target ;
//					if (node.hasClass('c-c')) {
//						var elt = CY.Node.getDOMNode(node) ;
//						var commentIds = getCommentIdsFromClasses(elt) ;
//						if (commentIds.length > 0) {
//							//hideOverlay(gICommentForm) ;
//							// gIComments.hide() ;20080814 moved it to gSync._showComments
//							gSync.showComments(commentIds, [e.pageX, e.pageY]) ;
//						}
//					}
//				}) ;
//		}
	}
} ;

gLastScrollTime = null ;
checkForAlignement = function () {
	var now = (new Date()).getTime() ;
	if ((gLastScrollTime != null) && (now - gLastScrollTime) > 200) {
		positionICommentForm() ;
		gLastScrollTime = null ;
	}
};

onFrameScroll = function () {
	gLastScrollTime = (new Date()).getTime() ;
};

browse = function(order, whereto) {
	gSync.browse(order, whereto) ;
};

initialConnect = function() {
	CY.on("mouseup", onTextMouseUp, "#textcontainer");
	gTimer = CY.Lang.later(200, this, checkForAlignement, [], true) ;
	CY.on('scroll', onFrameScroll, window, this, true);
	CY.on('resize', onFrameScroll, window, this, true);
};

preventLinksInText = function() {
	var interceptLink = function(e) {
		var a = e.target;
		var href = null;
		while (a != null && href == null) {
			a = a.get('parentNode');
			href = a.get("href");
		}

		if (a != null && href != null) {
			//alert(window.location) ;
			var clean_window_location = window.location.href ;

			var ind = clean_window_location.indexOf('#') ;
			if (ind != -1)
				clean_window_location = clean_window_location.substring(0, ind) ;

			if (href.indexOf(clean_window_location) == -1 ) {
				window.open(a.get("href"));
				e.preventDefault(); ;
			}
		}
	} ;

	CY.all("#textcontainer a").on("click", interceptLink);
};

onDomReady = function(arg1) {
	preventLinksInText();
	var q1 = new CY.AsyncQueue(); //
	// doesn't behave like the doc says :
	// no timeout -> seems in blocking mode
	q1.add( {
		fn : function() {

			if (gLayout.isInComentSite()) {
				parent.toInitialSize();
			}
			if (sv_withComments) {
				instanciateICommentForm();
			}
		},
		timeout :5
	}, {
		fn : function() {

			gGETValues = CY.JSON.parse(sv_get_params);

			CY.get('#maincontainer').setStyle('display', 'block');
			CY.get('#textcontainer').setStyle('display', 'block');

			var val = (sv_withComments) ? gPrefs.get('layout','comments_col_width') : 0 ;
			var colWidth = sliderValToPx(val) ;
			gLayout.setLeftColumnWidth(colWidth) ;

			if (gLayout.isInFrame()) {
				parent.f_initFrame();
				parent.f_layoutFrames();

				if (sv_withComments) {
					parent.f_fillTopToolbar() ;
					if (hasPerm("can_create_comment"))
						parent.$("#add_comment_btn").removeClass('initially_hidden');
					//parent.enqueueLoadingMsg(); // no more loading message ? TODO

					parent.f_fillFilterTab() ;
					parent.f_fillPreferencesTab() ;

//					parent.f_fillBrowseSection() ;

					var firstTimeFilterData = CY.JSON.parse(sv_filter_data);
					parent.f_updateFilterData(firstTimeFilterData);

					parent.f_setFilterValue(gGETValues) ;
				}
				parent.f_fillTextPreferencesTab() ;
			}

			if (gLayout.isInComentSite())
				parent.$("#c_fullscreen_btn").show();
			else {
				parent.$("#c_fullscreen_btn").hide();
			}

		},
		timeout :5
	}, {
		fn : function() {
			if (sv_withComments) {

				reinit(gGETValues);
				initialConnect();
			}
		},
		timeout :5
	}, {
		fn : function() {
			if (gLayout.isInFrame()) {
				parent.f_interfaceUnfreeze() ;
				parent.f_removeLoadingMsg();
			}
			// if there is a comment id in the url display it
			if ("comment_id_key" in gGETValues) {
				var id_key = gGETValues["comment_id_key"] ;
				var comment = gDb.getCommentByIdKey(id_key) ;
				if (comment != null) {
					var path = gDb.getPath(comment) ;
					var topParentComment = path[path.length - 1] ;
					gSync.showSingleComment(topParentComment) ;
				}
			}

			// if comment_auto_display: show all comments
			if ("comments_auto_display" in gGETValues) {
				gSync.showAllComments();
			}

//			else {
//			gSync.showAllComments() ;// show all
//			}
		}
	});
	q1.run();
};

<|endoftext|>


<commit_before>const { app, BrowserWindow, shell, Menu } = require('electron');
const createRPC = require('./rpc');
const createMenu = require('./menu');
const uuid = require('uuid');
const { resolve } = require('path');
const isDev = require('electron-is-dev');
const AutoUpdater = require('./auto-updater');
const toHex = require('convert-css-color-name-to-hex');
const notify = require('./notify');

app.commandLine.appendSwitch('js-flags', '--harmony');

// set up config
const config = require('./config');
config.init();
const plugins = require('./plugins');
const Session = require('./session');

const windowSet = new Set([]);

// expose to plugins
app.config = config;
app.plugins = plugins;
app.getWindows = () => new Set([...windowSet]); // return a clone

if (isDev) {
  console.log('running in dev mode');
} else {
  console.log('running in prod mode');
}

const url = 'file://' + resolve(
  isDev ? __dirname : app.getAppPath(),
  'index.html'
);

console.log('electron will open', url);

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('ready', () => {
  function createWindow (fn) {
    let cfg = plugins.getDecoratedConfig();

    const [width, height] = cfg.windowSize || [540, 380];

    const browserDefaults = {
      width,
      height,
      minHeight: 190,
      minWidth: 370,
      titleBarStyle: 'hidden-inset',
      title: 'HyperTerm',
      backgroundColor: toHex(cfg.backgroundColor || '#000'),
      transparent: true,
      icon: resolve(__dirname, 'static/icon.png'),
      // we only want to show when the prompt
      // is ready for user input
      show: process.env.HYPERTERM_DEBUG || isDev
    };
    const browserOptions = plugins.getDecoratedBrowserOptions(browserDefaults);

    const win = new BrowserWindow(browserOptions);

    windowSet.add(win);
    win.loadURL(url);

    const rpc = createRPC(win);
    const sessions = new Map();

    // config changes
    const cfgUnsubscribe = config.subscribe(() => {
      const cfg_ = plugins.getDecoratedConfig();

      win.webContents.send('config change');

      if (cfg_.shell !== cfg.shell) {
        notify(
          'Shell configuration changed!',
          'Open a new tab or window to start using the new shell'
        );
      }

      cfg = cfg_;
    });

    rpc.on('init', () => {
      win.show();
      if (fn) fn(win);

      // auto updates
      if (!isDev && process.platform !== 'linux') {
        AutoUpdater(win);
      } else {
        console.log('ignoring auto updates during dev');
      }
    });

    rpc.on('new', ({ rows = 40, cols = 100, cwd = process.env.HOME }) => {
      const shell = cfg.shell;

      initSession({ rows, cols, cwd, shell }, (uid, session) => {
        sessions.set(uid, session);
        rpc.emit('session add', {
          uid,
          shell: session.shell,
          pid: session.pty.pid
        });

        session.on('data', (data) => {
          rpc.emit('session data', { uid, data });
        });

        session.on('title', (title) => {
          rpc.emit('session title', { uid, title });
        });

        session.on('exit', () => {
          rpc.emit('session exit', { uid });
          sessions.delete(uid);
        });
      });
    });

    // TODO: this goes away when we are able to poll
    // for the title ourseleves, instead of relying
    // on Session and focus/blur to subscribe
    rpc.on('focus', ({ uid }) => {
      const session = sessions.get(uid);

      if (session) {
        session.focus();
      } else {
        console.log('session not found by', uid);
      }
    });

    rpc.on('blur', ({ uid }) => {
      const session = sessions.get(uid);

      if (session) {
        session.blur();
      } else {
        console.log('session not found by', uid);
      }
    });

    rpc.on('exit', ({ uid }) => {
      const session = sessions.get(uid);

      if (session) {
        session.exit();
      } else {
        console.log('session not found by', uid);
      }
    });

    rpc.on('unmaximize', () => {
      win.unmaximize();
    });

    rpc.on('maximize', () => {
      win.maximize();
    });

    rpc.on('resize', ({ cols, rows }) => {
      sessions.forEach((session) => {
        session.resize({ cols, rows });
      });
    });

    rpc.on('data', ({ uid, data }) => {
      sessions.get(uid).write(data);
    });

    rpc.on('open external', ({ url }) => {
      shell.openExternal(url);
    });

    rpc.win.on('move', () => {
      rpc.emit('move');
    });

    const deleteSessions = () => {
      sessions.forEach((session, key) => {
        session.removeAllListeners();
        session.destroy();
        sessions.delete(key);
      });
    };

    // we reset the rpc channel only upon
    // subsequent refreshes (ie: F5)
    let i = 0;
    win.webContents.on('did-navigate', () => {
      if (i++) {
        deleteSessions();
      }
    });

    // expose internals to extension authors
    win.rpc = rpc;
    win.sessions = sessions;

    const load = () => {
      plugins.onWindow(win);
    };

    // load plugins
    load();

    const pluginsUnsubscribe = plugins.subscribe((err) => {
      if (!err) {
        load();
        win.webContents.send('plugins change');
      }
    });

    // the window can be closed by the browser process itself
    win.on('close', () => {
      windowSet.delete(win);
      rpc.destroy();
      deleteSessions();
      cfgUnsubscribe();
      pluginsUnsubscribe();
      if (windowSet.size === 0) {
        win.close();
      }
    });
  }

  // when opening create a new window
  createWindow();

  // expose to plugins
  app.createWindow = createWindow;

  // mac only. when the dock icon is clicked
  // and we don't have any active windows open,
  // we open one
  app.on('activate', () => {
    if (!windowSet.size) {
      createWindow();
    }
  });

  const setupMenu = () => {
    const tpl = plugins.decorateMenu(createMenu({
      createWindow,
      updatePlugins: () => {
        plugins.updatePlugins({ force: true });
      }
    }));

    Menu.setApplicationMenu(Menu.buildFromTemplate(tpl));
  };

  const load = () => {
    plugins.onApp(app);
    setupMenu();
  };

  load();
  plugins.subscribe(load);
});

function initSession (opts, fn) {
  fn(uuid.v4(), new Session(opts));
}
<commit_msg>Fix #467 and #206; quit app on window close (#489)<commit_after>const { app, BrowserWindow, shell, Menu } = require('electron');
const createRPC = require('./rpc');
const createMenu = require('./menu');
const uuid = require('uuid');
const { resolve } = require('path');
const isDev = require('electron-is-dev');
const AutoUpdater = require('./auto-updater');
const toHex = require('convert-css-color-name-to-hex');
const notify = require('./notify');

app.commandLine.appendSwitch('js-flags', '--harmony');

// set up config
const config = require('./config');
config.init();
const plugins = require('./plugins');
const Session = require('./session');

const windowSet = new Set([]);

// expose to plugins
app.config = config;
app.plugins = plugins;
app.getWindows = () => new Set([...windowSet]); // return a clone

if (isDev) {
  console.log('running in dev mode');
} else {
  console.log('running in prod mode');
}

const url = 'file://' + resolve(
  isDev ? __dirname : app.getAppPath(),
  'index.html'
);

console.log('electron will open', url);

app.on('ready', () => {
  function createWindow (fn) {
    let cfg = plugins.getDecoratedConfig();

    const [width, height] = cfg.windowSize || [540, 380];

    const browserDefaults = {
      width,
      height,
      minHeight: 190,
      minWidth: 370,
      titleBarStyle: 'hidden-inset',
      title: 'HyperTerm',
      backgroundColor: toHex(cfg.backgroundColor || '#000'),
      transparent: true,
      icon: resolve(__dirname, 'static/icon.png'),
      // we only want to show when the prompt
      // is ready for user input
      show: process.env.HYPERTERM_DEBUG || isDev
    };
    const browserOptions = plugins.getDecoratedBrowserOptions(browserDefaults);

    const win = new BrowserWindow(browserOptions);

    windowSet.add(win);
    win.loadURL(url);

    const rpc = createRPC(win);
    const sessions = new Map();

    // config changes
    const cfgUnsubscribe = config.subscribe(() => {
      const cfg_ = plugins.getDecoratedConfig();

      win.webContents.send('config change');

      if (cfg_.shell !== cfg.shell) {
        notify(
          'Shell configuration changed!',
          'Open a new tab or window to start using the new shell'
        );
      }

      cfg = cfg_;
    });

    rpc.on('init', () => {
      win.show();
      if (fn) fn(win);

      // auto updates
      if (!isDev && process.platform !== 'linux') {
        AutoUpdater(win);
      } else {
        console.log('ignoring auto updates during dev');
      }
    });

    rpc.on('new', ({ rows = 40, cols = 100, cwd = process.env.HOME }) => {
      const shell = cfg.shell;

      initSession({ rows, cols, cwd, shell }, (uid, session) => {
        sessions.set(uid, session);
        rpc.emit('session add', {
          uid,
          shell: session.shell,
          pid: session.pty.pid
        });

        session.on('data', (data) => {
          rpc.emit('session data', { uid, data });
        });

        session.on('title', (title) => {
          rpc.emit('session title', { uid, title });
        });

        session.on('exit', () => {
          rpc.emit('session exit', { uid });
          sessions.delete(uid);
        });
      });
    });

    // TODO: this goes away when we are able to poll
    // for the title ourseleves, instead of relying
    // on Session and focus/blur to subscribe
    rpc.on('focus', ({ uid }) => {
      const session = sessions.get(uid);

      if (session) {
        session.focus();
      } else {
        console.log('session not found by', uid);
      }
    });

    rpc.on('blur', ({ uid }) => {
      const session = sessions.get(uid);

      if (session) {
        session.blur();
      } else {
        console.log('session not found by', uid);
      }
    });

    rpc.on('exit', ({ uid }) => {
      const session = sessions.get(uid);

      if (session) {
        session.exit();
      } else {
        console.log('session not found by', uid);
      }
    });

    rpc.on('unmaximize', () => {
      win.unmaximize();
    });

    rpc.on('maximize', () => {
      win.maximize();
    });

    rpc.on('resize', ({ cols, rows }) => {
      sessions.forEach((session) => {
        session.resize({ cols, rows });
      });
    });

    rpc.on('data', ({ uid, data }) => {
      sessions.get(uid).write(data);
    });

    rpc.on('open external', ({ url }) => {
      shell.openExternal(url);
    });

    rpc.win.on('move', () => {
      rpc.emit('move');
    });

    const deleteSessions = () => {
      sessions.forEach((session, key) => {
        session.removeAllListeners();
        session.destroy();
        sessions.delete(key);
      });
    };

    // we reset the rpc channel only upon
    // subsequent refreshes (ie: F5)
    let i = 0;
    win.webContents.on('did-navigate', () => {
      if (i++) {
        deleteSessions();
      }
    });

    // expose internals to extension authors
    win.rpc = rpc;
    win.sessions = sessions;

    const load = () => {
      plugins.onWindow(win);
    };

    // load plugins
    load();

    const pluginsUnsubscribe = plugins.subscribe((err) => {
      if (!err) {
        load();
        win.webContents.send('plugins change');
      }
    });

    // the window can be closed by the browser process itself
    win.on('close', () => {
      windowSet.delete(win);
      rpc.destroy();
      deleteSessions();
      cfgUnsubscribe();
      pluginsUnsubscribe();
    });

    win.on('closed', () => {
      if (process.platform !== 'darwin') {
        app.quit();
      }
    });
  }

  // when opening create a new window
  createWindow();

  // expose to plugins
  app.createWindow = createWindow;

  // mac only. when the dock icon is clicked
  // and we don't have any active windows open,
  // we open one
  app.on('activate', () => {
    if (!windowSet.size) {
      createWindow();
    }
  });

  const setupMenu = () => {
    const tpl = plugins.decorateMenu(createMenu({
      createWindow,
      updatePlugins: () => {
        plugins.updatePlugins({ force: true });
      }
    }));

    Menu.setApplicationMenu(Menu.buildFromTemplate(tpl));
  };

  const load = () => {
    plugins.onApp(app);
    setupMenu();
  };

  load();
  plugins.subscribe(load);
});

function initSession (opts, fn) {
  fn(uuid.v4(), new Session(opts));
}
<|endoftext|>


<commit_before>$(document).ready(function() {
    //tutti gli eventi ajax che evvengono in plist sono nel formato pilst.on(evento,[selettore],function(...){...});
    var plist = $("#postlist");
    var loading = N.getLangData().LOADING;
    var lang = null; /* globale dato che la uso anche altrove */
    var load = false; //gestisce i caricamenti ed evita sovrapposizioni. Dichiarata qui che è il foglio che viene incluso di default ovunque e per primo
    plist.html('
'+loading+'...
');

    var fixHeights = function() {
        plist.find(".nerdz_message").each (function() {
            var el = $(this).find('div:first');
            // TODO: switch from attr('data-parsed') to data('parsed')
            if ((el.height() >= 200 || el.find ('.gistLoad').length > 0) && !el.attr('data-parsed'))
            {
                el.data ('real-height', el.height()).addClass ("compressed");
                var n = el.next();
                n.prepend ('
>> ' + N.getLangData().EXPAND + ' <<
'); // Spaces master race.
            }
            el.attr('data-parsed','1');
        });
    };

    var onRemoveHiddenPost = function() {
        var me = $(this), target = me.data ("target"), lv = localStorage.getItem ("hid").split ("|"), serialized = "";
        $("#" + target).slideToggle (function() {
            $(this).find (".img_frame > img").each (function() {
                $(this).css ("margin-top", (117 - $(this).height()) / 2);
            });
        });
        me.parent().remove();
        for (var zxcvbn in lv)
            if (lv[zxcvbn] != target)
                serialized += lv[zxcvbn] + "|";
        if (serialized !== '')
            localStorage.setItem ("hid", serialized.slice (0, -1));
        else
        {
            localStorage.removeItem ("hid");
            $("#hp-cnt").remove();
            $("#hp-title").remove();
        }
    };

    var hideHidden = function() {
        var hidden = localStorage.getItem ("hid");
        if (hidden !== null)
        {
            var pids = hidden.split ("|").sort().reverse(), len = pids.length;
            while (len--)
            {
                var post = plist.find ("#" + pids[len]);
                if (post.length)
                {
                    post.hide();
                    var pLink = window[pids[len].replace (/post/, "lnk")] || "#";
                    pids[len] = $(document.createElement("li"))
                        .append ($(document.createElement("a")).attr ("href", pLink).text (decodeURIComponent (pLink.substr (1))))
                        .append ($(document.createElement("a")).data ("target", pids[len]).css ("float", "right").html ("X").click (onRemoveHiddenPost));
                }
                else
                    pids.splice (len, 1);
            }
            if (pids.length)
            {
                if (!$("#hp-cnt").length)
                {
                    // create the hidden posts box
                    $(document.createElement("div")).addClass ("title").click (function() {
                        $("#hp-cnt").slideToggle();
                    }).html (N.getStaticData().lang.HIDDEN_POSTS).attr ("id", "hp-title").appendTo ("#right_col");
                    $(document.createElement("div")).hide().addClass ("box").attr ("id", "hp-cnt")
                        .append ($(document.createElement ("ul")).html (pids)).appendTo ("#right_col");
                }
                else
                    $("#hp-cnt ul").html (pids);
            }
        }
        // Hide 'blacklisted user changed nickname'
        // We ALWAYS have windows.idios that is the blacklisted users array
        $("#postlist ").find(".news a:nth-last-child(3)").each(function() {
            if($.inArray($(this).html(), window.idiots) > -1) {
                $(this).parent().parent().hide();
            }
        });

        fixHeights();
    };

    plist.on('click',".spoiler",function(){
      if($(this).data("parsed")) return;
      $.each($(this).find("img"),function(){
        m = (117-$(this).height())/2;
        if (m>1)
          $(this).css("margin-top", m);
      });
      $(this).data("parsed","1");
    });

    plist.on('click','.more',function() {
        var me = $(this), par = me.parent(), jenk = par.prev();
        if (me.data ('busy') == 'godyes') return;
        me.data ('busy', 'godyes');
        // obtain the real height of the post and do some hardcore animations
        //jenk.removeClass ("compressed"); var realHeight = jenk.height();
        jenk.animate ({ maxHeight: jenk.data ('real-height') }, 500, function() {
            jenk.removeClass ("compressed").css ("max-height", "none");
            me.slideUp ('slow', function() {
                me.remove();
            });
        });
    });

    plist.on('click',".hide",function() {
        var pid = $(this).data('postid');
        var hidden = localStorage.getItem('hid');
        if(hidden === null) {
            localStorage.setItem('hid',pid);
        }
        else
        {
            hidden += "|"+pid;
            localStorage.setItem('hid',hidden);
        }
        //auto lock
        var lock = $("#post"+pid).find('img.imgunlocked');
        if(lock.length)
        {
            lock.eq(0).click();
        }
        $("#"+pid).slideUp (hideHidden);
    });

    $("#profilePostList").on('click',function() {
        plist.html('
'+loading+'...
');
        $("#fast_nerdz").show();
        $("#nerdzlist").hide();
        $(".selectlang").css('color','');
        localStorage.removeItem("autolang");
        load = false;
        N.html.profile.getHomePostList(0,function(data) {
            plist.html(data);
            plist.data('type','profile');
            plist.data('mode','std');
            hideHidden();
            load = true;
        });
    });

    $("#projectPostList").on('click',function() {
        plist.html('
'+loading+'...
');
        $("#fast_nerdz").hide();
        $("#projlist").hide();
        $(".projlang").css('color','');
        load = false;
        N.html.project.getHomePostList(0,function(data) {
            plist.html(data);
            plist.data('type','project');
            plist.data('mode','std');
            hideHidden();
            load = true;
        });
    });

    $("#nerdzselect").on('click',function() {
        $("#nerdzlist").toggle();
    });

    $("#projselect").on('click',function() {
        $("#projlist").toggle();
    });

    $(".selectlang").on('click',function() {
        plist.html('
'+loading+'...
');
        lang = $(this).data('lang');
        localStorage.setItem("autolang",lang);
        $(".selectlang").css('color','');
        $(this).css('color','#2370B6');
        load = false;
        if(lang == 'usersifollow')
        {
            $("#fast_nerdz").show();
            N.html.profile.getFollowedHomePostList(0,function(data) {
                plist.html(data);
                plist.data('type','profile');
                plist.data('mode','followed');
                hideHidden();
                load = true;
            });
        }
        else
        {
            if(lang == '*') {
                $("#fast_nerdz").show();
            }
            else {
                $("#fast_nerdz").hide();
            }

            load = false;
            N.html.profile.getByLangHomePostList(0,lang,function(data) {
                plist.html(data);
                plist.data('mode','language');
                plist.data('type','profile');
                hideHidden();
                load = true;
            });
        }
    });

    $(".projlang").on('click',function() {
        $("#fast_nerdz").hide();
        plist.html('
'+loading+'...
');
        lang = $(this).data('lang');
        $(".projlang").css('color','');
        $(this).css('color','#2370B6');
        load = false;
        if(lang == 'usersifollow')
        {
                N.html.project.getFollowedHomePostList(0,function(data) {
                plist.html(data);
                plist.data('type','project');
                plist.data('mode','followed');
                hideHidden();
                load = true;
            });
        }
        else
        {
            N.html.project.getByLangHomePostList(0,lang,function(data) {
                plist.html(data);
                plist.data('type','project');
                plist.data('mode','language');
                hideHidden();
                load = true;
            });
        }
    });

    $("#stdfrm").on('submit',function(e) {
        e.preventDefault();
        $("#pmessage").html(loading+'...');
        N.json.profile.newPost({message: $("#frmtxt").val(), to: 0 },function(data) {
            if(data.status == 'ok') {
                $("#frmtxt").val('');
                load = false;
                if(lang == '*') {
                    N.html.profile.getByLangHomePostList(0,lang,function(data) {
                        plist.html(data);
                        plist.data('type','profile');
                        plist.data('mode','language');
                        hideHidden();
                        load = true;
                    });
                }
                else if(lang == 'usersifollow') {
                    N.html.profile.getFollowedHomePostList(0,function(data) {
                        plist.html(data);
                        plist.data('type','profile');
                        plist.data('mode','followed');
                        hideHidden();
                        load = true;
                    });
                }
                else {
                    $("#profilePostList").click();
                }
            }

            $("#pmessage").html(data.message);

            setTimeout(function() {
                        $("#pmessage").html('');
                        },5000);
        });
    });

    //default profile posts
    if(localStorage.getItem("autolang"))
    {
        $("#nerdzselect").click();
        var el = $("#nerdzlist").find("ul").find("[data-lang='"+localStorage.getItem("autolang")+"']");
        el.click();
        el.css('color','#2370B6');
    }
    else
    {
        plist.data('location','home');
        load = false;
        N.html.profile.getHomePostList(0,function(data) {
            plist.html(data);
            hideHidden();
            plist.data('type','profile');
            plist.data('mode','std');
            load = true;
        });
    }

    /* Autoload vecchi post allo scrolldown */
        //questo serve per search, che avendo l'azione iniziale nel file default.js, non condivide la variabile load. Uso sessionStorage per ovviare
    var sl = 'searchLoad'; /*search label */
    sessionStorage.setItem(sl,"0");
    var tmpDivId = "scrtxt";
    var manageScrollResponse = function(data) {
        $("#"+tmpDivId).remove();
        if(data.length > 0) {
            plist.append(data);
            hideHidden();
            load = true;
            sessionStorage.setItem(sl, "0"); // se sono entrato qui, sicuramente non cerco
        }
    };

    var manageScrollSearchResponse = function(data) {
        $("#"+tmpDivId).remove();
        if(data.length > 0) {
            plist.append(data);
            hideHidden();
            sessionStorage.setItem(sl, "1");
            load = false; // se sono entrato qui, sicuramente stavo cercando
        }
    };

    $(window).scroll(function() {
        if($(this).scrollTop()+200 >= ( $(document).height() - $(this).height() ))
        {
            var num = 10; //TODO: numero di posts, parametro?
            var hpid = plist.find("div[id^='post']").last().data('hpid');
            var mode = plist.data('mode');
            var type = plist.data('type');
            var append = '
'+loading+'...
';

            if((load || ("1" == sessionStorage.getItem(sl))) && !$("#"+tmpDivId).length)
            {
                plist.append(append);
            }

            if(load)
            {
                load = false;
                if(mode == 'std') {
                    N.html[type].getHomePostListBeforeHpid(num,hpid,manageScrollResponse);
                }
                else if(mode == 'followed') {
                    N.html[type].getFollowedHomePostListBeforeHpid(num,hpid,manageScrollResponse);
                }
                else if(mode == 'language') {
                    N.html[type].getByLangHomePostListBeforeHpid(num,lang,hpid, manageScrollResponse);
                }
            }
            //a true ci va in default.js, dopo il primo search
            if(sessionStorage.getItem(sl) == "1")
            {
                sessionStorage.setItem(sl, "0");
                if(type == 'project' && mode == 'search')
                {
                    N.html.search.globalProjectPostsBeforeHpid(num,$("#footersearch input[name=q]").val(), hpid, manageScrollSearchResponse);
                }
                else if(type == 'profile' && mode == 'search')
                {
                    N.html.search.globalProfilePostsBeforeHpid(num, $("#footersearch input[name=q]").val(), hpid, manageScrollSearchResponse);
                }
            }
        }
    });
});
<commit_msg>Update home.js<commit_after>$(document).ready(function() {
    //tutti gli eventi ajax che evvengono in plist sono nel formato pilst.on(evento,[selettore],function(...){...});
    var plist = $("#postlist");
    var loading = N.getLangData().LOADING;
    var lang = null; /* globale dato che la uso anche altrove */
    var load = false; //gestisce i caricamenti ed evita sovrapposizioni. Dichiarata qui che è il foglio che viene incluso di default ovunque e per primo
    plist.html('
'+loading+'...
');

    var fixHeights = function() {
        plist.find(".nerdz_message").each (function() {
            var el = $(this).find('div:first');
            // TODO: switch from attr('data-parsed') to data('parsed')
            if ((el.height() >= 200 || el.find ('.gistLoad').length > 0) && !el.attr('data-parsed'))
            {
                el.data ('real-height', el.height()).addClass ("compressed");
                var n = el.next();
                n.prepend ('
>> ' + N.getLangData().EXPAND + ' <<
'); // Spaces master race.
            }
            el.attr('data-parsed','1');
        });
    };

    var onRemoveHiddenPost = function() {
        var me = $(this), target = me.data ("target"), lv = localStorage.getItem ("hid").split ("|"), serialized = "";
        $("#" + target).slideToggle (function() {
            $(this).find (".img_frame > img").each (function() {
                $(this).css ("margin-top", (117 - $(this).height()) / 2);
            });
        });
        me.parent().remove();
        for (var zxcvbn in lv)
            if (lv[zxcvbn] != target)
                serialized += lv[zxcvbn] + "|";
        if (serialized !== '')
            localStorage.setItem ("hid", serialized.slice (0, -1));
        else
        {
            localStorage.removeItem ("hid");
            $("#hp-cnt").remove();
            $("#hp-title").remove();
        }
    };

    var hideHidden = function() {
        var hidden = localStorage.getItem ("hid");
        if (hidden !== null)
        {
            var pids = hidden.split ("|").sort().reverse(), len = pids.length;
            while (len--)
            {
                var post = plist.find ("#" + pids[len]);
                if (post.length)
                {
                    post.hide();
                    var pLink = window[pids[len].replace (/post/, "lnk")];
                    pids[len] = $(document.createElement("li"))
                        .append ($(document.createElement("a")).attr ("href", pLink).text (decodeURIComponent (pLink.substr (1))))
                        .append ($(document.createElement("a")).data ("target", pids[len]).css ("float", "right").html ("X").click (onRemoveHiddenPost));
                }
                else
                    pids.splice (len, 1);
            }
            if (pids.length)
            {
                if (!$("#hp-cnt").length)
                {
                    // create the hidden posts box
                    $(document.createElement("div")).addClass ("title").click (function() {
                        $("#hp-cnt").slideToggle();
                    }).html (N.getStaticData().lang.HIDDEN_POSTS).attr ("id", "hp-title").appendTo ("#right_col");
                    $(document.createElement("div")).hide().addClass ("box").attr ("id", "hp-cnt")
                        .append ($(document.createElement ("ul")).html (pids)).appendTo ("#right_col");
                }
                else
                    $("#hp-cnt ul").html (pids);
            }
        }
        // Hide 'blacklisted user changed nickname'
        // We ALWAYS have windows.idios that is the blacklisted users array
        $("#postlist ").find(".news a:nth-last-child(3)").each(function() {
            if($.inArray($(this).html(), window.idiots) > -1) {
                $(this).parent().parent().hide();
            }
        });

        fixHeights();
    };

    plist.on('click',".spoiler",function(){
      if($(this).data("parsed")) return;
      $.each($(this).find("img"),function(){
        m = (117-$(this).height())/2;
        if (m>1)
          $(this).css("margin-top", m);
      });
      $(this).data("parsed","1");
    });

    plist.on('click','.more',function() {
        var me = $(this), par = me.parent(), jenk = par.prev();
        if (me.data ('busy') == 'godyes') return;
        me.data ('busy', 'godyes');
        // obtain the real height of the post and do some hardcore animations
        //jenk.removeClass ("compressed"); var realHeight = jenk.height();
        jenk.animate ({ maxHeight: jenk.data ('real-height') }, 500, function() {
            jenk.removeClass ("compressed").css ("max-height", "none");
            me.slideUp ('slow', function() {
                me.remove();
            });
        });
    });

    plist.on('click',".hide",function() {
        var pid = $(this).data('postid');
        var hidden = localStorage.getItem('hid');
        if(hidden === null) {
            localStorage.setItem('hid',pid);
        }
        else
        {
            hidden += "|"+pid;
            localStorage.setItem('hid',hidden);
        }
        //auto lock
        var lock = $("#post"+pid).find('img.imgunlocked');
        if(lock.length)
        {
            lock.eq(0).click();
        }
        $("#"+pid).slideUp (hideHidden);
    });

    $("#profilePostList").on('click',function() {
        plist.html('
'+loading+'...
');
        $("#fast_nerdz").show();
        $("#nerdzlist").hide();
        $(".selectlang").css('color','');
        localStorage.removeItem("autolang");
        load = false;
        N.html.profile.getHomePostList(0,function(data) {
            plist.html(data);
            plist.data('type','profile');
            plist.data('mode','std');
            hideHidden();
            load = true;
        });
    });

    $("#projectPostList").on('click',function() {
        plist.html('
'+loading+'...
');
        $("#fast_nerdz").hide();
        $("#projlist").hide();
        $(".projlang").css('color','');
        load = false;
        N.html.project.getHomePostList(0,function(data) {
            plist.html(data);
            plist.data('type','project');
            plist.data('mode','std');
            hideHidden();
            load = true;
        });
    });

    $("#nerdzselect").on('click',function() {
        $("#nerdzlist").toggle();
    });

    $("#projselect").on('click',function() {
        $("#projlist").toggle();
    });

    $(".selectlang").on('click',function() {
        plist.html('
'+loading+'...
');
        lang = $(this).data('lang');
        localStorage.setItem("autolang",lang);
        $(".selectlang").css('color','');
        $(this).css('color','#2370B6');
        load = false;
        if(lang == 'usersifollow')
        {
            $("#fast_nerdz").show();
            N.html.profile.getFollowedHomePostList(0,function(data) {
                plist.html(data);
                plist.data('type','profile');
                plist.data('mode','followed');
                hideHidden();
                load = true;
            });
        }
        else
        {
            if(lang == '*') {
                $("#fast_nerdz").show();
            }
            else {
                $("#fast_nerdz").hide();
            }

            load = false;
            N.html.profile.getByLangHomePostList(0,lang,function(data) {
                plist.html(data);
                plist.data('mode','language');
                plist.data('type','profile');
                hideHidden();
                load = true;
            });
        }
    });

    $(".projlang").on('click',function() {
        $("#fast_nerdz").hide();
        plist.html('
'+loading+'...
');
        lang = $(this).data('lang');
        $(".projlang").css('color','');
        $(this).css('color','#2370B6');
        load = false;
        if(lang == 'usersifollow')
        {
                N.html.project.getFollowedHomePostList(0,function(data) {
                plist.html(data);
                plist.data('type','project');
                plist.data('mode','followed');
                hideHidden();
                load = true;
            });
        }
        else
        {
            N.html.project.getByLangHomePostList(0,lang,function(data) {
                plist.html(data);
                plist.data('type','project');
                plist.data('mode','language');
                hideHidden();
                load = true;
            });
        }
    });

    $("#stdfrm").on('submit',function(e) {
        e.preventDefault();
        $("#pmessage").html(loading+'...');
        N.json.profile.newPost({message: $("#frmtxt").val(), to: 0 },function(data) {
            if(data.status == 'ok') {
                $("#frmtxt").val('');
                load = false;
                if(lang == '*') {
                    N.html.profile.getByLangHomePostList(0,lang,function(data) {
                        plist.html(data);
                        plist.data('type','profile');
                        plist.data('mode','language');
                        hideHidden();
                        load = true;
                    });
                }
                else if(lang == 'usersifollow') {
                    N.html.profile.getFollowedHomePostList(0,function(data) {
                        plist.html(data);
                        plist.data('type','profile');
                        plist.data('mode','followed');
                        hideHidden();
                        load = true;
                    });
                }
                else {
                    $("#profilePostList").click();
                }
            }

            $("#pmessage").html(data.message);

            setTimeout(function() {
                        $("#pmessage").html('');
                        },5000);
        });
    });

    //default profile posts
    if(localStorage.getItem("autolang"))
    {
        $("#nerdzselect").click();
        var el = $("#nerdzlist").find("ul").find("[data-lang='"+localStorage.getItem("autolang")+"']");
        el.click();
        el.css('color','#2370B6');
    }
    else
    {
        plist.data('location','home');
        load = false;
        N.html.profile.getHomePostList(0,function(data) {
            plist.html(data);
            hideHidden();
            plist.data('type','profile');
            plist.data('mode','std');
            load = true;
        });
    }

    /* Autoload vecchi post allo scrolldown */
        //questo serve per search, che avendo l'azione iniziale nel file default.js, non condivide la variabile load. Uso sessionStorage per ovviare
    var sl = 'searchLoad'; /*search label */
    sessionStorage.setItem(sl,"0");
    var tmpDivId = "scrtxt";
    var manageScrollResponse = function(data) {
        $("#"+tmpDivId).remove();
        if(data.length > 0) {
            plist.append(data);
            hideHidden();
            load = true;
            sessionStorage.setItem(sl, "0"); // se sono entrato qui, sicuramente non cerco
        }
    };

    var manageScrollSearchResponse = function(data) {
        $("#"+tmpDivId).remove();
        if(data.length > 0) {
            plist.append(data);
            hideHidden();
            sessionStorage.setItem(sl, "1");
            load = false; // se sono entrato qui, sicuramente stavo cercando
        }
    };

    $(window).scroll(function() {
        if($(this).scrollTop()+200 >= ( $(document).height() - $(this).height() ))
        {
            var num = 10; //TODO: numero di posts, parametro?
            var hpid = plist.find("div[id^='post']").last().data('hpid');
            var mode = plist.data('mode');
            var type = plist.data('type');
            var append = '
'+loading+'...
';

            if((load || ("1" == sessionStorage.getItem(sl))) && !$("#"+tmpDivId).length)
            {
                plist.append(append);
            }

            if(load)
            {
                load = false;
                if(mode == 'std') {
                    N.html[type].getHomePostListBeforeHpid(num,hpid,manageScrollResponse);
                }
                else if(mode == 'followed') {
                    N.html[type].getFollowedHomePostListBeforeHpid(num,hpid,manageScrollResponse);
                }
                else if(mode == 'language') {
                    N.html[type].getByLangHomePostListBeforeHpid(num,lang,hpid, manageScrollResponse);
                }
            }
            //a true ci va in default.js, dopo il primo search
            if(sessionStorage.getItem(sl) == "1")
            {
                sessionStorage.setItem(sl, "0");
                if(type == 'project' && mode == 'search')
                {
                    N.html.search.globalProjectPostsBeforeHpid(num,$("#footersearch input[name=q]").val(), hpid, manageScrollSearchResponse);
                }
                else if(type == 'profile' && mode == 'search')
                {
                    N.html.search.globalProfilePostsBeforeHpid(num, $("#footersearch input[name=q]").val(), hpid, manageScrollSearchResponse);
                }
            }
        }
    });
});
<|endoftext|>


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

export default `\
#define SHADER_NAME icon-layer-vertex-shader

attribute vec2 positions;

attribute vec3 instancePositions;
attribute float instanceSizes;
attribute float instanceAngles;
attribute vec4 instanceColors;
attribute vec3 instancePickingColors;
attribute vec4 instanceIconFrames;
attribute float instanceColorModes;
attribute vec2 instanceOffsets;

uniform vec2 viewportSize;
uniform float sizeScale;
uniform float renderPickingBuffer;
uniform vec2 iconsTextureDim;

varying float vColorMode;
varying vec4 vColor;
varying vec2 vTextureCoords;

vec2 rotate_by_angle(vec2 vertex, float angle) {
  float angle_radian = angle * PI / 180.0;
  float cos_angle = cos(angle_radian);
  float sin_angle = sqrt(1.0 - cos_angle * cos_angle);
  mat2 rotationMatrix = mat2(cos_angle, -sin_angle, sin_angle, cos_angle);
  return rotationMatrix * vertex;
}

void main(void) {
  vec2 iconSize = instanceIconFrames.zw;
  vec2 iconSize_clipspace = iconSize / viewportSize * 2.0;
  // scale icon height to match instanceSize
  float instanceScale = iconSize.y == 0.0 ? 0.0 : instanceSizes / iconSize.y;
  vec3 center = project_position(instancePositions);
  vec2 vertex = (positions / 2.0 + instanceOffsets);
  vertex = rotate_by_angle(vertex, instanceAngles) * iconSize_clipspace *
    sizeScale * instanceScale;
  vertex.y *= -1.0;

  gl_Position = project_to_clipspace(vec4(center, 1.0)) + vec4(vertex, 0.0, 0.0);

  vTextureCoords = mix(
    instanceIconFrames.xy,
    instanceIconFrames.xy + iconSize,
    (positions.xy + 1.0) / 2.0
  ) / iconsTextureDim;

  vTextureCoords.y = 1.0 - vTextureCoords.y;

  vec4 color = instanceColors / 255.;
  vec4 pickingColor = vec4(instancePickingColors / 255., 1.);
  vColor = mix(color, pickingColor, renderPickingBuffer);

  vColorMode = instanceColorModes;
}
`;
<commit_msg>[icon-layer] use sin to get 180-360 degree ranges (#780)<commit_after>// Copyright (c) 2015 - 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

export default `\
#define SHADER_NAME icon-layer-vertex-shader

attribute vec2 positions;

attribute vec3 instancePositions;
attribute float instanceSizes;
attribute float instanceAngles;
attribute vec4 instanceColors;
attribute vec3 instancePickingColors;
attribute vec4 instanceIconFrames;
attribute float instanceColorModes;
attribute vec2 instanceOffsets;

uniform vec2 viewportSize;
uniform float sizeScale;
uniform float renderPickingBuffer;
uniform vec2 iconsTextureDim;

varying float vColorMode;
varying vec4 vColor;
varying vec2 vTextureCoords;

vec2 rotate_by_angle(vec2 vertex, float angle) {
  float angle_radian = angle * PI / 180.0;
  float cos_angle = cos(angle_radian);
  float sin_angle = sin(angle_radian);
  mat2 rotationMatrix = mat2(cos_angle, -sin_angle, sin_angle, cos_angle);
  return rotationMatrix * vertex;
}

void main(void) {
  vec2 iconSize = instanceIconFrames.zw;
  vec2 iconSize_clipspace = iconSize / viewportSize * 2.0;
  // scale icon height to match instanceSize
  float instanceScale = iconSize.y == 0.0 ? 0.0 : instanceSizes / iconSize.y;
  vec3 center = project_position(instancePositions);
  vec2 vertex = (positions / 2.0 + instanceOffsets);
  vertex = rotate_by_angle(vertex, instanceAngles) * iconSize_clipspace *
    sizeScale * instanceScale;
  vertex.y *= -1.0;

  gl_Position = project_to_clipspace(vec4(center, 1.0)) + vec4(vertex, 0.0, 0.0);

  vTextureCoords = mix(
    instanceIconFrames.xy,
    instanceIconFrames.xy + iconSize,
    (positions.xy + 1.0) / 2.0
  ) / iconsTextureDim;

  vTextureCoords.y = 1.0 - vTextureCoords.y;

  vec4 color = instanceColors / 255.;
  vec4 pickingColor = vec4(instancePickingColors / 255., 1.);
  vColor = mix(color, pickingColor, renderPickingBuffer);

  vColorMode = instanceColorModes;
}
`;
<|endoftext|>


<commit_before>/*
 Copyright, 2013, by Tomas Korcak. <korczis@gmail.com>

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

(function () {
    'use strict';

    var deferred = require('deferred'),
        fs = require('fs'),
        path = require('path'),
        utils = require('../utils');

    /**
     * Intializes router
     * @param microscratch Microscratch app which this router belongs to
     * @param app Express app which this router belongs to
     */
    module.exports.initialize = function (microscratch, app) {
        var d = deferred();

        var readdir = deferred.promisify(fs.readdir);

        var self = this;
        var routesDir = path.join(__dirname, './routes');
        readdir(routesDir).then(function(files) {
            console.log(files);

            for(var i = 0; i < files.length; i++) {
                var routePath = "./routes/" + files[i];

                var route = require(routePath);
                route(microscratch, app);
            }

            d.resolve(self);
        });

        return d.promise();

        /*
        // Root route
        app.get('/', function (req, res) {
            var data = {
                appName: microscratch.config.appName
            };

            var tmpl = path.join(microscratch.config.server.dirs.views, "index.hbs");
            fs.exists(tmpl, function (exists) {
                if(exists) {
                    res.render("index", data);
                } else {
                    res.render("microscratch", data);
                }
            });
        });

        // Microscratch route
        app.get('/microscratch', function (req, res) {
            var data = {
                appName: microscratch.config.appName
            };

            res.render("microscratch", data);
        });

        // Microscratch route
        app.get('/mocha', function (req, res) {
            var data = {
                appName: microscratch.config.appName
            };

            res.render("mocha", data);
        });

        app.get('/config', function (req, res) {
            res.json(microscratch.config);
        });

        app.get('/query', function(req, res) {
            microscratch.mongo.getCollection('datasets');
        });
        */
    };

}());
<commit_msg>Removed dead code<commit_after>/*
 Copyright, 2013, by Tomas Korcak. <korczis@gmail.com>

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

(function () {
    'use strict';

    var deferred = require('deferred'),
        fs = require('fs'),
        path = require('path'),
        utils = require('../utils');

    /**
     * Intializes router
     * @param microscratch Microscratch app which this router belongs to
     * @param app Express app which this router belongs to
     */
    module.exports.initialize = function (microscratch, app) {
        var d = deferred();

        var readdir = deferred.promisify(fs.readdir);

        var self = this;
        var routesDir = path.join(__dirname, './routes');
        readdir(routesDir).then(function(files) {
            console.log(files);

            for(var i = 0; i < files.length; i++) {
                var routePath = "./routes/" + files[i];

                var route = require(routePath);
                route(microscratch, app);
            }

            d.resolve(self);
        });

        return d.promise();

    };

}());
<|endoftext|>