Compare commits

...

79 Commits

Author SHA1 Message Date
Matt Pass
8d8edc171c Version v 0.7.4 number change only 2012-06-21 07:56:51 +01:00
Matt Pass
c1f4740b68 Vars & functions to control tab dragging
New dragSrcEl variable and 4 x functions to hand start, over, drop and
end
Means tabs can now be dragged & all references appropriately swapped
2012-06-21 07:56:10 +01:00
Matt Pass
d6a5f486d7 Draggable attribute added
To allow tabs to be dragged (using HTML5)
2012-06-21 07:54:39 +01:00
Matt Pass
807cc53fa8 Target references now hardcoded on init
Previously identified objects by selectTab, but this doesn't work with
dragged tabs
Now identifying using init 'num' value, which is much better & also
means less code
2012-06-21 07:53:55 +01:00
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
Matt Pass
abd61689f1 Better handling of changed files
Insetad of notifying user that file they're attempting to save, now they
can revert
This means the file they're trying to save is reverted to the server
file
Changes they have made are copied into a new file
User can optionally cancel to avoid this
2012-05-26 22:25:12 +01:00
Matt Pass
acbe46b013 Version No & CodeMirror Version No Update 2012-05-26 22:22:45 +01:00
Matt Pass
bbf169907a Update CodeMirror to v.2.25
Update to latest version
2012-05-26 22:22:06 +01:00
Matt Pass
1d3af5c62d Remove CodeMirror 2.24
Update to newer version 2.25
2012-05-26 22:20:40 +01:00
Matt Pass
d095e6a5fe CoffeeScript Support & Update Lang on Tab Switch
CoffeeScript is now supported as a language by ICEcoder
When you switch tabs, the cursor display info also now changes
2012-05-25 17:44:12 +01:00
Matt Pass
96df3ac91b Shortening of hex codes & swapping tab text cols
Hex codes shortened if poss (ie, #888888 becomes #888 and #ff0000
becomes #f00)
Swapped text colour on tabs, selected now has black text, others white
text
2012-05-25 17:03:12 +01:00
Matt Pass
38fe4fd85e Merge branch 'master' of https://github.com/mattpass/ICEcoder 2012-05-25 15:29:20 +01:00
Matt Pass
95ac9b50e0 Republish only 2012-05-25 15:26:43 +01:00
Matt Pass
1f26ddaf3d Another slight format fix 2012-05-24 18:23:48 +01:00
Matt Pass
64231d7f01 Minor format fixes 2012-05-24 18:22:09 +01:00
Matt Pass
656c10e5cf Added MIT license with note about sub-licenses 2012-05-24 18:18:03 +01:00
86 changed files with 1357 additions and 2419 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",
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,230 +0,0 @@
(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 countTimes(func) {
if (typeof func == "string") func = CodeMirror.commands[func];
return function(cm) { for (var i = 0, c = popCount(); i < c; ++i) func(cm); }
}
function iterObj(o, f) {
for (var prop in o) if (o.hasOwnProperty(prop)) f(prop, o[prop]);
}
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 editCursor(mode) {
if (mode == "vim-insert") {
// put in your cursor css changing code
} else if (mode == "vim") {
// put in your cursor css changing code
}
}
function delTillMark(cm, cHar) {
var i = mark[cHar], 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], 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);
}
var map = CodeMirror.keyMap.vim = {
"0": function(cm) {count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(cm);},
// 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) {popCount(); cm.setCursor(cm.getCursor().line, cm.getCursor().ch+1, true); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"Shift-A": function(cm) {popCount(); CodeMirror.commands.goLineEnd(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"I": function(cm) {popCount(); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"Shift-I": function(cm) {popCount(); goLineStartText(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"O": function(cm) {popCount(); CodeMirror.commands.goLineEnd(cm); CodeMirror.commands.newlineAndIndent(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"Shift-O": function(cm) {popCount(); CodeMirror.commands.goLineStart(cm); cm.replaceSelection("\n", "start"); cm.indentLine(cm.getCursor().line); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"G": function(cm) {cm.setOption("keyMap", "vim-prefix-g");},
"D": function(cm) {cm.setOption("keyMap", "vim-prefix-d"); emptyBuffer();},
"Shift-D": function(cm) {
emptyBuffer();
mark["Shift-D"] = cm.getCursor(false).line;
cm.setCursor(cm.getCursor(true).line);
delTillMark(cm,"Shift-D"); mark = [];
},
"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);},
nofallthrough: true
};
// Add bindings for number keys
for (var i = 1; i < 10; ++i) map[i] = pushCountDigit(i);
// 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)},
"'~'": 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", "'$'": "goLineEnd"
}, function(key, cmd) { map[key] = countTimes(cmd); });
CodeMirror.keyMap["vim-prefix-g"] = {
"E": countTimes(function(cm) { moveToWord(cm, word, -1, "start");}),
"Shift-E": countTimes(function(cm) { moveToWord(cm, bigWord, -1, "start");}),
auto: "vim",
nofallthrough: true
};
CodeMirror.keyMap["vim-prefix-m"] = {
auto: "vim",
nofallthrough: true
};
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();},
auto: "vim",
nofallthrough: true
};
CodeMirror.keyMap["vim-prefix-d'"] = {
auto: "vim",
nofallthrough: true
};
CodeMirror.keyMap["vim-prefix-y'"] = {
auto: "vim",
nofallthrough: true
};
// iterate through uppercase alphabet char codes
for (var i = 65; i < 65 + 26; i++) {
// apply for `letter` and 'Shift-' + `letter`
for (var m = String.fromCharCode(i); m.length < 8; m = "Shift-" + 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-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
};
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");
editCursor("vim");
},
"Ctrl-N": function(cm) {/* Code to bring up autocomplete hint */},
"Ctrl-P": function(cm) {/* Code to bring up autocomplete hint */},
fallthrough: ["default"]
};
})();

View File

@@ -1,174 +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
* - xmlpure
*
* 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;
}
}
}
} else if (mode == 'xmlpure') {
var pos = cm.getCursor();
var tok = cm.getTokenAt(pos);
var tagName = tok.state.context.tagName;
if (ch == '>') {
// <foo> tagName=foo, string=foo
// <foo /> tagName=foo, string=/ # ignore
// <foo></foo> tagName=foo, string=/foo # ignore
if (tok.string == tagName) {
cm.replaceSelection('>'); // parity w/html modes
pos = {line: pos.line, ch: pos.ch + 1};
cm.setCursor(pos);
insertEndTag(cm, indent, pos, tagName);
return;
}
} else if (ch == '/') {
// <foo / tagName=foo, string= # ignore
// <foo></ tagName=foo, string=<
if (tok.string == '<') {
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,50 +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 (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,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

@@ -43,6 +43,7 @@
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
}
.CodeMirror-wrap pre {
@@ -63,8 +64,19 @@
position: absolute;
visibility: hidden;
border-left: 1px solid black;
border-right:none;
width:0;
border-right: none;
width: 0;
}
.cm-keymap-fat-cursor pre.CodeMirror-cursor {
width: auto;
border: 0;
background: transparent;
background: rgba(0, 200, 0, .4);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
}
/* Kludge to turn off filter in ie9+, which also accepts rgba */
.cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
}
.CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}
.CodeMirror-focused pre.CodeMirror-cursor {
@@ -100,7 +112,7 @@ div.CodeMirror-selected { background: #d9d9d9; }
.cm-s-default span.cm-bracket {color: #cc7;}
.cm-s-default span.cm-tag {color: #170;}
.cm-s-default span.cm-attribute {color: #00c;}
.cm-s-default span.cm-header {color: #a0a;}
.cm-s-default span.cm-header {color: blue;}
.cm-s-default span.cm-quote {color: #090;}
.cm-s-default span.cm-hr {color: #999;}
.cm-s-default span.cm-link {color: #00c;}

View File

@@ -1,3 +1,5 @@
// CodeMirror version 2.25
//
// All functions that need access to the editor's state live inside
// the CodeMirror function. Below that, at the bottom of the file,
// some utilities are defined.
@@ -78,7 +80,7 @@ var CodeMirror = (function() {
// Variables used by startOperation/endOperation to track what
// happened during the operation.
var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone,
gutterDirty, callbacks;
gutterDirty, callbacks, maxLengthChanged;
// Current visible range (may be bigger than the view window).
var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
// bracketHighlighted is used to remember that a bracket has been
@@ -370,6 +372,7 @@ var CodeMirror = (function() {
return;
case 2:
if (start) setCursor(start.line, start.ch, true);
setTimeout(focusInput, 20);
return;
}
// For button 1, if it was clicked inside the editor
@@ -593,7 +596,7 @@ var CodeMirror = (function() {
if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
if (((window.opera && !e.which) || khtml) && handleKeyBinding(e)) return;
if (((window.opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) return;
var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
if (mode.electricChars.indexOf(ch) > -1)
@@ -668,7 +671,7 @@ var CodeMirror = (function() {
var recomputeMaxLength = false, maxLineLength = maxLine.length;
if (!options.lineWrapping)
doc.iter(from.line, to.line + 1, function(line) {
if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
});
if (from.line != to.line || newText.length > 1) gutterDirty = true;
@@ -724,20 +727,12 @@ var CodeMirror = (function() {
} else {
doc.iter(from.line, from.line + newText.length, function(line) {
var l = line.text;
if (l.length > maxLineLength) {
if (!line.hidden && l.length > maxLineLength) {
maxLine = l; maxLineLength = l.length; maxWidth = null;
recomputeMaxLength = false;
}
});
if (recomputeMaxLength) {
maxLineLength = 0; maxLine = ""; maxWidth = null;
doc.iter(0, doc.size, function(line) {
var l = line.text;
if (l.length > maxLineLength) {
maxLineLength = l.length; maxLine = l;
}
});
}
if (recomputeMaxLength) maxLengthChanged = true;
}
// Add these lines to the work array, so that they will be
@@ -769,6 +764,18 @@ var CodeMirror = (function() {
if (scroller.clientHeight)
code.style.height = (doc.height * textHeight() + 2 * paddingTop()) + "px";
}
function computeMaxLength() {
var maxLineLength = 0;
maxLine = ""; maxWidth = null;
doc.iter(0, doc.size, function(line) {
var l = line.text;
if (!line.hidden && l.length > maxLineLength) {
maxLineLength = l.length; maxLine = l;
}
});
maxLengthChanged = false;
}
function replaceRange(code, from, to) {
from = clipPos(from);
@@ -856,7 +863,8 @@ var CodeMirror = (function() {
else if (overwrite && posEq(sel.from, sel.to))
sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};
replaceSelection(text.slice(same), "end");
prevInput = text;
if (text.length > 1000) { input.value = prevInput = ""; }
else prevInput = text;
return true;
}
function resetInput(user) {
@@ -1493,6 +1501,16 @@ var CodeMirror = (function() {
return changeLine(handle, function(line, no) {
if (line.hidden != hidden) {
line.hidden = hidden;
if (!options.lineWrapping) {
var l = line.text;
if (hidden && l.length == maxLine.length) {
maxLengthChanged = true;
}
else if (!hidden && l.length > maxLine.length) {
maxLine = l; maxWidth = null;
maxLengthChanged = false;
}
}
updateLineHeight(line, hidden ? 0 : 1);
var fline = sel.from.line, tline = sel.to.line;
if (hidden && (fline == no || tline == no)) {
@@ -1845,6 +1863,7 @@ var CodeMirror = (function() {
}
function endOperation() {
var reScroll = false, updated;
if (maxLengthChanged) computeMaxLength();
if (selectionChanged) reScroll = !scrollCursorIntoView();
if (changes.length) updated = updateDisplay(changes, true);
else {
@@ -2484,8 +2503,10 @@ var CodeMirror = (function() {
if (wrapWBR) html.push("<wbr>");
}
html.push(open);
span_(text.slice(wrapAt - outPos), style);
var cut = wrapAt - outPos;
span_(window.opera ? text.slice(cut, cut + 1) : text.slice(cut), style);
html.push("</span>");
if (window.opera) span_(text.slice(cut + 1), style);
wrapAt--;
outPos += l;
} else {
@@ -2601,11 +2622,7 @@ var CodeMirror = (function() {
},
insertHeight: function(at, lines, height) {
this.height += height;
// The trick below is apparently too advanced for IE, which
// occasionally corrupts this.lines (duplicating elements) when
// it is used.
if (ie) this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
else this.lines.splice.apply(this.lines, [at, 0].concat(lines));
this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
},
iterN: function(at, n, op) {
@@ -3056,4 +3073,4 @@ var CodeMirror = (function() {
})();
return CodeMirror;
})();
})();

View File

@@ -1,7 +1,7 @@
(function(){
function SearchCursor(cm, query, pos, caseFold) {
this.atOccurrence = false; this.cm = cm;
if (caseFold == null) caseFold = typeof query == "string" && query == query.toLowerCase();
if (caseFold == null && typeof query == "string") caseFold = false;
pos = pos ? cm.clipPos(pos) : {line: 0, ch: 0};
this.pos = {from: pos, to: pos};

View File

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

View File

@@ -0,0 +1,347 @@
/**
* Link to the project's GitHub page:
* https://github.com/pickhardt/coffeescript-codemirror-mode
*/
CodeMirror.defineMode('coffeescript', function(conf) {
var ERRORCLASS = 'error';
function wordRegexp(words) {
return new RegExp("^((" + words.join(")|(") + "))\\b");
}
var singleOperators = new RegExp("^[\\+\\-\\*/%&|\\^~<>!\?]");
var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]');
var doubleOperators = new RegExp("^((\->)|(\=>)|(\\+\\+)|(\\+\\=)|(\\-\\-)|(\\-\\=)|(\\*\\*)|(\\*\\=)|(\\/\\/)|(\\/\\=)|(==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//))");
var doubleDelimiters = new RegExp("^((\\.\\.)|(\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
var tripleDelimiters = new RegExp("^((\\.\\.\\.)|(//=)|(>>=)|(<<=)|(\\*\\*=))");
var identifiers = new RegExp("^[_A-Za-z$][_A-Za-z$0-9]*");
var wordOperators = wordRegexp(['and', 'or', 'not',
'is', 'isnt', 'in',
'instanceof', 'typeof']);
var indentKeywords = ['for', 'while', 'loop', 'if', 'unless', 'else',
'switch', 'try', 'catch', 'finally', 'class'];
var commonKeywords = ['break', 'by', 'continue', 'debugger', 'delete',
'do', 'in', 'of', 'new', 'return', 'then',
'this', 'throw', 'when', 'until'];
var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
indentKeywords = wordRegexp(indentKeywords);
var stringPrefixes = new RegExp("^('{3}|\"{3}|['\"])");
var regexPrefixes = new RegExp("^(/{3}|/)");
var commonConstants = ['Infinity', 'NaN', 'undefined', 'null', 'true', 'false', 'on', 'off', 'yes', 'no'];
var constants = wordRegexp(commonConstants);
// Tokenizers
function tokenBase(stream, state) {
// Handle scope changes
if (stream.sol()) {
var scopeOffset = state.scopes[0].offset;
if (stream.eatSpace()) {
var lineOffset = stream.indentation();
if (lineOffset > scopeOffset) {
return 'indent';
} else if (lineOffset < scopeOffset) {
return 'dedent';
}
return null;
} else {
if (scopeOffset > 0) {
dedent(stream, state);
}
}
}
if (stream.eatSpace()) {
return null;
}
var ch = stream.peek();
// Handle docco title comment (single line)
if (stream.match("####")) {
stream.skipToEnd();
return 'comment';
}
// Handle multi line comments
if (stream.match("###")) {
state.tokenize = longComment;
return state.tokenize(stream, state);
}
// Single line comment
if (ch === '#') {
stream.skipToEnd();
return 'comment';
}
// Handle number literals
if (stream.match(/^-?[0-9\.]/, false)) {
var floatLiteral = false;
// Floats
if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
floatLiteral = true;
}
if (stream.match(/^-?\d+\.\d*/)) {
floatLiteral = true;
}
if (stream.match(/^-?\.\d+/)) {
floatLiteral = true;
}
if (floatLiteral) {
// prevent from getting extra . on 1..
if (stream.peek() == "."){
stream.backUp(1);
}
return 'number';
}
// Integers
var intLiteral = false;
// Hex
if (stream.match(/^-?0x[0-9a-f]+/i)) {
intLiteral = true;
}
// Decimal
if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
intLiteral = true;
}
// Zero by itself with no other piece of number.
if (stream.match(/^-?0(?![\dx])/i)) {
intLiteral = true;
}
if (intLiteral) {
return 'number';
}
}
// Handle strings
if (stream.match(stringPrefixes)) {
state.tokenize = tokenFactory(stream.current(), 'string');
return state.tokenize(stream, state);
}
// Handle regex literals
if (stream.match(regexPrefixes)) {
if (stream.current() != '/' || stream.match(/^.*\//, false)) { // prevent highlight of division
state.tokenize = tokenFactory(stream.current(), 'string-2');
return state.tokenize(stream, state);
} else {
stream.backUp(1);
}
}
// Handle operators and delimiters
if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) {
return 'punctuation';
}
if (stream.match(doubleOperators)
|| stream.match(singleOperators)
|| stream.match(wordOperators)) {
return 'operator';
}
if (stream.match(singleDelimiters)) {
return 'punctuation';
}
if (stream.match(constants)) {
return 'atom';
}
if (stream.match(keywords)) {
return 'keyword';
}
if (stream.match(identifiers)) {
return 'variable';
}
// Handle non-detected items
stream.next();
return ERRORCLASS;
}
function tokenFactory(delimiter, outclass) {
var singleline = delimiter.length == 1;
return function tokenString(stream, state) {
while (!stream.eol()) {
stream.eatWhile(/[^'"\/\\]/);
if (stream.eat('\\')) {
stream.next();
if (singleline && stream.eol()) {
return outclass;
}
} else if (stream.match(delimiter)) {
state.tokenize = tokenBase;
return outclass;
} else {
stream.eat(/['"\/]/);
}
}
if (singleline) {
if (conf.mode.singleLineStringErrors) {
outclass = ERRORCLASS
} else {
state.tokenize = tokenBase;
}
}
return outclass;
};
}
function longComment(stream, state) {
while (!stream.eol()) {
stream.eatWhile(/[^#]/);
if (stream.match("###")) {
state.tokenize = tokenBase;
break;
}
stream.eatWhile("#");
}
return "comment"
}
function indent(stream, state, type) {
type = type || 'coffee';
var indentUnit = 0;
if (type === 'coffee') {
for (var i = 0; i < state.scopes.length; i++) {
if (state.scopes[i].type === 'coffee') {
indentUnit = state.scopes[i].offset + conf.indentUnit;
break;
}
}
} else {
indentUnit = stream.column() + stream.current().length;
}
state.scopes.unshift({
offset: indentUnit,
type: type
});
}
function dedent(stream, state) {
if (state.scopes.length == 1) return;
if (state.scopes[0].type === 'coffee') {
var _indent = stream.indentation();
var _indent_index = -1;
for (var i = 0; i < state.scopes.length; ++i) {
if (_indent === state.scopes[i].offset) {
_indent_index = i;
break;
}
}
if (_indent_index === -1) {
return true;
}
while (state.scopes[0].offset !== _indent) {
state.scopes.shift();
}
return false
} else {
state.scopes.shift();
return false;
}
}
function tokenLexer(stream, state) {
var style = state.tokenize(stream, state);
var current = stream.current();
// Handle '.' connected identifiers
if (current === '.') {
style = state.tokenize(stream, state);
current = stream.current();
if (style === 'variable') {
return 'variable';
} else {
return ERRORCLASS;
}
}
// Handle properties
if (current === '@') {
stream.eat('@');
return 'keyword';
}
// Handle scope changes.
if (current === 'return') {
state.dedent += 1;
}
if (((current === '->' || current === '=>') &&
!state.lambda &&
state.scopes[0].type == 'coffee' &&
stream.peek() === '')
|| style === 'indent') {
indent(stream, state);
}
var delimiter_index = '[({'.indexOf(current);
if (delimiter_index !== -1) {
indent(stream, state, '])}'.slice(delimiter_index, delimiter_index+1));
}
if (indentKeywords.exec(current)){
indent(stream, state);
}
if (current == 'then'){
dedent(stream, state);
}
if (style === 'dedent') {
if (dedent(stream, state)) {
return ERRORCLASS;
}
}
delimiter_index = '])}'.indexOf(current);
if (delimiter_index !== -1) {
if (dedent(stream, state)) {
return ERRORCLASS;
}
}
if (state.dedent > 0 && stream.eol() && state.scopes[0].type == 'coffee') {
if (state.scopes.length > 1) state.scopes.shift();
state.dedent -= 1;
}
return style;
}
var external = {
startState: function(basecolumn) {
return {
tokenize: tokenBase,
scopes: [{offset:basecolumn || 0, type:'coffee'}],
lastToken: null,
lambda: false,
dedent: 0
};
},
token: function(stream, state) {
var style = tokenLexer(stream, state);
state.lastToken = {style:style, content: stream.current()};
if (stream.eol() && stream.lambda) {
state.lambda = false;
}
return style;
},
indent: function(state, textAfter) {
if (state.tokenize != tokenBase) {
return 0;
}
return state.scopes[0].offset;
}
};
return external;
});
CodeMirror.defineMIME('text/x-coffeescript', 'coffeescript');

View File

@@ -54,7 +54,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
}
else if (/\d/.test(ch)) {
else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
return ret("number", "number");
}

View File

@@ -0,0 +1,21 @@
.cm-s-erlang-dark { background: #002240; color: white; }
.cm-s-erlang-dark div.CodeMirror-selected { background: #b36539 !important; }
.cm-s-erlang-dark .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; }
.cm-s-erlang-dark .CodeMirror-gutter-text { color: #d0d0d0; }
.cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-erlang-dark span.cm-atom { color: #845dc4; }
.cm-s-erlang-dark span.cm-attribute { color: #ff80e1; }
.cm-s-erlang-dark span.cm-bracket { color: #ff9d00; }
.cm-s-erlang-dark span.cm-builtin { color: #eeaaaa; }
.cm-s-erlang-dark span.cm-comment { color: #7777ff; }
.cm-s-erlang-dark span.cm-def { color: #ee77aa; }
.cm-s-erlang-dark span.cm-error { color: #9d1e15; }
.cm-s-erlang-dark span.cm-keyword { color: #ffee80; }
.cm-s-erlang-dark span.cm-meta { color: #50fefe; }
.cm-s-erlang-dark span.cm-number { color: #ffd0d0; }
.cm-s-erlang-dark span.cm-operator { color: #dd1111; }
.cm-s-erlang-dark span.cm-string { color: #3ad900; }
.cm-s-erlang-dark span.cm-tag { color: #9effff; }
.cm-s-erlang-dark span.cm-variable { color: #50fe50; }
.cm-s-erlang-dark span.cm-variable-2 { color: #ee00ee; }

30
LICENSE.md Normal file
View File

@@ -0,0 +1,30 @@
Copyright (C) 2012 Matt Pass
Website: mattpass.com
Email: matt@mattpass.com
Twitter: @mattpass
#ICEcoder License
##Standard Open Source Initiative MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
```
Please note that this LICENSE file covers the ICEcoder shell IDE only and 3rd
party code, in subfolders such as CodeMirror and plugins, may contain their
own LICENSE files, and may not also be an MIT licence.
```

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,15 +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/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>
@@ -23,40 +25,96 @@ if ($theme=="default") {
}
?>
<style type="text/css">
.CodeMirror {position: absolute; width: 0px; background-color: #ffffff}
.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<?;};?>";}
span.CodeMirror-matchhighlight {background: #555555}
.CodeMirror-focused span.CodeMirror-matchhighlight {color: #000000; background: #555555; !important}
.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) {
var fileName = top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1];
var codeFold = CodeMirror.newFoldFunction(CodeMirror.tagRangeFinder,'<span style=\"display: inline-block; width: 13px; height: 13px; background-color: #bb0000; color: #ffffff; text-align: center; cursor: pointer\"><span style="position: relative; top: -1px">+</span></span> %N%');
var codeFold_JS_PHP_Ruby = CodeMirror.newFoldFunction(CodeMirror.braceRangeFinder,'<span style=\"display: inline-block; width: 13px; height: 13px; background-color: #bb0000; color: #ffffff; text-align: center; cursor: pointer\"><span style="position: relative; top: -1px">+</span></span> %N%');
var codeFold = CodeMirror.newFoldFunction(CodeMirror.tagRangeFinder,'<span style=\"display: inline-block; width: 13px; height: 13px; background-color: #b00; color: #fff; text-align: center; cursor: pointer\"><span style="position: relative; top: -1px">+</span></span> %N%');
var codeFold_JS_Coffee_PHP_Ruby = CodeMirror.newFoldFunction(CodeMirror.braceRangeFinder,'<span style=\"display: inline-block; width: 13px; height: 13px; background-color: #b00; color: #fff; text-align: center; cursor: pointer\"><span style="position: relative; top: -1px">+</span></span> %N%');
window['cM'+num] = CodeMirror(document.body, {
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() {
top.ICEcoder.getCaretPosition();
top.ICEcoder.updateCharDisplay();
window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].setLineClass(top.ICEcoder['cMActiveLine'+top.ICEcoder.selectedTab], null);
if(!window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].somethingSelected()) {
top.ICEcoder['cMActiveLine'+top.ICEcoder.selectedTab] = window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].setLineClass(window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].getCursor().line, "cm-s-activeLine");
window['cM'+num].setLineClass(top.ICEcoder['cMActiveLine'+num], null);
if(!window['cM'+num].somethingSelected()) {
top.ICEcoder['cMActiveLine'+num] = window['cM'+num].setLineClass(window['cM'+num].getCursor().line, "cm-s-activeLine");
}
window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].matchHighlight("CodeMirror-matchhighlight");
top.ICEcoder.cssColorPreview();
@@ -78,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();
@@ -122,7 +180,7 @@ function createNewCMInstance(num) {
};
lastKeyCode = e.keyCode;
},
onGutterClick: !fileName || (fileName && fileName.indexOf(".js") == -1 && fileName.indexOf(".php") && fileName.indexOf(".rb") == -1) ? codeFold : codeFold_JS_PHP_Ruby,
onGutterClick: !fileName || (fileName && fileName.indexOf(".js") == -1 && fileName.indexOf(".coffee") == -1 && fileName.indexOf(".php") && fileName.indexOf(".rb") == -1) ? codeFold : codeFold_JS_Coffee_PHP_Ruby,
extraKeys: {
"Tab": function(cm) {CodeMirror.commands[top.tabsIndent ? "defaultTab" : "insertTab"](cm);},
"Shift-Tab": "indentLess"
@@ -130,7 +188,7 @@ function createNewCMInstance(num) {
});
// Now create the active line for this CodeMirror object
top.ICEcoder['cMActiveLine'+top.ICEcoder.selectedTab] = window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].setLineClass(0, "cm-s-activeLine");
top.ICEcoder['cMActiveLine'+num] = window['cM'+num].setLineClass(0, "cm-s-activeLine");
};
</script>

View File

@@ -54,7 +54,7 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
if ($serverType=="Linux") {
$chmodInfo = substr(sprintf('%o', fileperms($link)), -4);
$fileAtts = '<span style="color: #888888; font-size: 8px">'.$chmodInfo.'</span>';
$fileAtts = '<span style="color: #888; font-size: 8px">'.$chmodInfo.'</span>';
}
$fileManager = "<ul class=\"fileManager\">";
$fileManager .= "<li class=\"pft-directory\"><a href=\"#\" onMouseOver=\"top.ICEcoder.overFileFolder('folder','$link')\" onMouseOut=\"top.ICEcoder.overFileFolder('folder','')\" style=\"position: relative; left:-22px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span id=\"|\">/ [ROOT]</span> ".$fileAtts."</a>";
@@ -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);
@@ -88,17 +89,19 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
$fileAtts = "";
if ($serverType=="Linux") {
$chmodInfo = substr(sprintf('%o', fileperms($link)), -4);
$fileAtts = '<span style="color: #888888; font-size: 8px">'.$chmodInfo.'</span>';
$fileAtts = '<span style="color: #888; font-size: 8px">'.$chmodInfo.'</span>';
}
if ($_SESSION['userLevel'] == 10 || ($_SESSION['userLevel'] < 10 && $restrictedFile==false)) {
$fileManager .= "<li class=\"pft-directory\"><a href=\"#\" onMouseOver=\"top.ICEcoder.overFileFolder('folder','$link')\" onMouseOut=\"top.ICEcoder.overFileFolder('folder','')\" style=\"position: relative; left:-22px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span id=\"".str_replace("/","|",str_replace($docRoot,"",$link))."\">" . htmlspecialchars($this_file) . "</span> ".$fileAtts."</a>";
$fileManager .= fileManager_dir("$directory/$this_file", $return_link , false);
$fileManager .= "</li>";
} else {
$fileManager .= "<li class=\"pft-directory\" style=\"cursor: pointer\"><span style=\"position: relative; left:-22px; color: #888888\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [HIDDEN] ".$fileAtts."</span></li>";
$fileManager .= "<li class=\"pft-directory\" style=\"cursor: pointer\"><span style=\"position: relative; left:-22px; color: #888\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [HIDDEN] ".$fileAtts."</span></li>";
}
} 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);
@@ -115,19 +118,24 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
$fileAtts = "";
if ($serverType=="Linux") {
$chmodInfo = substr(sprintf('%o', fileperms($link)), -4);
$fileAtts = '<span style="color: #888888; font-size: 8px">'.$chmodInfo.'</span>';
$fileAtts = '<span style="color: #888; font-size: 8px">'.$chmodInfo.'</span>';
}
$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.')\">";
$fileManager .= "<li class=\"pft-file " . strtolower($ext) . "\" style=\"cursor: default\"><span style=\"position: relative; left:-22px; color: #888888\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [HIDDEN] ".$fileAtts."</span></li>";
$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>";
}
}
}
}
$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.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>
@@ -124,7 +133,7 @@ lastOpenFiles = [<?php
<div id="tabsBar" class="tabsBar" onContextMenu="return false">
<?php
for ($i=1;$i<=10;$i++) {
echo '<div id="tab'.$i.'" class="tab" onClick="if(ICEcoder.canSwitchTabs) {ICEcoder.switchTab('.$i.')} else {ICEcoder.canSwitchTabs=true}"></div>';
echo '<div id="tab'.$i.'" class="tab" draggable="true" onClick="if(ICEcoder.canSwitchTabs) {ICEcoder.switchTab('.$i.')} else {ICEcoder.canSwitchTabs=true}"></div>';
}
?><div class="newTab" onClick="ICEcoder.newTab()"><img src="images/nav-new.png"></div>
</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;
}
@@ -22,19 +22,19 @@ body {overflow: hidden;
-moz-user-select: none;
-o-user-select:none;
user-select: none;
background-color: #222222;
background-color: #222;
}
h1 {font-size: 36px; font-weight: normal; color: #888888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #ffffff}
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: #ffffff; font-size: 10px}
.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: #ffffff}
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: #ffffff; 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 .version {position: relative; display: inline-block; margin-top: 25px; font-size: 10px; color: #bbbbbb}
.header .logo {position: relative; margin: 5px 10px 0px 5px; cursor: pointer}
.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 0 5px; cursor: pointer}
.files {position: absolute; display: inline-block; height: 100%; width: 250px; background-color: #444444; 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: #888888}
.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: #666666;
.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;
@@ -93,18 +94,18 @@ h2 {font-size: 18px; font-weight: normal; color: #ffffff}
}
.files .accountOptions {position: relative; height: 31px; width: 200px; margin-left: 15px; margin-top: 8px}
.files .accountOptions img {cursor: pointer}
.files .accountPassword {position: relative; border: 1px solid #888888; background-color: #999999; height: 18px; width: 140px; margin-left: 14px; margin-top: 15px}
.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: #999999; color: #555555; height:20px; margin-top: 16px; margin-left: 5px; font-size: 11px; cursor: pointer}
.files .button:hover {background-color: #444444; color: #eeeeee}
.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: #ffffff}
}
.files .serverMessage b {font-size: 10px}
.editor {position: absolute; display: inline-block; top: 0px; left: 15px; width: 2400px}
.editor .tabsBar {display: inline-block; height: 22px; width: 2400px; margin-top: 40px; padding-left: 41px; background-color: #888888;}
.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 #ffffff; border-right: solid 1px #777777; color: #ffffff; cursor: pointer;
.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: 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 #ffffff; border-right: solid 1px #777777; cursor: pointer;}
.editor .findBar {display: inline-block; height: 28px; width: 2400px; color: #ffffff; background-color: #141414}
.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 .submit {position: relative; top: -2px; height: 17px; border: 1px solid #bbbbbb; 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 .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 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: #ffffff; background-color: #00bb00}
.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: #ffffff; text-align: right}
.footer .nestDisplay {position: absolute; display: inline-block; padding: 5px 0px 0px 8px; margin-top: 3px; left: 255px; font-size: 12px; color: #ffffff; 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: #ffffff; 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: #333333; z-index: 10}
.fileMenu a {display: block; padding: 2px 5px; background-color: #444444; color: #eeeeee; text-decoration: none}
.fileMenu a:hover {background-color: #666666}
.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: #bbbbbb}
.screenCenter .accountPassword {border: 1px solid #888888; height: 18px}
.screenCenter .button {border: 0px; background: #666666; color: #ffffff; height: 22px; cursor: pointer}
.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: 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
@@ -29,19 +23,23 @@ var ICEcoder = {
stickyTab: false, // If we have a sticky tab open or not
stickyTabWindow: false, // Target variable for the sticky tab window
pluginIntervalRefs: [], // Array of plugin interval refs
dragSrcEl: null, // Tab element being dragged
// 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();
@@ -53,6 +51,16 @@ var ICEcoder = {
top.document.getElementById('accountLogin').style.top = "-50px";
setTimeout(function() {top.document.getElementById('accountLoginContainer').style.display = "none";},300);
}
// Add drag based events to our tabs
var tabs = document.querySelectorAll('.tab');
[].forEach.call(tabs, function(tab) {
// not used: dragenter, dragleave
tab.addEventListener('dragstart', ICEcoder.handleDragStart, false);
tab.addEventListener('dragover', ICEcoder.handleDragOver, false);
tab.addEventListener('drop', ICEcoder.handleDrop, false);
tab.addEventListener('dragend', ICEcoder.handleDragEnd, false);
});
},
// Set our layout according to the browser size
@@ -65,15 +73,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
@@ -89,9 +97,9 @@ var ICEcoder = {
contentCleanUp: function() {
var fileName, cM, content;
// If it's not a JS, Ruby or CSS file, replace & and our temp </textarea> value
// If it's not a JS, CoffeeScript Ruby or CSS file, replace & and our temp </textarea> value
fileName = ICEcoder.openFiles[ICEcoder.selectedTab-1];
if (fileName.indexOf(".js")<0&&fileName.indexOf(".rb")&&fileName.indexOf(".css")<0) {
if (fileName.indexOf(".js")<0 && fileName.indexOf(".coffee")<0 && fileName.indexOf(".rb")<0 && fileName.indexOf(".css")<0) {
cM = ICEcoder.getcMInstance();
content = cM.getValue();
content = content.replace(/<ICEcoder:\/:textarea>/g,'</textarea>');
@@ -182,7 +190,7 @@ var ICEcoder = {
ICEcoder.nestDisplay.innerHTML = "";
if ("undefined" != typeof ICEcoder.openFiles[ICEcoder.selectedTab-1]) {
fileName = ICEcoder.openFiles[ICEcoder.selectedTab-1];
if (fileName.indexOf(".js")<0&&fileName.indexOf(".rb")<0&&fileName.indexOf(".css")<0&&
if (fileName.indexOf(".js")<0 && fileName.indexOf(".coffee")<0 && fileName.indexOf(".rb")<0 && fileName.indexOf(".css")<0&&
(nestCheck.indexOf("include(")==-1)&&(nestCheck.indexOf("include_once(")==-1)&&
(nestCheck.indexOf("<html")>-1||nestCheck.indexOf("<body")>-1)) {
@@ -363,21 +371,30 @@ var ICEcoder = {
// Redo our find display
top.ICEcoder.findMode = false;
ICEcoder.findReplace('find',true,false);
// Finally, update the cursor display
top.ICEcoder.getCaretPosition();
top.ICEcoder.updateCharDisplay();
}
},
// 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 = "#bb0000" : 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)";
}
i==selectedTab ? tColor = "#ffffff" : tColor = "#000000";
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);
},
@@ -396,7 +413,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");
@@ -422,7 +438,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
@@ -446,11 +462,11 @@ var ICEcoder = {
ICEcoder.caretPos=cM.getValue().length;
ICEcoder.getNestLocation();
// Nesting is OK if at the end of the file we have no nests left, or it's a JS, Ruby or CSS file
if (ICEcoder.htmlTagArray.length==0||fileName.indexOf(".js")>0||fileName.indexOf(".rb")>0||fileName.indexOf(".css")>0) {
ICEcoder.nestValid.style.backgroundColor="#00bb00";
if (ICEcoder.htmlTagArray.length==0||fileName.indexOf(".js")>0||fileName.indexOf(".coffee")>0||fileName.indexOf(".rb")>0||fileName.indexOf(".css")>0) {
ICEcoder.nestValid.style.backgroundColor="#0b0";
ICEcoder.nestValid.innerHTML = "Nesting OK";
} else {
ICEcoder.nestValid.style.backgroundColor="#ff0000";
ICEcoder.nestValid.style.backgroundColor="#f00";
ICEcoder.nestValid.innerHTML = "Nesting Broken";
}
},
@@ -496,13 +512,14 @@ var ICEcoder = {
fileName = ICEcoder.openFiles[ICEcoder.selectedTab-1];
if (fileName.indexOf(".js")>0) {caretLocType="JavaScript"};
if (fileName.indexOf(".coffee")>0) {caretLocType="CoffeeScript"};
if (fileName.indexOf(".rb")>0) {caretLocType="Ruby"};
if (fileName.indexOf(".css")>0) {caretLocType="CSS"};
ICEcoder.caretLocType = caretLocType;
// If we're in a JS, PHP or Ruby code block, add that to the nest display
if (caretLocType=="JavaScript"||caretLocType=="PHP"||caretLocType=="Ruby") {
// If we're in a JS, CoffeeScript PHP or Ruby code block, add that to the nest display
if (caretLocType=="JavaScript"||caretLocType=="CoffeeScript"||caretLocType=="PHP"||caretLocType=="Ruby") {
ICEcoder.nestDisplay.innerHTML += " &gt; " + caretLocType;
}
},
@@ -554,7 +571,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
@@ -565,7 +581,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;
@@ -588,7 +604,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;
@@ -608,6 +624,8 @@ var ICEcoder = {
}
}
}
aMenus[0].childNodes[0].className = "open";
aMenus[0].childNodes[1].style.display = "block";
return false;
},
@@ -691,8 +709,20 @@ var ICEcoder = {
// Select or deselect file
selectDeselectFile: function(action,file) {
action == "select" ? file.style.backgroundColor="#888888" : file.style.backgroundColor="transparent";
action == "select" ? file.style.color="#ffffff" : file.style.color="#eeeeee";
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";
},
// Create a new file (start & instant save)
@@ -715,7 +745,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;
@@ -787,7 +821,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();
}
},
@@ -958,11 +992,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;
},
@@ -976,6 +1010,8 @@ var ICEcoder = {
if (fileName) {
if (fileName.indexOf('.js')>0) {
cM.setOption("mode","javascript");
} else if (fileName.indexOf('.coffee')>0) {
cM.setOption("mode","coffeescript");
} else if (fileName.indexOf('.rb')>0) {
cM.setOption("mode","ruby");
} else if (fileName.indexOf('.css')>0) {
@@ -992,7 +1028,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
@@ -1037,7 +1073,7 @@ var ICEcoder = {
lCLen = lineContent.length;
adjustCursor = 3;
if (ICEcoder.caretLocType=="JavaScript"||ICEcoder.caretLocType=="PHP"||ICEcoder.caretLocType=="Ruby"||ICEcoder.caretLocType=="CSS") {
if (ICEcoder.caretLocType=="JavaScript"||ICEcoder.caretLocType=="CoffeeScript"||ICEcoder.caretLocType=="PHP"||ICEcoder.caretLocType=="Ruby"||ICEcoder.caretLocType=="CSS") {
if (cM.somethingSelected()) {
if (ICEcoder.caretLocType=="Ruby") {
startLine = cM.getCursor(true).line;
@@ -1053,7 +1089,7 @@ var ICEcoder = {
}
}
} else {
if (ICEcoder.caretLocType=="CSS") {
if (ICEcoder.caretLocType=="CSS"||ICEcoder.caretLocType=="CoffeeScript") {
lineContent.slice(0,3)!="/* " ? cM.setLine(linePos, "/* " + lineContent + " */") : cM.setLine(linePos, lineContent.slice(3,lCLen).slice(0,lCLen-5));
if (lineContent.slice(0,3)=="/* ") {adjustCursor = -adjustCursor};
} else if (ICEcoder.caretLocType=="Ruby") {
@@ -1084,11 +1120,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;
}
@@ -1322,7 +1358,7 @@ var ICEcoder = {
ICEcoder.serverQueueItems.splice(1,ICEcoder.serverQueueItems.length);
}
top.document.getElementById('loadingMask').style.visibility = "hidden";
top.ICEcoder.serverMessage('<b style="color: #dd0000">Cancelled tasks</b>');
top.ICEcoder.serverMessage('<b style="color: #d00">Cancelled tasks</b>');
setTimeout(function() {top.ICEcoder.serverMessage();},2000);
},
@@ -1388,31 +1424,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();
}
@@ -1428,6 +1460,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 {
@@ -1454,7 +1490,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
@@ -1485,6 +1521,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()};
},
@@ -1493,5 +1535,104 @@ 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;
},
// Tab dragging start
handleDragStart: function(e) {
this.style.opacity = '0.2';
ICEcoder.dragSrcEl = this;
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('text/html', this.innerHTML);
},
// Tab dragging over tabs
handleDragOver: function(e) {
if (e.preventDefault) {e.preventDefault()}
e.dataTransfer.dropEffect = 'move';
return false;
},
// Tab dropping on target
handleDrop: function(e) {
if (e.stopPropagation) {e.stopPropagation()}
if (ICEcoder.dragSrcEl != this) {
ICEcoder.dragSrcEl.innerHTML = this.innerHTML.split(" ")[0] + ICEcoder.dragSrcEl.innerHTML.substr(ICEcoder.dragSrcEl.innerHTML.indexOf(" "),ICEcoder.dragSrcEl.innerHTML.length);
this.innerHTML = e.dataTransfer.getData('text/html').split(" ")[0] + this.innerHTML.substr(ICEcoder.dragSrcEl.innerHTML.indexOf(" "),ICEcoder.dragSrcEl.innerHTML.length);
var dragID = ICEcoder.dragSrcEl.id.substr(3,ICEcoder.dragSrcEl.id.length)*1;
var dropID = this.id.substr(3,this.id.length)*1;
if(dragID==top.ICEcoder.selectedTab) {
var a; // array value
var b = dragID-1;
var c = dropID-1;
a = top.ICEcoder.changedContent;
a[b]=[a[c],a[c]=a[b]][0];
a = top.ICEcoder.openFiles;
a[b]=[a[c],a[c]=a[b]][0];
a = top.ICEcoder.openFileMDTs;
a[b]=[a[c],a[c]=a[b]][0];
a = top.ICEcoder.cMInstances;
a[b]=[a[c],a[c]=a[b]][0];
top.ICEcoder.switchTab(dropID);
}
}
return false;
},
// Tab drag ending
handleDragEnd: function(e) {
this.style.opacity = '1';
}
};

25
lib/config.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
$versionNo = "v 0.7.4";
$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

@@ -157,7 +157,31 @@ if ($_GET['action']=="save") {
}
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);if (top.ICEcoder.stickyTabWindow.location) {top.ICEcoder.stickyTabWindow.location.reload()};action="doneSave";</script>';
} else {
echo "<script>alert('Sorry, this file has changed, cannot save\\n".$file."');</script>";
$loadedFile = file_get_contents($saveFile);
echo '<textarea name="loadedFile" id="loadedFile">'.str_replace("</textarea>","<ICEcoder:/:textarea>",$loadedFile).'</textarea>';
echo '<textarea name="userVersionFile" id="userVersionFile"></textarea>';
?>
<script>
var refreshFile = confirm('Sorry, this file has changed, cannot save\n<?php echo $file;?>\n\nReload this file and copy your version to a new document?');
if (refreshFile) {
var cM = top.ICEcoder.getcMInstance();
var thisTab = top.ICEcoder.selectedTab;
document.getElementById('userVersionFile').value = cM.getValue();
// Revert back to original
cM.setValue(document.getElementById('loadedFile').value);
top.ICEcoder.changedContent[thisTab-1] = 0;
top.ICEcoder.openFileMDTs[top.ICEcoder.selectedTab-1] = "<?php echo filemtime($saveFile); ?>";
cM.clearHistory();
// Now for the new file
top.ICEcoder.newTab();
cM = top.ICEcoder.getcMInstance();
cM.setValue(document.getElementById('userVersionFile').value);
cM.clearHistory();
// Finally, switch back to original tab
top.ICEcoder.switchTab(thisTab);
}
</script>
<?php
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);action="nothing";</script>';
}
} else {
@@ -206,7 +230,7 @@ if (action=="load") {
if (fileType=="image") {
top.document.getElementById('blackMask').style.visibility = "visible";
top.document.getElementById('mediaContainer').innerHTML = "<img src=\"<?php echo str_replace($docRoot,"",$file);?>\" class=\"whiteGlow\" style=\"border: solid 10px #ffffff; max-width: 700px; max-height: 500px\" onClick=\"return false\"><br><span class=\"whiteGlow\" style=\"border: solid 10px #ffffff; color: #000000; background-color: #ffffff\" onClick=\"return false\"><?php echo str_replace($docRoot,"",$file);?></span>";
top.document.getElementById('mediaContainer').innerHTML = "<img src=\"<?php echo str_replace($docRoot,"",$file);?>\" class=\"whiteGlow\" style=\"border: solid 10px #fff; max-width: 700px; max-height: 500px\" onClick=\"return false\"><br><span class=\"whiteGlow\" style=\"border: solid 10px #fff; color: #000; background-color: #fff\" onClick=\"return false\"><?php echo str_replace($docRoot,"",$file);?></span>";
}
top.ICEcoder.serverMessage();
@@ -239,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,55 +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: #eeeeee; 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-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;
}
@@ -23,9 +23,9 @@ body {overflow: hidden;
user-select: none;
}
h1 {font-size: 36px; font-weight: normal; color: #888888; margin-bottom: 20px}
h1 {font-size: 36px; font-weight: normal; color: #888; margin-bottom: 20px}
.help {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #ffffff; padding: 20px}
.help {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #fff; padding: 20px}
.help .key {display: inline-block; width: 175px; text-align: right; margin-right: 5px; float: left}
.help .key .plus {color: #888888}
.help .shortcut {display: inline-block; width: 175px; color: #888888; margin-left: 5px; float: left}
.help .key .plus {color: #888}
.help .shortcut {display: inline-block; width: 175px; color: #888; margin-left: 5px; float: left}

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;
}
@@ -23,13 +23,13 @@ body {overflow: hidden;
user-select: none;
}
h1 {font-size: 36px; font-weight: normal; color: #888888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #ffffff}
hr {border: 0; height: 1px; background-color: #888888}
h1 {font-size: 36px; font-weight: normal; color: #888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #fff}
hr {border: 0; height: 1px; background-color: #888}
.results {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #ffffff}
.results {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #fff}
.results .resultsPane {position: relative; width: 660px; height: 560px; font-size: 10px; padding: 20px; float: left}
.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;
}
@@ -23,23 +23,23 @@ body {overflow: hidden;
user-select: none;
}
h1 {font-size: 36px; font-weight: normal; color: #888888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #ffffff}
h1 {font-size: 36px; font-weight: normal; color: #888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #fff}
.settings {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #ffffff}
.settings .infoPane {position: relative; width: 230px; height: 560px; font-size: 10px; color: #bbbbbb; background-color: #ffffff; padding: 20px; float: left}
.settings .infoPane a {color: #888888; text-decoration: none}
.settings {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #fff}
.settings .infoPane {position: relative; width: 230px; height: 560px; font-size: 10px; color: #bbb; background-color: #fff; padding: 20px; float: left}
.settings .infoPane a {color: #888; text-decoration: none}
.settings .infoPane a:hover {text-decoration: underline}
.settings .logo {position: relative; margin-top: 2px}
.settings .version {position: relative; display: block; margin-top: 5px; margin-bottom: 10px; font-size: 10px; color: #bbbbbb}
.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 input, .settings textarea {border: 1px solid #555555; background-color: #444444; color: #ffffff}
.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: #ffffff; 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';};?>";}
span.CodeMirror-matchhighlight {background: #555555}
.CodeMirror-focused span.CodeMirror-matchhighlight {color: #000000; background: #555555; !important}
.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>
@@ -90,7 +93,7 @@ for ($i=0;$i<count($themeArray)-1;$i++) {
<br>
<h2>security</h2>
new password <span style="font-size: 10px; color: #888888">8 chars</span><br>
new password <span style="font-size: 10px; color: #888">8 chars</span><br>
<input type="password" name="accountPassword" onkeydown="showButton()"><br>
confirm password<br>
<input type="password" name="confirmPassword" onkeydown="showButton()"><br>
@@ -108,7 +111,7 @@ ip addresses<br>
<div class="settingsColumn2">
<h2>plugins</h2>
plugins array <span style="font-size: 10px; color: #888888">name, img src, style, url, target, setInterval (mins)</span><br>
plugins array <span style="font-size: 10px; color: #888">name, img src, style, url, target, setInterval (mins)</span><br>
<textarea name="plugins" class="plugins" onkeydown="showButton()"><?php
for($i=0;$i<count($plugins);$i++) {
for($j=0;$j<count($plugins[$i]);$j++) {
@@ -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

@@ -1,261 +1,264 @@
<?php
session_start();
// Function to handle salted hashing
define('SALT_LENGTH',9);
function generateHash($plainText,$salt=null) {
if ($salt === null) {
$salt = substr(md5(uniqid(rand(), true)),0,SALT_LENGTH);
} else {
$salt = substr($salt,0,SALT_LENGTH);
}
return $salt.sha1($salt.$plainText);
}
// -----------------
// Start of settings
// -----------------
$versionNo = "v 0.6.7";
$codeMirrorDir = "CodeMirror-2.24";
$cMThisVer = 2.24;
$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?
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
$settingsFile = 'settings.php';
$settingsContents = file_get_contents($settingsFile);
// Replace our lastOpenedFiles var with the the current
$repPosStart = strpos($settingsContents,'$tabsIndent');
$repPosEnd = strpos($settingsContents,'$lastOpenedFiles');
// Prepare all our vars
if ($_POST['tabsIndent']) {$tabsIndent = "true";} else {$tabsIndent = "false";};
if ($_POST['testcMVersion']) {$testcMVersion = "true";} else {$testcMVersion = "false";};
if ($_POST['openLastFiles']) {$openLastFiles = "true";} else {$openLastFiles = "false";};
if ($_POST['codeAssist']) {$codeAssist = "true";} else {$codeAssist = "false";};
if ($_POST['visibleTabs']) {$visibleTabs = "true";} else {$visibleTabs = "false";};
if ($_POST['lockedNav']) {$lockedNav = "true";} else {$lockedNav = "false";};
if ($_POST['accountPassword']!="") {$accountPassword = generateHash($_POST['accountPassword']);} else {$accountPassword = $_POST['oldPassword'];};
$restrictedFiles = 'array("'.str_replace(', ','","',$_POST['restrictedFiles']).'")';
$bannedFiles = 'array("'.str_replace(', ','","',$_POST['bannedFiles']).'")';
$allowedIPs = 'array("'.str_replace(', ','","',$_POST['allowedIPs']).'")';
$plugins = 'array('.PHP_EOL.' array('.PHP_EOL.' '.str_replace('====================','),'.PHP_EOL.' array(',$_POST['plugins']).'))';
$theme = $_POST['theme'];
$settingsNew = '$tabsIndent = '.$tabsIndent.';'.PHP_EOL;
$settingsNew .= '$testcMVersion = '.$testcMVersion.';'.PHP_EOL;
$settingsNew .= '$openLastFiles = '.$openLastFiles.';'.PHP_EOL;
$settingsNew .= '$codeAssist = '.$codeAssist.';'.PHP_EOL;
$settingsNew .= '$visibleTabs = '.$visibleTabs.';'.PHP_EOL;
$settingsNew .= '$lockedNav = '.$lockedNav.';'.PHP_EOL;
$settingsNew .= '$accountPassword = "'.$accountPassword.'";'.PHP_EOL;
$settingsNew .= '$restrictedFiles = '.$restrictedFiles.';'.PHP_EOL;
$settingsNew .= '$bannedFiles = '.$bannedFiles.';'.PHP_EOL;
$settingsNew .= '$allowedIPs = '.$allowedIPs.';'.PHP_EOL;
$settingsNew .= '$plugins = '.$plugins.';'.PHP_EOL;
$settingsNew .= '$theme = "'.$theme.'";'.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");
fwrite($fh, $settingsContents);
fclose($fh);
// OK, now this file is updated, update our current session with new arrays
$_SESSION['restrictedFiles'] = $restrictedFiles = explode(", ",$_POST['restrictedFiles']);
$_SESSION['bannedFiles'] = $bannedFiles = explode(", ",$_POST['bannedFiles']);
$_SESSION['allowedIPs'] = $allowedIPs = explode(", ",$_POST['allowedIPs']);
// Work out the theme to use now
if ($theme=="default") {$themeURL="lib/editor.css";} else {$themeURL=$codeMirrorDir."/theme/".$theme.".css";};
// 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>";
}
// Save the currently opened files for next time
if (isset($_GET["saveFiles"]) && $_GET['saveFiles']) {
if ($_SESSION['userLevel'] == 10) {
$settingsFile = 'settings.php';
$settingsContents = file_get_contents($settingsFile);
// Replace our lastOpenedFiles var with the the current
$repPosStart = strpos($settingsContents,'lastOpenedFiles = "')+19;
$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);
fclose($fh);
}
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);</script>';
}
// Establish our user level
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['restrictedFiles'])) {$_SESSION['restrictedFiles'] = $restrictedFiles;}
if (!isset($_SESSION['bannedFiles'])) {$_SESSION['bannedFiles'] = $bannedFiles;}
if (!isset($_SESSION['allowedIPs'])) {$_SESSION['allowedIPs'] = $allowedIPs;}
// Determin our allowed IP addresses
$allowedIP = false;
for($i=0;$i<count($_SESSION['allowedIPs']);$i++) {
if ($_SESSION['allowedIPs'][$i]==$_SERVER["REMOTE_ADDR"]||$_SESSION['allowedIPs'][$i]=="*") {
$allowedIP = true;
}
}
// If user not allowed to view, boot to site root
if (!$allowedIP) {
echo '<script>top.window.location="/";</script>';
};
// Establish our shortened URL, explode the path based on server type (Linux or Windows)
if (strpos($_SERVER['DOCUMENT_ROOT'],"/")>-1) {$slashType = "/";} else {$slashType = "\\";};
$shortURLStarts = explode($slashType,$_SERVER['DOCUMENT_ROOT']);
// Then clear item at the end if there is one, plus trailing slash
// We end up with the directory name of the server root
if ($shortURLStarts[count($shortURLStarts)-1]!="") {$trimArray=1;} else {$trimArray=2;}
$shortURLStarts = $shortURLStarts[count($shortURLStarts)-$trimArray];
// If we're updating or calling from the index.php page, do/redo plugins & last opened files
if ((isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) || strpos($_SERVER['PHP_SELF'],"index.php")>0) {
// If we're updating, we need to recreate the plugins array
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
$plugins = array();
$pluginsArray = explode("====================",str_replace("\"","",str_replace("\r","",str_replace("\n","",$_POST['plugins']))));
for ($i=0;$i<count($pluginsArray);$i++) {
array_push($plugins, explode(",",$pluginsArray[$i]));
}
}
// Work out the plugins to display to the user
$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>';
};
// If we're updating, replace the plugin display with our newly established one
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
echo "<script>top.document.getElementById('pluginsContainer').innerHTML = '".$pluginsDisplay."';</script>";
}
// Work out what plugins we'll need to set on a setInterval
$onLoadExtras = "";
for ($i=0;$i<count($plugins);$i++) {
if ($plugins[$i][5]!="") {
$onLoadExtras .= ";top.ICEcoder.startPluginIntervals(".$i.",'".$plugins[$i][3]."','".$plugins[$i][4]."','".$plugins[$i][5]."')";
};
};
// If we're updating our settings, clear existing setIntervals & the array refs, then start new ones
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
?>
<script>
for (i=0;i<=top.ICEcoder.pluginIntervalRefs.length-1;i++) {
clearInterval(top.ICEcoder['plugTimer'+top.ICEcoder.pluginIntervalRefs[i]]);
}
top.ICEcoder.pluginIntervalRefs = [];
<?php echo $onLoadExtras.PHP_EOL; ?>
</script>
<?php
}
// Finally, open last opened files if we need to (applies to index.php only)
if ($openLastFiles) {
$onLoadExtras .= ";top.ICEcoder.autoOpenFiles()";
}
}
// If we're due to show the settings screen
if ($accountPassword == "" && isset($_GET['settings'])) {
?>
<!DOCTYPE html>
<html>
<head>
<title>ICE Coder - <?php echo $versionNo;?> :: Settings</title>
<link rel="stylesheet" type="text/css" href="coder.css">
</head>
<body style="background-color: #ffffff">
<div class="screenContainer">
<div class="screenVCenter">
<div class="screenCenter">
<img src="../images/ice-coder.gif">
<div class="version"><?php echo $versionNo;?></div>
<form name="settingsUpdate" action="../index.php" method="POST">
<input type="password" name="accountPassword" class="accountPassword">
<input type="submit" name="submit" value="Set Password" class="button">
</form>
</div>
</div>
</div>
</body>
</html>
<?php
} else {
// If the password hasn't been set, set it, but only if we're including
// from the index.php file (as this file is included from multiple places)
if ($accountPassword == "" && strpos($_SERVER['PHP_SELF'],"index.php")>0) {
// If we're setting a password
if (isset($_POST['accountPassword'])) {
$password = generateHash($_POST['accountPassword']);
$settingsFile = 'lib/settings.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");
fwrite($fh, $settingsContents);
fclose($fh);
// Set the session user level
$_SESSION['userLevel'] = 10;
// Finally, load again as now this file has changed and auto login
header('Location: index.php');
} else {
// We need to set the password
header('Location: lib/settings.php?settings=set');
}
}
// If we're logging in, refresh the file manager and show icons if login is correct
if(isset($_POST['loginPassword'])) {
if(isset($_POST['loginPassword']) && generateHash($_POST['loginPassword'],$accountPassword)==$accountPassword) {
$loginAttempt = 'loginOK';
} else {
$loginAttempt = 'loginFailed';
}
echo "<script>top.ICEcoder.refreshFileManager('".$loginAttempt."');</script>";
}
}
<?php
session_start();
// Function to handle salted hashing
define('SALT_LENGTH',9);
function generateHash($plainText,$salt=null) {
if ($salt === null) {
$salt = substr(md5(uniqid(rand(), true)),0,SALT_LENGTH);
} else {
$salt = substr($salt,0,SALT_LENGTH);
}
return $salt.sha1($salt.$plainText);
}
// Settings are stored in this file
include("config.php");
// Update this config file?
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
$settingsFile = 'config.php';
$settingsContents = file_get_contents($settingsFile);
// Replace our settings vars
$repPosStart = strpos($settingsContents,'$tabsIndent');
$repPosEnd = strpos($settingsContents,'$previousFiles');
// Prepare all our vars
if ($_POST['tabsIndent']) {$tabsIndent = "true";} else {$tabsIndent = "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";};
if ($_POST['accountPassword']!="") {$accountPassword = generateHash($_POST['accountPassword']);} else {$accountPassword = $_POST['oldPassword'];};
$restrictedFiles = 'array("'.str_replace(', ','","',$_POST['restrictedFiles']).'")';
$bannedFiles = 'array("'.str_replace(', ','","',$_POST['bannedFiles']).'")';
$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 .= '$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;
$settingsNew .= '$accountPassword = "'.$accountPassword.'";'.PHP_EOL;
$settingsNew .= '$restrictedFiles = '.$restrictedFiles.';'.PHP_EOL;
$settingsNew .= '$bannedFiles = '.$bannedFiles.';'.PHP_EOL;
$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 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 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']);
// Work out the theme to use now
if ($theme=="default") {$themeURL="lib/editor.css";} else {$themeURL=$codeMirrorDir."/theme/".$theme.".css";};
// 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.",".$tabWidth.",".$refreshFM.");</script>";
}
// Save the currently opened files for next time
if (isset($_GET["saveFiles"]) && $_GET['saveFiles']) {
if ($_SESSION['userLevel'] == 10) {
$settingsFile = 'config.php';
$settingsContents = file_get_contents($settingsFile);
// Replace our previousFiles var with the the current
$repPosStart = strpos($settingsContents,'previousFiles = "')+18;
$repPosEnd = strpos($settingsContents,'";',$repPosStart)-$repPosStart;
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>';
}
// Establish our user level
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;}
// Determin our allowed IP addresses
$allowedIP = false;
for($i=0;$i<count($_SESSION['allowedIPs']);$i++) {
if ($_SESSION['allowedIPs'][$i]==$_SERVER["REMOTE_ADDR"]||$_SESSION['allowedIPs'][$i]=="*") {
$allowedIP = true;
}
}
// If user not allowed to view, boot to site root
if (!$allowedIP) {
echo '<script>top.window.location="/";</script>';
};
// Establish our shortened URL, explode the path based on server type (Linux or Windows)
if (strpos($_SERVER['DOCUMENT_ROOT'],"/")>-1) {$slashType = "/";} else {$slashType = "\\";};
$shortURLStarts = explode($slashType,$_SERVER['DOCUMENT_ROOT']);
// Then clear item at the end if there is one, plus trailing slash
// We end up with the directory name of the server root
if ($shortURLStarts[count($shortURLStarts)-1]!="") {$trimArray=1;} else {$trimArray=2;}
$shortURLStarts = $shortURLStarts[count($shortURLStarts)-$trimArray];
// If we're updating or calling from the index.php page, do/redo plugins & last opened files
if ((isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) || strpos($_SERVER['PHP_SELF'],"index.php")>0) {
// If we're updating, we need to recreate the plugins array
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
$plugins = array();
$pluginsArray = explode("====================",str_replace("\"","",str_replace("\r","",str_replace("\n","",$_POST['plugins']))));
for ($i=0;$i<count($pluginsArray);$i++) {
array_push($plugins, explode(",",$pluginsArray[$i]));
}
}
// Work out the plugins to display to the user
$pluginsDisplay = "";
for ($i=0;$i<count($plugins);$i++) {
$target = explode(":",$plugins[$i][4]);
$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
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
echo "<script>top.document.getElementById('pluginsContainer').innerHTML = '".$pluginsDisplay."';</script>";
}
// Work out what plugins we'll need to set on a setInterval
$onLoadExtras = "";
for ($i=0;$i<count($plugins);$i++) {
if ($plugins[$i][5]!="") {
$onLoadExtras .= ";top.ICEcoder.startPluginIntervals(".$i.",'".$plugins[$i][3]."','".$plugins[$i][4]."','".$plugins[$i][5]."')";
};
};
// If we're updating our settings, clear existing setIntervals & the array refs, then start new ones
if (isset($_POST["theme"]) && $_POST["theme"] && $_SESSION['userLevel'] == 10) {
?>
<script>
for (i=0;i<=top.ICEcoder.pluginIntervalRefs.length-1;i++) {
clearInterval(top.ICEcoder['plugTimer'+top.ICEcoder.pluginIntervalRefs[i]]);
}
top.ICEcoder.pluginIntervalRefs = [];
<?php echo $onLoadExtras.PHP_EOL; ?>
</script>
<?php
}
// Finally, open last opened files if we need to (applies to index.php only)
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
if ($accountPassword == "" && isset($_GET['settings'])) {
?>
<!DOCTYPE html>
<html>
<head>
<title>ICE Coder - <?php echo $versionNo;?> :: Settings</title>
<link rel="stylesheet" type="text/css" href="coder.css">
</head>
<body>
<div class="screenContainer">
<div class="screenVCenter">
<div class="screenCenter">
<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">
<input type="submit" name="submit" value="Set Password" class="button">
</form>
</div>
</div>
</div>
</body>
</html>
<?php
} else {
// If the password hasn't been set, set it, but only if we're including
// from the index.php file (as this file is included from multiple places)
if ($accountPassword == "" && strpos($_SERVER['PHP_SELF'],"index.php")>0) {
// If we're setting a password
if (isset($_POST['accountPassword'])) {
$password = generateHash($_POST['accountPassword']);
$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 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
$_SESSION['userLevel'] = 10;
// Finally, load again as now this file has changed and auto login
header('Location: index.php');
} else {
// We need to set the password
header('Location: lib/settings.php?settings=set');
}
}
// If we're logging in, refresh the file manager and show icons if login is correct
if(isset($_POST['loginPassword'])) {
if(isset($_POST['loginPassword']) && generateHash($_POST['loginPassword'],$accountPassword)==$accountPassword) {
$loginAttempt = 'loginOK';
} else {
$loginAttempt = 'loginFailed';
}
echo "<script>top.ICEcoder.refreshFileManager('".$loginAttempt."');</script>";
}
}
?>

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>