pulling in code.google.com changes

This commit is contained in:
Eric Bidelman
2012-06-27 23:19:03 -07:00
parent c6422f6acb
commit bb77904419
24 changed files with 576 additions and 174 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@@ -10,7 +10,7 @@ body {
font-family: Helvetica, Arial, sans-serif;
font-size: 13px;
line-height: 18px;
min-width: 1200px;
min-width: 975px;
padding: 20px;
}
@@ -279,12 +279,10 @@ input[type=text].form-error{
width: 0;
}
#file1-container {
float: left;
}
#file1-container,
#file2-container {
float: right;
float: left;
position: relative;
}
.input-container {
@@ -316,25 +314,99 @@ input[type=text].form-error{
padding-top: 5px;
}
.file-diff {
#arrow-container {
float: left;
height: 575px;
margin-top: 36px;
overflow: hidden;
position: relative;
width: 40px;
}
#arrow-container.arrow-edit {
opacity: 0;
}
#arrow-container .arrow {
background: url('../img/arrow-right.png') center no-repeat;
background-size: auto 95px;
height: 16px;
opacity: 0;
}
#arrow-container .undo {
background: url('../img/undo.svg') right no-repeat;
height: 16px;
opacity: 0;
}
#arrow-container .visible {
cursor: pointer;
opacity: 1;
}
#plus-container {
display: none;
float: left;
height: 575px;
margin-right: 2px;
margin-top: 36px;
overflow: hidden;
position: relative;
width: 16px;
z-index: 10;
}
#plus-container div {
border: 1px solid #999;
color: #999;
font-size: 18px;
height: 14px;
opacity: 0;
text-align: center;
width: 14px;
}
#plus-container div.plus,
#plus-container div.minus {
cursor: pointer;
opacity: 1;
}
#plus-container div.plus:after {
content: "+";
}
#plus-container div.minus:after {
content: "-";
}
.file-diff,
textarea {
background: #fafafa;
border: 1px solid #999;
float: left;
font-family: monospace;
font-size: 12px;
height: 600px;
height: 585px;
line-height: 16px;
margin-bottom: 10px;
margin-top: 10px;
overflow: auto;
white-space: nowrap;
width: 550px;
width: 455px;
}
div.button.edit,
div.button.done{
float: right;
}
.file-diff div {
float: left;
min-height: 16px;
position: relative;
white-space: nowrap;
width: 100%;
}
@@ -379,8 +451,15 @@ input[type=text].form-error{
width: 35px;
}
.file-diff div div.text,
.file-diff div div.left-text {
position: absolute;
left: 36px;
}
.file-diff div span {
float: left;
position: relative;
}
.file-diff div span.ins {
@@ -399,6 +478,25 @@ input[type=text].form-error{
display: none;
}
#file1-container .file-diff div.fix,
#file2-container .file-diff div.fix {
background: none;
}
#file1-container .file-diff div.fix span.del {
background: none;
}
#file2-container .file-diff div.fix span.ins {
display: none;
}
#file2-container .file-diff div.fix span.del {
display: block;
background: none;
}
.hidden {
display: none;
}

BIN
diff/img/arrow-left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 B

BIN
diff/img/arrow-right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 565 B

BIN
diff/img/icon_48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

15
diff/img/undo.png Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="21px" height="21px" viewBox="0 0 21 21" overflow="visible" enable-background="new 0 0 21 21"
xml:space="preserve">
<defs>
</defs>
<path d="M10.5,7C8.566,7,6.531,8.098,5.097,9.597L3,7.5V14h6.5l-2.259-2.259C8.125,10.747,9.904,9.1,12,9.1
c2.434,0,4.656,1.041,6,3.9C17,9,14,7,10.5,7z"/>
<rect opacity="0" fill="#4387FD" width="21" height="21"/>
</svg>

After

Width:  |  Height:  |  Size: 811 B

15
diff/img/undo.svg Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="21px" height="21px" viewBox="0 0 21 21" overflow="visible" enable-background="new 0 0 21 21"
xml:space="preserve">
<defs>
</defs>
<path d="M10.5,7C8.566,7,6.531,8.098,5.097,9.597L3,7.5V14h6.5l-2.259-2.259C8.125,10.747,9.904,9.1,12,9.1
c2.434,0,4.656,1.041,6,3.9C17,9,14,7,10.5,7z"/>
<rect opacity="0" fill="#4387FD" width="21" height="21"/>
</svg>

After

Width:  |  Height:  |  Size: 811 B

BIN
diff/js/.diff.js.swp Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -6,8 +6,8 @@
function onLaunched(launchData) {
chrome.appWindow.create('main.html', {
width: 1250,
height: 790
width: 1024,
height: 768
});
}

View File

@@ -27,6 +27,36 @@ $(document).ready(function() {
}
}, 500);
$('.edit').click(function() {
var text = getText();
$('#arrow-container').addClass('arrow-edit');
$('.file-diff.2').addClass('hidden');
$('textarea.diff-text').val(text);
$('textarea.diff-text').scrollTop($('.file-diff.1').scrollTop());
$('textarea.diff-text').removeClass('hidden');
$('.edit').addClass('hidden');
$('.done').removeClass('hidden');
});
$('.done').click(function() {
var text = $('textarea.diff-text').val();
var fileName = $('#file2-container div.file-name').text();
var filePath = $('#file2-container div.tooltip-text').text();
setText(text, fileName, 1, filePath);
$('#arrow-container').removeClass('arrow-edit');
$('.file-diff.2').removeClass('hidden');
$('textarea.diff-text').addClass('hidden');
$('.edit').removeClass('hidden');
$('.done').addClass('hidden');
});
$('textarea.diff-text').scroll(function () {
$('.file-diff.1').scrollTop($('textarea.diff-text').scrollTop());
$('.file-diff.2').scrollTop($('textarea.diff-text').scrollTop());
$('#arrow-container').scrollTop($('textarea.diff-text').scrollTop());
$('#plus-container').scrollTop($('textarea.diff-text').scrollTop());
});
for (i = 1; i < 3; i++) {
$('.choose-file.' + i).change(function() {
var i = $(this).attr('class').split(' ')[1];
@@ -35,7 +65,7 @@ $(document).ready(function() {
var fileName = $('input[type=file].' + i).val();
fileName = fileName.slice(12, fileName.length);
setTextFromFile(file, fileName, $fileArea, i - 1);
$('.file-diff-input.' + i).scrollTop(0);
$('.file-diff.' + i).scrollTop(0);
$('a.tooltip-text.' + i).text(fileName);
});
@@ -70,6 +100,9 @@ $(document).ready(function() {
var i = $(this).attr('class').split(' ')[1];
$('.file-diff.' + (i % 2 + 1)).scrollTop(
$('.file-diff.' + i).scrollTop());
$('#arrow-container').scrollTop($('.file-diff.' + i).scrollTop());
$('#plus-container').scrollTop($('.file-diff.' + i).scrollTop());
$('textarea.diff-text').scrollTop($('.file-diff.' + i).scrollTop());
});
}
@@ -106,7 +139,6 @@ $(document).ready(function() {
expandAllMatches();
});
$.ajaxSetup({
error: function(xhr) {
message = ajaxErrorMessage(xhr);
@@ -117,6 +149,35 @@ $(document).ready(function() {
});
});
function getText() {
var lines = $('.file-diff.2 div').children('.text');
var text = '';
for (var i = 0; i < lines.length; i++) {
if (!$(lines[i]).hasClass('hidden')) {
var line = $(lines[i]).children();
for (var j = 0; j < line.length; j++) {
if ($(lines[i]).hasClass('left')) {
if (!$(line[j]).hasClass('ins'))
text += $(line[j]).html();
} else {
if (!$(line[j]).hasClass('del'))
text += $(line[j]).html();
}
}
text += '\n';
}
}
text = escapeHtml(text);
return text;
}
function escapeHtml(text) {
var text = text.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&nbsp;/g, ' ');
return text;
}
function ajaxErrorMessage(xhr) {
message = 'Please enter a valid URL';
@@ -139,7 +200,7 @@ function ajaxErrorMessage(xhr) {
function setTextFromUrl() {
var url = $('.enter-url input#url').val();
if (!(url.slice(0, 3) == 'http')) {
if (!(url.slice(0, 4) == 'http')) {
url = 'http://' + url;
}
var urlSecs = url.split('/');
@@ -289,7 +350,8 @@ function computeDiff(file1, file2) {
setLineTypes();
setLineNums();
if (texts[0] != '' && texts[1] != '') {
setNumDiffs();
setNumDiffs(true);
setArrows();
createCollapsibleMatches();
}
}
@@ -343,7 +405,7 @@ function createHtmlLines(diffs) {
html2 += '</div><div>';
} while (line2 > line1) {
line1 += 1;
html2 += '</div><div>';
html1 += '</div><div>';
}
txt = '<span>' + text[i] + '</span>';
html1 += txt;
@@ -403,12 +465,47 @@ function setLineTypes() {
$('.file-diff > div:last-child').remove();
}
function isBlankLine(lineDiv) {
if ($(lineDiv).attr('class'))
var lineNum = $(lineDiv).attr('class').replace('blank ', '')
.replace('ins ', '')
.replace('del ', '')
.split(' ')[0];
return ( $(lineDiv).hasClass('blank') && !$(lineDiv).hasClass('fix') )
|| ( ($(lineDiv).children('.left.text').length > 0)
&& ($('.file-diff.1 .' + lineNum).hasClass('blank'))
)
|| ( ($(lineDiv).hasClass('blank') && $(lineDiv).hasClass('fix'))
&& ($(lineDiv).children('.left.text').length == 0)
)
|| $(lineDiv).hasClass('collapsed-num');
}
function setLineNums() {
files = [1, 2];
for (var j = 0; j < files.length; j++) {
lineNum = 1;
$('.file-diff.' + files[j] + ' > div').each(function() {
if (!$(this).hasClass('blank')) {
var realLine = 1;
for (var i = 0; i < files.length; i++) {
var lineNum = 1;
realLine = 1;
$('.file-diff.' + files[i] + ' > div').each(function() {
if (!isBlankLine(this)) {
$(this).html('<div class="text right">' + $(this).html() + '</div>');
$(this).prepend('<div class="lineNum">' + lineNum + '</div>');
lineNum += 1;
}
$(this).addClass('realLine-' + realLine);
realLine += 1;
});
}
}
function resetLineNums() {
var files = [1, 2];
$('.file-diff > div > div.lineNum').remove();
for (var i = 0; i < files.length; i++) {
var lineNum = 1;
$('.file-diff.' + files[i] + ' > div').each(function() {
if (!isBlankLine(this)) {
$(this).prepend('<div class="lineNum">' + lineNum + '</div>');
lineNum += 1;
}
@@ -416,35 +513,43 @@ function setLineNums() {
}
}
function setNumDiffs() {
var diffLines = numDiffLines();
var diffChunks = numDiffChunks();
$('#num-diffs').html('Different Lines: ' + diffLines
+ '<br>Different Chunks: ' + diffChunks);
}
function numDiffChunks() {
var files = [0, 1];
var numChunks = [0, 0];
for (var i = 0; i < files.length; i++) {
var cont = false;
var lines = $('.file-diff.' + (files[i] + 1) + ' div').children();
for (var j = 0; j < lines.length; j++) {
var $line = $(lines[j]).parent();
if ($line.hasClass('ins') ||
$line.hasClass('del') ||
$line.hasClass('blank')) {
if (!cont) {
cont = true;
numChunks[files[i]] += 1;
}
$line.addClass('chunk-' + numChunks[files[i]]);
} else {
cont = false;
function setArrows() {
var numChunks = 0;
var arrow = '<div class="arrow"></div>';
var cont = 0;
$('#arrow-container').html('');
var lines = $('.file-diff.1').children('div');
for (var j = 0; j < lines.length; j++) {
var $line = $(lines[j]);
if ($line.hasClass('ins') ||
$line.hasClass('del') ||
$line.hasClass('blank')) {
if (cont == 0) {
numChunks += 1;
}
cont += 1;
} else if (cont > 0) {
var mid = (cont / 2) | 0;
for (var k = 0; k < mid; k++)
$('#arrow-container').append(arrow);
$('#arrow-container').append('<div class="arrow visible '
+ 'chunk-' + numChunks + '"></div>');
$('#arrow-container').append('<div class="undo visible hidden '
+ 'chunk-' + numChunks + '"></div>');
for (var k = mid + 1; k < cont; k++)
$('#arrow-container').append(arrow);
cont = 0;
$('#arrow-container').append(arrow);
} else {
$('#arrow-container').append(arrow);
}
}
return Math.max(numChunks[0], numChunks[1]);
setArrowClicks();
}
function setNumDiffs(set) {
var diffChunks = numDiffChunks(set);
$('#num-diffs').html(diffChunks + ' differences');
}
function numDiffLines() {
@@ -452,9 +557,10 @@ function numDiffLines() {
var numDiffs = [0, 0];
for (var i = 0; i < files.length; i++) {
$('.file-diff.' + (files[i] + 1) + ' div').each(function(lineNum) {
if ($(this).hasClass('ins') ||
$(this).hasClass('del') ||
$(this).hasClass('blank')) {
if (( $(this).hasClass('ins') ||
$(this).hasClass('del') ||
$(this).hasClass('blank')
) && !$(this).hasClass('fix')) {
numDiffs[files[i]] += 1;
}
});
@@ -462,9 +568,53 @@ function numDiffLines() {
return Math.max(numDiffs[0], numDiffs[1])
}
function numDiffChunks(set) {
var files = [0, 1];
var numChunks = [0, 0];
for (var i = 0; i < files.length; i++) {
var cont = 0;
var lines = $('.file-diff.' + (files[i] + 1)).children('div');
for (var j = 0; j < lines.length; j++) {
var $line = $(lines[j]);
if (( $line.hasClass('ins') ||
$line.hasClass('del') ||
$line.hasClass('blank')
) && !$line.hasClass('fix')) {
if (cont == 0) {
numChunks[files[i]] += 1;
}
cont += 1;
if (set)
$line.addClass('chunk-' + numChunks[files[i]]);
} else if (cont > 0) {
cont = 0;
}
}
}
return Math.max(numChunks[0], numChunks[1]);
}
function setArrowClicks() {
$('#arrow-container div.arrow.visible').click(function () {
var chunkNum = $(this).attr('class').replace('arrow ', '')
.replace('visible ', '')
.split(' ')[0];
moveChunk(chunkNum);
});
$('#arrow-container div.undo.visible').click(function () {
var chunkNum = $(this).attr('class').replace('undo ', '')
.replace('visible ', '')
.split(' ')[0];
undoMoveChunk(chunkNum);
});
}
function createCollapsibleMatches() {
var lines1 = $('.file-diff.1').children('div');
var lines2 = $('.file-diff.2').children('div');
var arrows = $('#arrow-container').children('div');
var plusses = $('#plus-container').children('div');
var numContMatches = 0;
for (var i = 0; i < lines1.length; i++) {
if (!$(lines1[i]).hasClass('ins') &&
@@ -472,58 +622,125 @@ function createCollapsibleMatches() {
!$(lines1[i]).hasClass('blank')) {
numContMatches += 1;
} else {
collapse(lines1, lines2, numContMatches, i)
collapse(lines1, lines2, arrows, plusses, numContMatches, i)
numContMatches = 0;
}
}
collapse(lines1, lines2, numContMatches, lines1.length);
collapse(lines1, lines2, arrows, plusses, numContMatches, lines1.length);
$('.collapsed-num a').click(function () {
$('.collapsed-num > a').click(function () {
var collapsedNumClass = $(this).attr('class');
var $collapsedNum = $('div.' + collapsedNumClass);
expandSection($collapsedNum);
});
}
function collapse(lines1, lines2, numContMatches, i) {
function collapse(lines1, lines2, arrows, plusses, numContMatches, i) {
if (numContMatches > 10) {
var firstCol = i - numContMatches + 5;
var lastCol = i - 6;
var numCol = lastCol - firstCol + 1
var firstCol = i - numContMatches + 6;
var lastCol = i - 5;
var numCol = lastCol - firstCol;
var firstLine = firstCol + '-line';
for (var l = firstCol; l <= lastCol; l++) {
$(lines1[l]).addClass('hidden collapsible');
$(lines2[l]).addClass('hidden collapsible');
$(lines1[l]).addClass(firstLine);
$(lines2[l]).addClass(firstLine);
for (var l = firstCol; l < lastCol; l++) {
$(lines1[l]).addClass('hidden collapsible ' + firstLine);
$(lines2[l]).addClass('hidden collapsible ' + firstLine);
$(arrows[l]).addClass('hidden collapsible ' + firstLine);
$(plusses[l]).addClass('hidden collapsible ' + firstLine);
}
$(lines1[firstCol]).before('<div class="collapsed-num ' + firstLine + '">'
+ numCol + ' lines collapsed (<a class="'
+ firstLine + '">expand</a>)</div>');
+ numCol + ' lines collapsed (<a class="'
+ firstLine + '">expand</a>)</div>');
$(lines2[firstCol]).before('<div class="collapsed-num ' + firstLine + '">'
+ numCol + ' lines collapsed (<a class="'
+ firstLine + '">expand</a>)</div>');
+ numCol + ' lines collapsed (<a class="'
+ firstLine + '">expand</a>)</div>');
$(arrows[firstCol]).before('<div class="arrow collapsed-num '
+ firstLine + '"></div>');
$(plusses[firstCol]).addClass('minus');
$(plusses[firstCol]).before('<div class="plus ' + firstLine + '"></div>');
}
}
function moveChunk(chunkNum) {
var lines1 = $('.file-diff.1').children('div.' + chunkNum);
var lines2 = $('.file-diff.2').children('div.' + chunkNum);
for (var i = 0; i < lines1.length; i++) {
var realLineNum = $(lines1[i]).attr('class')
.replace('ins ', '')
.replace('del ', '')
.replace('blank ', '')
.split(' ')[0];
var text = '';
if ($('.file-diff.1 .' + realLineNum).children('.text.right').length > 0)
text = $('.file-diff.1 .' + realLineNum + ' > div.text').html();
var div = '<div class="left text">' + text + '</div>';
$('.file-diff.2 > .' + realLineNum + ' > .text.right').addClass('hidden');
$('.file-diff.2 > .' + realLineNum).append(div);
$('.file-diff.1 > .' + realLineNum).addClass('fix');
$('.file-diff.2 > .' + realLineNum).addClass('fix');
}
$('#arrow-container .arrow.' + chunkNum).addClass('hidden');
$('#arrow-container .undo.' + chunkNum).removeClass('hidden');
resetLineNums();
setNumDiffs();
var text = getText();
saveFile(text, 'file1.txt');
}
function undoMoveChunk(chunkNum) {
var lines1 = $('.file-diff.1').children('div.' + chunkNum);
var lines2 = $('.file-diff.2').children('div.' + chunkNum);
for (var i = 0; i < lines1.length; i++) {
var lineNum = $(lines1[i]).attr('class')
.replace('ins ', '')
.replace('del ', '')
.replace('blank ', '')
.replace('fix ', '')
.split(' ')[0];
$('.file-diff.2 > .' + lineNum + ' > .text.right').removeClass('hidden');
$('.file-diff.2 > .' + lineNum + ' > .left').remove();
$('.file-diff.1 > .' + lineNum).removeClass('fix');
$('.file-diff.2 > .' + lineNum).removeClass('fix');
}
$('#arrow-container .arrow.' + chunkNum).removeClass('hidden');
$('#arrow-container .undo.' + chunkNum).addClass('hidden');
resetLineNums();
setNumDiffs();
var text = getText();
saveFile(text, 'file1.txt');
}
function expandAllMatches() {
$('.file-diff > div.collapsible').removeClass('hidden');
$('.file-diff div.collapsed-num').addClass('hidden');
$('div.collapsible').removeClass('hidden');
$('div.collapsed-num').addClass('hidden');
$('div.plus').addClass('hidden');
}
function collapseAllMatches() {
$('.file-diff > div.collapsible').addClass('hidden');
$('.file-diff div.collapsed-num').removeClass('hidden');
$('div.collapsible').addClass('hidden');
$('div.collapsed-num').removeClass('hidden');
$('div.plus').removeClass('hidden');
}
function expandSection($collapsedNum) {
var classes = $collapsedNum.attr('class');
var c = classes.replace(/(?:^|\s)(collapsed-num)(?=\s|$)/g, '').split(' ');
c = c[1];
var c = classes.replace('collapsed-num ', '')
.replace('plus ', '')
.split(' ')[0];
$collapsedNum.addClass('hidden');
$('div.plus.' + c).addClass('hidden');
$('div.collapsible.' + c).removeClass('hidden');
}
function collapseSection($collapsedNum) {
var classes = $collapsedNum.attr('class');
var c = classes.replace('collapsible ', '')
.replace('minus ', '')
.split(' ')[0];
$collapsedNum.removeClass('hidden');
$('div.plus.' + c).removeClass('hidden');
$('div.collapsible.' + c).addClass('hidden');
}
function errorHandler(e) {
switch (e.code) {
case FileError.QUOTA_EXCEEDED_ERR:

View File

@@ -14,6 +14,8 @@
<div class="text">You are currently offline</div>
</div>
<div id="plus-container"></div>
<div id="file1-container">
<div class="input-container url">
<div class="button form-cover">Choose URL</div>
@@ -36,6 +38,8 @@
<div class="file-diff 1" id="drop-zone1"></div>
</div>
<div id="arrow-container"></div>
<div id="file2-container">
<div class="input-container url">
<div class="button form-cover">Choose URL</div>
@@ -54,14 +58,18 @@
<span class="pointer"></span>
</div>
</div>
<div class="button edit">Edit</div>
<div class="button done hidden">Done</div>
<br>
<div class="file-diff 2" id="drop-zone2"></div>
<textarea class="diff-text hidden"></textarea>
</div>
<br class="clear">
<div id="num-diffs"></div>
<br>
<div id="collapse-all" class="button">Collapse Matching Lines</div>
<div id="expand-all" class="button">Expand All Lines</div>

View File

@@ -1,17 +1,21 @@
{
"name": "Diff Tool",
"description": "Platform app that displays diff of two files.",
"manifest_version": 2,
"version": "1",
"name": "Diff Tool",
"description": "View diff of two files.",
"version": "0.1.2",
"offline_enabled" : true,
"app": {
"background": {
"scripts": ["js/background.js"]
}
},
"permissions": [
"experimental",
"unlimitedStorage",
"<all_urls>"
],
"icons": { "16": "img/icon_16.png", "128": "img/icon_128.png" }
"permissions": ["experimental",
"appWindow",
"unlimitedStorage",
"<all_urls>"
],
"icons": { "16": "img/icon_16.png",
"48": "img/icon_48.png",
"128": "img/icon_128.png"
}
}

View File

@@ -38,7 +38,7 @@ div.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/
.cm-s-lesser-dark span.cm-builtin { color: #ff9e59; }
.cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; }
.cm-s-lesser-dark span.cm-tag { color: #669199; }
.cm-s-lesser-dark span.cm-attribute {color: #00c;}
.cm-s-lesser-dark span.cm-attribute {color: #66c;}
.cm-s-lesser-dark span.cm-header {color: #a0a;}
.cm-s-lesser-dark span.cm-quote {color: #090;}
.cm-s-lesser-dark span.cm-hr {color: #999;}

View File

@@ -2,7 +2,6 @@ var newButton, openButton, saveButton;
var editor;
var fileEntry;
var hasWriteAccess;
var isCrOS = false;
function errorHandler(e) {
var msg = "";
@@ -42,7 +41,7 @@ function handleDocumentChange(title) {
mode = {name: "javascript", json: true};
modeName = "JavaScript (JSON)";
} else if (title.match(/.html$/)) {
mode = "htmlembedded";
mode = "htmlmixed";
modeName = "HTML";
} else if (title.match(/.css$/)) {
mode = "css";
@@ -87,18 +86,20 @@ function readFileIntoEditor(theFileEntry) {
function writeEditorToFile(theFileEntry) {
theFileEntry.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(e) {
handleDocumentChange(theFileEntry.fullPath);
console.log("Write completed.");
};
fileWriter.onerror = function(e) {
console.log("Write failed: " + e.toString());
};
var blob = new Blob([editor.getValue()]);
fileWriter.write(blob);
fileWriter.truncate(blob.size);
fileWriter.onwriteend = function() {
fileWriter.onwriteend = function(e) {
handleDocumentChange(theFileEntry.fullPath);
console.log("Write completed.");
};
fileWriter.write(blob);
}
}, errorHandler);
}
@@ -136,33 +137,46 @@ function handleSaveButton() {
if (fileEntry && hasWriteAccess) {
writeEditorToFile(fileEntry);
} else {
if (isCrOS) {
chrome.fileBrowserHandler.selectFile({ "suggestedName": "new_file.txt" },
function(selectInfo) {
setFile(selectInfo.entry, true);
handleSaveButton();
}
);
} else {
chrome.fileSystem.chooseFile({ type: 'saveFile' }, onChosenFileToSave);
}
chrome.fileSystem.chooseFile({ type: 'saveFile' }, onChosenFileToSave);
}
}
window.onload = function() {
// TODO: since chrome.fileSystem seems to be the future, this test should
// hinge on availablility of that API rather than absence of this one.
isCrOS = (typeof chrome.fileBrowserHandler != 'undefined');
function initContextMenu() {
chrome.contextMenus.removeAll(function() {
for (var snippetName in SNIPPETS) {
chrome.contextMenus.create({
title: snippetName,
id: snippetName,
contexts: ['all']
});
}
});
}
chrome.contextMenus.onClicked.addListener(function(info) {
// Context menu command wasn't meant for us.
if (!document.hasFocus()) {
return;
}
editor.replaceSelection(SNIPPETS[info.menuItemId]);
});
onload = function() {
initContextMenu();
newButton = document.getElementById("new");
openButton = document.getElementById("open");
saveButton = document.getElementById("save");
newButton.addEventListener("click", handleNewButton);
openButton.addEventListener("click", handleOpenButton);
saveButton.addEventListener("click", handleSaveButton);
editor = CodeMirror.fromTextArea(document.getElementById("editor"),
{ mode: {name: "javascript", json: true },
editor = CodeMirror(
document.getElementById("editor"),
{
mode: {name: "javascript", json: true },
lineNumbers: true,
theme: "lesser-dark",
extraKeys: {
@@ -171,12 +185,18 @@ window.onload = function() {
}
});
if (isCrOS) {
// file_browser_handlers aren't available for apps, grrr.
openButton.disabled = true;
} else {
// We don't appear to be running on CrOS. Use chrome.fileSystem instead.
openButton.addEventListener("click", handleOpenButton);
}
newFile();
onresize();
};
onresize = function() {
var container = document.getElementById('editor');
var containerWidth = container.offsetWidth;
var containerHeight = container.offsetHeight;
var scrollerElement = editor.getScrollerElement();
scrollerElement.style.width = containerWidth + 'px';
scrollerElement.style.height = containerHeight + 'px';
editor.refresh();
}

View File

@@ -2,13 +2,14 @@
<html>
<head>
<script type="text/javascript" src="editor.js"></script>
<script src="snippets.js"></script>
<script src="editor.js"></script>
<script src="cm/lib/codemirror.js"></script>
<script src="cm/mode/css/css.js"></script>
<script src="cm/mode/htmlembedded/htmlembedded.js"></script>
<script src="cm/mode/htmlmixed/htmlmixed.js"></script>
<script src="cm/mode/xml/xml.js"></script>
<script src="cm/mode/javascript/javascript.js"></script>
<script src="cm/mode/htmlmixed/htmlmixed.js"></script>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="cm/lib/codemirror.css">
@@ -21,11 +22,15 @@
<button id="new"> <img src="img/16x16/file_add.png"/>New </button>
<button id="open"><img src="img/16x16/file.png"/> Open </button>
<button id="save"><img src="img/16x16/diskette.png"/>Save </button>
</div>
<div class="info">Filename:&nbsp;<span id="title"></span></div>
<div><textarea id="editor" name="editor"></textarea></div>
<div class="info">Mode:&nbsp;<span id="mode"></span></div>
<div id="editor"></div>
<div class="info">
<label>Filename: </label><span id="title"></span>
<label>Mode: </label><span id="mode"></span>
</div>
</body>
</html>

View File

@@ -1,6 +1,6 @@
{
"name": "MiniCodeEdit",
"version": "0.1.10",
"version": "0.1.11",
"manifest_version": 2,
"description": "A very small code editor.",
"app": {
@@ -11,9 +11,9 @@
"permissions": [
"experimental",
"fileBrowserHandler",
"fileSystem",
"unlimitedStorage"
"unlimitedStorage",
"contextMenus"
],
"icons": {

View File

@@ -0,0 +1,8 @@
var SNIPPETS = {
"Hello World: Manifest": '{\n "manifest_version": 2,\n "name": "Hello World",\n "version": "0.0.1",\n "app": {\n "background": {\n "scripts": ["main.js"]\n }\n },\n "permissions": [\n "experimental"\n ]\n}\n',
"Hello World: main.js": "chrome.experimental.app.onLaunched.addListener(function() {\n chrome.appWindow.create('window.html', {\n width: 400,\n height: 400\n });\n})",
"Hello World: window.html": '<!DOCTYPE html>\n<html>\n <body>\n <h1>Hello World!</h1>\n </body>\n</html>',
"Hello World: window.html w/form": '<!DOCTYPE html>\n<html>\n <script src="window.js"></script>\n </head>\n <body> \n\n <form id="name-form">\n <input id="name-input" size="40">\n <input type="submit">\n </form>\n \n <h2>Hello <span id="output"></span></h2> \n </body>\n</html>',
"Hello World: window.js": "onload = function() {\n document.getElementById('name-form').onsubmit = function(e) {\n e.preventDefault();\n\n document.getElementById('output').innerHTML =\n document.getElementById('name-input').value;\n };\n};\n",
"Servo: onRead": "function onRead(readInfo) {\n var uint8View = new Uint8Array(readInfo.data);\n var value = uint8View[0] - '0'.charCodeAt(0);\n var rotation = value * 18.0;\n\n document.getElementById('image').style.webkitTransform =\n 'rotateZ(' + rotation + 'deg)';\n\n // Keep on reading.\n chrome.experimental.serial.read(connectionId, onRead);\n};"
};

View File

@@ -1,6 +1,7 @@
body {
margin: 2px;
margin: 0;
padding: 0;
overflow: hidden;
}
button {
@@ -9,9 +10,7 @@ button {
.CodeMirror {
margin: 0;
padding: 2px 0;
border-bottom: 1px solid #333;
border-top: 1px solid #333;
padding: 0;
}
.CodeMirror-scroll {
@@ -20,15 +19,32 @@ button {
overflow-x: auto;
}
#editor {
position: absolute;
top: 29px;
bottom: 24px;
left: 0;
right: 0;
background: #262626;
}
.info {
font-family: monospace;
white-space: nowrap;
position: absolute;
bottom: 0;
background: #eee;
padding: 2px;
height: 20px;
left: 0;
right: 0;
}
.info label {
font-weight: bold;
}
.buttons {
margin-bottom: 1em;
}
#editor {
display: none;
padding: 2px;
height: 25px;
}

View File

@@ -1,33 +1,25 @@
var connectionId = -1;
var onWrite = function(writeInfo) {
};
var setPosition = function(position) {
function setPosition(position) {
var buffer = new ArrayBuffer(1);
var uint8View = new Uint8Array(buffer);
uint8View[0] = 48 + position;
chrome.experimental.serial.write(connectionId, buffer, onWrite);
uint8View[0] = '0'.charCodeAt(0) + position;
chrome.experimental.serial.write(connectionId, buffer, function() {});
};
var onRead = function(readInfo) {
if (readInfo.bytesRead > 0) {
var uint8View = new Uint8Array(readInfo.data);
var charValue = uint8View[0];
if (charValue != 13 && charValue != 10) {
var value = uint8View[0] - 48;
var rotation = value * 18.0;
function onRead(readInfo) {
var uint8View = new Uint8Array(readInfo.data);
var value = uint8View[0] - '0'.charCodeAt(0);
var rotation = value * 18.0;
document.getElementById('image').style.webkitTransform =
'rotateZ(' + rotation + 'deg)';
}
}
document.getElementById('image').style.webkitTransform =
'rotateZ(' + rotation + 'deg)';
// Keep on reading.
chrome.experimental.serial.read(connectionId, onRead);
};
var onOpen = function(openInfo) {
function onOpen(openInfo) {
connectionId = openInfo.connectionId;
if (connectionId == -1) {
setStatus('Could not open');
@@ -36,13 +28,40 @@ var onOpen = function(openInfo) {
setStatus('Connected');
setPosition(0);
onRead({bytesRead: 0});
chrome.experimental.serial.read(connectionId, onRead);
};
function setStatus(status) {
document.getElementById('status').innerText = status;
}
function buildPortPicker(ports) {
var eligiblePorts = ports.filter(function(port) {
return !port.match(/[Bb]luetooth/);
});
var portPicker = document.getElementById('port-picker');
eligiblePorts.forEach(function(port) {
var portOption = document.createElement('option');
portOption.value = portOption.innerText = port;
portPicker.appendChild(portOption);
});
portPicker.onchange = function() {
if (connectionId != -1) {
chrome.experimental.serial.close(connectionId, openSelectedPort);
return;
}
openSelectedPort();
};
}
function openSelectedPort() {
var portPicker = document.getElementById('port-picker');
var selectedPort = portPicker.options[portPicker.selectedIndex].value;
chrome.experimental.serial.open(selectedPort, onOpen);
}
onload = function() {
var tv = document.getElementById('tv');
navigator.webkitGetUserMedia(
@@ -61,30 +80,7 @@ onload = function() {
};
chrome.experimental.serial.getPorts(function(ports) {
var eligiblePorts = ports.filter(function(port) {
return !port.match(/[Bb]luetooth/);
});
var portPicker = document.getElementById('port-picker');
eligiblePorts.forEach(function(port) {
var portOption = document.createElement('option');
portOption.value = portOption.innerText = port;
portPicker.appendChild(portOption);
});
portPicker.onchange = function() {
if (connectionId != -1) {
chrome.experimental.serial.close(connectionId, openSelectedPort);
return;
}
openSelectedPort();
};
function openSelectedPort() {
var selectedPort = portPicker.options[portPicker.selectedIndex].value;
chrome.experimental.serial.open(selectedPort, onOpen);
}
buildPortPicker(ports)
openSelectedPort();
});
};