Minimap and function/class list now working

This commit is contained in:
Matt Pass
2016-09-05 12:20:46 +01:00
parent b6faf3b412
commit b16e8dd03d

View File

@@ -28,6 +28,7 @@ var ICEcoder = {
scrollbarVisible: false, // Indicates if the main pane has a scrollbar
mouseDown: false, // If the mouse is down
mouseDownInCM: false, // If the mouse is down within CodeMirror instance (can be false, 'editor' or 'gutter')
mouseDownMinimap: false, // If the mouse is down on Minimap nav box
draggingFilesW: false, // If we're dragging the file manager width
draggingTab: false, // If we're dragging a tab
draggingWithKey: false, // The key that's down while dragging, false if no key
@@ -42,6 +43,8 @@ var ICEcoder = {
tabFGnormalFile: '#eee', // FG of normal file
tabFGnormalTab: '#888', // FG of normal tab
serverQueueItems: [], // Array of URLs to call in order
miniMapBoxTop: 0, // Top of the minimap box highlighter
miniMapBoxHeight: 0, // Height of the minimap box highlighter
previewWindow: false, // Target variable for the preview window
previewWindowLoading: false, // Loading state of preview window
pluginIntervalRefs: [], // Array of plugin interval refs
@@ -66,7 +69,7 @@ var ICEcoder = {
// Set our aliases
initAliases: function() {
var aliasArray = ["header","files", "fileOptions", "optionsFile", "optionsEdit", "optionsSource", "optionsHelp", "filesFrame", "editor", "tabsBar", "findBar", "content", "footer", "nestValid", "versionsDisplay", "splitPaneControls", "splitPaneNamesMain", "splitPaneNamesDiff", "charDisplay", "byteDisplay"];
var aliasArray = ["header","files", "fileOptions", "optionsFile", "optionsEdit", "optionsSource", "optionsHelp", "filesFrame", "editor", "tabsBar", "findBar", "content", "footer", "nestValid", "versionsDisplay", "splitPaneControls", "splitPaneNamesMain", "splitPaneNamesDiff", "charDisplay", "byteDisplay", "docExplorer", "miniMap", "miniMapContainer", "miniMapContent", "functionClassList"];
// Create our ID aliases
for (var i=0;i<aliasArray.length;i++) {
@@ -164,14 +167,14 @@ var ICEcoder = {
this.filesFrame.style.height = (winH-headerH-fileNavH) + "px";
this.nestValid.style.left = (this.filesW+10) + "px";
this.versionsDisplay.style.left = (this.filesW+25) + "px";
this.splitPaneControls.style.left = (parseInt((winW-this.filesW)/2,10)-25-4+this.filesW) + "px";
this.splitPaneNamesMain.style.left = (parseInt((winW-this.filesW)*0.25,10)-50+this.filesW) + "px";
this.splitPaneNamesDiff.style.left = (parseInt((winW-this.filesW)*0.75,10)-50+this.filesW) + "px";
this.splitPaneControls.style.left = (parseInt((winW-this.filesW)/2,10)-25-4+this.filesW) - 100 + "px";
this.splitPaneNamesMain.style.left = (parseInt((winW-this.filesW)*0.25,10)-50+this.filesW) - 60 + "px";
this.splitPaneNamesDiff.style.left = (parseInt((winW-this.filesW)*0.75,10)-50+this.filesW) - 135 + "px";
top.ICEcoder.setTabWidths();
// If we need to set the editor sizes
if (!dontSetEditor) {
this.editor.style.width = ICEcoder.content.style.width = (winW-this.filesW) + "px";
this.editor.style.width = ICEcoder.content.style.width = (winW-this.filesW) - 200 + "px";
ICEcoder.content.style.height = (winH-headerH-tabsBarH-findBarH-26) + "px";
// Resize the CodeMirror instances to match the window size
@@ -187,6 +190,8 @@ var ICEcoder = {
top.ICEcoder.content.contentWindow['cM'+ICEcoder.cMInstances[i]].setSize(top.ICEcoder.splitPaneLeftPerc+"%",top.ICEcoder.content.style.height);
}
}
// Set height of docExplorer
this.docExplorer.style.height = top.ICEcoder.content.style.height;
// Place resultsBar to edge of pane or it's scrollbar
if (!top.ICEcoder.splitPane) {
top.ICEcoder.content.contentWindow.document.getElementById('resultsBar').style.right = !top.ICEcoder.scrollBarVisible ? "0" : "17px";
@@ -253,6 +258,12 @@ var ICEcoder = {
},4);
},
// Doc Explorer show item
docExplorerShow: function(item) {
get('miniMap').style.display = item == "miniMap" ? 'block' : 'none';
get('functionClassList').style.display = item == "functionClassList" ? 'block' : 'none';
},
// Set the width of the file manager on demand
changeFilesW: function(expandContract) {
if (!ICEcoder.lockedNav||ICEcoder.filesW==ICEcoder.minFilesW) {
@@ -429,6 +440,16 @@ var ICEcoder = {
// If we're not loading the file, it's a change, so update tab
if (!top.ICEcoder.loadingFile) {
top.ICEcoder.redoTabHighlight(top.ICEcoder.selectedTab);
// File load needs to force a simple change to get minimap functional
} else {
setTimeout(function(){
thisCM.replaceRange('X',{line: 1, ch: 1},{line: 1, ch: 1});
thisCM.undo();
thisCM.clearHistory();
top.ICEcoder.savedPoints[top.ICEcoder.selectedTab-1] = thisCM.changeGeneration();
top.ICEcoder.savedContents[top.ICEcoder.selectedTab-1] = thisCM.getValue();
},0);
}
// Detect if we have a scrollbar & set layout again
@@ -496,6 +517,15 @@ var ICEcoder = {
top.get('results').innerHTML = top.ICEcoder.results.length + " " + top.t['results'];
top.ICEcoder.findMode = false;
}
// Update the list of functions and classes
top.ICEcoder.updateFunctionClassList();
// Update the minimap nav
if ("undefined" != typeof top.doMiniNav) {
clearTimeout(top.doMiniNav);
}
top.doMiniNav = setTimeout(function() {
top.ICEcoder.setMinimap();
},top.ICEcoder.loadingFile ? 0 : 100);
filepath = top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1];
if (filepath) {
filename = filepath.substr(filepath.lastIndexOf("/")+1);
@@ -514,6 +544,45 @@ var ICEcoder = {
top.ICEcoder.indicateChanges();
},
cMonUpdate: function(thisCM,cMinstance) {
var cM, percThru;
// Get CM instance and percentage through document
cM = top.ICEcoder.getcMInstance();
percThru = thisCM.getScrollInfo().top/(thisCM.getScrollInfo().height-thisCM.getScrollInfo().clientHeight);
// If we've got a minimap box ready
if (get('miniMapBox')) {
// If content to display has a greater height than docExplorer
if (parseInt(get('miniMapContent').getBoundingClientRect().height,10) > parseInt(get('docExplorer').style.height,10)) {
// Set the minimap container to same height
get('miniMapContainer').style.height = parseInt(get('docExplorer').style.height,10)+"px";
// Set box height relative to font height
top.ICEcoder.miniMapBoxHeight = parseInt(get('docExplorer').style.height,10)/cM.defaultTextHeight()*2;
get('miniMapBox').style.height = top.ICEcoder.miniMapBoxHeight + "px";
// Set top position of it according to percentage through document and account for height of nav box
top.ICEcoder.miniMapBoxTop = (percThru*parseInt(get('docExplorer').style.height,10)) - (percThru*top.ICEcoder.miniMapBoxHeight);
// Set the minimap position according to scroll position (used if we move cursor in document)
get('miniMapContent').style.marginTop = (-(parseInt(get('miniMapContent').getBoundingClientRect().height,10) - parseInt(get('docExplorer').style.height,10))*percThru) + "px";
// If less than the docExplorer height
} else {
// Set height of container to that of the content
get('miniMapContainer').style.height = parseInt(get('miniMapContent').getBoundingClientRect().height,10)+"px";
// Set box height relative to font height
top.ICEcoder.miniMapBoxHeight = parseInt(get('docExplorer').style.height,10)/cM.defaultTextHeight()*2;
get('miniMapBox').style.height = top.ICEcoder.miniMapBoxHeight + "px";
// Set top position of it according to percentage through minimap and account for height of nav box
top.ICEcoder.miniMapBoxTop = (percThru*parseInt(get('miniMap').getBoundingClientRect().height,10)) - (percThru*top.ICEcoder.miniMapBoxHeight);
// Set the minimap position to 0
get('miniMapContent').style.marginTop = 0;
}
// Can set the Minimap nav position if not dragging it (let Draggabilly handle that)
if (!top.ICEcoder.mouseDownMinimap) {
get('miniMapBox').style.top = top.ICEcoder.miniMapBoxTop + "px";
}
}
},
// On scroll
cMonScroll: function(thisCM,cMinstance) {
var cM, cMdiff, otherCM;
@@ -531,8 +600,7 @@ var ICEcoder = {
// Scroll other pane x & y to match this one we're scrolling, after a 0ms tickover to avoid judder
setTimeout(function(){otherCM.scrollTo(thisCM.getScrollInfo().left, thisCM.getScrollInfo().top);},0);
}
}
}
},
// On input read
@@ -1053,6 +1121,115 @@ var ICEcoder = {
}
}
}
},
// Update function & class list {
updateFunctionClassList: function() {
var cM, functionClassList;
cM = ICEcoder.getcMInstance();
top.ICEcoder.functionClassList = [];
if(cM) {
// For each line, establish if there's a function or class item on it
cM.doc.eachLine(function(handle){top.ICEcoder.updateFunctionClassListItems(handle)});
// Update the list displayed
setTimeout(function() {
functionClassList = '';
// For each of the items in our array, if it's verified, add it into string
for (var i=0; i<top.ICEcoder.functionClassList.length; i++) {
if (top.ICEcoder.functionClassList[i]['verified']) {
functionClassList += '<div onclick="top.ICEcoder.goToLine('+(top.ICEcoder.functionClassList[i]['line']+1)+')" class="functionClassListItem"><span class="name">'+top.ICEcoder.functionClassList[i]['name']+'</span><br><span class="params">'+top.ICEcoder.functionClassList[i]['params']+'</span></div>';
}
}
// Update our list
get('functionClassList').innerHTML = functionClassList;
},0);
}
},
setMinimap: function() {
var cM;
cM = ICEcoder.getcMInstance();
top.ICEcoder.functionClassList = [];
if(cM) {
top.ICEcoder.content.contentWindow.CodeMirror.runMode(cM.getValue(),"application/x-httpd-php",get('miniMapContent'));
// white-space: pre; vs pre-wrap
get('miniMapContent').innerHTML = '<div class="cm-s-'+top.ICEcoder.theme+'" style="font-family: monospace; white-space: pre-wrap; font-size: 2px; line-height: 2px">'+get('miniMapContent').innerHTML+'</div>';
get('miniMapContent').innerHTML = get('miniMapContent').innerHTML.replace(/\<span /g,'<span style="font-size: 2px; font-family: monospace" ');
get('miniMapContainer').innerHTML = '<div style="position: absolute; display: inline-block; top: '+
top.ICEcoder.miniMapBoxTop+
'px; left: 0; width: 200px; height: '+
top.ICEcoder.miniMapBoxHeight+'px; background: rgba(0,198,255,0.3); z-index: 100; cursor: pointer" id="miniMapBox"></div>';
if (!top.ICEcoder.minimapNav) {
var elem = get('miniMapBox');
var draggie = new Draggabilly( elem, {
axis: 'y',
containment: true
});
draggie.on( 'dragMove', function( event, pointer, moveVector ) {
yPos = this.position.y;
maxHeight = parseInt(get('docExplorer').style.height,10) <= parseInt(get('miniMapContent').getBoundingClientRect().height,10)
? parseInt(get('docExplorer').style.height,10)
: parseInt(get('miniMapContent').getBoundingClientRect().height,10);
newPerc = (this.position.y/(maxHeight-top.ICEcoder.miniMapBoxHeight));
yPos = (cM.getScrollInfo().height-cM.getScrollInfo().clientHeight)*newPerc;
cM.scrollTo(0,yPos); // this.position.y
});
draggie.on( 'pointerDown', function( event, pointer ) {
top.ICEcoder.mouseDownMinimap = true;
});
draggie.on( 'pointerUp', function( event, pointer ) {
top.ICEcoder.mouseDownMinimap = false;
});
top.ICEcoder.minimapNav = true;
}
}
},
updateFunctionClassListItems: function(x) {
var cM;
cM = ICEcoder.getcMInstance();
functionClassText = "";
if (x.text.indexOf("function ") > -1 && x.text.replace(/\$function/g,"").indexOf("function ") > -1) {
functionClassText = x.text.substring(x.text.indexOf("function ") + 9);
}
if (x.text.indexOf("class ") > -1 && x.text.replace(/\$class/g,"").indexOf("class ") > -1) {
functionClassText = x.text.substring(x.text.indexOf("class ") + 6);
}
functionClassText = functionClassText.trim().split("{")[0].split("(");
if (functionClassText[0] != "") {
top.ICEcoder.functionClassList.push({
line: cM.getLineNumber(x),
name: functionClassText[0],
params: "("+functionClassText[1],
verified: false
});
setTimeout(function() {
if (!x.styles || (x.styles && x.styles.indexOf('def') > -1 && cM.getLineNumber(x))) {
//if (x.styles && x.styles.indexOf('def') > -1 && cM.getLineNumber(x)) {
for (var i=0; i< top.ICEcoder.functionClassList.length; i++) {
if (top.ICEcoder.functionClassList[i]['line'] == cM.getLineNumber(x)) {
top.ICEcoder.functionClassList[i]['verified'] = true;
}
};
}
},0);
}
},
// Autocomplete
@@ -2957,6 +3134,11 @@ var ICEcoder = {
styleNode.setAttribute('type', 'text/css');
styleNode.setAttribute('href', themeURL);
top.ICEcoder.content.contentWindow.document.getElementsByTagName('head')[0].appendChild(styleNode);
styleNode = document.createElement('link');
styleNode.setAttribute('rel', 'stylesheet');
styleNode.setAttribute('type', 'text/css');
styleNode.setAttribute('href', themeURL);
top.document.getElementsByTagName('head')[0].appendChild(styleNode);
if (["3024-day","base16-light","eclipse","elegant","mdn-like","neat","neo","paraiso-light","solarized","the-matrix","xq-light"].indexOf(top.ICEcoder.theme)>-1) {
activeLineBG = "#ccc";
} else if (["3024-night","blackboard","colorforth","liquibyte","night","tomorrow-night-bright","tomorrow-night-eighties","vibrant-ink"].indexOf(top.ICEcoder.theme)>-1) {
@@ -3381,6 +3563,15 @@ var ICEcoder = {
cM.refresh();
cMdiff.refresh();
top.ICEcoder.updateFunctionClassList();
// Update the minimap nav
if ("undefined" != typeof top.doMiniNav) {
clearTimeout(top.doMiniNav);
}
top.doMiniNav = setTimeout(function() {
top.ICEcoder.setMinimap();
},top.ICEcoder.loadingFile ? 0 : 100);
// Highlight the selected tab
ICEcoder.redoTabHighlight(ICEcoder.selectedTab);