<commit_before>define(["dojo/_base/kernel", "dojo/_base/declare","dojo/on","dojo/_base/array","dojo/DeferredList","./TransitionEvent","./ProgressIndicator"],
	function(dojo, declare, on, darra, DeferredList, TransitionEvent, ProgressIndicator){

	var Controller = dojo.declare(null, {
		constructor: function(){
			this.viewMap={};
			this.currentView=null;
			this.defaultView=null;
			dojo.ready(dojo.hitch(this, function(){
				on(dojo.body(), "startTransition", dojo.hitch(this, "onStartTransition"));
			}));
		},

		findCurrentView: function(moveTo,src){
			if(moveTo){
				var w = dijit.byId(moveTo);
				if(w && w.getShowingView){ return w.getShowingView(); }
			}
			if (dojox.mobile.currentView) {
				return dojox.mobile.currentView;
			}
			w = src;
			while(true){
				w = w.getParent();
				if(!w){ return null; }
				if(w instanceof dojox.mobile.View){ break; }
			}
			return w;
		},

		onStartTransition: function(evt){
			//console.log("onStartTransition:", evt.detail, evt.detail.moveTo, evt.detail.href, evt.detail.scene, evt);
			evt.preventDefault();
			if(!evt.detail || (evt.detail && !evt.detail.moveTo && !evt.detail.href && !evt.detail.url && !evt.detail.scene)){ return; }
			var w = this.findCurrentView(evt.detail.moveTo, (evt.target && evt.target.id)?dijit.byId(evt.target.id):dijit.byId(evt.target)); // the current view widget
			if(!w || (evt.detail && evt.detail.moveTo && w === dijit.byId(evt.detail.moveTo))){ return; }
			if(evt.detail.href){
				var t = dijit.byId(evt.target.id).hrefTarget;
				if(t){
					dojox.mobile.openWindow(evt.detail.href, t);
				}else{
					w.performTransition(null, evt.detail.transitionDir, evt.detail.transition, evt.target, function(){location.href = evt.detail.href;});
				}
				return;
			} else if(evt.detail.scene){
				dojo.publish("/dojox/mobile/app/pushScene", [evt.detail.scene]);
				return;
			}
			var moveTo = evt.detail.moveTo;
			if(evt.detail.url){
				var id;
				if(dojox.mobile._viewMap && dojox.mobile._viewMap[evt.detail.url]){
					// external view has already been loaded
					id = dojox.mobile._viewMap[evt.detail.url];
				}else{
					// get the specified external view and append it to the
					var text = this._text;
					if(!text){
						if(dijit.byId(evt.target.id).sync){
							text = dojo.trim(dojo._getText(evt.detail.url));
						}else{
							require(["dojo/_base/xhr"], dojo.hitch(this, function(xhr){
								var prog = ProgressIndicator.getInstance();
								dojo.body().appendChild(prog.domNode);
								prog.start();
								var xhr = dojo.xhrGet({
									url: evt.detail.url,
									handleAs: "text"
								});
								xhr.addCallback(dojo.hitch(this, function(response, ioArgs){
									prog.stop();
									if(response){
										this._text = response;
										new TransitionEvent(evt.target, {
												transition: evt.detail.transition,
											 	transitionDir: evt.detail.transitionDir,
											 	moveTo: moveTo,
											 	href: evt.detail.href,
											 	url: evt.detail.url,
											 	scene: evt.detail.scene},
											 		evt.detail)
											 			.dispatch();
									}
								}));
								xhr.addErrback(function(error){
									prog.stop();
									console.log("Failed to load "+evt.detail.url+"\n"+(error.description||error));
								});
							}));
							return;
						}
					}
					this._text = null;
					id = this._parse(text, dijit.byId(evt.target.id).urlTarget);
					if(!dojox.mobile._viewMap){
						dojox.mobile._viewMap = [];
					}
					dojox.mobile._viewMap[evt.detail.url] = id;
				}
				moveTo = id;
				w = this.findCurrentView(moveTo,dijit.byId(evt.target.id)) || w; // the current view widget
			}
			w.performTransition(moveTo, evt.detail.transitionDir, evt.detail.transition, null, null);
		},

		_parse: function(text,id){
			var container = dojo.create("DIV");
			var view;
			var currentView	 = this.findCurrentView();
			var target = dijit.byId(id) && dijit.byId(id).containerNode
						|| dojo.byId(id)
						|| currentView && currentView.domNode.parentNode
						|| dojo.body();
			if(text.charAt(0) == "<"){ // html markup
			//container.innerHTML = text;
			var container = dojo.create("DIV",{innerHTML: text});
				view = container.firstChild; //

				if(!view && view.nodeType != 1){
					console.log("dojox.mobile._ItemBase#transitionTo: invalid view content");
					return;
				}
				view.style.visibility = "hidden";
				target.appendChild(container);
				var ws = dojo.parser.parse(container);
				dojo.forEach(ws, function(w){
					if(w && !w._started && w.startup){
						w.startup();
					}
				});
				target.appendChild(target.removeChild(container).firstChild); // reparent
				dijit.byNode(view)._visible = true;
			}else if(text.charAt(0) == "{"){ // json
				target.appendChild(container);
				this._ws = [];
				view = this._instantiate(eval('('+text+')'), container);
				for(var i = 0; i < this._ws.length; i++){
						var w = this._ws[i];
						w.startup && !w._started && (!w.getParent || !w.getParent()) && w.startup();
				}
				this._ws = null;
			}
			view.style.display = "none";
			view.style.visibility = "visible";
			var id = view.id;
			return dojo.hash ? "#" + id : id;
		},

		_instantiate: function(/*Object*/obj, /*DomNode*/node, /*Widget*/parent){
			var widget;
			for(var key in obj){
				if(key.charAt(0) == "@"){ continue; }
				var cls = dojo.getObject(key);
				if(!cls){ continue; }
				var params = {};
				var proto = cls.prototype;
				var objs = dojo.isArray(obj[key]) ? obj[key] : [obj[key]];
				for(var i = 0; i < objs.length; i++){
					for(var prop in objs[i]){
						if(prop.charAt(0) == "@"){
							var val = objs[i][prop];
							prop = prop.substring(1);
							if(typeof proto[prop] == "string"){
								params[prop] = val;
							}else if(typeof proto[prop] == "number"){
								params[prop] = val - 0;
							}else if(typeof proto[prop] == "boolean"){
							params[prop] = (val != "false");
							}else if(typeof proto[prop] == "object"){
								params[prop] = eval("(" + val + ")");
							}
						}
					}
					widget = new cls(params, node);
					if(node){ // to call View's startup()
						widget._visible = true;
						this._ws.push(widget);
					}
					if(parent && parent.addChild){
						parent.addChild(widget);
					}
					this._instantiate(objs[i], null, widget);
				}
			}
			return widget && widget.domNode;
		}
	});
	new Controller(); // singleton
	return Controller;
});

<commit_msg>Fixes #13439 !strict. _parse searches for a fixed bottom bar. If found, insert a new view before it.<commit_after>define(["dojo/_base/kernel", "dojo/_base/declare","dojo/on","dojo/_base/array","dojo/DeferredList","./TransitionEvent","./ProgressIndicator"],
	function(dojo, declare, on, darra, DeferredList, TransitionEvent, ProgressIndicator){

	var Controller = dojo.declare(null, {
		constructor: function(){
			this.viewMap={};
			this.currentView=null;
			this.defaultView=null;
			dojo.ready(dojo.hitch(this, function(){
				on(dojo.body(), "startTransition", dojo.hitch(this, "onStartTransition"));
			}));
		},

		findCurrentView: function(moveTo,src){
			if(moveTo){
				var w = dijit.byId(moveTo);
				if(w && w.getShowingView){ return w.getShowingView(); }
			}
			if (dojox.mobile.currentView) {
				return dojox.mobile.currentView;
			}
			w = src;
			while(true){
				w = w.getParent();
				if(!w){ return null; }
				if(w instanceof dojox.mobile.View){ break; }
			}
			return w;
		},

		onStartTransition: function(evt){
			//console.log("onStartTransition:", evt.detail, evt.detail.moveTo, evt.detail.href, evt.detail.scene, evt);
			evt.preventDefault();
			if(!evt.detail || (evt.detail && !evt.detail.moveTo && !evt.detail.href && !evt.detail.url && !evt.detail.scene)){ return; }
			var w = this.findCurrentView(evt.detail.moveTo, (evt.target && evt.target.id)?dijit.byId(evt.target.id):dijit.byId(evt.target)); // the current view widget
			if(!w || (evt.detail && evt.detail.moveTo && w === dijit.byId(evt.detail.moveTo))){ return; }
			if(evt.detail.href){
				var t = dijit.byId(evt.target.id).hrefTarget;
				if(t){
					dojox.mobile.openWindow(evt.detail.href, t);
				}else{
					w.performTransition(null, evt.detail.transitionDir, evt.detail.transition, evt.target, function(){location.href = evt.detail.href;});
				}
				return;
			} else if(evt.detail.scene){
				dojo.publish("/dojox/mobile/app/pushScene", [evt.detail.scene]);
				return;
			}
			var moveTo = evt.detail.moveTo;
			if(evt.detail.url){
				var id;
				if(dojox.mobile._viewMap && dojox.mobile._viewMap[evt.detail.url]){
					// external view has already been loaded
					id = dojox.mobile._viewMap[evt.detail.url];
				}else{
					// get the specified external view and append it to the
					var text = this._text;
					if(!text){
						if(dijit.byId(evt.target.id).sync){
							text = dojo.trim(dojo._getText(evt.detail.url));
						}else{
							require(["dojo/_base/xhr"], dojo.hitch(this, function(xhr){
								var prog = ProgressIndicator.getInstance();
								dojo.body().appendChild(prog.domNode);
								prog.start();
								var xhr = dojo.xhrGet({
									url: evt.detail.url,
									handleAs: "text"
								});
								xhr.addCallback(dojo.hitch(this, function(response, ioArgs){
									prog.stop();
									if(response){
										this._text = response;
										new TransitionEvent(evt.target, {
												transition: evt.detail.transition,
											 	transitionDir: evt.detail.transitionDir,
											 	moveTo: moveTo,
											 	href: evt.detail.href,
											 	url: evt.detail.url,
											 	scene: evt.detail.scene},
											 		evt.detail)
											 			.dispatch();
									}
								}));
								xhr.addErrback(function(error){
									prog.stop();
									console.log("Failed to load "+evt.detail.url+"\n"+(error.description||error));
								});
							}));
							return;
						}
					}
					this._text = null;
					id = this._parse(text, dijit.byId(evt.target.id).urlTarget);
					if(!dojox.mobile._viewMap){
						dojox.mobile._viewMap = [];
					}
					dojox.mobile._viewMap[evt.detail.url] = id;
				}
				moveTo = id;
				w = this.findCurrentView(moveTo,dijit.byId(evt.target.id)) || w; // the current view widget
			}
			w.performTransition(moveTo, evt.detail.transitionDir, evt.detail.transition, null, null);
		},

		_parse: function(text, id){
			var container, view;
			var currentView	 = this.findCurrentView();
			var target = dijit.byId(id) && dijit.byId(id).containerNode
						|| dojo.byId(id)
						|| currentView && currentView.domNode.parentNode
						|| dojo.body();
			// if a fixed bottom bar exists, a new view should be placed before it.
			var refNode = null;
			for(var j = target.childNodes.length - 1; j >= 0; j--){
				var c = target.childNodes[j];
				if(c.nodeType === 1){
					if(c.getAttribute("fixed") === "bottom"){
						refNode = c;
					}
					break;
				}
			}
			if(text.charAt(0) == "<"){ // html markup
				container = dojo.create("DIV", {innerHTML: text});
				view = container.firstChild; //

				if(!view && view.nodeType != 1){
					console.log("dojox.mobile._ItemBase#transitionTo: invalid view content");
					return;
				}
				view.style.visibility = "hidden";
				target.insertBefore(container, refNode);
				var ws = dojo.parser.parse(container);
				dojo.forEach(ws, function(w){
					if(w && !w._started && w.startup){
						w.startup();
					}
				});
				target.replaceChild(container.firstChild, container); // reparent
				dijit.byNode(view)._visible = true;
			}else if(text.charAt(0) == "{"){ // json
				container = dojo.create("DIV");
				target.insertBefore(container, refNode);
				this._ws = [];
				view = this._instantiate(eval('('+text+')'), container);
				for(var i = 0; i < this._ws.length; i++){
						var w = this._ws[i];
						w.startup && !w._started && (!w.getParent || !w.getParent()) && w.startup();
				}
				this._ws = null;
			}
			view.style.display = "none";
			view.style.visibility = "visible";
			return dojo.hash ? "#" + view.id : view.id;
		},

		_instantiate: function(/*Object*/obj, /*DomNode*/node, /*Widget*/parent){
			var widget;
			for(var key in obj){
				if(key.charAt(0) == "@"){ continue; }
				var cls = dojo.getObject(key);
				if(!cls){ continue; }
				var params = {};
				var proto = cls.prototype;
				var objs = dojo.isArray(obj[key]) ? obj[key] : [obj[key]];
				for(var i = 0; i < objs.length; i++){
					for(var prop in objs[i]){
						if(prop.charAt(0) == "@"){
							var val = objs[i][prop];
							prop = prop.substring(1);
							if(typeof proto[prop] == "string"){
								params[prop] = val;
							}else if(typeof proto[prop] == "number"){
								params[prop] = val - 0;
							}else if(typeof proto[prop] == "boolean"){
							params[prop] = (val != "false");
							}else if(typeof proto[prop] == "object"){
								params[prop] = eval("(" + val + ")");
							}
						}
					}
					widget = new cls(params, node);
					if(node){ // to call View's startup()
						widget._visible = true;
						this._ws.push(widget);
					}
					if(parent && parent.addChild){
						parent.addChild(widget);
					}
					this._instantiate(objs[i], null, widget);
				}
			}
			return widget && widget.domNode;
		}
	});
	new Controller(); // singleton
	return Controller;
});

<|endoftext|>


<commit_before>var urlParser = require('url');
const tls = require('tls');
const net = require('net');
var utils = require('./utils.js');

var packageJson = require('../package.json');
var versionNumber = packageJson.version;
var clientName = 'node-internet-radio v' + versionNumber;

function getStreamStation(url, callback) {
  var urlString = url;
  var completed = false;
  var buffer = '';
  var maxBufferSize = 100000;

  // Failure timer
  var timeout = setTimeout(function() {
    tearDown();
    return callback(
      new Error('Attempting to fetch station data via stream timed out.')
    );
  }, 5000);

  var url = urlParser.parse(url);
  var headers =
    'Icy-Metadata: 1\r\nUser-Agent: ' +
    clientName +
    '\r\nhost: ' +
    url.hostname +
    '\r\n';

  // Support HTTP Basic auth via Username:Password@host url syntax
  if (url.auth) {
    var encodedAuth = new Buffer(url.auth).toString('base64');
    headers += 'Authorization: Basic ' + encodedAuth + '\r\n';
  }

  var getString = 'GET ' + url.path + ' HTTP/1.0\r\n' + headers + '\r\n\r\n';

  if (url.protocol === 'http:') {
    var port = url.port || 80;

    var client = new net.Socket();
    client.setTimeout(5);
    client.setEncoding('utf8');
    client.connect(port, url.hostname, function() {
      client.write(getString);
    });
  } else if (url.protocol === 'https:') {
    var port = url.port || 443;
    var client = tls.connect(
      port,
      url.hostname,
      { ecdhCurve: false, servername: url.hostname },
      function() {
        client.write(getString);
      }
    );
  } else {
    const error = new Error(
      'Unknown protocol: ' + url.protocol + '. Unable to fetch stream.'
    );
    return errorCallback(error);
  }

  client.on('data', dataCallback);
  client.on('error', errorCallback);
  client.on('close', closeCallback);

  function dataCallback(response) {
    var title = null;
    const responseString = response.toString();

    // Append to the buffer and check if our title is fully included yet
    // We're looking for a string with the format of
    // StreamTitle=Artist Name - Song Name;
    buffer += responseString;

    var titlecheck = getDetailsFromBuffer(buffer);
    if (titlecheck != null) {
      handleBuffer(buffer, callback);
      tearDown();
      return;
    }

    if (buffer.length > maxBufferSize) {
      return returnError();
    }
  }

  function errorCallback(error) {
    if (completed) {
      return;
    }
    tearDown();
    console.trace(error);
    return callback(error);
  }

  function closeCallback() {
    var redirectUrl = handleRedirect(buffer);

    if (redirectUrl) {
      tearDown();
      return getStreamStation(redirectUrl, callback);
    }

    if (areThereErrors(buffer)) {
      return returnError();
    }

    if (completed) {
      return;
    }
  }

  function tearDown() {
    clearTimeout(timeout);

    completed = true;
    buffer = null;

    if (client != null) {
      client.destroy();
      client = null;
    }
  }

  function getDetailsFromBuffer(buffer) {
    var startSubstring = 'StreamTitle=';
    var startPosition = buffer.indexOf(startSubstring);
    var endSubstring = ';';
    var endPosition = buffer.toString().indexOf(';', startPosition);

    if (startPosition > -1 && endPosition > startPosition) {
      var titleString = buffer.substring(startPosition, endPosition);
      var title = titleString.substring(13, titleString.length - 1);
      return title;
    }

    return null;
  }

  function getHeadersFromBuffer(buffer) {
    var headersArray = buffer.split('\n');
    var headersObject = {};

    headersArray
      .filter(function(line) {
        return (
          (line.indexOf('icy') !== -1 && line.indexOf(':') !== -1) ||
          line.toLowerCase().indexOf('content-type') !== -1
        );
      })
      .forEach(function(line) {
        var keyValueArray = line.trim().split(':');
        headersObject[keyValueArray[0].toLowerCase()] = keyValueArray[1].trim();
      });

    return headersObject;
  }

  function handleBuffer(buffer, callback) {
    var title = getDetailsFromBuffer(buffer);
    title = utils.fixTrackTitle(title);

    var headers = getHeadersFromBuffer(buffer);

    var station = {};
    station.title = title;
    station.fetchsource = 'STREAM';
    station.headers = headers;

    return callback(null, station);
  }

  function handleRedirect(buffer) {
    var redirectTest = /Location: (.*)/m.exec(buffer);
    if (redirectTest) {
      // Redirect!
      var newUrl = redirectTest[1];

      if (newUrl === urlString) {
        const error = new Error(
          'Redirect loop detected. ' + urlString + ' -> ' + newUrl
        );
        return errorCallback(error);
      }

      return newUrl;
    }

    return false;
  }

  function areThereErrors(buffer) {
    // If we get back HTML there's a problem
    var contentTypeTest = /Content-Type: text\/html(.*)/m.exec(buffer);
    if (contentTypeTest) {
      return true;
    }

    return false;
  }

  function returnError() {
    tearDown();
    return callback(new Error('Error fetching stream'));
  }
}

module.exports.getStreamStation = getStreamStation;
<commit_msg>Guard against out of bounds checking of header values<commit_after>var urlParser = require('url');
const tls = require('tls');
const net = require('net');
var utils = require('./utils.js');

var packageJson = require('../package.json');
var versionNumber = packageJson.version;
var clientName = 'node-internet-radio v' + versionNumber;

function getStreamStation(url, callback) {
  var urlString = url;
  var completed = false;
  var buffer = '';
  var maxBufferSize = 100000;

  // Failure timer
  var timeout = setTimeout(function () {
    tearDown();
    return callback(
      new Error('Attempting to fetch station data via stream timed out.')
    );
  }, 5000);

  var url = urlParser.parse(url);
  var headers =
    'Icy-Metadata: 1\r\nUser-Agent: ' +
    clientName +
    '\r\nhost: ' +
    url.hostname +
    '\r\n';

  // Support HTTP Basic auth via Username:Password@host url syntax
  if (url.auth) {
    var encodedAuth = new Buffer(url.auth).toString('base64');
    headers += 'Authorization: Basic ' + encodedAuth + '\r\n';
  }

  var getString = 'GET ' + url.path + ' HTTP/1.0\r\n' + headers + '\r\n\r\n';

  if (url.protocol === 'http:') {
    var port = url.port || 80;

    var client = new net.Socket();
    client.setTimeout(5);
    client.setEncoding('utf8');
    client.connect(port, url.hostname, function () {
      client.write(getString);
    });
  } else if (url.protocol === 'https:') {
    var port = url.port || 443;
    var client = tls.connect(
      port,
      url.hostname,
      { ecdhCurve: false, servername: url.hostname },
      function () {
        client.write(getString);
      }
    );
  } else {
    const error = new Error(
      'Unknown protocol: ' + url.protocol + '. Unable to fetch stream.'
    );
    return errorCallback(error);
  }

  client.on('data', dataCallback);
  client.on('error', errorCallback);
  client.on('close', closeCallback);

  function dataCallback(response) {
    var title = null;
    const responseString = response.toString();

    // Append to the buffer and check if our title is fully included yet
    // We're looking for a string with the format of
    // StreamTitle=Artist Name - Song Name;
    buffer += responseString;

    var titlecheck = getDetailsFromBuffer(buffer);
    if (titlecheck != null) {
      handleBuffer(buffer, callback);
      tearDown();
      return;
    }

    if (buffer.length > maxBufferSize) {
      return returnError();
    }
  }

  function errorCallback(error) {
    if (completed) {
      return;
    }
    tearDown();
    console.trace(error);
    return callback(error);
  }

  function closeCallback() {
    var redirectUrl = handleRedirect(buffer);

    if (redirectUrl) {
      tearDown();
      return getStreamStation(redirectUrl, callback);
    }

    if (areThereErrors(buffer)) {
      return returnError();
    }

    if (completed) {
      return;
    }
  }

  function tearDown() {
    clearTimeout(timeout);

    completed = true;
    buffer = null;

    if (client != null) {
      client.destroy();
      client = null;
    }
  }

  function getDetailsFromBuffer(buffer) {
    var startSubstring = 'StreamTitle=';
    var startPosition = buffer.indexOf(startSubstring);
    var endSubstring = ';';
    var endPosition = buffer.toString().indexOf(';', startPosition);

    if (startPosition > -1 && endPosition > startPosition) {
      var titleString = buffer.substring(startPosition, endPosition);
      var title = titleString.substring(13, titleString.length - 1);
      return title;
    }

    return null;
  }

  function getHeadersFromBuffer(buffer) {
    var headersArray = buffer.split('\n');
    var headersObject = {};

    headersArray
      .filter(function (line) {
        return (
          (line.indexOf('icy') !== -1 && line.indexOf(':') !== -1) ||
          line.toLowerCase().indexOf('content-type') !== -1
        );
      })
      .forEach(function (line) {
        var keyValueArray = line.trim().split(":");
        if (keyValueArray.length === 2) {
          headersObject[keyValueArray[0].toLowerCase()] = keyValueArray[1].trim();
        }
      });

    return headersObject;
  }

  function handleBuffer(buffer, callback) {
    var title = getDetailsFromBuffer(buffer);
    title = utils.fixTrackTitle(title);

    var headers = getHeadersFromBuffer(buffer);

    var station = {};
    station.title = title;
    station.fetchsource = 'STREAM';
    station.headers = headers;

    return callback(null, station);
  }

  function handleRedirect(buffer) {
    var redirectTest = /Location: (.*)/m.exec(buffer);
    if (redirectTest) {
      // Redirect!
      var newUrl = redirectTest[1];

      if (newUrl === urlString) {
        const error = new Error(
          'Redirect loop detected. ' + urlString + ' -> ' + newUrl
        );
        return errorCallback(error);
      }

      return newUrl;
    }

    return false;
  }

  function areThereErrors(buffer) {
    // If we get back HTML there's a problem
    var contentTypeTest = /Content-Type: text\/html(.*)/m.exec(buffer);
    if (contentTypeTest) {
      return true;
    }

    return false;
  }

  function returnError() {
    tearDown();
    return callback(new Error('Error fetching stream'));
  }
}

module.exports.getStreamStation = getStreamStation;
<|endoftext|>


<commit_before>const fs = require('fs');
const path = require('path');
const http = require('http');
const https = require('https');

let paramIndex = 2;
const CONFIG_FILE_PATH = process.argv[paramIndex++];
if(!CONFIG_FILE_PATH) {
    throw new Error('Config file path not set');
}
const API_URL = process.argv[paramIndex++];
if(!API_URL) {
    throw new Error('API URL not set');
}
const ASSETS_BASE_URL = process.argv[paramIndex++] || './';
const GOOGLE_API_KEY = process.argv[paramIndex++];
if(!GOOGLE_API_KEY) {
    throw new Error('Google API key not set');
}
const GOOGLE_TRACKER_ID = process.argv[paramIndex++];
let PARTNER_LOGO_URL = process.argv[paramIndex++];
const THEME_FILE_PATH = process.argv[paramIndex++];
if(!THEME_FILE_PATH) {
    throw new Error('Theme file path not set');
}
const THEME = process.argv[paramIndex++] || 'pink';

if(PARTNER_LOGO_URL) {
    let destLogoFileUrl = '/assets/img/partner-logo.png';
    downloadFile(PARTNER_LOGO_URL, `../client/src${destLogoFileUrl}`).then(
        () => {
            PARTNER_LOGO_URL = destLogoFileUrl;
            writeConfig();
        },
        (err) => {
            console.log('Error downloading partner logo', err);
            PARTNER_LOGO_URL = '';
            writeConfig();
        }
    );
}

function writeConfig() {
    const configFilePath = path.join(process.cwd(), CONFIG_FILE_PATH);
    let configContent =
`export const params = {
  assetsBaseUrl: '${ASSETS_BASE_URL}',
  googleApiKey: '${GOOGLE_API_KEY}',
  googleTrackerId: '${GOOGLE_TRACKER_ID}',
  apiUrl: '${API_URL}',
  partnerLogoUrl: '${PARTNER_LOGO_URL}'
};`;
    fs.writeFileSync(configFilePath, configContent);

    const themeFilePath = path.join(process.cwd(), THEME_FILE_PATH);
    let themeContent = `@import 'theme-${THEME}';`;
    fs.writeFileSync(themeFilePath, themeContent);
}

async function downloadFile(url, destFilePath) {
    return await new Promise((resolve, reject) => {
        const client = url.startsWith('https') ? https : http;
        client.get(url, (res) => {
            if(res.statusCode !== 200) {
                reject(new Error(`Error downloading file: ${res.statusCode}`));
                return;
            }
            const contentType = res.headers['content-type'];
            if(!contentType.startsWith('image/')) {
                reject(new Error('Downloaded file is not an image'));
                return;
            }
            const data = [];
            res.on('error', function(err) {
                reject(err);
            });
            res.on('data', function(chunk) {
                data.push(Buffer.from(chunk, 'binary'));
            });
            res.on('end', function() {
                fs.writeFileSync(destFilePath, Buffer.concat(data));
                resolve();
            });
        });
    });
}<commit_msg>Updated partner logo code to follow redirects.<commit_after>const fs = require('fs');
const path = require('path');
const http = require('http');
const https = require('https');

let paramIndex = 2;
const CONFIG_FILE_PATH = process.argv[paramIndex++];
if(!CONFIG_FILE_PATH) {
    throw new Error('Config file path not set');
}
const API_URL = process.argv[paramIndex++];
if(!API_URL) {
    throw new Error('API URL not set');
}
const ASSETS_BASE_URL = process.argv[paramIndex++] || './';
const GOOGLE_API_KEY = process.argv[paramIndex++];
if(!GOOGLE_API_KEY) {
    throw new Error('Google API key not set');
}
const GOOGLE_TRACKER_ID = process.argv[paramIndex++];
let PARTNER_LOGO_URL = process.argv[paramIndex++];
const THEME_FILE_PATH = process.argv[paramIndex++];
if(!THEME_FILE_PATH) {
    throw new Error('Theme file path not set');
}
const THEME = process.argv[paramIndex++] || 'pink';

if(PARTNER_LOGO_URL) {
    let destLogoFileUrl = '/assets/img/partner-logo.png';
    downloadFileSync(PARTNER_LOGO_URL, `../client/src${destLogoFileUrl}`).then(
        () => {
            PARTNER_LOGO_URL = destLogoFileUrl;
            writeConfig();
        },
        (err) => {
            console.log('Error downloading partner logo', err);
            PARTNER_LOGO_URL = '';
            writeConfig();
        }
    );
}

function writeConfig() {
    const configFilePath = path.join(process.cwd(), CONFIG_FILE_PATH);
    let configContent =
`export const params = {
  assetsBaseUrl: '${ASSETS_BASE_URL}',
  googleApiKey: '${GOOGLE_API_KEY}',
  googleTrackerId: '${GOOGLE_TRACKER_ID}',
  apiUrl: '${API_URL}',
  partnerLogoUrl: '${PARTNER_LOGO_URL}'
};`;
    fs.writeFileSync(configFilePath, configContent);

    const themeFilePath = path.join(process.cwd(), THEME_FILE_PATH);
    let themeContent = `@import 'theme-${THEME}';`;
    fs.writeFileSync(themeFilePath, themeContent);
}

async function downloadFileSync(url, destFilePath) {
    await downloadFile(url, destFilePath);
}

async function downloadFile(url, destFilePath) {
    return new Promise((resolve, reject) => {
        const client = url.startsWith('https') ? https : http;
        client.get(url, (res) => {
            if(res.statusCode === 301 || res.statusCode === 302) {
                // redirect
                downloadFile(res.headers.location, destFilePath).then(resolve, reject);
                return;
            } else if(res.statusCode !== 200) {
                reject(new Error(`Error downloading file: ${res.statusCode}`));
                return;
            }
            const contentType = res.headers['content-type'];
            if(!contentType.startsWith('image/')) {
                reject(new Error('Downloaded file is not an image'));
                return;
            }
            const data = [];
            res.on('error', function(err) {
                reject(err);
            });
            res.on('data', function(chunk) {
                data.push(Buffer.from(chunk, 'binary'));
            });
            res.on('end', function() {
                fs.writeFileSync(destFilePath, Buffer.concat(data));
                resolve();
            });
        });
    });
}<|endoftext|>


<commit_before>function UserDetailAssistant(argFromPusher) {
	/* this is the creator function for your scene assistant object. It will be passed all the
	   additional parameters (after the scene name) that were passed to pushScene. The reference
	   to the scene controller (this.controller) has not be established yet, so any initialization
	   that needs the scene controller should be done in the setup function below. */

	scene_helpers.addCommonSceneMethods(this);

	sch.debug('argFromPusher:' + sch.enJSON(argFromPusher));

	if (sc.helpers.isString(argFromPusher) || sc.helpers.isNumber(argFromPusher)) {
		/*
			we were passed a single arg, so we need to retrieve the user data
		*/
		this.userid  = argFromPusher;
		this.userRetrieved = false;
	} else {
		this.userobj = argFromPusher.userobj;
		this.userRetrieved = true;
	}

}

UserDetailAssistant.prototype.setup = function() {
	var thisA = this;

	this.initTwit();

	if (sc.app.username && sc.app.password) {
		this.setupCommonMenus({
			viewMenuItems: [
				{
					items:[
						{label: $L("User Details"), command:'scroll-top', 'class':"palm-header left", width:320}
					]
				}

			],
			cmdMenuItems:[
				{
					items: [
						{label:$L('Compose'),  icon:'compose', command:'compose', shortcut:'N'},
						{}
					]
				}

			]
		});
		this.initAppMenu({ 'items':loggedin_appmenu_items });

	} else {
		this.setupCommonMenus({});

		this.initAppMenu();
	};

	this.scroller = this.controller.getSceneScroller();

	/* this function is for setup tasks that have to happen when the scene is first created */

	/* use Mojo.View.render to render view templates and add them to the scene, if needed. */

	/* setup widgets here */

	/* add event handlers to listen to events from widgets */

	jQuery().bind('new_user_timeline_data', { thisAssistant:this }, function(e, tweets) {

		var rendertweets = tweets;
		// they come in oldest-first, so reverse it since we're rendering as a collection
		rendertweets = rendertweets.reverse();

		jQuery.each( rendertweets, function() {
			this.text = Spaz.makeItemsClickable(this.text);

			/*
				save this tweet to Depot
			*/
			sc.app.Tweets.save(this);

		});

		/*
			Render the new tweets as a collection (speed increase, I suspect)
		*/

		var itemhtml = sc.app.tpl.parseArray('tweet', rendertweets);

		jQuery('#user-timeline').html(itemhtml);

		/*
			Update relative dates
		*/
		sch.updateRelativeTimes('#user-timeline>div.timeline-entry .meta>.date', 'data-created_at');

	});

	jQuery().bind('get_user_succeeded', function(e, userobj) {
		thisA.userRetrieved = true;
		thisA.userobj = userobj;

		sch.debug(thisA.userobj.);

		thisA.userobj.description = Spaz.makeItemsClickable(thisA.userobj.description);

		var itemhtml = sc.app.tpl.parseTemplate('user-detail', thisA.userobj);
		jQuery('#user-detail').html(itemhtml);
		sch.debug(jQuery('#user-detail').get(0).outerHTML);

		thisA.twit.getUserTimeline(thisA.userobj.id);
	});

	jQuery().bind('get_user_failed', function(e, error_obj) {
		// error_obj.url
		// error_obj.xhr
		// error_obj.msg
		var err_msg = $L('There was an error retrieving this user');
		thisA.displayErrorInfo(err_msg, error_obj);

	});

	jQuery().bind('create_friendship_succeeded',  { thisAssistant:this }, function(e, userobj) {
		jQuery('#follow-user[data-screen_name="'+userobj.screen_name+'"]')
			.attr('data-following', 'true')
			.html($L('Stop following user'));
	});
	jQuery().bind('destroy_friendship_succeeded', { thisAssistant:this }, function(e, userobj) {
		jQuery('#follow-user[data-screen_name="'+userobj.screen_name+'"]')
			.attr('data-following', 'false')
			.html($L('Follow user'));
	});

	jQuery().bind('create_block_succeeded', { thisAssistant:this }, function(e, userobj) {
		jQuery('#block-user[data-screen_name="'+userobj.screen_name+'"]')
			.attr('data-blocked', 'true')
			.html($L('Unblock user'));
	});
	jQuery().bind('destroy_block_succeeded', { thisAssistant:this }, function(e, userobj) {
		jQuery('#block-user[data-screen_name="'+userobj.screen_name+'"]')
			.attr('data-blocked', 'false')
			.html($L('Block user'));
	});

};

UserDetailAssistant.prototype.activate = function(event) {
	/* put in event handlers here that should only be in effect when this scene is active. For
	   example, key handlers that are observing the document */

	var thisA = this; // for closures

	jQuery('#user-timeline-trigger', this.scroller).live(Mojo.Event.tap, function(e) {
		sch.debug(jQuery(this).attr('id'));
		var jq_usertl = jQuery('#user-timeline');
		if (jq_usertl.is(':visible')) {
			jq_usertl.slideUp('500');
			jQuery(this).find('.arrow_button').addClass('palm-arrow-closed').removeClass('palm-arrow-expanded');
		} else {
			jq_usertl.slideDown('500');
			jQuery(this).find('.arrow_button').removeClass('palm-arrow-closed').addClass('palm-arrow-expanded');
		}

	});
	jQuery('#user-detail-actions #search-user', this.scroller).live(Mojo.Event.tap, function(e) {
		var screen_name = jQuery(this).attr('data-screen_name');
		sch.debug("searching for '"+screen_name+"'");
		thisA.searchFor('from:'+screen_name+' OR to:'+screen_name);
	});
	jQuery('#user-detail-actions #reply-to-user', this.scroller).live(Mojo.Event.tap, function(e) {
		sch.debug(jQuery(this).attr('id'));
		thisA.prepReply(jQuery(this).attr('data-screen_name'));
	});
	jQuery('#user-detail-actions #dm-user', this.scroller).live(Mojo.Event.tap, function(e) {
		sch.debug(jQuery(this).attr('id'));
		thisA.prepDirectMessage(jQuery(this).attr('data-screen_name'));
	});
	jQuery('#user-detail-actions #follow-user', this.scroller).live(Mojo.Event.tap, function(e) {
		sch.debug("Friend user:"+jQuery(this).attr('data-screen_name'));
		// Mojo.Controller.notYetImplemented();

		var user_id = jQuery(this).attr('data-screen_name');
		if (jQuery(this).attr('data-following') === 'true') {
			sch.debug('UN-FOLLOWING');
			thisA.twit.removeFriend(user_id);
		} else {
			sch.debug('FOLLOWING');
			thisA.twit.addFriend(user_id);
		}

	});
	jQuery('#user-detail-actions #block-user', this.scroller).live(Mojo.Event.tap, function(e) {
		sch.debug("Block user:"+jQuery(this).attr('data-screen_name'));
		// Mojo.Controller.notYetImplemented();

		/*
			Note that on first load of user detail, state will alwasy be 'false'
			because we don't get blocked state via the API
		*/
		var user_id = jQuery(this).attr('data-screen_name');
		if (jQuery(this).attr('data-blocked') === 'true') {
			sch.debug('UNBLOCKING:'+user_id);
			thisA.twit.unblock(user_id);
		} else {
			sch.debug('BLOCKING:'+user_id);
			thisA.twit.block(user_id);
		}

		// sch.debug('BLOCKING:'+user_id);
		// thisA.twit.block(user_id);

	});

	jQuery('#user-detail-container div.timeline-entry', this.scroller).live(Mojo.Event.tap, function(e) {
		var jqtarget = jQuery(e.target);

		e.stopImmediatePropagation();

		if (jqtarget.is('div.timeline-entry>.user') || jqtarget.is('div.timeline-entry>.user img')) {
			var userid = jQuery(this).attr('data-user-id');
			Mojo.Controller.stageController.pushScene('user-detail', userid);
			return;

		} else if (jqtarget.is('.username.clickable')) {
			var userid = jqtarget.attr('data-user-screen_name');
			Mojo.Controller.stageController.pushScene('user-detail', '@'+userid);
			return;

		} else if (jqtarget.is('.hashtag.clickable')) {
			var hashtag = jqtarget.attr('data-hashtag');
			thisA.searchFor('#'+hashtag);
			return;

		} else if (jqtarget.is('div.timeline-entry .meta')) {
			var status_id = jqtarget.attr('data-status-id');
			var isdm = false;
			var status_obj = null;

			if (jqtarget.parent().parent().hasClass('dm')) {
				isdm = true;
			}

			Mojo.Controller.stageController.pushScene('message-detail', {'status_id':status_id, 'isdm':isdm, 'status_obj':status_obj});
			return;

		} else if (jqtarget.is('div.timeline-entry a[href]')) {
			return;

		} else {
			var status_id = jQuery(this).attr('data-status-id');
			var isdm = false;
			var status_obj = null;

			if (jQuery(this).hasClass('dm')) {
				isdm = true;
			}

			Mojo.Controller.stageController.pushScene('message-detail', {'status_id':status_id, 'isdm':isdm, 'status_obj':status_obj});
			return;
		}
	});

	// jQuery('#user-detail-container .username.clickable', this.scroller).live(Mojo.Event.tap, function(e) {
	// 	var userid = jQuery(this).attr('data-user-screen_name');
	// 	Mojo.Controller.stageController.pushScene('user-detail', userid);
	// });
	//
	// jQuery('#user-detail-container .hashtag.clickable', this.scroller).live(Mojo.Event.tap, function(e) {
	// 	var hashtag = jQuery(this).attr('data-hashtag');
	// 	thisA.searchFor('#'+hashtag);
	// });
	//
	// jQuery('#user-detail-container div.timeline-entry>.status>.meta', this.scroller).live(Mojo.Event.tap, function(e) {
	// 	var statusid = jQuery(this).attr('data-status-id');
	// 	Mojo.Controller.stageController.pushScene('message-detail', statusid);
	// });
	//
	// jQuery('#user-detail-container div.timeline-entry', this.scroller).live(Mojo.Event.tap, function(e) {
	// 	var statusid = jQuery(this).attr('data-status-id');
	// 	Mojo.Controller.stageController.pushScene('message-detail', statusid);
	// });

	if (!this.userRetrieved) {
		sc.app.Tweets.getUser(
			this.userid,
			function(r) {
				jQuery(document).trigger('get_user_succeeded', [r]);
			},
			function(r) {
				jQuery(document).trigger('get_user_failed', [r]);
			}
		);
		// this.twit.getUser(this.userid);
	}

	// this.addPostPopup();

};

UserDetailAssistant.prototype.deactivate = function(event) {
	/* remove any event handlers you added in activate and do any other cleanup that should happen before
	   this scene is popped or another scene is pushed on top */

	// alert('UserDetailAssistant.prototype.deactivate');

	// this.removePostPopup();

	/*
		We have to unbind our event listeners or weird/bad things happen
	*/
	jQuery('#user-detail-actions #view-user-posts', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-actions #search-user', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-actions #reply-to-user', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-actions #dm-user', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-actions #follow-user', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-actions #block-user', this.scroller).die(Mojo.Event.tap);

	// jQuery('#user-detail-container .username.clickable', this.scroller).die(Mojo.Event.tap);
	// jQuery('#user-detail-container .hashtag.clickable', this.scroller).die(Mojo.Event.tap);
	// jQuery('#user-detail-container div.timeline-entry>.status>.meta', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-timeline-trigger', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-container div.timeline-entry', this.scroller).die(Mojo.Event.tap);
};

UserDetailAssistant.prototype.cleanup = function(event) {
	/* this function should do any cleanup needed before the scene is destroyed as
	   a result of being popped off the scene stack */

	jQuery().unbind('new_user_timeline_data');
	jQuery().unbind('get_user_succeeded');
	jQuery().unbind('get_user_failed');
	jQuery().unbind('create_friendship_succeeded');
	jQuery().unbind('destroy_friendship_succeeded');
	jQuery().unbind('create_block_succeeded');
	jQuery().unbind('destroy_block_succeeded');

};
<commit_msg>Fix for syntax error in user-detail-assistant.js<commit_after>function UserDetailAssistant(argFromPusher) {
	/* this is the creator function for your scene assistant object. It will be passed all the
	   additional parameters (after the scene name) that were passed to pushScene. The reference
	   to the scene controller (this.controller) has not be established yet, so any initialization
	   that needs the scene controller should be done in the setup function below. */

	scene_helpers.addCommonSceneMethods(this);

	sch.debug('argFromPusher:' + sch.enJSON(argFromPusher));

	if (sc.helpers.isString(argFromPusher) || sc.helpers.isNumber(argFromPusher)) {
		/*
			we were passed a single arg, so we need to retrieve the user data
		*/
		this.userid  = argFromPusher;
		this.userRetrieved = false;
	} else {
		this.userobj = argFromPusher.userobj;
		this.userRetrieved = true;
	}

}

UserDetailAssistant.prototype.setup = function() {
	var thisA = this;

	this.initTwit();

	if (sc.app.username && sc.app.password) {
		this.setupCommonMenus({
			viewMenuItems: [
				{
					items:[
						{label: $L("User Details"), command:'scroll-top', 'class':"palm-header left", width:320}
					]
				}

			],
			cmdMenuItems:[
				{
					items: [
						{label:$L('Compose'),  icon:'compose', command:'compose', shortcut:'N'},
						{}
					]
				}

			]
		});
		this.initAppMenu({ 'items':loggedin_appmenu_items });

	} else {
		this.setupCommonMenus({});

		this.initAppMenu();
	};

	this.scroller = this.controller.getSceneScroller();

	/* this function is for setup tasks that have to happen when the scene is first created */

	/* use Mojo.View.render to render view templates and add them to the scene, if needed. */

	/* setup widgets here */

	/* add event handlers to listen to events from widgets */

	jQuery().bind('new_user_timeline_data', { thisAssistant:this }, function(e, tweets) {

		var rendertweets = tweets;
		// they come in oldest-first, so reverse it since we're rendering as a collection
		rendertweets = rendertweets.reverse();

		jQuery.each( rendertweets, function() {
			this.text = Spaz.makeItemsClickable(this.text);

			/*
				save this tweet to Depot
			*/
			sc.app.Tweets.save(this);

		});

		/*
			Render the new tweets as a collection (speed increase, I suspect)
		*/

		var itemhtml = sc.app.tpl.parseArray('tweet', rendertweets);

		jQuery('#user-timeline').html(itemhtml);

		/*
			Update relative dates
		*/
		sch.updateRelativeTimes('#user-timeline>div.timeline-entry .meta>.date', 'data-created_at');

	});

	jQuery().bind('get_user_succeeded', function(e, userobj) {
		thisA.userRetrieved = true;
		thisA.userobj = userobj;

		sch.debug(thisA.userobj);

		thisA.userobj.description = Spaz.makeItemsClickable(thisA.userobj.description);

		var itemhtml = sc.app.tpl.parseTemplate('user-detail', thisA.userobj);
		jQuery('#user-detail').html(itemhtml);
		sch.debug(jQuery('#user-detail').get(0).outerHTML);

		thisA.twit.getUserTimeline(thisA.userobj.id);
	});

	jQuery().bind('get_user_failed', function(e, error_obj) {
		// error_obj.url
		// error_obj.xhr
		// error_obj.msg
		var err_msg = $L('There was an error retrieving this user');
		thisA.displayErrorInfo(err_msg, error_obj);

	});

	jQuery().bind('create_friendship_succeeded',  { thisAssistant:this }, function(e, userobj) {
		jQuery('#follow-user[data-screen_name="'+userobj.screen_name+'"]')
			.attr('data-following', 'true')
			.html($L('Stop following user'));
	});
	jQuery().bind('destroy_friendship_succeeded', { thisAssistant:this }, function(e, userobj) {
		jQuery('#follow-user[data-screen_name="'+userobj.screen_name+'"]')
			.attr('data-following', 'false')
			.html($L('Follow user'));
	});

	jQuery().bind('create_block_succeeded', { thisAssistant:this }, function(e, userobj) {
		jQuery('#block-user[data-screen_name="'+userobj.screen_name+'"]')
			.attr('data-blocked', 'true')
			.html($L('Unblock user'));
	});
	jQuery().bind('destroy_block_succeeded', { thisAssistant:this }, function(e, userobj) {
		jQuery('#block-user[data-screen_name="'+userobj.screen_name+'"]')
			.attr('data-blocked', 'false')
			.html($L('Block user'));
	});

};

UserDetailAssistant.prototype.activate = function(event) {
	/* put in event handlers here that should only be in effect when this scene is active. For
	   example, key handlers that are observing the document */

	var thisA = this; // for closures

	jQuery('#user-timeline-trigger', this.scroller).live(Mojo.Event.tap, function(e) {
		sch.debug(jQuery(this).attr('id'));
		var jq_usertl = jQuery('#user-timeline');
		if (jq_usertl.is(':visible')) {
			jq_usertl.slideUp('500');
			jQuery(this).find('.arrow_button').addClass('palm-arrow-closed').removeClass('palm-arrow-expanded');
		} else {
			jq_usertl.slideDown('500');
			jQuery(this).find('.arrow_button').removeClass('palm-arrow-closed').addClass('palm-arrow-expanded');
		}

	});
	jQuery('#user-detail-actions #search-user', this.scroller).live(Mojo.Event.tap, function(e) {
		var screen_name = jQuery(this).attr('data-screen_name');
		sch.debug("searching for '"+screen_name+"'");
		thisA.searchFor('from:'+screen_name+' OR to:'+screen_name);
	});
	jQuery('#user-detail-actions #reply-to-user', this.scroller).live(Mojo.Event.tap, function(e) {
		sch.debug(jQuery(this).attr('id'));
		thisA.prepReply(jQuery(this).attr('data-screen_name'));
	});
	jQuery('#user-detail-actions #dm-user', this.scroller).live(Mojo.Event.tap, function(e) {
		sch.debug(jQuery(this).attr('id'));
		thisA.prepDirectMessage(jQuery(this).attr('data-screen_name'));
	});
	jQuery('#user-detail-actions #follow-user', this.scroller).live(Mojo.Event.tap, function(e) {
		sch.debug("Friend user:"+jQuery(this).attr('data-screen_name'));
		// Mojo.Controller.notYetImplemented();

		var user_id = jQuery(this).attr('data-screen_name');
		if (jQuery(this).attr('data-following') === 'true') {
			sch.debug('UN-FOLLOWING');
			thisA.twit.removeFriend(user_id);
		} else {
			sch.debug('FOLLOWING');
			thisA.twit.addFriend(user_id);
		}

	});
	jQuery('#user-detail-actions #block-user', this.scroller).live(Mojo.Event.tap, function(e) {
		sch.debug("Block user:"+jQuery(this).attr('data-screen_name'));
		// Mojo.Controller.notYetImplemented();

		/*
			Note that on first load of user detail, state will alwasy be 'false'
			because we don't get blocked state via the API
		*/
		var user_id = jQuery(this).attr('data-screen_name');
		if (jQuery(this).attr('data-blocked') === 'true') {
			sch.debug('UNBLOCKING:'+user_id);
			thisA.twit.unblock(user_id);
		} else {
			sch.debug('BLOCKING:'+user_id);
			thisA.twit.block(user_id);
		}

		// sch.debug('BLOCKING:'+user_id);
		// thisA.twit.block(user_id);

	});

	jQuery('#user-detail-container div.timeline-entry', this.scroller).live(Mojo.Event.tap, function(e) {
		var jqtarget = jQuery(e.target);

		e.stopImmediatePropagation();

		if (jqtarget.is('div.timeline-entry>.user') || jqtarget.is('div.timeline-entry>.user img')) {
			var userid = jQuery(this).attr('data-user-id');
			Mojo.Controller.stageController.pushScene('user-detail', userid);
			return;

		} else if (jqtarget.is('.username.clickable')) {
			var userid = jqtarget.attr('data-user-screen_name');
			Mojo.Controller.stageController.pushScene('user-detail', '@'+userid);
			return;

		} else if (jqtarget.is('.hashtag.clickable')) {
			var hashtag = jqtarget.attr('data-hashtag');
			thisA.searchFor('#'+hashtag);
			return;

		} else if (jqtarget.is('div.timeline-entry .meta')) {
			var status_id = jqtarget.attr('data-status-id');
			var isdm = false;
			var status_obj = null;

			if (jqtarget.parent().parent().hasClass('dm')) {
				isdm = true;
			}

			Mojo.Controller.stageController.pushScene('message-detail', {'status_id':status_id, 'isdm':isdm, 'status_obj':status_obj});
			return;

		} else if (jqtarget.is('div.timeline-entry a[href]')) {
			return;

		} else {
			var status_id = jQuery(this).attr('data-status-id');
			var isdm = false;
			var status_obj = null;

			if (jQuery(this).hasClass('dm')) {
				isdm = true;
			}

			Mojo.Controller.stageController.pushScene('message-detail', {'status_id':status_id, 'isdm':isdm, 'status_obj':status_obj});
			return;
		}
	});

	// jQuery('#user-detail-container .username.clickable', this.scroller).live(Mojo.Event.tap, function(e) {
	// 	var userid = jQuery(this).attr('data-user-screen_name');
	// 	Mojo.Controller.stageController.pushScene('user-detail', userid);
	// });
	//
	// jQuery('#user-detail-container .hashtag.clickable', this.scroller).live(Mojo.Event.tap, function(e) {
	// 	var hashtag = jQuery(this).attr('data-hashtag');
	// 	thisA.searchFor('#'+hashtag);
	// });
	//
	// jQuery('#user-detail-container div.timeline-entry>.status>.meta', this.scroller).live(Mojo.Event.tap, function(e) {
	// 	var statusid = jQuery(this).attr('data-status-id');
	// 	Mojo.Controller.stageController.pushScene('message-detail', statusid);
	// });
	//
	// jQuery('#user-detail-container div.timeline-entry', this.scroller).live(Mojo.Event.tap, function(e) {
	// 	var statusid = jQuery(this).attr('data-status-id');
	// 	Mojo.Controller.stageController.pushScene('message-detail', statusid);
	// });

	if (!this.userRetrieved) {
		sc.app.Tweets.getUser(
			this.userid,
			function(r) {
				jQuery(document).trigger('get_user_succeeded', [r]);
			},
			function(r) {
				jQuery(document).trigger('get_user_failed', [r]);
			}
		);
		// this.twit.getUser(this.userid);
	}

	// this.addPostPopup();

};

UserDetailAssistant.prototype.deactivate = function(event) {
	/* remove any event handlers you added in activate and do any other cleanup that should happen before
	   this scene is popped or another scene is pushed on top */

	// alert('UserDetailAssistant.prototype.deactivate');

	// this.removePostPopup();

	/*
		We have to unbind our event listeners or weird/bad things happen
	*/
	jQuery('#user-detail-actions #view-user-posts', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-actions #search-user', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-actions #reply-to-user', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-actions #dm-user', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-actions #follow-user', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-actions #block-user', this.scroller).die(Mojo.Event.tap);

	// jQuery('#user-detail-container .username.clickable', this.scroller).die(Mojo.Event.tap);
	// jQuery('#user-detail-container .hashtag.clickable', this.scroller).die(Mojo.Event.tap);
	// jQuery('#user-detail-container div.timeline-entry>.status>.meta', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-timeline-trigger', this.scroller).die(Mojo.Event.tap);
	jQuery('#user-detail-container div.timeline-entry', this.scroller).die(Mojo.Event.tap);
};

UserDetailAssistant.prototype.cleanup = function(event) {
	/* this function should do any cleanup needed before the scene is destroyed as
	   a result of being popped off the scene stack */

	jQuery().unbind('new_user_timeline_data');
	jQuery().unbind('get_user_succeeded');
	jQuery().unbind('get_user_failed');
	jQuery().unbind('create_friendship_succeeded');
	jQuery().unbind('destroy_friendship_succeeded');
	jQuery().unbind('create_block_succeeded');
	jQuery().unbind('destroy_block_succeeded');

};
<|endoftext|>


<commit_before>
import * as Actions from './actions.js';

const defaultState = {
  hasData: false,
  isRequesting: false,
  count: 0
};

const statusReducer = (state = defaultState, action) => {

  console.log(action, state);

  // console.log(state,action);
  switch (action.type) {
  case Actions.MAKE_CHOICE:
    return Object.assign({}, state, { count: ++state.count });
  case Actions.DATA_REQUESTED:
    return Object.assign({}, state, { isRequesting: true });
  case Actions.DATA_RECIEVED:
    return Object.assign({}, state, { isRequesting: false, hasData: true });
  default: return state;
  }
};

module.exports = statusReducer;
<commit_msg>scroll to top on router change<commit_after>
import _ from 'lodash';
import * as Actions from './actions.js';

const defaultState = {
  hasData: false,
  isRequesting: false,
  count: 0
};

const statusReducer = (state = defaultState, action) => {

  console.log(action, state);

  switch (action.type) {
  case '@@router/LOCATION_CHANGE':
    _.defer(()=>{window.scrollTo(0, 0);});
    return state;
  case Actions.MAKE_CHOICE:
    return Object.assign({}, state, { count: ++state.count });
  case Actions.DATA_REQUESTED:
    return Object.assign({}, state, { isRequesting: true });
  case Actions.DATA_RECIEVED:
    return Object.assign({}, state, { isRequesting: false, hasData: true });
  default: return state;
  }
};

module.exports = statusReducer;
<|endoftext|>


<commit_before>import React from 'react';
import createClass from 'create-react-class';
import PropTypes from 'prop-types';
import Select from 'react-select';
import fetch from 'isomorphic-fetch';

const GithubUsers = createClass({
	displayName: 'GithubUsers',
	propTypes: {
		label: PropTypes.string,
	},
	getInitialState () {
		return {
			backspaceRemoves: true,
			multi: true
		};
	},
	onChange (value) {
		this.setState({
			value: value,
		});
	},
	switchToMulti () {
		this.setState({
			multi: true,
			value: [this.state.value],
		});
	},
	switchToSingle () {
		this.setState({
			multi: false,
			value: this.state.value ? this.state.value[0] : null
		});
	},
	getUsers (input) {
		if (!input) {
			return Promise.resolve({ options: [] });
		}

		return fetch(`https://api.github.com/search/users?q=${input}`)
		.then((response) => response.json())
		.then((json) => {
			return { options: json.items };
		});
	},
	gotoUser (value, event) {
		window.open(value.html_url);
	},
	toggleBackspaceRemoves () {
		this.setState({
			backspaceRemoves: !this.state.backspaceRemoves
		});
	},
	toggleCreatable () {
		this.setState({
			creatable: !this.state.creatable
		});
	},
	render () {
		const AsyncComponent = this.state.creatable
			? Select.AsyncCreatable
			: Select.Async;

		return (

{this.props.label} (Source)

				<AsyncComponent multi={this.state.multi} value={this.state.value} onChange={this.onChange} onValueClick={this.gotoUser} valueKey="id" labelKey="login" loadOptions={this.getUsers} backspaceRemoves={this.state.backspaceRemoves} />

						<input type="radio" className="checkbox-control" checked={this.state.multi} onChange={this.switchToMulti}/>
						Multiselect

						<input type="radio" className="checkbox-control" checked={!this.state.multi} onChange={this.switchToSingle}/>
						Single Value

					   <input type="checkbox" className="checkbox-control" checked={this.state.creatable} onChange={this.toggleCreatable} />
					   Creatable?

					   <input type="checkbox" className="checkbox-control" checked={this.state.backspaceRemoves} onChange={this.toggleBackspaceRemoves} />
					   Backspace Removes?

This example uses fetch.js for showing Async options with Promises

		);
	}
});

module.exports = GithubUsers;
<commit_msg>Fixed console error<commit_after>import React from 'react';
import createClass from 'create-react-class';
import PropTypes from 'prop-types';
import Select from 'react-select';
import fetch from 'isomorphic-fetch';

const GithubUsers = createClass({
	displayName: 'GithubUsers',
	propTypes: {
		label: PropTypes.string,
	},
	getInitialState () {
		return {
			backspaceRemoves: true,
			multi: true,
			creatable: false,
		};
	},
	onChange (value) {
		this.setState({
			value: value,
		});
	},
	switchToMulti () {
		this.setState({
			multi: true,
			value: [this.state.value],
		});
	},
	switchToSingle () {
		this.setState({
			multi: false,
			value: this.state.value ? this.state.value[0] : null
		});
	},
	getUsers (input) {
		if (!input) {
			return Promise.resolve({ options: [] });
		}

		return fetch(`https://api.github.com/search/users?q=${input}`)
		.then((response) => response.json())
		.then((json) => {
			return { options: json.items };
		});
	},
	gotoUser (value, event) {
		window.open(value.html_url);
	},
	toggleBackspaceRemoves () {
		this.setState({
			backspaceRemoves: !this.state.backspaceRemoves
		});
	},
	toggleCreatable () {
		this.setState({
			creatable: !this.state.creatable
		});
	},
	render () {
		const AsyncComponent = this.state.creatable
			? Select.AsyncCreatable
			: Select.Async;

		return (

{this.props.label} (Source)

				<AsyncComponent multi={this.state.multi} value={this.state.value} onChange={this.onChange} onValueClick={this.gotoUser} valueKey="id" labelKey="login" loadOptions={this.getUsers} backspaceRemoves={this.state.backspaceRemoves} />

						<input type="radio" className="checkbox-control" checked={this.state.multi} onChange={this.switchToMulti}/>
						Multiselect

						<input type="radio" className="checkbox-control" checked={!this.state.multi} onChange={this.switchToSingle}/>
						Single Value

					   <input type="checkbox" className="checkbox-control" checked={this.state.creatable} onChange={this.toggleCreatable} />
					   Creatable?

					   <input type="checkbox" className="checkbox-control" checked={this.state.backspaceRemoves} onChange={this.toggleBackspaceRemoves} />
					   Backspace Removes?

This example uses fetch.js for showing Async options with Promises

		);
	}
});

module.exports = GithubUsers;
<|endoftext|>


<commit_before>openerp.web.view_editor = function(openerp) {
var QWeb = openerp.web.qweb;
openerp.web.ViewEditor =   openerp.web.Widget.extend({
    init: function(parent, element_id, dataset, view, options) {
        this._super(parent);
        this.element_id = element_id
        this.parent = parent
        this.dataset = dataset;
        this.model = dataset.model;
        this.xml_id = 0;
    },
    start: function() {
        this.View_editor();
    },
    View_editor : function() {
        var self = this;
        var action = {
            name:'ViewEditor',
            context:this.session.user_context,
            domain: [["model", "=", this.dataset.model]],
            res_model : 'ir.ui.view',
            views : [[false, 'list']],
            type: 'ir.actions.act_window',
            target: "current",
            limit : 80,
            auto_search : true,
            flags: {
                sidebar: false,
                views_switcher: false,
                action_buttons:false,
                search_view:false,
                pager:false,
                radio:true
            },
        };
        var action_manager = new openerp.web.ActionManager(this);
        this.view_edit_dialog = new openerp.web.Dialog(this,{
            modal: true,
            title: 'ViewEditor',
            width: 750,
            height: 500,
            buttons: {
            "Create": function(){
                //to do
            },
            "Edit": function(){
                self.xml_id = 0 ;
                self.get_data();
            },
            "Close": function(){
                $(this).dialog('destroy');
            }
        },
        });
        this.view_edit_dialog.start();
        this.view_edit_dialog.open();
        action_manager.appendTo(this.view_edit_dialog);
        action_manager.do_action(action);
    },
    check_attr: function(xml, tag, level) {
        var obj = new Object();
        obj.child_id = [];
        obj.id = this.xml_id++;
        obj.level = level+1;
        var render_name = "<" + tag;
        obj.att_list = [];
        obj.att_list.push(tag);
        $(xml).each(function() {
            _.each(this.attributes, function(attrs){
                if (tag != 'button') {
                    if (attrs.nodeName == "string" || attrs.nodeName == "name" || attrs.nodeName == "index") {
                        render_name += ' ' + attrs.nodeName + '=' + '"' + attrs.nodeValue + '"' ;
                    }
                } else if (attrs.nodeName == "name") {
                    render_name += ' ' + attrs.nodeName + '=' + '"' + attrs.nodeValue + '"';
                }
                if (attrs.nodeName != "position") {
                    obj.att_list.push( [attrs.nodeName,attrs.nodeValue] );
                }
            });
            render_name+= ">";
        });
        obj.name = render_name;
        return obj;
    },
    save_object: function(val, parent_list, child_obj_list) {
        var self = this;
        var check_id = parent_list[0];
        var p_list = parent_list.slice(1);
        if (val.child_id.length != 0) {
            _.each(val.child_id, function(val, key) {
                if (val.id==check_id) {
                    if (p_list.length!=0) {
                        self.save_object(val, p_list, child_obj_list);
                    } else {
                        val.child_id = child_obj_list;
                        return false;
                    }
                }
            });
        } else {
            val.child_id = child_obj_list;
        }
    },
    xml_node_create: function(xml, root, parent_list, parent_id, main_object){
        var self = this;
        var child_obj_list = [];
        var children_list = $(xml).filter(root).children();
        var parents = $(children_list[0]).parents().get();
        _.each(children_list, function (child_node) {
            child_obj_list.push(self.check_attr(child_node,child_node.tagName.toLowerCase(),parents.length));
        });
        if (children_list.length != 0) {
            if (parents.length <= parent_list.length) {
                parent_list.splice(parents.length - 1);
            }
            parent_list.push(parent_id);
            self.save_object(main_object[0], parent_list.slice(1), child_obj_list);
        }
        for (var i=0; i<children_list.length; i++) {
            self.xml_node_create
            (children_list[i], children_list[i].tagName.toLowerCase(),
                parent_list, child_obj_list[i].id, main_object);
        }
        return main_object;
    },
    parse_xml: function(arch, view_id) {
        var root = $(arch).filter(":first")[0];
        var tag = root.tagName.toLowerCase();
        var obj ={'child_id':[],'id':this.xml_id++,'level':0,'att_list':[],'name':"<view view_id='"+view_id+"'>"};
        var root_object = this.check_attr(root,tag,0);
        obj.child_id = this.xml_node_create(arch, tag, [], this.xml_id-1, [root_object], [])
        return [obj];
    },
    get_data: function() {
        var self = this;
        var view_id =((this.view_edit_dialog.$element.find("input[name='radiogroup']:checked").parent()).parent()).attr('data-id');
        var ve_dataset = new openerp.web.DataSet(this, 'ir.ui.view');
        ve_dataset.read_ids([parseInt(view_id)], ['arch'], function (arch) {
            one_object = self.parse_xml(arch[0].arch,view_id);
            one_object.arch = arch[0].arch;
            dataset = new openerp.web.DataSetSearch(self, 'ir.ui.view', null, null);
            dataset.read_slice([], {domain : [['inherit_id','=', parseInt(view_id)]]}, function (result) {
                _.each(result, function(res) {
                    self.inherit_view(one_object, res);
                });
                return self.edit_view({"main_object": one_object,
                         "parent_child_id": self.parent_child_list(one_object, [])});
            });
        });
    },
    parent_child_list : function(one_object, p_list) {
        var self = this;
        _.each(one_object , function(element){
            if(element.child_id.length != 0){
                p_list.push({"key":element.id,"value":_.pluck(element.child_id, 'id')});
                self.parent_child_list(element.child_id, p_list);
            }
        });
        return p_list;
    },
    inherit_view : function(one_object, result) {
        var self = this;
        var root = $(result.arch).filter('*');
        var xml_list = [];
        if (root[0].tagName.toLowerCase() == "data") {
            xml_list = $(root[0]).children();
        } else {
            xml_list.push(root[0]);
        }
        _.each(xml_list , function(xml){
            var parent_id;
            var check_list = [];
            var xpath_object = self.parse_xml(xml,result.id);
            if (xml.tagName.toLowerCase() == "xpath" ) {
                var part_expr = _.without($(xml).attr('expr').split("/"),"");
                _.each(part_expr,function(part){
                    check_list.push(_.without($.trim(part.replace(/[^a-zA-Z 0-9 _]+/g,'!')).split("!"),""));
                });
            } else {
                    check_list = [_.flatten(xpath_object[0].child_id[0].att_list)];
            }
            self.full_path_search(check_list ,one_object ,xpath_object);
        });
    },
    full_path_search: function(check_list ,val ,xpath_object) {
        var self = this;
        if(xpath_object.length!=0){
            var check = check_list[0];
            var obj;
            switch (check.length) {
                case 2:
                    if(parseInt(check[1])){
                        var list_1 = _.select(val,function(element){
                            var main_list = _.flatten(element.att_list);
                            return _.include(main_list, check[0]);
                        });
                        obj = val[_.indexOf(val,list_1[parseInt(check[1])-1])];
                    } else {
                        obj = _.detect(val, function(element){
                            var main_list = _.flatten(element.att_list);
                            return _.include(main_list, check[0]);
                        });
                    }
                    break;
                case 3:
                    obj = _.detect(val,function(element){
                        var main_list = _.flatten(element.att_list);
                        check = _.uniq(check);
                        var insert = _.intersection(main_list,check);
                        if(insert.length == check.length ){return element;}
                    });
                    break;
                case 1:
                    var list_1 = _.select(val,function(element){
                        var main_list = _.flatten(element.att_list);
                        return _.include(main_list, check[0]);
                    });
                    if(list_1 != 0){
                        (check_list.length == 1)? obj = list_1[0] : check_list.shift();
                    }
                    break;
            }
            if(obj) {
                check_list.shift();
                if (check_list.length !=0){
                    self.full_path_search(check_list ,obj.child_id ,xpath_object);
                } else {
                    var level = obj.level+1;
                    self.increase_level(xpath_object[0], level)
                    obj.child_id.push(xpath_object[0]);
                    xpath_object.pop();
                    return;
                }
            }
            else {
                _.each(val,function(element){
                    self.full_path_search(check_list ,element.child_id ,xpath_object);
                });
            }
        }
    },
    increase_level: function(val, level) {
        var self = this;
        val.level = level;
        _.each(val.child_id, function(val, key) {
            self.increase_level(val, level + 1);
        });
    },
    edit_view: function(one_object) {
        var self = this;
        this.edit_xml_dialog = new openerp.web.Dialog(this,{
            modal: true,
            title: 'Edit Xml',
            width: 750,
            height: 500,
            buttons: {
                "Inherited View": function(){
                    //todo
                },
                "Preview": function(){
                    //todo
                },
                "Close": function(){
                    $(this).dialog('destroy');
                }
            }
        });
        this.edit_xml_dialog.start().open();
        this.edit_xml_dialog.$element.html(QWeb.render('view_editor', {
            'data': one_object['main_object'],
        }));
        this.edit_xml_dialog.$element.find("tr[id^='viewedit-']").click(function() {
            $("tr[id^='viewedit-']").removeClass('ui-selected');
            $(this).addClass('ui-selected');
        });
        this.edit_xml_dialog.$element.find("img[id^='parentimg-']").click(function() {
            if ($(this).attr('src') == '/web/static/src/img/collapse.gif') {
                $(this).attr('src', '/web/static/src/img/expand.gif');
                self.on_expand(this);
            } else {
                $(this).attr('src', '/web/static/src/img/collapse.gif');
                var id = this.id.split('-')[1];
                self.on_collapse(this,one_object['parent_child_id'], one_object['main_object']);
            }
        });
        this.edit_xml_dialog.$element.find("img[id^='side-']").click(function() {
            var side = $(this).closest("tr[id^='viewedit-']")
            var id_tr = (side.attr('id')).split('-')[1];
            var img = side.find("img[id='parentimg-"+id_tr+"']").attr('src'); ;
            var level = side.attr('level');
            var list_shift =[];
            var last_tr;
            var cur_tr = side;
            list_shift.push(side);
            var next_tr;
            switch (this.id) {
                case "side-add":
                    break;
                case "side-remove":
                    break;
                case "side-edit":
                    break;
                case "side-up":
                    while (1) {
                        var prev_tr = cur_tr.prev();
                        if(level >= prev_tr.attr('level') || prev_tr.length == 0) {
                           last_tr = prev_tr;
                           break;
                        }
                        cur_tr = prev_tr;
                    }
                    if (img) {
                        while (1) {
                            next_tr = side.next();
                            if (next_tr.attr('level') <= level || next_tr.length == 0) {
                                break;
                            } else {
                                list_shift.push(next_tr);
                                side = next_tr;
                            }
                        }
                    }
                    if (last_tr.length != 0 && last_tr.attr('level') == level) {
                        _.each(list_shift, function(rec) {
                             $(last_tr).before(rec);
                        });
                    }
                break;
            case "side-down":
                if (img) {
                    while (1) {
                        next_tr = cur_tr.next();
                        if (next_tr.attr('level') <= level || next_tr.length == 0) {
                            last_tr = next_tr;
                            break;
                        } else {
                            list_shift.push(next_tr);
                            cur_tr = next_tr;
                        }
                   }
                }
                else {
                    last_tr = cur_tr.next();
                }
                if (last_tr.length != 0 && last_tr.attr('level') == level) {
                    var last_tr_id = (last_tr.attr('id')).split('-')[1];
                    img = last_tr.find("img[id='parentimg-" + last_tr_id + "']").attr('src');
                    if (img) {
                        this.edit_xml_dialog.$element.find("img[id='parentimg-" + last_tr_id + "']").attr('src', '/web/static/src/img/expand.gif');
                        while (1) {
                            var next_tr = last_tr.next();
                            if (next_tr.attr('level') <= level || next_tr.length == 0) break;
                            next_tr.hide();
                            last_tr = next_tr;
                        }
                    }
                    list_shift.reverse();
                    _.each(list_shift, function(rec) {
                       $(last_tr).after(rec);
                    });
                }
                break;
            }
        });
    },
    on_expand: function(expand_img){
        var level = parseInt($(expand_img).closest("tr[id^='viewedit-']").attr('level'));
        var cur_tr = $(expand_img).closest("tr[id^='viewedit-']");
        while (1) {
            var nxt_tr = cur_tr.next();
            if (parseInt(nxt_tr.attr('level')) > level){
                cur_tr = nxt_tr;
                nxt_tr.hide();
            } else return nxt_tr;
        }
    },
    on_collapse: function(collapse_img, parent_child_id, id, main_object) {
        var self = this;
        var id = collapse_img.id.split('-')[1];
        var datas = _.detect(parent_child_id,function(res) {
            return res.key == id;
        });
        _.each(datas.value, function(rec) {
            var tr = self.edit_xml_dialog.$element.find("tr[id='viewedit-"+rec+"']");
            tr.find("img[id='parentimg-"+rec+"']").attr('src','/web/static/src/img/expand.gif');
            tr.show();
        });
    }
});
};<commit_msg>[FIX] vieweditor:- used close method instead of manually destory.<commit_after>openerp.web.view_editor = function(openerp) {
var QWeb = openerp.web.qweb;
openerp.web.ViewEditor =   openerp.web.Widget.extend({
    init: function(parent, element_id, dataset, view, options) {
        this._super(parent);
        this.element_id = element_id
        this.parent = parent
        this.dataset = dataset;
        this.model = dataset.model;
        this.xml_id = 0;
    },
    start: function() {
        this.View_editor();
    },
    View_editor : function() {
        var self = this;
        var action = {
            name:'ViewEditor',
            context:this.session.user_context,
            domain: [["model", "=", this.dataset.model]],
            res_model : 'ir.ui.view',
            views : [[false, 'list']],
            type: 'ir.actions.act_window',
            target: "current",
            limit : 80,
            auto_search : true,
            flags: {
                sidebar: false,
                views_switcher: false,
                action_buttons:false,
                search_view:false,
                pager:false,
                radio:true
            },
        };
        var action_manager = new openerp.web.ActionManager(this);
        this.view_edit_dialog = new openerp.web.Dialog(this,{
            modal: true,
            title: 'ViewEditor',
            width: 750,
            height: 500,
            buttons: {
            "Create": function(){
                //to do
            },
            "Edit": function(){
                self.xml_id = 0 ;
                self.get_data();
            },
            "Close": function(){
                this.view_edit_dialog.close();
            }
        },
        });
        this.view_edit_dialog.start();
        this.view_edit_dialog.open();
        action_manager.appendTo(this.view_edit_dialog);
        action_manager.do_action(action);
    },
    check_attr: function(xml, tag, level) {
        var obj = new Object();
        obj.child_id = [];
        obj.id = this.xml_id++;
        obj.level = level+1;
        var render_name = "<" + tag;
        obj.att_list = [];
        obj.att_list.push(tag);
        $(xml).each(function() {
            _.each(this.attributes, function(attrs){
                if (tag != 'button') {
                    if (attrs.nodeName == "string" || attrs.nodeName == "name" || attrs.nodeName == "index") {
                        render_name += ' ' + attrs.nodeName + '=' + '"' + attrs.nodeValue + '"' ;
                    }
                } else if (attrs.nodeName == "name") {
                    render_name += ' ' + attrs.nodeName + '=' + '"' + attrs.nodeValue + '"';
                }
                if (attrs.nodeName != "position") {
                    obj.att_list.push( [attrs.nodeName,attrs.nodeValue] );
                }
            });
            render_name+= ">";
        });
        obj.name = render_name;
        return obj;
    },
    save_object: function(val, parent_list, child_obj_list) {
        var self = this;
        var check_id = parent_list[0];
        var p_list = parent_list.slice(1);
        if (val.child_id.length != 0) {
            _.each(val.child_id, function(val, key) {
                if (val.id==check_id) {
                    if (p_list.length!=0) {
                        self.save_object(val, p_list, child_obj_list);
                    } else {
                        val.child_id = child_obj_list;
                        return false;
                    }
                }
            });
        } else {
            val.child_id = child_obj_list;
        }
    },
    xml_node_create: function(xml, root, parent_list, parent_id, main_object){
        var self = this;
        var child_obj_list = [];
        var children_list = $(xml).filter(root).children();
        var parents = $(children_list[0]).parents().get();
        _.each(children_list, function (child_node) {
            child_obj_list.push(self.check_attr(child_node,child_node.tagName.toLowerCase(),parents.length));
        });
        if (children_list.length != 0) {
            if (parents.length <= parent_list.length) {
                parent_list.splice(parents.length - 1);
            }
            parent_list.push(parent_id);
            self.save_object(main_object[0], parent_list.slice(1), child_obj_list);
        }
        for (var i=0; i<children_list.length; i++) {
            self.xml_node_create
            (children_list[i], children_list[i].tagName.toLowerCase(),
                parent_list, child_obj_list[i].id, main_object);
        }
        return main_object;
    },
    parse_xml: function(arch, view_id) {
        var root = $(arch).filter(":first")[0];
        var tag = root.tagName.toLowerCase();
        var obj ={'child_id':[],'id':this.xml_id++,'level':0,'att_list':[],'name':"<view view_id='"+view_id+"'>"};
        var root_object = this.check_attr(root,tag,0);
        obj.child_id = this.xml_node_create(arch, tag, [], this.xml_id-1, [root_object], [])
        return [obj];
    },
    get_data: function() {
        var self = this;
        var view_id =((this.view_edit_dialog.$element.find("input[name='radiogroup']:checked").parent()).parent()).attr('data-id');
        var ve_dataset = new openerp.web.DataSet(this, 'ir.ui.view');
        ve_dataset.read_ids([parseInt(view_id)], ['arch'], function (arch) {
            one_object = self.parse_xml(arch[0].arch,view_id);
            one_object.arch = arch[0].arch;
            dataset = new openerp.web.DataSetSearch(self, 'ir.ui.view', null, null);
            dataset.read_slice([], {domain : [['inherit_id','=', parseInt(view_id)]]}, function (result) {
                _.each(result, function(res) {
                    self.inherit_view(one_object, res);
                });
                return self.edit_view({"main_object": one_object,
                         "parent_child_id": self.parent_child_list(one_object, [])});
            });
        });
    },
    parent_child_list : function(one_object, p_list) {
        var self = this;
        _.each(one_object , function(element){
            if(element.child_id.length != 0){
                p_list.push({"key":element.id,"value":_.pluck(element.child_id, 'id')});
                self.parent_child_list(element.child_id, p_list);
            }
        });
        return p_list;
    },
    inherit_view : function(one_object, result) {
        var self = this;
        var root = $(result.arch).filter('*');
        var xml_list = [];
        if (root[0].tagName.toLowerCase() == "data") {
            xml_list = $(root[0]).children();
        } else {
            xml_list.push(root[0]);
        }
        _.each(xml_list , function(xml){
            var parent_id;
            var check_list = [];
            var xpath_object = self.parse_xml(xml,result.id);
            if (xml.tagName.toLowerCase() == "xpath" ) {
                var part_expr = _.without($(xml).attr('expr').split("/"),"");
                _.each(part_expr,function(part){
                    check_list.push(_.without($.trim(part.replace(/[^a-zA-Z 0-9 _]+/g,'!')).split("!"),""));
                });
            } else {
                    check_list = [_.flatten(xpath_object[0].child_id[0].att_list)];
            }
            self.full_path_search(check_list ,one_object ,xpath_object);
        });
    },
    full_path_search: function(check_list ,val ,xpath_object) {
        var self = this;
        if(xpath_object.length!=0){
            var check = check_list[0];
            var obj;
            switch (check.length) {
                case 2:
                    if(parseInt(check[1])){
                        var list_1 = _.select(val,function(element){
                            var main_list = _.flatten(element.att_list);
                            return _.include(main_list, check[0]);
                        });
                        obj = val[_.indexOf(val,list_1[parseInt(check[1])-1])];
                    } else {
                        obj = _.detect(val, function(element){
                            var main_list = _.flatten(element.att_list);
                            return _.include(main_list, check[0]);
                        });
                    }
                    break;
                case 3:
                    obj = _.detect(val,function(element){
                        var main_list = _.flatten(element.att_list);
                        check = _.uniq(check);
                        var insert = _.intersection(main_list,check);
                        if(insert.length == check.length ){return element;}
                    });
                    break;
                case 1:
                    var list_1 = _.select(val,function(element){
                        var main_list = _.flatten(element.att_list);
                        return _.include(main_list, check[0]);
                    });
                    if(list_1 != 0){
                        (check_list.length == 1)? obj = list_1[0] : check_list.shift();
                    }
                    break;
            }
            if(obj) {
                check_list.shift();
                if (check_list.length !=0){
                    self.full_path_search(check_list ,obj.child_id ,xpath_object);
                } else {
                    var level = obj.level+1;
                    self.increase_level(xpath_object[0], level)
                    obj.child_id.push(xpath_object[0]);
                    xpath_object.pop();
                    return;
                }
            }
            else {
                _.each(val,function(element){
                    self.full_path_search(check_list ,element.child_id ,xpath_object);
                });
            }
        }
    },
    increase_level: function(val, level) {
        var self = this;
        val.level = level;
        _.each(val.child_id, function(val, key) {
            self.increase_level(val, level + 1);
        });
    },
    edit_view: function(one_object) {
        var self = this;
        this.edit_xml_dialog = new openerp.web.Dialog(this,{
            modal: true,
            title: 'Edit Xml',
            width: 750,
            height: 500,
            buttons: {
                "Inherited View": function(){
                    //todo
                },
                "Preview": function(){
                    //todo
                },
                "Close": function(){
                    this.edit_xml_dialog.close();
                }
            }
        });
        this.edit_xml_dialog.start().open();
        this.edit_xml_dialog.$element.html(QWeb.render('view_editor', {
            'data': one_object['main_object'],
        }));
        this.edit_xml_dialog.$element.find("tr[id^='viewedit-']").click(function() {
            $("tr[id^='viewedit-']").removeClass('ui-selected');
            $(this).addClass('ui-selected');
        });
        this.edit_xml_dialog.$element.find("img[id^='parentimg-']").click(function() {
            if ($(this).attr('src') == '/web/static/src/img/collapse.gif') {
                $(this).attr('src', '/web/static/src/img/expand.gif');
                self.on_expand(this);
            } else {
                $(this).attr('src', '/web/static/src/img/collapse.gif');
                var id = this.id.split('-')[1];
                self.on_collapse(this,one_object['parent_child_id'], one_object['main_object']);
            }
        });
        this.edit_xml_dialog.$element.find("img[id^='side-']").click(function() {
            var side = $(this).closest("tr[id^='viewedit-']")
            var id_tr = (side.attr('id')).split('-')[1];
            var img = side.find("img[id='parentimg-"+id_tr+"']").attr('src'); ;
            var level = side.attr('level');
            var list_shift =[];
            var last_tr;
            var cur_tr = side;
            list_shift.push(side);
            var next_tr;
            switch (this.id) {
                case "side-add":
                    break;
                case "side-remove":
                    break;
                case "side-edit":
                    break;
                case "side-up":
                    while (1) {
                        var prev_tr = cur_tr.prev();
                        if(level >= prev_tr.attr('level') || prev_tr.length == 0) {
                           last_tr = prev_tr;
                           break;
                        }
                        cur_tr = prev_tr;
                    }
                    if (img) {
                        while (1) {
                            next_tr = side.next();
                            if (next_tr.attr('level') <= level || next_tr.length == 0) {
                                break;
                            } else {
                                list_shift.push(next_tr);
                                side = next_tr;
                            }
                        }
                    }
                    if (last_tr.length != 0 && last_tr.attr('level') == level) {
                        _.each(list_shift, function(rec) {
                             $(last_tr).before(rec);
                        });
                    }
                break;
            case "side-down":
                if (img) {
                    while (1) {
                        next_tr = cur_tr.next();
                        if (next_tr.attr('level') <= level || next_tr.length == 0) {
                            last_tr = next_tr;
                            break;
                        } else {
                            list_shift.push(next_tr);
                            cur_tr = next_tr;
                        }
                   }
                }
                else {
                    last_tr = cur_tr.next();
                }
                if (last_tr.length != 0 && last_tr.attr('level') == level) {
                    var last_tr_id = (last_tr.attr('id')).split('-')[1];
                    img = last_tr.find("img[id='parentimg-" + last_tr_id + "']").attr('src');
                    if (img) {
                        this.edit_xml_dialog.$element.find("img[id='parentimg-" + last_tr_id + "']").attr('src', '/web/static/src/img/expand.gif');
                        while (1) {
                            var next_tr = last_tr.next();
                            if (next_tr.attr('level') <= level || next_tr.length == 0) break;
                            next_tr.hide();
                            last_tr = next_tr;
                        }
                    }
                    list_shift.reverse();
                    _.each(list_shift, function(rec) {
                       $(last_tr).after(rec);
                    });
                }
                break;
            }
        });
    },
    on_expand: function(expand_img){
        var level = parseInt($(expand_img).closest("tr[id^='viewedit-']").attr('level'));
        var cur_tr = $(expand_img).closest("tr[id^='viewedit-']");
        while (1) {
            var nxt_tr = cur_tr.next();
            if (parseInt(nxt_tr.attr('level')) > level){
                cur_tr = nxt_tr;
                nxt_tr.hide();
            } else return nxt_tr;
        }
    },
    on_collapse: function(collapse_img, parent_child_id, id, main_object) {
        var self = this;
        var id = collapse_img.id.split('-')[1];
        var datas = _.detect(parent_child_id,function(res) {
            return res.key == id;
        });
        _.each(datas.value, function(rec) {
            var tr = self.edit_xml_dialog.$element.find("tr[id='viewedit-"+rec+"']");
            tr.find("img[id='parentimg-"+rec+"']").attr('src','/web/static/src/img/expand.gif');
            tr.show();
        });
    }
});
};<|endoftext|>


<commit_before>var textdatabase = [];
var hashtable = {};
var freqlist = {};
var aggression = 5;

var hashtableLoaded = false;
var freqlistLoaded = false;

var xhr = new XMLHttpRequest();
xhr.open('GET', chrome.extension.getURL('mthesaur.txt'), true);
xhr.onreadystatechange = function()
{
	if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200)
	{
		var temptextdatabase = xhr.responseText.split("\n");

        for(var i = 0; i < temptextdatabase.length; i++) {
        	var line = temptextdatabase[i].split(",");

        	textdatabase.push(line);

        	for(var j = 0; j < line.length; j++) {
        		if(line[j].length > aggression) {
        			for(var k = 0; k < line.length; k++) {
        				if(line[k].length <= aggression && line[k].length > 0) {
        					hashtable[line[j]] = line[k];
        					break;
        				}
        			}
        		}
        	}
        }
        hashtableLoaded = true;
        walk(document.body);
    }
};
xhr.send();

var xhr = new XMLHttpRequest();
xhr.open('GET', chrome.extension.getURL('word_freq.txt'), true);
xhr.onreadystatechange = function()
{
	if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200)
	{
		var tempfreqlist = xhr.responseText.split("\n");
		for(var i = 0 ; i < tempfreqlist.length; i++){
			freqlist[tempfreqlist[i]] = i;
		}
		freqlistLoaded = true;
		walk(document.body);
	}
};
xhr.send();

function trim (str) {
	return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}

function getSynonyms(word) {
	if(typeof word === 'undefined')
		return [word];

	word = word.toLowerCase();

	if(hashtable.hasOwnProperty(word))
		return [hashtable[word]];

	return [word];
}

function walk(node) {
	if(freqlistLoaded && hashtableLoaded) {
		var ent = document.createTreeWalker(
			node, NodeFilter.SHOW_TEXT, null, false);

		while(ent.nextNode()) {
			var current = ent.currentNode;
			current.textContent = process(current.textContent);
		}
		document.body.addEventListener('DOMNodeInserted', function(event) {
			walk(event.target);});
	}
}

function process(text){

	var processedText = text;
	var words = text.split(" ");

	for(var i = 0; i < words.length; i++) {
		var word = words[i];

		if(typeof word != 'undefined' && word.length > aggression) {

			var synonyms = getSynonyms(word);

			if(typeof synonyms != 'undefined') {
				for(var j = 0; j < synonyms.length; j++){
					if(synonyms[j].length <= aggression) {
						processedText = processedText.replace(word, synonyms[j]);
						break;
					}
				}
			}
		}
	}
	return processedText;
}<commit_msg>Added some framework for common word search, needs algorithm<commit_after>var textdatabase = [];
var hashtable = {};
var freqlist = {};
var aggression = 5;

var hashtableLoaded = false;
var freqlistLoaded = false;

var xhr = new XMLHttpRequest();
xhr.open('GET', chrome.extension.getURL('mthesaur.txt'), true);
xhr.onreadystatechange = function()
{
	if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200)
	{
		var temptextdatabase = xhr.responseText.split("\n");

        for(var i = 0; i < temptextdatabase.length; i++) {
        	var line = temptextdatabase[i].split(",");

        	textdatabase.push(line);

        	for(var j = 0; j < line.length; j++) {
        		if(line[j].length > aggression) {
        			for(var k = 0; k < line.length; k++) {
        				if(line[k].length <= aggression && line[k].length > 0) {
        					hashtable[line[j]] = line[k];
        					break;
        				}
        			}
        		}
        	}
        }
        hashtableLoaded = true;
        walk(document.body);
    }
};
xhr.send();

var xhr = new XMLHttpRequest();
xhr.open('GET', chrome.extension.getURL('word_freq.txt'), true);
xhr.onreadystatechange = function()
{
	if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200)
	{
		var tempfreqlist = xhr.responseText.split("\n");
		for(var i = 0 ; i < tempfreqlist.length; i++){
			freqlist[tempfreqlist[i]] = i;
		}
		freqlistLoaded = true;
		walk(document.body);
	}
};
xhr.send();

function getCommoner(word) {
	if(typeof word === 'undefined')
		return [word];
	word = trim(word.toLowerCase(););
	if(!hashtable.hasOwnProperty(word)) {
		//replace with common word
	}
	else
		return [word];
}

function trim (str) {
	return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}

function getSynonyms(word) {
	if(typeof word === 'undefined')
		return [word];

	word = trim(word.toLowerCase());

	if(hashtable.hasOwnProperty(word))
		return [hashtable[word]];

	return [word];
}

function walk(node) {
	if(freqlistLoaded && hashtableLoaded) {
		var ent = document.createTreeWalker(
			node, NodeFilter.SHOW_TEXT, null, false);

		while(ent.nextNode()) {
			var current = ent.currentNode;
			current.textContent = process(current.textContent);
		}
		document.body.addEventListener('DOMNodeInserted', function(event) {
			walk(event.target);});
	}
}

function process(text){

	var processedText = text;
	var words = text.split(" ");

	for(var i = 0; i < words.length; i++) {
		var word = words[i];

		if(typeof word != 'undefined' && word.length > aggression) {

			var synonyms = getSynonyms(word);

			if(typeof synonyms != 'undefined') {
				for(var j = 0; j < synonyms.length; j++){
					if(synonyms[j].length <= aggression) {
						processedText = processedText.replace(word, synonyms[j]);
						break;
					}
				}
			}
		}
	}
	return processedText;
}<|endoftext|>