From 4c27e23d807c8bb3ef70e223210ee33ecee40967 Mon Sep 17 00:00:00 2001 From: Matt Pass Date: Sat, 11 Oct 2014 13:12:57 +0100 Subject: [PATCH] Split pane, new functions and diff mode set up New vars for splitPane, debounce and editorFocusInstance added Split pane controls added and center themselves and can now trigger single and split pane views Editor functions added here for focus, blur, onkeyup, oncursoractivity, onchange and oninputread, can handle requests from either main or diff pane updateDiffs function added which will show differences between 2 panes using jsdifflib and markText updatePreviewWindow now it's own function too Many functions redone so they can also take requests from either main or diff panes, by using thisCM instead of cM getcMdiffInstance function also added Diff pane also updated on changing settings and switching tab --- lib/ice-coder.js | 609 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 451 insertions(+), 158 deletions(-) diff --git a/lib/ice-coder.js b/lib/ice-coder.js index 8f4be48..f2f35a7 100644 --- a/lib/ice-coder.js +++ b/lib/ice-coder.js @@ -51,11 +51,14 @@ var ICEcoder = { bugFilesSizesActual: [], // Array of actual sizes of bug files githubDiff: false, // Toggle for viewing GitHub/FM diff view githubAuthTokenSet: false, // Has the user set their GitHub token yet + splitPane: false, // Single or split pane editing + debounce: "", // Contains debounce timeout object + editorFocusInstance: "", // Name of editor instance that has focus ready: false, // Indicates if ICEcoder is ready for action // Set our aliases initAliases: function() { - var aliasArray = ["header","files", "fileOptions", "optionsFile", "optionsEdit", "optionsRemote", "optionsHelp", "filesFrame","editor","tabsBar","findBar","content","footer","nestValid","nestDisplay","charDisplay","byteDisplay"]; + var aliasArray = ["header","files", "fileOptions", "optionsFile", "optionsEdit", "optionsRemote", "optionsHelp", "filesFrame","editor","tabsBar","findBar","content","footer","nestValid","nestDisplay","splitPaneControls","charDisplay","byteDisplay"]; // Create our ID aliases for (var i=0;i -1 ? top.ICEcoder.prevLineDiff : top.ICEcoder.prevLine; + if (thisCMPrevLine != thisCM.getCursor().line && + thisCM.getLine(thisCMPrevLine) && + thisCM.getLine(thisCMPrevLine).length > 0 && + thisCM.getLine(thisCMPrevLine).replace(/\s/g, '').length == 0) { + thisCM.replaceRange("",{line: thisCMPrevLine, ch: 0},{line: thisCMPrevLine, ch: 1000000}); + } + }, + + // On change + cMonChange: function(thisCM,cMinstance,changeObj) { + var filepath, filename, fileExt; + + // If we're not loading the file, it's a change, so update tab + if (!top.ICEcoder.loadingFile) { + top.ICEcoder.redoTabHighlight(top.ICEcoder.selectedTab); + } + top.ICEcoder.getCaretPosition(); + top.ICEcoder.dontUpdateNest = false; + top.ICEcoder.updateCharDisplay(); + top.ICEcoder.updateByteDisplay(); + top.ICEcoder.updateNestingIndicator(); + if (top.ICEcoder.findMode) { + top.ICEcoder.results.splice(top.ICEcoder.findResult,1); + top.document.getElementById('results').innerHTML = top.ICEcoder.results.length + " " + top.t['results']; + top.ICEcoder.findMode = false; + } + filepath = top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1]; + if (filepath) { + filename = filepath.substr(filepath.lastIndexOf("/")+1); + fileExt = filename.substr(filename.lastIndexOf(".")+1); + for (var i=changeObj.from.line; i-1 ? "brace" : "xml" ,null ,"+" ,"-", true, thisCM, i); + } + if (changeObj.text[0] == "}" || changeObj.removed && changeObj.removed[0] == "}") { + cursor = thisCM.getSearchCursor("{",thisCM.getCursor(),false); + cursor.findPrevious(); + for (var i=cursor.from().line; i-1 ? "brace" : "xml" ,null ,"+" ,"-", true, thisCM, i); + } + } + } + if (top.ICEcoder.splitPane) { + top.ICEcoder.updateDiffs(); + } + // Update HTML edited files live + if (filepath && top.ICEcoder.previewWindow.location) { + top.ICEcoder.updatePreviewWindow(thisCM,filepath,filename,fileExt); + } + // Update the title tag to indicate any changes + top.ICEcoder.indicateChanges(); + }, + + // On input read + cMonInputRead: function(thisCM,cMinstance) { + if (top.ICEcoder.autoComplete == "keypress" && top.ICEcoder.codeAssist) { + clearTimeout(top.ICEcoder.debounce); + if (!thisCM.state.completionActive) { + top.ICEcoder.debounce = setTimeout(function() { + CodeMirror.commands.autocomplete(thisCM); + },200); + } + } + }, + + updateDiffs: function() { + var cM, cMdiff, mainText, diffText, sm, opcodes, cMmarks, markColor; + + cM = top.ICEcoder.getcMInstance(); + cMdiff = top.ICEcoder.getcMdiffInstance(); + + // Get the baseText and newText values from the two textboxes, and split them into lines + mainText = difflib.stringAsLines(cM.getValue()); + diffText = difflib.stringAsLines(cMdiff.getValue()); + + // Create a SequenceMatcher instance that diffs the two sets of lines + sm = new difflib.SequenceMatcher(mainText, diffText); + + // Get the opcodes from the SequenceMatcher instance + // Opcodes is a list of 3-tuples describing what changes should be made to the base text in order to yield the new text + opcodes = sm.get_opcodes(); + + cMmarks = cM.getAllMarks(); + for (var i=0; i -1) { + top.ICEcoder.previewWindow.document.documentElement.innerHTML = thisCM.getValue(); + } else if (["md"].indexOf(fileExt) > -1) { + top.ICEcoder.previewWindow.document.documentElement.innerHTML = mmd(thisCM.getValue()); + } + } else if (["css"].indexOf(fileExt) > -1) { + if (top.ICEcoder.previewWindow.document.documentElement.innerHTML.indexOf(filename) > -1) { + var css = thisCM.getValue(); + var style = document.createElement('style'); + style.type = 'text/css'; + style.id = "ICEcoder"+filepath.replace(/\//g,"_"); + if (style.styleSheet){ + style.styleSheet.cssText = css; + } else { + style.appendChild(document.createTextNode(css)); + } + if (top.ICEcoder.previewWindow.document.getElementById(style.id)) { + top.ICEcoder.previewWindow.document.documentElement.removeChild(top.ICEcoder.previewWindow.document.getElementById(style.id)); + } + top.ICEcoder.previewWindow.document.documentElement.appendChild(style); + } + } + // Do the pesticide plugin if it exists + try {top.ICEcoder.doPesticide();} catch(err) {}; + }, + // Clean up our loaded code contentCleanUp: function() { - var cM, content; + var cM, cMdiff, thisCM, content; // Replace any temp /textarea value cM = ICEcoder.getcMInstance(); - content = cM.getValue(); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + content = thisCM.getValue(); content = content.replace(//g,'<\/textarea>'); // Then set the content in the editor & clear the history - cM.setValue(content); - cM.clearHistory(); - top.ICEcoder.savedPoints[top.ICEcoder.selectedTab-1] = cM.changeGeneration(); + thisCM.setValue(content); + thisCM.clearHistory(); + top.ICEcoder.savedPoints[top.ICEcoder.selectedTab-1] = thisCM.changeGeneration(); }, // Undo last change undo: function() { - var cM; + var cM, cMdiff, thisCM; cM = ICEcoder.getcMInstance(); - cM.undo(); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + thisCM.undo(); }, // Redo change redo: function() { - var cM; + var cM, cMdiff, thisCM; cM = ICEcoder.getcMInstance(); - cM.redo(); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + thisCM.redo(); }, // Indent more/less indent: function(moreLess) { - var cM; + var cM, cMdiff, thisCM; cM = ICEcoder.getcMInstance(); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; if (moreLess=="more") { - top.ICEcoder.content.contentWindow.CodeMirror.commands.indentMore(cM); + top.ICEcoder.content.contentWindow.CodeMirror.commands.indentMore(thisCM); } else { - top.ICEcoder.content.contentWindow.CodeMirror.commands.indentLess(cM); + top.ICEcoder.content.contentWindow.CodeMirror.commands.indentLess(thisCM); } }, // Move current line up/down moveLines: function(dir) { - var cM, lineStart, lineEnd, swapLineNo, swapLine; + var cM, cMdiff, thisCM, lineStart, lineEnd, swapLineNo, swapLine; cM = top.ICEcoder.getcMInstance(); + cMdiff = top.ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; // Get start & end lines plus the line we'll swap with - lineStart = cM.getCursor('start'); - lineEnd = cM.getCursor('end'); + lineStart = thisCM.getCursor('start'); + lineEnd = thisCM.getCursor('end'); if (dir=="up" && lineStart.line>0) {swapLineNo = lineStart.line-1} - if (dir=="down" && lineEnd.line=lineStart.line; i--) { - cM.replaceRange(cM.getLine(i),{line:i+1,ch:0},{line:i+1,ch:1000000}); + thisCM.replaceRange(thisCM.getLine(i),{line:i+1,ch:0},{line:i+1,ch:1000000}); } } // Now swap our final line with the swap line to complete the move - cM.replaceRange(swapLine,{line: dir=="up" ? lineEnd.line : lineStart.line, ch: 0},{line: dir=="up" ? lineEnd.line : lineStart.line, ch:1000000}); + thisCM.replaceRange(swapLine,{line: dir=="up" ? lineEnd.line : lineStart.line, ch: 0},{line: dir=="up" ? lineEnd.line : lineStart.line, ch:1000000}); // Finally set the moved selection - cM.setSelection( + thisCM.setSelection( {line: lineStart.line+(dir=="up" ? -1 : 1), ch: lineStart.ch}, {line: lineEnd.line+(dir=="up" ? -1 : 1), ch: lineEnd.ch} ); @@ -271,46 +472,56 @@ var ICEcoder = { // Highlight specified line highlightLine: function(line) { - var cM; + var cM, cMdiff, thisCM; cM = top.ICEcoder.getcMInstance(); - cM.setSelection({line:line,ch:0}, {line:line,ch:cM.lineInfo(line).text.length}); + cMdiff = top.ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + thisCM.setSelection({line:line,ch:0}, {line:line,ch:thisCM.lineInfo(line).text.length}); }, // Focus the editor - focus: function() { - var cM; + focus: function(diff) { + var cM, cMdiff, thisCM; if (!(/iPhone|iPad|iPod/i.test(navigator.userAgent))) { cM = top.ICEcoder.getcMInstance(); - if (cM) { - cM.focus(); + cMdiff = top.ICEcoder.getcMdiffInstance(); + thisCM = diff ? cMdiff : cM; + if (thisCM) { + thisCM.focus(); } } }, // Go to a specific line number goToLine: function(lineNo) { - var cM; + var cM, cMdiff, thisCM; cM = ICEcoder.getcMInstance(); - cM.setCursor(lineNo ? lineNo-1 : top.get('goToLineNo').value-1); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + + thisCM.setCursor(lineNo ? lineNo-1 : top.get('goToLineNo').value-1); top.ICEcoder.focus(); return false; }, // Comment/uncomment line or selected range on keypress lineCommentToggle: function() { - var cM, cursorPos, linePos, lineContent, lCLen, adjustCursor; + var cM, cMdiff, thisCM, cursorPos, linePos, lineContent, lCLen, adjustCursor; cM = ICEcoder.getcMInstance(); - cursorPos = cM.getCursor().ch; - linePos = cM.getCursor().line; - lineContent = cM.getLine(linePos); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + + cursorPos = thisCM.getCursor().ch; + linePos = thisCM.getCursor().line; + lineContent = thisCM.getLine(linePos); lCLen = lineContent.length; adjustCursor = 2; - ICEcoder.lineCommentToggleSub(cM, cursorPos, linePos, lineContent, lCLen, adjustCursor); + ICEcoder.lineCommentToggleSub(thisCM, cursorPos, linePos, lineContent, lCLen, adjustCursor); }, // Highlight or hide block upon roll over/out of nest positions @@ -388,116 +599,130 @@ var ICEcoder = { // Wrap our selected text/cursor with tags tagWrapper: function(tag) { - var cM, tagStart, tagEnd, startLine, endLine; + var cM, cMdiff, thisCM, tagStart, tagEnd, startLine, endLine; cM = ICEcoder.getcMInstance(); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; tagStart = tag; tagEnd = tag; if (tag=='div') { - startLine = cM.getCursor('start').line; - endLine = cM.getCursor().line; - cM.operation(function() { - cM.replaceSelection("
\n"+cM.getSelection()+"\n
","around"); + startLine = thisCM.getCursor('start').line; + endLine = thisCM.getCursor().line; + thisCM.operation(function() { + thisCM.replaceSelection("
\n"+thisCM.getSelection()+"\n
","around"); for (var i=startLine+1; i<=endLine+1; i++) { - cM.indentLine(i); + thisCM.indentLine(i); } - cM.indentLine(endLine+2,'prev'); - cM.indentLine(endLine+2,'subtract'); + thisCM.indentLine(endLine+2,'prev'); + thisCM.indentLine(endLine+2,'subtract'); }); } else { if ( ['p','a','b','i','strong','em','h1','h2','h3','li'].indexOf(tag)>-1 && - cM.getSelection().substr(0,tag.length+1) == "<"+tagStart && - cM.getSelection().substr(-(tag.length+3)) == "") { + thisCM.getSelection().substr(0,tag.length+1) == "<"+tagStart && + thisCM.getSelection().substr(-(tag.length+3)) == "") { // Undo wrapper - cM.replaceSelection(cM.getSelection().substr(cM.getSelection().indexOf(">")+1,cM.getSelection().length-cM.getSelection().indexOf(">")-1-tag.length-3),"around"); + thisCM.replaceSelection(thisCM.getSelection().substr(thisCM.getSelection().indexOf(">")+1,thisCM.getSelection().length-thisCM.getSelection().indexOf(">")-1-tag.length-3),"around"); } else { if (tag=='a') {tagStart='a href=""';} // Do wrapper - cM.replaceSelection("<"+tagStart+">"+cM.getSelection()+"","around"); - if (tag=='a') {cM.setCursor({line:cM.getCursor('start').line,ch:cM.getCursor('start').ch+9})} + thisCM.replaceSelection("<"+tagStart+">"+thisCM.getSelection()+"","around"); + if (tag=='a') {thisCM.setCursor({line:thisCM.getCursor('start').line,ch:thisCM.getCursor('start').ch+9})} } } }, // Add a line break at end of current or specified line addLineBreakAtEnd: function(line) { - var cM; + var cM,cMdiff, thisCM; cM = ICEcoder.getcMInstance(); - if (!line) {line = cM.getCursor().line}; - cM.replaceRange(cM.getLine(line)+"
",{line:line,ch:0},{line:line,ch:1000000}); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + if (!line) {line = thisCM.getCursor().line}; + thisCM.replaceRange(thisCM.getLine(line)+"
",{line:line,ch:0},{line:line,ch:1000000}); }, // Insert a line before and auto-indent insertLineBefore: function(line) { - var cM; + var cM, cMdiff, thisCM; cM = ICEcoder.getcMInstance(); - if (!line) {line = cM.getCursor().line}; - cM.operation(function() { - cM.replaceRange("\n"+cM.getLine(line),{line:line,ch:0},{line:line,ch:1000000}); - cM.setCursor({line: cM.getCursor().line-1, ch: 0}); - cM.execCommand('indentAuto'); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + if (!line) {line = thisCM.getCursor().line}; + thisCM.operation(function() { + thisCM.replaceRange("\n"+thisCM.getLine(line),{line:line,ch:0},{line:line,ch:1000000}); + thisCM.setCursor({line: thisCM.getCursor().line-1, ch: 0}); + thisCM.execCommand('indentAuto'); }); }, // Insert a line after and auto-indent insertLineAfter: function(line) { - var cM; + var cM, cMdiff, thisCM; cM = ICEcoder.getcMInstance(); - if (!line) {line = cM.getCursor().line}; - cM.operation(function() { - cM.replaceRange(cM.getLine(line)+"\n",{line:line,ch:0},{line:line,ch:1000000}); - cM.execCommand('indentAuto'); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + if (!line) {line = thisCM.getCursor().line}; + thisCM.operation(function() { + thisCM.replaceRange(thisCM.getLine(line)+"\n",{line:line,ch:0},{line:line,ch:1000000}); + thisCM.execCommand('indentAuto'); }); }, // Duplicate line duplicateLines: function(line) { - var cM, ch, lineExtra, userSelStart, userSelEnd, lineBreak; + var cM, cMdiff, thisCM, ch, lineExtra, userSelStart, userSelEnd, lineBreak; cM = ICEcoder.getcMInstance(); - if (!line && cM.somethingSelected()) { - userSelStart = cM.getCursor('start'); - userSelEnd = cM.getCursor('end'); - lineExtra = userSelStart.line != userSelEnd.line && userSelEnd.ch == cM.getLine(userSelEnd.line).length ? "\n" : ""; - cM.replaceSelection(cM.getSelection()+lineExtra+cM.getSelection(), "end"); - cM.setSelection(userSelStart, userSelEnd); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + if (!line && thisCM.somethingSelected()) { + userSelStart = thisCM.getCursor('start'); + userSelEnd = thisCM.getCursor('end'); + lineExtra = userSelStart.line != userSelEnd.line && userSelEnd.ch == thisCM.getLine(userSelEnd.line).length ? "\n" : ""; + thisCM.replaceSelection(thisCM.getSelection()+lineExtra+thisCM.getSelection(), "end"); + thisCM.setSelection(userSelStart, userSelEnd); } else { - if (!line) {line = cM.getCursor().line}; - ch = cM.getCursor().ch; - cM.replaceRange(cM.getLine(line)+"\n"+cM.getLine(line),{line:line,ch:0},{line:line,ch:1000000}); - cM.setCursor(line+1,ch); + if (!line) {line = thisCM.getCursor().line}; + ch = thisCM.getCursor().ch; + thisCM.replaceRange(thisCM.getLine(line)+"\n"+thisCM.getLine(line),{line:line,ch:0},{line:line,ch:1000000}); + thisCM.setCursor(line+1,ch); } }, // Remove line removeLines: function(line) { - var cM, ch; + var cM, cMdiff, thisCM, ch; cM = ICEcoder.getcMInstance(); - if (!line && cM.somethingSelected()) { - cM.replaceSelection("","end"); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + if (!line && thisCM.somethingSelected()) { + thisCM.replaceSelection("","end"); } else { - if (!line) {line = cM.getCursor().line}; - ch = cM.getCursor().ch; - cM.execCommand('deleteLine'); - cM.setCursor(line-1,ch); + if (!line) {line = thisCM.getCursor().line}; + ch = thisCM.getCursor().ch; + thisCM.execCommand('deleteLine'); + thisCM.setCursor(line-1,ch); } }, // Jump to and highlight the function definition current token jumpToDefinition: function() { - var cM, tokenString, defVars; + var cM, cMdiff, thisCM, tokenString, defVars; cM = ICEcoder.getcMInstance(); - tokenString = cM.getTokenAt(cM.getCursor()).string; + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + tokenString = thisCM.getTokenAt(thisCM.getCursor()).string; - if (cM.somethingSelected() && top.ICEcoder.origCurorPos) { - cM.setCursor(top.ICEcoder.origCurorPos); + if (thisCM.somethingSelected() && top.ICEcoder.origCurorPos) { + thisCM.setCursor(top.ICEcoder.origCurorPos); } else { - top.ICEcoder.origCurorPos = cM.getCursor(); + top.ICEcoder.origCurorPos = thisCM.getCursor(); defVars = [ "var "+tokenString, "function "+tokenString, @@ -518,32 +743,41 @@ var ICEcoder = { // Autocomplete autocomplete: function() { - var cM; + var cM, cMdiff, thisCM; cM = ICEcoder.getcMInstance(); - top.ICEcoder.content.contentWindow.CodeMirror.commands.autocomplete(cM); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + top.ICEcoder.content.contentWindow.CodeMirror.commands.autocomplete(thisCM); }, // Paste a URL, locally or absolutely if CTRL/Cmd key down pasteURL: function(url) { - var cM; + var cM, cMdiff, thisCM; - cM = ICEcoder.getcMInstance(); + cM = top.ICEcoder.getcMInstance(); + cMdiff = top.ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; if(top.ICEcoder.draggingWithKey == "CTRL") { url = window.location.protocol + "//" + window.location.hostname + url; } - cM.replaceSelection(url,"around"); + thisCM.replaceSelection(url,"around"); }, // Search for selected text online searchForSelected: function() { + var cM, cMdiff, thisCM; + + cM = top.ICEcoder.getcMInstance(); + cMdiff = top.ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; if (top.ICEcoder.caretLocType) { - if (top.ICEcoder.getcMInstance().getSelection() != "") { + if (thisCM.getSelection() != "") { var searchPrefix = top.ICEcoder.caretLocType.toLowerCase()+" "; if (top.ICEcoder.caretLocType=="Content") { searchPrefix = ""; } - window.open("http://www.google.com/#output=search&q="+searchPrefix+top.ICEcoder.getcMInstance().getSelection()); + window.open("http://www.google.com/#output=search&q="+searchPrefix+thisCM.getSelection()); } else { top.ICEcoder.message(top.t['No text selected...']); } @@ -1176,7 +1410,7 @@ var ICEcoder = { // Find & replace text according to user selections findReplace: function(findString,resultsOnly,buttonClick) { - var find, replace, results, cM, content, scrollBarVisible, cursor, avgBlockH, addPadding, rBlocks, blockColor, replaceQS, targetQS, filesQS; + var find, replace, results, cM, cMdiff, thisCM, content, scrollBarVisible, cursor, avgBlockH, addPadding, rBlocks, blockColor, replaceQS, targetQS, filesQS; // Determine our find & replace strings and results display find = findString.toLowerCase(); @@ -1185,20 +1419,22 @@ var ICEcoder = { // If we have something to find in currrent document cM = ICEcoder.getcMInstance(); - if (cM && find.length>0 && document.findAndReplace.target.value==top.t['this document']) { - content = cM.getValue().toLowerCase(); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + if (thisCM && find.length>0 && document.findAndReplace.target.value==top.t['this document']) { + content = thisCM.getValue().toLowerCase(); // Find & replace the next instance, or all? if (document.findAndReplace.connector.value==top.t['and'] && buttonClick) { - if (document.findAndReplace.replaceAction.value==top.t['replace'] && cM.getSelection().toLowerCase()==find) { - cM.replaceSelection(replace,"around"); + if (document.findAndReplace.replaceAction.value==top.t['replace'] && thisCM.getSelection().toLowerCase()==find) { + thisCM.replaceSelection(replace,"around"); } else if (document.findAndReplace.replaceAction.value==top.t['replace all']) { var rExp = new RegExp(find,"gi"); - cM.setValue(cM.getValue().replace(rExp,replace)); + thisCM.setValue(thisCM.getValue().replace(rExp,replace)); } } // Get the content again, as it might of changed - content = cM.getValue().toLowerCase(); + content = thisCM.getValue().toLowerCase(); if (!top.ICEcoder.findMode||find!=top.ICEcoder.lastsearch) { ICEcoder.results = []; ICEcoder.resultsLines = []; @@ -1206,8 +1442,8 @@ var ICEcoder = { for (var i=0;i0) { // Detect if we have a scrollbar - scrollBarVisible = cM.getScrollInfo().height > cM.getScrollInfo().clientHeight; + scrollBarVisible = thisCM.getScrollInfo().height > thisCM.getScrollInfo().clientHeight; // Show results only if (resultsOnly) { @@ -1229,7 +1465,7 @@ var ICEcoder = { // Find our cursor position relative to results ICEcoder.findResult = 0; for (var i=0;i-1 ? cM.getCursor().line+1 == i ? "#b00" : "#888" : "transparent" + for (var i=1; i<=thisCM.lineCount(); i++) { + blockColor = ICEcoder.resultsLines.indexOf(i)>-1 ? thisCM.getCursor().line+1 == i ? "#b00" : "#888" : "transparent" rBlocks += '
'; } top.ICEcoder.content.contentWindow.document.getElementById('resultsBar').innerHTML = rBlocks; @@ -1312,14 +1548,17 @@ var ICEcoder = { // Work out the nesting depth location on demand and update our display if required getNestLocation: function(updateNestDisplay) { - var cM, nestCheck, state, cx, startPos, fileName; + var cM, cMdiff, thisCM, nestCheck, state, cx, startPos, fileName; cM = ICEcoder.getcMInstance(); - if (cM) { - nestCheck = cM.getValue(); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + + if (thisCM) { + nestCheck = thisCM.getValue(); // Get the token state at our cursor - state = cM.getTokenAt(cM.getCursor()).state; + state = thisCM.getTokenAt(thisCM.getCursor()).state; cx = false; // XML @@ -1360,14 +1599,17 @@ var ICEcoder = { // Get the caret position getCaretPosition: function() { - var cM, line, ch, chPos; + var cM, cMdiff, thisCM, line, ch, chPos; cM = ICEcoder.getcMInstance(); - line = cM.getCursor().line; - ch = cM.getCursor().ch; + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + + line = thisCM.getCursor().line; + ch = thisCM.getCursor().ch; chPos = 0; for (var i=0;i -1 ? cMdiff : cM; ICEcoder.caretLocationType(); - ICEcoder.charDisplay.innerHTML = ICEcoder.caretLocType + ", Line: " + (cM.getCursor().line+1) + ", Char: " + cM.getCursor().ch; + ICEcoder.charDisplay.innerHTML = ICEcoder.caretLocType + ", Line: " + (thisCM.getCursor().line+1) + ", Char: " + thisCM.getCursor().ch; }, // Update the byte display updateByteDisplay: function() { - ICEcoder.byteDisplay.innerHTML = ICEcoder.getcMInstance().getValue().length.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " bytes"; + var cM, cMdiff, thisCM; + + cM = ICEcoder.getcMInstance(); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + ICEcoder.byteDisplay.innerHTML = thisCM.getValue().length.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + " bytes"; }, // Toggle the char/byte display @@ -1412,6 +1661,21 @@ var ICEcoder = { ]; }, + // Determine the CodeMirror instance we're using + getcMdiffInstance: function(tab) { + return top.ICEcoder.content.contentWindow[ + (// target specific tab + !isNaN(tab) + ? 'cM'+ICEcoder.cMInstances[tab-1] + // new tab or selected tab + : tab=="new"||(tab!="new" && ICEcoder.openFiles.length>0) + ? 'cM'+ICEcoder.cMInstances[ICEcoder.selectedTab-1] + // fallback to first tab + : 'cM1') + + 'diff' + ]; + }, + // Get the mouse position getMouseXY: function(e,area) { var tempX, tempY; @@ -1475,14 +1739,17 @@ var ICEcoder = { // Show a CSS color block next to our text cursor cssColorPreview: function() { - var cM, string, rx, match, oldBlock, newBlock; + var cM, cMdiff, thisCM, string, rx, match, oldBlock, newBlock; cM = ICEcoder.getcMInstance(); - if (cM) { - string = cM.getLine(cM.getCursor().line); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + + if (thisCM) { + string = thisCM.getLine(thisCM.getCursor().line); rx = /(#[\da-f]{3}(?:[\da-f]{3})?\b|\b(?:rgb|hsl)a?\([\s\d%,.-]+\)|\b[a-z]+\b)/gi; - while((match = rx.exec(string)) && cM.getCursor().ch > match.index+match[0].length); + while((match = rx.exec(string)) && thisCM.getCursor().ch > match.index+match[0].length); oldBlock = top.get('content').contentWindow.document.getElementById('cssColor'); if (oldBlock) {oldBlock.parentNode.removeChild(oldBlock)}; @@ -1498,7 +1765,7 @@ var ICEcoder = { newBlock.onclick = function() {top.ICEcoder.showColorPicker(match[0])}; if (newBlock.style.backgroundColor=="") {newBlock.style.display = "none"}; top.get('header').appendChild(newBlock); - cM.addWidget(cM.getCursor(), top.get('cssColor'), true); + thisCM.addWidget(thisCM.getCursor(), top.get('cssColor'), true); } } }, @@ -1574,11 +1841,13 @@ var ICEcoder = { // Insert new color value insertColorValue: function(color) { - var cM, cursor; + var cM, cMdiff, thisCM, cursor; cM = ICEcoder.getcMInstance(); - cursor = cM.getTokenAt(cM.getCursor()); - cM.replaceRange(color,{line:cM.getCursor().line,ch:cursor.start},{line:cM.getCursor().line,ch:1000000}); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + cursor = thisCM.getTokenAt(thisCM.getCursor()); + thisCM.replaceRange(color,{line:thisCM.getCursor().line,ch:cursor.start},{line:thisCM.getCursor().line,ch:1000000}); }, // Change opacity of the file manager icons @@ -1844,10 +2113,18 @@ var ICEcoder = { top.ICEcoder.indentWithTabs = indentWithTabs; top.ICEcoder.indentSize = indentSize; for (var i=0;i0) { - var cM, filepath, filename, fileExt; + var cM, cMdiff, thisCM, filepath, filename, fileExt; filepath = top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1]; filename = filepath.substr(filepath.lastIndexOf("/")+1); fileExt = filename.substr(filename.lastIndexOf(".")+1); cM = ICEcoder.getcMInstance(); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; top.ICEcoder.previewWindow = window.open(filepath,"previewWindow"); if (["md"].indexOf(fileExt) > -1) { - top.ICEcoder.previewWindow.onload = function() {top.ICEcoder.previewWindow.document.documentElement.innerHTML = mmd(cM.getValue())}; + top.ICEcoder.previewWindow.onload = function() {top.ICEcoder.previewWindow.document.documentElement.innerHTML = mmd(thisCM.getValue())}; } else { top.ICEcoder.previewWindow.onload = function() { // Do the pesticide plugin if it exists @@ -2093,16 +2372,18 @@ var ICEcoder = { // Print code of current tab printCode: function() { - var cM, printIFrame; + var cM, cMdiff, thisCM, printIFrame; cM = top.ICEcoder.getcMInstance(); + cMdiff = top.ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; printIFrame = top.ICEcoder.filesFrame.contentWindow.frames['fileControl']; // Print page content injected into iFrame, escaped with pre and xssClean - printIFrame.window.document.body.innerHTML = 'ICEcoder code output
'+top.ICEcoder.xssClean(cM.getValue())+'
'; + printIFrame.window.document.body.innerHTML = 'ICEcoder code output
'+top.ICEcoder.xssClean(thisCM.getValue())+'
'; printIFrame.focus(); printIFrame.print(); // Focus back on code - cM.focus(); + thisCM.focus(); }, // Update the title tag to indicate any changes @@ -2128,26 +2409,32 @@ var ICEcoder = { // Change tabs by switching visibility of instances switchTab: function(newTab,noFocus) { - var cM; + var cM, cMdiff, thisCM; // Identify tab that's currently selected & get the instance ICEcoder.selectedTab = newTab; cM = ICEcoder.getcMInstance(); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; - if (cM) { + if (thisCM) { // Switch mode to HTML, PHP, CSS etc ICEcoder.switchMode(); // Set all cM instances to be hidden, then make our selected instance visible for (var i=0;i -1 ? true : false); } return false; @@ -2718,13 +3007,15 @@ var ICEcoder = { // Add snippet code completion addSnippet: function() { - var cM, lineNo, whiteSpace, content; + var cM, cMdiff, thisCM, lineNo, whiteSpace, content; // Get line content after trimming whitespace cM = ICEcoder.getcMInstance(); - lineNo = cM.getCursor().line; - whiteSpace = cM.getLine(lineNo).length - cM.getLine(lineNo).replace(/^\s\s*/, '').length; - content = cM.getLine(lineNo).slice(whiteSpace); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + lineNo = thisCM.getCursor().line; + whiteSpace = thisCM.getLine(lineNo).length - thisCM.getLine(lineNo).replace(/^\s\s*/, '').length; + content = thisCM.getLine(lineNo).slice(whiteSpace); // function snippet if (content.slice(0,8)=="function") { top.ICEcoder.doSnippet('function','function VAR() {\nINDENT\tCURSOR\nINDENT}'); @@ -2739,26 +3030,28 @@ var ICEcoder = { // Action a snippet doSnippet: function(tgtString,replaceString) { - var cM, lineNo, lineContents, remainder, strPos, replacedLine, whiteSpace, curPos, sPos, lineNoCount; + var cM, cMdiff, thisCM, lineNo, lineContents, remainder, strPos, replacedLine, whiteSpace, curPos, sPos, lineNoCount; // Get line contents - cM = top.ICEcoder.getcMInstance(); - lineNo = cM.getCursor().line; - lineContents = cM.getLine(lineNo); + cM = ICEcoder.getcMInstance(); + cMdiff = ICEcoder.getcMdiffInstance(); + thisCM = top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? cMdiff : cM; + lineNo = thisCM.getCursor().line; + lineContents = thisCM.getLine(lineNo); // Find our target string if (lineContents.indexOf(tgtString)>-1) { // Get text on the line from our target to the end - remainder = cM.getLine(lineNo); + remainder = thisCM.getLine(lineNo); strPos = remainder.indexOf(tgtString); remainder = remainder.slice(remainder.indexOf(tgtString)+tgtString.length+1); // Replace the function name if any replaceString = replaceString.replace(/VAR/g,remainder); // Get replaced string from start to our strPos - replacedLine = cM.getLine(lineNo).slice(0,strPos); + replacedLine = thisCM.getLine(lineNo).slice(0,strPos); // Trim whitespace from start - whiteSpace = cM.getLine(lineNo).length - cM.getLine(lineNo).replace(/^\s\s*/, '').length; - whiteSpace = cM.getLine(lineNo).slice(0,whiteSpace); + whiteSpace = thisCM.getLine(lineNo).length - thisCM.getLine(lineNo).replace(/^\s\s*/, '').length; + whiteSpace = thisCM.getLine(lineNo).slice(0,whiteSpace); // Replace indent with whatever whitespace we have replaceString = replaceString.replace(/INDENT/g,whiteSpace); replacedLine += replaceString; @@ -2773,10 +3066,10 @@ var ICEcoder = { } } // Clear the cursor string and set the cursor there - cM.replaceRange(replacedLine.replace("CURSOR",""),{line:lineNo,ch:0},{line:lineNo,ch:1000000}); - cM.setCursor(lineNoCount,curPos); + thisCM.replaceRange(replacedLine.replace("CURSOR",""),{line:lineNo,ch:0},{line:lineNo,ch:1000000}); + thisCM.setCursor(lineNoCount,curPos); // Finally, focus on the editor - top.ICEcoder.focus(); + top.ICEcoder.focus(top.ICEcoder.editorFocusInstance.indexOf('diff') > -1 ? true : false); } } }; \ No newline at end of file