Compare commits

...

74 Commits

Author SHA1 Message Date
Matt Pass
f0d4ef75d3 Design improvements for readability of shortcuts 2012-05-10 20:43:52 +01:00
Matt Pass
ec27eb53bc Close button now has 30% white BG, transparent on file deselect 2012-05-10 20:42:49 +01:00
Matt Pass
6512d4895b Nav design improvements & fix to .file types
Nav highlighting & changed status indication now improved
Fixed problem when adding .files it sees it as a folder
2012-05-10 18:43:11 +01:00
Matt Pass
de81341452 Version number update only 2012-05-10 18:41:40 +01:00
Matt Pass
97e6906f17 2 x new filetypes added, some hidden code renamed ready for next lot 2012-05-10 18:41:03 +01:00
Matt Pass
feeb3907bf Nav tab close button now round 2012-05-10 18:40:26 +01:00
Matt Pass
955d7714a2 Design improvements to the nav tabs 2012-05-10 18:40:04 +01:00
Matt Pass
e506d5a535 Couple of new filetype icons 2012-05-10 18:39:40 +01:00
Matt Pass
09ff2f279d Plenty of adjustments to give a new darker styling
Felt the file manager on the left being white was a bit jarring on the eyes
A darker background would be more suitable for long periods
Also decided to overhaul icons and give everything a modern feel
Previously it looked a bit dated, now looks much fresher
2012-05-09 17:22:18 +01:00
Matt Pass
e17a240661 Links in FM now white to suit dark BG removed CSS for unused filetypes
Plus added a couple of more specific filetypes
Commented out a few as I'll add them v/soon (before next point release)
2012-05-09 17:18:28 +01:00
Matt Pass
a6e244a82f No longer considers .asp/.aspx in restrictedFiles, considers .rb instead 2012-05-09 17:16:35 +01:00
Matt Pass
491fb4c243 Adjustments to colours/styling of tabs, items in FM & new Help popup
Minor alts to suit different states of tabs
Also minor alts to select/deselect of files/folders in file manager to suit darker style
New function to show/hide help popup on demand
2012-05-09 17:15:06 +01:00
Matt Pass
ca46e36e5a Minor alts to graphics to fit new styling
Slight adjustments to contrast of graphics
2012-05-09 17:10:28 +01:00
Matt Pass
09e3ece5a7 Help popup by clicking logo
You can now access help popup by clicking ICEcoder logo
2012-05-09 17:09:20 +01:00
Matt Pass
57e820501a Help popup added
New help popup screen, accessed by clicking ICEcoder logo
Shows shortcut keys for now
2012-05-09 17:08:14 +01:00
Matt Pass
1577118643 New & updated file manager icons
Added a few more specific icons such as html, js, ruby etc
Now starting to look more modern
Udpdated some general icons such as directory & refresh too
2012-05-09 17:06:17 +01:00
Matt Pass
856a0c9f31 Removing old icons
Removed many icons from the file manager
This is because I won't be supporting these file types, they're general purpose, or look dated
Will look to add css, sql, doc, pdf, swf, xls and more in the future
2012-05-09 17:04:17 +01:00
Matt Pass
c621479709 Dealing with new files & lastOpenedFiles array
[NEW] or 'blank' files not allowed into lastOpenedFiles array
Only update settings file if we have something to save
Otherwise, clear server message and remove from server queue
2012-05-08 18:31:35 +01:00
Matt Pass
b7769e6203 Dealing with fileMDT for new files
Don't tack fileMDT onto query string if it's undefined (ie, new files)
New file saves then possible if we don't have a fileMDT on query string
2012-05-08 18:29:03 +01:00
Matt Pass
b1e27282a9 Clear server message as well as remove from server queue 2012-05-08 18:26:21 +01:00
Matt Pass
c19df45ec1 New openFilesMDT array, stop erroneously showing changed tab & minor fixes
openFilesMDTs array now stores modified datetimes for collab edits
Stop clearing value of editor instance to avoid change tab error
New code to work with openFilesMDTs array
Stop switching to another tab unless we're closing current
2012-05-08 07:56:13 +01:00
Matt Pass
0ca29f9201 Additional if check on file datetime for collab edits
Wrapped an additional if around the save operations
This is to check if we have latest file, allowing collab edits
(if we attempt save and don't have latest modified date time, alert user
Other minor updates to work with new MDT vars, params, arrays
clearstatcache necessary to get latest modified datetime
2012-05-08 07:51:31 +01:00
Matt Pass
e208b45a88 v0.6.61 dev, .sql now restricted filetype and settings BG colour change 2012-05-08 07:47:31 +01:00
Matt Pass
b8f7be6376 Default BG now dark grey 2012-05-08 07:42:44 +01:00
mattpass
5ae958e349 Merge pull request #50 from WimTibackx/master
Fixes error #49 by isset catching missing GET & POST key errors in a stricter environment. Merged.
2012-05-07 13:09:54 -07:00
Wim Tibackx
7237ef8c69 One more... 2012-05-07 21:56:00 +02:00
Wim Tibackx
215a4ab362 Fix my earlier settings screw-up... Sorry! 2012-05-07 21:52:54 +02:00
Wim Tibackx
8c83378b8b Fixing issue #49: Notices in settings.php (unknown POST/GET-keys). About fix for issue #49 (example: lib/settings.php line 46): If isset(post theme) gives false, post theme would've given that too. If it gives true, validation is still the same as before. 2012-05-07 21:20:58 +02:00
mattpass
9d14ca1eb2 Update README.md 2012-05-07 13:01:33 +02:00
mattpass
78067a8dec Update README.md 2012-05-07 12:51:49 +02:00
mattpass
d12ea02c42 Update README.md 2012-05-07 12:40:31 +02:00
mattpass
3ceb519b8a Update README.md 2012-05-07 12:23:47 +02:00
mattpass
5508cd1074 Update README.md 2012-05-07 12:19:34 +02:00
Matt Pass
d2bf52e5a3 CSS for new multiple results screen 2012-05-05 17:48:34 +01:00
Matt Pass
f39b8e2a35 New multiple results screen
Shows multiple find results & allows user to replace singally, or all
Also shows count of found results, updates text & button vis on interaction
2012-05-05 17:48:13 +01:00
Matt Pass
8c97be00dc Nest display & find/replace improvements
Loaded code no longer has & converted to & so code is not messed with
Nesting only displays if you don't have include, include_once (PHP), plus must have html or body tag (HTML)
Found count display now updates on switching tabs
findReplace updated to take 3rd param, detecting how it was triggered
Find is now case-sensitive by default
Code realigned in findReplace to work more specifically with 'this document'
Extra code also added to replace all
Display count now fixed to be accurate
Multiple results screen show shows when not finding within current document
Function to deal with updating and showing/hiding of results count display
2012-05-05 17:36:13 +01:00
Matt Pass
83085c4c1f Update to always return and provide error message
Alert message now displays if a zip could not be created
Will now always return, success or fail to stop server queue jams
2012-05-05 15:44:01 +01:00
Matt Pass
8adec9a48b 'replace'/'replace all' select menu & show/hide results display switching
New select menu in find & replace, allowing you to replace or replace all
Results count displays only if you select 'this document'
New param on findReplace function to indicate clicking button or not
2012-05-05 15:42:27 +01:00
Matt Pass
c177374d23 Extra param to signify we're not triggering from button click 2012-05-05 15:19:12 +01:00
Matt Pass
334ced8627 Version number update only 2012-05-05 15:17:07 +01:00
Matt Pass
d8229d79a5 New class for replace select menu 2012-05-05 15:16:12 +01:00
Matt Pass
c8665584e9 Minor fix to stop matching on whitespace chars only
Whitespace only chars are now trimmed and so not matched
This is a future update (in next version of CodeMirror) that I'm adding now
2012-05-05 15:14:57 +01:00
Matt Pass
c56af14f52 stickyTab, login, plugin & settings improvements/features
New vars for stickyTab and plugin interval refs
New login container, adjusts to width of file manager
Upon login, slide login box up to reveal icons
New vars to allow stickyTab on CTRL+S+Enter
Improvement so you don't end up with a locked nav thats collapsed
Fix so we only switchtab if we have associated CM instance
Also updates found results display on switching tab
SwitchMode only does this if there is a filename (tab name) available
Plugin timers now created under vars so they can be cleared
If there is a login attempt, slide login box up to reveal icons
New function to show settings screen on demand
New function to update theme, tabsIndent, lockedNav, visibleTabs & file manager
(This is so changed settings can be applied straight away)
File manager refresh only happens if it needs to, for efficiency
2012-05-01 08:18:46 +01:00
Matt Pass
ed8fb0dd67 Settings can now be updated and changes applied on the fly
Moved various items around in code
Identified settings area with start & end comment blocks
.sql files are now a banned file type
new vars for tabsIndent, codeAssist & lockedNav
When settings are changed from settings screen, this file updates itself
Also then applies settings and refreshes/reloads intelligently
Work out if we have an approved IP or not, if not boot to root
Apply plugins (display & setIntervals) on load or on change of this file
Also apply autoOpenFiles onload from index.php
Refresh file manager and show icons if we have a correct login
2012-05-01 08:07:21 +01:00
Matt Pass
f906b41cd2 CSS classes for new settings popup screen 2012-05-01 07:56:37 +01:00
Matt Pass
1491e24039 Settings screen show in popup on right click of logo
Right clicking the ICEcoder logo now shows this settings screen in a popup
This allows you to control all main settings for ICEcoder
Saving settings applies changes to settings.php
Also intelligently reloads & refreshes relevant items for efficiency
Thanked a few people in this screen, hope they don't mind
2012-05-01 07:55:53 +01:00
Matt Pass
30dbad53a7 Session IP, plugin, autoOpenFiles, settingsScreen, & login improvements
Checking of IP now done via session var, so it's updatable via settings
Plugin intervals, display of icons & autoOpenFiles moved to settings.php
(This is so these things can be updated upon settings change)
init function now takes param to determin if you are logged in or not
Logo now right clickable to show settings screen
Account login box now in own container so it can slide out of view on login
Other minor changes to fit in with new features
2012-05-01 07:44:40 +01:00
Matt Pass
b129bc39cb Save now works with stickyTabs, plus minor improvements
When you save, if there is a stickyTab window, it reloads
Popups for images now have white glow around them, plus fix to text color
Moved clearing the server message to cover images too
2012-05-01 07:35:00 +01:00
Matt Pass
5ffba58802 Classes for h1, h2, whiteGlow, accountLogin & container, blue glow & more
Many new classes, including a few adjustments
whiteGlow class to surround popups and a similar blue one for input boxes
Minor adjustments to others to fit new features
2012-05-01 07:31:19 +01:00
Matt Pass
3cd5b99edd Tabbing can now dynamically switch between tab & indent
tab:after now always available, has dynamic content (blank or tab symbol)
Tabbing can now dynamically switch and is either default or indents
(default tabs, but if you've something selected will indent selected lines)
2012-05-01 07:26:01 +01:00
Matt Pass
89b1b51097 Upgrade to CodeMirror 2.24 2012-05-01 07:15:56 +01:00
Matt Pass
6b5c95fc3a Remove CodeMirror 2.23 (upgrading to 2.24) 2012-05-01 07:14:15 +01:00
Matt Pass
8019f66a78 Default = icecoder fix
If you choose the default theme, we need to identify that as 'iceocder'
2012-04-20 08:01:13 +01:00
Matt Pass
b5e8afb8d9 Fix to match new function variable name 2012-04-20 08:00:29 +01:00
Matt Pass
e2b585027b Various CSS styles back in theme
cursor, selected, gutter & matching bracket styles back in default theme
These styles pertain to this theme only and to avoid conflicts with another themne are back in
2012-04-20 07:47:04 +01:00
Matt Pass
56ade7fa75 Some CSS moved back into default theme & visibleTabs option back in
selected, gutter, cursor & matching bracket moved back into default theme
(As it pertains to that theme only)
$visibleTabs option back in
2012-04-20 07:45:58 +01:00
Matt Pass
efbef411f9 Theme setting, open last files if logged in plus fragmenting file menu
User selected 'Theme' variable set here and used later
Last opened files only loaded on start if you are logged in
Rename & View Webpage now within their own wrapper
(This allows us to only show if we have 1 file selected, done via JS)
2012-04-19 17:50:33 +01:00
Matt Pass
6ef524e4ce Themes applied to editor & styling made more general
Some of the general styling moved from default theme to here
(margin on HTML & body, plus selected, gutter, cursor & matching styles)
Removed setting of theme here, done dynamically with existing functions
2012-04-19 17:47:49 +01:00
Matt Pass
dff7573531 Theme can now be chosen, right click menu now dynamic & reload FM
Updates to allow usage of theme as chosen by user
Menu that displays when user click is now more dynamic
(Shows options based on number of files selected)
Function to reload File Manager on demand plus show loading screen
2012-04-19 17:43:41 +01:00
Matt Pass
881b8f014b Adjustment to onContextMenu & FM reloader
Removed selecting of files/folders func when right clicking
Added refresh icon to reload file manager on click
2012-04-19 17:40:19 +01:00
Matt Pass
d273c82b86 Removed clipboard plugin, theme setting & fix to stop UI jamming
Infinite Clipboard plugin removed as no longer developing this idea
Theme setting now available to choose the default or a CM based theme
UI now doesn't jam when opening/closing files if you're not logged in
2012-04-19 17:39:05 +01:00
Matt Pass
6e5ab719a4 Simplified default CSS file
HTML & body styling now spplied to tags
selected, gutter, cursor and matching elements now applied in editor.php
This all allows CodeMirror themes to be used if users want to switch from default
2012-04-19 17:34:28 +01:00
Matt Pass
b416dd79f5 CSS class for refresh icon 2012-04-19 17:29:46 +01:00
Matt Pass
1e4237a483 Refresh icon added to File Manager
Users can now reload file manager by clicking icon
2012-04-19 17:29:00 +01:00
Matt Pass
a90a53458d Clipboard plugin icon removed
Icon removed as no longer including an Infinite Clipboard plugin
2012-04-19 17:28:22 +01:00
Matt Pass
54fa471d26 CodeMirror themes dir added
CodeMirror themes can now be used by ICEcoder
All themes folder included so users can choose if they wish
2012-04-19 17:27:48 +01:00
Matt Pass
be20e8f302 Updates to the fold code function to standardise folding
Orig pull request approved by Marijn and merged into CodeMirror repo
(Not this one, but my previous fix)
2012-04-19 17:25:56 +01:00
Matt Pass
222f651d68 Minor fix to start session from beginnig of file
Was causing problems when opening a file, not able to set as session not started
2012-04-14 18:26:44 +01:00
Matt Pass
b70ee4553a Ruby language support & visible tabs
CodeMirror mode now loaded for Ruby code highlighting
CSS for visible tabs if setting turned on
2012-04-14 18:10:00 +01:00
Matt Pass
493037a01b Ruby language support & auto loading of last opened files
Ruby now supported as a language in .rb files or within % blocks
List of last opened files updates on opening, closing and renaming tabs
Comment toggle function now handles Ruby commenting via # hashes
(Decided not to go for =begin and =end as this requires extra lines)
New function to handle opening of previously opened files
A few global vars that have been added recently now closed
2012-04-14 18:08:03 +01:00
Matt Pass
8233763511 Extra code to allow for auto opening of files
On opening and files being auto loaded, we need to establish the shortURL
This is so tabs can have the correct name on auto loading files
2012-04-14 17:54:52 +01:00
Matt Pass
2c01eeba17 Visible tabs and auto opening last opened files
Option to show tabs as arrows or blanks
Option to open last opened files on next session or not
Accompanying coding to update list of last opened files on demand
Version no update to v0.6.3
2012-04-14 17:53:11 +01:00
Matt Pass
82fd2a5b5d Handling of unsaved changes & loading of previous files
Closing or reloading the window now checks for unsaved files and alerts user
Filenames opened in previous session loaded into array on start
If we have the setting on to open these files, they are opened sequentially on load
2012-04-14 17:44:02 +01:00
Matt Pass
e297fd049f Ruby code highlighting mode added
Mode added from CodeMirror modes lib to handle highlighting of Ruby coding
2012-04-14 17:36:44 +01:00
94 changed files with 2400 additions and 745 deletions

View File

@@ -1,347 +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);
}
var map = CodeMirror.keyMap.vim = {
"0": function(cm) {count.length > 0 ? pushCountDigit("0")(cm) : CodeMirror.commands.goLineStart(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(); CodeMirror.commands.goLineStartSmart(cm); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"O": function(cm) {popCount(); CodeMirror.commands.goLineEnd(cm); cm.replaceSelection("\n", "end"); cm.setOption("keyMap", "vim-insert"); editCursor("vim-insert");},
"Shift-O": function(cm) {popCount(); CodeMirror.commands.goLineStart(cm); cm.replaceSelection("\n", "start"); 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();},
"M": function(cm) {cm.setOption("keyMap", "vim-prefix-m"); mark = [];},
"Y": function(cm) {cm.setOption("keyMap", "vim-prefix-y"); emptyBuffer(); yank = 0;},
"/": function(cm) {var f = CodeMirror.commands.find; f && f(cm); sdir = "f"},
"Shift-/": 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);},
catchall: function(cm) {/*ignore*/}
};
// 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)},
"Shift-`": 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", "Shift-4": "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",
catchall: function(cm) {/*ignore*/}
};
CodeMirror.keyMap["vim-prefix-m"] = {
"A": function(cm) {mark["A"] = cm.getCursor().line;},
"Shift-A": function(cm) {mark["Shift-A"] = cm.getCursor().line;},
"B": function(cm) {mark["B"] = cm.getCursor().line;},
"Shift-B": function(cm) {mark["Shift-B"] = cm.getCursor().line;},
"C": function(cm) {mark["C"] = cm.getCursor().line;},
"Shift-C": function(cm) {mark["Shift-C"] = cm.getCursor().line;},
"D": function(cm) {mark["D"] = cm.getCursor().line;},
"Shift-D": function(cm) {mark["Shift-D"] = cm.getCursor().line;},
"E": function(cm) {mark["E"] = cm.getCursor().line;},
"Shift-E": function(cm) {mark["Shift-E"] = cm.getCursor().line;},
"F": function(cm) {mark["F"] = cm.getCursor().line;},
"Shift-F": function(cm) {mark["Shift-F"] = cm.getCursor().line;},
"G": function(cm) {mark["G"] = cm.getCursor().line;},
"Shift-G": function(cm) {mark["Shift-G"] = cm.getCursor().line;},
"H": function(cm) {mark["H"] = cm.getCursor().line;},
"Shift-H": function(cm) {mark["Shift-H"] = cm.getCursor().line;},
"I": function(cm) {mark["I"] = cm.getCursor().line;},
"Shift-I": function(cm) {mark["Shift-I"] = cm.getCursor().line;},
"J": function(cm) {mark["J"] = cm.getCursor().line;},
"Shift-J": function(cm) {mark["Shift-J"] = cm.getCursor().line;},
"K": function(cm) {mark["K"] = cm.getCursor().line;},
"Shift-K": function(cm) {mark["Shift-K"] = cm.getCursor().line;},
"L": function(cm) {mark["L"] = cm.getCursor().line;},
"Shift-L": function(cm) {mark["Shift-L"] = cm.getCursor().line;},
"M": function(cm) {mark["M"] = cm.getCursor().line;},
"Shift-M": function(cm) {mark["Shift-M"] = cm.getCursor().line;},
"N": function(cm) {mark["N"] = cm.getCursor().line;},
"Shift-N": function(cm) {mark["Shift-N"] = cm.getCursor().line;},
"O": function(cm) {mark["O"] = cm.getCursor().line;},
"Shift-O": function(cm) {mark["Shift-O"] = cm.getCursor().line;},
"P": function(cm) {mark["P"] = cm.getCursor().line;},
"Shift-P": function(cm) {mark["Shift-P"] = cm.getCursor().line;},
"Q": function(cm) {mark["Q"] = cm.getCursor().line;},
"Shift-Q": function(cm) {mark["Shift-Q"] = cm.getCursor().line;},
"R": function(cm) {mark["R"] = cm.getCursor().line;},
"Shift-R": function(cm) {mark["Shift-R"] = cm.getCursor().line;},
"S": function(cm) {mark["S"] = cm.getCursor().line;},
"Shift-S": function(cm) {mark["Shift-S"] = cm.getCursor().line;},
"T": function(cm) {mark["T"] = cm.getCursor().line;},
"Shift-T": function(cm) {mark["Shift-T"] = cm.getCursor().line;},
"U": function(cm) {mark["U"] = cm.getCursor().line;},
"Shift-U": function(cm) {mark["Shift-U"] = cm.getCursor().line;},
"V": function(cm) {mark["V"] = cm.getCursor().line;},
"Shift-V": function(cm) {mark["Shift-V"] = cm.getCursor().line;},
"W": function(cm) {mark["W"] = cm.getCursor().line;},
"Shift-W": function(cm) {mark["Shift-W"] = cm.getCursor().line;},
"X": function(cm) {mark["X"] = cm.getCursor().line;},
"Shift-X": function(cm) {mark["Shift-X"] = cm.getCursor().line;},
"Y": function(cm) {mark["Y"] = cm.getCursor().line;},
"Shift-Y": function(cm) {mark["Shift-Y"] = cm.getCursor().line;},
"Z": function(cm) {mark["Z"] = cm.getCursor().line;},
"Shift-Z": function(cm) {mark["Shift-Z"] = cm.getCursor().line;},
auto: "vim",
catchall: function(cm) {/*ignore*/}
}
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",
catchall: function(cm) {/*ignore*/}
};
CodeMirror.keyMap["vim-prefix-d'"] = {
"A": function(cm) {delTillMark(cm,"A");},
"Shift-A": function(cm) {delTillMark(cm,"Shift-A");},
"B": function(cm) {delTillMark(cm,"B");},
"Shift-B": function(cm) {delTillMark(cm,"Shift-B");},
"C": function(cm) {delTillMark(cm,"C");},
"Shift-C": function(cm) {delTillMark(cm,"Shift-C");},
"D": function(cm) {delTillMark(cm,"D");},
"Shift-D": function(cm) {delTillMark(cm,"Shift-D");},
"E": function(cm) {delTillMark(cm,"E");},
"Shift-E": function(cm) {delTillMark(cm,"Shift-E");},
"F": function(cm) {delTillMark(cm,"F");},
"Shift-F": function(cm) {delTillMark(cm,"Shift-F");},
"G": function(cm) {delTillMark(cm,"G");},
"Shift-G": function(cm) {delTillMark(cm,"Shift-G");},
"H": function(cm) {delTillMark(cm,"H");},
"Shift-H": function(cm) {delTillMark(cm,"Shift-H");},
"I": function(cm) {delTillMark(cm,"I");},
"Shift-I": function(cm) {delTillMark(cm,"Shift-I");},
"J": function(cm) {delTillMark(cm,"J");},
"Shift-J": function(cm) {delTillMark(cm,"Shift-J");},
"K": function(cm) {delTillMark(cm,"K");},
"Shift-K": function(cm) {delTillMark(cm,"Shift-K");},
"L": function(cm) {delTillMark(cm,"L");},
"Shift-L": function(cm) {delTillMark(cm,"Shift-L");},
"M": function(cm) {delTillMark(cm,"M");},
"Shift-M": function(cm) {delTillMark(cm,"Shift-M");},
"N": function(cm) {delTillMark(cm,"N");},
"Shift-N": function(cm) {delTillMark(cm,"Shift-N");},
"O": function(cm) {delTillMark(cm,"O");},
"Shift-O": function(cm) {delTillMark(cm,"Shift-O");},
"P": function(cm) {delTillMark(cm,"P");},
"Shift-P": function(cm) {delTillMark(cm,"Shift-P");},
"Q": function(cm) {delTillMark(cm,"Q");},
"Shift-Q": function(cm) {delTillMark(cm,"Shift-Q");},
"R": function(cm) {delTillMark(cm,"R");},
"Shift-R": function(cm) {delTillMark(cm,"Shift-R");},
"S": function(cm) {delTillMark(cm,"S");},
"Shift-S": function(cm) {delTillMark(cm,"Shift-S");},
"T": function(cm) {delTillMark(cm,"T");},
"Shift-T": function(cm) {delTillMark(cm,"Shift-T");},
"U": function(cm) {delTillMark(cm,"U");},
"Shift-U": function(cm) {delTillMark(cm,"Shift-U");},
"V": function(cm) {delTillMark(cm,"V");},
"Shift-V": function(cm) {delTillMark(cm,"Shift-V");},
"W": function(cm) {delTillMark(cm,"W");},
"Shift-W": function(cm) {delTillMark(cm,"Shift-W");},
"X": function(cm) {delTillMark(cm,"X");},
"Shift-X": function(cm) {delTillMark(cm,"Shift-X");},
"Y": function(cm) {delTillMark(cm,"Y");},
"Shift-Y": function(cm) {delTillMark(cm,"Shift-Y");},
"Z": function(cm) {delTillMark(cm,"Z");},
"Shift-Z": function(cm) {delTillMark(cm,"Shift-Z");},
auto: "vim",
catchall: function(cm) {/*ignore*/}
};
CodeMirror.keyMap["vim-prefix-y'"] = {
"A": function(cm) {yankTillMark(cm,"A");},
"Shift-A": function(cm) {yankTillMark(cm,"Shift-A");},
"B": function(cm) {yankTillMark(cm,"B");},
"Shift-B": function(cm) {yankTillMark(cm,"Shift-B");},
"C": function(cm) {yankTillMark(cm,"C");},
"Shift-C": function(cm) {yankTillMark(cm,"Shift-C");},
"D": function(cm) {yankTillMark(cm,"D");},
"Shift-D": function(cm) {yankTillMark(cm,"Shift-D");},
"E": function(cm) {yankTillMark(cm,"E");},
"Shift-E": function(cm) {yankTillMark(cm,"Shift-E");},
"F": function(cm) {yankTillMark(cm,"F");},
"Shift-F": function(cm) {yankTillMark(cm,"Shift-F");},
"G": function(cm) {yankTillMark(cm,"G");},
"Shift-G": function(cm) {yankTillMark(cm,"Shift-G");},
"H": function(cm) {yankTillMark(cm,"H");},
"Shift-H": function(cm) {yankTillMark(cm,"Shift-H");},
"I": function(cm) {yankTillMark(cm,"I");},
"Shift-I": function(cm) {yankTillMark(cm,"Shift-I");},
"J": function(cm) {yankTillMark(cm,"J");},
"Shift-J": function(cm) {yankTillMark(cm,"Shift-J");},
"K": function(cm) {yankTillMark(cm,"K");},
"Shift-K": function(cm) {yankTillMark(cm,"Shift-K");},
"L": function(cm) {yankTillMark(cm,"L");},
"Shift-L": function(cm) {yankTillMark(cm,"Shift-L");},
"M": function(cm) {yankTillMark(cm,"M");},
"Shift-M": function(cm) {yankTillMark(cm,"Shift-M");},
"N": function(cm) {yankTillMark(cm,"N");},
"Shift-N": function(cm) {yankTillMark(cm,"Shift-N");},
"O": function(cm) {yankTillMark(cm,"O");},
"Shift-O": function(cm) {yankTillMark(cm,"Shift-O");},
"P": function(cm) {yankTillMark(cm,"P");},
"Shift-P": function(cm) {yankTillMark(cm,"Shift-P");},
"Q": function(cm) {yankTillMark(cm,"Q");},
"Shift-Q": function(cm) {yankTillMark(cm,"Shift-Q");},
"R": function(cm) {yankTillMark(cm,"R");},
"Shift-R": function(cm) {yankTillMark(cm,"Shift-R");},
"S": function(cm) {yankTillMark(cm,"S");},
"Shift-S": function(cm) {yankTillMark(cm,"Shift-S");},
"T": function(cm) {yankTillMark(cm,"T");},
"Shift-T": function(cm) {yankTillMark(cm,"Shift-T");},
"U": function(cm) {yankTillMark(cm,"U");},
"Shift-U": function(cm) {yankTillMark(cm,"Shift-U");},
"V": function(cm) {yankTillMark(cm,"V");},
"Shift-V": function(cm) {yankTillMark(cm,"Shift-V");},
"W": function(cm) {yankTillMark(cm,"W");},
"Shift-W": function(cm) {yankTillMark(cm,"Shift-W");},
"X": function(cm) {yankTillMark(cm,"X");},
"Shift-X": function(cm) {yankTillMark(cm,"Shift-X");},
"Y": function(cm) {yankTillMark(cm,"Y");},
"Shift-Y": function(cm) {yankTillMark(cm,"Shift-Y");},
"Z": function(cm) {yankTillMark(cm,"Z");},
"Shift-Z": function(cm) {yankTillMark(cm,"Shift-Z");},
auto: "vim",
catchall: function(cm) {/*ignore*/}
};
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",
catchall: function(cm) {/*ignore*/}
};
CodeMirror.keyMap["vim-insert"] = {
"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,4 +1,4 @@
Copyright (C) 2011 by Marijn Haverbeke <marijnh@gmail.com>
Copyright (C) 2012 by Marijn Haverbeke <marijnh@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -24,6 +24,6 @@
CodeMirror.keyMap["emacs-Ctrl-X"] = {
"Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": "undo", "K": "close",
auto: "emacs", catchall: function(cm) {/*ignore*/}
auto: "emacs", nofallthrough: true
};
})();

View File

@@ -0,0 +1,230 @@
(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

@@ -42,11 +42,13 @@
padding: 0; margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden;

View File

@@ -1,5 +1,3 @@
// CodeMirror version 2.23
//
// 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.
@@ -41,7 +39,7 @@ var CodeMirror = (function() {
lineSpace = gutter.nextSibling.firstChild, measure = lineSpace.firstChild,
cursor = measure.nextSibling, selectionDiv = cursor.nextSibling,
lineDiv = selectionDiv.nextSibling;
themeChanged();
themeChanged(); keyMapChanged();
// Needed to hide big blue blinking cursor on Mobile Safari
if (ios) input.style.width = "0px";
if (!webkit) lineSpace.draggable = true;
@@ -98,7 +96,6 @@ var CodeMirror = (function() {
// Register our event handlers.
connect(scroller, "mousedown", operation(onMouseDown));
connect(scroller, "dblclick", operation(onDoubleClick));
connect(lineSpace, "dragstart", onDragStart);
connect(lineSpace, "selectstart", e_preventDefault);
// Gecko browsers fire contextmenu *after* opening the menu, at
// which point we can't mess with it anymore. Context menu is
@@ -118,9 +115,16 @@ var CodeMirror = (function() {
connect(input, "focus", onFocus);
connect(input, "blur", onBlur);
connect(scroller, "dragenter", e_stop);
connect(scroller, "dragover", e_stop);
connect(scroller, "drop", operation(onDrop));
if (options.dragDrop) {
connect(lineSpace, "dragstart", onDragStart);
function drag_(e) {
if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
e_stop(e);
}
connect(scroller, "dragenter", drag_);
connect(scroller, "dragover", drag_);
connect(scroller, "drop", operation(onDrop));
}
connect(scroller, "paste", function(){focusInput(); fastPoll();});
connect(input, "paste", fastPoll);
connect(input, "cut", operation(function(){
@@ -160,6 +164,7 @@ var CodeMirror = (function() {
else if (option == "theme") themeChanged();
else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)();
else if (option == "tabSize") updateDisplay(true);
else if (option == "keyMap") keyMapChanged();
if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme") {
gutterChanged();
updateDisplay(true);
@@ -312,6 +317,7 @@ var CodeMirror = (function() {
},
operation: function(f){return operation(f)();},
compoundChange: function(f){return compoundChange(f);},
refresh: function(){
updateDisplay(true);
if (scroller.scrollHeight > lastScrollPos)
@@ -336,7 +342,7 @@ var CodeMirror = (function() {
splitLines(code), top, top);
updateInput = true;
}
function getValue(code) {
function getValue() {
var text = [];
doc.iter(0, doc.size, function(line) { text.push(line.text); });
return text.join("\n");
@@ -385,20 +391,22 @@ var CodeMirror = (function() {
} else { lastClick = {time: now, pos: start}; }
var last = start, going;
if (dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) &&
!posLess(start, sel.from) && !posLess(sel.to, start)) {
// Let the drag handler handle this.
if (webkit) lineSpace.draggable = true;
var up = connect(document, "mouseup", operation(function(e2) {
function dragEnd(e2) {
if (webkit) lineSpace.draggable = false;
draggingText = false;
up();
up(); drop();
if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
e_preventDefault(e2);
setCursor(start.line, start.ch, true);
focusInput();
}
}), true);
}
var up = connect(document, "mouseup", operation(dragEnd), true);
var drop = connect(scroller, "drop", operation(dragEnd), true);
draggingText = true;
// IE's approach to draggable
if (lineSpace.dragDrop) lineSpace.dragDrop();
@@ -447,6 +455,7 @@ var CodeMirror = (function() {
selectWordAt(start);
}
function onDrop(e) {
if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return;
e.preventDefault();
var pos = posFromMouse(e, true), files = e.dataTransfer.files;
if (!pos || options.readOnly) return;
@@ -456,12 +465,12 @@ var CodeMirror = (function() {
reader.onload = function() {
text[i] = reader.result;
if (++read == n) {
pos = clipPos(pos);
operation(function() {
pos = clipPos(pos);
operation(function() {
var end = replaceRange(text.join(""), pos, pos);
setSelectionUser(pos, end);
})();
}
}
};
reader.readAsText(file);
}
@@ -472,12 +481,14 @@ var CodeMirror = (function() {
try {
var text = e.dataTransfer.getData("Text");
if (text) {
var curFrom = sel.from, curTo = sel.to;
setSelectionUser(pos, pos);
if (draggingText) replaceRange("", curFrom, curTo);
replaceSelection(text);
focusInput();
}
compoundChange(function() {
var curFrom = sel.from, curTo = sel.to;
setSelectionUser(pos, pos);
if (draggingText) replaceRange("", curFrom, curTo);
replaceSelection(text);
focusInput();
});
}
}
catch(e){}
}
@@ -529,25 +540,33 @@ var CodeMirror = (function() {
if (e_prop(e, "ctrlKey")) name = "Ctrl-" + name;
if (e_prop(e, "metaKey")) name = "Cmd-" + name;
var stopped = false;
function stop() { stopped = true; }
if (e_prop(e, "shiftKey")) {
handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap,
function(b) {return doHandleBinding(b, true);})
function(b) {return doHandleBinding(b, true);}, stop)
|| lookupKey(name, options.extraKeys, options.keyMap, function(b) {
if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(b);
});
}, stop);
} else {
handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding);
handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding, stop);
}
if (stopped) handled = false;
if (handled) {
e_preventDefault(e);
restartBlink();
if (ie) { e.oldKeyCode = e.keyCode; e.keyCode = 0; }
}
return handled;
}
function handleCharBinding(e, ch) {
var handled = lookupKey("'" + ch + "'", options.extraKeys,
options.keyMap, doHandleBinding);
if (handled) e_preventDefault(e);
options.keyMap, function(b) { return doHandleBinding(b, true); });
if (handled) {
e_preventDefault(e);
restartBlink();
}
return handled;
}
@@ -648,7 +667,7 @@ var CodeMirror = (function() {
if (suppressEdits) return;
var recomputeMaxLength = false, maxLineLength = maxLine.length;
if (!options.lineWrapping)
doc.iter(from.line, to.line, function(line) {
doc.iter(from.line, to.line + 1, function(line) {
if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
});
if (from.line != to.line || newText.length > 1) gutterDirty = true;
@@ -696,14 +715,14 @@ var CodeMirror = (function() {
doc.insert(from.line + 1, added);
}
if (options.lineWrapping) {
var perLine = scroller.clientWidth / charWidth() - 3;
var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3);
doc.iter(from.line, from.line + newText.length, function(line) {
if (line.hidden) return;
var guess = Math.ceil(line.text.length / perLine) || 1;
if (guess != line.height) updateLineHeight(line, guess);
});
} else {
doc.iter(from.line, i + newText.length, function(line) {
doc.iter(from.line, from.line + newText.length, function(line) {
var l = line.text;
if (l.length > maxLineLength) {
maxLine = l; maxLineLength = l.length; maxWidth = null;
@@ -874,8 +893,9 @@ var CodeMirror = (function() {
var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft;
var gutterw = options.fixedGutter ? gutter.clientWidth : 0;
if (x1 < screenleft + gutterw) {
if (x1 < 50) x1 = 0;
var atLeft = x1 < gutterw + pl + 10;
if (x1 < screenleft + gutterw || atLeft) {
if (atLeft) x1 = 0;
scroller.scrollLeft = Math.max(0, x1 - 10 - gutterw);
scrolled = true;
}
@@ -890,10 +910,10 @@ var CodeMirror = (function() {
function visibleLines() {
var lh = textHeight(), top = scroller.scrollTop - paddingTop();
var from_height = Math.max(0, Math.floor(top / lh));
var to_height = Math.ceil((top + scroller.clientHeight) / lh);
return {from: lineAtHeight(doc, from_height),
to: lineAtHeight(doc, to_height)};
var fromHeight = Math.max(0, Math.floor(top / lh));
var toHeight = Math.ceil((top + scroller.clientHeight) / lh);
return {from: lineAtHeight(doc, fromHeight),
to: lineAtHeight(doc, toHeight)};
}
// Uses a set of changes plus the current scroll position to
// determine which DOM updates have to be made, and makes the
@@ -924,7 +944,7 @@ var CodeMirror = (function() {
if (range.from >= range.to) intact.splice(i--, 1);
else intactLines += range.to - range.from;
}
if (intactLines == to - from) return;
if (intactLines == to - from && from == showingFrom && to == showingTo) return;
intact.sort(function(a, b) {return a.domStart - b.domStart;});
var th = textHeight(), gutterDisplay = gutter.style.display;
@@ -1108,12 +1128,14 @@ var CodeMirror = (function() {
selectionDiv.style.display = "none";
} else {
var sameLine = fromPos.y == toPos.y, html = "";
function add(left, top, right, height) {
html += '<div class="CodeMirror-selected" style="position: absolute; left: ' + left +
'px; top: ' + top + 'px; right: ' + right + 'px; height: ' + height + 'px"></div>';
}
var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth;
var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight;
function add(left, top, right, height) {
var rstyle = quirksMode ? "width: " + (!right ? clientWidth : clientWidth - right - left) + "px"
: "right: " + right + "px";
html += '<div class="CodeMirror-selected" style="position: absolute; left: ' + left +
'px; top: ' + top + 'px; ' + rstyle + '; height: ' + height + 'px"></div>';
}
if (sel.from.ch && fromPos.y >= 0) {
var right = sameLine ? clientWidth - toPos.x : 0;
add(fromPos.x, fromPos.y, right, th);
@@ -1189,13 +1211,14 @@ var CodeMirror = (function() {
var line = getLine(lNo);
if (!line.hidden) {
var ch = pos.ch;
if (ch > oldCh || ch > line.text.length) ch = line.text.length;
if (toEnd || ch > oldCh || ch > line.text.length) ch = line.text.length;
return {line: lNo, ch: ch};
}
lNo += dir;
}
}
var line = getLine(pos.line);
var toEnd = pos.ch == line.text.length && pos.ch != oldCh;
if (!line.hidden) return pos;
if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1);
else return getNonHidden(-1) || getNonHidden(1);
@@ -1355,9 +1378,14 @@ var CodeMirror = (function() {
return (tabCache[w] = {html: str + "</span>", width: w});
}
function themeChanged() {
scroller.className = scroller.className.replace(/\s*cm-s-\w+/g, "") +
scroller.className = scroller.className.replace(/\s*cm-s-\S+/g, "") +
options.theme.replace(/(^|\s)\s*/g, " cm-s-");
}
function keyMapChanged() {
var style = keyMap[options.keyMap].style;
wrapper.className = wrapper.className.replace(/\s*cm-keymap-\S+/g, "") +
(style ? " cm-keymap-" + style : "");
}
function TextMarker() { this.set = []; }
TextMarker.prototype.clear = operation(function() {
@@ -1506,8 +1534,7 @@ var CodeMirror = (function() {
if (x <= 0) return 0;
var lineObj = getLine(line), text = lineObj.text;
function getX(len) {
measure.innerHTML = "<pre><span>" + lineObj.getHTML(makeTab, len) + "</span></pre>";
return measure.firstChild.firstChild.offsetWidth;
return measureLine(lineObj, len).left;
}
var from = 0, fromX = 0, to = text.length, toX;
// Guess a suitable upper bound for our search.
@@ -1530,19 +1557,13 @@ var CodeMirror = (function() {
}
}
var tempId = Math.floor(Math.random() * 0xffffff).toString(16);
var tempId = "CodeMirror-temp-" + Math.floor(Math.random() * 0xffffff).toString(16);
function measureLine(line, ch) {
if (ch == 0) return {top: 0, left: 0};
var extra = "";
// Include extra text at the end to make sure the measured line is wrapped in the right way.
if (options.lineWrapping) {
var end = line.text.indexOf(" ", ch + 6);
extra = htmlEscape(line.text.slice(ch + 1, end < 0 ? line.text.length : end + (ie ? 5 : 0)));
}
measure.innerHTML = "<pre>" + line.getHTML(makeTab, ch) +
'<span id="CodeMirror-temp-' + tempId + '">' + htmlEscape(line.text.charAt(ch) || " ") + "</span>" +
extra + "</pre>";
var elt = document.getElementById("CodeMirror-temp-" + tempId);
var wbr = options.lineWrapping && ch < line.text.length &&
spanAffectsWrapping.test(line.text.slice(ch - 1, ch + 1));
measure.innerHTML = "<pre>" + line.getHTML(makeTab, ch, tempId, wbr) + "</pre>";
var elt = document.getElementById(tempId);
var top = elt.offsetTop, left = elt.offsetLeft;
// Older IEs report zero offsets for spans directly after a wrap
if (ie && top == 0 && left == 0) {
@@ -1790,13 +1811,17 @@ var CodeMirror = (function() {
var changed = line.highlight(mode, state, options.tabSize);
if (changed) realChange = true;
line.stateAfter = copyState(mode, state);
var done = null;
if (compare) {
if (hadState && compare(hadState, state)) return true;
} else {
var same = hadState && compare(hadState, state);
if (same != Pass) done = !!same;
}
if (done == null) {
if (changed !== false || !hadState) unchanged = 0;
else if (++unchanged > 3 && (!mode.indent || mode.indent(hadState, "") == mode.indent(state, "")))
return true;
done = true;
}
if (done) return true;
++i;
});
if (bail) return;
@@ -1856,6 +1881,11 @@ var CodeMirror = (function() {
};
}
function compoundChange(f) {
history.startCompound();
try { return f(); } finally { history.endCompound(); }
}
for (var ext in extensions)
if (extensions.propertyIsEnumerable(ext) &&
!instance.propertyIsEnumerable(ext))
@@ -1877,12 +1907,14 @@ var CodeMirror = (function() {
electricChars: true,
autoClearEmptyLines: false,
onKeyEvent: null,
onDragEvent: null,
lineWrapping: false,
lineNumbers: false,
gutter: false,
fixedGutter: false,
firstLineNumber: 1,
readOnly: false,
dragDrop: true,
onChange: null,
onCursorActivity: null,
onGutterClick: null,
@@ -1906,6 +1938,10 @@ var CodeMirror = (function() {
var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
CodeMirror.defineMode = function(name, mode) {
if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name;
if (arguments.length > 2) {
mode.dependencies = [];
for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]);
}
modes[name] = mode;
};
CodeMirror.defineMIME = function(mime, spec) {
@@ -1922,10 +1958,7 @@ var CodeMirror = (function() {
CodeMirror.getMode = function(options, spec) {
var spec = CodeMirror.resolveMode(spec);
var mfactory = modes[spec.name];
if (!mfactory) {
if (window.console) console.warn("No mode " + spec.name + " found, falling back to plain text.");
return CodeMirror.getMode(options, "text/plain");
}
if (!mfactory) return CodeMirror.getMode(options, "text/plain");
return mfactory(options, spec);
};
CodeMirror.listModes = function() {
@@ -1983,6 +2016,10 @@ var CodeMirror = (function() {
indentMore: function(cm) {cm.indentSelection("add");},
indentLess: function(cm) {cm.indentSelection("subtract");},
insertTab: function(cm) {cm.replaceSelection("\t", "end");},
defaultTab: function(cm) {
if (cm.somethingSelected()) cm.indentSelection("add");
else cm.replaceSelection("\t", "end");
},
transposeChars: function(cm) {
var cur = cm.getCursor(), line = cm.getLine(cur.line);
if (cur.ch > 0 && cur.ch < line.length - 1)
@@ -2000,7 +2037,7 @@ var CodeMirror = (function() {
keyMap.basic = {
"Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
"End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
"Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "insertTab", "Shift-Tab": "indentAuto",
"Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "defaultTab", "Shift-Tab": "indentAuto",
"Enter": "newlineAndIndent", "Insert": "toggleOverwrite"
};
// Note that the save and find-related commands aren't defined by
@@ -2035,12 +2072,15 @@ var CodeMirror = (function() {
if (typeof val == "string") return keyMap[val];
else return val;
}
function lookupKey(name, extraMap, map, handle) {
function lookupKey(name, extraMap, map, handle, stop) {
function lookup(map) {
map = getKeyMap(map);
var found = map[name];
if (found != null && handle(found)) return true;
if (map.catchall) return handle(map.catchall);
if (map.nofallthrough) {
if (stop) stop();
return true;
}
var fallthrough = map.fallthrough;
if (fallthrough == null) return false;
if (Object.prototype.toString.call(fallthrough) != "[object Array]")
@@ -2402,9 +2442,9 @@ var CodeMirror = (function() {
indentation: function(tabSize) {return countColumn(this.text, null, tabSize);},
// Produces an HTML fragment for the line, taking selection,
// marking, and highlighting into account.
getHTML: function(makeTab, endAt) {
getHTML: function(makeTab, wrapAt, wrapId, wrapWBR) {
var html = [], first = true, col = 0;
function span(text, style) {
function span_(text, style) {
if (!text) return;
// Work around a bug where, in some compat modes, IE ignores leading spaces
if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1);
@@ -2432,24 +2472,50 @@ var CodeMirror = (function() {
if (style) html.push('<span class="', style, '">', escaped, "</span>");
else html.push(escaped);
}
var span = span_;
if (wrapAt != null) {
var outPos = 0, open = "<span id=\"" + wrapId + "\">";
span = function(text, style) {
var l = text.length;
if (wrapAt >= outPos && wrapAt < outPos + l) {
if (wrapAt > outPos) {
span_(text.slice(0, wrapAt - outPos), style);
// See comment at the definition of spanAffectsWrapping
if (wrapWBR) html.push("<wbr>");
}
html.push(open);
span_(text.slice(wrapAt - outPos), style);
html.push("</span>");
wrapAt--;
outPos += l;
} else {
outPos += l;
span_(text, style);
// Output empty wrapper when at end of line
if (outPos == wrapAt && outPos == len) html.push(open + " </span>");
// Stop outputting HTML when gone sufficiently far beyond measure
else if (outPos > wrapAt + 10 && /\s/.test(text)) span = function(){};
}
}
}
var st = this.styles, allText = this.text, marked = this.marked;
var len = allText.length;
if (endAt != null) len = Math.min(endAt, len);
function styleToClass(style) {
if (!style) return null;
return "cm-" + style.replace(/ +/g, " cm-");
}
if (!allText && endAt == null)
if (!allText && wrapAt == null) {
span(" ");
else if (!marked || !marked.length)
} else if (!marked || !marked.length) {
for (var i = 0, ch = 0; ch < len; i+=2) {
var str = st[i], style = st[i+1], l = str.length;
if (ch + l > len) str = str.slice(0, len - ch);
ch += l;
span(str, styleToClass(style));
}
else {
} else {
var pos = 0, i = 0, text = "", style, sg = 0;
var nextChange = marked[0].from || 0, marks = [], markpos = 0;
function advanceMarks() {
@@ -2535,7 +2601,11 @@ var CodeMirror = (function() {
},
insertHeight: function(at, lines, height) {
this.height += height;
this.lines.splice.apply(this.lines, [at, 0].concat(lines));
// 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));
for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
},
iterN: function(at, n, op) {
@@ -2701,33 +2771,36 @@ var CodeMirror = (function() {
function History() {
this.time = 0;
this.done = []; this.undone = [];
this.compound = 0;
this.closed = false;
}
History.prototype = {
addChange: function(start, added, old) {
this.undone.length = 0;
var time = +new Date, cur = this.done[this.done.length - 1], last = cur && cur[cur.length - 1];
var dtime = time - this.time;
if (dtime > 400 || !last) {
this.done.push([{start: start, added: added, old: old}]);
} else if (last.start > start + old.length || last.start + last.added < start - last.added + last.old.length) {
if (this.compound && cur && !this.closed) {
cur.push({start: start, added: added, old: old});
} else if (dtime > 400 || !last || this.closed ||
last.start > start + old.length || last.start + last.added < start) {
this.done.push([{start: start, added: added, old: old}]);
this.closed = false;
} else {
var oldoff = 0;
if (start < last.start) {
for (var i = last.start - start - 1; i >= 0; --i)
last.old.unshift(old[i]);
oldoff = Math.min(0, added - old.length);
last.added += last.start - start + oldoff;
last.start = start;
} else if (last.start < start) {
oldoff = start - last.start;
added += oldoff;
}
for (var i = last.added - oldoff, e = old.length; i < e; ++i)
last.old.push(old[i]);
if (last.added < added) last.added = added;
var startBefore = Math.max(0, last.start - start),
endAfter = Math.max(0, (start + old.length) - (last.start + last.added));
for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]);
for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]);
if (startBefore) last.start = start;
last.added += added - (old.length - startBefore - endAfter);
}
this.time = time;
},
startCompound: function() {
if (!this.compound++) this.closed = true;
},
endCompound: function() {
if (!--this.compound) this.closed = true;
}
};
@@ -2789,8 +2862,10 @@ var CodeMirror = (function() {
var gecko = /gecko\/\d{7}/i.test(navigator.userAgent);
var ie = /MSIE \d/.test(navigator.userAgent);
var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent);
var quirksMode = ie && document.documentMode == 5;
var webkit = /WebKit\//.test(navigator.userAgent);
var chrome = /Chrome\//.test(navigator.userAgent);
var safari = /Apple Computer/.test(navigator.vendor);
var khtml = /KHTML\//.test(navigator.userAgent);
// Detect drag-and-drop
@@ -2802,13 +2877,25 @@ var CodeMirror = (function() {
return "draggable" in div || "dragDrop" in div;
}();
var lineSep = "\n";
// Feature-detect whether newlines in textareas are converted to \r\n
(function () {
var lineSep = function () {
var te = document.createElement("textarea");
te.value = "foo\nbar";
if (te.value.indexOf("\r") > -1) lineSep = "\r\n";
}());
if (te.value.indexOf("\r") > -1) return "\r\n";
return "\n";
}();
// For a reason I have yet to figure out, some browsers disallow
// word wrapping between certain characters *only* if a new inline
// element is started between them. This makes it hard to reliably
// measure the position of things, since that requires inserting an
// extra span. This terribly fragile set of regexps matches the
// character combinations that suffer from this phenomenon on the
// various browsers.
var spanAffectsWrapping = /^$/; // Won't match any two-character string
if (gecko) spanAffectsWrapping = /$'/;
else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/;
else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/;
// Counts the column offset in a string, taking tabs into account.
// Used mostly to find indentation.
@@ -2969,4 +3056,4 @@ var CodeMirror = (function() {
})();
return CodeMirror;
})();
})();

View File

@@ -1,7 +1,7 @@
// the tagRangeFinder function is
// Copyright (C) 2011 by Daniel Glazman <daniel@glazman.org>
// released under the MIT license (../../LICENSE) like the rest of CodeMirror
CodeMirror.tagRangeFinder = function(cm, line) {
CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
var nameChar = nameStartChar + "\-\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
var xmlNAMERegExp = new RegExp("^[" + nameStartChar + "][" + nameChar + "]*");
@@ -36,8 +36,10 @@ CodeMirror.tagRangeFinder = function(cm, line) {
var slash = lt.lastIndexOf("/", gt);
if (-1 != slash && slash < gt) {
var str = lineText.substr(slash, gt - slash + 1);
if (!str.match( /\/\s*\>/ )) // yep, that's the end of empty tag
return l+1;
if (!str.match( /\/\s*\>/ )) { // yep, that's the end of empty tag
if (hideEnd === true) l++;
return l;
}
}
}
l++;
@@ -95,8 +97,10 @@ CodeMirror.tagRangeFinder = function(cm, line) {
depth--;
else
depth++;
if (!depth)
return l+1;
if (!depth) {
if (hideEnd === true) l++;
return l;
}
}
}
l++;
@@ -105,7 +109,7 @@ CodeMirror.tagRangeFinder = function(cm, line) {
}
};
CodeMirror.braceRangeFinder = function(cm, line) {
CodeMirror.braceRangeFinder = function(cm, line, hideEnd) {
var lineText = cm.getLine(line);
var startChar = lineText.lastIndexOf("{");
if (startChar < 0 || lineText.lastIndexOf("}") > startChar) return;
@@ -127,6 +131,7 @@ CodeMirror.braceRangeFinder = function(cm, line) {
}
}
if (end == null || end == line + 1) return;
if (hideEnd === true) end++;
return end;
};
@@ -144,7 +149,7 @@ CodeMirror.indentRangeFinder = function(cm, line) {
return last + 1;
};
CodeMirror.newFoldFunction = function(rangeFinder, markText) {
CodeMirror.newFoldFunction = function(rangeFinder, markText, hideEnd) {
var folded = [];
if (markText == null) markText = '<div style="position: absolute; left: 2px; color:#600">&#x25bc;</div>%N%';
@@ -169,7 +174,7 @@ CodeMirror.newFoldFunction = function(rangeFinder, markText) {
folded.splice(known.pos, 1);
expand(cm, known.region);
} else {
var end = rangeFinder(cm, line);
var end = rangeFinder(cm, line, hideEnd);
if (end == null) return;
var hidden = [];
for (var i = line + 1; i < end; ++i) {

View File

@@ -0,0 +1,50 @@
(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

@@ -23,7 +23,7 @@
function markDocument(cm, className, minChars) {
clearMarks(cm);
minChars = (typeof minChars !== 'undefined' ? minChars : DEFAULT_MIN_CHARS);
if (cm.somethingSelected() && cm.getSelection().length >= minChars) {
if (cm.somethingSelected() && cm.getSelection().replace(/^\s+|\s+$/g, "").length >= minChars) {
var state = getMatchHighlightState(cm);
var query = cm.getSelection();
cm.operation(function() {

View File

@@ -43,7 +43,7 @@ CodeMirror.overlayParser = function(base, overlay, combine) {
else return state.overlayCur;
},
indent: function(state, textAfter) {
indent: base.indent && function(state, textAfter) {
return base.indent(state.base, textAfter);
},
electricChars: base.electricChars

View File

@@ -72,14 +72,14 @@
query = parseQuery(query);
dialog(cm, replacementQueryDialog, "Replace with:", function(text) {
if (all) {
cm.operation(function() {
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());

View File

@@ -21,7 +21,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
}
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
curPunc = ch;
return null
return null;
}
if (/\d/.test(ch)) {
stream.eatWhile(/[\w\.]/);

View File

@@ -243,7 +243,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function maybeoperator(type, value) {
if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator);
if (type == "operator") return cont(expression);
if (type == "operator" || type == ":") return cont(expression);
if (type == ";") return;
if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
if (type == ".") return cont(property, maybeoperator);
@@ -341,8 +341,9 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
indent: function(state, textAfter) {
if (state.tokenize != jsTokenBase) return 0;
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
type = lexical.type, closing = firstChar == type;
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
var type = lexical.type, closing = firstChar == type;
if (type == "vardef") return lexical.indented + 4;
else if (type == "form" && firstChar == "{") return lexical.indented;
else if (type == "stat" || type == "form") return lexical.indented + indentUnit;

View File

@@ -143,7 +143,7 @@
electricChars: "/{}:"
}
});
}, "xml", "clike", "javascript", "css");
CodeMirror.defineMIME("application/x-httpd-php", "php");
CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true});
CodeMirror.defineMIME("text/x-php", phpConfig);

View File

@@ -0,0 +1,24 @@
Copyright (c) 2011, Ubalo, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the Ubalo, Inc. nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL UBALO, INC BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,171 @@
<!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

@@ -0,0 +1,200 @@
CodeMirror.defineMode("ruby", function(config, parserConfig) {
function wordObj(words) {
var o = {};
for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
return o;
}
var keywords = wordObj([
"alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else",
"elsif", "END", "end", "ensure", "false", "for", "if", "in", "module", "next", "not", "or",
"redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless",
"until", "when", "while", "yield", "nil", "raise", "throw", "catch", "fail", "loop", "callcc",
"caller", "lambda", "proc", "public", "protected", "private", "require", "load",
"require_relative", "extend", "autoload"
]);
var indentWords = wordObj(["def", "class", "case", "for", "while", "do", "module", "then",
"catch", "loop", "proc", "begin"]);
var dedentWords = wordObj(["end", "until"]);
var matching = {"[": "]", "{": "}", "(": ")"};
var curPunc;
function chain(newtok, stream, state) {
state.tokenize.push(newtok);
return newtok(stream, state);
}
function tokenBase(stream, state) {
curPunc = null;
if (stream.sol() && stream.match("=begin") && stream.eol()) {
state.tokenize.push(readBlockComment);
return "comment";
}
if (stream.eatSpace()) return null;
var ch = stream.next();
if (ch == "`" || ch == "'" || ch == '"' ||
(ch == "/" && !stream.eol() && stream.peek() != " ")) {
return chain(readQuoted(ch, "string", ch == '"' || ch == "`"), stream, state);
} else if (ch == "%") {
var style, embed = false;
if (stream.eat("s")) style = "atom";
else if (stream.eat(/[WQ]/)) { style = "string"; embed = true; }
else if (stream.eat(/[wxqr]/)) style = "string";
var delim = stream.eat(/[^\w\s]/);
if (!delim) return "operator";
if (matching.propertyIsEnumerable(delim)) delim = matching[delim];
return chain(readQuoted(delim, style, embed, true), stream, state);
} else if (ch == "#") {
stream.skipToEnd();
return "comment";
} else if (ch == "<" && stream.eat("<")) {
stream.eat("-");
stream.eat(/[\'\"\`]/);
var match = stream.match(/^\w+/);
stream.eat(/[\'\"\`]/);
if (match) return chain(readHereDoc(match[0]), stream, state);
return null;
} else if (ch == "0") {
if (stream.eat("x")) stream.eatWhile(/[\da-fA-F]/);
else if (stream.eat("b")) stream.eatWhile(/[01]/);
else stream.eatWhile(/[0-7]/);
return "number";
} else if (/\d/.test(ch)) {
stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+\-]?[\d_]+)?/);
return "number";
} else if (ch == "?") {
while (stream.match(/^\\[CM]-/)) {}
if (stream.eat("\\")) stream.eatWhile(/\w/);
else stream.next();
return "string";
} else if (ch == ":") {
if (stream.eat("'")) return chain(readQuoted("'", "atom", false), stream, state);
if (stream.eat('"')) return chain(readQuoted('"', "atom", true), stream, state);
stream.eatWhile(/[\w\?]/);
return "atom";
} else if (ch == "@") {
stream.eat("@");
stream.eatWhile(/[\w\?]/);
return "variable-2";
} else if (ch == "$") {
stream.next();
stream.eatWhile(/[\w\?]/);
return "variable-3";
} else if (/\w/.test(ch)) {
stream.eatWhile(/[\w\?]/);
if (stream.eat(":")) return "atom";
return "ident";
} else if (ch == "|" && (state.varList || state.lastTok == "{" || state.lastTok == "do")) {
curPunc = "|";
return null;
} else if (/[\(\)\[\]{}\\;]/.test(ch)) {
curPunc = ch;
return null;
} else if (ch == "-" && stream.eat(">")) {
return "arrow";
} else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) {
stream.eatWhile(/[=+\-\/*:\.^%<>~|]/);
return "operator";
} else {
return null;
}
}
function tokenBaseUntilBrace() {
var depth = 1;
return function(stream, state) {
if (stream.peek() == "}") {
depth--;
if (depth == 0) {
state.tokenize.pop();
return state.tokenize[state.tokenize.length-1](stream, state);
}
} else if (stream.peek() == "{") {
depth++;
}
return tokenBase(stream, state);
};
}
function readQuoted(quote, style, embed, unescaped) {
return function(stream, state) {
var escaped = false, ch;
while ((ch = stream.next()) != null) {
if (ch == quote && (unescaped || !escaped)) {
state.tokenize.pop();
break;
}
if (embed && ch == "#" && !escaped && stream.eat("{")) {
state.tokenize.push(tokenBaseUntilBrace(arguments.callee));
break;
}
escaped = !escaped && ch == "\\";
}
return style;
};
}
function readHereDoc(phrase) {
return function(stream, state) {
if (stream.match(phrase)) state.tokenize.pop();
else stream.skipToEnd();
return "string";
};
}
function readBlockComment(stream, state) {
if (stream.sol() && stream.match("=end") && stream.eol())
state.tokenize.pop();
stream.skipToEnd();
return "comment";
}
return {
startState: function() {
return {tokenize: [tokenBase],
indented: 0,
context: {type: "top", indented: -config.indentUnit},
continuedLine: false,
lastTok: null,
varList: false};
},
token: function(stream, state) {
if (stream.sol()) state.indented = stream.indentation();
var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;
if (style == "ident") {
var word = stream.current();
style = keywords.propertyIsEnumerable(stream.current()) ? "keyword"
: /^[A-Z]/.test(word) ? "tag"
: (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def"
: "variable";
if (indentWords.propertyIsEnumerable(word)) kwtype = "indent";
else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";
else if ((word == "if" || word == "unless") && stream.column() == stream.indentation())
kwtype = "indent";
}
if (curPunc || (style && style != "comment")) state.lastTok = word || curPunc || style;
if (curPunc == "|") state.varList = !state.varList;
if (kwtype == "indent" || /[\(\[\{]/.test(curPunc))
state.context = {prev: state.context, type: curPunc || style, indented: state.indented};
else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev)
state.context = state.context.prev;
if (stream.eol())
state.continuedLine = (curPunc == "\\" || style == "operator");
return style;
},
indent: function(state, textAfter) {
if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0;
var firstChar = textAfter && textAfter.charAt(0);
var ct = state.context;
var closing = ct.type == matching[firstChar] ||
ct.type == "keyword" && /^(?:end|until|else|elsif|when|rescue)\b/.test(textAfter);
return ct.indented + (closing ? 0 : config.indentUnit) +
(state.continuedLine ? config.indentUnit : 0);
},
electricChars: "}de" // enD and rescuE
};
});
CodeMirror.defineMIME("text/x-ruby", "ruby");

View File

@@ -1,12 +1,44 @@
CodeMirror.defineMode("xml", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var Kludges = parserConfig.htmlMode ? {
autoSelfClosers: {"br": true, "img": true, "hr": true, "link": true, "input": true,
"meta": true, "col": true, "frame": true, "base": true, "area": true},
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
'track': true, 'wbr': true},
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
'th': true, 'tr': true},
contextGrabbers: {
'dd': {'dd': true, 'dt': true},
'dt': {'dd': true, 'dt': true},
'li': {'li': true},
'option': {'option': true, 'optgroup': true},
'optgroup': {'optgroup': true},
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
'rp': {'rp': true, 'rt': true},
'rt': {'rp': true, 'rt': true},
'tbody': {'tbody': true, 'tfoot': true},
'td': {'td': true, 'th': true},
'tfoot': {'tbody': true},
'th': {'td': true, 'th': true},
'thead': {'tbody': true, 'tfoot': true},
'tr': {'tr': true}
},
doNotIndent: {"pre": true},
allowUnquoted: true,
allowMissing: false
} : {autoSelfClosers: {}, doNotIndent: {}, allowUnquoted: false, allowMissing: false};
} : {
autoSelfClosers: {},
implicitlyClosed: {},
contextGrabbers: {},
doNotIndent: {},
allowUnquoted: false,
allowMissing: false
};
var alignCDATA = parserConfig.alignCDATA;
// Return variables for tokenizers
@@ -162,7 +194,12 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
} else if (type == "closeTag") {
var err = false;
if (curState.context) {
err = curState.context.tagName != tagName;
if (curState.context.tagName != tagName) {
if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) {
popContext();
}
err = !curState.context || curState.context.tagName != tagName;
}
} else {
err = true;
}
@@ -174,9 +211,15 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
function endtag(startOfLine) {
return function(type) {
if (type == "selfcloseTag" ||
(type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase())))
(type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) {
maybePopContext(curState.tagName.toLowerCase());
return cont();
if (type == "endTag") {pushContext(curState.tagName, startOfLine); return cont();}
}
if (type == "endTag") {
maybePopContext(curState.tagName.toLowerCase());
pushContext(curState.tagName, startOfLine);
return cont();
}
return cont();
};
}
@@ -188,6 +231,20 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
return cont(arguments.callee);
}
}
function maybePopContext(nextTagName) {
var parentTagName;
while (true) {
if (!curState.context) {
return;
}
parentTagName = curState.context.tagName.toLowerCase();
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
return;
}
popContext();
}
}
function attributes(type) {
if (type == "word") {setStyle = "attribute"; return cont(attribute, attributes);}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
/* Port of TextMate's Blackboard theme */
.cm-s-blackboard { background: #0C1021; color: #F8F8F8; }
.cm-s-blackboard .CodeMirror-selected { background: #253B76 !important; }
.cm-s-blackboard .CodeMirror-gutter { background: #0C1021; border-right: 0; }
.cm-s-blackboard .CodeMirror-gutter-text { color: #888; }
.cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7 !important; }
.cm-s-blackboard .cm-keyword { color: #FBDE2D; }
.cm-s-blackboard .cm-atom { color: #D8FA3C; }
.cm-s-blackboard .cm-number { color: #D8FA3C; }
.cm-s-blackboard .cm-def { color: #8DA6CE; }
.cm-s-blackboard .cm-variable { color: #FF6400; }
.cm-s-blackboard .cm-operator { color: #FBDE2D;}
.cm-s-blackboard .cm-comment { color: #AEAEAE; }
.cm-s-blackboard .cm-string { color: #61CE3C; }
.cm-s-blackboard .cm-string-2 { color: #61CE3C; }
.cm-s-blackboard .cm-meta { color: #D8FA3C; }
.cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; }
.cm-s-blackboard .cm-builtin { color: #8DA6CE; }
.cm-s-blackboard .cm-tag { color: #8DA6CE; }
.cm-s-blackboard .cm-attribute { color: #8DA6CE; }
.cm-s-blackboard .cm-header { color: #FF6400; }
.cm-s-blackboard .cm-hr { color: #AEAEAE; }
.cm-s-blackboard .cm-link { color: #8DA6CE; }

View File

@@ -0,0 +1,18 @@
.cm-s-cobalt { background: #002240; color: white; }
.cm-s-cobalt div.CodeMirror-selected { background: #b36539 !important; }
.cm-s-cobalt .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; }
.cm-s-cobalt .CodeMirror-gutter-text { color: #d0d0d0; }
.cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-cobalt span.cm-comment { color: #08f; }
.cm-s-cobalt span.cm-atom { color: #845dc4; }
.cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; }
.cm-s-cobalt span.cm-keyword { color: #ffee80; }
.cm-s-cobalt span.cm-string { color: #3ad900; }
.cm-s-cobalt span.cm-meta { color: #ff9d00; }
.cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; }
.cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; }
.cm-s-cobalt span.cm-error { color: #9d1e15; }
.cm-s-cobalt span.cm-bracket { color: #d8d8d8; }
.cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }
.cm-s-cobalt span.cm-link { color: #845dc4; }

View File

@@ -0,0 +1,25 @@
.cm-s-eclipse span.cm-meta {color: #FF1717;}
.cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; }
.cm-s-eclipse span.cm-atom {color: #219;}
.cm-s-eclipse span.cm-number {color: #164;}
.cm-s-eclipse span.cm-def {color: #00f;}
.cm-s-eclipse span.cm-variable {color: black;}
.cm-s-eclipse span.cm-variable-2 {color: #0000C0;}
.cm-s-eclipse span.cm-variable-3 {color: #0000C0;}
.cm-s-eclipse span.cm-property {color: black;}
.cm-s-eclipse span.cm-operator {color: black;}
.cm-s-eclipse span.cm-comment {color: #3F7F5F;}
.cm-s-eclipse span.cm-string {color: #2A00FF;}
.cm-s-eclipse span.cm-string-2 {color: #f50;}
.cm-s-eclipse span.cm-error {color: #f00;}
.cm-s-eclipse span.cm-qualifier {color: #555;}
.cm-s-eclipse span.cm-builtin {color: #30a;}
.cm-s-eclipse span.cm-bracket {color: #cc7;}
.cm-s-eclipse span.cm-tag {color: #170;}
.cm-s-eclipse span.cm-attribute {color: #00c;}
.cm-s-eclipse span.cm-link {color: #219;}
.cm-s-eclipse .CodeMirror-matchingbracket {
border:1px solid grey;
color:black !important;;
}

View File

@@ -0,0 +1,10 @@
.cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom {color: #762;}
.cm-s-elegant span.cm-comment {color: #262; font-style: italic; line-height: 1em;}
.cm-s-elegant span.cm-meta {color: #555; font-style: italic; line-height: 1em;}
.cm-s-elegant span.cm-variable {color: black;}
.cm-s-elegant span.cm-variable-2 {color: #b11;}
.cm-s-elegant span.cm-qualifier {color: #555;}
.cm-s-elegant span.cm-keyword {color: #730;}
.cm-s-elegant span.cm-builtin {color: #30a;}
.cm-s-elegant span.cm-error {background-color: #fdd;}
.cm-s-elegant span.cm-link {color: #762;}

View File

@@ -0,0 +1,45 @@
/*
http://lesscss.org/ dark theme
Ported to CodeMirror by Peter Kroon
*/
.CodeMirror{
line-height: 15px;
}
.cm-s-lesser-dark {
font-family: 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Monaco', Courier, monospace !important;
font-size:12px;
}
.cm-s-lesser-dark { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; }
.cm-s-lesser-dark div.CodeMirror-selected {background: #45443B !important;} /* 33322B*/
.cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-lesser-dark .CodeMirror-lines { margin-left:3px; margin-right:3px; }/*editable code holder*/
div.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/
.cm-s-lesser-dark .CodeMirror-gutter { background: #262626; border-right:1px solid #aaa; padding-right:3px; min-width:2.5em; }
.cm-s-lesser-dark .CodeMirror-gutter-text { color: #777; }
.cm-s-lesser-dark span.cm-keyword { color: #599eff; }
.cm-s-lesser-dark span.cm-atom { color: #C2B470; }
.cm-s-lesser-dark span.cm-number { color: #B35E4D; }
.cm-s-lesser-dark span.cm-def {color: white;}
.cm-s-lesser-dark span.cm-variable { color:#D9BF8C; }
.cm-s-lesser-dark span.cm-variable-2 { color: #669199; }
.cm-s-lesser-dark span.cm-variable-3 { color: white; }
.cm-s-lesser-dark span.cm-property {color: #92A75C;}
.cm-s-lesser-dark span.cm-operator {color: #92A75C;}
.cm-s-lesser-dark span.cm-comment { color: #666; }
.cm-s-lesser-dark span.cm-string { color: #BCD279; }
.cm-s-lesser-dark span.cm-string-2 {color: #f50;}
.cm-s-lesser-dark span.cm-meta { color: #738C73; }
.cm-s-lesser-dark span.cm-error { color: #9d1e15; }
.cm-s-lesser-dark span.cm-qualifier {color: #555;}
.cm-s-lesser-dark span.cm-builtin { color: #ff9e59; }
.cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; }
.cm-s-lesser-dark span.cm-tag { color: #669199; }
.cm-s-lesser-dark span.cm-attribute {color: #00c;}
.cm-s-lesser-dark span.cm-header {color: #a0a;}
.cm-s-lesser-dark span.cm-quote {color: #090;}
.cm-s-lesser-dark span.cm-hr {color: #999;}
.cm-s-lesser-dark span.cm-link {color: #00c;}

View File

@@ -0,0 +1,28 @@
/* Based on Sublime Text's Monokai theme */
.cm-s-monokai {background: #272822; color: #f8f8f2;}
.cm-s-monokai div.CodeMirror-selected {background: #49483E !important;}
.cm-s-monokai .CodeMirror-gutter {background: #272822; border-right: 0px;}
.cm-s-monokai .CodeMirror-gutter-text {color: #d0d0d0;}
.cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}
.cm-s-monokai span.cm-comment {color: #75715e;}
.cm-s-monokai span.cm-atom {color: #ae81ff;}
.cm-s-monokai span.cm-number {color: #ae81ff;}
.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;}
.cm-s-monokai span.cm-keyword {color: #f92672;}
.cm-s-monokai span.cm-string {color: #e6db74;}
.cm-s-monokai span.cm-variable {color: #a6e22e;}
.cm-s-monokai span.cm-variable-2 {color: #9effff;}
.cm-s-monokai span.cm-def {color: #fd971f;}
.cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;}
.cm-s-monokai span.cm-bracket {color: #f8f8f2;}
.cm-s-monokai span.cm-tag {color: #f92672;}
.cm-s-monokai span.cm-link {color: #ae81ff;}
.cm-s-monokai .CodeMirror-matchingbracket {
text-decoration: underline;
color: white !important;
}

View File

@@ -0,0 +1,9 @@
.cm-s-neat span.cm-comment { color: #a86; }
.cm-s-neat span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; }
.cm-s-neat span.cm-string { color: #a22; }
.cm-s-neat span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; }
.cm-s-neat span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; }
.cm-s-neat span.cm-variable { color: black; }
.cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; }
.cm-s-neat span.cm-meta {color: #555;}
.cm-s-neat span.cm-link { color: #3a3; }

View File

@@ -0,0 +1,21 @@
/* Loosely based on the Midnight Textmate theme */
.cm-s-night { background: #0a001f; color: #f8f8f8; }
.cm-s-night div.CodeMirror-selected { background: #a8f !important; }
.cm-s-night .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }
.cm-s-night .CodeMirror-gutter-text { color: #f8f8f8; }
.cm-s-night .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-night span.cm-comment { color: #6900a1; }
.cm-s-night span.cm-atom { color: #845dc4; }
.cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; }
.cm-s-night span.cm-keyword { color: #599eff; }
.cm-s-night span.cm-string { color: #37f14a; }
.cm-s-night span.cm-meta { color: #7678e2; }
.cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; }
.cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; }
.cm-s-night span.cm-error { color: #9d1e15; }
.cm-s-night span.cm-bracket { color: #8da6ce; }
.cm-s-night span.cm-comment { color: #6900a1; }
.cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; }
.cm-s-night span.cm-link { color: #845dc4; }

View File

@@ -0,0 +1,21 @@
.cm-s-rubyblue { font:13px/1.4em Trebuchet, Verdana, sans-serif; } /* - customized editor font - */
.cm-s-rubyblue { background: #112435; color: white; }
.cm-s-rubyblue div.CodeMirror-selected { background: #38566F !important; }
.cm-s-rubyblue .CodeMirror-gutter { background: #1F4661; border-right: 7px solid #3E7087; min-width:2.5em; }
.cm-s-rubyblue .CodeMirror-gutter-text { color: white; }
.cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; line-height: 1em; }
.cm-s-rubyblue span.cm-atom { color: #F4C20B; }
.cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; }
.cm-s-rubyblue span.cm-keyword { color: #F0F; }
.cm-s-rubyblue span.cm-string { color: #F08047; }
.cm-s-rubyblue span.cm-meta { color: #F0F; }
.cm-s-rubyblue span.cm-variable-2, .cm-s-rubyblue span.cm-tag { color: #7BD827; }
.cm-s-rubyblue span.cm-variable-3, .cm-s-rubyblue span.cm-def { color: white; }
.cm-s-rubyblue span.cm-error { color: #AF2018; }
.cm-s-rubyblue span.cm-bracket { color: #F0F; }
.cm-s-rubyblue span.cm-link { color: #F4C20B; }
.cm-s-rubyblue span.CodeMirror-matchingbracket { color:#F0F !important; }
.cm-s-rubyblue span.cm-builtin, .cm-s-rubyblue span.cm-special { color: #FF9D00; }

View File

@@ -0,0 +1,46 @@
/*
Copyright (C) 2011 by MarkLogic Corporation
Author: Mike Brevoort <mike@brevoort.com>
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.
*/
.cm-s-xq-dark { background: #0a001f; color: #f8f8f8; }
.cm-s-xq-dark span.CodeMirror-selected { background: #a8f !important; }
.cm-s-xq-dark .CodeMirror-gutter { background: #0a001f; border-right: 1px solid #aaa; }
.cm-s-xq-dark .CodeMirror-gutter-text { color: #f8f8f8; }
.cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-xq-dark span.cm-keyword {color: #FFBD40;}
.cm-s-xq-dark span.cm-atom {color: #6C8CD5;}
.cm-s-xq-dark span.cm-number {color: #164;}
.cm-s-xq-dark span.cm-def {color: #FFF; text-decoration:underline;}
.cm-s-xq-dark span.cm-variable {color: #FFF;}
.cm-s-xq-dark span.cm-variable-2 {color: #EEE;}
.cm-s-xq-dark span.cm-variable-3 {color: #DDD;}
.cm-s-xq-dark span.cm-property {}
.cm-s-xq-dark span.cm-operator {}
.cm-s-xq-dark span.cm-comment {color: gray;}
.cm-s-xq-dark span.cm-string {color: #9FEE00;}
.cm-s-xq-dark span.cm-meta {color: yellow;}
.cm-s-xq-dark span.cm-error {color: #f00;}
.cm-s-xq-dark span.cm-qualifier {color: #FFF700;}
.cm-s-xq-dark span.cm-builtin {color: #30a;}
.cm-s-xq-dark span.cm-bracket {color: #cc7;}
.cm-s-xq-dark span.cm-tag {color: #FFBD40;}
.cm-s-xq-dark span.cm-attribute {color: #FFF700;}

View File

@@ -1,27 +1,66 @@
ICE coder :: Matt Pass
#ICEcoder
##Web based IDE for smart web development
Demo: http://www.mattpass.com/_coder
Early version of the web based IDE which allows for creation of websites in the web browser. Uses the brilliant CodeMirror for code highlighting & editing, with a slick IDE wrapped around it to make the whole thing work.
Early version of the web based IDE which allows for creation of websites in the web browser.
###Features you'd expect
* Context aware code highlighting
* Supports HTML, CSS, JavaScript, PHP & Ruby
* Smart tab key system (selected text indents line)
* File manager
* Find & replace/replace all
* Document tabs indicate current doc & changes made
* Code folding
* Open last files on load
* Web based, access from anywhere
* Free, open source & customisable
Uses the brilliant CodeMirror plus some other PHP & JS code to deal with file handling and make the whole thing work. Also has the extra plugin 'Adminer' for DB management.
###Cool features you wouldn't expect
* Find & replace in current doc, open docs, files & filenames
* Found match & current position counter
* Indicates content type cursor is on
* Account login to keep certain files secure
* Restrict files, ban files and restrict by IP
* Settings to change functionality & editor theme
* Code Assist system
* Displays nest position of text cursor, hover to select, click to set cursor
* Nest structure OK/broken indicator
* Highlight word and press CTRL+I to Google search that
* Adds end tags as you type and in a context aware way
* Can rename open files (whoaah!)
* CTRL+Enter open current webpage in new tab
* CTRL+S+Enter opens a sticky tab to show live edits
* ESC = Comment/Uncomment line, incl partial lines
* Image viewer
* Colour preview block on CSS colours, ie red, #ff0000 or RGBA(255,0,0,0.5)
* MySQL Database management via Adminer plugin
* Backs up files every 10 mins or on click of backup plugin icon
###Installation
####Step 1: Clone the repo
```
$ git clone git@github:mattpass/ICEcoder
```
####Step 2: Upload all the files
```
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
```
####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
```
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.
Is fully open source and I'd encourage you to take it, make it your own and customise to your hearts content! :)
Suitable for commercial & non-commercial projects, just let me know if it's useful to you and any cool customisations you make to it.
Please feel free to assist with the development of this and maybe in time we can produce a fantastic web based IDE for web devs.
INSTALLATION
1.Open /lib/settings.php and adjust variables to suit
2.Upload all the files to a Linux or Windows host under a new sub-dir URL such as yourdomain.com/_coder. Set public write permissions on the settings.php file
3.Visit this URL in your browser and set a password
4.Now you have top level access and can save (CTRL+S), delete (DEL) etc
Plenty of comments included in the code to assist with understanding.
Plenty of comments included in the code to assist with understanding, customising etc.
Comments, improvements & feedback welcomed!

View File

@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html>
<html style="margin: 0px">
<head>
<title>CodeMirror 2: ICE Coders Editor of Choice</title>
<?php include("lib/settings.php");?>
@@ -11,30 +11,40 @@
<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/php/php.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/ruby/ruby.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/lib/util/searchcursor.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/lib/util/match-highlighter.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/lib/util/foldcode.js"></script>
<link rel="stylesheet" href="lib/editor.css">
<?php
if ($theme=="default") {
echo '<link rel="stylesheet" href="lib/editor.css">';
} else {
echo '<link rel="stylesheet" href="'.$codeMirrorDir.'/theme/'.$theme.'.css">';
}
?>
<style type="text/css">
.CodeMirror {position: absolute; width: 0px; background-color: #ffffff}
.CodeMirror-scroll {width: 100px; height: 100px;}
.cm-s-visible {display: block; top: 0px}
.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) {?>\21e5<?;};?>";}
span.CodeMirror-matchhighlight {background: #555555}
.CodeMirror-focused span.CodeMirror-matchhighlight {color: #000000; background: #555555; !important}
</style>
</head>
<body onKeyDown="return top.ICEcoder.interceptKeys('content', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<body style="margin: 0px" onKeyDown="return top.ICEcoder.interceptKeys('content', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<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 = 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: #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%');
window['cM'+num] = CodeMirror(document.body, {
mode: "application/x-httpd-php",
theme: "icecoder",
lineNumbers: true,
lineWrapping: true,
indentUnit: 4,
@@ -69,7 +79,7 @@ function createNewCMInstance(num) {
},
onKeyEvent: function(instance, e) {
top.ICEcoder.redoChangedContent(event);
top.ICEcoder.findReplace('find',true);
top.ICEcoder.findReplace('find',true,false);
top.ICEcoder.getCaretPosition();
top.ICEcoder.updateCharDisplay();
tok = window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].getTokenAt(window['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].getCursor());
@@ -112,8 +122,11 @@ function createNewCMInstance(num) {
};
lastKeyCode = e.keyCode;
},
onGutterClick: !fileName || (fileName && fileName.indexOf(".js") == -1 && fileName.indexOf(".php") == -1) ? codeFold : codeFold_JS_PHP,
extraKeys: {"Tab": "indentMore", "Shift-Tab": "indentLess"}
onGutterClick: !fileName || (fileName && fileName.indexOf(".js") == -1 && fileName.indexOf(".php") && fileName.indexOf(".rb") == -1) ? codeFold : codeFold_JS_PHP_Ruby,
extraKeys: {
"Tab": function(cm) {CodeMirror.commands[top.tabsIndent ? "defaultTab" : "insertTab"](cm);},
"Shift-Tab": "indentLess"
}
});
// Now create the active line for this CodeMirror object

View File

@@ -142,7 +142,7 @@ function php4_scandir($dir) {
?>
<!DOCTYPE html>
<html onMouseDown="top.ICEcoder.mouseDown=true" onMouseUp="top.ICEcoder.mouseDown=false" onMouseMove="top.ICEcoder.getMouseXY(event);top.ICEcoder.canResizeFilesW()" onContextMenu="top.ICEcoder.rightClickedFile=top.ICEcoder.thisFileFolderLink; top.ICEcoder.selectFileFolder(); return top.ICEcoder.showMenu()" onClick="top.ICEcoder.selectFileFolder()">
<html onMouseDown="top.ICEcoder.mouseDown=true" onMouseUp="top.ICEcoder.mouseDown=false" onMouseMove="top.ICEcoder.getMouseXY(event);top.ICEcoder.canResizeFilesW()" onContextMenu="top.ICEcoder.rightClickedFile=top.ICEcoder.thisFileFolderLink; return top.ICEcoder.showMenu()" onClick="top.ICEcoder.selectFileFolder()">
<head>
<title>ICE Coder File Manager</title>
<link rel="stylesheet" type="text/css" href="lib/files.css">
@@ -150,6 +150,7 @@ function php4_scandir($dir) {
</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>
<?php
echo fileManager($_SERVER['DOCUMENT_ROOT'], "[link]");
?>

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 603 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 618 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 537 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 651 B

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 734 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 447 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 538 B

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 626 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 B

After

Width:  |  Height:  |  Size: 56 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 377 B

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,8 +1,8 @@
<?php
include("lib/settings.php");
$allowedIP = false;
for($i=0;$i<count($allowedIPs);$i++) {
if ($allowedIPs[$i]==$_SERVER["REMOTE_ADDR"]||$allowedIPs[$i]=="*") {
for($i=0;$i<count($_SESSION['allowedIPs']);$i++) {
if ($_SESSION['allowedIPs'][$i]==$_SERVER["REMOTE_ADDR"]||$_SESSION['allowedIPs'][$i]=="*") {
$allowedIP = true;
}
}
@@ -27,22 +27,35 @@ if ($testcMVersion) {
<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';};?>;
<?
$docRoot = str_replace("\\","/",$_SERVER['DOCUMENT_ROOT']);
if (strrpos($docRoot,"/")==strlen($docRoot)-1) {$docRoot = substr($docRoot,0,strlen($docRoot)-1);};
echo 'fullPath = "'.$docRoot.'";'.PHP_EOL;
?>
window.onbeforeunload = function() {
for (var i=0; i<=top.ICEcoder.changedContent.length; i++) {
if (top.ICEcoder.changedContent[i]==1) {
return "You have some unsaved changes.";
}
}
}
lastOpenFiles = [<?php
if ($lastOpenedFiles!="" && $_SESSION['userLevel'] == 10) {
$openFilesArray = explode(",",$lastOpenedFiles);
for ($i=0;$i<count($openFilesArray);$i++) {
echo "'".$openFilesArray[$i]."'";
if ($i<count($openFilesArray)-1) {echo ",";};
}
}
?>];
</script>
<script language="JavaScript" src="lib/coder.js"></script>
</head><?php
$onLoadExtras = "";
for ($i=0;$i<count($plugins);$i++) {
if ($plugins[$i][5]!="") {
$onLoadExtras .= ";ICEcoder.startPluginIntervals('".$plugins[$i][3]."','".$plugins[$i][4]."','".$plugins[$i][5]."')";
};
};
?>
<body onLoad="ICEcoder.init()<?php echo $onLoadExtras;?>" onResize="ICEcoder.setLayout()" onMouseMove="top.ICEcoder.getMouseXY(event);top.ICEcoder.canResizeFilesW()" onMouseDown="top.ICEcoder.mouseDown=true" onMouseUp="top.ICEcoder.mouseDown=false" onKeyDown="return ICEcoder.interceptKeys('coder', event);" onKeyUp="parent.ICEcoder.resetKeys(event);">
</head>
<body onLoad="ICEcoder.init(<?php if ($_SESSION['userLevel'] == 10) {echo "'login'";} ?>)<?php echo $onLoadExtras;?>" onResize="ICEcoder.setLayout()" onMouseMove="top.ICEcoder.getMouseXY(event);top.ICEcoder.canResizeFilesW()" onMouseDown="top.ICEcoder.mouseDown=true" onMouseUp="top.ICEcoder.mouseDown=false" onKeyDown="return ICEcoder.interceptKeys('coder', event);" onKeyUp="parent.ICEcoder.resetKeys(event);">
<div id="blackMask" class="blackMask" onClick="ICEcoder.showHide('hide',this)">
<div class="popupVCenter">
@@ -57,45 +70,42 @@ echo 'fullPath = "'.$docRoot.'";'.PHP_EOL;
<div class="popup">
<div class="circleOutside"></div>
<div class="circleInside"></div>
&nbsp;&nbsp;&nbsp;loading...
&nbsp;&nbsp;&nbsp;working...
</div>
</div>
</div>
<div id="fileMenu" class="fileMenu" onMouseOut="this.style.display='none'" onMouseOver="ICEcoder.changeFilesW('expand')" onMouseOut="ICEcoder.changeFilesW('contract')">
<div id="fileMenu" class="fileMenu" onMouseOver="ICEcoder.changeFilesW('expand')" onMouseOut="ICEcoder.changeFilesW('contract')">
<span id="folderMenuItems">
<a href="javascript:top.ICEcoder.newFile()" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">New File</a>
<a href="javascript:top.ICEcoder.newFolder()" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">New Folder</a>
</span>
<a href="javascript:top.ICEcoder.deleteFile(top.ICEcoder.rightClickedFile)" onMouseOver="document.getElementById('fileMenu').style.display='inline-block'">Delete</a>
<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 id="singleFileMenuItems">
<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>
</div>
<div id="header" class="header" onContextMenu="return false">
<div class="plugins">
<?php
for ($i=0;$i<count($plugins);$i++) {
$target = explode(":",$plugins[$i][4]);
echo '<a href="'.$plugins[$i][3].'" target="'.$target[0].'"><img src="'.$plugins[$i][1].'" style="'.$plugins[$i][2].'" alt="'.$plugins[$i][0].'"></a>';
};
?>
<div class="plugins" id="pluginsContainer">
<?php echo $pluginsDisplay; ?>
</div>
<div class="version"><?php echo $versionNo;?></div>
<img src="images/ice-coder.gif" class="logo">
<img src="images/ice-coder.gif" 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';">
<div class="account" id="account">
<?php if($_SESSION['userLevel']<10) {?>
<form name="login" action="index.php" method="POST">
<input type="password" name="loginPassword" class="accountPassword">
<input type="submit" name="submit" value="Login" class="button">
</form>
<?php } else {
$lockStyleExtra = ' style="margin-top: -22px"';
?>
<div class="accountOptions">
<div class="accountLoginContainer" id="accountLoginContainer">
<div class="accountLogin" id="accountLogin">
<form name="login" action="lib/settings.php" method="POST" target="ff">
<input type="password" name="loginPassword" class="accountPassword">
<input type="submit" name="submit" value="Login" class="button">
</form>
</div>
</div>
<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>
@@ -103,9 +113,8 @@ echo 'fullPath = "'.$docRoot.'";'.PHP_EOL;
<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>
</div>
<?php ;};?>
<a nohref style="cursor: pointer" onClick="ICEcoder.lockUnlockNav()"><img src="images/file-manager-icons/padlock.png" id="fmLock" class="lock"<?php echo $lockStyleExtra; ?>></a>
</div>
<a nohref style="cursor: pointer" onClick="ICEcoder.lockUnlockNav()"><img src="images/file-manager-icons/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>
@@ -123,27 +132,33 @@ echo 'fullPath = "'.$docRoot.'";'.PHP_EOL;
<form name="findAndReplace">
<div class="findReplace">
<div class="findText">Find</div>
<input type="text" name="find" value="" id="find" class="textbox find" onKeyUp="ICEcoder.findReplace('find',true)">
<input type="text" name="find" value="" id="find" class="textbox find" onKeyUp="ICEcoder.findReplace('find',true,false)">
<div class="findTextPlural">'s</div>
<select name="connector" onChange="ICEcoder.findReplaceOptions()">
<option>in</option>
<option>and</option>
</select>
<div class="replaceText" id="rText" style="display: none">replace with</div>
<div class="replaceText" id="rText" style="display: none">
<select name="replaceAction" class="replaceAction">
<option>replace</option>
<option>replace all</option>
</select>
with
</div>
<input type="text" name="replace" value="" id="replace" class="textbox replace" style="display: none">
<div class="targetText" id="rTarget" style="display: none">in</div>
<select name="target">
<select name="target" onChange="ICEcoder.updateResultsDisplay(this.value=='this document' ? 'show' : 'hide')">
<option>this document</option>
<option>open documents</option>
<option>all files</option>
<option>all filenames</option>
</select>
<input type="button" name="submit" value="&gt;&gt;" class="submit" onClick="ICEcoder.findReplace('findReplace',false)">
<input type="button" name="submit" value="&gt;&gt;" class="submit" onClick="ICEcoder.findReplace('findReplace',false,true)">
<div class="results" id="results"></div>
</div>
</form>
<form onSubmit="return ICEcoder.goToLine()">
<div class="codeAssist"><input type="checkbox" name="codeAssist" checked onClick="top.ICEcoder.codeAssistToggle()">Code Assist</div>
<div class="codeAssist"><input type="checkbox" name="codeAssist" id="codeAssist" checked onClick="top.ICEcoder.codeAssistToggle()">Code Assist</div>
<div class="goLine">Go to Line<input type="text" name="goToLine" value="" id="goToLineNo" class="textbox goToLine">
</form>
</div>

View File

@@ -18,15 +18,24 @@ table, caption, tbody, tfoot, thead, tr, th, td {
}
body {overflow: hidden;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select:none;
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select:none;
user-select: none;
background-color: #222222;
}
h1 {font-size: 36px; font-weight: normal; color: #888888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #ffffff}
.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 .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}
.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);
}
.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;
width:50px; height:50px; margin:0 auto; -moz-animation:spin .5s infinite linear; -webkit-animation:spin .5s infinite linear;
@@ -67,22 +76,35 @@ body {overflow: hidden;
.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}
.header .logo {position: relative; margin: 5px 10px 0px 5px; cursor: pointer}
.files {position: absolute; display: inline-block; height: 100%; width: 250px; background-color: #e0e0e0; background-image: url('../images/files-arrow.gif'); background-repeat: no-repeat; background-position: 100% 50%; overflow: hidden; z-index: 1;
.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 .account {display: inline-block; height: 50px; width: 250px; margin-top: 40px; background-color: #888888}
.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;
-webkit-transition: top 0.3s;
-moz-transition: top 0.3s;
-o-transition: top 0.3s;
transition: top 0.3s;
}
.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 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);
}
.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 .lock {margin-left: 225px; margin-top: -20px}
.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: 180px; 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: 0px; 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;
@@ -90,22 +112,23 @@ body {overflow: hidden;
}
.files .serverMessage b {font-size: 10px}
.editor {position: absolute; display: inline-block; top: 0px; left: 15px; width: 2400px; background-color: #fbfbfb;}
.editor .tabsBar {display: inline-block; height: 21px; width: 2400px; margin-top: 40px; padding-left: 41px; border-bottom: solid 1px #888888; background-color: #eeeeee;}
.tabsBar .tab {display: inline-block; display: none; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0px 0px; padding: 4px 8px 2px 8px; font-size: 10px; border-left: solid 1px #ffffff; border-right: solid 1px #bbbbbb; color: #ffffff; cursor: pointer;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
.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;
-webkit-transition: all 0.15s;
-moz-transition: all 0.15s;
-o-transition: all 0.15s;
transition: all 0.15s;
}
.tabsBar .tab img {margin: 1px 0px 0px 5px}
.tabsBar .newTab {display: inline-block; background-image: url('../images/nav-bg.gif'); background-repeat: repeat-x; background-position: 0px 0px; padding: 5px 5px 1px 5px; border-left: solid 1px #ffffff; border-right: solid 1px #bbbbbb; cursor: pointer;}
.editor .findBar {display: inline-block; height: 28px; width: 2400px; background-color: #eeeeee}
.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}
.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 .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 .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}
@@ -138,4 +161,4 @@ body {overflow: hidden;
.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}
.screenCenter .button {border: 0px; background: #666666; color: #ffffff; height: 22px; cursor: pointer}

View File

@@ -16,6 +16,7 @@ var ICEcoder = {
delKeyDown: false, // Indicates if DEL keydown
canSwitchTabs: true, // Stops switching of tabs when trying to close
openFiles: [], // Array of open file URLs
openFileMDTs: [], // Array of open file modification datetimes
cMInstances: [], // List of CodeMirror instance no's
nextcMInstance: 1, // Next available CodeMirror instance no
selectedFiles: [], // Array of selected files
@@ -25,13 +26,16 @@ var ICEcoder = {
mouseDown: false, // If the mouse is down or not
draggingFilesW: false, // If we're dragging the file manager width or not
serverQueueItems: [], // Array of URLs to call in order
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
// Don't consider these tags as part of nesting as they're singles, JS or PHP code blocks
tagNestExceptions: ["!DOCTYPE","meta","link","img","br","hr","input","script","?php","?"],
// 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() {
var aliasArray = ["header","files","account","fmLock","filesFrame","editor","tabsBar","findBar","content","footer","nestValid","nestDisplay","charDisplay"];
init: function(login) {
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++) {
@@ -43,6 +47,12 @@ var ICEcoder = {
// Hide the loading screen
top.document.getElementById('loadingMask').style.visibility = "hidden";
// If we're logging in, slide the login area to reveal the icons
if (login) {
top.document.getElementById('accountLogin').style.top = "-50px";
setTimeout(function() {top.document.getElementById('accountLoginContainer').style.display = "none";},300);
}
},
// Set our layout according to the browser size
@@ -56,7 +66,7 @@ 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 = editor.style.left = this.filesW + "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";
@@ -79,12 +89,11 @@ var ICEcoder = {
contentCleanUp: function() {
var fileName, cM, content;
// If it's not a JS or CSS file, replace & and our temp </textarea> value
// If it's not a JS, Ruby or CSS file, replace & and our temp </textarea> value
fileName = ICEcoder.openFiles[ICEcoder.selectedTab-1];
if (fileName.indexOf(".js")<0&&fileName.indexOf(".css")<0) {
if (fileName.indexOf(".js")<0&&fileName.indexOf(".rb")&&fileName.indexOf(".css")<0) {
cM = ICEcoder.getcMInstance();
content = cM.getValue();
if (top.ICEcoder.codeAssist) {content = content.replace(/ & /g,' &amp; ');};
content = content.replace(/<ICEcoder:\/:textarea>/g,'</textarea>');
// Then set the content in the editor & clear the history
@@ -113,7 +122,7 @@ var ICEcoder = {
// Get the tag name and if it's the start of a code block, set the var for that
tagStart=nestCheck.substr(startPos,nestCheck.length).split(" ")[0].split(">")[0].split("\n")[0];
if (tagStart=="script"||tagStart=="?php"||tagStart=="?") {ICEcoder.codeBlock=true}
if (tagStart=="script"||tagStart=="?php"||tagStart=="?"||tagStart=="%") {ICEcoder.codeBlock=true}
if (tagStart!="") {ICEcoder.tagStart = tagStart}
};
@@ -156,7 +165,8 @@ var ICEcoder = {
}
} else if (
((ICEcoder.tagStart=="script"||ICEcoder.tagStart=="/script")&&tagEndJS=="</script")||
((ICEcoder.tagStart=="?php"||ICEcoder.tagStart=="?")&&tagEnd=="?")) {
((ICEcoder.tagStart=="?php"||ICEcoder.tagStart=="?")&&tagEnd=="?")||
(ICEcoder.tagStart=="%"&&tagEnd=="%")) {
ICEcoder.codeBlock=false;
}
}
@@ -168,12 +178,13 @@ var ICEcoder = {
// Now we've built up our nest depth array, if we're due to show it in the display
if (updateNestDisplay && !top.ICEcoder.dontUpdateNest) {
// Clear the display
ICEcoder.nestDisplay.innerHTML = "";
if ("undefined" != typeof ICEcoder.openFiles[ICEcoder.selectedTab-1]) {
fileName = ICEcoder.openFiles[ICEcoder.selectedTab-1];
if (fileName.indexOf(".js")<0&&fileName.indexOf(".css")<0) {
if (fileName.indexOf(".js")<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)) {
// Then for all the array items, output as the nest display
for (var i=0;i<ICEcoder.htmlTagArray.length;i++) {
@@ -237,12 +248,17 @@ var ICEcoder = {
} else {
top.ICEcoder.saveFile();
}
top.ICEcoder.ctrlKeyDown = false;
top.ICEcoder.stickyTabMaybe = true;
return false;
// CTRL+Enter (Open Webpage)
} else if(key==13 && top.ICEcoder.ctrlKeyDown==true && top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1] != "/[NEW]") {
window.open(top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1]);
if (top.ICEcoder.stickyTabMaybe) {
top.ICEcoder.stickyTabWindow = window.open(top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1],"stickyTab");
top.ICEcoder.stickyTab = true;
} else {
window.open(top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1]);
}
top.ICEcoder.ctrlKeyDown = false;
return false;
@@ -268,7 +284,7 @@ var ICEcoder = {
key = evt.keyCode ? evt.keyCode : evt.which ? evt.which : evt.charCode;
if (key==17) {top.ICEcoder.ctrlKeyDown = false;}
if (key==17) {top.ICEcoder.ctrlKeyDown = false; top.ICEcoder.stickyTabMaybe = false;}
if (key==16) {top.ICEcoder.shiftKeyDown = false;}
if (key==46) {top.ICEcoder.delKeyDown = false;}
},
@@ -276,7 +292,7 @@ var ICEcoder = {
// Set the width of the file manager on demand
changeFilesW: function(expandContract) {
if (!ICEcoder.lockedNav) {
if (!ICEcoder.lockedNav||(ICEcoder.lockedNav && ICEcoder.filesW==ICEcoder.minFilesW)) {
if ("undefined" != typeof ICEcoder.changeFilesInt) {clearInterval(ICEcoder.changeFilesInt)};
ICEcoder.changeFilesInt = setInterval(function() {ICEcoder.changeFilesWStep(expandContract)},10);
}
@@ -327,30 +343,40 @@ var ICEcoder = {
ICEcoder.selectedTab = newTab;
cM = ICEcoder.getcMInstance();
// Switch mode to HTML, PHP, CSS etc
ICEcoder.switchMode();
if (cM) {
// Switch mode to HTML, PHP, CSS etc
ICEcoder.switchMode();
// Set all cM instances to be hidden, then make our selected instance visable
for (var i=0;i<ICEcoder.cMInstances.length;i++) {
ICEcoder.content.contentWindow['cM'+ICEcoder.cMInstances[i]].setOption('theme','icecoder hidden');
// Set all cM instances to be hidden, then make our selected instance visable
for (var i=0;i<ICEcoder.cMInstances.length;i++) {
ICEcoder.content.contentWindow['cM'+ICEcoder.cMInstances[i]].setOption('theme',top.theme+' hidden');
}
cM.setOption('theme',top.theme+' visible');
// Focus on & refresh our selected instance
cM.focus();
cM.refresh();
// Highlight the selected tab
ICEcoder.redoTabHighlight(ICEcoder.selectedTab);
// Redo our find display
top.ICEcoder.findMode = false;
ICEcoder.findReplace('find',true,false);
}
cM.setOption('theme','icecoder visible');
// Focus on & refresh our selected instance
cM.focus();
cM.refresh();
// Highlight the selected tab
ICEcoder.redoTabHighlight(ICEcoder.selectedTab);
},
// Reset all tabs to be without a highlight and then highlight the selected
redoTabHighlight: function(selectedTab) {
var bgVPos;
var bgVPos, tColor;
for(var i=1;i<=ICEcoder.changedContent.length;i++) {
ICEcoder.changedContent[i-1]==1 ? bgVPos = -44 : bgVPos = 0;
i==selectedTab ? ICEcoder.changedContent[selectedTab-1]==1 ? bgVPos = -33 : bgVPos = -22 : bgVPos = bgVPos;
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)";
}
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";
}
ICEcoder.changedContent[selectedTab-1]==1 ? top.ICEcoder.fMIconVis('fMSave',1) : top.ICEcoder.fMIconVis('fMSave',0.3);
@@ -385,7 +411,7 @@ var ICEcoder = {
top.ICEcoder.openFiles.push(top.ICEcoder.shortURL);
// Setup a new tab
closeTabLink = '<a nohref onClick="parent.ICEcoder.closeTab('+(top.ICEcoder.openFiles.length)+')"><img src="images/nav-close.gif"></a>';
closeTabLink = '<a nohref onClick="top.ICEcoder.closeTab('+(top.ICEcoder.openFiles.length)+')"><img src="images/nav-close.gif" id="closeTabButton'+(top.ICEcoder.openFiles.length)+'" class="closeTab"></a>';
top.document.getElementById('tab'+(top.ICEcoder.openFiles.length)).style.display = "inline-block";
top.document.getElementById('tab'+(top.ICEcoder.openFiles.length)).innerHTML = top.ICEcoder.openFiles[top.ICEcoder.openFiles.length-1] + " " + closeTabLink;
@@ -395,6 +421,8 @@ var ICEcoder = {
// Add a new value ready to indicate if this content has been changed
top.ICEcoder.changedContent.push(0);
top.ICEcoder.setLastOpenedFiles();
},
// Create a new tab for a file
@@ -405,7 +433,7 @@ var ICEcoder = {
top.ICEcoder.openFiles[tabNum] = newName;
// Setup a new tab
closeTabLink = '<a nohref onClick="parent.ICEcoder.closeTab('+tabNum+')"><img src="images/nav-close.gif"></a>';
closeTabLink = '<a nohref onClick="parent.ICEcoder.closeTab('+tabNum+')"><img src="images/nav-close.gif" id="closeTabButton'+tabNum+'" class="closeTab"></a>';
top.document.getElementById('tab'+tabNum).innerHTML = top.ICEcoder.openFiles[tabNum] + " " + closeTabLink;
},
@@ -417,8 +445,8 @@ var ICEcoder = {
fileName = ICEcoder.openFiles[ICEcoder.selectedTab-1];
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 or CSS file
if (ICEcoder.htmlTagArray.length==0||fileName.indexOf(".js")>0||fileName.indexOf(".css")>0) {
// 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";
ICEcoder.nestValid.innerHTML = "Nesting OK";
} else {
@@ -462,17 +490,19 @@ var ICEcoder = {
caretChunk = cM.getValue().substr(0,ICEcoder.caretPos+1);
if (caretChunk.lastIndexOf("<script")>caretChunk.lastIndexOf("</script>")&&caretLocType=="Unknown") {caretLocType = "JavaScript"};
if (caretChunk.lastIndexOf("<?")>caretChunk.lastIndexOf("?>")&&caretLocType=="Unknown") {caretLocType = "PHP"};
if (caretChunk.lastIndexOf("<%")>caretChunk.lastIndexOf("%>")&&caretLocType=="Unknown") {caretLocType = "Ruby"};
if (caretChunk.lastIndexOf("<")>caretChunk.lastIndexOf(">")&&caretLocType=="Unknown") {caretLocType = "HTML"};
if (caretLocType=="Unknown") {caretLocType = "Content"};
fileName = ICEcoder.openFiles[ICEcoder.selectedTab-1];
if (fileName.indexOf(".js")>0) {caretLocType="JavaScript"};
if (fileName.indexOf(".rb")>0) {caretLocType="Ruby"};
if (fileName.indexOf(".css")>0) {caretLocType="CSS"};
ICEcoder.caretLocType = caretLocType;
// If we're in a JS or PHP code block, add that to the nest display
if (caretLocType=="JavaScript"||caretLocType=="PHP") {
// If we're in a JS, PHP or Ruby code block, add that to the nest display
if (caretLocType=="JavaScript"||caretLocType=="PHP"||caretLocType=="Ruby") {
ICEcoder.nestDisplay.innerHTML += " &gt; " + caretLocType;
}
},
@@ -480,7 +510,7 @@ var ICEcoder = {
// Alter array indicating which files have changed
redoChangedContent: function(evt) {
var key;
key = evt.keyCode ? evt.keyCode : evt.which ? evt.which : evt.charCode;
// Exclude a few keys such as Escape...
if (top.ICEcoder.ctrlKeyDown==false && key!=27 && key!=20 && (key<16||key>19) && (key<37||key>40) && (key!=144||key!=145) && (key!=44||key!=45) && (key<33||key>36) && (key!=91||key!=92) && (key<112||key>123)) {
@@ -506,21 +536,20 @@ var ICEcoder = {
ICEcoder.openFiles[i-1] = ICEcoder.openFiles[i];
// reduce the tab reference number on the closeTab link by 1
top.document.getElementById('tab'+i).innerHTML = top.document.getElementById('tab'+i).innerHTML.replace(("closeTab("+(i+1)+")"),"closeTab("+i+")");
top.document.getElementById('tab'+i).innerHTML = top.document.getElementById('tab'+i).innerHTML.replace(("closeTab("+(i+1)+")"),"closeTab("+i+")").replace(("closeTabButton("+(i+1)+")"),"closeTabButton("+i+")");
}
// hide the instance we're closing by setting the hide class, clear the value & remove from the array
ICEcoder.content.contentWindow['cM'+top.ICEcoder.cMInstances[closeTabNum-1]].setOption('theme','icecoder hidden');
ICEcoder.content.contentWindow['cM'+top.ICEcoder.cMInstances[closeTabNum-1]].setValue('');
// hide the instance we're closing by setting the hide class and removing from the array
ICEcoder.content.contentWindow['cM'+top.ICEcoder.cMInstances[closeTabNum-1]].setOption('theme',top.theme+' hidden');
top.ICEcoder.cMInstances.splice(closeTabNum-1,1);
// clear the rightmost tab (or only one left in a 1 tab scenario) & remove from the array
top.document.getElementById('tab'+ICEcoder.openFiles.length).style.display = "none";
top.document.getElementById('tab'+ICEcoder.openFiles.length).innerHTML = "";
ICEcoder.openFiles.pop();
// Determin the new selectedTab number, reduced by 1 if we have some tabs, 0 for a reset state
ICEcoder.openFiles.length>0 ? ICEcoder.selectedTab-=1 : ICEcoder.selectedTab = 0;
ICEcoder.openFileMDTs.pop();
// If we're closing the selected tab, determin the new selectedTab number, reduced by 1 if we have some tabs, 0 for a reset state
if (ICEcoder.selectedTab==closeTabNum) {
ICEcoder.openFiles.length>0 ? ICEcoder.selectedTab-=1 : ICEcoder.selectedTab = 0;
}
if (ICEcoder.openFiles.length>0 && ICEcoder.selectedTab==0) {ICEcoder.selectedTab=1};
// hide the content area if we have no tabs open
@@ -532,10 +561,11 @@ var ICEcoder = {
ICEcoder.switchMode();
ICEcoder.switchTab(ICEcoder.selectedTab);
}
// Highlight the selected tab after splicing the change state out of the array
top.ICEcoder.changedContent.splice(closeTabNum-1,1);
top.parent.ICEcoder.redoTabHighlight(ICEcoder.selectedTab);
top.ICEcoder.setLastOpenedFiles();
}
// Lastly, stop it from trying to also switch tab
top.ICEcoder.canSwitchTabs=false;
@@ -649,19 +679,20 @@ var ICEcoder = {
document.findAndReplace.target[2].innerHTML = "selected files";
document.findAndReplace.target[3].innerHTML = "selected filenames";
}
// Finally, show or grey out the relevant file manager icons
top.ICEcoder.selectedFiles.length == 1 ? top.ICEcoder.fMIconVis('fMOpen',1) : top.ICEcoder.fMIconVis('fMOpen',0.3);
top.ICEcoder.selectedFiles.length == 1 && top.ICEcoder.thisFileFolderType == "folder" ? top.ICEcoder.fMIconVis('fMNewFile',1) : top.ICEcoder.fMIconVis('fMNewFile',0.3);
top.ICEcoder.selectedFiles.length == 1 && top.ICEcoder.thisFileFolderType == "folder" ? top.ICEcoder.fMIconVis('fMNewFolder',1) : top.ICEcoder.fMIconVis('fMNewFolder',0.3);
top.ICEcoder.selectedFiles.length == 1 ? top.ICEcoder.fMIconVis('fMDelete',1) : top.ICEcoder.fMIconVis('fMDelete',0.3);
top.ICEcoder.selectedFiles.length > 0 ? top.ICEcoder.fMIconVis('fMDelete',1) : top.ICEcoder.fMIconVis('fMDelete',0.3);
top.ICEcoder.selectedFiles.length == 1 ? top.ICEcoder.fMIconVis('fMRename',1) : top.ICEcoder.fMIconVis('fMRename',0.3);
// Hide the file menu incase it's showing
top.document.getElementById('fileMenu').style.display = "none";
},
// Select or deselect file
selectDeselectFile: function(action,file) {
action == "select" ? file.style.backgroundColor="#888888" : file.style.backgroundColor="#dddddd";
action == "select" ? file.style.color="#f8f8f8" : file.style.color="#000000";
action == "select" ? file.style.backgroundColor="#888888" : file.style.backgroundColor="transparent";
action == "select" ? file.style.color="#ffffff" : file.style.color="#eeeeee";
},
// Create a new file (start & instant save)
@@ -733,8 +764,8 @@ var ICEcoder = {
var saveType;
saveAs ? saveType = "saveAs" : saveType = "save";
top.ICEcoder.serverQueue("add","lib/file-control.php?action=save&file="+ICEcoder.openFiles[ICEcoder.selectedTab-1].replace(/\//g,"|")+"&saveType="+saveType);
top.ICEcoder.serverQueue("add","lib/file-control.php?action=save&file="+ICEcoder.openFiles[ICEcoder.selectedTab-1].replace(/\//g,"|")+"&fileMDT="+ICEcoder.openFileMDTs[ICEcoder.selectedTab-1]+"&saveType="+saveType);
top.ICEcoder.serverMessage('<b>Saving</b><br>'+ICEcoder.openFiles[ICEcoder.selectedTab-1]);
},
@@ -749,12 +780,14 @@ var ICEcoder = {
if(top.ICEcoder.openFiles[i]==shortURL.replace(/\|/g,"/")) {
// rename array item and the tab
top.ICEcoder.openFiles[i] = renamedFile;
closeTabLink = '<a nohref onClick="top.ICEcoder.files.contentWindow.closeTab('+(i+1)+')"><img src="images/nav-close.gif"></a>';
closeTabLink = '<a nohref onClick="top.ICEcoder.files.contentWindow.closeTab('+(i+1)+')"><img src="images/nav-close.gif" id="closeTabButton'+(i+1)+'" class="closeTab"></a>';
top.document.getElementById('tab'+(i+1)).innerHTML = top.ICEcoder.openFiles[i] + " " + closeTabLink;
}
}
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();
}
},
@@ -777,12 +810,21 @@ var ICEcoder = {
// Show menu on right clicking in file manager
showMenu: function() {
var menuType, folderMenuItems;
var menuType, folderMenuItems, foundFile;
if (top.ICEcoder.selectedFiles.length == 0) {top.ICEcoder.selectFileFolder()};
foundFile=false;
for (var i=0;i<=top.ICEcoder.selectedFiles.length-1;i++) {
if (top.ICEcoder.rightClickedFile.replace(fullPath,"")==top.ICEcoder.selectedFiles[i].replace(/\|/g,"/")) {foundFile=true};
}
if (!foundFile) {top.ICEcoder.selectFileFolder()};
if ("undefined" != typeof top.ICEcoder.thisFileFolderLink && top.ICEcoder.thisFileFolderLink!="") {
top.ICEcoder.selectedFiles[0].indexOf(".")>0 ? menuType = "file" : menuType = "folder";
top.ICEcoder.selectedFiles[0].indexOf(".")>-1 ? menuType = "file" : menuType = "folder";
folderMenuItems = top.document.getElementById('folderMenuItems');
menuType == "folder" ? folderMenuItems.style.display = "block" : folderMenuItems.style.display = "none";
menuType == "folder" && top.ICEcoder.selectedFiles.length == 1 ? folderMenuItems.style.display = "block" : folderMenuItems.style.display = "none";
top.ICEcoder.selectedFiles.length > 1 ? singleFileMenuItems.style.display = "none" : singleFileMenuItems.style.display = "block";
document.getElementById('fileMenu').style.display = "inline-block";
document.getElementById('fileMenu').style.left = (top.ICEcoder.mouseX+20) + "px";
document.getElementById('fileMenu').style.top = (top.ICEcoder.mouseY-top.document.getElementById('filesFrame').contentWindow.document.body.scrollTop+80) + "px";
@@ -807,30 +849,42 @@ var ICEcoder = {
},
// Find & replace text according to user selections
findReplace: function(action,resultsOnly) {
var find, findLen, cM, content, lineCount, numChars, charsToCursor, charCount, startPos, endPos;
findReplace: function(action,resultsOnly,buttonClick) {
var find, findLen, replaceLen, cM, content, lineCount, numChars, charsToCursor, charCount, startPos, endPos, replaceQS;
// Determine our find string, in lowercase and the length of that
find = parent.parent.document.getElementById('find').value.toLowerCase();
find = top.document.getElementById('find').value;
findLen = find.length;
replaceLen = top.document.getElementById('replace').value.length;
// If we have something to find
if (findLen>0) {
// If we have something to find in currrent document
if (findLen>0 && document.findAndReplace.target.value=="this document") {
cM = ICEcoder.getcMInstance();
content = cM.getValue().toLowerCase();
content = cM.getValue();
// Find & replace the next instance?
if (document.findAndReplace.connector.value=="and" && cM.getSelection()==find) {
cM.replaceSelection(document.getElementById('replace').value);
// Find & replace the next instance, or all?
if (document.findAndReplace.connector.value=="and") {
if (document.findAndReplace.replaceAction.value=="replace" && cM.getSelection()==find) {
cM.replaceSelection(document.getElementById('replace').value);
}
if (document.findAndReplace.replaceAction.value=="replace all" && buttonClick) {
var rExp = new RegExp(find,"g");
cM.setValue(cM.getValue().replace(rExp,document.getElementById('replace').value));
}
}
// Get the content again, as it might of changed
content = cM.getValue();
if (!top.ICEcoder.findMode||parent.parent.document.getElementById('find').value!=ICEcoder.lastsearch) {
ICEcoder.results = [];
for (var i=0;i<content.length;i++) {
if (content.substr(i,findLen)==find) {
if (content.substr(i,findLen)==find && i!= ICEcoder.findResult) {
ICEcoder.results.push(i);
i+=findLen-1;
}
}
// Also remember the last search term made
ICEcoder.lastsearch = find;
}
@@ -855,7 +909,7 @@ var ICEcoder = {
charsToCursor = numChars+cM.getCursor().ch;
ICEcoder.findResult = 0;
for (var i=0;i<ICEcoder.results.length;i++) {
if (ICEcoder.results[i]<=charsToCursor) {
if (ICEcoder.results[i]<charsToCursor) {
ICEcoder.findResult++;
}
}
@@ -870,13 +924,17 @@ var ICEcoder = {
}
}
charCount = ICEcoder.results[ICEcoder.findResult]-content.lastIndexOf('\n',ICEcoder.results[ICEcoder.findResult])-1;
charCount = ICEcoder.results[ICEcoder.findResult];
startPos = new Object();
startPos.line = lineCount;
startPos.ch = charCount;
endPos = new Object();
endPos.line = lineCount;
endPos.ch = charCount+findLen;
if (document.findAndReplace.connector.value=="and" && document.findAndReplace.replaceAction.value=="replace all" && buttonClick) {
endPos.ch = charCount+replaceLen;
} else {
endPos.ch = charCount+findLen;
}
// Finally, highlight our selection
cM = ICEcoder.getcMInstance();
@@ -888,7 +946,14 @@ var ICEcoder = {
parent.parent.document.getElementById('results').innerHTML = "No results";
}
} else {
parent.parent.document.getElementById('results').innerHTML = "";
// Show the relevant multiple results popup
if (find != "" && buttonClick) {
replaceQS = "";
if (document.findAndReplace.connector.value=="and") {
replaceQS = "&replace="+document.getElementById('replace').value;
}
top.document.getElementById('mediaContainer').innerHTML = '<iframe src="lib/multiple-results.php?find='+find+replaceQS+'" class="whiteGlow" style="width: 700px; height: 500px"></iframe>';
}
}
},
@@ -908,12 +973,16 @@ var ICEcoder = {
cM = ICEcoder.getcMInstance();
fileName = ICEcoder.openFiles[ICEcoder.selectedTab-1];
if (fileName.indexOf('.js')>0) {
cM.setOption("mode","javascript");
} else if (fileName.indexOf('.css')>0) {
cM.setOption("mode","css");
} else {
cM.setOption("mode","application/x-httpd-php");
if (fileName) {
if (fileName.indexOf('.js')>0) {
cM.setOption("mode","javascript");
} else if (fileName.indexOf('.rb')>0) {
cM.setOption("mode","ruby");
} else if (fileName.indexOf('.css')>0) {
cM.setOption("mode","css");
} else {
cM.setOption("mode","application/x-httpd-php");
}
}
},
@@ -939,24 +1008,27 @@ var ICEcoder = {
},
// Start running plugin intervals according to given specifics
startPluginIntervals: function(plugURL,plugTarget,plugTimer) {
startPluginIntervals: function(plugRef,plugURL,plugTarget,plugTimer) {
// For this window instances
if (plugTarget=="_parent"||plugTarget=="_top"||plugTarget=="_self"||plugTarget=="") {
setInterval('window.location=\''+plugURL+'\'',plugTimer*1000*60);
top.ICEcoder['plugTimer'+plugRef] = setInterval('window.location=\''+plugURL+'\'',plugTimer*1000*60);
// for fileControl iframe instances
} else if (plugTarget.indexOf("fileControl")==0) {
setInterval(function() {top.ICEcoder.serverQueue("add",plugURL);top.ICEcoder.serverMessage(plugTarget.split(":")[1]);},plugTimer*1000*60);
top.ICEcoder['plugTimer'+plugRef] = setInterval(function() {top.ICEcoder.serverQueue("add",plugURL);top.ICEcoder.serverMessage(plugTarget.split(":")[1]);},plugTimer*1000*60);
// for _blank or named target window instances
} else {
setInterval('window.open(\''+plugURL+'\',\''+plugTarget+'\')',plugTimer*1000*60);
top.ICEcoder['plugTimer'+plugRef] = setInterval('window.open(\''+plugURL+'\',\''+plugTarget+'\')',plugTimer*1000*60);
}
// push the plugin ref into our array
top.ICEcoder.pluginIntervalRefs.push(plugRef);
},
// Comment or uncomment line on keypress
lineCommentToggle: function() {
var cM, cursorPos, linePos, lineContent, lCLen, adjustCursor;
var cM, cursorPos, linePos, lineContent, lCLen, adjustCursor, startLine, endLine;
cM = ICEcoder.getcMInstance();
cursorPos = cM.getCursor().ch;
@@ -965,17 +1037,28 @@ var ICEcoder = {
lCLen = lineContent.length;
adjustCursor = 3;
if (ICEcoder.caretLocType=="JavaScript"||ICEcoder.caretLocType=="PHP"||ICEcoder.caretLocType=="CSS") {
if (ICEcoder.caretLocType=="JavaScript"||ICEcoder.caretLocType=="PHP"||ICEcoder.caretLocType=="Ruby"||ICEcoder.caretLocType=="CSS") {
if (cM.somethingSelected()) {
if (cM.getSelection().slice(0,2)!="/*") {
cM.replaceSelection("/*" + cM.getSelection() + "*/");
if (ICEcoder.caretLocType=="Ruby") {
startLine = cM.getCursor(true).line;
endLine = cM.getCursor().line;
for (var i = startLine; i<=endLine; i++) {
cM.getLine(i).slice(0,2)!="# " ? cM.setLine(i, "# " + cM.getLine(i)) : cM.setLine(i, cM.getLine(i).slice(2,cM.getLine(i).length));
}
} else {
cM.replaceSelection(cM.getSelection().slice(2,cM.getSelection().length-2));
if (cM.getSelection().slice(0,2)!="/*") {
cM.replaceSelection("/*" + cM.getSelection() + "*/");
} else {
cM.replaceSelection(cM.getSelection().slice(2,cM.getSelection().length-2));
}
}
} else {
if (ICEcoder.caretLocType=="CSS") {
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") {
lineContent.slice(0,2)!="# " ? cM.setLine(linePos, "# " + lineContent) : cM.setLine(linePos, lineContent.slice(2,lCLen));
if (lineContent.slice(0,2)=="# ") {adjustCursor = -adjustCursor};
} else {
lineContent.slice(0,3)!="// " ? cM.setLine(linePos, "// " + lineContent) : cM.setLine(linePos, lineContent.slice(3,lCLen));
if (lineContent.slice(0,3)=="// ") {adjustCursor = -adjustCursor};
@@ -1034,7 +1117,7 @@ var ICEcoder = {
if (action=="add") {
// Determin if this is a file or folder and based on that, set the CSS styling & link
file.indexOf(".")>0 ? actionElemType = "file" : actionElemType = "folder";
file.indexOf(".")>-1 ? actionElemType = "file" : actionElemType = "folder";
actionElemType=="file" ? cssStyle = "pft-file ext-" + file.substr(file.indexOf(".")+1,file.length) : cssStyle = "pft-directory";
actionElemType=="file" ? hrefLink = "nohref" : hrefLink = "href=\"#\"";
@@ -1206,16 +1289,19 @@ var ICEcoder = {
if (ICEcoder.selectedFiles.length==1) {
top.ICEcoder.rightClickedFile=top.ICEcoder.thisFileFolderLink=top.fullPath+top.ICEcoder.selectedFiles[0].replace('|','/');
if (action=="open" && ICEcoder.selectedFiles[0].indexOf(".")>0) {
if (action=="open" && ICEcoder.selectedFiles[0].indexOf(".")>-1) {
top.ICEcoder.thisFileFolderType='file';
top.ICEcoder.openFile();
}
if (action=="newFile") {top.ICEcoder.newFile();}
if (action=="newFolder") {top.ICEcoder.newFolder();}
if (action=="delete") {top.ICEcoder.deleteFile(top.ICEcoder.rightClickedFile);}
if (action=="rename") {top.ICEcoder.renameFile(top.ICEcoder.rightClickedFile);}
}
if (action=="delete" && ICEcoder.selectedFiles.length>0) {
top.ICEcoder.deleteFile();
}
if (action=="view" && ICEcoder.openFiles.length>0) {
window.open(top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1]);
}
@@ -1242,7 +1328,7 @@ var ICEcoder = {
// Highlight or hide block upon roll over/out of nest positions
highlightBlock: function(nestPos,hide) {
var cM;
var cM, searchPos, cursor, startPos, endPos;
cM = ICEcoder.getcMInstance();
// Hiding the block
@@ -1285,7 +1371,7 @@ var ICEcoder = {
// Set our cursor position upon mouse click of the nest position
setPosition: function(nestPos,line,tag) {
var cM;
var cM, char, charPos;
cM = ICEcoder.getcMInstance();
// Set out char position just after the tag, and refocus on the editor
@@ -1294,11 +1380,118 @@ var ICEcoder = {
cM.focus();
// Now update the nest display up to this nest depth & without any HTML tags to kill further interactivity
charPos = 0;
for (i=0;i<=nestPos;i++) {
for (var i=0;i<=nestPos;i++) {
charPos = ICEcoder.nestDisplay.innerHTML.indexOf("&gt;",charPos+1);
}
ICEcoder.nestDisplay.innerHTML = ICEcoder.nestDisplay.innerHTML.substr(0,charPos).replace(/<(?:.|\n)*?>/gm, '');
top.ICEcoder.dontUpdateNest = false;
top.ICEcoder.dontSelect = true;
},
// Set the current lastOpenedFiles in the settings file
setLastOpenedFiles: function() {
var lastOpenedFiles;
lastOpenedFiles = "";
// 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 += ","};
}
}
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);
}
},
// 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('|','/');
top.ICEcoder.thisFileFolderType='file';
top.ICEcoder.openFile();
}
},
// Refresh file manager on demand
refreshFileManager: function(loginAttempt) {
top.document.getElementById('loadingMask').style.visibility = "visible";
top.ICEcoder.filesFrame.src="files.php";
top.ICEcoder.filesFrame.style.opacity="0";
top.ICEcoder.filesFrame.onload = function() {
top.ICEcoder.filesFrame.style.opacity="1";
top.document.getElementById('loadingMask').style.visibility = "hidden";
if (loginAttempt) {
if (loginAttempt == "loginOK") {
top.document.getElementById('accountLogin').style.top = "-50px";
setTimeout(function() {top.document.getElementById('accountLoginContainer').style.display = "none";},300);
} else {
alert('Sorry, that\'s not correct.');
}
}
}
},
// Show the settings screen
settingsScreen: function(vis) {
if (vis=="show") {
top.document.getElementById('mediaContainer').innerHTML = '<iframe src="lib/settings-screen.php" class="whiteGlow" style="width: 970px; height: 600px"></iframe>';
}
top.ICEcoder.showHide(vis,top.document.getElementById('blackMask'));
},
// Show the help screen
helpScreen: function(vis) {
if (vis=="show") {
top.document.getElementById('mediaContainer').innerHTML = '<iframe src="lib/help.php" class="whiteGlow" style="width: 400px; height: 400px"></iframe>';
}
top.ICEcoder.showHide(vis,top.document.getElementById('blackMask'));
},
// Update the settings used when we make a change to them
useNewSettings: function(themeURL,tabsIndent,codeAssist,lockedNav,visibleTabs,refreshFM) {
var styleNode, strCSS, cMCSS;
// Add new stylesheet for selected theme
top.theme = themeURL.slice(themeURL.lastIndexOf("/")+1,themeURL.lastIndexOf("."));
if (top.theme=="editor") {top.theme="icecoder"};
styleNode = document.createElement('link');
styleNode.setAttribute('rel', 'stylesheet');
styleNode.setAttribute('type', 'text/css');
styleNode.setAttribute('href', themeURL);
top.ICEcoder.content.contentWindow.document.getElementsByTagName('head')[0].appendChild(styleNode);
top.ICEcoder.switchTab(top.ICEcoder.selectedTab);
// Tabs indent setting
top.tabsIndent = tabsIndent;
// Check/uncheck Code Assist setting
top.document.getElementById('codeAssist').checked = codeAssist;
// Unlock/lock the file manager
if (lockedNav != top.ICEcoder.lockedNav) {top.ICEcoder.lockUnlockNav()};
if (!lockedNav) {
ICEcoder.changeFilesW('contract');
top.document.getElementById('fileMenu').style.display='none';
}
// Show visible tabs or not
document.all ? strCSS = 'rules' : strCSS = 'cssRules';
cMCSS = ICEcoder.content.contentWindow.document;
visibleTabs ? cMCSS.styleSheets[2][strCSS][5].style['content'] = '"\\21e5"' : cMCSS.styleSheets[2][strCSS][5].style['content'] = '" "';
// Finally, refresh the file manager if we need to
if (refreshFM) {top.ICEcoder.refreshFileManager()};
},
// Update and show/hide found results display?
updateResultsDisplay: function(showHide) {
ICEcoder.findReplace('find',true,false);
document.getElementById('results').style.display = showHide == "show" ? 'inline-block' : 'none';
}
};

View File

@@ -1,6 +1,4 @@
html, body {margin: 0px}
/* Based VERY loosely on the Monokai theme */
/* ICE coder default theme: Based VERY loosely on Monokai */
.cm-s-icecoder {font-size: 12px; color: #666; background: #1c1c19;}
@@ -35,11 +33,8 @@ html, body {margin: 0px}
.cm-s-icecoder span.cm-hr {color: #999;}
.cm-s-icecoder span.cm-link {color: #ff0;}
.cm-s-icecoder .CodeMirror-cursor {border-left: 1px solid white !important;}
.cm-s-icecoder .CodeMirror-selected {background: #037 !important;}
.cm-s-icecoder .CodeMirror-gutter {background: #333; border-right: 1px solid #e8e8e8}
.cm-s-icecoder .CodeMirror-gutter-text {color: #999; width: 35px; cursor: default}
.cm-s-icecoder .CodeMirror-cursor {border-left: 1px solid white !important;}
.cm-s-icecoder .CodeMirror-matchingbracket{border: 1px solid grey; color: black !important;}
span.CodeMirror-matchhighlight {background: #555555}
.CodeMirror-focused span.CodeMirror-matchhighlight {color: #000000; background: #555555; !important}
.cm-s-icecoder .CodeMirror-matchingbracket {border: 1px solid grey; color: black !important;}

View File

@@ -28,7 +28,9 @@ if ($_GET['action']=="load") {
}
}
if ($_SESSION['userLevel'] == 10 || ($_SESSION['userLevel'] < 10 && $bannedFile==false)) {
echo '<script>fileType="text";</script>';
echo '<script>fileType="text";top.ICEcoder.rightClickedFile=top.ICEcoder.thisFileFolderLink=\''.$file.'\';';
echo 'shortURL = top.ICEcoder.thisFileFolderLink.replace(/\|/g,"/");';
echo 'top.ICEcoder.shortURL = shortURL.substr((shortURL.indexOf(top.shortURLStarts)+top.shortURLStarts.length),shortURL.length);</script>';
$loadedFile = file_get_contents($file);
echo '<textarea name="loadedFile" id="loadedFile">'.str_replace("</textarea>","<ICEcoder:/:textarea>",$loadedFile).'</textarea>';
} else {
@@ -136,21 +138,28 @@ if ($_GET['action']=="save") {
$saveFile = str_replace("\\","/",$_SERVER['DOCUMENT_ROOT']).$file;
$saveFile = str_replace("//","/",$saveFile);
if ((file_exists($saveFile) && is_writable($saveFile)) || $_POST['newFileName']!="") {
$fh = fopen($saveFile, 'w') or die("can't open file");
fwrite($fh, $_POST['contents']);
fclose($fh);
if (filemtime($saveFile)==$_GET['fileMDT']||!(isset($_GET['fileMDT']))) {
$fh = fopen($saveFile, 'w') or die("Sorry, cannot save");
fwrite($fh, $_POST['contents']);
fclose($fh);
clearstatcache();
echo '<script>top.ICEcoder.openFileMDTs[top.ICEcoder.selectedTab-1]="'.filemtime($saveFile).'";</script>';
if (isset($_POST['newFileName'])&&$_POST['newFileName']!="") {
// Reload file manager & stop CTRL+s being sticky
$fileName = substr($file,strrpos($file,"/")+1);
$fileLoc = substr($file,0,strrpos($file,"/"));
if ($fileLoc=="") {$fileLoc = "/";};
echo '<script>top.ICEcoder.selectedFiles=[];top.ICEcoder.updateFileManagerList(\'add\',\''.$fileLoc.'\',\''.$fileName.'\')</script>';
if (isset($_POST['newFileName'])&&$_POST['newFileName']!="") {
// Reload file manager & stop CTRL+s being sticky
$fileName = substr($file,strrpos($file,"/")+1);
$fileLoc = substr($file,0,strrpos($file,"/"));
if ($fileLoc=="") {$fileLoc = "/";};
echo '<script>top.ICEcoder.selectedFiles=[];top.ICEcoder.updateFileManagerList(\'add\',\''.$fileLoc.'\',\''.$fileName.'\')</script>';
}
if (isset($_POST['newFileName'])&&$_POST['newFileName']!="") {
echo '<script>top.ICEcoder.renameTab(top.ICEcoder.selectedTab,\''.$file.'\');</script>';
}
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>";
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);action="nothing";</script>';
}
if (isset($_POST['newFileName'])&&$_POST['newFileName']!="") {
echo '<script>top.ICEcoder.renameTab(top.ICEcoder.selectedTab,\''.$file.'\');</script>';
}
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);action="doneSave";</script>';
} else {
echo "<script>alert('Sorry, cannot write\\n".$file."');</script>";
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);action="nothing";</script>';
@@ -191,19 +200,21 @@ if (action=="load") {
top.ICEcoder.content.contentWindow['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].setLineClass(top.ICEcoder['cMActiveLine'+top.ICEcoder.selectedTab], null);
top.ICEcoder['cMActiveLine'+top.ICEcoder.selectedTab] = top.ICEcoder.content.contentWindow['cM'+top.ICEcoder.cMInstances[top.ICEcoder.selectedTab-1]].setLineClass(0, "cm-s-activeLine");
top.ICEcoder.nextcMInstance++;
top.ICEcoder.serverMessage();
top.ICEcoder.serverQueue("del",0);
top.ICEcoder.openFileMDTs.push('<?php echo filemtime($file); ?>');
top.ICEcoder.loadingFile = false;
}
if (fileType=="image") {
top.document.getElementById('blackMask').style.visibility = "visible";
top.document.getElementById('mediaContainer').innerHTML = "<img src=\"<?php echo str_replace($docRoot,"",$file);?>\" style=\"border: solid 10px #ffffff; max-width: 700px; max-height: 500px\" onClick=\"return false\"><br><span style=\"border: solid 10px #ffffff; 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 #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.ICEcoder.serverMessage();
top.ICEcoder.serverQueue("del",0);
}
</script>
<form name="saveFile" action="file-control.php?action=save&file=<?php if (isset($file)) {echo $file;};?>" method="POST">
<form name="saveFile" action="file-control.php?action=save&file=<?php if (isset($file)) {echo $file;}; if (isset($_GET['fileMDT']) && $_GET['fileMDT']!="undefined") {echo "&fileMDT=".$_GET['fileMDT'];};?>" method="POST">
<textarea name="contents"></textarea>
<input type="hidden" name="newFileName" value="">
</form>

View File

@@ -19,6 +19,8 @@ table, caption, tbody, tfoot, thead, tr, th, td {
body {margin: 0px; overflow: auto}
.refresh {float: right; margin-right: 15px; cursor: pointer}
.fileManager {
margin: 15px 0px 15px 22px;
-webkit-user-select: none;
@@ -28,7 +30,7 @@ body {margin: 0px; overflow: auto}
}
.fileManager span {font-family: helvetica, arial, swiss, verdana;}
.fileManager a {color: #000000; text-decoration: none;}
.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);}
@@ -38,61 +40,24 @@ body {margin: 0px; overflow: auto}
.fileManager LI.pft-file { list-style-image: url(../images/file-manager-icons/file.png); }
/* Additional file types */
.fileManager LI.ext-3gp { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-afp { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-afpa { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-asp { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-aspx { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-avi { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-bat { list-style-image: url(../images/file-manager-icons/application.png); }
.fileManager LI.ext-bmp { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-c { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-cfm { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-cgi { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-com { list-style-image: url(../images/file-manager-icons/application.png); }
.fileManager LI.ext-cpp { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-css { list-style-image: url(../images/file-manager-icons/css.png); }
.fileManager LI.ext-doc { list-style-image: url(../images/file-manager-icons/doc.png); }
.fileManager LI.ext-exe { list-style-image: url(../images/file-manager-icons/application.png); }
.fileManager LI.ext-gif { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-fla { list-style-image: url(../images/file-manager-icons/flash.png); }
.fileManager LI.ext-h { list-style-image: url(../images/file-manager-icons/code.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-jar { list-style-image: url(../images/file-manager-icons/java.png); }
.fileManager LI.ext-jpg { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-jpeg { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-js { list-style-image: url(../images/file-manager-icons/script.png); }
.fileManager LI.ext-lasso { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-log { list-style-image: url(../images/file-manager-icons/txt.png); }
.fileManager LI.ext-m4p { list-style-image: url(../images/file-manager-icons/music.png); }
.fileManager LI.ext-mov { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-mp3 { list-style-image: url(../images/file-manager-icons/music.png); }
.fileManager LI.ext-mp4 { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-mpg { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-mpeg { list-style-image: url(../images/file-manager-icons/film.png); }
.fileManager LI.ext-ogg { list-style-image: url(../images/file-manager-icons/music.png); }
.fileManager LI.ext-pcx { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-pdf { list-style-image: url(../images/file-manager-icons/pdf.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/picture.png); }
.fileManager LI.ext-ppt { list-style-image: url(../images/file-manager-icons/ppt.png); }
.fileManager LI.ext-psd { list-style-image: url(../images/file-manager-icons/psd.png); }
.fileManager LI.ext-pl { list-style-image: url(../images/file-manager-icons/script.png); }
.fileManager LI.ext-py { list-style-image: url(../images/file-manager-icons/script.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-rpm { list-style-image: url(../images/file-manager-icons/linux.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/db.png); }
.fileManager LI.ext-swf { list-style-image: url(../images/file-manager-icons/flash.png); }
.fileManager LI.ext-tif { list-style-image: url(../images/file-manager-icons/picture.png); }
.fileManager LI.ext-tiff { list-style-image: url(../images/file-manager-icons/picture.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-vb { list-style-image: url(../images/file-manager-icons/code.png); }
.fileManager LI.ext-wav { list-style-image: url(../images/file-manager-icons/music.png); }
.fileManager LI.ext-wmv { list-style-image: url(../images/file-manager-icons/film.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/code.png); }
.fileManager LI.ext-zip { list-style-image: url(../images/file-manager-icons/zip.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); } */

31
lib/help.css Normal file
View File

@@ -0,0 +1,31 @@
/* First, reset everything to a standard */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
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;
font-size: 12px;
vertical-align: top;
}
body {overflow: hidden;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select:none;
user-select: none;
}
h1 {font-size: 36px; font-weight: normal; color: #888888; margin-bottom: 20px}
.help {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #ffffff; 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}

38
lib/help.php Normal file
View File

@@ -0,0 +1,38 @@
<?php include("settings.php");?>
<!DOCTYPE html>
<html>
<head>
<title>ICE Coder - <?php echo $versionNo;?> :: Help & Shortcuts</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="help.css">
</head>
<body class="help">
<h1 id="title">help</h1>
<h2>In file manager</h2>
<span class="key">Delete</span> <span class="shortcut">Delete file</span><br><br>
<h2>Within document</h2>
<span class="key">CTRL <span class="plus">+</span> I</span> <span class="shortcut">Search selected text</span><br>
<span class="key">Esc</span> <span class="shortcut">Comment / uncomment text</span><br>
<span class="key">Tab</span> <span class="shortcut">Insert tab / indent selected text</span><br><br>
<h2>Anywhere</h2>
<span class="key">CTRL <span class="plus">+</span> F</span> <span class="shortcut">Find</span><br>
<span class="key">CTRL <span class="plus">+</span> G</span> <span class="shortcut">Go to line</span><br>
<span class="key">CTRL <span class="plus">+</span> S</span> <span class="shortcut">Save</span><br>
<span class="key">CTRL <span class="plus">+</span> Shift <span class="plus">+</span> S</span> <span class="shortcut">Save as...</span><br>
<span class="key">CTRL <span class="plus">+</span> Enter</span> <span class="shortcut">View webpage</span><br>
<span class="key">CTRL <span class="plus">+</span> S <span class="plus">+</span> Enter</span> <span class="shortcut">Save & create sticky tab</span><br>
<span class="key">Esc</span> <span class="shortcut">Cancel tasks</span><br><br>
<h2>Clicking logo</h2>
<span class="key">Left click</span> <span class="shortcut">Help</span><br>
<span class="key">Right click</span> <span class="shortcut">Settings</span><br>
</body>
</html>

35
lib/multiple-results.css Normal file
View File

@@ -0,0 +1,35 @@
/* First, reset everything to a standard */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
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;
font-size: 12px;
vertical-align: top;
}
body {overflow: hidden;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select:none;
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}
.results {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #ffffff}
.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}

75
lib/multiple-results.php Normal file
View File

@@ -0,0 +1,75 @@
<?php include("settings.php");?>
<!DOCTYPE html>
<html>
<head>
<title>ICE Coder - <?php echo $versionNo;?> :: Multiple Results Screen</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="multiple-results.css">
</head>
<body class="results">
<div class="resultsPane">
<h1 id="title"></h1>
<div id="results"></div>
</div>
<?php if (isset($_GET['replace'])) { ?>
<div class="replaceAll" id="replaceAll" onClick="replaceAll()" style="opacity: 0.1">replace all</div>
<?php ;}; ?>
<script>
var resultsDisplay = "";
var foundTabArray = [];
var startTab = top.ICEcoder.selectedTab;
var rExp = new RegExp("<?php echo $_GET['find']; ?>","g");
for (var i=1;i<=top.ICEcoder.openFiles.length;i++) {
top.ICEcoder.switchTab(i);
var cM = top.ICEcoder.getcMInstance();
var content = cM.getValue();
if (content.match(rExp)) {
resultsDisplay += '<a href="javascript:gotoTab('+i+')">'+ top.ICEcoder.openFiles[i-1]+ '</a><br><div id="foundCount'+i+'">Found '+content.match(rExp).length+' times</div>';
<?php if (isset($_GET['replace'])) { ?>
resultsDisplay += '<div class="replace" id="replace" onClick="replaceSingle('+i+');this.style.display=\'none\'">replace</div>';
<?php ;}; ?>
resultsDisplay += '<hr>';
foundTabArray.push(i);
}
}
if (startTab!=top.ICEcoder.selectedTab) {
top.ICEcoder.switchTab(startTab);
}
foundTabArray.length==0 ? showHide = "hide" : showHide = "show";
top.ICEcoder.showHide(showHide,top.document.getElementById('blackMask'));
if (foundTabArray.length==0) {alert('No matches found')};
<?php if (isset($_GET['replace'])) { ?>
if (foundTabArray.length!=0) {document.getElementById('replaceAll').style.opacity = 1};
<?php ;}; ?>
foundTabArray.length >= 2 ? plural = "s" : plural = "";
document.getElementById('title').innerHTML = "'<?php echo $_GET['find']; ?>' found in "+foundTabArray.length+" file"+plural;
document.getElementById('results').innerHTML = resultsDisplay;
var gotoTab = function(tab) {
top.ICEcoder.switchTab(tab);
top.ICEcoder.showHide('hide',top.document.getElementById('blackMask'));
}
var replaceSingle = function(tab) {
top.ICEcoder.switchTab(tab);
cM = top.ICEcoder.getcMInstance();
content = cM.getValue();
cM.setValue(cM.getValue().replace(rExp,top.document.getElementById('replace').value));
document.getElementById('foundCount'+tab).innerHTML = document.getElementById('foundCount'+tab).innerHTML.replace('Found','Replaced');
}
var replaceAll = function() {
for (var i=0;i<=foundTabArray.length-1;i++) {
replaceSingle(foundTabArray[i]);
}
top.ICEcoder.showHide('hide',top.document.getElementById('blackMask'));
}
</script>
</body>
</html>

45
lib/settings-screen.css Normal file
View File

@@ -0,0 +1,45 @@
/* First, reset everything to a standard */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
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;
font-size: 12px;
vertical-align: top;
}
body {overflow: hidden;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select:none;
user-select: none;
}
h1 {font-size: 36px; font-weight: normal; color: #888888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #ffffff}
.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 .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 .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 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);
}
.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}

205
lib/settings-screen.php Normal file
View File

@@ -0,0 +1,205 @@
<?php include("settings.php");?>
<!DOCTYPE html>
<html>
<head>
<title>ICE Coder - <?php echo $versionNo;?> :: Settings Screen</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="settings-screen.css">
<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/javascript/javascript.js"></script>
<style type="text/css">
.CodeMirror {position: absolute; width: 0px; background-color: #ffffff; font-family: monospace}
.CodeMirror-scroll {height: 220px; width: 420px; overflow: hidden}
.cm-s-visible {display: block; top: 0px}
.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}
</style>
<link rel="stylesheet" href="editor.css">
<?php
$themeArray = array("ambiance","blackboard","cobalt","eclipse","elegant","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;
}
?>
</head>
<body class="settings">
<div class="infoPane">
<img src="../images/ice-coder.gif" class="logo">
<div class="version"><?php echo $versionNo;?></div>
<p>
git:<br>
<a href="http://github.com/mattpass/ICEcoder" target="_blank">http://github.com/mattpass/ICEcoder</a>
<br><br>
codemirror dir:<br>
<?php echo $codeMirrorDir; ?>
<br><br>
codemirror version:<br>
<?php echo $cMThisVer; ?>
<br><br>
doc root:<br>
<?php if($_SESSION['userLevel']==10) { echo $_SERVER['DOCUMENT_ROOT']; } else { echo '[HIDDEN]'; }; ?>
<br><br><br><br>
<div style="font-size: 10px; line-height: 12px">ICE coder by Matt Pass (<a href="http://www.twitter.com/mattpass" style="font-size: 10px" target="_blank">@mattpass</a>)<br><br>
Free to use it for your own purposes, commercial or not, just let me know of any cool uses or customisations. :)<br><br>
No warranty or liability accepted for anything, all responsibility of use is your own.<br><br>
Thanks go to the following people who have inspired me to create this and in the odd case, provided feedback or code:<br>
<?php
$peopleArray = array("marijnjh", "maettig", "wimtibackx", "jakubvrana", "davidwalshblog", "kuvos", "paul_irish", "mathias", "rem");
for ($i=0;$i<count($peopleArray)-1;$i++) {
echo '<a href="http://www.twitter.com/'.$peopleArray[$i].'" style="font-size: 10px" target="_blank">@'.$peopleArray[$i].'</a>';
if ($i<count($peopleArray)-2) {
echo ", ";
}
}
?>
</div>
</p>
</div>
<form name="settings" action="settings.php" method="POST">
<div class="settingsColumn1">
<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="openLastFiles" value="true"<?php if($openLastFiles) {echo ' checked';};?>> auto open last files on login<br>
<br>
<h2>assisting</h2>
<input type="checkbox" onclick="showButton()" name="codeAssist" value="true"<?php if($codeAssist) {echo ' checked';};?>> code assist<br>
<input type="checkbox" onclick="showButton();showHideTabs()" name="visibleTabs" value="true"<?php if($visibleTabs) {echo ' checked';};?>> visible tabs<br>
<input type="checkbox" onclick="showButton()" name="lockedNav" value="true"<?php if($lockedNav) {echo ' checked';};?>> locked nav<br>
<br>
<h2>security</h2>
new password <span style="font-size: 10px; color: #888888">8 chars</span><br>
<input type="password" name="accountPassword" onkeydown="showButton()"><br>
confirm password<br>
<input type="password" name="confirmPassword" onkeydown="showButton()"><br>
<input type="hidden" name="oldPassword" value="<?php echo $accountPassword; ?>">
<br>
restricted files/folders<br>
<input type="text" onkeydown="document.settings.changedFileSettings.value='true';showButton()" name="restrictedFiles" value="<?php for($i=0;$i<=count($restrictedFiles)-1;$i++) {echo $restrictedFiles[$i]; if ($i<count($restrictedFiles)-1) {echo ', ';};}; ?>"><br>
banned files/folders<br>
<input type="text" onkeydown="document.settings.changedFileSettings.value='true';showButton()" name="bannedFiles" value="<?php for($i=0;$i<=count($bannedFiles)-1;$i++) {echo $bannedFiles[$i]; if ($i<count($bannedFiles)-1) {echo ', ';};}; ?>"><br>
<input type="hidden" name="changedFileSettings" value="false">
<br>
ip addresses<br>
<input type="text" onkeydown="showButton()" name="allowedIPs" value="<?php for($i=0;$i<=count($allowedIPs)-1;$i++) {echo $allowedIPs[$i]; if ($i<count($allowedIPs)-1) {echo ', ';};}; ?>"><br>
</div>
<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>
<textarea name="plugins" class="plugins" onkeydown="showButton()"><?php
for($i=0;$i<count($plugins);$i++) {
for($j=0;$j<count($plugins[$i]);$j++) {
echo '"'.$plugins[$i][$j].'"';
if ($j<count($plugins[$i])-1) {
echo ',';
};
if (!($i==count($plugins)-1 && $j==count($plugins[$i])-1)) {
echo PHP_EOL;
}
if (($i<count($plugins)-1 && $j==count($plugins[$i])-1)) {
echo "====================".PHP_EOL;
}
}
}
?></textarea>
<br><br>
<h2>style</h2>
theme<br>
<select onchange="selectTheme();showButton()" id="select" name="theme">
<option<?php if ($theme=="default") {echo ' selected';}; ?>>default</option>
<?php
for ($i=0;$i<count($themeArray)-1;$i++) {
if ($theme==$themeArray[$i]) {$optionSelected = ' selected';} else {$optionSelected = '';};
echo '<option'.$optionSelected.'>'.$themeArray[$i].'</option>'.PHP_EOL;
}
?>
</select>
<br><br>
<textarea id="code" name="code">
function findSequence(goal) {
function find(start,history) {
if (start==goal)
return history;
else if (start>goal)
return null;
else
return find(start+5,"("+history+"+5)") ||
find(start*3,"("+history+"*3)");
}
return find(1,"1");
}</textarea>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
readOnly: "nocursor",
theme: "<?php if ($theme=="default") {echo 'icecoder';} else {echo $theme;}; ?>"
});
var input = document.getElementById("select");
function selectTheme() {
var theme = input.options[input.selectedIndex].innerHTML;
if (theme=="default") {theme = "icecoder"};
editor.setOption("theme", theme);
}
var showButton = function() {
document.getElementById('updateButton').style.opacity = 1;
}
var showHideTabs = function() {
document.all ? strCSS = 'rules' : strCSS = 'cssRules';
document.settings.visibleTabs.checked ? document.styleSheets[2][strCSS][5].style['content'] = '"\\21e5"' : document.styleSheets[2][strCSS][5].style['content'] = '" "';
}
var validatePasswords = function() {
<?php if($_SESSION['userLevel']==10) { ?>
if (document.settings.accountPassword.value != 0 && document.settings.accountPassword.value.length<8) {
alert('Please use at least 8 chars in the password');
} else {
if (document.settings.accountPassword.value != document.settings.confirmPassword.value) {
alert('Sorry, your passwords don\'t match')
} else {
document.settings.submit();
}
}
<?php } else { ?>
alert('Sorry, you need to be logged in to change settings');
<?php ;}; ?>
}
</script>
<div class="update" id="updateButton" onClick="validatePasswords()">update</div>
</div>
</form>
</body>
</html>

View File

@@ -1,22 +1,5 @@
<?php
$versionNo = "v 0.6.2";
$codeMirrorDir = "CodeMirror-2.23";
$cMThisVer = 2.23;
$testcMVersion = false; // test if we're using the latest CodeMirror version
$restrictedFiles = array("wp-",".php",".asp",".aspx");
$bannedFiles = array("_coder","wp-",".exe");
$allowedIPs = array("*"); // allowed IPs, * for any
$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"),
array("Clipboard","images/clipboard.png","","javascript:alert('Doesn\'t do anything yet but will be a clipboard for copied text items, up to 100 levels')","_self","")
);
$accountPassword = "";
// ---------------
// End of settings
// ---------------
session_start();
// Function to handle salted hashing
define('SALT_LENGTH',9);
@@ -29,7 +12,107 @@ function generateHash($plainText,$salt=null) {
return $salt.sha1($salt.$plainText);
}
session_start();
// -----------------
// 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;};
@@ -37,6 +120,19 @@ $_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 = "\\";};
@@ -47,6 +143,56 @@ $shortURLStarts = explode($slashType,$_SERVER['DOCUMENT_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'])) {
?>
@@ -58,7 +204,7 @@ if ($accountPassword == "" && isset($_GET['settings'])) {
<link rel="stylesheet" type="text/css" href="coder.css">
</head>
<body>
<body style="background-color: #ffffff">
<div class="screenContainer">
<div class="screenVCenter">
@@ -78,7 +224,7 @@ if ($accountPassword == "" && isset($_GET['settings'])) {
</html>
<?php
} else {
// If the password hasn't been set, set it, but only if we're including
// 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
@@ -101,5 +247,15 @@ if ($accountPassword == "" && isset($_GET['settings'])) {
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

@@ -74,9 +74,14 @@ Class zipIt {
// Trigger the class
$zipItDoZip = new zipIt();
$zipItAddToZip = $zipItDoZip->zipFilesUp($zipItSaveLocation.$zipItFileName);
if ($zipItAddToZip) {echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);</script>';};
if (!$zipItAddToZip) {echo '<script>alert("Could not zip files up!");</script>';};
;};
?>
<script>
top.ICEcoder.serverMessage();
top.ICEcoder.serverQueue("del",0);
</script>
</body>
</html>