Compare commits

..

64 Commits

Author SHA1 Message Date
Matt Pass
2237c91067 Version number, Zip It! plugin & tabWidth
Version number now v 0.7.3
Zip It! is new plugin instead of backupOpenFiles
tabWidth now set to 4 chars by default
2012-06-17 16:34:37 +01:00
Matt Pass
98a08fddf8 tabWidth option and plugins tooltip
tabWidth option now saved as a setting
Plugins show tooltip now on hover via title attribute
2012-06-17 16:33:14 +01:00
Matt Pass
21cdcb20b4 New tabWidth option
tabWidth option now shown in 'style' section
On change, this affects editor demo instance
2012-06-17 16:27:59 +01:00
Matt Pass
47547b2ae8 Dark active line & dynamic tab widths
Config file included so we can use vars
Active line is now black rather than dark blue
(This is a bit experimental and unusual, so we'll see how it works out)
indentUnit & tabSize params in CM now uses JS var, so updateable
2012-06-17 16:26:43 +01:00
Matt Pass
6e9af92471 tabWidth var & Zip It! file manager option
New tabWidth var available to use
New Zip It! option added to file manager menu
(allowing users to zip anything on demand)
2012-06-17 16:21:53 +01:00
Matt Pass
cc7df4222a Removed unneeded for loop
Completely unneeded for loop controlling tabWidth's removed
2012-06-17 16:20:35 +01:00
Matt Pass
25b5af50c2 tabWidth changable & Zip It! on Demand
useNewSettings now takes a tabWidth param
This changes the width of all open documents in CM instance
New function to call Zip It! plugin on demand with target
(This means you can zip anything up from the file manager menu)
2012-06-17 16:17:31 +01:00
Matt Pass
7c8c728ad4 Darker file manager menu
Was same colour as file manager and didn't stand out
Now slightly darker to help visual appearance
2012-06-17 16:15:02 +01:00
Matt Pass
655fef4baa Zip It! Plugin Added
This replaces backupOpenFiles
Now zips up whole website be default, but also can zip up targets
This plugin is also now available from the file manager menu
2012-06-17 16:13:22 +01:00
Matt Pass
a27db58031 Removed backupOpenFiles Plugin
Plugin which backs up open files now removed
This is because the rest of your site isn't being backed up, just open
files
Now the whole site being backed up instead
Devs are used to saving regularly and so this is a better setup
2012-06-17 16:12:08 +01:00
Matt Pass
7c0cb2d1c3 goToLine now takes number as a param
You can optionally pass through a param to goToLine
It will go to this given line instead of textfield value
This makes it more usable via API calls
2012-06-11 07:48:46 +01:00
Matt Pass
229a089d45 Now checks for updates of ICEcoder & CodeMirror
Extended this process to check for firstly ICEcoder updates and then
CodeMirror
Both working via their own remotely sourced latest-version.txt files
If ICEcoder is up to date, if performs a check on CodeMirrors version
no.
2012-06-11 07:46:43 +01:00
Matt Pass
49ca9d75f9 testcMVersion var now checkUpdates
Repurposed this var to both check for newer ICEcoder and CodeMirror
versions
Renamed to checkUpdates
2012-06-11 07:43:46 +01:00
Matt Pass
745903d133 Move file/folder count & last 10 files clickable
File & folder count moved into files section
Last 10 files is now clickable to open file
Also shows [none] if there aren't any files to display
Couple of bytes saved in server DT display process
Will also only update server DT if it's visible
2012-06-10 11:46:23 +01:00
Matt Pass
54bf805548 openFile function now takes a file as param
You can now pass through a file link to this function
If passed through, it'll be set as the file to open
2012-06-10 11:36:54 +01:00
Matt Pass
2ac674f5c6 Version no update to v0.7.2 2012-06-09 18:44:10 +01:00
Matt Pass
2b5a16be70 FM visually linked to tabs & file setting updates
Changed content indicator in tab doesn't count if undo history is back
to the start
File highlighting now visually linked with the tabs of open docs
Selected file have blue BG, other open files 15% white BG
lastOpenedFiles now previousFiles in a few places
2012-06-09 18:43:57 +01:00
Matt Pass
1fbe9df342 Server DT, last 10 files and improved layout
Layout is now in 3 areas, collapsable too via CSS float
Server name, OS & IP combined
Date & time now shown under server
This is also updated via JS
2012-06-09 18:39:12 +01:00
Matt Pass
1217d2d05e previousFiles & last10Files
renamed lastOpenedFiles to previousFiles
Now also saves the last 10 opened files in new setting
2012-06-09 18:36:42 +01:00
Matt Pass
432795026c renamed lastOpenedFiles to previousFiles 2012-06-09 18:31:44 +01:00
Matt Pass
ab23eaa6ff previousFiles & last10Files
renamed lastOpenedFiles to previousFiles
New setting added - last10Files
2012-06-09 18:30:51 +01:00
Matt Pass
4583c0c713 Class fixes & new class for full screen
.header & .files need top & left CSS props set to avoid centering in
full screen
New class for screenModeIcon
2012-06-07 07:53:07 +01:00
Matt Pass
d3a961f13f Version no update to v 0.7.1 2012-06-07 07:51:45 +01:00
Matt Pass
7a97af2c1d Function to switch screen mode
Handles future proposed spec, plus Moz & Chrome prefixes for usage now
Also changes icon on switching
2012-06-07 07:51:18 +01:00
Matt Pass
750cc59fd5 Screen mode switcher
Small icon now shows in top right to switch between full screen and
restored screen
2012-06-07 07:50:33 +01:00
Matt Pass
dfcf54d412 Spliting IE/FF & Chrome/Safari CSS styles
IE & Firefox have different margin rendering to Chrome
Chrome & Safari hack to provide different margin-top
2012-06-01 17:52:11 +01:00
Matt Pass
5fd1c35d85 Check if container exists before updating
A quick check is performed container exists before attemping update
2012-06-01 17:51:07 +01:00
Matt Pass
21b61bd027 CSS handled differently, updating container moved
Conditional IE hack removed as it needs to apply to Firefox too
Now a CSS margin-top hack relating to Chrome only in CSS file
Moved updating of file, folder, bytes container to editor.php file
(This means it shows correctly on load)
2012-06-01 17:50:18 +01:00
Matt Pass
7fa28c6d8b onLoad, update file, folder, byte display 2012-06-01 17:48:11 +01:00
Matt Pass
97e396794a Server info display showing files, folders, bytes
Files, folders & bytes along with supplementary text established
This is then added to the container on the server info page
2012-06-01 17:18:08 +01:00
Matt Pass
b096ef3606 Files, folders & bytes now counted up
Count of files & folders are running as files & folders are found
Bytes of files also totalled
onLoad, a new function is called to update the server info display
2012-06-01 17:16:46 +01:00
Matt Pass
74b0d86c36 Container to show file & folder count
This is updated once the file manager has loaded
2012-06-01 17:13:08 +01:00
Matt Pass
319c509318 Handling CLEAR when updating lastOpenedFiles
Now drops in correct value, either string array or empty value
2012-06-01 08:26:03 +01:00
Matt Pass
5703a040be lastOpenedFiles handling on no files
CLEAR now sent through as value if no files
No need for else clause now
2012-06-01 08:24:44 +01:00
Matt Pass
6752b8ef50 Adding headings & margin adjusts to server info 2012-06-01 08:23:32 +01:00
Matt Pass
7062560eaa Version number update only 2012-05-31 15:07:12 +01:00
Matt Pass
3be433c910 Visibility of content, padlock dir & IE fixes
Removed comments/dislaimer at top, now use LICENSE file
No longer show or hide content area, it's shown from init load if logged
in
Changed location of packlock icon
IE now using e var for event and not event, fixes JS issue
On refresh and successful login, set visibility & src of content area
(This shows server info upon login)
2012-05-31 15:07:00 +01:00
Matt Pass
bd0969e870 Altered error text & showing content area on load
Better error message to user re public write permissions on config.php
If logged in, now shows content area and therefore server details
2012-05-31 15:01:07 +01:00
Matt Pass
ffbac321a4 Change of padlock image location & IE CSS hack
Padlock now located in parent image folder
IE differs in it's placement of icons, so have conditional IE CSS fix
2012-05-31 14:59:27 +01:00
Matt Pass
222f6589a9 FM icons now work from single sprite sheet
All filetypes now show icons via single sprite sheet
This works via setting a class with pseudo :before containing icon sized
block with icon in BG
blank.gif is used as a sizing placeholder for LI images
Removed a few trailing semi colons
2012-05-31 14:57:59 +01:00
Matt Pass
a2245775a9 Adjustment to location of padlock image 2012-05-31 14:52:34 +01:00
Matt Pass
d594050166 Server & user info screen
CodeMirror instances now on z-index of 1, above body
Body by default now shows server & user details if logged in and no docs
loaded
2012-05-31 14:51:46 +01:00
Matt Pass
2665055558 New FM icons sprite sheet & blank.gif
All file manager icons now in single sprite sheet
These are shown using CSS class pseudo's
blank.gif is needed to easily determin height
2012-05-31 14:37:37 +01:00
Matt Pass
3e41afb0a6 Set value not innerHTML in textarea
Setting innerHTML works fine in Chrome & Firefox but not IE
In order to make IE compatible, made this improvement
(More syntactically appropriate anyway)
2012-05-31 14:35:48 +01:00
Matt Pass
f1ec4a2453 Padlock & refresh icons moved
Moved from FM dir (no longer exists) to parent 'images' dir
2012-05-31 14:32:59 +01:00
Matt Pass
98f1ace910 Removed single FM icons
Removed individual file manager icons from own dir
Icons now show via CSS and spritesheet
2012-05-31 14:32:09 +01:00
Matt Pass
401a3a7abb New initAliases function & scoping of vars
Initialisation of DOM vars now in own function
(This allows Firefox loadstack to work fine & is more efficient too,
only ever called once)
'this' also prefixes the DOM vars initialised, so works in Firefox
2012-05-29 17:53:41 +01:00
Matt Pass
6a0cc816a9 Aliases now initialised in seperate function
Initialise once DOM load complete, prior to 1st setLayout call
2012-05-29 17:51:08 +01:00
Matt Pass
4bafb3aaa1 Need e not event
Wasn't working in Firefox, this fixes issue
2012-05-29 17:50:14 +01:00
Matt Pass
782aac54e4 Logo now is a PNG
Has transparent BG, so can show on white or dark grey BG
2012-05-29 17:11:44 +01:00
Matt Pass
06dd46c24f Logo now is a PNG
Has transparent BG, so can show on white or dark grey BG
2012-05-29 17:11:10 +01:00
Matt Pass
bc50886250 Alterations to the install process 2012-05-29 16:58:02 +01:00
Matt Pass
4264c479ad Version number update to v0.6.9 2012-05-29 16:26:32 +01:00
Matt Pass
b3afe9458e Root files & folders show on load
Makes sense to show files & folders at root level on load, rather than
just show a single folder. This topmost level is now shown on load.
2012-05-29 07:55:48 +01:00
Matt Pass
1382277c74 Default list of excluded files increased
Now by default the excluded files includes anything in the _coder
folder, plus filetypes that shouldn't really be searched within (mainly
media files).
2012-05-28 19:10:29 +01:00
Matt Pass
d1df67338d ICEcoder & user settings now stored in new file
Settings moved from settings.php to this new config.php file
This seperates processing from data storage as ICEcoder evolves
2012-05-28 18:53:40 +01:00
Matt Pass
ccc5b9d30a Settings moved to config.php file, new array & BG
ICEcoder & user settings moved to new file, config.php
Settings.php is now used to handle settings and the seperate file for
storage
New array setting - findFilesExclude defines excluded strings
Settings screen BG is now dark grey not white, matches ICEcoders dark UI
2012-05-28 18:52:20 +01:00
Matt Pass
86142ca5f1 New setting to exclude files/folders from find
A new string array can now be added to settings screen
This array defines strings that are to be excluded from find in
files/folders and their names results when using the Find & Replace
function.
2012-05-28 18:47:51 +01:00
Matt Pass
b55fe4856c CSS compacting & new Erlang Dark theme
New theme added
0px now 0
2012-05-28 07:56:32 +01:00
Matt Pass
d5df587cc3 CSS compacting
0px now 0
2012-05-28 07:55:45 +01:00
Matt Pass
0665d10a7c CSS compacting & robot meta tag
noindex, nofollow robots meta tag
0px now 0
2012-05-28 07:54:00 +01:00
Matt Pass
43f7089106 CSS compacting & JS file sorting
0px now 0
Sorted load order of a few mode files
2012-05-28 07:53:00 +01:00
Matt Pass
fcb7722a55 Removed mode demo pages
Remoevd the demo page for each mode, not necessary
2012-05-28 07:50:57 +01:00
Matt Pass
7c5a005784 Removed unused CodeMirror files
Removed the 2 x keymap files and unused files from util dir
These files are all unused, if users want them, they can download
(Same thinking as only including used 'mode' files)
2012-05-28 07:50:25 +01:00
59 changed files with 519 additions and 3095 deletions

View File

@@ -1,29 +0,0 @@
// TODO number prefixes
(function() {
// Really primitive kill-ring implementation.
var killRing = [];
function addToRing(str) {
killRing.push(str);
if (killRing.length > 50) killRing.shift();
}
function getFromRing() { return killRing[killRing.length - 1] || ""; }
function popFromRing() { if (killRing.length > 1) killRing.pop(); return getFromRing(); }
CodeMirror.keyMap.emacs = {
"Ctrl-X": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-X");},
"Ctrl-W": function(cm) {addToRing(cm.getSelection()); cm.replaceSelection("");},
"Ctrl-Alt-W": function(cm) {addToRing(cm.getSelection()); cm.replaceSelection("");},
"Alt-W": function(cm) {addToRing(cm.getSelection());},
"Ctrl-Y": function(cm) {cm.replaceSelection(getFromRing());},
"Alt-Y": function(cm) {cm.replaceSelection(popFromRing());},
"Ctrl-/": "undo", "Shift-Ctrl--": "undo", "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd",
"Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": "clearSearch", "Shift-Alt-5": "replace",
"Ctrl-Z": "undo", "Cmd-Z": "undo", "Alt-/": "autocomplete",
fallthrough: ["basic", "emacsy"]
};
CodeMirror.keyMap["emacs-Ctrl-X"] = {
"Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": "undo", "K": "close",
auto: "emacs", nofallthrough: true
};
})();

View File

@@ -1,500 +0,0 @@
// Supported keybindings:
//
// Cursor movement:
// h, j, k, l
// e, E, w, W, b, B
// Ctrl-f, Ctrl-b
// Ctrl-n, Ctrl-p
// $, ^, 0
// G
// ge, gE
// gg
// f<char>, F<char>, t<char>, T<char>
// Ctrl-o, Ctrl-i TODO (FIXME - Ctrl-O wont work in Chrome)
// /, ?, n, N TODO (does not work)
// #, * TODO
//
// Entering insert mode:
// i, I, a, A, o, O
// s
// ce, cb (without support for number of actions like c3e - TODO)
// cc
// S, C TODO
// cf<char>, cF<char>, ct<char>, cT<char>
//
// Deleting text:
// x, X
// J
// dd, D
// de, db (without support for number of actions like d3e - TODO)
// df<char>, dF<char>, dt<char>, dT<char>
//
// Yanking and pasting:
// yy, Y
// p, P
// p'<char> TODO - test
// y'<char> TODO - test
// m<char> TODO - test
//
// Changing text in place:
// ~
// r<char>
//
// Visual mode:
// v, V TODO
//
// Misc:
// . TODO
//
(function() {
var count = "";
var sdir = "f";
var buf = "";
var yank = 0;
var mark = [];
function emptyBuffer() { buf = ""; }
function pushInBuffer(str) { buf += str; };
function pushCountDigit(digit) { return function(cm) {count += digit;} }
function popCount() { var i = parseInt(count); count = ""; return i || 1; }
function iterTimes(func) {
for (var i = 0, c = popCount(); i < c; ++i) func(i, i == c - 1);
}
function countTimes(func) {
if (typeof func == "string") func = CodeMirror.commands[func];
return function(cm) { iterTimes(function () { func(cm); }) };
}
function iterObj(o, f) {
for (var prop in o) if (o.hasOwnProperty(prop)) f(prop, o[prop]);
}
function iterList(l, f) {
for (var i in l) f(l[i]);
}
function toLetter(ch) {
// T -> t, Shift-T -> T, '*' -> *, "Space" -> " "
if (ch.slice(0, 6) == "Shift-") {
return ch.slice(0, 1);
} else {
if (ch == "Space") return " ";
if (ch.length == 3 && ch[0] == "'" && ch[2] == "'") return ch[1];
return ch.toLowerCase();
}
}
var SPECIAL_SYMBOLS = "~`!@#$%^&*()_-+=[{}]\\|/?.,<>:;\"\'1234567890";
function toCombo(ch) {
// t -> T, T -> Shift-T, * -> '*', " " -> "Space"
if (ch == " ") return "Space";
var specialIdx = SPECIAL_SYMBOLS.indexOf(ch);
if (specialIdx != -1) return "'" + ch + "'";
if (ch.toLowerCase() == ch) return ch.toUpperCase();
return "Shift-" + ch.toUpperCase();
}
var word = [/\w/, /[^\w\s]/], bigWord = [/\S/];
function findWord(line, pos, dir, regexps) {
var stop = 0, next = -1;
if (dir > 0) { stop = line.length; next = 0; }
var start = stop, end = stop;
// Find bounds of next one.
outer: for (; pos != stop; pos += dir) {
for (var i = 0; i < regexps.length; ++i) {
if (regexps[i].test(line.charAt(pos + next))) {
start = pos;
for (; pos != stop; pos += dir) {
if (!regexps[i].test(line.charAt(pos + next))) break;
}
end = pos;
break outer;
}
}
}
return {from: Math.min(start, end), to: Math.max(start, end)};
}
function moveToWord(cm, regexps, dir, where) {
var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line), word;
while (true) {
word = findWord(line, ch, dir, regexps);
ch = word[where == "end" ? "to" : "from"];
if (ch == cur.ch && word.from != word.to) ch = word[dir < 0 ? "from" : "to"];
else break;
}
cm.setCursor(cur.line, word[where == "end" ? "to" : "from"], true);
}
function joinLineNext(cm) {
var cur = cm.getCursor(), ch = cur.ch, line = cm.getLine(cur.line);
CodeMirror.commands.goLineEnd(cm);
if (cur.line != cm.lineCount()) {
CodeMirror.commands.goLineEnd(cm);
cm.replaceSelection(" ", "end");
CodeMirror.commands.delCharRight(cm);
}
}
function delTillMark(cm, cHar) {
var i = mark[cHar];
if (i === undefined) {
// console.log("Mark not set"); // TODO - show in status bar
return;
}
var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
cm.setCursor(start);
for (var c = start; c <= end; c++) {
pushInBuffer("\n"+cm.getLine(start));
cm.removeLine(start);
}
}
function yankTillMark(cm, cHar) {
var i = mark[cHar];
if (i === undefined) {
// console.log("Mark not set"); // TODO - show in status bar
return;
}
var l = cm.getCursor().line, start = i > l ? l : i, end = i > l ? i : l;
for (var c = start; c <= end; c++) {
pushInBuffer("\n"+cm.getLine(c));
}
cm.setCursor(start);
}
function goLineStartText(cm) {
// Go to the start of the line where the text begins, or the end for whitespace-only lines
var cur = cm.getCursor(), firstNonWS = cm.getLine(cur.line).search(/\S/);
cm.setCursor(cur.line, firstNonWS == -1 ? line.length : firstNonWS, true);
}
function charIdxInLine(cm, cHar, motion_options) {
// Search for cHar in line.
// motion_options: {forward, inclusive}
// If inclusive = true, include it too.
// If forward = true, search forward, else search backwards.
// If char is not found on this line, do nothing
var cur = cm.getCursor(), line = cm.getLine(cur.line), idx;
var ch = toLetter(cHar), mo = motion_options;
if (mo.forward) {
idx = line.indexOf(ch, cur.ch + 1);
if (idx != -1 && mo.inclusive) idx += 1;
} else {
idx = line.lastIndexOf(ch, cur.ch);
if (idx != -1 && !mo.inclusive) idx += 1;
}
return idx;
}
function moveTillChar(cm, cHar, motion_options) {
// Move to cHar in line, as found by charIdxInLine.
var idx = charIdxInLine(cm, cHar, motion_options), cur = cm.getCursor();
if (idx != -1) cm.setCursor({line: cur.line, ch: idx});
}
function delTillChar(cm, cHar, motion_options) {
// delete text in this line, untill cHar is met,
// as found by charIdxInLine.
// If char is not found on this line, do nothing
var idx = charIdxInLine(cm, cHar, motion_options);
var cur = cm.getCursor();
if (idx !== -1) {
if (motion_options.forward) {
cm.replaceRange("", {line: cur.line, ch: cur.ch}, {line: cur.line, ch: idx});
} else {
cm.replaceRange("", {line: cur.line, ch: idx}, {line: cur.line, ch: cur.ch});
}
}
}
function enterInsertMode(cm) {
// enter insert mode: switch mode and cursor
if (!cm) console.log("call enterInsertMode with 'cm' as an argument");
popCount();
cm.setOption("keyMap", "vim-insert");
}
// main keymap
var map = CodeMirror.keyMap.vim = {
// Pipe (|); TODO: should be *screen* chars, so need a util function to turn tabs into spaces?
"'|'": function(cm) {
cm.setCursor(cm.getCursor().line, popCount() - 1, true);
},
"'^'": function(cm) { popCount(); goLineStartText(cm);},
"A": function(cm) {
cm.setCursor(cm.getCursor().line, cm.getCursor().ch+1, true);
enterInsertMode(cm);
},
"Shift-A": function(cm) { CodeMirror.commands.goLineEnd(cm); enterInsertMode(cm);},
"I": function(cm) { enterInsertMode(cm);},
"Shift-I": function(cm) { goLineStartText(cm); enterInsertMode(cm);},
"O": function(cm) {
CodeMirror.commands.goLineEnd(cm);
CodeMirror.commands.newlineAndIndent(cm);
enterInsertMode(cm);
},
"Shift-O": function(cm) {
CodeMirror.commands.goLineStart(cm);
cm.replaceSelection("\n", "start");
cm.indentLine(cm.getCursor().line);
enterInsertMode(cm);
},
"G": function(cm) { cm.setOption("keyMap", "vim-prefix-g");},
"Shift-D": function(cm) {
// commented out verions works, but I left original, cause maybe
// I don't know vim enouth to see what it does
/* var cur = cm.getCursor();
var f = {line: cur.line, ch: cur.ch}, t = {line: cur.line};
pushInBuffer(cm.getRange(f, t));
cm.replaceRange("", f, t);
*/
emptyBuffer();
mark["Shift-D"] = cm.getCursor(false).line;
cm.setCursor(cm.getCursor(true).line);
delTillMark(cm,"Shift-D"); mark = [];
},
"S": function (cm) {
countTimes(function (_cm) {
CodeMirror.commands.delCharRight(_cm);
})(cm);
enterInsertMode(cm);
},
"M": function(cm) {cm.setOption("keyMap", "vim-prefix-m"); mark = [];},
"Y": function(cm) {cm.setOption("keyMap", "vim-prefix-y"); emptyBuffer(); yank = 0;},
"Shift-Y": function(cm) {
emptyBuffer();
mark["Shift-D"] = cm.getCursor(false).line;
cm.setCursor(cm.getCursor(true).line);
yankTillMark(cm,"Shift-D"); mark = [];
},
"/": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = "f";},
"'?'": function(cm) {
var f = CodeMirror.commands.find;
if (f) { f(cm); CodeMirror.commands.findPrev(cm); sdir = "r"; }
},
"N": function(cm) {
var fn = CodeMirror.commands.findNext;
if (fn) sdir != "r" ? fn(cm) : CodeMirror.commands.findPrev(cm);
},
"Shift-N": function(cm) {
var fn = CodeMirror.commands.findNext;
if (fn) sdir != "r" ? CodeMirror.commands.findPrev(cm) : fn.findNext(cm);
},
"Shift-G": function(cm) {
count == "" ? cm.setCursor(cm.lineCount()) : cm.setCursor(parseInt(count)-1);
popCount();
CodeMirror.commands.goLineStart(cm);
},
"'$'": function (cm) {
countTimes("goLineEnd")(cm);
if (cm.getCursor().ch) CodeMirror.commands.goColumnLeft(cm);
},
nofallthrough: true, style: "fat-cursor"
};
// standard mode switching
iterList(["d", "t", "T", "f", "F", "c", "r"],
function (ch) {
CodeMirror.keyMap.vim[toCombo(ch)] = function (cm) {
cm.setOption("keyMap", "vim-prefix-" + ch);
emptyBuffer();
};
});
function addCountBindings(keyMap) {
// Add bindings for number keys
keyMap["0"] = function(cm) {
count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(cm);
};
for (var i = 1; i < 10; ++i) keyMap[i] = pushCountDigit(i);
}
addCountBindings(CodeMirror.keyMap.vim);
// main num keymap
// Add bindings that are influenced by number keys
iterObj({
"H": "goColumnLeft", "L": "goColumnRight", "J": "goLineDown",
"K": "goLineUp", "Left": "goColumnLeft", "Right": "goColumnRight",
"Down": "goLineDown", "Up": "goLineUp", "Backspace": "goCharLeft",
"Space": "goCharRight",
"B": function(cm) {moveToWord(cm, word, -1, "end");},
"E": function(cm) {moveToWord(cm, word, 1, "end");},
"W": function(cm) {moveToWord(cm, word, 1, "start");},
"Shift-B": function(cm) {moveToWord(cm, bigWord, -1, "end");},
"Shift-E": function(cm) {moveToWord(cm, bigWord, 1, "end");},
"Shift-W": function(cm) {moveToWord(cm, bigWord, 1, "start");},
"X": function(cm) {CodeMirror.commands.delCharRight(cm);},
"P": function(cm) {
var cur = cm.getCursor().line;
if (buf!= "") {
CodeMirror.commands.goLineEnd(cm);
cm.replaceSelection(buf, "end");
}
cm.setCursor(cur+1);
},
"Shift-X": function(cm) {CodeMirror.commands.delCharLeft(cm);},
"Shift-J": function(cm) {joinLineNext(cm);},
"Shift-P": function(cm) {
var cur = cm.getCursor().line;
if (buf!= "") {
CodeMirror.commands.goLineUp(cm);
CodeMirror.commands.goLineEnd(cm);
cm.replaceSelection(buf, "end");
}
cm.setCursor(cur+1);
},
"'~'": function(cm) {
var cur = cm.getCursor(), cHar = cm.getRange({line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
cHar = cHar != cHar.toLowerCase() ? cHar.toLowerCase() : cHar.toUpperCase();
cm.replaceRange(cHar, {line: cur.line, ch: cur.ch}, {line: cur.line, ch: cur.ch+1});
cm.setCursor(cur.line, cur.ch+1);
},
"Ctrl-B": function(cm) {CodeMirror.commands.goPageUp(cm);},
"Ctrl-F": function(cm) {CodeMirror.commands.goPageDown(cm);},
"Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
"U": "undo", "Ctrl-R": "redo"
}, function(key, cmd) { map[key] = countTimes(cmd); });
// empty key maps
iterList([
"vim-prefix-d'",
"vim-prefix-y'",
"vim-prefix-df",
"vim-prefix-dF",
"vim-prefix-dt",
"vim-prefix-dT",
"vim-prefix-c",
"vim-prefix-cf",
"vim-prefix-cF",
"vim-prefix-ct",
"vim-prefix-cT",
"vim-prefix-",
"vim-prefix-f",
"vim-prefix-F",
"vim-prefix-t",
"vim-prefix-T",
"vim-prefix-r",
"vim-prefix-m"
],
function (prefix) {
CodeMirror.keyMap[prefix] = {
auto: "vim",
nofallthrough: true
};
});
CodeMirror.keyMap["vim-prefix-g"] = {
"E": countTimes(function(cm) { moveToWord(cm, word, -1, "start");}),
"Shift-E": countTimes(function(cm) { moveToWord(cm, bigWord, -1, "start");}),
"G": function (cm) { cm.setCursor({line: 0, ch: cm.getCursor().ch});},
auto: "vim", nofallthrough: true, style: "fat-cursor"
};
CodeMirror.keyMap["vim-prefix-d"] = {
"D": countTimes(function(cm) {
pushInBuffer("\n"+cm.getLine(cm.getCursor().line));
cm.removeLine(cm.getCursor().line);
}),
"'": function(cm) {
cm.setOption("keyMap", "vim-prefix-d'");
emptyBuffer();
},
"E": countTimes("delWordRight"),
"B": countTimes("delWordLeft"),
auto: "vim", nofallthrough: true, style: "fat-cursor"
};
// FIXME - does not work for bindings like "d3e"
addCountBindings(CodeMirror.keyMap["vim-prefix-d"]);
CodeMirror.keyMap["vim-prefix-c"] = {
"E": function (cm) {
countTimes("delWordRight")(cm);
enterInsertMode(cm);
},
"B": function (cm) {
countTimes("delWordLeft")(cm);
enterInsertMode(cm);
},
"C": function (cm) {
iterTimes(function (i, last) {
CodeMirror.commands.deleteLine(cm);
if (i) {
CodeMirror.commands.delCharRight(cm);
if (last) CodeMirror.commands.deleteLine(cm);
}
});
enterInsertMode(cm);
},
auto: "vim", nofallthrough: true, style: "fat-cursor"
};
iterList(["vim-prefix-d", "vim-prefix-c", "vim-prefix-"], function (prefix) {
iterList(["f", "F", "T", "t"],
function (ch) {
CodeMirror.keyMap[prefix][toCombo(ch)] = function (cm) {
cm.setOption("keyMap", prefix + ch);
emptyBuffer();
};
});
});
var MOTION_OPTIONS = {
"t": {inclusive: false, forward: true},
"f": {inclusive: true, forward: true},
"T": {inclusive: false, forward: false},
"F": {inclusive: true, forward: false}
};
function setupPrefixBindingForKey(m) {
CodeMirror.keyMap["vim-prefix-m"][m] = function(cm) {
mark[m] = cm.getCursor().line;
};
CodeMirror.keyMap["vim-prefix-d'"][m] = function(cm) {
delTillMark(cm,m);
};
CodeMirror.keyMap["vim-prefix-y'"][m] = function(cm) {
yankTillMark(cm,m);
};
CodeMirror.keyMap["vim-prefix-r"][m] = function (cm) {
var cur = cm.getCursor();
cm.replaceRange(toLetter(m),
{line: cur.line, ch: cur.ch},
{line: cur.line, ch: cur.ch + 1});
CodeMirror.commands.goColumnLeft(cm);
};
// all commands, related to motions till char in line
iterObj(MOTION_OPTIONS, function (ch, options) {
CodeMirror.keyMap["vim-prefix-" + ch][m] = function(cm) {
moveTillChar(cm, m, options);
};
CodeMirror.keyMap["vim-prefix-d" + ch][m] = function(cm) {
delTillChar(cm, m, options);
};
CodeMirror.keyMap["vim-prefix-c" + ch][m] = function(cm) {
delTillChar(cm, m, options);
enterInsertMode(cm);
};
});
};
for (var i = 65; i < 65 + 26; i++) { // uppercase alphabet char codes
var ch = String.fromCharCode(i);
setupPrefixBindingForKey(toCombo(ch));
setupPrefixBindingForKey(toCombo(ch.toLowerCase()));
}
iterList(SPECIAL_SYMBOLS, function (ch) {
setupPrefixBindingForKey(toCombo(ch));
});
setupPrefixBindingForKey("Space");
CodeMirror.keyMap["vim-prefix-y"] = {
"Y": countTimes(function(cm) { pushInBuffer("\n"+cm.getLine(cm.getCursor().line+yank)); yank++; }),
"'": function(cm) {cm.setOption("keyMap", "vim-prefix-y'"); emptyBuffer();},
auto: "vim", nofallthrough: true, style: "fat-cursor"
};
CodeMirror.keyMap["vim-insert"] = {
// TODO: override navigation keys so that Esc will cancel automatic indentation from o, O, i_<CR>
"Esc": function(cm) {
cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1, true);
cm.setOption("keyMap", "vim");
},
"Ctrl-N": "autocomplete",
"Ctrl-P": "autocomplete",
fallthrough: ["default"]
};
})();

View File

@@ -1,146 +0,0 @@
/**
* Tag-closer extension for CodeMirror.
*
* This extension adds a "closeTag" utility function that can be used with key bindings to
* insert a matching end tag after the ">" character of a start tag has been typed. It can
* also complete "</" if a matching start tag is found. It will correctly ignore signal
* characters for empty tags, comments, CDATA, etc.
*
* The function depends on internal parser state to identify tags. It is compatible with the
* following CodeMirror modes and will ignore all others:
* - htmlmixed
* - xml
*
* See demos/closetag.html for a usage example.
*
* @author Nathan Williams <nathan@nlwillia.net>
* Contributed under the same license terms as CodeMirror.
*/
(function() {
/** Option that allows tag closing behavior to be toggled. Default is true. */
CodeMirror.defaults['closeTagEnabled'] = true;
/** Array of tag names to add indentation after the start tag for. Default is the list of block-level html tags. */
CodeMirror.defaults['closeTagIndent'] = ['applet', 'blockquote', 'body', 'button', 'div', 'dl', 'fieldset', 'form', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'html', 'iframe', 'layer', 'legend', 'object', 'ol', 'p', 'select', 'table', 'ul'];
/**
* Call during key processing to close tags. Handles the key event if the tag is closed, otherwise throws CodeMirror.Pass.
* - cm: The editor instance.
* - ch: The character being processed.
* - indent: Optional. Omit or pass true to use the default indentation tag list defined in the 'closeTagIndent' option.
* Pass false to disable indentation. Pass an array to override the default list of tag names.
*/
CodeMirror.defineExtension("closeTag", function(cm, ch, indent) {
if (!cm.getOption('closeTagEnabled')) {
throw CodeMirror.Pass;
}
var mode = cm.getOption('mode');
if (mode == 'text/html') {
/*
* Relevant structure of token:
*
* htmlmixed
* className
* state
* htmlState
* type
* context
* tagName
* mode
*
* xml
* className
* state
* tagName
* type
*/
var pos = cm.getCursor();
var tok = cm.getTokenAt(pos);
var state = tok.state;
if (state.mode && state.mode != 'html') {
throw CodeMirror.Pass; // With htmlmixed, we only care about the html sub-mode.
}
if (ch == '>') {
var type = state.htmlState ? state.htmlState.type : state.type; // htmlmixed : xml
if (tok.className == 'tag' && type == 'closeTag') {
throw CodeMirror.Pass; // Don't process the '>' at the end of an end-tag.
}
cm.replaceSelection('>'); // Mode state won't update until we finish the tag.
pos = {line: pos.line, ch: pos.ch + 1};
cm.setCursor(pos);
tok = cm.getTokenAt(cm.getCursor());
state = tok.state;
type = state.htmlState ? state.htmlState.type : state.type; // htmlmixed : xml
if (tok.className == 'tag' && type != 'selfcloseTag') {
var tagName = state.htmlState ? state.htmlState.context.tagName : state.tagName; // htmlmixed : xml
if (tagName.length > 0) {
insertEndTag(cm, indent, pos, tagName);
}
return;
}
// Undo the '>' insert and allow cm to handle the key instead.
cm.setSelection({line: pos.line, ch: pos.ch - 1}, pos);
cm.replaceSelection("");
} else if (ch == '/') {
if (tok.className == 'tag' && tok.string == '<') {
var tagName = state.htmlState ? (state.htmlState.context ? state.htmlState.context.tagName : '') : state.context.tagName; // htmlmixed : xml # extra htmlmized check is for '</' edge case
if (tagName.length > 0) {
completeEndTag(cm, pos, tagName);
return;
}
}
}
}
throw CodeMirror.Pass; // Bubble if not handled
});
function insertEndTag(cm, indent, pos, tagName) {
if (shouldIndent(cm, indent, tagName)) {
cm.replaceSelection('\n\n</' + tagName + '>', 'end');
cm.indentLine(pos.line + 1);
cm.indentLine(pos.line + 2);
cm.setCursor({line: pos.line + 1, ch: cm.getLine(pos.line + 1).length});
} else {
cm.replaceSelection('</' + tagName + '>');
cm.setCursor(pos);
}
}
function shouldIndent(cm, indent, tagName) {
if (typeof indent == 'undefined' || indent == null || indent == true) {
indent = cm.getOption('closeTagIndent');
}
if (!indent) {
indent = [];
}
return indexOf(indent, tagName.toLowerCase()) != -1;
}
// C&P from codemirror.js...would be nice if this were visible to utilities.
function indexOf(collection, elt) {
if (collection.indexOf) return collection.indexOf(elt);
for (var i = 0, e = collection.length; i < e; ++i)
if (collection[i] == elt) return i;
return -1;
}
function completeEndTag(cm, pos, tagName) {
cm.replaceSelection('/' + tagName + '>');
cm.setCursor({line: pos.line, ch: pos.ch + tagName.length + 2 });
}
})();

View File

@@ -1,23 +0,0 @@
.CodeMirror-dialog {
position: relative;
}
.CodeMirror-dialog > div {
position: absolute;
top: 0; left: 0; right: 0;
background: white;
border-bottom: 1px solid #eee;
z-index: 15;
padding: .1em .8em;
overflow: hidden;
color: #333;
}
.CodeMirror-dialog input {
border: none;
outline: none;
background: transparent;
width: 20em;
color: inherit;
font-family: monospace;
}

View File

@@ -1,63 +0,0 @@
// Open simple dialogs on top of an editor. Relies on dialog.css.
(function() {
function dialogDiv(cm, template) {
var wrap = cm.getWrapperElement();
var dialog = wrap.insertBefore(document.createElement("div"), wrap.firstChild);
dialog.className = "CodeMirror-dialog";
dialog.innerHTML = '<div>' + template + '</div>';
return dialog;
}
CodeMirror.defineExtension("openDialog", function(template, callback) {
var dialog = dialogDiv(this, template);
var closed = false, me = this;
function close() {
if (closed) return;
closed = true;
dialog.parentNode.removeChild(dialog);
}
var inp = dialog.getElementsByTagName("input")[0];
if (inp) {
CodeMirror.connect(inp, "keydown", function(e) {
if (e.keyCode == 13 || e.keyCode == 27) {
CodeMirror.e_stop(e);
close();
me.focus();
if (e.keyCode == 13) callback(inp.value);
}
});
inp.focus();
CodeMirror.connect(inp, "blur", close);
}
return close;
});
CodeMirror.defineExtension("openConfirm", function(template, callbacks) {
var dialog = dialogDiv(this, template);
var buttons = dialog.getElementsByTagName("button");
var closed = false, me = this, blurring = 1;
function close() {
if (closed) return;
closed = true;
dialog.parentNode.removeChild(dialog);
me.focus();
}
buttons[0].focus();
for (var i = 0; i < buttons.length; ++i) {
var b = buttons[i];
(function(callback) {
CodeMirror.connect(b, "click", function(e) {
CodeMirror.e_preventDefault(e);
close();
if (callback) callback(me);
});
})(callbacks[i]);
CodeMirror.connect(b, "blur", function() {
--blurring;
setTimeout(function() { if (blurring <= 0) close(); }, 200);
});
CodeMirror.connect(b, "focus", function() { ++blurring; });
}
});
})();

View File

@@ -1,294 +0,0 @@
// ============== Formatting extensions ============================
// A common storage for all mode-specific formatting features
if (!CodeMirror.modeExtensions) CodeMirror.modeExtensions = {};
// Returns the extension of the editor's current mode
CodeMirror.defineExtension("getModeExt", function () {
var mname = CodeMirror.resolveMode(this.getOption("mode")).name;
var ext = CodeMirror.modeExtensions[mname];
if (!ext) throw new Error("No extensions found for mode " + mname);
return ext;
});
// If the current mode is 'htmlmixed', returns the extension of a mode located at
// the specified position (can be htmlmixed, css or javascript). Otherwise, simply
// returns the extension of the editor's current mode.
CodeMirror.defineExtension("getModeExtAtPos", function (pos) {
var token = this.getTokenAt(pos);
if (token && token.state && token.state.mode)
return CodeMirror.modeExtensions[token.state.mode == "html" ? "htmlmixed" : token.state.mode];
else
return this.getModeExt();
});
// Comment/uncomment the specified range
CodeMirror.defineExtension("commentRange", function (isComment, from, to) {
var curMode = this.getModeExtAtPos(this.getCursor());
if (isComment) { // Comment range
var commentedText = this.getRange(from, to);
this.replaceRange(curMode.commentStart + this.getRange(from, to) + curMode.commentEnd
, from, to);
if (from.line == to.line && from.ch == to.ch) { // An empty comment inserted - put cursor inside
this.setCursor(from.line, from.ch + curMode.commentStart.length);
}
}
else { // Uncomment range
var selText = this.getRange(from, to);
var startIndex = selText.indexOf(curMode.commentStart);
var endIndex = selText.lastIndexOf(curMode.commentEnd);
if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
// Take string till comment start
selText = selText.substr(0, startIndex)
// From comment start till comment end
+ selText.substring(startIndex + curMode.commentStart.length, endIndex)
// From comment end till string end
+ selText.substr(endIndex + curMode.commentEnd.length);
}
this.replaceRange(selText, from, to);
}
});
// Applies automatic mode-aware indentation to the specified range
CodeMirror.defineExtension("autoIndentRange", function (from, to) {
var cmInstance = this;
this.operation(function () {
for (var i = from.line; i <= to.line; i++) {
cmInstance.indentLine(i, "smart");
}
});
});
// Applies automatic formatting to the specified range
CodeMirror.defineExtension("autoFormatRange", function (from, to) {
var absStart = this.indexFromPos(from);
var absEnd = this.indexFromPos(to);
// Insert additional line breaks where necessary according to the
// mode's syntax
var res = this.getModeExt().autoFormatLineBreaks(this.getValue(), absStart, absEnd);
var cmInstance = this;
// Replace and auto-indent the range
this.operation(function () {
cmInstance.replaceRange(res, from, to);
var startLine = cmInstance.posFromIndex(absStart).line;
var endLine = cmInstance.posFromIndex(absStart + res.length).line;
for (var i = startLine; i <= endLine; i++) {
cmInstance.indentLine(i, "smart");
}
});
});
// Define extensions for a few modes
CodeMirror.modeExtensions["css"] = {
commentStart: "/*",
commentEnd: "*/",
wordWrapChars: [";", "\\{", "\\}"],
autoFormatLineBreaks: function (text) {
return text.replace(new RegExp("(;|\\{|\\})([^\r\n])", "g"), "$1\n$2");
}
};
CodeMirror.modeExtensions["javascript"] = {
commentStart: "/*",
commentEnd: "*/",
wordWrapChars: [";", "\\{", "\\}"],
getNonBreakableBlocks: function (text) {
var nonBreakableRegexes = [
new RegExp("for\\s*?\\(([\\s\\S]*?)\\)"),
new RegExp("'([\\s\\S]*?)('|$)"),
new RegExp("\"([\\s\\S]*?)(\"|$)"),
new RegExp("//.*([\r\n]|$)")
];
var nonBreakableBlocks = new Array();
for (var i = 0; i < nonBreakableRegexes.length; i++) {
var curPos = 0;
while (curPos < text.length) {
var m = text.substr(curPos).match(nonBreakableRegexes[i]);
if (m != null) {
nonBreakableBlocks.push({
start: curPos + m.index,
end: curPos + m.index + m[0].length
});
curPos += m.index + Math.max(1, m[0].length);
}
else { // No more matches
break;
}
}
}
nonBreakableBlocks.sort(function (a, b) {
return a.start - b.start;
});
return nonBreakableBlocks;
},
autoFormatLineBreaks: function (text) {
var curPos = 0;
var reLinesSplitter = new RegExp("(;|\\{|\\})([^\r\n])", "g");
var nonBreakableBlocks = this.getNonBreakableBlocks(text);
if (nonBreakableBlocks != null) {
var res = "";
for (var i = 0; i < nonBreakableBlocks.length; i++) {
if (nonBreakableBlocks[i].start > curPos) { // Break lines till the block
res += text.substring(curPos, nonBreakableBlocks[i].start).replace(reLinesSplitter, "$1\n$2");
curPos = nonBreakableBlocks[i].start;
}
if (nonBreakableBlocks[i].start <= curPos
&& nonBreakableBlocks[i].end >= curPos) { // Skip non-breakable block
res += text.substring(curPos, nonBreakableBlocks[i].end);
curPos = nonBreakableBlocks[i].end;
}
}
if (curPos < text.length - 1) {
res += text.substr(curPos).replace(reLinesSplitter, "$1\n$2");
}
return res;
}
else {
return text.replace(reLinesSplitter, "$1\n$2");
}
}
};
CodeMirror.modeExtensions["xml"] = {
commentStart: "<!--",
commentEnd: "-->",
wordWrapChars: [">"],
autoFormatLineBreaks: function (text) {
var lines = text.split("\n");
var reProcessedPortion = new RegExp("(^\\s*?<|^[^<]*?)(.+)(>\\s*?$|[^>]*?$)");
var reOpenBrackets = new RegExp("<", "g");
var reCloseBrackets = new RegExp("(>)([^\r\n])", "g");
for (var i = 0; i < lines.length; i++) {
var mToProcess = lines[i].match(reProcessedPortion);
if (mToProcess != null && mToProcess.length > 3) { // The line starts with whitespaces and ends with whitespaces
lines[i] = mToProcess[1]
+ mToProcess[2].replace(reOpenBrackets, "\n$&").replace(reCloseBrackets, "$1\n$2")
+ mToProcess[3];
continue;
}
}
return lines.join("\n");
}
};
CodeMirror.modeExtensions["htmlmixed"] = {
commentStart: "<!--",
commentEnd: "-->",
wordWrapChars: [">", ";", "\\{", "\\}"],
getModeInfos: function (text, absPos) {
var modeInfos = new Array();
modeInfos[0] =
{
pos: 0,
modeExt: CodeMirror.modeExtensions["xml"],
modeName: "xml"
};
var modeMatchers = new Array();
modeMatchers[0] =
{
regex: new RegExp("<style[^>]*>([\\s\\S]*?)(</style[^>]*>|$)", "i"),
modeExt: CodeMirror.modeExtensions["css"],
modeName: "css"
};
modeMatchers[1] =
{
regex: new RegExp("<script[^>]*>([\\s\\S]*?)(</script[^>]*>|$)", "i"),
modeExt: CodeMirror.modeExtensions["javascript"],
modeName: "javascript"
};
var lastCharPos = (typeof (absPos) !== "undefined" ? absPos : text.length - 1);
// Detect modes for the entire text
for (var i = 0; i < modeMatchers.length; i++) {
var curPos = 0;
while (curPos <= lastCharPos) {
var m = text.substr(curPos).match(modeMatchers[i].regex);
if (m != null) {
if (m.length > 1 && m[1].length > 0) {
// Push block begin pos
var blockBegin = curPos + m.index + m[0].indexOf(m[1]);
modeInfos.push(
{
pos: blockBegin,
modeExt: modeMatchers[i].modeExt,
modeName: modeMatchers[i].modeName
});
// Push block end pos
modeInfos.push(
{
pos: blockBegin + m[1].length,
modeExt: modeInfos[0].modeExt,
modeName: modeInfos[0].modeName
});
curPos += m.index + m[0].length;
continue;
}
else {
curPos += m.index + Math.max(m[0].length, 1);
}
}
else { // No more matches
break;
}
}
}
// Sort mode infos
modeInfos.sort(function sortModeInfo(a, b) {
return a.pos - b.pos;
});
return modeInfos;
},
autoFormatLineBreaks: function (text, startPos, endPos) {
var modeInfos = this.getModeInfos(text);
var reBlockStartsWithNewline = new RegExp("^\\s*?\n");
var reBlockEndsWithNewline = new RegExp("\n\\s*?$");
var res = "";
// Use modes info to break lines correspondingly
if (modeInfos.length > 1) { // Deal with multi-mode text
for (var i = 1; i <= modeInfos.length; i++) {
var selStart = modeInfos[i - 1].pos;
var selEnd = (i < modeInfos.length ? modeInfos[i].pos : endPos);
if (selStart >= endPos) { // The block starts later than the needed fragment
break;
}
if (selStart < startPos) {
if (selEnd <= startPos) { // The block starts earlier than the needed fragment
continue;
}
selStart = startPos;
}
if (selEnd > endPos) {
selEnd = endPos;
}
var textPortion = text.substring(selStart, selEnd);
if (modeInfos[i - 1].modeName != "xml") { // Starting a CSS or JavaScript block
if (!reBlockStartsWithNewline.test(textPortion)
&& selStart > 0) { // The block does not start with a line break
textPortion = "\n" + textPortion;
}
if (!reBlockEndsWithNewline.test(textPortion)
&& selEnd < text.length - 1) { // The block does not end with a line break
textPortion += "\n";
}
}
res += modeInfos[i - 1].modeExt.autoFormatLineBreaks(textPortion);
}
}
else { // Single-mode text
res = modeInfos[0].modeExt.autoFormatLineBreaks(text.substring(startPos, endPos));
}
return res;
}
};

View File

@@ -1,134 +0,0 @@
(function () {
function forEach(arr, f) {
for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
}
function arrayContains(arr, item) {
if (!Array.prototype.indexOf) {
var i = arr.length;
while (i--) {
if (arr[i] === item) {
return true;
}
}
return false;
}
return arr.indexOf(item) != -1;
}
function scriptHint(editor, keywords, getToken) {
// Find the token at the cursor
var cur = editor.getCursor(), token = getToken(editor, cur), tprop = token;
// If it's not a 'word-style' token, ignore the token.
if (!/^[\w$_]*$/.test(token.string)) {
token = tprop = {start: cur.ch, end: cur.ch, string: "", state: token.state,
className: token.string == "." ? "property" : null};
}
// If it is a property, find out what it is a property of.
while (tprop.className == "property") {
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
if (tprop.string != ".") return;
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
if (tprop.string == ')') {
var level = 1;
do {
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
switch (tprop.string) {
case ')': level++; break;
case '(': level--; break;
default: break;
}
} while (level > 0)
tprop = getToken(editor, {line: cur.line, ch: tprop.start});
if (tprop.className == 'variable')
tprop.className = 'function';
else return; // no clue
}
if (!context) var context = [];
context.push(tprop);
}
return {list: getCompletions(token, context, keywords),
from: {line: cur.line, ch: token.start},
to: {line: cur.line, ch: token.end}};
}
CodeMirror.javascriptHint = function(editor) {
return scriptHint(editor, javascriptKeywords,
function (e, cur) {return e.getTokenAt(cur);});
}
function getCoffeeScriptToken(editor, cur) {
// This getToken, it is for coffeescript, imitates the behavior of
// getTokenAt method in javascript.js, that is, returning "property"
// type and treat "." as indepenent token.
var token = editor.getTokenAt(cur);
if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
token.end = token.start;
token.string = '.';
token.className = "property";
}
else if (/^\.[\w$_]*$/.test(token.string)) {
token.className = "property";
token.start++;
token.string = token.string.replace(/\./, '');
}
return token;
}
CodeMirror.coffeescriptHint = function(editor) {
return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken);
}
var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
"toUpperCase toLowerCase split concat match replace search").split(" ");
var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
"lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
var funcProps = "prototype apply call bind".split(" ");
var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " +
"if in instanceof new null return switch throw true try typeof var void while with").split(" ");
var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
"if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
function getCompletions(token, context, keywords) {
var found = [], start = token.string;
function maybeAdd(str) {
if (str.indexOf(start) == 0 && !arrayContains(found, str)) found.push(str);
}
function gatherCompletions(obj) {
if (typeof obj == "string") forEach(stringProps, maybeAdd);
else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
else if (obj instanceof Function) forEach(funcProps, maybeAdd);
for (var name in obj) maybeAdd(name);
}
if (context) {
// If this is a property, see if it belongs to some object we can
// find in the current environment.
var obj = context.pop(), base;
if (obj.className == "variable")
base = window[obj.string];
else if (obj.className == "string")
base = "";
else if (obj.className == "atom")
base = 1;
else if (obj.className == "function") {
if (window.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
(typeof window.jQuery == 'function'))
base = window.jQuery();
else if (window._ != null && (obj.string == '_') && (typeof window._ == 'function'))
base = window._();
}
while (base != null && context.length)
base = base[context.pop().string];
if (base != null) gatherCompletions(base);
}
else {
// If not, just look in the window object and any local scope
// (reading into JS mode internals to get at the local variables)
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
gatherCompletions(window);
forEach(keywords, maybeAdd);
}
return found;
}
})();

View File

@@ -1,51 +0,0 @@
(function() {
if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
var loading = {};
function splitCallback(cont, n) {
var countDown = n;
return function() { if (--countDown == 0) cont(); }
}
function ensureDeps(mode, cont) {
var deps = CodeMirror.modes[mode].dependencies;
if (!deps) return cont();
var missing = [];
for (var i = 0; i < deps.length; ++i) {
if (!CodeMirror.modes.hasOwnProperty(deps[i]))
missing.push(deps[i]);
}
if (!missing.length) return cont();
var split = splitCallback(cont, missing.length);
for (var i = 0; i < missing.length; ++i)
CodeMirror.requireMode(missing[i], split);
}
CodeMirror.requireMode = function(mode, cont) {
if (typeof mode != "string") mode = mode.name;
if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
var script = document.createElement("script");
script.src = CodeMirror.modeURL.replace(/%N/g, mode);
var others = document.getElementsByTagName("script")[0];
others.parentNode.insertBefore(script, others);
var list = loading[mode] = [cont];
var count = 0, poll = setInterval(function() {
if (++count > 100) return clearInterval(poll);
if (CodeMirror.modes.hasOwnProperty(mode)) {
clearInterval(poll);
loading[mode] = null;
ensureDeps(mode, function() {
for (var i = 0; i < list.length; ++i) list[i]();
});
}
}, 200);
};
CodeMirror.autoLoadMode = function(instance, mode) {
if (!CodeMirror.modes.hasOwnProperty(mode))
CodeMirror.requireMode(mode, function() {
instance.setOption("mode", instance.getOption("mode"));
});
};
}());

View File

@@ -1,51 +0,0 @@
// Utility function that allows modes to be combined. The mode given
// as the base argument takes care of most of the normal mode
// functionality, but a second (typically simple) mode is used, which
// can override the style of text. Both modes get to parse all of the
// text, but when both assign a non-null style to a piece of code, the
// overlay wins, unless the combine argument was true, in which case
// the styles are combined.
CodeMirror.overlayParser = function(base, overlay, combine) {
return {
startState: function() {
return {
base: CodeMirror.startState(base),
overlay: CodeMirror.startState(overlay),
basePos: 0, baseCur: null,
overlayPos: 0, overlayCur: null
};
},
copyState: function(state) {
return {
base: CodeMirror.copyState(base, state.base),
overlay: CodeMirror.copyState(overlay, state.overlay),
basePos: state.basePos, baseCur: null,
overlayPos: state.overlayPos, overlayCur: null
};
},
token: function(stream, state) {
if (stream.start == state.basePos) {
state.baseCur = base.token(stream, state.base);
state.basePos = stream.pos;
}
if (stream.start == state.overlayPos) {
stream.pos = stream.start;
state.overlayCur = overlay.token(stream, state.overlay);
state.overlayPos = stream.pos;
}
stream.pos = Math.min(state.basePos, state.overlayPos);
if (stream.eol()) state.basePos = state.overlayPos = 0;
if (state.overlayCur == null) return state.baseCur;
if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur;
else return state.overlayCur;
},
indent: base.indent && function(state, textAfter) {
return base.indent(state.base, textAfter);
},
electricChars: base.electricChars
};
};

View File

@@ -1,49 +0,0 @@
CodeMirror.runMode = function(string, modespec, callback, options) {
var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
var isNode = callback.nodeType == 1;
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
if (isNode) {
var node = callback, accum = [], col = 0;
callback = function(text, style) {
if (text == "\n") {
accum.push("<br>");
col = 0;
return;
}
var escaped = "";
// HTML-escape and replace tabs
for (var pos = 0;;) {
var idx = text.indexOf("\t", pos);
if (idx == -1) {
escaped += CodeMirror.htmlEscape(text.slice(pos));
col += text.length - pos;
break;
} else {
col += idx - pos;
escaped += CodeMirror.htmlEscape(text.slice(pos, idx));
var size = tabSize - col % tabSize;
col += size;
for (var i = 0; i < size; ++i) escaped += " ";
pos = idx + 1;
}
}
if (style)
accum.push("<span class=\"cm-" + CodeMirror.htmlEscape(style) + "\">" + escaped + "</span>");
else
accum.push(escaped);
}
}
var lines = CodeMirror.splitLines(string), state = CodeMirror.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n");
var stream = new CodeMirror.StringStream(lines[i]);
while (!stream.eol()) {
var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start);
stream.start = stream.pos;
}
}
if (isNode)
node.innerHTML = accum.join("");
};

View File

@@ -1,114 +0,0 @@
// Define search commands. Depends on dialog.js or another
// implementation of the openDialog method.
// Replace works a little oddly -- it will do the replace on the next
// Ctrl-G (or whatever is bound to findNext) press. You prevent a
// replace by making sure the match is no longer selected when hitting
// Ctrl-G.
(function() {
function SearchState() {
this.posFrom = this.posTo = this.query = null;
this.marked = [];
}
function getSearchState(cm) {
return cm._searchState || (cm._searchState = new SearchState());
}
function dialog(cm, text, shortText, f) {
if (cm.openDialog) cm.openDialog(text, f);
else f(prompt(shortText, ""));
}
function confirmDialog(cm, text, shortText, fs) {
if (cm.openConfirm) cm.openConfirm(text, fs);
else if (confirm(shortText)) fs[0]();
}
function parseQuery(query) {
var isRE = query.match(/^\/(.*)\/$/);
return isRE ? new RegExp(isRE[1]) : query;
}
var queryDialog =
'Search: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
function doSearch(cm, rev) {
var state = getSearchState(cm);
if (state.query) return findNext(cm, rev);
dialog(cm, queryDialog, "Search for:", function(query) {
cm.operation(function() {
if (!query || state.query) return;
state.query = parseQuery(query);
if (cm.lineCount() < 2000) { // This is too expensive on big documents.
for (var cursor = cm.getSearchCursor(query); cursor.findNext();)
state.marked.push(cm.markText(cursor.from(), cursor.to(), "CodeMirror-searching"));
}
state.posFrom = state.posTo = cm.getCursor();
findNext(cm, rev);
});
});
}
function findNext(cm, rev) {cm.operation(function() {
var state = getSearchState(cm);
var cursor = cm.getSearchCursor(state.query, rev ? state.posFrom : state.posTo);
if (!cursor.find(rev)) {
cursor = cm.getSearchCursor(state.query, rev ? {line: cm.lineCount() - 1} : {line: 0, ch: 0});
if (!cursor.find(rev)) return;
}
cm.setSelection(cursor.from(), cursor.to());
state.posFrom = cursor.from(); state.posTo = cursor.to();
})}
function clearSearch(cm) {cm.operation(function() {
var state = getSearchState(cm);
if (!state.query) return;
state.query = null;
for (var i = 0; i < state.marked.length; ++i) state.marked[i].clear();
state.marked.length = 0;
})}
var replaceQueryDialog =
'Replace: <input type="text" style="width: 10em"/> <span style="color: #888">(Use /re/ syntax for regexp search)</span>';
var replacementQueryDialog = 'With: <input type="text" style="width: 10em"/>';
var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
function replace(cm, all) {
dialog(cm, replaceQueryDialog, "Replace:", function(query) {
if (!query) return;
query = parseQuery(query);
dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
if (all) {
cm.compoundChange(function() { cm.operation(function() {
for (var cursor = cm.getSearchCursor(query); cursor.findNext();) {
if (typeof query != "string") {
var match = cm.getRange(cursor.from(), cursor.to()).match(query);
cursor.replace(text.replace(/\$(\d)/, function(w, i) {return match[i];}));
} else cursor.replace(text);
}
})});
} else {
clearSearch(cm);
var cursor = cm.getSearchCursor(query, cm.getCursor());
function advance() {
var start = cursor.from(), match;
if (!(match = cursor.findNext())) {
cursor = cm.getSearchCursor(query);
if (!(match = cursor.findNext()) ||
(cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
}
cm.setSelection(cursor.from(), cursor.to());
confirmDialog(cm, doReplaceConfirm, "Replace?",
[function() {doReplace(match);}, advance]);
}
function doReplace(match) {
cursor.replace(typeof query == "string" ? text :
text.replace(/\$(\d)/, function(w, i) {return match[i];}));
advance();
}
advance();
}
});
});
}
CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
CodeMirror.commands.findNext = doSearch;
CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
CodeMirror.commands.clearSearch = clearSearch;
CodeMirror.commands.replace = replace;
CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
})();

View File

@@ -1,16 +0,0 @@
.CodeMirror-completions {
position: absolute;
z-index: 10;
overflow: hidden;
-webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
-moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
box-shadow: 2px 3px 5px rgba(0,0,0,.2);
}
.CodeMirror-completions select {
background: #fafafa;
outline: none;
border: none;
padding: 0;
margin: 0;
font-family: monospace;
}

View File

@@ -1,72 +0,0 @@
(function() {
CodeMirror.simpleHint = function(editor, getHints) {
// We want a single cursor position.
if (editor.somethingSelected()) return;
var result = getHints(editor);
if (!result || !result.list.length) return;
var completions = result.list;
function insert(str) {
editor.replaceRange(str, result.from, result.to);
}
// When there is only one completion, use it directly.
if (completions.length == 1) {insert(completions[0]); return true;}
// Build the select widget
var complete = document.createElement("div");
complete.className = "CodeMirror-completions";
var sel = complete.appendChild(document.createElement("select"));
// Opera doesn't move the selection when pressing up/down in a
// multi-select, but it does properly support the size property on
// single-selects, so no multi-select is necessary.
if (!window.opera) sel.multiple = true;
for (var i = 0; i < completions.length; ++i) {
var opt = sel.appendChild(document.createElement("option"));
opt.appendChild(document.createTextNode(completions[i]));
}
sel.firstChild.selected = true;
sel.size = Math.min(10, completions.length);
var pos = editor.cursorCoords();
complete.style.left = pos.x + "px";
complete.style.top = pos.yBot + "px";
document.body.appendChild(complete);
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
if(winW - pos.x < sel.clientWidth)
complete.style.left = (pos.x - sel.clientWidth) + "px";
// Hack to hide the scrollbar.
if (completions.length <= 10)
complete.style.width = (sel.clientWidth - 1) + "px";
var done = false;
function close() {
if (done) return;
done = true;
complete.parentNode.removeChild(complete);
}
function pick() {
insert(completions[sel.selectedIndex]);
close();
setTimeout(function(){editor.focus();}, 50);
}
CodeMirror.connect(sel, "blur", close);
CodeMirror.connect(sel, "keydown", function(event) {
var code = event.keyCode;
// Enter
if (code == 13) {CodeMirror.e_stop(event); pick();}
// Escape
else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
else if (code != 38 && code != 40) {
close(); editor.focus();
// Pass the event to the CodeMirror instance so that it can handle things like backspace properly.
editor.triggerOnKeyDown(event);
setTimeout(function(){CodeMirror.simpleHint(editor, getHints);}, 50);
}
});
CodeMirror.connect(sel, "dblclick", pick);
sel.focus();
// Opera sometimes ignores focusing a freshly created node
if (window.opera) setTimeout(function(){if (!done) sel.focus();}, 100);
return true;
};
})();

View File

@@ -1,101 +0,0 @@
<!doctype html>
<html>
<head>
<title>CodeMirror: C-like mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="clike.js"></script>
<link rel="stylesheet" href="../../doc/docs.css">
<style>.CodeMirror {border: 2px inset #dee;}</style>
</head>
<body>
<h1>CodeMirror: C-like mode</h1>
<form><textarea id="code" name="code">
/* C demo code */
#include <zmq.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
#include <stdio.h>
#include <fcntl.h>
#include <malloc.h>
typedef struct {
void* arg_socket;
zmq_msg_t* arg_msg;
char* arg_string;
unsigned long arg_len;
int arg_int, arg_command;
int signal_fd;
int pad;
void* context;
sem_t sem;
} acl_zmq_context;
#define p(X) (context->arg_##X)
void* zmq_thread(void* context_pointer) {
acl_zmq_context* context = (acl_zmq_context*)context_pointer;
char ok = 'K', err = 'X';
int res;
while (1) {
while ((res = sem_wait(&amp;context->sem)) == EINTR);
if (res) {write(context->signal_fd, &amp;err, 1); goto cleanup;}
switch(p(command)) {
case 0: goto cleanup;
case 1: p(socket) = zmq_socket(context->context, p(int)); break;
case 2: p(int) = zmq_close(p(socket)); break;
case 3: p(int) = zmq_bind(p(socket), p(string)); break;
case 4: p(int) = zmq_connect(p(socket), p(string)); break;
case 5: p(int) = zmq_getsockopt(p(socket), p(int), (void*)p(string), &amp;p(len)); break;
case 6: p(int) = zmq_setsockopt(p(socket), p(int), (void*)p(string), p(len)); break;
case 7: p(int) = zmq_send(p(socket), p(msg), p(int)); break;
case 8: p(int) = zmq_recv(p(socket), p(msg), p(int)); break;
case 9: p(int) = zmq_poll(p(socket), p(int), p(len)); break;
}
p(command) = errno;
write(context->signal_fd, &amp;ok, 1);
}
cleanup:
close(context->signal_fd);
free(context_pointer);
return 0;
}
void* zmq_thread_init(void* zmq_context, int signal_fd) {
acl_zmq_context* context = malloc(sizeof(acl_zmq_context));
pthread_t thread;
context->context = zmq_context;
context->signal_fd = signal_fd;
sem_init(&amp;context->sem, 1, 0);
pthread_create(&amp;thread, 0, &amp;zmq_thread, context);
pthread_detach(thread);
return context;
}
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-csrc"
});
</script>
<p>Simple mode that tries to handle C-like languages as well as it
can. Takes two configuration parameters: <code>keywords</code>, an
object whose property names are the keywords in the language,
and <code>useCPP</code>, which determines whether C preprocessor
directives are recognized.</p>
<p><strong>MIME types defined:</strong> <code>text/x-csrc</code>
(C code), <code>text/x-c++src</code> (C++
code), <code>text/x-java</code> (Java
code), <code>text/x-csharp</code> (C#).</p>
</body>
</html>

View File

@@ -1,727 +0,0 @@
<!doctype html>
<html>
<head>
<title>CodeMirror: CoffeeScript mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="coffeescript.js"></script>
<style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
<link rel="stylesheet" href="../../doc/docs.css">
</head>
<body>
<h1>CodeMirror: CoffeeScript mode</h1>
<form><textarea id="code" name="code">
# CoffeeScript mode for CodeMirror
# Copyright (c) 2011 Jeff Pickhardt, released under
# the MIT License.
#
# Modified from the Python CodeMirror mode, which also is
# under the MIT License Copyright (c) 2010 Timothy Farrell.
#
# The following script, Underscore.coffee, is used to
# demonstrate CoffeeScript mode for CodeMirror.
#
# To download CoffeeScript mode for CodeMirror, go to:
# https://github.com/pickhardt/coffeescript-codemirror-mode
# **Underscore.coffee
# (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.**
# Underscore is freely distributable under the terms of the
# [MIT license](http://en.wikipedia.org/wiki/MIT_License).
# Portions of Underscore are inspired by or borrowed from
# [Prototype.js](http://prototypejs.org/api), Oliver Steele's
# [Functional](http://osteele.com), and John Resig's
# [Micro-Templating](http://ejohn.org).
# For all details and documentation:
# http://documentcloud.github.com/underscore/
# Baseline setup
# --------------
# Establish the root object, `window` in the browser, or `global` on the server.
root = this
# Save the previous value of the `_` variable.
previousUnderscore = root._
### Multiline
comment
###
# Establish the object that gets thrown to break out of a loop iteration.
# `StopIteration` is SOP on Mozilla.
breaker = if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
#### Docco style single line comment (title)
# Helper function to escape **RegExp** contents, because JS doesn't have one.
escapeRegExp = (string) -> string.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1')
# Save bytes in the minified (but not gzipped) version:
ArrayProto = Array.prototype
ObjProto = Object.prototype
# Create quick reference variables for speed access to core prototypes.
slice = ArrayProto.slice
unshift = ArrayProto.unshift
toString = ObjProto.toString
hasOwnProperty = ObjProto.hasOwnProperty
propertyIsEnumerable = ObjProto.propertyIsEnumerable
# All **ECMA5** native implementations we hope to use are declared here.
nativeForEach = ArrayProto.forEach
nativeMap = ArrayProto.map
nativeReduce = ArrayProto.reduce
nativeReduceRight = ArrayProto.reduceRight
nativeFilter = ArrayProto.filter
nativeEvery = ArrayProto.every
nativeSome = ArrayProto.some
nativeIndexOf = ArrayProto.indexOf
nativeLastIndexOf = ArrayProto.lastIndexOf
nativeIsArray = Array.isArray
nativeKeys = Object.keys
# Create a safe reference to the Underscore object for use below.
_ = (obj) -> new wrapper(obj)
# Export the Underscore object for **CommonJS**.
if typeof(exports) != 'undefined' then exports._ = _
# Export Underscore to global scope.
root._ = _
# Current version.
_.VERSION = '1.1.0'
# Collection Functions
# --------------------
# The cornerstone, an **each** implementation.
# Handles objects implementing **forEach**, arrays, and raw objects.
_.each = (obj, iterator, context) ->
try
if nativeForEach and obj.forEach is nativeForEach
obj.forEach iterator, context
else if _.isNumber obj.length
iterator.call context, obj[i], i, obj for i in [0...obj.length]
else
iterator.call context, val, key, obj for own key, val of obj
catch e
throw e if e isnt breaker
obj
# Return the results of applying the iterator to each element. Use JavaScript
# 1.6's version of **map**, if possible.
_.map = (obj, iterator, context) ->
return obj.map(iterator, context) if nativeMap and obj.map is nativeMap
results = []
_.each obj, (value, index, list) ->
results.push iterator.call context, value, index, list
results
# **Reduce** builds up a single result from a list of values. Also known as
# **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.
_.reduce = (obj, iterator, memo, context) ->
if nativeReduce and obj.reduce is nativeReduce
iterator = _.bind iterator, context if context
return obj.reduce iterator, memo
_.each obj, (value, index, list) ->
memo = iterator.call context, memo, value, index, list
memo
# The right-associative version of **reduce**, also known as **foldr**. Uses
# JavaScript 1.8's version of **reduceRight**, if available.
_.reduceRight = (obj, iterator, memo, context) ->
if nativeReduceRight and obj.reduceRight is nativeReduceRight
iterator = _.bind iterator, context if context
return obj.reduceRight iterator, memo
reversed = _.clone(_.toArray(obj)).reverse()
_.reduce reversed, iterator, memo, context
# Return the first value which passes a truth test.
_.detect = (obj, iterator, context) ->
result = null
_.each obj, (value, index, list) ->
if iterator.call context, value, index, list
result = value
_.breakLoop()
result
# Return all the elements that pass a truth test. Use JavaScript 1.6's
# **filter**, if it exists.
_.filter = (obj, iterator, context) ->
return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter
results = []
_.each obj, (value, index, list) ->
results.push value if iterator.call context, value, index, list
results
# Return all the elements for which a truth test fails.
_.reject = (obj, iterator, context) ->
results = []
_.each obj, (value, index, list) ->
results.push value if not iterator.call context, value, index, list
results
# Determine whether all of the elements match a truth test. Delegate to
# JavaScript 1.6's **every**, if it is present.
_.every = (obj, iterator, context) ->
iterator ||= _.identity
return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
result = true
_.each obj, (value, index, list) ->
_.breakLoop() unless (result = result and iterator.call(context, value, index, list))
result
# Determine if at least one element in the object matches a truth test. Use
# JavaScript 1.6's **some**, if it exists.
_.some = (obj, iterator, context) ->
iterator ||= _.identity
return obj.some iterator, context if nativeSome and obj.some is nativeSome
result = false
_.each obj, (value, index, list) ->
_.breakLoop() if (result = iterator.call(context, value, index, list))
result
# Determine if a given value is included in the array or object,
# based on `===`.
_.include = (obj, target) ->
return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf
return true for own key, val of obj when val is target
false
# Invoke a method with arguments on every item in a collection.
_.invoke = (obj, method) ->
args = _.rest arguments, 2
(if method then val[method] else val).apply(val, args) for val in obj
# Convenience version of a common use case of **map**: fetching a property.
_.pluck = (obj, key) ->
_.map(obj, (val) -> val[key])
# Return the maximum item or (item-based computation).
_.max = (obj, iterator, context) ->
return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
result = computed: -Infinity
_.each obj, (value, index, list) ->
computed = if iterator then iterator.call(context, value, index, list) else value
computed >= result.computed and (result = {value: value, computed: computed})
result.value
# Return the minimum element (or element-based computation).
_.min = (obj, iterator, context) ->
return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
result = computed: Infinity
_.each obj, (value, index, list) ->
computed = if iterator then iterator.call(context, value, index, list) else value
computed < result.computed and (result = {value: value, computed: computed})
result.value
# Sort the object's values by a criterion produced by an iterator.
_.sortBy = (obj, iterator, context) ->
_.pluck(((_.map obj, (value, index, list) ->
{value: value, criteria: iterator.call(context, value, index, list)}
).sort((left, right) ->
a = left.criteria; b = right.criteria
if a < b then -1 else if a > b then 1 else 0
)), 'value')
# Use a comparator function to figure out at what index an object should
# be inserted so as to maintain order. Uses binary search.
_.sortedIndex = (array, obj, iterator) ->
iterator ||= _.identity
low = 0
high = array.length
while low < high
mid = (low + high) >> 1
if iterator(array[mid]) < iterator(obj) then low = mid + 1 else high = mid
low
# Convert anything iterable into a real, live array.
_.toArray = (iterable) ->
return [] if (!iterable)
return iterable.toArray() if (iterable.toArray)
return iterable if (_.isArray(iterable))
return slice.call(iterable) if (_.isArguments(iterable))
_.values(iterable)
# Return the number of elements in an object.
_.size = (obj) -> _.toArray(obj).length
# Array Functions
# ---------------
# Get the first element of an array. Passing `n` will return the first N
# values in the array. Aliased as **head**. The `guard` check allows it to work
# with **map**.
_.first = (array, n, guard) ->
if n and not guard then slice.call(array, 0, n) else array[0]
# Returns everything but the first entry of the array. Aliased as **tail**.
# Especially useful on the arguments object. Passing an `index` will return
# the rest of the values in the array from that index onward. The `guard`
# check allows it to work with **map**.
_.rest = (array, index, guard) ->
slice.call(array, if _.isUndefined(index) or guard then 1 else index)
# Get the last element of an array.
_.last = (array) -> array[array.length - 1]
# Trim out all falsy values from an array.
_.compact = (array) -> item for item in array when item
# Return a completely flattened version of an array.
_.flatten = (array) ->
_.reduce array, (memo, value) ->
return memo.concat(_.flatten(value)) if _.isArray value
memo.push value
memo
, []
# Return a version of the array that does not contain the specified value(s).
_.without = (array) ->
values = _.rest arguments
val for val in _.toArray(array) when not _.include values, val
# Produce a duplicate-free version of the array. If the array has already
# been sorted, you have the option of using a faster algorithm.
_.uniq = (array, isSorted) ->
memo = []
for el, i in _.toArray array
memo.push el if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
memo
# Produce an array that contains every item shared between all the
# passed-in arrays.
_.intersect = (array) ->
rest = _.rest arguments
_.select _.uniq(array), (item) ->
_.all rest, (other) ->
_.indexOf(other, item) >= 0
# Zip together multiple lists into a single array -- elements that share
# an index go together.
_.zip = ->
length = _.max _.pluck arguments, 'length'
results = new Array length
for i in [0...length]
results[i] = _.pluck arguments, String i
results
# If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),
# we need this function. Return the position of the first occurrence of an
# item in an array, or -1 if the item is not included in the array.
_.indexOf = (array, item) ->
return array.indexOf item if nativeIndexOf and array.indexOf is nativeIndexOf
i = 0; l = array.length
while l - i
if array[i] is item then return i else i++
-1
# Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,
# if possible.
_.lastIndexOf = (array, item) ->
return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf
i = array.length
while i
if array[i] is item then return i else i--
-1
# Generate an integer Array containing an arithmetic progression. A port of
# [the native Python **range** function](http://docs.python.org/library/functions.html#range).
_.range = (start, stop, step) ->
a = arguments
solo = a.length <= 1
i = start = if solo then 0 else a[0]
stop = if solo then a[0] else a[1]
step = a[2] or 1
len = Math.ceil((stop - start) / step)
return [] if len <= 0
range = new Array len
idx = 0
loop
return range if (if step > 0 then i - stop else stop - i) >= 0
range[idx] = i
idx++
i+= step
# Function Functions
# ------------------
# Create a function bound to a given object (assigning `this`, and arguments,
# optionally). Binding with arguments is also known as **curry**.
_.bind = (func, obj) ->
args = _.rest arguments, 2
-> func.apply obj or root, args.concat arguments
# Bind all of an object's methods to that object. Useful for ensuring that
# all callbacks defined on an object belong to it.
_.bindAll = (obj) ->
funcs = if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
_.each funcs, (f) -> obj[f] = _.bind obj[f], obj
obj
# Delays a function for the given number of milliseconds, and then calls
# it with the arguments supplied.
_.delay = (func, wait) ->
args = _.rest arguments, 2
setTimeout((-> func.apply(func, args)), wait)
# Memoize an expensive function by storing its results.
_.memoize = (func, hasher) ->
memo = {}
hasher or= _.identity
->
key = hasher.apply this, arguments
return memo[key] if key of memo
memo[key] = func.apply this, arguments
# Defers a function, scheduling it to run after the current call stack has
# cleared.
_.defer = (func) ->
_.delay.apply _, [func, 1].concat _.rest arguments
# Returns the first function passed as an argument to the second,
# allowing you to adjust arguments, run code before and after, and
# conditionally execute the original function.
_.wrap = (func, wrapper) ->
-> wrapper.apply wrapper, [func].concat arguments
# Returns a function that is the composition of a list of functions, each
# consuming the return value of the function that follows.
_.compose = ->
funcs = arguments
->
args = arguments
for i in [funcs.length - 1..0] by -1
args = [funcs[i].apply(this, args)]
args[0]
# Object Functions
# ----------------
# Retrieve the names of an object's properties.
_.keys = nativeKeys or (obj) ->
return _.range 0, obj.length if _.isArray(obj)
key for key, val of obj
# Retrieve the values of an object's properties.
_.values = (obj) ->
_.map obj, _.identity
# Return a sorted list of the function names available in Underscore.
_.functions = (obj) ->
_.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()
# Extend a given object with all of the properties in a source object.
_.extend = (obj) ->
for source in _.rest(arguments)
obj[key] = val for key, val of source
obj
# Create a (shallow-cloned) duplicate of an object.
_.clone = (obj) ->
return obj.slice 0 if _.isArray obj
_.extend {}, obj
# Invokes interceptor with the obj, and then returns obj.
# The primary purpose of this method is to "tap into" a method chain,
# in order to perform operations on intermediate results within
the chain.
_.tap = (obj, interceptor) ->
interceptor obj
obj
# Perform a deep comparison to check if two objects are equal.
_.isEqual = (a, b) ->
# Check object identity.
return true if a is b
# Different types?
atype = typeof(a); btype = typeof(b)
return false if atype isnt btype
# Basic equality test (watch out for coercions).
return true if `a == b`
# One is falsy and the other truthy.
return false if (!a and b) or (a and !b)
# One of them implements an `isEqual()`?
return a.isEqual(b) if a.isEqual
# Check dates' integer values.
return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
# Both are NaN?
return false if _.isNaN(a) and _.isNaN(b)
# Compare regular expressions.
if _.isRegExp(a) and _.isRegExp(b)
return a.source is b.source and
a.global is b.global and
a.ignoreCase is b.ignoreCase and
a.multiline is b.multiline
# If a is not an object by this point, we can't handle it.
return false if atype isnt 'object'
# Check for different array lengths before comparing contents.
return false if a.length and (a.length isnt b.length)
# Nothing else worked, deep compare the contents.
aKeys = _.keys(a); bKeys = _.keys(b)
# Different object sizes?
return false if aKeys.length isnt bKeys.length
# Recursive comparison of contents.
return false for key, val of a when !(key of b) or !_.isEqual(val, b[key])
true
# Is a given array or object empty?
_.isEmpty = (obj) ->
return obj.length is 0 if _.isArray(obj) or _.isString(obj)
return false for own key of obj
true
# Is a given value a DOM element?
_.isElement = (obj) -> obj and obj.nodeType is 1
# Is a given value an array?
_.isArray = nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)
# Is a given variable an arguments object?
_.isArguments = (obj) -> obj and obj.callee
# Is the given value a function?
_.isFunction = (obj) -> !!(obj and obj.constructor and obj.call and obj.apply)
# Is the given value a string?
_.isString = (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))
# Is a given value a number?
_.isNumber = (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'
# Is a given value a boolean?
_.isBoolean = (obj) -> obj is true or obj is false
# Is a given value a Date?
_.isDate = (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
# Is the given value a regular expression?
_.isRegExp = (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
# Is the given value NaN -- this one is interesting. `NaN != NaN`, and
# `isNaN(undefined) == true`, so we make sure it's a number first.
_.isNaN = (obj) -> _.isNumber(obj) and window.isNaN(obj)
# Is a given value equal to null?
_.isNull = (obj) -> obj is null
# Is a given variable undefined?
_.isUndefined = (obj) -> typeof obj is 'undefined'
# Utility Functions
# -----------------
# Run Underscore.js in noConflict mode, returning the `_` variable to its
# previous owner. Returns a reference to the Underscore object.
_.noConflict = ->
root._ = previousUnderscore
this
# Keep the identity function around for default iterators.
_.identity = (value) -> value
# Run a function `n` times.
_.times = (n, iterator, context) ->
iterator.call context, i for i in [0...n]
# Break out of the middle of an iteration.
_.breakLoop = -> throw breaker
# Add your own custom functions to the Underscore object, ensuring that
# they're correctly added to the OOP wrapper as well.
_.mixin = (obj) ->
for name in _.functions(obj)
addToWrapper name, _[name] = obj[name]
# Generate a unique integer id (unique within the entire client session).
# Useful for temporary DOM ids.
idCounter = 0
_.uniqueId = (prefix) ->
(prefix or '') + idCounter++
# By default, Underscore uses **ERB**-style template delimiters, change the
# following template settings to use alternative delimiters.
_.templateSettings = {
start: '<%'
end: '%>'
interpolate: /<%=(.+?)%>/g
}
# JavaScript templating a-la **ERB**, pilfered from John Resig's
# *Secrets of the JavaScript Ninja*, page 83.
# Single-quote fix from Rick Strahl.
# With alterations for arbitrary delimiters, and to preserve whitespace.
_.template = (str, data) ->
c = _.templateSettings
endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
fn = new Function 'obj',
'var p=[],print=function(){p.push.apply(p,arguments);};' +
'with(obj||{}){p.push(\'' +
str.replace(/\r/g, '\\r')
.replace(/\n/g, '\\n')
.replace(/\t/g, '\\t')
.replace(endMatch,"<22><><EFBFBD>")
.split("'").join("\\'")
.split("<22><><EFBFBD>").join("'")
.replace(c.interpolate, "',$1,'")
.split(c.start).join("');")
.split(c.end).join("p.push('") +
"');}return p.join('');"
if data then fn(data) else fn
# Aliases
# -------
_.forEach = _.each
_.foldl = _.inject = _.reduce
_.foldr = _.reduceRight
_.select = _.filter
_.all = _.every
_.any = _.some
_.contains = _.include
_.head = _.first
_.tail = _.rest
_.methods = _.functions
# Setup the OOP Wrapper
# ---------------------
# If Underscore is called as a function, it returns a wrapped object that
# can be used OO-style. This wrapper holds altered versions of all the
# underscore functions. Wrapped objects may be chained.
wrapper = (obj) ->
this._wrapped = obj
this
# Helper function to continue chaining intermediate results.
result = (obj, chain) ->
if chain then _(obj).chain() else obj
# A method to easily add functions to the OOP wrapper.
addToWrapper = (name, func) ->
wrapper.prototype[name] = ->
args = _.toArray arguments
unshift.call args, this._wrapped
result func.apply(_, args), this._chain
# Add all ofthe Underscore functions to the wrapper object.
_.mixin _
# Add all mutator Array functions to the wrapper.
_.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) ->
method = Array.prototype[name]
wrapper.prototype[name] = ->
method.apply(this._wrapped, arguments)
result(this._wrapped, this._chain)
# Add all accessor Array functions to the wrapper.
_.each ['concat', 'join', 'slice'], (name) ->
method = Array.prototype[name]
wrapper.prototype[name] = ->
result(method.apply(this._wrapped, arguments), this._chain)
# Start chaining a wrapped Underscore object.
wrapper::chain = ->
this._chain = true
this
# Extracts the result from a wrapped and chained object.
wrapper::value = -> this._wrapped
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
</script>
<p><strong>MIME types defined:</strong> <code>text/x-coffeescript</code>.</p>
<p>The CoffeeScript mode was written by Jeff Pickhardt (<a href="LICENSE">license</a>).</p>
</body>
</html>

View File

@@ -1,55 +0,0 @@
<!doctype html>
<html>
<head>
<title>CodeMirror: CSS mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="css.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style>
<link rel="stylesheet" href="../../doc/docs.css">
</head>
<body>
<h1>CodeMirror: CSS mode</h1>
<form><textarea id="code" name="code">
/* Some example CSS */
@import url("something.css");
body {
margin: 0;
padding: 3em 6em;
font-family: tahoma, arial, sans-serif;
color: #000;
}
#navigation a {
font-weight: bold;
text-decoration: none !important;
}
h1 {
font-size: 2.5em;
}
h2 {
font-size: 1.7em;
}
h1:before, h2:before {
content: "::";
}
code {
font-family: courier, monospace;
font-size: 80%;
color: #418A8A;
}
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
</script>
<p><strong>MIME types defined:</strong> <code>text/css</code>.</p>
</body>
</html>

View File

@@ -1,77 +0,0 @@
<!doctype html>
<html>
<head>
<title>CodeMirror: JavaScript mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="javascript.js"></script>
<link rel="stylesheet" href="../../doc/docs.css">
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
</head>
<body>
<h1>CodeMirror: JavaScript mode</h1>
<div><textarea id="code" name="code">
// Demo code (the actual new parser character stream implementation)
function StringStream(string) {
this.pos = 0;
this.string = string;
}
StringStream.prototype = {
done: function() {return this.pos >= this.string.length;},
peek: function() {return this.string.charAt(this.pos);},
next: function() {
if (this.pos &lt; this.string.length)
return this.string.charAt(this.pos++);
},
eat: function(match) {
var ch = this.string.charAt(this.pos);
if (typeof match == "string") var ok = ch == match;
else var ok = ch &amp;&amp; match.test ? match.test(ch) : match(ch);
if (ok) {this.pos++; return ch;}
},
eatWhile: function(match) {
var start = this.pos;
while (this.eat(match));
if (this.pos > start) return this.string.slice(start, this.pos);
},
backUp: function(n) {this.pos -= n;},
column: function() {return this.pos;},
eatSpace: function() {
var start = this.pos;
while (/\s/.test(this.string.charAt(this.pos))) this.pos++;
return this.pos - start;
},
match: function(pattern, consume, caseInsensitive) {
if (typeof pattern == "string") {
function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
if (consume !== false) this.pos += str.length;
return true;
}
}
else {
var match = this.string.slice(this.pos).match(pattern);
if (match &amp;&amp; consume !== false) this.pos += match[0].length;
return match;
}
}
};
</textarea></div>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
matchBrackets: true
});
</script>
<p>JavaScript mode supports a single configuration
option, <code>json</code>, which will set the mode to expect JSON
data rather than a JavaScript program.</p>
<p><strong>MIME types defined:</strong> <code>text/javascript</code>, <code>application/json</code>.</p>
</body>
</html>

View File

@@ -1,48 +0,0 @@
<!doctype html>
<html>
<head>
<title>CodeMirror: PHP mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../xml/xml.js"></script>
<script src="../javascript/javascript.js"></script>
<script src="../css/css.js"></script>
<script src="../clike/clike.js"></script>
<script src="php.js"></script>
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<link rel="stylesheet" href="../../doc/docs.css">
</head>
<body>
<h1>CodeMirror: PHP mode</h1>
<form><textarea id="code" name="code">
<?php
function hello($who) {
return "Hello " . $who;
}
?>
<p>The program says <?= hello("World") ?>.</p>
<script>
alert("And here is some JS code"); // also colored
</script>
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
matchBrackets: true,
mode: "application/x-httpd-php",
indentUnit: 4,
indentWithTabs: true,
enterMode: "keep",
tabMode: "shift"
});
</script>
<p>Simple HTML/PHP mode based on
the <a href="../clike/">C-like</a> mode. Depends on XML,
JavaScript, CSS, and C-like modes.</p>
<p><strong>MIME types defined:</strong> <code>application/x-httpd-php</code> (HTML with PHP code), <code>text/x-php</code> (plain, non-wrapped PHP code).</p>
</body>
</html>

View File

@@ -1,171 +0,0 @@
<!doctype html>
<html>
<head>
<title>CodeMirror: Ruby mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="ruby.js"></script>
<style>
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
.cm-s-default span.cm-arrow { color: red; }
</style>
<link rel="stylesheet" href="../../doc/docs.css">
</head>
<body>
<h1>CodeMirror: Ruby mode</h1>
<form><textarea id="code" name="code">
# Code from http://sandbox.mc.edu/~bennet/ruby/code/poly_rb.html
#
# This program evaluates polynomials. It first asks for the coefficients
# of a polynomial, which must be entered on one line, highest-order first.
# It then requests values of x and will compute the value of the poly for
# each x. It will repeatly ask for x values, unless you the user enters
# a blank line. It that case, it will ask for another polynomial. If the
# user types quit for either input, the program immediately exits.
#
#
# Function to evaluate a polynomial at x. The polynomial is given
# as a list of coefficients, from the greatest to the least.
def polyval(x, coef)
sum = 0
coef = coef.clone # Don't want to destroy the original
while true
sum += coef.shift # Add and remove the next coef
break if coef.empty? # If no more, done entirely.
sum *= x # This happens the right number of times.
end
return sum
end
#
# Function to read a line containing a list of integers and return
# them as an array of integers. If the string conversion fails, it
# throws TypeError. If the input line is the word 'quit', then it
# converts it to an end-of-file exception
def readints(prompt)
# Read a line
print prompt
line = readline.chomp
raise EOFError.new if line == 'quit' # You can also use a real EOF.
# Go through each item on the line, converting each one and adding it
# to retval.
retval = [ ]
for str in line.split(/\s+/)
if str =~ /^\-?\d+$/
retval.push(str.to_i)
else
raise TypeError.new
end
end
return retval
end
#
# Take a coeff and an exponent and return the string representation, ignoring
# the sign of the coefficient.
def term_to_str(coef, exp)
ret = ""
# Show coeff, unless it's 1 or at the right
coef = coef.abs
ret = coef.to_s unless coef == 1 && exp > 0
ret += "x" if exp > 0 # x if exponent not 0
ret += "^" + exp.to_s if exp > 1 # ^exponent, if > 1.
return ret
end
#
# Create a string of the polynomial in sort-of-readable form.
def polystr(p)
# Get the exponent of first coefficient, plus 1.
exp = p.length
# Assign exponents to each term, making pairs of coeff and exponent,
# Then get rid of the zero terms.
p = (p.map { |c| exp -= 1; [ c, exp ] }).select { |p| p[0] != 0 }
# If there's nothing left, it's a zero
return "0" if p.empty?
# *** Now p is a non-empty list of [ coef, exponent ] pairs. ***
# Convert the first term, preceded by a "-" if it's negative.
result = (if p[0][0] < 0 then "-" else "" end) + term_to_str(*p[0])
# Convert the rest of the terms, in each case adding the appropriate
# + or - separating them.
for term in p[1...p.length]
# Add the separator then the rep. of the term.
result += (if term[0] < 0 then " - " else " + " end) +
term_to_str(*term)
end
return result
end
#
# Run until some kind of endfile.
begin
# Repeat until an exception or quit gets us out.
while true
# Read a poly until it works. An EOF will except out of the
# program.
print "\n"
begin
poly = readints("Enter a polynomial coefficients: ")
rescue TypeError
print "Try again.\n"
retry
end
break if poly.empty?
# Read and evaluate x values until the user types a blank line.
# Again, an EOF will except out of the pgm.
while true
# Request an integer.
print "Enter x value or blank line: "
x = readline.chomp
break if x == ''
raise EOFError.new if x == 'quit'
# If it looks bad, let's try again.
if x !~ /^\-?\d+$/
print "That doesn't look like an integer. Please try again.\n"
next
end
# Convert to an integer and print the result.
x = x.to_i
print "p(x) = ", polystr(poly), "\n"
print "p(", x, ") = ", polyval(x, poly), "\n"
end
end
rescue EOFError
print "\n=== EOF ===\n"
rescue Interrupt, SignalException
print "\n=== Interrupted ===\n"
else
print "--- Bye ---\n"
end
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: "text/x-ruby",
tabMode: "indent",
matchBrackets: true,
indentUnit: 4
});
</script>
<p><strong>MIME types defined:</strong> <code>text/x-ruby</code>.</p>
<p>Development of the CodeMirror Ruby mode was kindly sponsored
by <a href="http://ubalo.com/">Ubalo</a>, who hold
the <a href="LICENSE">license</a>.</p>
</body>
</html>

View File

@@ -1,44 +0,0 @@
<!doctype html>
<html>
<head>
<title>CodeMirror: XML mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="xml.js"></script>
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<link rel="stylesheet" href="../../doc/docs.css">
</head>
<body>
<h1>CodeMirror: XML mode</h1>
<form><textarea id="code" name="code">
&lt;html style="color: green"&gt;
&lt;!-- this is a comment --&gt;
&lt;head&gt;
&lt;title&gt;HTML Example&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
The indentation tries to be &lt;em&gt;somewhat &amp;quot;do what
I mean&amp;quot;&lt;/em&gt;... but might not match your style.
&lt;/body&gt;
&lt;/html&gt;
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: {name: "xml", alignCDATA: true},
lineNumbers: true
});
</script>
<p>The XML mode supports two configuration parameters:</p>
<dl>
<dt><code>htmlMode (boolean)</code></dt>
<dd>This switches the mode to parse HTML instead of XML. This
means attributes do not have to be quoted, and some elements
(such as <code>br</code>) do not require a closing tag.</dd>
<dt><code>alignCDATA (boolean)</code></dt>
<dd>Setting this to true will force the opening tag of CDATA
blocks to not be indented.</dd>
</dl>
<p><strong>MIME types defined:</strong> <code>application/xml</code>, <code>text/html</code>.</p>
</body>
</html>

View File

@@ -44,17 +44,16 @@ Early version of the web based IDE which allows for creation of websites in the
$ git clone git@github:mattpass/ICEcoder
```
####Step 2: Upload all the files
####Step 2: Upload the files (Linux or Windows hosting OK)
```
Linux or Windows hosting OK
Upload to a new sub-dir URL such as yourdomain.com/_coder
Set public write permissions on the lib/settings.php file
Set public write permissions on the lib/config.php file
```
####Step 3: Start coding
```
Visit the sub-dir URL in your browser and enter a password
Now you're setup, auto-logged in too and ready to code
Now you're setup, auto-logged in and ready to code!
```
Suitable for commercial & non-commercial projects, just let me know if it's useful to you and any cool customisations you make to it. I take no responsibility for anything, your usage is all down to you.

View File

@@ -1,16 +1,17 @@
<?php include("lib/config.php");?>
<!DOCTYPE html>
<html style="margin: 0px">
<html style="margin: 0">
<head>
<title>CodeMirror 2: ICE Coders Editor of Choice</title>
<?php include("lib/settings.php");?>
<link rel="stylesheet" href="<?php echo $codeMirrorDir; ?>/lib/codemirror.css">
<script src="<?php echo $codeMirrorDir; ?>/lib/codemirror.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/xml/xml.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/javascript/javascript.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/coffeescript/coffeescript.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/css/css.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/clike/clike.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/css/css.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/javascript/javascript.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/xml/xml.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/coffeescript/coffeescript.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/php/php.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/ruby/ruby.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/lib/util/searchcursor.js"></script>
@@ -24,19 +25,75 @@ if ($theme=="default") {
}
?>
<style type="text/css">
.CodeMirror {position: absolute; width: 0px; background-color: #fff}
.CodeMirror {position: absolute; width: 0; background-color: #fff; top: 0px; z-index: 1}
.CodeMirror-scroll {width: 100px; height: 100px;}
.cm-s-visible {display: block; top: 0px}
.cm-s-visible {display: block; top: 0}
.cm-s-hidden {display: none; top: 4000px}
.cm-s-activeLine {background: #002 !important;}
.cm-s-activeLine {background: #000 !important;}
// Make sure this next one remains the 5th item, updated with JS
.cm-tab:after {position: relative; display: inline-block; width: 0px; left: -1.4em; overflow: visible; color: #aaa; content: "<?php if ($visibleTabs) {?>\21e5<?;};?>";}
.cm-tab:after {position: relative; display: inline-block; width: 0; left: -1.4em; overflow: visible; color: #aaa; content: "<?php if ($visibleTabs) {?>\21e5<?;};?>";}
span.CodeMirror-matchhighlight {background: #555}
.CodeMirror-focused span.CodeMirror-matchhighlight {color: #000; background: #555; !important}
</style>
</head>
<body style="margin: 0px" onKeyDown="return top.ICEcoder.interceptKeys('content', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<body onLoad="top.ICEcoder.updateFileFolderCount()" style="color: #fff; margin: 0" onKeyDown="return top.ICEcoder.interceptKeys('content', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<div style="margin: 32px 43px; font-family: arial; font-size: 10px; color: #dddddd">
<?php if($_SESSION['userLevel'] == 10) {
echo '<div style="float: left; margin-right: 50px">'.PHP_EOL;
echo '<h2 style="color: rgba(0,198,255,0.7)">server</h2>'.PHP_EOL;
echo '<span style="color:#888">Server name, OS & IP:</span><br>'.PHP_EOL;
echo $_SERVER['SERVER_NAME'].' &nbsp;&nbsp; '.$_SERVER['SERVER_SOFTWARE'].' &nbsp;&nbsp; '.$_SERVER['SERVER_ADDR'].'<br><br>'.PHP_EOL;
echo '<span style="color:#888">Root:</span><br>'.PHP_EOL;
echo $_SERVER['DOCUMENT_ROOT'].'<br><br>'.PHP_EOL;
echo '<span style="color:#888">PHP version:</span><br>'.PHP_EOL;
echo phpversion().'<br><br>'.PHP_EOL;
echo '<span style="color:#888">Date & time:</span><br>'.PHP_EOL;
echo '<span id="serverDT"></span><br><br><br>'.PHP_EOL;
echo '</div>'.PHP_EOL;
echo '<div style="float: left">'.PHP_EOL;
echo '<h2 style="color: rgba(0,198,255,0.7)">files</h2>'.PHP_EOL;
echo '<span style="color:#888">Last 10 files opened:</span><br>'.PHP_EOL;
$last10FilesArray = explode(",",$last10Files);
for ($i=0;$i<count($last10FilesArray);$i++) {
if ($last10Files=="") {
echo '[none]<br><br>';
} else {
echo '<a style="cursor:pointer" onClick="top.ICEcoder.openFile(top.fullPath+\''.str_replace("|","/",$last10FilesArray[$i]).'\')">';
echo str_replace("|","/",$last10FilesArray[$i]);
echo '</a><br>'.PHP_EOL;
if ($i==count($last10FilesArray)-1) {echo '<br>'.PHP_EOL;};
}
}
echo '<span style="color:#888">File & folder count:</span><br>'.PHP_EOL;
echo '<div id="fileFolderCounts"></div><br><br><br>'.PHP_EOL;
echo '</div>'.PHP_EOL;
echo '<div style="clear: both">'.PHP_EOL;
echo '<h2 style="color: rgba(0,198,255,0.7)">your device</h2>'.PHP_EOL;
echo '<span style="color:#888">Browser:</span><br>'.PHP_EOL;
echo $_SERVER['HTTP_USER_AGENT'].'<br><br>'.PHP_EOL;
echo '<span style="color:#888">Your IP:</span><br>'.PHP_EOL;
echo $_SERVER['REMOTE_ADDR'].PHP_EOL;
echo '</div>'.PHP_EOL;
}; ?>
<script>
var nDT=<?php echo time()*1000;?>;
setInterval(function(){
var s=(new Date(nDT+=1e3)+'').split(' '),
d=s[2]*1,
t=s[4].split(':'),
p=t[0]>11?'pm':'am',
e=d%20==1|d>30?'st':d%20==2?'nd':d%20==3?'rd':'th';
t[0]=--t[0]%12+1;
if (document.getElementById('serverDT')) {
document.getElementById('serverDT').innerHTML=[s[0],d+e,s[1],s[3],t.join(':')+p].join(' ');
}
},1000);
</script>
</div>
<script>
function createNewCMInstance(num) {
@@ -48,8 +105,8 @@ function createNewCMInstance(num) {
mode: "application/x-httpd-php",
lineNumbers: true,
lineWrapping: true,
indentUnit: 4,
tabSize: 4,
indentUnit: top.tabWidth,
tabSize: top.tabWidth,
indentWithTabs: true,
electricChars: false,
onCursorActivity: function() {
@@ -79,7 +136,7 @@ function createNewCMInstance(num) {
}
},
onKeyEvent: function(instance, e) {
top.ICEcoder.redoChangedContent(event);
top.ICEcoder.redoChangedContent(e);
top.ICEcoder.findReplace('find',true,false);
top.ICEcoder.getCaretPosition();
top.ICEcoder.updateCharDisplay();

View File

@@ -74,6 +74,7 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
if( $this_file != "." && $this_file != ".." && $bannedFile == false) {
if( is_dir("$directory/$this_file") ) {
// Directory
$dirCount++;
$dirRep = str_replace("\\","/",$directory);
$link = str_replace("[link]", "$dirRep/" . urlencode($this_file), $return_link);
$link = str_replace("//","/",$link);
@@ -99,6 +100,8 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
}
} else {
// File
$fileCount++;
$fileBytes+=filesize($link);
// Get extension (prefix 'ext-' to prevent invalid classes from extensions that begin with numbers)
$ext = "ext-" . substr($this_file, strrpos($this_file, ".") + 1);
$dirRep = str_replace("\\","/",$directory);
@@ -119,7 +122,7 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
}
$fileManager .= "<li class=\"pft-file " . strtolower($ext) . "\"><a nohref onMouseOver=\"top.ICEcoder.overFileFolder('file','$link')\" onMouseOut=\"top.ICEcoder.overFileFolder('file','')\" style=\"position: relative; left:-22px; cursor: pointer\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span id=\"".str_replace("/","|",str_replace($docRoot,"",$link))."\">" . htmlspecialchars($this_file) . "</span> ".$fileAtts."</a></li>";
} else {
$fileAtts = "<img src=\"images/file-manager-icons/padlock.png\" style=\"cursor: pointer\" onClick=\"alert('Sorry, you need higher admin level rights to view.')\">";
$fileAtts = "<img src=\"images/padlock.png\" style=\"cursor: pointer\" onClick=\"alert('Sorry, you need higher admin level rights to view.')\">";
$fileManager .= "<li class=\"pft-file " . strtolower($ext) . "\" style=\"cursor: default\"><span style=\"position: relative; left:-22px; color: #888\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [HIDDEN] ".$fileAtts."</span></li>";
}
}
@@ -127,7 +130,12 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
}
$fileManager .= "</ul>";
}
return $fileManager;
$varOutput = "";
if ($dirCount) {$varOutput .= "top.ICEcoder.dirCount+=".$dirCount.";".PHP_EOL;};
if ($fileCount) {$varOutput .= "top.ICEcoder.fileCount+=".$fileCount.";".PHP_EOL;};
if ($fileBytes) {$varOutput .= "top.ICEcoder.fileBytes+=".$fileBytes.";".PHP_EOL;};
// After outputting the fileManager, output the JS vars, but only the first time
return $fileManager."<script>if (top.ICEcoder.dirCount==0) {".PHP_EOL.$varOutput."}</script>";
}
// For PHP4 compatibility
@@ -146,12 +154,19 @@ function php4_scandir($dir) {
<head>
<title>ICE Coder File Manager</title>
<link rel="stylesheet" type="text/css" href="lib/files.css">
<script src="lib/coder.js" type="text/javascript"></script>
</head>
<body onLoad="top.ICEcoder.fileManager()" onDblClick="top.ICEcoder.openFile()" onKeyDown="return top.ICEcoder.interceptKeys('files', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<div onClick="top.ICEcoder.refreshFileManager()" class="refresh"><img src="images/file-manager-icons/refresh.png"></div>
<div onClick="top.ICEcoder.refreshFileManager()" class="refresh"><img src="images/refresh.png"></div>
<script>
top.ICEcoder.dirCount = 0;
top.ICEcoder.fileCount = 0;
top.ICEcoder.fileBytes = 0;
</script>
<?php
echo fileManager($_SERVER['DOCUMENT_ROOT'], "[link]");
?>

BIN
images/blank.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 954 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

BIN
images/full-screen.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 B

BIN
images/ice-coder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 752 B

After

Width:  |  Height:  |  Size: 752 B

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
images/restored-screen.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 B

View File

Before

Width:  |  Height:  |  Size: 551 B

After

Width:  |  Height:  |  Size: 551 B

View File

@@ -10,12 +10,18 @@ if (!$allowedIP) {
header('Location: /');
};
// Test for latest CodeMirror version
if ($testcMVersion) {
$cMLatestVer = json_encode(file_get_contents("http://codemirror.net/latest-version.txt"));
$cMLatestVer = rtrim(ltrim($cMLatestVer,"\""),"\"\\n");
if ($cMThisVer<$cMLatestVer) {
echo '<script>alert(\'Code Mirror '.$cMLatestVer.' now released\n\nPlease upgrade\');</script>';
// Check for updates of ICEcoder & CodeMirror
if ($checkUpdates) {
$ICEcoderLatestVer = json_encode(file_get_contents("http://icecoder.net/latest-version.txt"));
$ICEcoderLatestVer = rtrim(ltrim($ICEcoderLatestVer,"\""),"\"\\n");
if (ltrim($versionNo,"v ")<ltrim($ICEcoderLatestVer,"v ")) {
echo '<script>alert(\'ICEcoder '.$ICEcoderLatestVer.' now released\n\nPlease upgrade\');</script>';
} else {
$cMLatestVer = json_encode(file_get_contents("http://codemirror.net/latest-version.txt"));
$cMLatestVer = rtrim(ltrim($cMLatestVer,"\""),"\"\\n");
if ($cMThisVer<$cMLatestVer) {
echo '<script>alert(\'Code Mirror '.$cMLatestVer.' now released\n\nPlease upgrade\');</script>';
}
}
}
?>
@@ -24,11 +30,13 @@ if ($testcMVersion) {
<html>
<head>
<title>ICE Coder - <?php echo $versionNo;?></title>
<meta name="robots" content="noindex, nofollow">
<link rel="stylesheet" type="text/css" href="lib/coder.css">
<script>
shortURLStarts = "<?php echo $shortURLStarts;?>";
theme = "<?php if ($theme=="default") {echo 'icecoder';} else {echo $theme;};?>";
tabsIndent = <?php if ($tabsIndent) {echo 'true';} else {echo 'false';};?>;
tabWidth = <?php echo $tabWidth; ?>;
<?
$docRoot = str_replace("\\","/",$_SERVER['DOCUMENT_ROOT']);
if (strrpos($docRoot,"/")==strlen($docRoot)-1) {$docRoot = substr($docRoot,0,strlen($docRoot)-1);};
@@ -42,9 +50,9 @@ window.onbeforeunload = function() {
}
}
lastOpenFiles = [<?php
if ($lastOpenedFiles!="" && $_SESSION['userLevel'] == 10) {
$openFilesArray = explode(",",$lastOpenedFiles);
previousFiles = [<?php
if ($previousFiles!="" && $_SESSION['userLevel'] == 10) {
$openFilesArray = explode(",",$previousFiles);
for ($i=0;$i<count($openFilesArray);$i++) {
echo "'".$openFilesArray[$i]."'";
if ($i<count($openFilesArray)-1) {echo ",";};
@@ -85,14 +93,15 @@ lastOpenFiles = [<?php
<a href="javascript:top.ICEcoder.renameFile(top.ICEcoder.rightClickedFile)" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">Rename</a>
<a href="javascript:window.open(top.ICEcoder.rightClickedFile.substr((top.ICEcoder.rightClickedFile.indexOf(shortURLStarts)+top.shortURLStarts.length),top.ICEcoder.rightClickedFile.length))" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">View Webpage</a>
</span>
<a href="javascript:top.ICEcoder.zipIt(top.ICEcoder.rightClickedFile)" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">Zip It!</a>
</div>
<div id="header" class="header" onContextMenu="return false">
<div class="plugins" id="pluginsContainer">
<?php echo $pluginsDisplay; ?>
</div>
<div class="version"><?php echo $versionNo;?></div>
<img src="images/ice-coder.gif" class="logo" onClick="ICEcoder.helpScreen('show')" onContextMenu="ICEcoder.settingsScreen('show')">
<div class="version"><?php echo $versionNo;?></div><img src="images/full-screen.gif" id="screenMode" class="screenModeIcon" onClick="top.ICEcoder.fullScreenSwitcher()">
<img src="images/ice-coder.png" class="logo" onClick="ICEcoder.helpScreen('show')" onContextMenu="ICEcoder.settingsScreen('show')">
</div>
<div id="files" class="files" onMouseOver="ICEcoder.changeFilesW('expand')" onMouseOut="ICEcoder.changeFilesW('contract'); top.document.getElementById('fileMenu').style.display='none';">
@@ -108,13 +117,13 @@ lastOpenFiles = [<?php
<div class="accountOptions">
<a nohref title="Save" onClick="ICEcoder.fMIcon('save')"><img src="images/save.png" alt="Save" id="fMSave" style="opacity: 0.3"></a>
<a nohref title="Open" onClick="ICEcoder.fMIcon('open')"><img src="images/open.png" alt="Open" id="fMOpen" style="margin-left: 7px; opacity: 0.3"></a>
<a nohref title="New File" onClick="ICEcoder.fMIcon('newFile')"><img src="images/new-file.png" alt="New File" id="fMNewFile" style="margin: 8px 0px 0px 10px; opacity: 0.3"></a>
<a nohref title="New Folder" onClick="ICEcoder.fMIcon('newFolder')"><img src="images/new-folder.png" alt="New Folder" id="fMNewFolder" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
<a nohref title="Delete" onClick="ICEcoder.fMIcon('delete')"><img src="images/delete.png" alt="Delete" id="fMDelete" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
<a nohref title="Rename" onClick="ICEcoder.fMIcon('rename')"><img src="images/rename.png" alt="Rename" id="fMRename" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
<a nohref title="View" onClick="ICEcoder.fMIcon('view')"><img src="images/view.png" alt="View" id="fMView" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
<a nohref title="New File" onClick="ICEcoder.fMIcon('newFile')"><img src="images/new-file.png" alt="New File" id="fMNewFile" style="margin: 8px 0 0 10px; opacity: 0.3"></a>
<a nohref title="New Folder" onClick="ICEcoder.fMIcon('newFolder')"><img src="images/new-folder.png" alt="New Folder" id="fMNewFolder" style="margin: 9px 0 0 5px; opacity: 0.3"></a>
<a nohref title="Delete" onClick="ICEcoder.fMIcon('delete')"><img src="images/delete.png" alt="Delete" id="fMDelete" style="margin: 9px 0 0 5px; opacity: 0.3"></a>
<a nohref title="Rename" onClick="ICEcoder.fMIcon('rename')"><img src="images/rename.png" alt="Rename" id="fMRename" style="margin: 9px 0 0 5px; opacity: 0.3"></a>
<a nohref title="View" onClick="ICEcoder.fMIcon('view')"><img src="images/view.png" alt="View" id="fMView" style="margin: 9px 0 0 5px; opacity: 0.3"></a>
</div>
<a nohref style="cursor: pointer" onClick="ICEcoder.lockUnlockNav()"><img src="images/file-manager-icons/padlock.png" id="fmLock" class="lock"></a>
<a nohref style="cursor: pointer" onClick="ICEcoder.lockUnlockNav()"><img src="images/padlock.png" id="fmLock" class="lock"></a>
</div>
<iframe id="filesFrame" class="frame" name="ff" src="files.php" style="opacity: 0" onLoad="this.style.opacity='1'"></iframe>
<div class="serverMessage" id="serverMessage"></div>
@@ -174,6 +183,7 @@ lastOpenFiles = [<?php
</div>
<script>
ICEcoder.initAliases();
ICEcoder.setLayout('dontSetEditor');
</script>

View File

@@ -9,10 +9,10 @@ dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
font-family: arial, verdana, helvetica, sans-serif;
border: 0px;
margin: 0px;
padding: 0px;
outline: 0px;
border: 0;
margin: 0;
padding: 0;
outline: 0;
font-size: 12px;
vertical-align: top;
}
@@ -28,13 +28,13 @@ body {overflow: hidden;
h1 {font-size: 36px; font-weight: normal; color: #888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #fff}
.blackMask {position: fixed; display: table; width: 100%; height: 100%; top: 0px; left: 0px; visibility: hidden; background-color: rgba(0,0,0,0.8); text-align: center; z-index: 100}
.blackMask {position: fixed; display: table; width: 100%; height: 100%; top: 0; left: 0; visibility: hidden; background-color: rgba(0,0,0,0.8); text-align: center; z-index: 100}
.blackMask .popupVCenter {#position: absolute; display: table-cell; #top: 50%; vertical-align: middle; text-align: center}
.popupVCenter .popup {#position: relative; #top: -50%; text-align: center; color: #fff; font-size: 10px}
.whiteGlow {
-webkit-box-shadow: 0px 0px 8px 2px rgba(255,255,255,0.6);
-moz-box-shadow: 0px 0px 8px 2px rgba(255,255,255,0.6);
box-shadow: 0px 0px 8px 2px rgba(255,255,255,0.6);
-webkit-box-shadow: 0 0 8px 2px rgba(255,255,255,0.6);
-moz-box-shadow: 0 0 8px 2px rgba(255,255,255,0.6);
box-shadow: 0 0 8px 2px rgba(255,255,255,0.6);
}
.circleOutside {background-color: rgba(0,0,0,0); border:5px solid rgba(0,183,229,0.9); opacity:.9; border-top:5px solid rgba(0,0,0,0); border-left:5px solid rgba(0,0,0,0); border-radius:50px; box-shadow: 0 0 35px #2187e7;
@@ -60,32 +60,33 @@ h2 {font-size: 18px; font-weight: normal; color: #fff}
100% { -webkit-transform:rotate(-360deg);}
}
.progressBar {top: 0px; left: 0px; width:100%; height:1px; margin:2px 0; background:#2187e7; position:absolute; box-shadow:0px 0px 10px 1px rgba(0,198,255,0.7);
.progressBar {top: 0; left: 0; width:100%; height:1px; margin:2px 0; background:#2187e7; position:absolute; box-shadow:0 0 10px 1px rgba(0,198,255,0.7);
-moz-animation:fullexpand 10s ease-out; -webkit-animation:fullexpand 10s ease-out;
}
@-moz-keyframes fullexpand {
0% { width:0px;}
0% { width:0;}
100%{ width:100%;}
}
@-webkit-keyframes fullexpand {
0% { width:0px;}
0% { width:0;}
100%{ width:100%;}
}
.header {position: absolute; display: inline-block; width: 100%; height: 40px; background-color: #fff; text-align: right; z-index: 2}
.header {position: absolute; display: inline-block; top: 0; left: 0; width: 100%; height: 40px; background-color: #fff; text-align: right; z-index: 2}
.header .plugins {position: absolute; display: inline-block; left: 15px; top: 3px}
.header .plugins img {position: relative; display: inline-block; margin-right: 15px}
.header .screenModeIcon {position: absolute; top: 5px; right: 178px; cursor: pointer}
.header .version {position: relative; display: inline-block; margin-top: 25px; font-size: 10px; color: #bbb}
.header .logo {position: relative; margin: 5px 10px 0px 5px; cursor: pointer}
.header .logo {position: relative; margin: 5px 10px 0 5px; cursor: pointer}
.files {position: absolute; display: inline-block; height: 100%; width: 250px; background-color: #444; background-image: url('../images/files-arrow.gif'); background-repeat: no-repeat; background-position: 100% 50%; overflow: hidden; z-index: 1;
-webkit-box-shadow: 0px 0px 10px 4px rgba(0,0,0,0.4);
-moz-box-shadow: 0px 0px 10px 4px rgba(0,0,0,0.4);
box-shadow: 0px 0px 10px 4px rgba(0,0,0,0.4);
.files {position: absolute; display: inline-block; top: 0; left: 0; height: 100%; width: 250px; background-color: #444; background-image: url('../images/files-arrow.gif'); background-repeat: no-repeat; background-position: 100% 50%; overflow: hidden; z-index: 1;
-webkit-box-shadow: 0 0 10px 4px rgba(0,0,0,0.4);
-moz-box-shadow: 0 0 10px 4px rgba(0,0,0,0.4);
box-shadow: 0 0 10px 4px rgba(0,0,0,0.4);
}
.files .account {display: inline-block; height: 50px; width: 250px; margin-top: 40px; background-color: #888}
.files .accountLoginContainer {position: absolute; width: 250px; height: 50px; z-index: 1}
.files .accountLoginContainer .accountLogin {position: absolute; width: 250px; height: 50px; top: 0px; background-color: #666;
.files .accountLoginContainer .accountLogin {position: absolute; width: 250px; height: 50px; top: 0; background-color: #666;
-webkit-transition: top 0.3s;
-moz-transition: top 0.3s;
-o-transition: top 0.3s;
@@ -96,15 +97,15 @@ h2 {font-size: 18px; font-weight: normal; color: #fff}
.files .accountPassword {position: relative; border: 1px solid #888; background-color: #999; height: 18px; width: 140px; margin-left: 14px; margin-top: 15px}
.files input:focus, .findReplace input:focus, .findReplace select:focus, .accountPassword:focus {
outline: none;
-webkit-box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
-moz-box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
-webkit-box-shadow: 0 0 10px 1px rgba(0,198,255,0.7);
-moz-box-shadow: 0 0 10px 1px rgba(0,198,255,0.7);
box-shadow: 0 0 10px 1px rgba(0,198,255,0.7);
}
.files .button {position: absolute; border: 0px; background: #999; color: #555; height:20px; margin-top: 16px; margin-left: 5px; font-size: 11px; cursor: pointer}
.files .button {position: absolute; border: 0; background: #999; color: #555; height:20px; margin-top: 16px; margin-left: 5px; font-size: 11px; cursor: pointer}
.files .button:hover {background-color: #444; color: #eee}
.files .lock {position: relative; margin-left: 225px; margin-top: -20px; z-index: 1}
.files .frame {display: inline-block; width: 250px}
.files .serverMessage {position: absolute; display: inline-block; width: 450px; bottom: 0px; margin-bottom: 30px; background-color: rgba(255,255,255,0.8); font-size: 10px; padding: 7px 12px; opacity: 0;
.files .serverMessage {position: absolute; display: inline-block; width: 450px; bottom: 0; margin-bottom: 30px; background-color: rgba(255,255,255,0.8); font-size: 10px; padding: 7px 12px; opacity: 0;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-o-transition: all 0.2s;
@@ -112,53 +113,53 @@ h2 {font-size: 18px; font-weight: normal; color: #fff}
}
.files .serverMessage b {font-size: 10px}
.editor {position: absolute; display: inline-block; top: 0px; left: 15px; width: 2400px}
.editor {position: absolute; display: inline-block; top: 0; left: 15px; width: 2400px}
.editor .tabsBar {display: inline-block; height: 22px; width: 2400px; margin-top: 40px; padding-left: 41px; background-color: #888;}
.tabsBar .tab {display: inline-block; display: none; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0px 0px; padding: 5px 8px 2px 8px; font-size: 10px; border-left: solid 1px #fff; border-right: solid 1px #777; color: #fff; cursor: pointer;
.tabsBar .tab {display: inline-block; display: none; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0 0; padding: 5px 8px 2px 8px; font-size: 10px; border-left: solid 1px #fff; border-right: solid 1px #777; color: #fff; cursor: pointer;
-webkit-transition: all 0.15s;
-moz-transition: all 0.15s;
-o-transition: all 0.15s;
transition: all 0.15s;
}
.tabsBar .tab .closeTab {margin: 1px 0px 0px 5px; border-radius: 6px}
.tabsBar .newTab {display: inline-block; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0px 0px; padding: 6px 5px 1px 5px; border-left: solid 1px #fff; border-right: solid 1px #777; cursor: pointer;}
.tabsBar .tab .closeTab {margin: 1px 0 0 5px; border-radius: 6px}
.tabsBar .newTab {display: inline-block; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0 0; padding: 6px 5px 1px 5px; border-left: solid 1px #fff; border-right: solid 1px #777; cursor: pointer;}
.editor .findBar {display: inline-block; height: 28px; width: 2400px; color: #fff; background-color: #141414}
.findBar .findReplace {position: absolute; z-index: 1}
.findReplace select {position: relative; font-size: 10px; margin: 8px 2px 0px 2px; top: -2px;}
.findReplace .findText {display: inline-block; height: 21px; font-size: 10px; margin: 8px 2px 0px 2px; margin-left: 43px}
.findReplace select {position: relative; font-size: 10px; margin: 8px 2px 0 2px; top: -2px;}
.findReplace .findText {display: inline-block; height: 21px; font-size: 10px; margin: 8px 2px 0 2px; margin-left: 43px}
.findReplace .find {position: relative; width: 120px; height: 16px; border: 0; top: -2px; font-size: 10px; padding-left: 5px}
.findReplace .findTextPlural {display: inline-block; height: 21px; font-size: 10px; margin: 8px 2px 0px 0px}
.findReplace .replaceAction {margin: 0px 2px 0px 0px; top: -2px}
.findReplace .replaceText {height: 21px; font-size: 10px; margin: 8px 2px 0px 2px}
.findReplace .findTextPlural {display: inline-block; height: 21px; font-size: 10px; margin: 8px 2px 0 0}
.findReplace .replaceAction {margin: 0 2px 0 0; top: -2px}
.findReplace .replaceText {height: 21px; font-size: 10px; margin: 8px 2px 0 2px}
.findReplace .replace {position: relative; width: 120px; height: 16px; border: 0; top: -2px; font-size: 10px; padding-left: 5px}
.findReplace .targetText {height: 21px; font-size: 10px; margin: 8px 2px 0px 2px}
.findReplace .targetText {height: 21px; font-size: 10px; margin: 8px 2px 0 2px}
.findReplace .submit {position: relative; top: -2px; height: 17px; border: 1px solid #bbb; background-color: #f8f8f8; font-size: 10px; cursor: pointer}
.findReplace .results {position: relative; display: inline-block; width: 200px; height: 20px; font-size: 10px; margin: 8px 0px 0px 20px}
.findReplace .results {position: relative; display: inline-block; width: 200px; height: 20px; font-size: 10px; margin: 8px 0 0 20px}
.findBar .codeAssist {position: fixed; display: inline-block; width: 100px; right: 74px; top: 70px; height: 21px; font-size: 10px; z-index: 1}
.findBar .codeAssist input {margin-top: -1px}
.findBar .goLine {position: fixed; display: inline-block; width: 100px; right: -10px; top: 70px; height: 21px; font-size: 10px; z-index: 1}
.goLine .goToLine {width: 25px; height: 16px; border: 0; font-size: 10px; margin: -3px 0px 0px 3px}
.goLine .goToLine {width: 25px; height: 16px; border: 0; font-size: 10px; margin: -3px 0 0 3px}
.editor .code {position: relative; display: inline-block; top: 28px; width: 600px; height: 600px; visibility: hidden}
.footer {position: fixed; display: inline-block; width: 100%; height: 30px; bottom: 0px; background-color: rgba(0,0,0,0.7); left: 0px; z-index: 2}
.footer .nesting {display: inline-block; padding: 5px 8px; margin: 4px 0px 0px 15px; font-weight: bold; font-size: 10px; color: #fff; background-color: #0b0}
.footer .nestLoc {position: absolute; display: inline-block; width: 120px; padding: 5px 0px 0px 8px; margin-top: 3px; left: 112px; font-weight: bold; font-size: 12px; color: #fff; text-align: right}
.footer .nestDisplay {position: absolute; display: inline-block; padding: 5px 0px 0px 8px; margin-top: 3px; left: 255px; font-size: 12px; color: #fff; text-align: right}
.footer .charDisplay {position: absolute; display: inline-block; padding: 5px 0px 0px 8px; margin-top: 3px; left: 100%; font-weight: bold; font-size: 12px; color: #fff; text-align: right; width: 200px; text-align: right; margin-left: -220px}
.footer {position: fixed; display: inline-block; width: 100%; height: 30px; bottom: 0; background-color: rgba(0,0,0,0.7); left: 0; z-index: 2}
.footer .nesting {display: inline-block; padding: 5px 8px; margin: 4px 0 0 15px; font-weight: bold; font-size: 10px; color: #fff; background-color: #0b0}
.footer .nestLoc {position: absolute; display: inline-block; width: 120px; padding: 5px 0 0 8px; margin-top: 3px; left: 112px; font-weight: bold; font-size: 12px; color: #fff; text-align: right}
.footer .nestDisplay {position: absolute; display: inline-block; padding: 5px 0 0 8px; margin-top: 3px; left: 255px; font-size: 12px; color: #fff; text-align: right}
.footer .charDisplay {position: absolute; display: inline-block; padding: 5px 0 0 8px; margin-top: 3px; left: 100%; font-weight: bold; font-size: 12px; color: #fff; text-align: right; width: 200px; text-align: right; margin-left: -220px}
.textbox {
-webkit-box-shadow: inset 1px 1px 2px 0px rgba(0,0,0,0.4);
-moz-box-shadow: inset 1px 1px 2px 0px rgba(0,0,0,0.4);
box-shadow: inset 1px 1px 2px 0px rgba(0,0,0,0.4);
-webkit-box-shadow: inset 1px 1px 2px 0 rgba(0,0,0,0.4);
-moz-box-shadow: inset 1px 1px 2px 0 rgba(0,0,0,0.4);
box-shadow: inset 1px 1px 2px 0 rgba(0,0,0,0.4);
}
.fileMenu {position: absolute; display: none; left: 0px; top: 0px; background-color: #333; z-index: 10}
.fileMenu a {display: block; padding: 2px 5px; background-color: #444; color: #eee; text-decoration: none}
.fileMenu {position: absolute; display: none; left: 0; top: 0; background-color: #333; z-index: 10}
.fileMenu a {display: block; padding: 2px 5px; background-color: #333; color: #eee; text-decoration: none}
.fileMenu a:hover {background-color: #666}
.screenContainer {position: absolute; display: table; width: 100%; height: 100%; top: 0px; left: 0px; text-align: center}
.screenContainer {position: absolute; display: table; width: 100%; height: 100%; top: 0; left: 0; text-align: center}
.screenContainer .screenVCenter {#position: absolute; display: table-cell; #top: 50%; vertical-align: middle; text-align: center}
.screenVCenter .screenCenter {#position: relative; #top: -50%; text-align: center; display: inline}
.screenCenter .version {position: relative; display: block; margin: 5px 0px 15px 0px; font-size: 10px; color: #bbb}
.screenCenter .version {position: relative; display: block; margin: 5px 0 15px 0; font-size: 10px; color: #bbb}
.screenCenter .accountPassword {border: 1px solid #888; height: 18px}
.screenCenter .button {border: 0px; background: #666; color: #fff; height: 22px; cursor: pointer}
.screenCenter .button {border: 0; background: #666; color: #fff; height: 22px; cursor: pointer}

View File

@@ -1,9 +1,3 @@
// ICE coder by Matt Pass
// Free to use it for your own purposes, commercial or not, just let me know of any cool uses or customisations. :)
// No warranty or liability accepted for anything, all responsibility of use is your own.
// Latest version: https://github.com/mattpass/ICEcoder
// Twitter: @mattpass
var ICEcoder = {
// Define settings
filesW: 250, // Initial width of the files pane
@@ -33,15 +27,18 @@ var ICEcoder = {
// Don't consider these tags as part of nesting as they're singles, JS, PHP or Ruby code blocks
tagNestExceptions: ["!DOCTYPE","meta","link","img","br","hr","input","script","?php","?","%"],
// On load, set aliases, set the layout and get the nest location
init: function(login) {
// Set our aliases
initAliases: function() {
var aliasArray = ["header","files","account","accountLogin","fmLock","filesFrame","editor","tabsBar","findBar","content","footer","nestValid","nestDisplay","charDisplay"];
// Create our ID aliases
for (var i=0;i<aliasArray.length;i++) {
ICEcoder[aliasArray[i]] = top.document.getElementById(aliasArray[i]);
}
},
// On load, set the layout and get the nest location
init: function(login) {
// Set layout & the nest location
ICEcoder.setLayout();
@@ -65,15 +62,15 @@ var ICEcoder = {
// Apply sizes to various elements of the page
headerH = 40, footerH = 30, accountH = 50, tabsBarH = 21, findBarH = 28;
header.style.width = tabsBar.style.width = findBar.style.width = winW + "px";
files.style.width = accountLogin.style.width = editor.style.left = this.filesW + "px";
account.style.height = accountH + "px";
fmLock.style.marginLeft = (this.filesW-27) + "px";
filesFrame.style.height = (winH-headerH-accountH-footerH) + "px";
this.header.style.width = this.tabsBar.style.width = this.findBar.style.width = winW + "px";
this.files.style.width = this.accountLogin.style.width = this.editor.style.left = this.filesW + "px";
this.account.style.height = this.accountH + "px";
this.fmLock.style.marginLeft = (this.filesW-27) + "px";
this.filesFrame.style.height = (winH-headerH-accountH-footerH) + "px";
// If we need to set the editor sizes
if (!dontSetEditor) {
editor.style.width = ICEcoder.content.style.width = (winW-this.filesW) + "px";
this.editor.style.width = ICEcoder.content.style.width = (winW-this.filesW) + "px";
ICEcoder.content.style.height = (winH-headerH-footerH-tabsBarH-findBarH) + "px";
// Resize the CodeMirror instances to match the window size
@@ -372,16 +369,21 @@ var ICEcoder = {
// Reset all tabs to be without a highlight and then highlight the selected
redoTabHighlight: function(selectedTab) {
var bgVPos, tColor;
var cM, bgVPos, tColor, fileLink;
cM = ICEcoder.getcMInstance();
for(var i=1;i<=ICEcoder.changedContent.length;i++) {
if (document.getElementById('closeTabButton'+i)) {
ICEcoder.changedContent[i-1]==1 ? document.getElementById('closeTabButton'+i).style.backgroundColor = "#b00" : document.getElementById('closeTabButton'+i).style.backgroundColor = "rgba(255,255,255,0.3)";
ICEcoder.changedContent[i-1]==1 && cM.historySize().undo>0 ? document.getElementById('closeTabButton'+i).style.backgroundColor = "#b00" : document.getElementById('closeTabButton'+i).style.backgroundColor = "rgba(255,255,255,0.3)";
}
i==selectedTab ? tColor = "#000" : tColor = "#fff";
if ("undefined" != typeof top.ICEcoder.openFiles[i-1] && top.ICEcoder.openFiles[i-1] != "/[NEW]") {
fileLink = top.ICEcoder.filesFrame.contentWindow.document.getElementById(top.ICEcoder.openFiles[i-1].replace(/\//g,"|"));
i==selectedTab ? fileLink.style.backgroundColor = "#4499dd" : fileLink.style.backgroundColor = "rgba(255,255,255,0.15)";
}
document.getElementById('tab'+i).style.color = tColor;
i==selectedTab ? bgVPos = -22 : bgVPos = 0;
document.getElementById('tab'+i).style.backgroundPosition = "0px "+bgVPos+"px";
document.getElementById('tab'+i).style.backgroundPosition = "0 "+bgVPos+"px";
}
ICEcoder.changedContent[selectedTab-1]==1 ? top.ICEcoder.fMIconVis('fMSave',1) : top.ICEcoder.fMIconVis('fMSave',0.3);
},
@@ -400,7 +402,6 @@ var ICEcoder = {
cM = ICEcoder.getcMInstance('new');
ICEcoder.switchTab(ICEcoder.openFiles.length);
ICEcoder.content.style.visibility='visible';
cM.setLineClass(ICEcoder['cMActiveLine'+ICEcoder.selectedTab], null);
ICEcoder['cMActiveLine'+ICEcoder.selectedTab] = cM.setLineClass(0, "cm-s-activeLine");
@@ -426,7 +427,7 @@ var ICEcoder = {
// Add a new value ready to indicate if this content has been changed
top.ICEcoder.changedContent.push(0);
top.ICEcoder.setLastOpenedFiles();
top.ICEcoder.setPreviousFiles();
},
// Create a new tab for a file
@@ -559,7 +560,6 @@ var ICEcoder = {
// hide the content area if we have no tabs open
if (ICEcoder.openFiles.length==0) {
top.document.getElementById('content').style.visibility = "hidden";
top.ICEcoder.fMIconVis('fMView',0.3);
} else {
// Switch the mode & the tab
@@ -570,7 +570,7 @@ var ICEcoder = {
top.ICEcoder.changedContent.splice(closeTabNum-1,1);
top.parent.ICEcoder.redoTabHighlight(ICEcoder.selectedTab);
top.ICEcoder.setLastOpenedFiles();
top.ICEcoder.setPreviousFiles();
}
// Lastly, stop it from trying to also switch tab
top.ICEcoder.canSwitchTabs=false;
@@ -593,7 +593,7 @@ var ICEcoder = {
while (1) {
if (node != null) {
if (node.tagName == "UL") {
var d = (node.style.display == "none")
var d = (node.style.display == "none");
node.style.display = (d) ? "block" : "none";
this.className = (d) ? "open" : "closed";
return false;
@@ -613,6 +613,8 @@ var ICEcoder = {
}
}
}
aMenus[0].childNodes[0].className = "open";
aMenus[0].childNodes[1].style.display = "block";
return false;
},
@@ -696,7 +698,19 @@ var ICEcoder = {
// Select or deselect file
selectDeselectFile: function(action,file) {
action == "select" ? file.style.backgroundColor="#888" : file.style.backgroundColor="transparent";
var isOpen;
top.ICEcoder.openFiles.indexOf(file.id.replace(/\|/g,"/")) > -1 ? isOpen = true : isOpen = false;
if (top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1] == file.id.replace(/\|/g,"/")) {
file.style.backgroundColor="#4499dd";
} else {
if (action=="select") {
file.style.backgroundColor="#888";
} else {
isOpen ? file.style.backgroundColor = "rgba(255,255,255,0.15)" : file.style.backgroundColor="transparent";
}
}
action == "select" ? file.style.color="#fff" : file.style.color="#eee";
},
@@ -720,7 +734,11 @@ var ICEcoder = {
},
// Open a file on demand
openFile: function() {
openFile: function(fileLink) {
if (fileLink) {
top.ICEcoder.thisFileFolderLink=fileLink;
top.ICEcoder.thisFileFolderType="file";
}
if (top.ICEcoder.thisFileFolderLink!="" && top.ICEcoder.thisFileFolderType=="file") {
var shortURL, canOpenFile;
@@ -792,7 +810,7 @@ var ICEcoder = {
top.ICEcoder.serverQueue("add","lib/file-control.php?action=rename&file="+renamedFile+"&oldFileName="+top.ICEcoder.rightClickedFile.replace(/\|/g,"/"));
top.ICEcoder.serverMessage('<b>Renaming to</b><br>'+renamedFile);
top.ICEcoder.setLastOpenedFiles();
top.ICEcoder.setPreviousFiles();
}
},
@@ -963,11 +981,11 @@ var ICEcoder = {
},
// Go to a specific line number
goToLine: function() {
goToLine: function(lineNo) {
var cM;
cM = ICEcoder.getcMInstance();
cM.setCursor(document.getElementById('goToLineNo').value-1);
cM.setCursor(lineNo ? lineNo-1 : document.getElementById('goToLineNo').value-1);
cM.focus();
return false;
},
@@ -999,7 +1017,7 @@ var ICEcoder = {
lockIcon = top.document.getElementById('fmLock');
ICEcoder.lockedNav ? ICEcoder.lockedNav = false : ICEcoder.lockedNav = true;
ICEcoder.lockedNav ? lockIcon.src="images/file-manager-icons/padlock.png" : lockIcon.src="images/file-manager-icons/padlock-disabled.png";
ICEcoder.lockedNav ? lockIcon.src="images/padlock.png" : lockIcon.src="images/padlock-disabled.png";
},
// Determine the CodeMirror instance we're using on demand
@@ -1091,11 +1109,11 @@ var ICEcoder = {
var tempX, tempY, scrollTop, IE;
IE = document.all ? true : false;
if (!IE) {document.captureEvents(Event.MOUSEMOVE)};
if (IE) {
top.ICEcoder.mouseX = event.clientX + document.body.scrollLeft;
top.ICEcoder.mouseY = event.clientY + document.body.scrollTop;
top.ICEcoder.mouseX = e.clientX + document.body.scrollLeft;
top.ICEcoder.mouseY = e.clientY + document.body.scrollTop;
} else {
document.captureEvents(Event.MOUSEMOVE);
top.ICEcoder.mouseX = e.pageX;
top.ICEcoder.mouseY = e.pageY;
}
@@ -1395,31 +1413,27 @@ var ICEcoder = {
top.ICEcoder.dontSelect = true;
},
// Set the current lastOpenedFiles in the settings file
setLastOpenedFiles: function() {
var lastOpenedFiles;
// Set the current previousFiles in the settings file
setPreviousFiles: function() {
var previousFiles;
lastOpenedFiles = "";
previousFiles = "";
// Generate a comma seperated list
for (var i=0;i<top.ICEcoder.openFiles.length;i++) {
if (top.ICEcoder.openFiles[i]!="" && top.ICEcoder.openFiles[i].indexOf("[NEW]")==-1) {
lastOpenedFiles += top.ICEcoder.openFiles[i].replace(/\//g,"|");
if (i<top.ICEcoder.openFiles.length-1) {lastOpenedFiles += ","};
previousFiles += top.ICEcoder.openFiles[i].replace(/\//g,"|");
if (i<top.ICEcoder.openFiles.length-1) {previousFiles += ","};
}
}
if (lastOpenedFiles!="") {
// Then send through to the settings page to update setting
top.ICEcoder.serverQueue("add","lib/settings.php?saveFiles="+lastOpenedFiles);
} else {
top.ICEcoder.serverMessage();
top.ICEcoder.serverQueue("del",0);
}
if (previousFiles=="") {previousFiles="CLEAR"};
// Then send through to the settings page to update setting
top.ICEcoder.serverQueue("add","lib/settings.php?saveFiles="+previousFiles);
},
// Opens the last files we had open
autoOpenFiles: function() {
for (var i=0;i<=top.lastOpenFiles.length-1;i++) {
top.ICEcoder.rightClickedFile=top.ICEcoder.thisFileFolderLink=top.fullPath+top.lastOpenFiles[i].replace('|','/');
for (var i=0;i<=top.previousFiles.length-1;i++) {
top.ICEcoder.rightClickedFile=top.ICEcoder.thisFileFolderLink=top.fullPath+top.previousFiles[i].replace('|','/');
top.ICEcoder.thisFileFolderType='file';
top.ICEcoder.openFile();
}
@@ -1435,6 +1449,10 @@ var ICEcoder = {
top.document.getElementById('loadingMask').style.visibility = "hidden";
if (loginAttempt) {
if (loginAttempt == "loginOK") {
if (top.ICEcoder.openFiles.length==0) {
top.ICEcoder.content.style.visibility='visible';
top.ICEcoder.content.src = "editor.php";
}
top.document.getElementById('accountLogin').style.top = "-50px";
setTimeout(function() {top.document.getElementById('accountLoginContainer').style.display = "none";},300);
} else {
@@ -1461,7 +1479,7 @@ var ICEcoder = {
},
// Update the settings used when we make a change to them
useNewSettings: function(themeURL,tabsIndent,codeAssist,lockedNav,visibleTabs,refreshFM) {
useNewSettings: function(themeURL,tabsIndent,codeAssist,lockedNav,visibleTabs,tabWidth,refreshFM) {
var styleNode, strCSS, cMCSS;
// Add new stylesheet for selected theme
@@ -1492,6 +1510,12 @@ var ICEcoder = {
cMCSS = ICEcoder.content.contentWindow.document;
visibleTabs ? cMCSS.styleSheets[2][strCSS][5].style['content'] = '"\\21e5"' : cMCSS.styleSheets[2][strCSS][5].style['content'] = '" "';
top.tabWidth = tabWidth;
for (var i=0;i<ICEcoder.cMInstances.length;i++) {
ICEcoder.content.contentWindow['cM'+ICEcoder.cMInstances[i]].setOption("indentUnit", top.tabWidth);
ICEcoder.content.contentWindow['cM'+ICEcoder.cMInstances[i]].setOption("tabSize", top.tabWidth);
}
// Finally, refresh the file manager if we need to
if (refreshFM) {top.ICEcoder.refreshFileManager()};
},
@@ -1500,5 +1524,53 @@ var ICEcoder = {
updateResultsDisplay: function(showHide) {
ICEcoder.findReplace('find',true,false);
document.getElementById('results').style.display = showHide == "show" ? 'inline-block' : 'none';
},
// Show file & folder count in server info screen
updateFileFolderCount: function() {
var fileText, dirText, unitSize, unitText, dContainer;
top.ICEcoder.dirCount > 1 ? dirText = "folders" : dirText = "folder";
top.ICEcoder.fileCount > 1 ? fileText = "files" : fileText = "file";
// Change into kilobytes
unitSize = Math.ceil(top.ICEcoder.fileBytes/1024);
unitText = "kb";
// Maybe we should show in megabytes?
if (unitSize >= 1024) {
unitSize = unitSize / 1024;
unitText = "mb";
}
// Update the display
dContainer = top.ICEcoder.content.contentWindow.document.getElementById('fileFolderCounts');
if (dContainer) {
dContainer.innerHTML = top.ICEcoder.fileCount+" "+fileText+", "+top.ICEcoder.dirCount+" "+dirText+"<br>~ "+unitSize+" "+unitText;
}
},
// Toggle full screen on/off
fullScreenSwitcher: function() {
var screenIcon;
screenIcon = top.document.getElementById('screenMode');
// Future use
if ("undefined" != typeof document.cancelFullScreen) {
document.fullScreen ? document.cancelFullScreen() : document.body.requestFullScreen();
// Moz specific
} else if ("undefined" != typeof document.mozCancelFullScreen) {
document.mozFullScreen ? document.mozCancelFullScreen() : document.body.mozRequestFullScreen();
// Chrome specific
} else if ("undefined" != typeof document.webkitCancelFullScreen) {
document.webkitIsFullScreen ? document.webkitCancelFullScreen() : document.body.webkitRequestFullScreen();
}
screenIcon.src.indexOf("images/full-screen.gif") > -1 ? screenIcon.src = "images/restored-screen.gif" : screenIcon.src = "images/full-screen.gif";
},
// Pass target file/folder to Zip It!
zipIt: function(tgt) {
tgt=tgt.replace(top.fullPath+"/","").replace(/\//g,"|");
top.ICEcoder.filesFrame.contentWindow.frames['fileControl'].location.href="plugins/zip-it/index.php?zip="+tgt;
}
};

25
lib/config.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
$versionNo = "v 0.7.3";
$codeMirrorDir = "CodeMirror-2.25";
$cMThisVer = 2.25;
$tabsIndent = true;
$checkUpdates = false;
$openLastFiles = true;
$findFilesExclude = array("_coder",".doc",".gif",".jpg",".jpeg",".pdf",".png",".swf",".xml",".zip");
$codeAssist = true;
$visibleTabs = false;
$lockedNav = true;
$accountPassword = "";
$restrictedFiles = array("wp-",".php",".rb",".sql");
$bannedFiles = array("_coder","wp-",".exe");
$allowedIPs = array("*");
$plugins = array(
array("Database Admin","images/database.png","margin-top: 3px","plugins/adminer/adminer-3.3.3-mysql-en.php","_blank",""),
array("Batch Image Processor","images/images.png","margin-top: 5px","http://birme.net","_blank",""),
array("Zip It!","images/zip-it.png","margin-top: 3px","plugins/zip-it/index.php?zip=|","fileControl:<b>Zipping Open Files</b>","10")
);
$theme = "default";
$tabWidth = 4;
$previousFiles = "";
$last10Files = "";
?>

View File

@@ -263,7 +263,7 @@ if (action=="save") {
if ("undefined" != typeof newFileName) {
top.ICEcoder.serverMessage('<b>Saving</b><br>'+newFileName);
}
document.saveFile.contents.innerHTML = top.document.getElementById('saveTemp1').value;
document.saveFile.contents.value = top.document.getElementById('saveTemp1').value;
document.saveFile.submit();
} else {
top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);

View File

@@ -9,56 +9,62 @@ dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
font-family: arial, verdana, helvetica, sans-serif;
border: 0px;
margin: 0px;
padding: 0px;
outline: 0px;
border: 0;
margin: 0;
padding: 0;
outline: 0;
font-size: 12px;
vertical-align: top;
}
body {margin: 0px; overflow: auto}
body {margin: 0; overflow: auto}
.refresh {float: right; margin-right: 15px; cursor: pointer}
.fileManager {
margin: 15px 0px 15px 22px;
margin: 15px 0 15px 22px;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
.fileManager span {font-family: helvetica, arial, swiss, verdana;}
.fileManager a {color: #eee; text-decoration: none;}
.fileManager .open {font-style: italic;}
.fileManager .closed {font-style: normal;}
.fileManager .pft-directory {list-style-image: url(../images/file-manager-icons/directory.png);}
.fileManager li {margin-left: 15px;}
.fileManager span {font-family: helvetica, arial, swiss, verdana}
.fileManager a {color: #eee; text-decoration: none}
.fileManager .open {font-style: italic}
.fileManager .closed {font-style: normal}
.fileManager .pft-directory, .fileManager .pft-file {list-style-image: url(../images/blank.gif)}
.fileManager li {margin-left: 15px}
/* Default file */
.fileManager LI.pft-file { list-style-image: url(../images/file-manager-icons/file.png); }
.fileManager LI.pft-directory:before, .fileManager LI.pft-file:before {
position: absolute; display: block; width: 16px; height: 16px; content: ""; margin-top: -2px; margin-left: -23px; background:url(../images/file-manager-icons.png) no-repeat 0 0;
}
@media screen and (-webkit-min-device-pixel-ratio:0) { /* hacked for chrome and safari */
.fileManager LI.pft-directory:before, .fileManager LI.pft-file:before {
margin-top: -19px;
}
}
.fileManager LI.pft-file:before {background-position: -16px 0}
/* Additional file types */
.fileManager LI.ext-coffee { list-style-image: url(../images/file-manager-icons/coffee.png); }
.fileManager LI.ext-css { list-style-image: url(../images/file-manager-icons/css.png); }
.fileManager LI.ext-doc { list-style-image: url(../images/file-manager-icons/doc.png); }
.fileManager LI.ext-gif { list-style-image: url(../images/file-manager-icons/gif.png); }
.fileManager LI.ext-htm { list-style-image: url(../images/file-manager-icons/html.png); }
.fileManager LI.ext-html { list-style-image: url(../images/file-manager-icons/html.png); }
.fileManager LI.ext-jpg { list-style-image: url(../images/file-manager-icons/jpg.png); }
.fileManager LI.ext-jpeg { list-style-image: url(../images/file-manager-icons/jpg.png); }
.fileManager LI.ext-js { list-style-image: url(../images/file-manager-icons/js.png); }
/*.fileManager LI.ext-pdf { list-style-image: url(../images/file-manager-icons/pdf.png); } */
.fileManager LI.ext-php { list-style-image: url(../images/file-manager-icons/php.png); }
.fileManager LI.ext-png { list-style-image: url(../images/file-manager-icons/png.png); }
.fileManager LI.ext-rb { list-style-image: url(../images/file-manager-icons/ruby.png); }
.fileManager LI.ext-rbx { list-style-image: url(../images/file-manager-icons/ruby.png); }
.fileManager LI.ext-rhtml { list-style-image: url(../images/file-manager-icons/ruby.png); }
.fileManager LI.ext-ruby { list-style-image: url(../images/file-manager-icons/ruby.png); }
/*.fileManager LI.ext-sql { list-style-image: url(../images/file-manager-icons/sql.png); } */
/*.fileManager LI.ext-swf { list-style-image: url(../images/file-manager-icons/swf.png); } */
.fileManager LI.ext-txt { list-style-image: url(../images/file-manager-icons/txt.png); }
/*.fileManager LI.ext-xls { list-style-image: url(../images/file-manager-icons/xls.png); } */
/*.fileManager LI.ext-xml { list-style-image: url(../images/file-manager-icons/xml.png); } */
/*.fileManager LI.ext-zip { list-style-image: url(../images/file-manager-icons/zip.png); } */
.fileManager LI.ext-coffee:before {background-position: -32px 0}
.fileManager LI.ext-css:before {background-position: -48px 0}
.fileManager LI.ext-gif:before {background-position: -64px 0}
.fileManager LI.ext-htm:before {background-position: -80px 0}
.fileManager LI.ext-html:before {background-position: -80px 0}
.fileManager LI.ext-jpg:before {background-position: -96px 0}
.fileManager LI.ext-jpeg:before {background-position: -96px 0}
.fileManager LI.ext-js:before {background-position: -112px 0}
/*.fileManager LI.ext-pdf:before {background-position: -???px 0} */
.fileManager LI.ext-php:before {background-position: -128px 0}
.fileManager LI.ext-png:before {background-position: -144px 0}
.fileManager LI.ext-rb:before {background-position: -160px 0}
.fileManager LI.ext-rbx:before {background-position: -160px 0}
.fileManager LI.ext-rhtml:before {background-position: -160px 0}
.fileManager LI.ext-ruby:before {background-position: -160px 0}
/*.fileManager LI.ext-sql:before {background-position: -???px 0} */
/*.fileManager LI.ext-swf:before {background-position: -???px 0} */
.fileManager LI.ext-txt:before {background-position: -176px 0}
/*.fileManager LI.ext-xml:before {background-position: -???px 0} */
.fileManager LI.ext-zip:before {background-position: -192px 0}

View File

@@ -8,10 +8,10 @@ b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
border: 0px;
margin: 0px;
padding: 0px;
outline: 0px;
border: 0;
margin: 0;
padding: 0;
outline: 0;
font-size: 12px;
vertical-align: top;
}

View File

@@ -8,10 +8,10 @@ b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
border: 0px;
margin: 0px;
padding: 0px;
outline: 0px;
border: 0;
margin: 0;
padding: 0;
outline: 0;
font-size: 12px;
vertical-align: top;
}
@@ -32,4 +32,4 @@ hr {border: 0; height: 1px; background-color: #888}
.results .resultsPane a {color: rgba(0,198,255,0.7); text-decoration: none}
.results .resultsPane a:hover {text-decoration: underline}
.replace {position: absolute; margin-top: -28px; right: 20px; padding: 5px 10px; font-size: 14px; background-color: rgba(0,198,255,0.7); cursor: pointer}
.replaceAll {position: absolute; bottom: 0px; right: 20px; padding: 5px 10px; font-size: 18px; background-color: rgba(0,198,255,0.7); cursor: pointer}
.replaceAll {position: absolute; bottom: 0; right: 20px; padding: 5px 10px; font-size: 18px; background-color: rgba(0,198,255,0.7); cursor: pointer}

View File

@@ -8,10 +8,10 @@ b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
border: 0px;
margin: 0px;
padding: 0px;
outline: 0px;
border: 0;
margin: 0;
padding: 0;
outline: 0;
font-size: 12px;
vertical-align: top;
}
@@ -33,13 +33,13 @@ h2 {font-size: 18px; font-weight: normal; color: #fff}
.settings .logo {position: relative; margin-top: 2px}
.settings .version {position: relative; display: block; margin-top: 5px; margin-bottom: 10px; font-size: 10px; color: #bbb}
.settings .settingsColumn1 {width: 220px; height: 560px; padding: 20px; float: left}
.settings .settingsColumn2 {width: 420px; height: 560px; padding: 20px 20px 20px 0px; float: left}
.settings .settingsColumn2 {width: 420px; height: 560px; padding: 20px 20px 20px 0; float: left}
.settings input, .settings textarea {border: 1px solid #555; background-color: #444; color: #fff}
.settings input:focus, .settings textarea:focus {
outline: none;
-webkit-box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
-moz-box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
box-shadow: 0px 0px 10px 1px rgba(0,198,255,0.7);
-webkit-box-shadow: 0 0 10px 1px rgba(0,198,255,0.7);
-moz-box-shadow: 0 0 10px 1px rgba(0,198,255,0.7);
box-shadow: 0 0 10px 1px rgba(0,198,255,0.7);
}
.settings .plugins {font-family: arial, verdana, helvetica, sans-serif; width: 410px; height: 123px; overflow: hidden}
.settings .update {position: absolute; bottom: 0px; right: 20px; padding: 5px 10px; font-size: 18px; background-color: rgba(0,198,255,0.7); opacity: 0.1; cursor: pointer}
.settings .update {position: absolute; bottom: 0; right: 20px; padding: 5px 10px; font-size: 18px; background-color: rgba(0,198,255,0.7); opacity: 0.1; cursor: pointer}

View File

@@ -12,20 +12,20 @@
<script src="../<?php echo $codeMirrorDir; ?>/mode/javascript/javascript.js"></script>
<style type="text/css">
.CodeMirror {position: absolute; width: 0px; background-color: #fff; font-family: monospace}
.CodeMirror {position: absolute; width: 0; background-color: #fff; font-family: monospace}
.CodeMirror-scroll {height: 220px; width: 420px; overflow: hidden}
.cm-s-visible {display: block; top: 0px}
.cm-s-visible {display: block; top: 0}
.cm-s-hidden {display: none; top: 4000px}
.cm-s-activeLine {background: #002 !important;}
// Make sure this next one remains the 5th item, updated with JS
.cm-tab:after {position: relative; display: inline-block; width: 0px; left: -1.4em; overflow: visible; color: #aaa; content: "<?php if($visibleTabs) {echo '\21e5';};?>";}
.cm-tab:after {position: relative; display: inline-block; width: 0; left: -1.4em; overflow: visible; color: #aaa; content: "<?php if($visibleTabs) {echo '\21e5';};?>";}
span.CodeMirror-matchhighlight {background: #555}
.CodeMirror-focused span.CodeMirror-matchhighlight {color: #000; background: #555; !important}
</style>
<link rel="stylesheet" href="editor.css">
<?php
$themeArray = array("ambiance","blackboard","cobalt","eclipse","elegant","lesser-dark","monokai","neat","night","rubyblue","xq-dark");
$themeArray = array("ambiance","blackboard","cobalt","eclipse","elegant","erlang-dark","lesser-dark","monokai","neat","night","rubyblue","xq-dark");
for ($i=0;$i<count($themeArray)-1;$i++) {
echo '<link rel="stylesheet" href="../'.$codeMirrorDir.'/theme/'.$themeArray[$i].'.css">'.PHP_EOL;
}
@@ -79,9 +79,12 @@ for ($i=0;$i<count($themeArray)-1;$i++) {
<h1>settings</h1>
<h2>functionality</h2>
<input type="checkbox" onclick="showButton()" name="tabsIndent" value="true"<?php if($tabsIndent) {echo ' checked';};?>> tab indents selection<br>
<input type="checkbox" onclick="showButton()" name="testcMVersion" value="true"<?php if($testcMVersion) {echo ' checked';};?>> test codemirror version on load<br>
<input type="checkbox" onclick="showButton()" name="checkUpdates" value="true"<?php if($checkUpdates) {echo ' checked';};?>> check for updates on load<br>
<input type="checkbox" onclick="showButton()" name="openLastFiles" value="true"<?php if($openLastFiles) {echo ' checked';};?>> auto open last files on login<br>
<br>
when finding in files, exclude:<br>
<input type="text" onkeydown="showButton()" name="findFilesExclude" value="<?php for($i=0;$i<=count($findFilesExclude)-1;$i++) {echo $findFilesExclude[$i]; if ($i<count($findFilesExclude)-1) {echo ', ';};}; ?>"><br>
<br>
<h2>assisting</h2>
<input type="checkbox" onclick="showButton()" name="codeAssist" value="true"<?php if($codeAssist) {echo ' checked';};?>> code assist<br>
@@ -153,11 +156,19 @@ function findSequence(goal) {
}
return find(1,"1");
}</textarea>
<br>
<span style="position: absolute; top: 520px">
tab width <span style="font-size: 10px; color: #888">chars</span><br>
<input type="text" name="tabWidth" id="tabWidth" style="width: 30px" onkeydown="showButton()" onkeyup="changeTabWidth()" value="<?php echo $tabWidth;?>">
</span>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
readOnly: "nocursor",
indentUnit: top.tabWidth,
tabSize: top.tabWidth,
theme: "<?php if ($theme=="default") {echo 'icecoder';} else {echo $theme;}; ?>"
});
@@ -168,6 +179,12 @@ function selectTheme() {
editor.setOption("theme", theme);
}
function changeTabWidth() {
var tabWidth = document.getElementById("tabWidth").value;
editor.setOption("indentUnit", tabWidth);
editor.setOption("tabSize", tabWidth);
}
var showButton = function() {
document.getElementById('updateButton').style.opacity = 1;
}

View File

@@ -12,48 +12,22 @@ function generateHash($plainText,$salt=null) {
return $salt.sha1($salt.$plainText);
}
// -----------------
// Start of settings
// -----------------
// Settings are stored in this file
include("config.php");
$versionNo = "v 0.6.8";
$codeMirrorDir = "CodeMirror-2.25";
$cMThisVer = 2.25;
$tabsIndent = true;
$testcMVersion = false;
$openLastFiles = true;
$codeAssist = true;
$visibleTabs = false;
$lockedNav = true;
$accountPassword = "";
$restrictedFiles = array("wp-",".php",".rb",".sql");
$bannedFiles = array("_coder","wp-",".exe");
$allowedIPs = array("*");
$plugins = array(
array("Database Admin","images/database.png","margin-top: 3px","plugins/adminer/adminer-3.3.3-mysql-en.php","_blank",""),
array("Batch Image Processor","images/images.png","margin-top: 5px","http://birme.net","_blank",""),
array("Backup","images/backup-open-files.png","margin-top: 3px","plugins/backupOpenFiles/index.php","fileControl:<b>Zipping Open Files</b>","10")
);
$theme = "default";
$lastOpenedFiles = "";
// ---------------
// End of settings
// ---------------
// Update this settings file?
// Update this config file?
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
$settingsFile = 'settings.php';
$settingsFile = 'config.php';
$settingsContents = file_get_contents($settingsFile);
// Replace our lastOpenedFiles var with the the current
// Replace our settings vars
$repPosStart = strpos($settingsContents,'$tabsIndent');
$repPosEnd = strpos($settingsContents,'$lastOpenedFiles');
$repPosEnd = strpos($settingsContents,'$previousFiles');
// Prepare all our vars
if ($_POST['tabsIndent']) {$tabsIndent = "true";} else {$tabsIndent = "false";};
if ($_POST['testcMVersion']) {$testcMVersion = "true";} else {$testcMVersion = "false";};
if ($_POST['checkUpdates']) {$checkUpdates = "true";} else {$checkUpdates = "false";};
if ($_POST['openLastFiles']) {$openLastFiles = "true";} else {$openLastFiles = "false";};
$findFilesExclude = 'array("'.str_replace(', ','","',$_POST['findFilesExclude']).'")';
if ($_POST['codeAssist']) {$codeAssist = "true";} else {$codeAssist = "false";};
if ($_POST['visibleTabs']) {$visibleTabs = "true";} else {$visibleTabs = "false";};
if ($_POST['lockedNav']) {$lockedNav = "true";} else {$lockedNav = "false";};
@@ -63,10 +37,12 @@ if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
$allowedIPs = 'array("'.str_replace(', ','","',$_POST['allowedIPs']).'")';
$plugins = 'array('.PHP_EOL.' array('.PHP_EOL.' '.str_replace('====================','),'.PHP_EOL.' array(',$_POST['plugins']).'))';
$theme = $_POST['theme'];
$tabWidth = $_POST['tabWidth']*1;
$settingsNew = '$tabsIndent = '.$tabsIndent.';'.PHP_EOL;
$settingsNew .= '$testcMVersion = '.$testcMVersion.';'.PHP_EOL;
$settingsNew .= '$checkUpdates = '.$checkUpdates.';'.PHP_EOL;
$settingsNew .= '$openLastFiles = '.$openLastFiles.';'.PHP_EOL;
$settingsNew .= '$findFilesExclude = '.$findFilesExclude.';'.PHP_EOL;
$settingsNew .= '$codeAssist = '.$codeAssist.';'.PHP_EOL;
$settingsNew .= '$visibleTabs = '.$visibleTabs.';'.PHP_EOL;
$settingsNew .= '$lockedNav = '.$lockedNav.';'.PHP_EOL;
@@ -76,15 +52,17 @@ if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
$settingsNew .= '$allowedIPs = '.$allowedIPs.';'.PHP_EOL;
$settingsNew .= '$plugins = '.$plugins.';'.PHP_EOL;
$settingsNew .= '$theme = "'.$theme.'";'.PHP_EOL;
$settingsNew .= '$tabWidth = '.$tabWidth.';'.PHP_EOL;
// Compile our new settings
$settingsContents = substr($settingsContents,0,$repPosStart).$settingsNew.substr($settingsContents,($repPosEnd),strlen($settingsContents));
// Now update this file
$fh = fopen($settingsFile, 'w') or die("can't update settings file");
// Now update the config file
$fh = fopen($settingsFile, 'w') or die("Can't update config file. Please set public write permissions on lib/config.php");
fwrite($fh, $settingsContents);
fclose($fh);
// OK, now this file is updated, update our current session with new arrays
// OK, now the config file has been updated, update our current session with new arrays
$_SESSION['findFilesExclude'] = $findFilesExclude = explode(", ",$_POST['findFilesExclude']);
$_SESSION['restrictedFiles'] = $restrictedFiles = explode(", ",$_POST['restrictedFiles']);
$_SESSION['bannedFiles'] = $bannedFiles = explode(", ",$_POST['bannedFiles']);
$_SESSION['allowedIPs'] = $allowedIPs = explode(", ",$_POST['allowedIPs']);
@@ -93,21 +71,40 @@ if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
// Do we need a file manager refresh?
if ($_POST['changedFileSettings']=="true") {$refreshFM="true";} else {$refreshFM="false";};
// With all that worked out, we can now hide the settings screen and apply the new settings
echo "<script>top.ICEcoder.settingsScreen('hide');top.ICEcoder.useNewSettings('".$themeURL."',".$tabsIndent.",".$codeAssist.",".$lockedNav.",".$visibleTabs.",".$refreshFM.");</script>";
echo "<script>top.ICEcoder.settingsScreen('hide');top.ICEcoder.useNewSettings('".$themeURL."',".$tabsIndent.",".$codeAssist.",".$lockedNav.",".$visibleTabs.",".$tabWidth.",".$refreshFM.");</script>";
}
// Save the currently opened files for next time
if (isset($_GET["saveFiles"]) && $_GET['saveFiles']) {
if ($_SESSION['userLevel'] == 10) {
$settingsFile = 'settings.php';
$settingsFile = 'config.php';
$settingsContents = file_get_contents($settingsFile);
// Replace our lastOpenedFiles var with the the current
$repPosStart = strpos($settingsContents,'lastOpenedFiles = "')+19;
// Replace our previousFiles var with the the current
$repPosStart = strpos($settingsContents,'previousFiles = "')+18;
$repPosEnd = strpos($settingsContents,'";',$repPosStart)-$repPosStart;
$settingsContents = substr($settingsContents,0,$repPosStart).$_GET['saveFiles'].substr($settingsContents,($repPosStart+$repPosEnd),strlen($settingsContents));
// Now update this file
$fh = fopen($settingsFile, 'w') or die("can't update settings file");
fwrite($fh, $settingsContents);
if ($_GET['saveFiles']!="CLEAR") {$saveFiles=$_GET['saveFiles'];} else {$saveFiles="";};
$settingsContents1 = substr($settingsContents,0,$repPosStart).$saveFiles.substr($settingsContents,($repPosStart+$repPosEnd),strlen($settingsContents));
// Now update the config file
$fh = fopen($settingsFile, 'w') or die("Can't update config file. Please set public write permissions on lib/config.php");
fwrite($fh, $settingsContents1);
// Update our top10Files var?
$saveFilesArray = explode(",",$saveFiles);
$last10FilesArray = explode(",",$last10Files);
for ($i=0;$i<count($saveFilesArray);$i++) {
$inLast10Files = in_array($saveFilesArray[$i],$last10FilesArray);
if (!$inLast10Files && $saveFilesArray[$i] !="") {
$repPosStart = strpos($settingsContents1,'last10Files = "')+16;
$repPosEnd = strpos($settingsContents1,'";',$repPosStart)-$repPosStart;
if ($last10Files!="") {$commaExtra=",";} else {$commaExtra="";};
if (count($last10FilesArray)>=10) {$last10Files=substr($last10Files,0,strrpos($last10Files,','));};
$settingsContents2 = substr($settingsContents1,0,$repPosStart).$saveFilesArray[$i].$commaExtra.$last10Files.substr($settingsContents1,($repPosStart+$repPosEnd),strlen($settingsContents1));
// Now update the config file
$fh = fopen($settingsFile, 'w') or die("Can't update config file. Please set public write permissions on lib/config.php");
fwrite($fh, $settingsContents2);
}
}
fclose($fh);
}
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);</script>';
@@ -118,6 +115,7 @@ if (!isset($_SESSION['userLevel'])) {$_SESSION['userLevel'] = 0;};
if(isset($_POST['loginPassword']) && generateHash($_POST['loginPassword'],$accountPassword)==$accountPassword) {$_SESSION['userLevel'] = 10;};
$_SESSION['userLevel'] = $_SESSION['userLevel'];
if (!isset($_SESSION['findFilesExclude'])) {$_SESSION['findFilesExclude'] = $findFilesExclude;}
if (!isset($_SESSION['restrictedFiles'])) {$_SESSION['restrictedFiles'] = $restrictedFiles;}
if (!isset($_SESSION['bannedFiles'])) {$_SESSION['bannedFiles'] = $bannedFiles;}
if (!isset($_SESSION['allowedIPs'])) {$_SESSION['allowedIPs'] = $allowedIPs;}
@@ -158,7 +156,7 @@ if ((isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10)
$pluginsDisplay = "";
for ($i=0;$i<count($plugins);$i++) {
$target = explode(":",$plugins[$i][4]);
$pluginsDisplay .= '<a href="'.$plugins[$i][3].'" target="'.$target[0].'"><img src="'.$plugins[$i][1].'" style="'.$plugins[$i][2].'" alt="'.$plugins[$i][0].'"></a>';
$pluginsDisplay .= '<a href="'.$plugins[$i][3].'" title="'.$plugins[$i][0].'" target="'.$target[0].'"><img src="'.$plugins[$i][1].'" style="'.$plugins[$i][2].'" alt="'.$plugins[$i][0].'"></a>';
};
// If we're updating, replace the plugin display with our newly established one
@@ -191,6 +189,11 @@ if ((isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10)
if ($openLastFiles) {
$onLoadExtras .= ";top.ICEcoder.autoOpenFiles()";
}
// Show server data if we're logged in
if ($_SESSION['userLevel'] == 10) {
$onLoadExtras .= ";top.ICEcoder.content.style.visibility='visible'";
}
}
// If we're due to show the settings screen
@@ -204,12 +207,12 @@ if ($accountPassword == "" && isset($_GET['settings'])) {
<link rel="stylesheet" type="text/css" href="coder.css">
</head>
<body style="background-color: #fff">
<body>
<div class="screenContainer">
<div class="screenVCenter">
<div class="screenCenter">
<img src="../images/ice-coder.gif">
<img src="../images/ice-coder.png">
<div class="version"><?php echo $versionNo;?></div>
<form name="settingsUpdate" action="../index.php" method="POST">
<input type="password" name="accountPassword" class="accountPassword">
@@ -230,12 +233,12 @@ if ($accountPassword == "" && isset($_GET['settings'])) {
// If we're setting a password
if (isset($_POST['accountPassword'])) {
$password = generateHash($_POST['accountPassword']);
$settingsFile = 'lib/settings.php';
$settingsFile = 'lib/config.php';
$settingsContents = file_get_contents($settingsFile);
// Replace our empty password with the one submitted by user
$settingsContents = str_replace('$accountPassword = "";','$accountPassword = "'.$password.'";',$settingsContents);
// Now update this file
$fh = fopen($settingsFile, 'w') or die("can't update settings file");
// Now update the config file
$fh = fopen($settingsFile, 'w') or die("Can't update config file. Please set public write permissions on lib/config.php");
fwrite($fh, $settingsContents);
fclose($fh);
// Set the session user level

View File

@@ -1,87 +0,0 @@
<!DOCTYPE html>
<body>
<script>
top.ICEcoder.serverMessage("<b>Zipping Open Files</b>");
</script>
<?php
// ------------------------------------
// backupOpenFiles by Matt Pass
// Will backups open files in ICE coder
// ------------------------------------
// If we have no post data for the 1st item, set a form up ready to post back
if (!isset($_POST['fileName1'])) {
echo '<form name="zipFiles" id="zipFiles" action="index.php" method="POST">'.PHP_EOL;
for ($i=1;$i<=10;$i++) {
echo '<input type="hidden" name="fileName'.$i.'" id="fName'.$i.'" value="" style="display: none">'.PHP_EOL;
echo '<textarea name="fileContent'.$i.'" id="fContent'.$i.'" style="display: none"></textarea>'.PHP_EOL;
}
echo '</form>'.PHP_EOL;
?>
<script>
// Populate values for file names & contents
for (i=1;i<=top.ICEcoder.openFiles.length;i++) {
document.getElementById('fName'+i).value = top.ICEcoder.openFiles[i-1];
document.getElementById('fContent'+i).value = top.ICEcoder.content.contentWindow['cM'+i].getValue();
}
if (top.ICEcoder.openFiles.length>0) {
document.zipFiles.submit();
}
</script>
<?php
;} else {
// Folder name & filename of the zip
$zipItSaveLocation = '../../backups/';
$zipItFileName = time().'.zip';
// Make the dir if it doesn't exist
if (!is_dir($zipItSaveLocation)) {
mkdir($zipItSaveLocation, 0777);
}
// Start a class
Class zipIt {
public function zipFilesUp($zipName='') {
// OK, if we've got at least one file to add
if($_POST['fileName1']!=="") {
$zip = new ZipArchive();
// Return if we have a problem creating/overwriting our zip
if($zip->open($zipName,$overwriteZip ? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE) !== true) {
return false;
}
// Otherwise, we're OK to add our string into a new file (incl dirs) in the zip, so do that
for($i=1;$i<=10;$i++) {
$fName = 'fileName'.$i;
if($_POST[$fName]!=="") {
$zip->addFromString(ltrim($_POST[$fName],"/"), $_POST['fileContent'.$i]);
}
}
$zip->close();
// We've been successful, so return with a positive response
return file_exists($zipName);
} else {
// If we had 0 files, return
return false;
}
}
}
// Trigger the class
$zipItDoZip = new zipIt();
$zipItAddToZip = $zipItDoZip->zipFilesUp($zipItSaveLocation.$zipItFileName);
if (!$zipItAddToZip) {echo '<script>alert("Could not zip files up!");</script>';};
;};
?>
<script>
top.ICEcoder.serverMessage();
top.ICEcoder.serverQueue("del",0);
</script>
</body>
</html>

71
plugins/zip-it/index.php Normal file
View File

@@ -0,0 +1,71 @@
<?php
// -----------------------------------------------
// Zip-It! for ICEcoder v0.9.0 by Matt Pass
// Will backup requested files/folders in ICEcoder
// -----------------------------------------------
include("../../lib/settings.php");
?>
<!DOCTYPE html>
<html>
<head>
<title>Zip It! for ICEcoder</title>
</head>
<body>
<?
$zipItSaveLocation = '../../backups/';
if ($_GET['zip']=="|") {$zipItFileName = "root";} else {$zipItFileName = str_replace("|","_",$_GET['zip']);};
$zipItFileName .= '-'.time().'.zip';
if (!is_dir($zipItSaveLocation)) {mkdir($zipItSaveLocation, 0777);}
Class zipIt {
public function zipFilesUp($zipName='') {
$zipFiles = array();
$zipTgt = str_replace("|","/",$_GET['zip']);
if (strpos($_GET['zip'],"/")!==0) {$zipTgt = "/".$zipTgt;};
$addItem = $_SERVER['DOCUMENT_ROOT'].$zipTgt;
if (is_dir($addItem)) {
$dirStack = array($addItem);
while (!empty($dirStack)) {
$currentDir = array_pop($dirStack);
$dir = dir($currentDir);
while (false !== ($node = $dir->read())) {
if (($node == '.') || ($node == '..')) {continue;}
if (is_dir($currentDir.$node) && !strpos($currentDir.$node,"_coder")) {
array_push($dirStack,$currentDir.$node.'/');
}
if (is_file($currentDir.$node)) {$zipFiles[] = $currentDir.$node;}
}
}
} else {
if(file_exists($addItem)) {$zipFiles[] = $addItem;}
}
if(count($zipFiles)) {
$zip = new ZipArchive();
if($zip->open($zipName,ZIPARCHIVE::CREATE)!== true) {return false;}
foreach($zipFiles as $file) {
$zip->addFile($file,str_replace($_SERVER['DOCUMENT_ROOT']."/","",$file));
}
$zip->close();
return file_exists($zipName);
} else {
return false;
}
}
}
if($_SESSION['userLevel']==10) {
$zipItDoZip = new zipIt();
echo '<script>top.ICEcoder.serverMessage("<b>Zipping Files</b>");</script>';
$zipItAddToZip = $zipItDoZip->zipFilesUp($zipItSaveLocation.$zipItFileName);
if (!$zipItAddToZip) {
echo '<script>alert("Could not zip files up!");</script>';
} else {
echo '<script>setTimeout(function(){top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);},500);</script>';
}
}
?>
</body>
</html>