<commit_before>var express  = require('express'),
    request = require('request'),
    cheerio = require('cheerio'),
    mustacheExpress = require('mustache-express'),
    bodyParser = require('body-parser'),
    app      = express(),
    radiodanClient = require('radiodan-client'),
    radiodan = radiodanClient.create(),
    player   = radiodan.player.get('main'),
    eventBus       = require('./lib/event-bus').create(),
    fs = require('fs'),
    path = require('path'),
    exec = require('child_process').exec,
    eventSource = require('express-eventsource'),
    port     = process.env.PORT || 5000;

app.engine('mustache', mustacheExpress());
app.set('view engine', 'mustache');
app.set('views', __dirname + '/static');

app.use(bodyParser.urlencoded({ extended: true }));

app.use('/radiodan', radiodanClient.middleware({crossOrigin: true}));

//stuff
bindToEventBus(player,eventBus);

var playlist = readConfig('config/playlist.json');
var config = readConfig('config/config.json');
var currentFeedUrl = null;

console.log("playlist is");
console.log(playlist);
console.log("config is");
console.log(config);

// server

// get rss shows the current url, if any
// and allows you to set it using a POST

app.get('/rss', function (req, res) {
  res.render('config', {});
// { feedUrl: config.feedUrl });
});

app.post('/rss', function (req, res) {
  if (req.body && req.body.feedUrl) {
     addFeedURL(req.body.feedUrl, req,res);
  }

  res.redirect('/');
});

// rssFromNFC allows a post (e.g from NFC) to set the RSS feed url
app.post('/rssFromNFC', function (req, res) {
  stopPlaying();
  if (req.body && req.body.feedUrl) {

     var powerLED      = radiodan.RGBLED.get('power');
     powerLED.emit({
      emit: true,
      colour: [100,100,0],
     });
     addFeedURL(req.body.feedUrl);
  }

  res.redirect('/');
});

// stop playing (e.g. from NFC trigger)

app.post('/stopFromNFC', function (req, res) {
  var st = player;
  console.log("status %j", st);
  stopPlaying();
  res.redirect('/');
});

// "write" a card
// actually just adds a card id and url to a list
// screen 1: ask people to put the card in the box

app.get('/write', function (req, res) {
  res.render('write');
});

// screen 2: test the card for suitability and feed back information about it

app.get('/write2', function (req, res) {

  var msg = "";
  //load the file
  var fullPath = __dirname;
  var fullFile = path.join(fullPath,"config/uid.json");
  if ( fs.existsSync(fullFile) ) {
    var data = require(fullFile);
    if(data){
      var feedUrl = data["feedUrl"] | "";
      var uid = data["uid"] | "";
      if(uid == ""){
        msg = "No card available to read";
      }else if (feedUrl==""){
        msg = "Card "+uid+" ready to associate with a feed"
      }else if (feedUrl!=""){
        msg = "Card "+uid+" already exists in the database - currently linked to "+feedUrl+" - proceeding will link it to another feed";
      }else{
        msg = "Something went wrong";
      }
    }else{
       msg = "No data found in "+fullFile;
    }
  }else{
    msg = "No uid.json file found at "+fullFile;
  }
  res.render('write2', { feedUrl: req.body.feedUrl, msg: msg });

});

// screen 3: check teh feed has enclosures

app.post('/write3', function (req, res) {
    request(req.body.feedUrl,function(err, data){
      var urlOk = "Contains audio links";
      if (err) {
        console.error('Error fetching feed');
        console.error(err.stack);
        urlOk = "problem with the feed url - check it doesn't have a typo - "+req.body.feedUrl;
        res.render('write3err', { feedUrl: req.body.feedUrl, urlOk: urlOk });
      }else{

        var doc = cheerio(data.body);
        var urls = doc.find('enclosure')
                .map(extractUrlFromEnclosure)
                .get();

        if(urls!=null && urls.length>0){
           urlOk = "Found "+urls.length+" audio files in the RSS feed - all ok";
           res.render('write3', { feedUrl: req.body.feedUrl, urlOk: urlOk });
        }else{
          urlOk = "No playable audio files found in the RSS feed, though it does exist";
          res.render('write3err', { feedUrl: req.body.feedUrl, urlOk: urlOk });
        }
      }
    });
});

//write4: write the ID to the database and display results

app.post('/write4', function (req, res) {

  var feedUrl = req.body.feedUrl;

  // read the data file
  var fullPath = __dirname;
  var fullDataFile = path.join(fullPath,"config/data.json");
  var fullUidFile = path.join(fullPath,"config/uid.json");
  var uid_data = null;
  var data = null;
  var msg = "";

  if ( fs.existsSync(fullUidFile) ) {
    uid_data = require(fullUidFile);
  }else{
    console.log("no uid");
    msg = "can't complete - no uid found";
  }

  if ( fs.existsSync(fullDataFile) ) {
    data = require(fullDataFile);
  }else{
    msg = "no data file found - continuing";
    data = {};
  }
  if(uid_data && data){
   var uid = uid_data["uid"];
   if(data[uid]){
     msg = "Replaced "+data[uid]+" for "+uid+" with "+feedUrl;
   }else{
     msg = "New id "+uid+" contains "+feedUrl;
   }
   data[uid] = feedUrl;
   var j = JSON.stringify(data, null, 4)
   fs.writeFile(fullDataFile, j, function (err3) {
        if (err3) throw err3;
        console.log("saved");
   });

   addFeedURL(feedUrl);
  }else{
   console.log("all went wrong somewhere");
  }
  res.render('write4', { feedUrl: feedUrl, cardId: uid, msg: msg });

});

app.listen(port);
listenToEvents();

showPowerLed();

var powerButton = radiodan.button.get("power");
powerButton.on("press", stopPlaying);
powerButton.on("release", startPlaying);

//console.log('Reading feedUrl', config.feedUrl);
//request(config.feedUrl,getRSSAndAddToPlaylist);

process.on('SIGTERM', gracefulExit);
process.on('SIGINT' , gracefulExit);

app.use(express.static(__dirname + '/static'));

console.log('Listening on port '+port);

///various handy methods

function showPowerLed(){
   var powerLED      = radiodan.RGBLED.get('power');
   powerLED.emit({
     emit: true,
     colour: [0,0,200],
   });
}

function addFeedURL(feedUrl){
  var exists = config[feedUrl];
  currentFeedUrl = feedUrl;
  if(exists){
    console.log("found feed");
    var toPlay = exists["lastPlayed"];
    var toSeekTo = exists["toSeekTo"];

    player.add({
      playlist: [toPlay],
      clear: true
    }).then(player.play()).then(player.seek({"time":toSeekTo})).then(getAndFilterRSS(feedUrl,toPlay));

  }else{
    console.log("feed doesn't exist - starting afresh");
    config[feedUrl] = {};
    writeConfig('config/config.json', config);
    request(feedUrl,getRSSAndAddToPlaylist);
  }

/*
  config.feedUrl = feedUrl;
  config = readConfig('config/config.json',null);
  console.log("new config");
  console.log(config);
*/
}

function extractUrlFromEnclosure(index, item) {
  return cheerio(item).attr('url');
}

function startPlaying(){
  console.log("powerButton PRESSED");
  player.play();
}

function stopPlaying() {
  console.log("powerButton RELEASED");
  player.pause({ value: true });
}

function getAndFilterRSS(feedUrl,toPlay){
  // remove the one we are already listening to
  // not sure about the ordering here
  request(feedUrl,function(err, data){

    var powerLED      = radiodan.RGBLED.get('power');

    var doc = cheerio(data.body);
    var urls = doc.find('enclosure')
                .map(extractUrlFromEnclosure)
                .get();
    var new_urls = [];
    console.log(urls);
    for(var x in urls){
       if(toPlay!=urls[x]){
         new_urls.push(urls[x]);
       }
    }
    player.add({
      playlist: new_urls,
      clear: false
    }).then(
       powerLED.emit({
        emit: true,
        colour: [0,0,100],
       })
  );

  });
}

function getRSSAndAddToPlaylist(err, data) {
  if (err) {
    console.error('Error fetching feed');
    console.error(err.stack);
    return;
  }

  var powerLED      = radiodan.RGBLED.get('power');

  var doc = cheerio(data.body);
  var urls = doc.find('enclosure')
                .map(extractUrlFromEnclosure)
                .get();
  player.add({
    playlist: urls,
    clear: true
  }).then(startPlaying()).then(
     powerLED.emit({
      emit: true,
      colour: [0,0,100],
     })
  );
}

function gracefulExit() {
  console.log('Exiting...');
  player.clear().then(process.exit);
}

function readConfig(file) {
  console.log("path is "+file);
  console.log("fs exists "+fs.existsSync(file)+" process "+process.env.HOME);
  var fullPath = __dirname;
  var fullFile = path.join(fullPath,file);
  console.log(fs.existsSync(fullFile));
  if ( fs.existsSync(fullFile) ) {
    try{
      return require(fullFile);
    }catch(e){
      console.log("problem "+e);
      return {};
    }
  }else{
    console.log("No config file");
    return {};
  }
}

function writeConfig(file, config) {

  var fullPath = __dirname;
  var fullFile = path.join(fullPath,file);
  console.log("writing config path "+file+" config "+JSON.stringify(config));
  try{
    fs.writeFileSync(file, JSON.stringify(config));
  }catch(e){
    console.log("problem writing to file "+e);
  }
}

function listenToEvents(){
  var eventStream = eventSource();

  var eventBus = new EventEmitter({ wildcard: true });

  ['*'].forEach(function (topic) {
    eventBus.on(topic, function (args) {
      console.log("!!t!!! "+topic);
      console.log("!!a!!! "+args);
    });
  });

}

function bindToEventBus(player, eventBus){

      player.on('player', function(playerData) {
        var msg = {
          playerId: player.id,
          player: playerData
        };

        eventBus.emit('player', msg);
      });

      player.on('playlist', function(playlistData) {
        var msg = {
          playerId: player.id,
          playlist: playlistData
        };

        eventBus.emit('playlist', msg);
      });

      var pl = null;

      ['*'].forEach(function (topic) {
        eventBus.on(topic, function (args) {
           if(args["playlist"] && args["playlist"].length>0){
             pl = args["playlist"][0];
             if(pl && pl.length > 0){
                writeConfig('config/playlist.json', playlist);
             }
           }
           if(args["player"]){
             var ply = args["player"];
             console.log(ply);
             var sid = ply["songid"];
             var elapsed = ply["elapsed"];
             var file = pl["file"];
             console.log("player "+file+" elapsed "+elapsed);
             if(file && elapsed){

               config[currentFeedUrl]["lastPlayed"]=file;
               config[currentFeedUrl]["toSeekTo"]=elapsed;
               console.log("saving config");
               writeConfig('config/config.json', config);
             }

           }

 //          console.log("!!!!!! topic  "+topic);
   //       console.log("!!!!!!args %j ",args);
        });
      });

}
<commit_msg>Fix a bug with saving the config file<commit_after>var express  = require('express'),
    request = require('request'),
    cheerio = require('cheerio'),
    mustacheExpress = require('mustache-express'),
    bodyParser = require('body-parser'),
    app      = express(),
    radiodanClient = require('radiodan-client'),
    radiodan = radiodanClient.create(),
    player   = radiodan.player.get('main'),
    eventBus       = require('./lib/event-bus').create(),
    fs = require('fs'),
    path = require('path'),
    exec = require('child_process').exec,
    eventSource = require('express-eventsource'),
    port     = process.env.PORT || 5000;

app.engine('mustache', mustacheExpress());
app.set('view engine', 'mustache');
app.set('views', __dirname + '/static');

app.use(bodyParser.urlencoded({ extended: true }));

app.use('/radiodan', radiodanClient.middleware({crossOrigin: true}));

//stuff
bindToEventBus(player,eventBus);

var playlist = readConfig('config/playlist.json');
var config = readConfig('config/config.json');
var currentFeedUrl = null;

console.log("playlist is");
console.log(playlist);
console.log("config is");
console.log(config);

// server

// get rss shows the current url, if any
// and allows you to set it using a POST

app.get('/rss', function (req, res) {
  res.render('config', {});
// { feedUrl: config.feedUrl });
});

app.post('/rss', function (req, res) {
  if (req.body && req.body.feedUrl) {
     addFeedURL(req.body.feedUrl, req,res);
  }

  res.redirect('/');
});

// rssFromNFC allows a post (e.g from NFC) to set the RSS feed url
app.post('/rssFromNFC', function (req, res) {
  stopPlaying();
  if (req.body && req.body.feedUrl) {

     var powerLED      = radiodan.RGBLED.get('power');
     powerLED.emit({
      emit: true,
      colour: [100,100,0],
     });
     addFeedURL(req.body.feedUrl);
  }

  res.redirect('/');
});

// stop playing (e.g. from NFC trigger)

app.post('/stopFromNFC', function (req, res) {
  var st = player;
  console.log("status %j", st);
  stopPlaying();
  res.redirect('/');
});

// "write" a card
// actually just adds a card id and url to a list
// screen 1: ask people to put the card in the box

app.get('/write', function (req, res) {
  res.render('write');
});

// screen 2: test the card for suitability and feed back information about it

app.get('/write2', function (req, res) {

  var msg = "";
  //load the file
  var fullPath = __dirname;
  var fullFile = path.join(fullPath,"config/uid.json");
  if ( fs.existsSync(fullFile) ) {
    var data = require(fullFile);
    if(data){
      var feedUrl = data["feedUrl"] | "";
      var uid = data["uid"] | "";
      if(uid == ""){
        msg = "No card available to read";
      }else if (feedUrl==""){
        msg = "Card "+uid+" ready to associate with a feed"
      }else if (feedUrl!=""){
        msg = "Card "+uid+" already exists in the database - currently linked to "+feedUrl+" - proceeding will link it to another feed";
      }else{
        msg = "Something went wrong";
      }
    }else{
       msg = "No data found in "+fullFile;
    }
  }else{
    msg = "No uid.json file found at "+fullFile;
  }
  res.render('write2', { feedUrl: req.body.feedUrl, msg: msg });

});

// screen 3: check teh feed has enclosures

app.post('/write3', function (req, res) {
    request(req.body.feedUrl,function(err, data){
      var urlOk = "Contains audio links";
      if (err) {
        console.error('Error fetching feed');
        console.error(err.stack);
        urlOk = "problem with the feed url - check it doesn't have a typo - "+req.body.feedUrl;
        res.render('write3err', { feedUrl: req.body.feedUrl, urlOk: urlOk });
      }else{

        var doc = cheerio(data.body);
        var urls = doc.find('enclosure')
                .map(extractUrlFromEnclosure)
                .get();

        if(urls!=null && urls.length>0){
           urlOk = "Found "+urls.length+" audio files in the RSS feed - all ok";
           res.render('write3', { feedUrl: req.body.feedUrl, urlOk: urlOk });
        }else{
          urlOk = "No playable audio files found in the RSS feed, though it does exist";
          res.render('write3err', { feedUrl: req.body.feedUrl, urlOk: urlOk });
        }
      }
    });
});

//write4: write the ID to the database and display results

app.post('/write4', function (req, res) {

  var feedUrl = req.body.feedUrl;

  // read the data file
  var fullPath = __dirname;
  var fullDataFile = path.join(fullPath,"config/data.json");
  var fullUidFile = path.join(fullPath,"config/uid.json");
  var uid_data = null;
  var data = null;
  var msg = "";

  if ( fs.existsSync(fullUidFile) ) {
    uid_data = require(fullUidFile);
  }else{
    console.log("no uid");
    msg = "can't complete - no uid found";
  }

  if ( fs.existsSync(fullDataFile) ) {
    data = require(fullDataFile);
  }else{
    msg = "no data file found - continuing";
    data = {};
  }
  if(uid_data && data){
   var uid = uid_data["uid"];
   if(data[uid]){
     msg = "Replaced "+data[uid]+" for "+uid+" with "+feedUrl;
   }else{
     msg = "New id "+uid+" contains "+feedUrl;
   }
   data[uid] = feedUrl;
   var j = JSON.stringify(data, null, 4)
   fs.writeFile(fullDataFile, j, function (err3) {
        if (err3) throw err3;
        console.log("saved");
   });

   addFeedURL(feedUrl);
  }else{
   console.log("all went wrong somewhere");
  }
  res.render('write4', { feedUrl: feedUrl, cardId: uid, msg: msg });

});

app.listen(port);
listenToEvents();

showPowerLed();

var powerButton = radiodan.button.get("power");
powerButton.on("press", stopPlaying);
powerButton.on("release", startPlaying);

//console.log('Reading feedUrl', config.feedUrl);
//request(config.feedUrl,getRSSAndAddToPlaylist);

process.on('SIGTERM', gracefulExit);
process.on('SIGINT' , gracefulExit);

app.use(express.static(__dirname + '/static'));

console.log('Listening on port '+port);

///various handy methods

function showPowerLed(){
   var powerLED      = radiodan.RGBLED.get('power');
   powerLED.emit({
     emit: true,
     colour: [0,0,200],
   });
}

function addFeedURL(feedUrl){
  var exists = config[feedUrl];
  currentFeedUrl = feedUrl;
  if(exists){
    console.log("found feed");
    var toPlay = exists["lastPlayed"];
    var toSeekTo = exists["toSeekTo"];

    player.add({
      playlist: [toPlay],
      clear: true
    }).then(player.play()).then(player.seek({"time":toSeekTo}));
//////???? libby .then(getAndFilterRSS(feedUrl,toPlay));

  }else{
    console.log("feed doesn't exist - starting afresh");
    config[feedUrl] = {};
    writeConfig('config/config.json', config);
    request(feedUrl,getRSSAndAddToPlaylist);
  }

/*
  config.feedUrl = feedUrl;
  config = readConfig('config/config.json',null);
  console.log("new config");
  console.log(config);
*/
}

function extractUrlFromEnclosure(index, item) {
  return cheerio(item).attr('url');
}

function startPlaying(){
  console.log("powerButton PRESSED");
  player.play();
}

function stopPlaying() {
  console.log("powerButton RELEASED");
  player.pause({ value: true });
}

function getAndFilterRSS(feedUrl,toPlay){
  // remove the one we are already listening to
  // not sure about the ordering here
  request(feedUrl,function(err, data){

    var powerLED      = radiodan.RGBLED.get('power');

    var doc = cheerio(data.body);
    var urls = doc.find('enclosure')
                .map(extractUrlFromEnclosure)
                .get();
    var new_urls = [];
    console.log(urls);
    for(var x in urls){
       if(toPlay!=urls[x]){
         new_urls.push(urls[x]);
       }
    }
    player.add({
      playlist: new_urls,
      clear: false
    }).then(
       powerLED.emit({
        emit: true,
        colour: [0,0,100],
       })
  );

  });
}

function getRSSAndAddToPlaylist(err, data) {
  if (err) {
    console.error('Error fetching feed');
    console.error(err.stack);
    return;
  }

  var powerLED      = radiodan.RGBLED.get('power');

  var doc = cheerio(data.body);
  var urls = doc.find('enclosure')
                .map(extractUrlFromEnclosure)
                .get();
  player.add({
    playlist: urls,
    clear: true
  }).then(startPlaying()).then(
     powerLED.emit({
      emit: true,
      colour: [0,0,100],
     })
  );
}

function gracefulExit() {
  console.log('Exiting...');
  player.clear().then(process.exit);
}

function readConfig(file) {
  console.log("path is "+file);
  console.log("fs exists "+fs.existsSync(file)+" process "+process.env.HOME);
  var fullPath = __dirname;
  var fullFile = path.join(fullPath,file);
  console.log(fs.existsSync(fullFile));
  if ( fs.existsSync(fullFile) ) {
    try{
      return require(fullFile);
    }catch(e){
      console.log("problem "+e);
      return {};
    }
  }else{
    console.log("No config file");
    return {};
  }
}

function writeConfig(file, config) {

  var fullPath = __dirname;
  var fullFile = path.join(fullPath,file);
  console.log("writing config path "+fullFile+" config "+JSON.stringify(config));
  try{
    fs.writeFileSync(fullFile, JSON.stringify(config));
  }catch(e){
    console.log("problem writing to file "+e);
  }
}

function listenToEvents(){
  var eventStream = eventSource();

  var eventBus = new EventEmitter({ wildcard: true });

  ['*'].forEach(function (topic) {
    eventBus.on(topic, function (args) {
      console.log("topic "+topic);
      console.log("args "+args);
    });
  });

}

function bindToEventBus(player, eventBus){

      player.on('player', function(playerData) {
        var msg = {
          playerId: player.id,
          player: playerData
        };

        eventBus.emit('player', msg);
      });

      player.on('playlist', function(playlistData) {
        var msg = {
          playerId: player.id,
          playlist: playlistData
        };

        eventBus.emit('playlist', msg);
      });

      var pl = null;

      ['*'].forEach(function (topic) {
        eventBus.on(topic, function (args) {
           if(args["playlist"] && args["playlist"].length>0){
             pl = args["playlist"][0];
             if(pl && pl.length > 0){
                writeConfig('config/playlist.json', playlist);
             }
           }
           if(args["player"]){
             var ply = args["player"];
             console.log(ply);
             var sid = ply["songid"];
             var elapsed = ply["elapsed"];
             var file = pl["file"];
             console.log("player "+file+" elapsed "+elapsed);
             if(file && elapsed){

               config[currentFeedUrl]["lastPlayed"]=file;
               config[currentFeedUrl]["toSeekTo"]=elapsed;
               console.log("saving config");
               writeConfig('config/config.json', config);
             }

           }

 //          console.log("!!!!!! topic  "+topic);
   //       console.log("!!!!!!args %j ",args);
        });
      });

}
<|endoftext|>


<commit_before>function getParameterByName(name) {
	var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
	return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}

$(function() {
	var conversions = {
		'uppercase': function(s) {
			return s.toUpperCase();
		},
		'lowercase': function(s) {
			return s.toLowerCase();
		},
		'URL encode': function(s) {
			return encodeURIComponent(s);
		},
		'URL decode': function(s) {
			return decodeURIComponent(s);
		},
		'ASCII to binary': ABC.toBinary,
		'binary to ASCII': ABC.toAscii,
	};

	$.each(conversions, function(k, v) {
		$('#conversion').append($(new Option(k, k)));
	});

	$('#conversion').change(function() {
		window.location.hash = '#!' + $(this).val();
		convertIfLive();
	});

	$('#conversion').val(window.location.hash.replace(/^#!/, '') || 'uppercase')

	$('#convert').click(function(e) {
		e.preventDefault();
		convert();
	});

	function convert() {
		var conversion = conversions[$('#conversion').val()];
		var input = $('#input').val();
		try {
			var output = conversion(input);
		}
		catch(e) {
			$('#input').addClass('error');
			return;
		}
		$('#input').removeClass('error');
		$('#output').val(output);
	}

	function convertIfLive() {
		if ($('#live').prop('checked')) {
			convert();
		}
	}

	$('#swap').click(function(e) {
		e.preventDefault();
		var input = $('#input').val();
		var output = $('#output').val();
		$('#input').val(output);
		$('#output').val(input);
		convertIfLive();
	});

	$('#clear').click(function(e) {
		e.preventDefault();
		$('#input').val('');
		$('#output').val('');
	});

	$('#input').on('input', function() {
		convertIfLive();
	});
});

// ABC - a generic, native JS (A)scii(B)inary(C)onverter.
// (c) 2013 Stephan Schmitz <eyecatchup@gmail.com>
// License: MIT, http://eyecatchup.mit-license.org
// URL: https://gist.github.com/eyecatchup/6742657
var ABC = {
  toAscii: function(bin) {
    return bin.replace(/\s*[01]{8}\s*/g, function(bin) {
      return String.fromCharCode(parseInt(bin, 2))
    })
  },
  toBinary: function(str, spaceSeparatedOctets) {
    return str.replace(/[\s\S]/g, function(str) {
      str = ABC.zeroPad(str.charCodeAt().toString(2));
      return !1 == spaceSeparatedOctets ? str : str + " "
    })
  },
  zeroPad: function(num) {
    return "00000000".slice(String(num).length) + num
  }
};
<commit_msg>add ROT-13<commit_after>function getParameterByName(name) {
	var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
	return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}

$(function() {
	var conversions = {
		'uppercase': function(s) {
			return s.toUpperCase();
		},
		'lowercase': function(s) {
			return s.toLowerCase();
		},
		'URL encode': function(s) {
			return encodeURIComponent(s);
		},
		'URL decode': function(s) {
			return decodeURIComponent(s);
		},
		'ASCII to binary': ABC.toBinary,
		'binary to ASCII': ABC.toAscii,
		'ROT-13': function(s) {
			// from http://stackoverflow.com/a/28490254/179805 by Stephen Quan
			return s.replace(/[A-Za-z]/g, function (c) {
				return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
					.charAt("NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm".indexOf(c));
			});
		},
	};

	$.each(conversions, function(k, v) {
		$('#conversion').append($(new Option(k, k)));
	});

	$('#conversion').change(function() {
		window.location.hash = '#!' + $(this).val();
		convertIfLive();
	});

	$('#conversion').val(window.location.hash.replace(/^#!/, '') || 'uppercase')

	$('#convert').click(function(e) {
		e.preventDefault();
		convert();
	});

	function convert() {
		var conversion = conversions[$('#conversion').val()];
		var input = $('#input').val();
		try {
			var output = conversion(input);
		}
		catch(e) {
			$('#input').addClass('error');
			return;
		}
		$('#input').removeClass('error');
		$('#output').val(output);
	}

	function convertIfLive() {
		if ($('#live').prop('checked')) {
			convert();
		}
	}

	$('#swap').click(function(e) {
		e.preventDefault();
		var input = $('#input').val();
		var output = $('#output').val();
		$('#input').val(output);
		$('#output').val(input);
		convertIfLive();
	});

	$('#clear').click(function(e) {
		e.preventDefault();
		$('#input').val('');
		$('#output').val('');
	});

	$('#input').on('input', function() {
		convertIfLive();
	});
});

// ABC - a generic, native JS (A)scii(B)inary(C)onverter.
// (c) 2013 Stephan Schmitz <eyecatchup@gmail.com>
// License: MIT, http://eyecatchup.mit-license.org
// URL: https://gist.github.com/eyecatchup/6742657
var ABC = {
  toAscii: function(bin) {
    return bin.replace(/\s*[01]{8}\s*/g, function(bin) {
      return String.fromCharCode(parseInt(bin, 2))
    })
  },
  toBinary: function(str, spaceSeparatedOctets) {
    return str.replace(/[\s\S]/g, function(str) {
      str = ABC.zeroPad(str.charCodeAt().toString(2));
      return !1 == spaceSeparatedOctets ? str : str + " "
    })
  },
  zeroPad: function(num) {
    return "00000000".slice(String(num).length) + num
  }
};
<|endoftext|>


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

/** Brackets Extension to load line navigator CodeMirror addon */
define(["require", "exports", "module"], function (require, exports, module) {
	"use strict";

	var DocumentManager     = brackets.getModule("document/DocumentManager"),
		EditorManager       = brackets.getModule("editor/EditorManager"),
		AppInit             = brackets.getModule("utils/AppInit"),
		FileUtils           = brackets.getModule("file/FileUtils");

	/*
	*
	* Try to load tern via requirejs to avoid having to modify brackets index.html
	*/
	/*
	var ternConfig = window.require.config({
		"baseUrl": require.toUrl("./tern"),
		"map":{
			"*": {
				"acorn": "../acorn/acorn",
				"acorn/acorn_loose": "../acorn/acorn_loose",
				"acorn/util/walk": "../acorn/util/walk"
			}
		},
		"shim":{
			"acorn/acorn_loose": {
				deps:["acorn"]
			},
			"acorn/util/walk": {
				deps:["acorn"]
			},
			"desktop" :{
				deps:["tern"]
			},
			"tern": {
				deps:["infer", "acorn", "condense", "acorn/acorn_loose", "acorn/util/walk"]
			},
			"infer": {
				deps: ["acorn", "acorn/acorn_loose", "acorn/util/walk", "env", "jsdoc"]
			},
			"condense": {
				deps: ["infer"]
			}
		},
		waitTimeout: 30
	});

	ternConfig(["require", "exports", "module", "desktop"], function() {
	});
	*/

	/**
	* tern server, which manager all the processing with an in process
	* service.
	*/
	function ternDocuments (options) {
		var _self = this;
		this.ready = $.Deferred();
		this.docs = [];
		this.onReady = this.ready.promise().done;
	}

	ternDocuments.prototype.query = function( query ) {
		throw "Must implement";
	}

	ternDocuments.prototype.findDocByProperty = function(_propName, data) {
		for (var i = 0; i < this.docs.length; ++i) {
			if (this.docs[i][_propName] == data) {
				return this.docs[i];
			}
		}
	}

	ternDocuments.prototype.findDocByName = function(name) {
		return this.findDocByProperty("name", name);
	}

	ternDocuments.prototype.findDocByInstance = function(doc) {
		return this.findDocByProperty("doc", doc);
	}

	ternDocuments.prototype.registerDoc = function(name, doc) {
		var _self = this;

	  	this.addDoc({name: name,
					 doc: doc,
					 changed: null});

	  	CodeMirror.on(doc, "change", function(){
			_self.trackChange.apply(_self, arguments);
		});
	}

	ternDocuments.prototype.trackChange = function (doc, change) {
		var _doc = this.findDocByInstance(doc);

		var changed = _doc.changed;
		if (changed == null){
			_doc.changed = changed = {
				from: change.from.line, to: change.from.line
			};
		}

		var end = change.from.line + (change.text.length - 1);

		if (change.from.line < changed.to) {
			changed.to = changed.to - (change.to.line - end);
		}

		if (end >= changed.to) {
			changed.to = end + 1;
		}

		if (changed.from > change.from.line) {
			changed.from = change.from.line;
		}
	}

	/**
	*  Interface to operate against a local instance of tern
	*/
	function localDocuments() {
		ternDocuments.apply(this, arguments);
		var _self = this;

		//
		// Load up all the definitions that we will need to start with.
		//
		require(["text!./tern/ecma5.json", "text!./tern/browser.json",
				 "text!./tern/plugin/requirejs/requirejs.json", "text!./tern/jquery.json"],
			function( _ecma5Env, _browserEnv, _requireEnv, _jQueryEnv ) {
				var environment = Array.prototype.slice.call(arguments, 0);
				$.each(environment.slice(0), function(index, item){
					environment[index] = JSON.parse(item);
				});

				_self._server = new tern.Server({
					getFile: function(){
						_self.getFile.apply(_self, arguments);
					},
					environment: environment
				});

				_self.ready.resolve(_self);
		});
	}

	// Create a localDocument server.
	localDocuments.prototype = new ternDocuments;
	localDocuments.prototype.constructor = localDocuments;

	localDocuments.prototype.query = function( query ) {
		var promise = $.Deferred();

		this._server.request( query, function(error, data) {
			if (error) {
				promise.fail(error);
			}
			else {
			  	console.log(data);
				promise.resolve(data);
			}
		});

		return promise.promise();
	}

	localDocuments.prototype.addDoc = function (doc) {
		this.docs.push(doc);
		this._server.addFile(doc.name);
	}

	var httpCache = {};
	localDocuments.prototype.getFile = function (name, c) {
		if (/^https?:\/\//.test(name)) {
			if (httpCache[name]){
			  return c(null, httpCache[name]);
			}

			jQuery.ajax({
				"url": name,
				"contentType": "text"
			})
			.done(function(data, status) {
				httpCache[name] = data;
				c(null, data);
			})
			.fail(function(){
				c(null, "");
			});
		}
		else {
			var doc = this.findDocByName(name);
			return c(null, doc ? doc.doc.getValue() : "");
		}
	}

	/**
	*  Interface to operate against a remote tern server
	*/
	function remoteDocuments() {
		ternDocuments.apply(this, arguments);
		var _self = this;

		setTimeout(function(){
			_self.ready.resolve(_self);
		}, 1);
	}

	remoteDocuments.prototype = new ternDocuments;
	remoteDocuments.prototype.constructor = remoteDocuments;

	remoteDocuments.prototype.ping = function (){
		return jQuery.ajax({
			"url": "http://localhost:56575/ping",
			"type": "GET"
		})
		.promise();
	}

	remoteDocuments.prototype.query = function( query ) {
		return jQuery.ajax({
			"url": "http://localhost:58034",
			"type": "POST",
			contentType: "application/json; charset=utf-8",
			data: JSON.stringify(query)
		})
		.pipe(function(data){
		  	console.log(data);
			return data;
		},
		function(error){
		})
		.promise();
	}

	remoteDocuments.prototype.addDoc = function(doc) {
		this.docs.push(doc);
	}

	/**
	*  Controls the interaction between brackets and tern
	*/
	var ternManager = (function() {
		var onReady = $.Deferred();
		//var docs = new remoteDocuments();
	  	var docs = new localDocuments();
		docs.onReady(onReady.resolve)

		return {
			onReady: onReady.promise().done,
			_docs: docs
		};
	})();

	ternManager.initEditor = function ( ) {
		// Change the current editor in view
		var editor = EditorManager.getCurrentFullEditor();

		// Make sure we have a valid editor
		if (!editor && !editor._codeMirror) {
			return;
		}

		var cm = editor._codeMirror;

		// if already bound, then exit...
		if ( cm._ternBindings ){
			return;
		}

		cm._ternBindings = ternManager;

		var file = editor.document.file;
		var keyMap = {
			"name": "ternBindings",
			"Ctrl-I": ternManager.findType,
			"Ctrl-.": function(cm) {
				CodeMirror.showHint(cm, ternManager.showHint, {async: true});
			},
			"Alt-.": ternManager.jumpToDef,
			"Alt-,": ternManager.jumpBack,
			"Ctrl-R": ternManager.renameVar
		};

		// Register key events
		cm.addKeyMap(keyMap);
		ternManager._docs.registerDoc(file.fullPath, cm.getDoc());
	}

	ternManager.showHint = function(cm, c) {
		var query = ternManager.buildQuery(cm, "completions");

		ternManager._docs.query(query)
			.done(function(data) {
				var completions = [];
				for (var i = 0; i < data.completions.length; ++i) {
					var completion = data.completions[i], className = ternManager.typeToIcon(completion.type);
					if (data.guess) {
						className += " Tern-completion-guess";
					}
					completions.push({text: completion.name, className: className});
				}

				c({
					from: cm.posFromIndex(data.from),
					to: cm.posFromIndex(data.to),
					list: completions
				});
			})
			.fail(function(error){
				// TODO: Need to handle errors
				return null;
			});
	}

	ternManager.findType = function(cm) {
		var query = ternManager.buildQuery(cm, "type");

		ternManager._docs.query(query)
			.done( function(data) {
			})
			.fail(function( error ){
			});
	}

	ternManager.jumpToDef = function(cm) {
		console.log("jumpToDef");
	}

	ternManager.jumpBack = function(cm) {
		console.log("jumpBack");
	}

	ternManager.renameVar = function(cm) {
	  	var query = ternManager.buildQuery(cm, "refs");

	  	ternManager._docs.query(query)
			.done(function(data) {
				var perFile = {};

			  	for (var i = 0; i < data.refs.length; ++i) {
					var use = data.refs[i];
					(perFile[use.file] || (perFile[use.file] = [])).push(use);
				}

			  	for (var file in perFile) {
					var refs = perFile[file], doc = ternManager._docs.findDocByName(file).doc;
					refs.sort(function(a, b) { return b.start - a.start; });

				  	for (var i = 0; i < refs.length; ++i) {
					  	console.log(refs[i]);
						//doc.replaceRange(newName, doc.posFromIndex(refs[i].start), doc.posFromIndex(refs[i].end));
					}
				}
			})
			.fail(function(error) {

			});
	}

	ternManager.typeToIcon = function (type) {
		var suffix;

		if (type == "?") {
			suffix = "unknown";
		}
		else if (type == "number" || type == "string" || type == "bool") {
			suffix = type;
		}
		else if (/^fn\(/.test(type)) {
			suffix = "fn";
		}
		else if (/^\[/.test(type)) {
			suffix = "array";
		}
		else {
			suffix = "object";
		}

		return "Tern-completion Tern-completion-" + suffix;
	}

	ternManager.buildQuery = function(cm, query) {
		var startPos, endPos;

		// 1. Let's make sure we have a query object
		//
		if (typeof query == "string") {
			query = {
				type: query
			};
		}

		// 2. Define a range where the intellence will be applied on
		//
		if (query.end == null && query.start == null) {
			endPos = cm.getCursor("end");
			query.end = cm.indexFromPos(endPos);

			if (cm.somethingSelected()) {
				startPos = cm.getCursor("start")
				query.start = cm.indexFromPos(startPos);
			}
		}
		else {
			endPos = query.end
			query.end = cm.indexFromPos(endPos);

			if (query.start != null) {
				startPos = query.start;
				query.start = cm.indexFromPos(startPos);
			}
		}

		if ( !startPos ) {
			startPos = endPos;
		}

		// 3. Specify the document name.
		// TODO: document needs to be remote server friendly
		var doc = ternManager._docs.findDocByInstance(cm.getDoc());
		if( doc ){
			query.file = doc.name;
		}

		return {
			query: query
		};
	}

	// Once the app is fully loaded, we will proceed to check the theme that
	// was last set
	AppInit.appReady(function () {
		ternManager.onReady(function(){
			// Initialize any already open document that's already in focus
			ternManager.initEditor();

			// Anytime a new doc is in view, register all the junk we need to
			$(DocumentManager).on("currentDocumentChange", ternManager.initEditor);
		});
	});

});

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

/** Brackets Extension to load line navigator CodeMirror addon */
define(["require", "exports", "module"], function (require, exports, module) {
	"use strict";

	var DocumentManager     = brackets.getModule("document/DocumentManager"),
		EditorManager       = brackets.getModule("editor/EditorManager"),
		AppInit             = brackets.getModule("utils/AppInit"),
		FileUtils           = brackets.getModule("file/FileUtils");

	/*
	*
	* Try to load tern via requirejs to avoid having to modify brackets index.html
	*/
	/*
	var ternRequire = window.require.config({
		"baseUrl": require.toUrl("./tern"),
		"map":{
			"*": {
				"acorn": "../acorn/acorn",
				"acorn/acorn_loose": "../acorn/acorn_loose",
				"acorn/util/walk": "../acorn/util/walk"
			}
		},
		"shim":{
			"acorn/acorn_loose": {
				deps:["acorn"]
			},
			"acorn/util/walk": {
				deps:["acorn"]
			},
			"desktop" :{
				deps:["tern"]
			},
			"tern": {
				deps:["infer", "acorn", "condense", "acorn/acorn_loose", "acorn/util/walk"]
			},
			"infer": {
				deps: ["acorn", "acorn/acorn_loose", "acorn/util/walk", "env", "jsdoc"]
			},
			"condense": {
				deps: ["infer"]
			}
		},
		waitTimeout: 30
	});

	ternRequire(["require", "exports", "module", "desktop"], function() {
	});
	*/

	/**
	* tern server, which manager all the processing with an in process
	* service.
	*/
	function ternDocuments (options) {
		var _self = this;
		this.ready = $.Deferred();
		this.docs = [];
		this.onReady = this.ready.promise().done;
	}

	ternDocuments.prototype.query = function( query ) {
		throw "Must implement";
	}

	ternDocuments.prototype.findDocByProperty = function(_propName, data) {
		for (var i = 0; i < this.docs.length; ++i) {
			if (this.docs[i][_propName] == data) {
				return this.docs[i];
			}
		}
	}

	ternDocuments.prototype.findDocByName = function(name) {
		return this.findDocByProperty("name", name);
	}

	ternDocuments.prototype.findDocByInstance = function(doc) {
		return this.findDocByProperty("doc", doc);
	}

	ternDocuments.prototype.registerDoc = function(name, doc) {
		var _self = this;

		this.addDoc({name: name,
					 doc: doc,
					 changed: null});

		CodeMirror.on(doc, "change", function(){
			_self.trackChange.apply(_self, arguments);
		});
	}

	ternDocuments.prototype.trackChange = function (doc, change) {
		var _doc = this.findDocByInstance(doc);

		var changed = _doc.changed;
		if (changed == null){
			_doc.changed = changed = {
				from: change.from.line,
				to: change.from.line
			};
		}

		var end = change.from.line + (change.text.length - 1);

		if (change.from.line < changed.to) {
			changed.to = changed.to - (change.to.line - end);
		}

		if (end >= changed.to) {
			changed.to = end + 1;
		}

		if (changed.from > change.from.line) {
			changed.from = change.from.line;
		}
	}

	/**
	*  Interface to operate against a local instance of tern
	*/
	function localDocuments() {
		ternDocuments.apply(this, arguments);
		var _self = this;

		//
		// Load up all the definitions that we will need to start with.
		//
		require(["text!./tern/ecma5.json", "text!./tern/browser.json",
				 "text!./tern/plugin/requirejs/requirejs.json", "text!./tern/jquery.json"],
			function( _ecma5Env, _browserEnv, _requireEnv, _jQueryEnv ) {
				var environment = Array.prototype.slice.call(arguments, 0);
				$.each(environment.slice(0), function(index, item){
					environment[index] = JSON.parse(item);
				});

				_self._server = new tern.Server({
					getFile: function(){
						_self.getFile.apply(_self, arguments);
					},
					environment: environment
				});

				_self.ready.resolve(_self);
		});
	}

	// Create a localDocument server.
	localDocuments.prototype = new ternDocuments;
	localDocuments.prototype.constructor = localDocuments;

	localDocuments.prototype.query = function( query ) {
		var promise = $.Deferred();

		this._server.request( query, function(error, data) {
			if (error) {
				promise.fail(error);
			}
			else {
				console.log(data);
				promise.resolve(data);
			}
		});

		return promise.promise();
	}

	localDocuments.prototype.addDoc = function (doc) {
		this.docs.push(doc);
		this._server.addFile(doc.name);
	}

	var httpCache = {};
	localDocuments.prototype.getFile = function (name, c) {
		if (/^https?:\/\//.test(name)) {
			if (httpCache[name]){
			  return c(null, httpCache[name]);
			}

			jQuery.ajax({
				"url": name,
				"contentType": "text"
			})
			.done(function(data, status) {
				httpCache[name] = data;
				c(null, data);
			})
			.fail(function(){
				c(null, "");
			});
		}
		else {
			var doc = this.findDocByName(name);
			return c(null, doc ? doc.doc.getValue() : "");
		}
	}

	/**
	*  Interface to operate against a remote tern server
	*/
	function remoteDocuments() {
		ternDocuments.apply(this, arguments);
		var _self = this;

		setTimeout(function(){
			_self.ready.resolve(_self);
		}, 1);
	}

	remoteDocuments.prototype = new ternDocuments;
	remoteDocuments.prototype.constructor = remoteDocuments;

	remoteDocuments.prototype.ping = function (){
		return jQuery.ajax({
			"url": "http://localhost:4943/ping",
			"type": "GET"
		})
		.promise();
	}

	remoteDocuments.prototype.query = function( query ) {

	  	//
 	  	// Raw integration with the server... I have to send the file I am working with.
	  	//
	  	var doc = this.findDocByName( query.query.file );

	  	if ( !query.files ) {
		 	query.files = [];
		}

		query.files.push({type: "full",
					name: doc.name,
					text: doc.doc.getValue()
				});

	  	// Send query to the server
	  	return jQuery.ajax({
			"url": "http://localhost:5923",
			"type": "POST",
			contentType: "application/json; charset=utf-8",
			data: JSON.stringify(query)
		})
		.pipe(function(data){
			console.log(data);
			return data;
		}, function(error){
 			console.log(error);
		})
		.promise();
	}

	remoteDocuments.prototype.addDoc = function(doc) {
		this.docs.push(doc);
	}

	/**
	*  Controls the interaction between brackets and tern
	*/
	var ternManager = (function() {
		var onReady = $.Deferred();
		var docs = new remoteDocuments();
		//var docs = new localDocuments();
		docs.onReady(onReady.resolve)

		return {
			onReady: onReady.promise().done,
			_docs: docs
		};
	})();

	ternManager.initEditor = function ( ) {
		// Change the current editor in view
		var editor = EditorManager.getCurrentFullEditor();

		// Make sure we have a valid editor
		if (!editor && !editor._codeMirror) {
			return;
		}

		var cm = editor._codeMirror;

		// if already bound, then exit...
		if ( cm._ternBindings ){
			return;
		}

		cm._ternBindings = ternManager;

		var file = editor.document.file;
		var keyMap = {
			"name": "ternBindings",
			"Ctrl-I": ternManager.findType,
			"Ctrl-.": function(cm) {
				CodeMirror.showHint(cm, ternManager.showHint, {async: true});
			},
			"Alt-.": ternManager.jumpToDef,
			"Alt-,": ternManager.jumpBack,
			"Ctrl-R": ternManager.renameVar
		};

		// Register key events
		cm.addKeyMap(keyMap);
		ternManager._docs.registerDoc(file.fullPath, cm.getDoc());
	}

	ternManager.showHint = function(cm, c) {
		var query = ternManager.buildQuery(cm, "completions");

		ternManager._docs.query(query)
			.done(function(data) {
				var completions = [];
				for (var i = 0; i < data.completions.length; ++i) {
					var completion = data.completions[i], className = ternManager.typeToIcon(completion.type);
					if (data.guess) {
						className += " Tern-completion-guess";
					}
					completions.push({text: completion.name, className: className});
				}

				c({
					from: cm.posFromIndex(data.from),
					to: cm.posFromIndex(data.to),
					list: completions
				});
			})
			.fail(function(error){
				// TODO: Need to handle errors
				return null;
			});
	}

	ternManager.findType = function(cm) {
		var query = ternManager.buildQuery(cm, "type");

		ternManager._docs.query(query)
			.done( function(data) {
			})
			.fail(function( error ){
			});
	}

	ternManager.jumpToDef = function(cm) {
		console.log("jumpToDef");
	}

	ternManager.jumpBack = function(cm) {
		console.log("jumpBack");
	}

	ternManager.renameVar = function(cm) {
		var query = ternManager.buildQuery(cm, "refs");

		ternManager._docs.query(query)
			.done(function(data) {
				var perFile = {};

				for (var i = 0; i < data.refs.length; ++i) {
					var use = data.refs[i];
					(perFile[use.file] || (perFile[use.file] = [])).push(use);
				}

				for (var file in perFile) {
					var refs = perFile[file], doc = ternManager._docs.findDocByName(file).doc;
					refs.sort(function(a, b) { return b.start - a.start; });

					for (var i = 0; i < refs.length; ++i) {
						console.log(refs[i]);
						//doc.replaceRange(newName, doc.posFromIndex(refs[i].start), doc.posFromIndex(refs[i].end));
					}
				}
			})
			.fail(function(error) {

			});
	}

	ternManager.typeToIcon = function (type) {
		var suffix;

		if (type == "?") {
			suffix = "unknown";
		}
		else if (type == "number" || type == "string" || type == "bool") {
			suffix = type;
		}
		else if (/^fn\(/.test(type)) {
			suffix = "fn";
		}
		else if (/^\[/.test(type)) {
			suffix = "array";
		}
		else {
			suffix = "object";
		}

		return "Tern-completion Tern-completion-" + suffix;
	}

	ternManager.buildQuery = function(cm, query) {
		var startPos, endPos, offset = 0, files = [];

		// 1. Let's make sure we have a query object
		//
		if (typeof query == "string") {
			query = {
				type: query
			};
		}

		// 2. Define a range where the intellence will be applied on
		//
		if (query.end == null && query.start == null) {
			endPos = cm.getCursor("end");
			query.end = cm.indexFromPos(endPos);

			if (cm.somethingSelected()) {
				startPos = cm.getCursor("start")
				query.start = cm.indexFromPos(startPos);
			}
		}
		else {
			endPos = query.end
			query.end = cm.indexFromPos(endPos);

			if (query.start != null) {
				startPos = query.start;
				query.start = cm.indexFromPos(startPos);
			}
		}

		if ( !startPos ) {
			startPos = endPos;
		}

		var doc = ternManager._docs.findDocByInstance(cm.getDoc());
		query.file = doc.name;

	  	return {
			query: query,
			files: files
		};
	}

	// Once the app is fully loaded, we will proceed to check the theme that
	// was last set
	AppInit.appReady(function () {
		ternManager.onReady(function(){
			// Initialize any already open document that's already in focus
			ternManager.initEditor();

			// Anytime a new doc is in view, register all the junk we need to
			$(DocumentManager).on("currentDocumentChange", ternManager.initEditor);
		});
	});

});
<|endoftext|>


<commit_before>// setting env var
const env = process.env.NODE_ENV || 'prod';

const electron = require('electron');
const app = electron.app
const BrowserWindow = electron.BrowserWindow

const installExtension = require('electron-devtools-installer');
installExtension.default(installExtension.REDUX_DEVTOOLS);

const electronSettings = require('electron-settings');

if (env === 'dev') {
  require('electron-debug')({showDevTools: true});
}

let mainWindow

function createWindow () {
  electronSettings.get('window').then((win) => {
    mainWindow = new BrowserWindow(win || {x: 100, y: 100, width: 800, height: 600})
    mainWindow.loadURL(`file://${__dirname}/src/index.html`)

    mainWindow.on('closed', function () {
      mainWindow = null
    })

    let ti;
    mainWindow.on('resize', () => {
      clearTimeout(ti);
      ti = setTimeout(() => {
        electronSettings.set('window', mainWindow.getBounds());
      }, 1000);
    });

    mainWindow.setMenu(null)

    if (env === 'dev') {
      // simple livereload
      const chokidar = require('chokidar');
      chokidar.watch('src/**/*.(js|css)', {
          ignored: /[\/\\]\./,
          persistent: true
        })
        .on('all', (event, path) => {
          mainWindow.reload();
        }
      );
    } else {
    }
  });
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', function () {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
    createWindow()
  }
})

<commit_msg>redux devtool only in dev env<commit_after>// setting env var
const env = process.env.NODE_ENV || 'prod';

const electron = require('electron');
const app = electron.app
const BrowserWindow = electron.BrowserWindow
const electronSettings = require('electron-settings');

if (env === 'dev') {
  const installExtension = require('electron-devtools-installer');
  installExtension.default(installExtension.REDUX_DEVTOOLS);
  require('electron-debug')({showDevTools: true});
}

let mainWindow

function createWindow () {
  electronSettings.get('window').then((win) => {
    mainWindow = new BrowserWindow(win || {x: 100, y: 100, width: 800, height: 600})
    mainWindow.loadURL(`file://${__dirname}/src/index.html`)

    mainWindow.on('closed', function () {
      mainWindow = null
    })

    let ti;
    mainWindow.on('resize', () => {
      clearTimeout(ti);
      ti = setTimeout(() => {
        electronSettings.set('window', mainWindow.getBounds());
      }, 1000);
    });

    mainWindow.setMenu(null)

    if (env === 'dev') {
      // simple livereload
      const chokidar = require('chokidar');
      chokidar.watch('src/**/*.(js|css)', {
          ignored: /[\/\\]\./,
          persistent: true
        })
        .on('all', (event, path) => {
          mainWindow.reload();
        }
      );
    } else {
    }
  });
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', function () {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
    createWindow()
  }
})

<|endoftext|>


<commit_before>#!/usr/bin/env node

var fs = require("fs"),
    rss = require("rss"),
    mustache = require("mustache"),
    chalk = require("chalk"),
    ncp = require("ncp"),
    prompt = require("prompt"),
    optp = require("nomnom").script("shock");

var success = chalk.green,
    failure = chalk.red;

prompt.message = "(shock)";

optp.command("init")
    .callback(function() {
        prompt.start();
        prompt.get(['title', 'author', 'description', 'url'], function(err, x) {
            if (err) {
                console.log(failure("Aborted."));
                process.exit();
            }
            ncp(__dirname+"/init", ".", function(err) {
                if (err) {
                    console.log(failure("Failed to create directory structure. Hmph."));
                    process.exit();
                }
                fs.readFile("index.json", function(err, data) {
                    var index = JSON.parse(data);
                    index.title = x.title;
                    index.author = x.author;
                    index.description = x.description;
                    index.url = x.url;
                    fs.writeFile("index.json", JSON.stringify(index, null, 4), function(err) {
                        console.log(success("Minimal shock site initialized."));
                    });
                });
            });
        });
    });

optp.command("compile")
    .callback(function() {
        fs.readFile("index.json", function(err, data) {
            if (err) {
                throw err;
            }
            var index;
            try {
                index = JSON.parse(data);
            } catch(e) {
                console.log(failure("index.json failed to parse (it has to be honest json, not a js object literal!)"));
                process.exit();
            }

            var header = fs.readFileSync("templates/" + index.templates.header).toString();
            var footer = fs.readFileSync("templates/" + index.templates.footer).toString();
            var postpage = fs.readFileSync("templates/" + index.templates.postpage).toString();
            var home = fs.readFileSync("templates/" + index.templates.home).toString();

            // Create RSS feed
            var feed = new rss({
                title: index.title,
                description: index.description,
                site_url: index.url,
                author: index.author,
                language: index.lang || "en",
            });

            var items = index.posts.sort(function(d) {
                return new Date(d.date).getTime();
            });
            items.forEach(function(item) {
                feed.item({
                    title: item.title,
                    description: item.description,
                    url: index.url + "/" + item.file,
                    date: item.date,
                    author: item.author || index.author
                });

                var view = {
                    title: item.title,
                    description: item.description,
                    date: item.date,
                    author: item.author,
                    header: header,
                    footer: footer,
                    content: fs.readFileSync("content/" + item.file).toString()
                }
                fs.writeFile(item.file, mustache.render(postpage, view), function() {
                    console.log(success("Created " + item.file));
                });

            });

            fs.writeFile("feed.xml", feed.xml("    "), function() {
                console.log(success("Created RSS feed."));
            });
            fs.writeFile("index.html", mustache.render(home, {
                header: header,
                footer: footer,
                posts: items
            }), function() {
                console.log(success("Created homepage."));
            })
        });
    });

optp.command("newpost")
    .callback(function() {
        fs.readFile("index.json", function(err, data) {
            if (err) {
                console.log(failure("Couldn't read index.json."));
                process.exit();
            }
            var index = JSON.parse(data);
            prompt.start();
            prompt.get(
                ['title', 'author', 'description', 'file', 'date'],
                function(err, data) {
                    if (err) {
                        console.log(failure("Aborted."));
                        process.exit();
                    }
                    index.posts.push(data);

                    fs.writeFile("index.json", JSON.stringify(index, null, 4), function(err) {
                        console.log(success("Post created."));
                    });
                });
        })
    });

var opts = optp.parse();
<commit_msg>unsort<commit_after>#!/usr/bin/env node

var fs = require("fs"),
    rss = require("rss"),
    mustache = require("mustache"),
    chalk = require("chalk"),
    ncp = require("ncp"),
    prompt = require("prompt"),
    optp = require("nomnom").script("shock");

var success = chalk.green,
    failure = chalk.red;

prompt.message = "(shock)";

optp.command("init")
    .callback(function() {
        prompt.start();
        prompt.get(['title', 'author', 'description', 'url'], function(err, x) {
            if (err) {
                console.log(failure("Aborted."));
                process.exit();
            }
            ncp(__dirname+"/init", ".", function(err) {
                if (err) {
                    console.log(failure("Failed to create directory structure. Hmph."));
                    process.exit();
                }
                fs.readFile("index.json", function(err, data) {
                    var index = JSON.parse(data);
                    index.title = x.title;
                    index.author = x.author;
                    index.description = x.description;
                    index.url = x.url;
                    fs.writeFile("index.json", JSON.stringify(index, null, 4), function(err) {
                        console.log(success("Minimal shock site initialized."));
                    });
                });
            });
        });
    });

optp.command("compile")
    .callback(function() {
        fs.readFile("index.json", function(err, data) {
            if (err) {
                throw err;
            }
            var index;
            try {
                index = JSON.parse(data);
            } catch(e) {
                console.log(failure("index.json failed to parse (it has to be honest json, not a js object literal!)"));
                process.exit();
            }

            var header = fs.readFileSync("templates/" + index.templates.header).toString();
            var footer = fs.readFileSync("templates/" + index.templates.footer).toString();
            var postpage = fs.readFileSync("templates/" + index.templates.postpage).toString();
            var home = fs.readFileSync("templates/" + index.templates.home).toString();

            // Create RSS feed
            var feed = new rss({
                title: index.title,
                description: index.description,
                site_url: index.url,
                author: index.author,
                language: index.lang || "en",
            });

            var items = index.posts.sort(function(d) {
                return -new Date(d.date).getTime();
            });
            items.forEach(function(item) {
                feed.item({
                    title: item.title,
                    description: item.description,
                    url: index.url + "/" + item.file,
                    date: item.date,
                    author: item.author || index.author
                });

                var view = {
                    title: item.title,
                    description: item.description,
                    date: item.date,
                    author: item.author,
                    header: header,
                    footer: footer,
                    content: fs.readFileSync("content/" + item.file).toString()
                }
                fs.writeFile(item.file, mustache.render(postpage, view), function() {
                    console.log(success("Created " + item.file));
                });

            });

            fs.writeFile("feed.xml", feed.xml("    "), function() {
                console.log(success("Created RSS feed."));
            });
            fs.writeFile("index.html", mustache.render(home, {
                header: header,
                footer: footer,
                posts: items
            }), function() {
                console.log(success("Created homepage."));
            })
        });
    });

optp.command("newpost")
    .callback(function() {
        fs.readFile("index.json", function(err, data) {
            if (err) {
                console.log(failure("Couldn't read index.json."));
                process.exit();
            }
            var index = JSON.parse(data);
            prompt.start();
            prompt.get(
                ['title', 'author', 'description', 'file', 'date'],
                function(err, data) {
                    if (err) {
                        console.log(failure("Aborted."));
                        process.exit();
                    }
                    index.posts.push(data);

                    fs.writeFile("index.json", JSON.stringify(index, null, 4), function(err) {
                        console.log(success("Post created."));
                    });
                });
        })
    });

var opts = optp.parse();
<|endoftext|>


<commit_before>'use strict';

if (!("Notification" in window)) {
    console.log("Your browser does not seem to support desktop notifications");
} else if (Notification.permission !== 'denied') {
    Notification.requestPermission();
}

function SE_questions_check() {
    var copyright = $('#copyright'), link = $('a', 'li.youarehere');
    return (copyright.length &&
            copyright.html().indexOf('stack exchange inc') != -1 &&
            link.length &&
            link.attr('href').indexOf('/questions') != -1);
}

if (SE_questions_check()) {
    function make_box(tags) {
        var box_cls = 'question-tags-popup', queue_cls = 'box-queue',
            popups = $('.' + box_cls), new_box;

        new_box = $("
", {html: '
'+tags.join('

')+'
',
                              class: box_cls})
        if (!$('#' + queue_cls).length)
            $('body').prepend($('
', { id: queue_cls }));

        $('#' + queue_cls).prepend(new_box);

        // 5 boxes at most
        if (popups.length >= 5)
            popups.last().remove();

    }

    var audio = new Audio(chrome.extension.getURL('sound.wav'));

    setInterval(function() {
        var tags, notification, count, children, title, nf = $('.new-post-activity');
        // Can be empty. Doing nothing if it is.
        if (nf.length) {
            // Play sound immediately
            audio.play();
            nf.trigger('click');
            // Number of new questions
            count = parseInt(nf.text());
            // `count` questions from the top
            children = $('.question-summary').slice(0, count);
            // Iterate over children in reverse order
            $(children.get().reverse()).each(function(i, v) {
                // Fetch all classes remove the first one (`tags`)
                tags = $(v).find('.tags').find('a').get().map(function (tag) {
                    return tag.text;
                });
                title = $('h3', v);
                if (Notification.permission === 'granted') {
                    notification = new Notification(title.text(), {
                        body: 'Tags: ' + tags.join(' '),
                        icon: chrome.extension.getURL('icon_128.png')
                    });
                    notification.onshow = function () {
                        setTimeout(function() { notification.close () }, 7500);
                    };
                    notification.onclick = function () {
                        window.open(title.find('a').attr('href'), '_blank');
                    };
                }
                // Finally, display it
                make_box(tags);
            });
        }
    }, 1000);
}
<commit_msg>Whoopsie, wrong logic<commit_after>'use strict';

if (!("Notification" in window)) {
    console.log("Your browser does not seem to support desktop notifications");
} else if (Notification.permission === 'default') {
    Notification.requestPermission();
}

function SE_questions_check() {
    var copyright = $('#copyright'), link = $('a', 'li.youarehere');
    return (copyright.length &&
            copyright.html().indexOf('stack exchange inc') != -1 &&
            link.length &&
            link.attr('href').indexOf('/questions') != -1);
}

if (SE_questions_check()) {
    function make_box(tags) {
        var box_cls = 'question-tags-popup', queue_cls = 'box-queue',
            popups = $('.' + box_cls), new_box;

        new_box = $("
", {html: '
'+tags.join('

')+'
',
                              class: box_cls})
        if (!$('#' + queue_cls).length)
            $('body').prepend($('
', { id: queue_cls }));

        $('#' + queue_cls).prepend(new_box);

        // 5 boxes at most
        if (popups.length >= 5)
            popups.last().remove();

    }

    var audio = new Audio(chrome.extension.getURL('sound.wav'));

    setInterval(function() {
        var tags, notification, count, children, title, nf = $('.new-post-activity');
        // Can be empty. Doing nothing if it is.
        if (nf.length) {
            // Play sound immediately
            audio.play();
            nf.trigger('click');
            // Number of new questions
            count = parseInt(nf.text());
            // `count` questions from the top
            children = $('.question-summary').slice(0, count);
            // Iterate over children in reverse order
            $(children.get().reverse()).each(function(i, v) {
                // Fetch all classes remove the first one (`tags`)
                tags = $(v).find('.tags').find('a').get().map(function (tag) {
                    return tag.text;
                });
                title = $('h3', v);
                if (Notification.permission === 'granted') {
                    notification = new Notification(title.text(), {
                        body: 'Tags: ' + tags.join(' '),
                        icon: chrome.extension.getURL('icon_128.png')
                    });
                    notification.onshow = function () {
                        setTimeout(function() { notification.close () }, 7500);
                    };
                    notification.onclick = function () {
                        window.open(title.find('a').attr('href'), '_blank');
                    };
                }
                // Finally, display it
                make_box(tags);
            });
        }
    }, 1000);
}
<|endoftext|>


<commit_before>/*jslint browser: true*/
/*global Tangram, gui */

map = (function () {
    'use strict';

    var locations = {
        'Oakland': [37.8044, -122.2708, 15],
        'New York': [40.70531887544228, -74.00976419448853, 15],
        'Seattle': [47.5937, -122.3215, 15],
        'USA': [39.538, -97.603, 5]
    };

    var map_start_location = locations['USA'];

    /*** URL parsing ***/

    // leaflet-style URL hash pattern:
    // #[zoom],[lat],[lng]
    var url_hash = window.location.hash.slice(1, window.location.hash.length).split('/');

    if (url_hash.length == 3) {
        map_start_location = [url_hash[1],url_hash[2], url_hash[0]];
        // convert from strings
        map_start_location = map_start_location.map(Number);
    }

    /*** Map ***/

    var map = L.map('map',
        {"keyboardZoomOffset" : .05}
    );

    var layer = Tangram.leafletLayer({
        scene: 'scene.yaml',
        numWorkers: 2,
        attribution: 'Tangram | © OSM contributors | Mapzen',
        unloadInvisibleTiles: false,
        updateWhenIdle: false
    });

    window.layer = layer;
    var scene = layer.scene;
    window.scene = scene;

    // setView expects format ([lat, long], zoom)
    map.setView(map_start_location.slice(0, 3), map_start_location[2]);

    var hash = new L.Hash(map);

    /***** Render loop *****/

    window.addEventListener('load', function () {
        // Scene initialized
        layer.on('init', function() {
        });
        layer.addTo(map);
    });

    return map;

}());
<commit_msg>add noscroll url option<commit_after>/*jslint browser: true*/
/*global Tangram, gui */

map = (function () {
    'use strict';

    var locations = {
        'Oakland': [37.8044, -122.2708, 15],
        'New York': [40.70531887544228, -74.00976419448853, 15],
        'Seattle': [47.5937, -122.3215, 15],
        'USA': [39.538, -97.603, 5]
    };

    var map_start_location = locations['USA'];

    /*** URL parsing ***/

    // leaflet-style URL hash pattern:
    // #[zoom],[lat],[lng]
    var url_hash = window.location.hash.slice(1, window.location.hash.length).split('/');

    if (url_hash.length == 3) {
        map_start_location = [url_hash[1],url_hash[2], url_hash[0]];
        // convert from strings
        map_start_location = map_start_location.map(Number);
    }

    /*** Map ***/

    var map = L.map('map',
        {"keyboardZoomOffset" : .05}
    );

    var url_search = window.location.search.slice(1);
    if (url_search.length > 0) {
        if (url_search.lastIndexOf('noscroll') > -1) {
            map.scrollWheelZoom.disable();
            map.touchZoom.disable();
        }
    }

    var layer = Tangram.leafletLayer({
        scene: 'scene.yaml',
        numWorkers: 2,
        attribution: 'Tangram | © OSM contributors | Mapzen',
        unloadInvisibleTiles: false,
        updateWhenIdle: false
    });

    window.layer = layer;
    var scene = layer.scene;
    window.scene = scene;

    // setView expects format ([lat, long], zoom)
    map.setView(map_start_location.slice(0, 3), map_start_location[2]);

    var hash = new L.Hash(map);

    /***** Render loop *****/

    window.addEventListener('load', function () {
        // Scene initialized
        layer.on('init', function() {
        });
        layer.addTo(map);
    });

    return map;

}());
<|endoftext|>


<commit_before>/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4,
maxerr: 50, browser: true */
/*global define, brackets, appshell */

/**
 * This extension provides in-editor livepreview through an iframe,
 * and leverages the experimental Multi Browser implementation of brackets
 * (see https://github.com/adobe/brackets/tree/master/src/LiveDevelopment/MultiBrowserImpl)
 */
define(function (require, exports, module) {
    "use strict";

    // Load dependencies
    var AppInit              = brackets.getModule("utils/AppInit"),
        CommandManager       = brackets.getModule("command/CommandManager"),
        Commands             = brackets.getModule("command/Commands"),
        EditorManager        = brackets.getModule("editor/EditorManager"),
        LiveDevServerManager = brackets.getModule("LiveDevelopment/LiveDevServerManager"),
        PreferencesManager   = brackets.getModule("preferences/PreferencesManager"),
        ProjectManager       = brackets.getModule("project/ProjectManager"),
        LiveDevelopment      = brackets.getModule("LiveDevelopment/LiveDevMultiBrowser"),
        UrlParams            = brackets.getModule("utils/UrlParams").UrlParams,
        ViewCommand          = brackets.getModule("view/ViewCommandHandlers"),
        Editor               = brackets.getModule("editor/Editor").Editor,
        // Load nohost dependencies
        Browser              = require("lib/iframe-browser"),
        HideUI               = require("lib/hideUI"),
        Launcher             = require("lib/launcher").Launcher,
        NoHostServer         = require("nohost/src/NoHostServer").NoHostServer,
        ExtensionUtils       = brackets.getModule("utils/ExtensionUtils"),
        PostMessageTransport = require("lib/PostMessageTransport");

    var _server,
        codeMirror,
        fs           = appshell.Filer.fs(),
        parentWindow = window.parent,
        params       = new UrlParams();

    // Load initial document
    var defaultHTML = require("text!lib/default.html");

    // Force entry to if statments on line 262 of brackets.js to create
    // a new project
    PreferencesManager.setViewState("afterFirstLaunch", false);
    params.remove("skipSampleProjectLoad");

    function _getServer() {
        if (!_server) {
            _server = new NoHostServer({
                pathResolver    : ProjectManager.makeProjectRelativeIfPossible,
                root            : ProjectManager.getProjectRoot()
            });
        }
        return _server;
    }

    function parseData(data, deferred) {
        var dataReceived = data;

        try {
            data = dataReceived || null;
            data = JSON.parse(data);
            data = data || {};
        } catch(err) {
            // Quick fix: Ignore the 'process-tick' message being sent
            if(dataReceived === 'process-tick') {
                return false;
            }

            console.error("Parsing message from thimble failed: ", err);

            if(deferred) {
                deferred.reject();
            }

            return false;
        }

        return data;
    }

    // We wait until the LiveDevelopment module is initialized and the project loaded
    // so we can safely swap our transport and launcher modules for
    // the defaults and start LiveDev.
    function _configureLiveDev() {
        // Turn preview iFrame On
        Browser.init();

        function _configureModules() {
            // Set up our transport and plug it into live-dev
            PostMessageTransport.setIframe(Browser.getBrowserIframe());
            LiveDevelopment.setTransport(PostMessageTransport);

            // Set up our launcher in a similar manner
            // XXXhumph - this depends on setLauncher() from https://github.com/adobe/brackets/pull/10558
            LiveDevelopment.setLauncher(new Launcher({
                browser: Browser,
                server: _getServer()
            }));

            LiveDevelopment.open();
        }
        LiveDevelopment.one("statusChange", _configureModules);
    }
    ProjectManager.one("projectOpen", _configureLiveDev);

    /*
     * This function is attached to the window as an event listener
     * Its purpose is to intercept post messages from bramble proxy in thimble
     * some of these being:
     * undo, redo, size changer, or any other buttons relating to menu or view
     * within event we expect to receive a JSONable object that contains a commandCategory:
     * menuCommand: "Menu Command" relating to menu commands runable
     * viewCommand: "View Command" relating to functions in viewcommand
     * editorCommand: "Editor Command" relating to functions relating ot the editor itself
     * also contains a variable of "params" which can be used to send further information needed
     */
    function _buttonListener(event) {
        var msgObj;
        try {
            msgObj = JSON.parse(event.data);
        } catch (e) {
            return;
        }

        if(msgObj.commandCategory === "menuCommand"){
            codeMirror.focus();
            CommandManager.execute(Commands[msgObj.command]);
        }
        else if (msgObj.commandCategory === "viewCommand") {
            ViewCommand[msgObj.command](msgObj.params);
        }
        else if (msgObj.commandCategory === "editorCommand") {
            Editor[msgObj.command](msgObj.params);
        }
    }

    // We configure Brackets to run the experimental live dev
    // with our nohost server and iframe combination. This has to
    // occur before the project is loaded, triggering the start of
    // the live preview.
    AppInit.extensionsLoaded(function () {
        // Flip livedev.multibrowser to true
        var prefs = PreferencesManager.getExtensionPrefs("livedev");
        prefs.set("multibrowser", true);

        ExtensionUtils.loadStyleSheet(module, "stylesheets/tutorials.css");

        // Register nohost server with highest priority
        LiveDevServerManager.registerServer({ create: _getServer }, 9001);
    });

    AppInit.appReady(function (){
        // When the app is loaded and ready, hide the menus/toolbars
        HideUI.hide();

        parentWindow.postMessage(JSON.stringify({
            type: "bramble:loaded"
        }), "*");

        // Once the app has loaded our file,
        // and we can be confident the editor is open,
        // get a reference to it and attach our "onchange"
        // listener to codemirror
        codeMirror = EditorManager.getActiveEditor()._codeMirror;

        parentWindow.postMessage(JSON.stringify({
            type: "bramble:change",
            sourceCode: codeMirror.getValue(),
            lastLine: codeMirror.lastLine(),
            scrollInfo: codeMirror.getScrollInfo()
        }), "*");

        codeMirror.on("change", function(){
            parentWindow.postMessage(JSON.stringify({
                type: "bramble:change",
                sourceCode: codeMirror.getValue(),
                lastLine: codeMirror.lastLine()
            }), "*");
        });

        codeMirror.on("viewportChange", function() {
            parentWindow.postMessage(JSON.stringify({
                type: "bramble:viewportChange",
                scrollInfo: codeMirror.getScrollInfo()
            }), "*");
        });

        window.addEventListener("message", function(e) {
            var data = parseData(e.data);
            var value;
            var mark;

            if(!data) {
                return;
            }

            if(data.type !== "bramble:edit") {
                return;
            }

            if(!data.fn) {
                console.error("No edit function sent from thimble to call on code mirror");
                return;
            }

            // QuickFix: Hack to create a DOM element as a marker since it cannot
            // be passed in through postMessage as JSON's stringify cannot work for
            // DOM elements (because it has circular references)
            if(data.fn === "setGutterMarker" && data.params[2]) {
                mark = document.createElement(data.params[2].name);
                var attributes = data.params[2].attributes;
                Object.keys(attributes).forEach(function(attrName) {
                    $(mark).attr(attrName, attributes[attrName]);
                });
                mark.innerHTML = data.params[2].innerHTML;
                data.params[2] = mark;
            }

            if(data.fn === "getLineHeight") {
                var codeMirrorLine = document.querySelector(data.params[0]);
                value = parseFloat(window.getComputedStyle(codeMirrorLine).height);
            } else {
                value = codeMirror[data.fn].apply(codeMirror, data.params);
            }

            if(value === undefined || value === null) {
                return;
            }

            parentWindow.postMessage(JSON.stringify({
                type: "bramble:edit",
                fn: data.fn,
                value: typeof value !== "object" ? value : undefined
            }), "*");
        });
    });

    // We listen for a message from Thimble containing
    // the make's initial code.
    // For now, we have a default html make for testing
    // with just Brackets.
    exports.initExtension = function() {
        var deferred = new $.Deferred();

        function _getInitialDocument(e) {
            var data = parseData(e.data, deferred);

            // Remove the listener after we confirm the event is the
            // one we're waiting for
            if (!data || data.type !== "bramble:init") {
                return;
            }

            window.removeEventListener("message", _getInitialDocument);

            window.addEventListener("message", _buttonListener);

            fs.writeFile(
                '/index.html',
                data.source ? data.source : defaultHTML,
                function(err) {
                    if (err) {
                        deferred.reject();
                        return;
                    }

                    deferred.resolve();
                }
            );
        }

        window.addEventListener("message", _getInitialDocument);

        // Signal to thimble that we're waiting for the
        // initial make source code
        window.parent.postMessage(JSON.stringify({
            type: "bramble:init"
        }), "*");

        return deferred.promise();
    };
});
<commit_msg>Fix #106 Added method to flip preference after brackets is done loading<commit_after>/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4,
maxerr: 50, browser: true */
/*global define, brackets, appshell */

/**
 * This extension provides in-editor livepreview through an iframe,
 * and leverages the experimental Multi Browser implementation of brackets
 * (see https://github.com/adobe/brackets/tree/master/src/LiveDevelopment/MultiBrowserImpl)
 */
define(function (require, exports, module) {
    "use strict";

    // Load dependencies
    var AppInit              = brackets.getModule("utils/AppInit"),
        CommandManager       = brackets.getModule("command/CommandManager"),
        Commands             = brackets.getModule("command/Commands"),
        EditorManager        = brackets.getModule("editor/EditorManager"),
        LiveDevServerManager = brackets.getModule("LiveDevelopment/LiveDevServerManager"),
        PreferencesManager   = brackets.getModule("preferences/PreferencesManager"),
        ProjectManager       = brackets.getModule("project/ProjectManager"),
        LiveDevelopment      = brackets.getModule("LiveDevelopment/LiveDevMultiBrowser"),
        UrlParams            = brackets.getModule("utils/UrlParams").UrlParams,
        ViewCommand          = brackets.getModule("view/ViewCommandHandlers"),
        Editor               = brackets.getModule("editor/Editor").Editor,
        // Load nohost dependencies
        Browser              = require("lib/iframe-browser"),
        HideUI               = require("lib/hideUI"),
        Launcher             = require("lib/launcher").Launcher,
        NoHostServer         = require("nohost/src/NoHostServer").NoHostServer,
        ExtensionUtils       = brackets.getModule("utils/ExtensionUtils"),
        PostMessageTransport = require("lib/PostMessageTransport");

    var _server,
        codeMirror,
        fs           = appshell.Filer.fs(),
        parentWindow = window.parent,
        params       = new UrlParams();

    // Load initial document
    var defaultHTML = require("text!lib/default.html");

    // Force entry to if statments on line 262 of brackets.js to create
    // a new project
    PreferencesManager.setViewState("afterFirstLaunch", false);
    params.remove("skipSampleProjectLoad");

    function _getServer() {
        if (!_server) {
            _server = new NoHostServer({
                pathResolver    : ProjectManager.makeProjectRelativeIfPossible,
                root            : ProjectManager.getProjectRoot()
            });
        }
        return _server;
    }

    function parseData(data, deferred) {
        var dataReceived = data;

        try {
            data = dataReceived || null;
            data = JSON.parse(data);
            data = data || {};
        } catch(err) {
            // Quick fix: Ignore the 'process-tick' message being sent
            if(dataReceived === 'process-tick') {
                return false;
            }

            console.error("Parsing message from thimble failed: ", err);

            if(deferred) {
                deferred.reject();
            }

            return false;
        }

        return data;
    }

    // We wait until the LiveDevelopment module is initialized and the project loaded
    // so we can safely swap our transport and launcher modules for
    // the defaults and start LiveDev.
    function _configureLiveDev() {
        // Turn preview iFrame On
        Browser.init();

        function _configureModules() {
            // Set up our transport and plug it into live-dev
            PostMessageTransport.setIframe(Browser.getBrowserIframe());
            LiveDevelopment.setTransport(PostMessageTransport);

            // Set up our launcher in a similar manner
            // XXXhumph - this depends on setLauncher() from https://github.com/adobe/brackets/pull/10558
            LiveDevelopment.setLauncher(new Launcher({
                browser: Browser,
                server: _getServer()
            }));

            LiveDevelopment.open();
        }
        LiveDevelopment.one("statusChange", _configureModules);
    }
    ProjectManager.one("projectOpen", _configureLiveDev);

    /*
     * This function is attached to the window as an event listener
     * Its purpose is to intercept post messages from bramble proxy in thimble
     * some of these being:
     * undo, redo, size changer, or any other buttons relating to menu or view
     * within event we expect to receive a JSONable object that contains a commandCategory:
     * menuCommand: "Menu Command" relating to menu commands runable
     * viewCommand: "View Command" relating to functions in viewcommand
     * editorCommand: "Editor Command" relating to functions relating ot the editor itself
     * also contains a variable of "params" which can be used to send further information needed
     */
    function _buttonListener(event) {
        var msgObj;
        try {
            msgObj = JSON.parse(event.data);
        } catch (e) {
            return;
        }

        if(msgObj.commandCategory === "menuCommand"){
            codeMirror.focus();
            CommandManager.execute(Commands[msgObj.command]);
        }
        else if (msgObj.commandCategory === "viewCommand") {
            ViewCommand[msgObj.command](msgObj.params);
        }
        else if (msgObj.commandCategory === "editorCommand") {
            Editor[msgObj.command](msgObj.params);
        }
    }

    // We configure Brackets to run the experimental live dev
    // with our nohost server and iframe combination. This has to
    // occur before the project is loaded, triggering the start of
    // the live preview.
    AppInit.extensionsLoaded(function () {
        // Flip livedev.multibrowser to true
        var prefs = PreferencesManager.getExtensionPrefs("livedev");
        prefs.set("multibrowser", true);

        ExtensionUtils.loadStyleSheet(module, "stylesheets/tutorials.css");

        // Register nohost server with highest priority
        LiveDevServerManager.registerServer({ create: _getServer }, 9001);
    });

    AppInit.appReady(function (){
        // When the app is loaded and ready, hide the menus/toolbars
        HideUI.hide();

        parentWindow.postMessage(JSON.stringify({
            type: "bramble:loaded"
        }), "*");

        //Below are methods to change the preferences of breackets, more available at:
        // https://github.com/adobe/brackets/wiki/How-to-Use-Brackets#list-of-supported-preferences
        PreferencesManager.set("insertHintOnTab", true);

        // Once the app has loaded our file,
        // and we can be confident the editor is open,
        // get a reference to it and attach our "onchange"
        // listener to codemirror
        codeMirror = EditorManager.getActiveEditor()._codeMirror;

        parentWindow.postMessage(JSON.stringify({
            type: "bramble:change",
            sourceCode: codeMirror.getValue(),
            lastLine: codeMirror.lastLine(),
            scrollInfo: codeMirror.getScrollInfo()
        }), "*");

        codeMirror.on("change", function(){
            parentWindow.postMessage(JSON.stringify({
                type: "bramble:change",
                sourceCode: codeMirror.getValue(),
                lastLine: codeMirror.lastLine()
            }), "*");
        });

        codeMirror.on("viewportChange", function() {
            parentWindow.postMessage(JSON.stringify({
                type: "bramble:viewportChange",
                scrollInfo: codeMirror.getScrollInfo()
            }), "*");
        });

        window.addEventListener("message", function(e) {
            var data = parseData(e.data);
            var value;
            var mark;

            if(!data) {
                return;
            }

            if(data.type !== "bramble:edit") {
                return;
            }

            if(!data.fn) {
                console.error("No edit function sent from thimble to call on code mirror");
                return;
            }

            // QuickFix: Hack to create a DOM element as a marker since it cannot
            // be passed in through postMessage as JSON's stringify cannot work for
            // DOM elements (because it has circular references)
            if(data.fn === "setGutterMarker" && data.params[2]) {
                mark = document.createElement(data.params[2].name);
                var attributes = data.params[2].attributes;
                Object.keys(attributes).forEach(function(attrName) {
                    $(mark).attr(attrName, attributes[attrName]);
                });
                mark.innerHTML = data.params[2].innerHTML;
                data.params[2] = mark;
            }

            if(data.fn === "getLineHeight") {
                var codeMirrorLine = document.querySelector(data.params[0]);
                value = parseFloat(window.getComputedStyle(codeMirrorLine).height);
            } else {
                value = codeMirror[data.fn].apply(codeMirror, data.params);
            }

            if(value === undefined || value === null) {
                return;
            }

            parentWindow.postMessage(JSON.stringify({
                type: "bramble:edit",
                fn: data.fn,
                value: typeof value !== "object" ? value : undefined
            }), "*");
        });
    });

    // We listen for a message from Thimble containing
    // the make's initial code.
    // For now, we have a default html make for testing
    // with just Brackets.
    exports.initExtension = function() {
        var deferred = new $.Deferred();

        function _getInitialDocument(e) {
            var data = parseData(e.data, deferred);

            // Remove the listener after we confirm the event is the
            // one we're waiting for
            if (!data || data.type !== "bramble:init") {
                return;
            }

            window.removeEventListener("message", _getInitialDocument);

            window.addEventListener("message", _buttonListener);

            fs.writeFile(
                '/index.html',
                data.source ? data.source : defaultHTML,
                function(err) {
                    if (err) {
                        deferred.reject();
                        return;
                    }

                    deferred.resolve();
                }
            );
        }

        window.addEventListener("message", _getInitialDocument);

        // Signal to thimble that we're waiting for the
        // initial make source code
        window.parent.postMessage(JSON.stringify({
            type: "bramble:init"
        }), "*");

        return deferred.promise();
    };
});
<|endoftext|>