Compare commits

...

134 Commits

Author SHA1 Message Date
Matt Pass
2ac674f5c6 Version no update to v0.7.2 2012-06-09 18:44:10 +01:00
Matt Pass
2b5a16be70 FM visually linked to tabs & file setting updates
Changed content indicator in tab doesn't count if undo history is back
to the start
File highlighting now visually linked with the tabs of open docs
Selected file have blue BG, other open files 15% white BG
lastOpenedFiles now previousFiles in a few places
2012-06-09 18:43:57 +01:00
Matt Pass
1fbe9df342 Server DT, last 10 files and improved layout
Layout is now in 3 areas, collapsable too via CSS float
Server name, OS & IP combined
Date & time now shown under server
This is also updated via JS
2012-06-09 18:39:12 +01:00
Matt Pass
1217d2d05e previousFiles & last10Files
renamed lastOpenedFiles to previousFiles
Now also saves the last 10 opened files in new setting
2012-06-09 18:36:42 +01:00
Matt Pass
432795026c renamed lastOpenedFiles to previousFiles 2012-06-09 18:31:44 +01:00
Matt Pass
ab23eaa6ff previousFiles & last10Files
renamed lastOpenedFiles to previousFiles
New setting added - last10Files
2012-06-09 18:30:51 +01:00
Matt Pass
4583c0c713 Class fixes & new class for full screen
.header & .files need top & left CSS props set to avoid centering in
full screen
New class for screenModeIcon
2012-06-07 07:53:07 +01:00
Matt Pass
d3a961f13f Version no update to v 0.7.1 2012-06-07 07:51:45 +01:00
Matt Pass
7a97af2c1d Function to switch screen mode
Handles future proposed spec, plus Moz & Chrome prefixes for usage now
Also changes icon on switching
2012-06-07 07:51:18 +01:00
Matt Pass
750cc59fd5 Screen mode switcher
Small icon now shows in top right to switch between full screen and
restored screen
2012-06-07 07:50:33 +01:00
Matt Pass
dfcf54d412 Spliting IE/FF & Chrome/Safari CSS styles
IE & Firefox have different margin rendering to Chrome
Chrome & Safari hack to provide different margin-top
2012-06-01 17:52:11 +01:00
Matt Pass
5fd1c35d85 Check if container exists before updating
A quick check is performed container exists before attemping update
2012-06-01 17:51:07 +01:00
Matt Pass
21b61bd027 CSS handled differently, updating container moved
Conditional IE hack removed as it needs to apply to Firefox too
Now a CSS margin-top hack relating to Chrome only in CSS file
Moved updating of file, folder, bytes container to editor.php file
(This means it shows correctly on load)
2012-06-01 17:50:18 +01:00
Matt Pass
7fa28c6d8b onLoad, update file, folder, byte display 2012-06-01 17:48:11 +01:00
Matt Pass
97e396794a Server info display showing files, folders, bytes
Files, folders & bytes along with supplementary text established
This is then added to the container on the server info page
2012-06-01 17:18:08 +01:00
Matt Pass
b096ef3606 Files, folders & bytes now counted up
Count of files & folders are running as files & folders are found
Bytes of files also totalled
onLoad, a new function is called to update the server info display
2012-06-01 17:16:46 +01:00
Matt Pass
74b0d86c36 Container to show file & folder count
This is updated once the file manager has loaded
2012-06-01 17:13:08 +01:00
Matt Pass
319c509318 Handling CLEAR when updating lastOpenedFiles
Now drops in correct value, either string array or empty value
2012-06-01 08:26:03 +01:00
Matt Pass
5703a040be lastOpenedFiles handling on no files
CLEAR now sent through as value if no files
No need for else clause now
2012-06-01 08:24:44 +01:00
Matt Pass
6752b8ef50 Adding headings & margin adjusts to server info 2012-06-01 08:23:32 +01:00
Matt Pass
7062560eaa Version number update only 2012-05-31 15:07:12 +01:00
Matt Pass
3be433c910 Visibility of content, padlock dir & IE fixes
Removed comments/dislaimer at top, now use LICENSE file
No longer show or hide content area, it's shown from init load if logged
in
Changed location of packlock icon
IE now using e var for event and not event, fixes JS issue
On refresh and successful login, set visibility & src of content area
(This shows server info upon login)
2012-05-31 15:07:00 +01:00
Matt Pass
bd0969e870 Altered error text & showing content area on load
Better error message to user re public write permissions on config.php
If logged in, now shows content area and therefore server details
2012-05-31 15:01:07 +01:00
Matt Pass
ffbac321a4 Change of padlock image location & IE CSS hack
Padlock now located in parent image folder
IE differs in it's placement of icons, so have conditional IE CSS fix
2012-05-31 14:59:27 +01:00
Matt Pass
222f6589a9 FM icons now work from single sprite sheet
All filetypes now show icons via single sprite sheet
This works via setting a class with pseudo :before containing icon sized
block with icon in BG
blank.gif is used as a sizing placeholder for LI images
Removed a few trailing semi colons
2012-05-31 14:57:59 +01:00
Matt Pass
a2245775a9 Adjustment to location of padlock image 2012-05-31 14:52:34 +01:00
Matt Pass
d594050166 Server & user info screen
CodeMirror instances now on z-index of 1, above body
Body by default now shows server & user details if logged in and no docs
loaded
2012-05-31 14:51:46 +01:00
Matt Pass
2665055558 New FM icons sprite sheet & blank.gif
All file manager icons now in single sprite sheet
These are shown using CSS class pseudo's
blank.gif is needed to easily determin height
2012-05-31 14:37:37 +01:00
Matt Pass
3e41afb0a6 Set value not innerHTML in textarea
Setting innerHTML works fine in Chrome & Firefox but not IE
In order to make IE compatible, made this improvement
(More syntactically appropriate anyway)
2012-05-31 14:35:48 +01:00
Matt Pass
f1ec4a2453 Padlock & refresh icons moved
Moved from FM dir (no longer exists) to parent 'images' dir
2012-05-31 14:32:59 +01:00
Matt Pass
98f1ace910 Removed single FM icons
Removed individual file manager icons from own dir
Icons now show via CSS and spritesheet
2012-05-31 14:32:09 +01:00
Matt Pass
401a3a7abb New initAliases function & scoping of vars
Initialisation of DOM vars now in own function
(This allows Firefox loadstack to work fine & is more efficient too,
only ever called once)
'this' also prefixes the DOM vars initialised, so works in Firefox
2012-05-29 17:53:41 +01:00
Matt Pass
6a0cc816a9 Aliases now initialised in seperate function
Initialise once DOM load complete, prior to 1st setLayout call
2012-05-29 17:51:08 +01:00
Matt Pass
4bafb3aaa1 Need e not event
Wasn't working in Firefox, this fixes issue
2012-05-29 17:50:14 +01:00
Matt Pass
782aac54e4 Logo now is a PNG
Has transparent BG, so can show on white or dark grey BG
2012-05-29 17:11:44 +01:00
Matt Pass
06dd46c24f Logo now is a PNG
Has transparent BG, so can show on white or dark grey BG
2012-05-29 17:11:10 +01:00
Matt Pass
bc50886250 Alterations to the install process 2012-05-29 16:58:02 +01:00
Matt Pass
4264c479ad Version number update to v0.6.9 2012-05-29 16:26:32 +01:00
Matt Pass
b3afe9458e Root files & folders show on load
Makes sense to show files & folders at root level on load, rather than
just show a single folder. This topmost level is now shown on load.
2012-05-29 07:55:48 +01:00
Matt Pass
1382277c74 Default list of excluded files increased
Now by default the excluded files includes anything in the _coder
folder, plus filetypes that shouldn't really be searched within (mainly
media files).
2012-05-28 19:10:29 +01:00
Matt Pass
d1df67338d ICEcoder & user settings now stored in new file
Settings moved from settings.php to this new config.php file
This seperates processing from data storage as ICEcoder evolves
2012-05-28 18:53:40 +01:00
Matt Pass
ccc5b9d30a Settings moved to config.php file, new array & BG
ICEcoder & user settings moved to new file, config.php
Settings.php is now used to handle settings and the seperate file for
storage
New array setting - findFilesExclude defines excluded strings
Settings screen BG is now dark grey not white, matches ICEcoders dark UI
2012-05-28 18:52:20 +01:00
Matt Pass
86142ca5f1 New setting to exclude files/folders from find
A new string array can now be added to settings screen
This array defines strings that are to be excluded from find in
files/folders and their names results when using the Find & Replace
function.
2012-05-28 18:47:51 +01:00
Matt Pass
b55fe4856c CSS compacting & new Erlang Dark theme
New theme added
0px now 0
2012-05-28 07:56:32 +01:00
Matt Pass
d5df587cc3 CSS compacting
0px now 0
2012-05-28 07:55:45 +01:00
Matt Pass
0665d10a7c CSS compacting & robot meta tag
noindex, nofollow robots meta tag
0px now 0
2012-05-28 07:54:00 +01:00
Matt Pass
43f7089106 CSS compacting & JS file sorting
0px now 0
Sorted load order of a few mode files
2012-05-28 07:53:00 +01:00
Matt Pass
fcb7722a55 Removed mode demo pages
Remoevd the demo page for each mode, not necessary
2012-05-28 07:50:57 +01:00
Matt Pass
7c5a005784 Removed unused CodeMirror files
Removed the 2 x keymap files and unused files from util dir
These files are all unused, if users want them, they can download
(Same thinking as only including used 'mode' files)
2012-05-28 07:50:25 +01:00
Matt Pass
abd61689f1 Better handling of changed files
Insetad of notifying user that file they're attempting to save, now they
can revert
This means the file they're trying to save is reverted to the server
file
Changes they have made are copied into a new file
User can optionally cancel to avoid this
2012-05-26 22:25:12 +01:00
Matt Pass
acbe46b013 Version No & CodeMirror Version No Update 2012-05-26 22:22:45 +01:00
Matt Pass
bbf169907a Update CodeMirror to v.2.25
Update to latest version
2012-05-26 22:22:06 +01:00
Matt Pass
1d3af5c62d Remove CodeMirror 2.24
Update to newer version 2.25
2012-05-26 22:20:40 +01:00
Matt Pass
d095e6a5fe CoffeeScript Support & Update Lang on Tab Switch
CoffeeScript is now supported as a language by ICEcoder
When you switch tabs, the cursor display info also now changes
2012-05-25 17:44:12 +01:00
Matt Pass
96df3ac91b Shortening of hex codes & swapping tab text cols
Hex codes shortened if poss (ie, #888888 becomes #888 and #ff0000
becomes #f00)
Swapped text colour on tabs, selected now has black text, others white
text
2012-05-25 17:03:12 +01:00
Matt Pass
38fe4fd85e Merge branch 'master' of https://github.com/mattpass/ICEcoder 2012-05-25 15:29:20 +01:00
Matt Pass
95ac9b50e0 Republish only 2012-05-25 15:26:43 +01:00
Matt Pass
1f26ddaf3d Another slight format fix 2012-05-24 18:23:48 +01:00
Matt Pass
64231d7f01 Minor format fixes 2012-05-24 18:22:09 +01:00
Matt Pass
656c10e5cf Added MIT license with note about sub-licenses 2012-05-24 18:18:03 +01:00
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
102 changed files with 2784 additions and 2291 deletions

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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

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

View File

@@ -1,4 +1,4 @@
// CodeMirror version 2.23
// CodeMirror version 2.25
//
// All functions that need access to the editor's state live inside
// the CodeMirror function. Below that, at the bottom of the file,
@@ -41,7 +41,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;
@@ -80,7 +80,7 @@ var CodeMirror = (function() {
// Variables used by startOperation/endOperation to track what
// happened during the operation.
var updateInput, userSelChange, changes, textChanged, selectionChanged, leaveInputAlone,
gutterDirty, callbacks;
gutterDirty, callbacks, maxLengthChanged;
// Current visible range (may be bigger than the view window).
var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0;
// bracketHighlighted is used to remember that a bracket has been
@@ -98,7 +98,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 +117,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 +166,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 +319,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 +344,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");
@@ -364,6 +372,7 @@ var CodeMirror = (function() {
return;
case 2:
if (start) setCursor(start.line, start.ch, true);
setTimeout(focusInput, 20);
return;
}
// For button 1, if it was clicked inside the editor
@@ -385,20 +394,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 +458,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 +468,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 +484,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 +543,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;
}
@@ -574,7 +596,7 @@ var CodeMirror = (function() {
if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return;
var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode");
if (window.opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;}
if (((window.opera && !e.which) || khtml) && handleKeyBinding(e)) return;
if (((window.opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) return;
var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) {
if (mode.electricChars.indexOf(ch) > -1)
@@ -648,8 +670,8 @@ var CodeMirror = (function() {
if (suppressEdits) return;
var recomputeMaxLength = false, maxLineLength = maxLine.length;
if (!options.lineWrapping)
doc.iter(from.line, to.line, function(line) {
if (line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
doc.iter(from.line, to.line + 1, function(line) {
if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;}
});
if (from.line != to.line || newText.length > 1) gutterDirty = true;
@@ -696,29 +718,21 @@ 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) {
if (!line.hidden && l.length > maxLineLength) {
maxLine = l; maxLineLength = l.length; maxWidth = null;
recomputeMaxLength = false;
}
});
if (recomputeMaxLength) {
maxLineLength = 0; maxLine = ""; maxWidth = null;
doc.iter(0, doc.size, function(line) {
var l = line.text;
if (l.length > maxLineLength) {
maxLineLength = l.length; maxLine = l;
}
});
}
if (recomputeMaxLength) maxLengthChanged = true;
}
// Add these lines to the work array, so that they will be
@@ -750,6 +764,18 @@ var CodeMirror = (function() {
if (scroller.clientHeight)
code.style.height = (doc.height * textHeight() + 2 * paddingTop()) + "px";
}
function computeMaxLength() {
var maxLineLength = 0;
maxLine = ""; maxWidth = null;
doc.iter(0, doc.size, function(line) {
var l = line.text;
if (!line.hidden && l.length > maxLineLength) {
maxLineLength = l.length; maxLine = l;
}
});
maxLengthChanged = false;
}
function replaceRange(code, from, to) {
from = clipPos(from);
@@ -837,7 +863,8 @@ var CodeMirror = (function() {
else if (overwrite && posEq(sel.from, sel.to))
sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))};
replaceSelection(text.slice(same), "end");
prevInput = text;
if (text.length > 1000) { input.value = prevInput = ""; }
else prevInput = text;
return true;
}
function resetInput(user) {
@@ -874,8 +901,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 +918,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 +952,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 +1136,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 +1219,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 +1386,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() {
@@ -1465,6 +1501,16 @@ var CodeMirror = (function() {
return changeLine(handle, function(line, no) {
if (line.hidden != hidden) {
line.hidden = hidden;
if (!options.lineWrapping) {
var l = line.text;
if (hidden && l.length == maxLine.length) {
maxLengthChanged = true;
}
else if (!hidden && l.length > maxLine.length) {
maxLine = l; maxWidth = null;
maxLengthChanged = false;
}
}
updateLineHeight(line, hidden ? 0 : 1);
var fline = sel.from.line, tline = sel.to.line;
if (hidden && (fline == no || tline == no)) {
@@ -1506,8 +1552,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 +1575,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 +1829,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;
@@ -1820,6 +1863,7 @@ var CodeMirror = (function() {
}
function endOperation() {
var reScroll = false, updated;
if (maxLengthChanged) computeMaxLength();
if (selectionChanged) reScroll = !scrollCursorIntoView();
if (changes.length) updated = updateDisplay(changes, true);
else {
@@ -1856,6 +1900,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 +1926,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 +1957,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 +1977,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 +2035,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 +2056,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 +2091,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 +2461,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 +2491,52 @@ 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);
var cut = wrapAt - outPos;
span_(window.opera ? text.slice(cut, cut + 1) : text.slice(cut), style);
html.push("</span>");
if (window.opera) span_(text.slice(cut + 1), style);
wrapAt--;
outPos += l;
} else {
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 +2622,7 @@ var CodeMirror = (function() {
},
insertHeight: function(at, lines, height) {
this.height += height;
this.lines.splice.apply(this.lines, [at, 0].concat(lines));
this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this;
},
iterN: function(at, n, op) {
@@ -2701,33 +2788,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 +2879,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 +2894,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.

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

@@ -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

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

View File

@@ -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

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

View File

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

View File

@@ -54,7 +54,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
}
else if (/\d/.test(ch)) {
else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
return ret("number", "number");
}
@@ -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,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,21 @@
.cm-s-erlang-dark { background: #002240; color: white; }
.cm-s-erlang-dark div.CodeMirror-selected { background: #b36539 !important; }
.cm-s-erlang-dark .CodeMirror-gutter { background: #002240; border-right: 1px solid #aaa; }
.cm-s-erlang-dark .CodeMirror-gutter-text { color: #d0d0d0; }
.cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-erlang-dark span.cm-atom { color: #845dc4; }
.cm-s-erlang-dark span.cm-attribute { color: #ff80e1; }
.cm-s-erlang-dark span.cm-bracket { color: #ff9d00; }
.cm-s-erlang-dark span.cm-builtin { color: #eeaaaa; }
.cm-s-erlang-dark span.cm-comment { color: #7777ff; }
.cm-s-erlang-dark span.cm-def { color: #ee77aa; }
.cm-s-erlang-dark span.cm-error { color: #9d1e15; }
.cm-s-erlang-dark span.cm-keyword { color: #ffee80; }
.cm-s-erlang-dark span.cm-meta { color: #50fefe; }
.cm-s-erlang-dark span.cm-number { color: #ffd0d0; }
.cm-s-erlang-dark span.cm-operator { color: #dd1111; }
.cm-s-erlang-dark span.cm-string { color: #3ad900; }
.cm-s-erlang-dark span.cm-tag { color: #9effff; }
.cm-s-erlang-dark span.cm-variable { color: #50fe50; }
.cm-s-erlang-dark span.cm-variable-2 { color: #ee00ee; }

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;}

30
LICENSE.md Normal file
View File

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

View File

@@ -1,27 +1,65 @@
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 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/config.php file
```
####Step 3: Start coding
```
Visit the sub-dir URL in your browser and enter a password
Now you're setup, auto-logged in 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,40 +1,95 @@
<!DOCTYPE html>
<html>
<html style="margin: 0">
<head>
<title>CodeMirror 2: ICE Coders Editor of Choice</title>
<?php include("lib/settings.php");?>
<link rel="stylesheet" href="<?php echo $codeMirrorDir; ?>/lib/codemirror.css">
<script src="<?php echo $codeMirrorDir; ?>/lib/codemirror.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/xml/xml.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/javascript/javascript.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/css/css.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/clike/clike.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/css/css.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/javascript/javascript.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/xml/xml.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/coffeescript/coffeescript.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/php/php.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/mode/ruby/ruby.js"></script>
<script src="<?php echo $codeMirrorDir; ?>/lib/util/searchcursor.js"></script>
<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 {position: absolute; width: 0; background-color: #fff; top: 0px; z-index: 1}
.CodeMirror-scroll {width: 100px; height: 100px;}
.cm-s-visible {display: block; top: 0px}
.cm-s-visible {display: block; top: 0}
.cm-s-hidden {display: none; top: 4000px}
.cm-s-activeLine {background: #002 !important;}
// Make sure this next one remains the 5th item, updated with JS
.cm-tab:after {position: relative; display: inline-block; width: 0; left: -1.4em; overflow: visible; color: #aaa; content: "<?php if ($visibleTabs) {?>\21e5<?;};?>";}
span.CodeMirror-matchhighlight {background: #555}
.CodeMirror-focused span.CodeMirror-matchhighlight {color: #000; background: #555; !important}
</style>
</head>
<body onKeyDown="return top.ICEcoder.interceptKeys('content', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<body onLoad="top.ICEcoder.updateFileFolderCount()" style="color: #fff; margin: 0" onKeyDown="return top.ICEcoder.interceptKeys('content', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<div style="margin: 32px 43px; font-family: arial; font-size: 10px; color: #dddddd">
<?php if($_SESSION['userLevel'] == 10) {
echo '<div style="float: left; margin-right: 50px">'.PHP_EOL;
echo '<h2 style="color: rgba(0,198,255,0.7)">server</h2>'.PHP_EOL;
echo '<span style="color:#888">Server name, OS & IP:</span><br>'.PHP_EOL;
echo $_SERVER['SERVER_NAME'].' &nbsp;&nbsp; '.$_SERVER['SERVER_SOFTWARE'].' &nbsp;&nbsp; '.$_SERVER['SERVER_ADDR'].'<br><br>'.PHP_EOL;
echo '<span style="color:#888">Root:</span><br>'.PHP_EOL;
echo $_SERVER['DOCUMENT_ROOT'].'<br><br>'.PHP_EOL;
echo '<span style="color:#888">PHP version:</span><br>'.PHP_EOL;
echo phpversion().'<br><br>'.PHP_EOL;
echo '<span style="color:#888">File & folder count:</span><br>'.PHP_EOL;
echo '<div id="fileFolderCounts"></div><br>'.PHP_EOL;
echo '<span style="color:#888">Date & time:</span><br>'.PHP_EOL;
echo '<span id="serverDT"></span><br><br><br>'.PHP_EOL;
echo '</div>'.PHP_EOL;
echo '<div style="float: left">'.PHP_EOL;
echo '<h2 style="color: rgba(0,198,255,0.7)">files</h2>'.PHP_EOL;
echo '<span style="color:#888">Last 10 files opened:</span><br>'.PHP_EOL;
echo str_replace("|","/",str_replace(",","<br>",$last10Files)).'<br><br><br>'.PHP_EOL;
echo '</div>'.PHP_EOL;
echo '<div style="clear: both">'.PHP_EOL;
echo '<h2 style="color: rgba(0,198,255,0.7)">your device</h2>'.PHP_EOL;
echo '<span style="color:#888">Browser:</span><br>'.PHP_EOL;
echo $_SERVER['HTTP_USER_AGENT'].'<br><br>'.PHP_EOL;
echo '<span style="color:#888">Your IP:</span><br>'.PHP_EOL;
echo $_SERVER['REMOTE_ADDR'].PHP_EOL;
echo '</div>'.PHP_EOL;
}; ?>
<script>
var nDT=<?php echo time()*1000;?>;
setInterval(function(){
var s=(new Date(nDT+=1000)+'').split(' '),
d=s[2]*1,
t=s[4].split(':'),
p=t[0]>11?'pm':'am',
e=d%20==1|d==31?'st':d%20==2?'nd':d%20==3?'rd':'th';
t[0]=--t[0]%12+1;
document.getElementById('serverDT').innerHTML=[s[0],d+e,s[1],s[3],t.join(':')+p].join(' ');
},1000);
</script>
</div>
<script>
function createNewCMInstance(num) {
var fileName = top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1];
var codeFold = CodeMirror.newFoldFunction(CodeMirror.tagRangeFinder,'<span style=\"display: inline-block; width: 13px; height: 13px; background-color: #bb0000; color: #ffffff; text-align: center; cursor: pointer\"><span style="position: relative; top: -1px">+</span></span> %N%');
var codeFold_JS_PHP = CodeMirror.newFoldFunction(CodeMirror.braceRangeFinder,'<span style=\"display: inline-block; width: 13px; height: 13px; background-color: #bb0000; color: #ffffff; text-align: center; cursor: pointer\"><span style="position: relative; top: -1px">+</span></span> %N%');
var codeFold = CodeMirror.newFoldFunction(CodeMirror.tagRangeFinder,'<span style=\"display: inline-block; width: 13px; height: 13px; background-color: #b00; color: #fff; text-align: center; cursor: pointer\"><span style="position: relative; top: -1px">+</span></span> %N%');
var codeFold_JS_Coffee_PHP_Ruby = CodeMirror.newFoldFunction(CodeMirror.braceRangeFinder,'<span style=\"display: inline-block; width: 13px; height: 13px; background-color: #b00; color: #fff; text-align: center; cursor: pointer\"><span style="position: relative; top: -1px">+</span></span> %N%');
window['cM'+num] = CodeMirror(document.body, {
mode: "application/x-httpd-php",
theme: "icecoder",
lineNumbers: true,
lineWrapping: true,
indentUnit: 4,
@@ -68,8 +123,8 @@ function createNewCMInstance(num) {
}
},
onKeyEvent: function(instance, e) {
top.ICEcoder.redoChangedContent(event);
top.ICEcoder.findReplace('find',true);
top.ICEcoder.redoChangedContent(e);
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 +167,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(".coffee") == -1 && fileName.indexOf(".php") && fileName.indexOf(".rb") == -1) ? codeFold : codeFold_JS_Coffee_PHP_Ruby,
extraKeys: {
"Tab": function(cm) {CodeMirror.commands[top.tabsIndent ? "defaultTab" : "insertTab"](cm);},
"Shift-Tab": "indentLess"
}
});
// Now create the active line for this CodeMirror object

View File

@@ -54,7 +54,7 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
if ($serverType=="Linux") {
$chmodInfo = substr(sprintf('%o', fileperms($link)), -4);
$fileAtts = '<span style="color: #888888; font-size: 8px">'.$chmodInfo.'</span>';
$fileAtts = '<span style="color: #888; font-size: 8px">'.$chmodInfo.'</span>';
}
$fileManager = "<ul class=\"fileManager\">";
$fileManager .= "<li class=\"pft-directory\"><a href=\"#\" onMouseOver=\"top.ICEcoder.overFileFolder('folder','$link')\" onMouseOut=\"top.ICEcoder.overFileFolder('folder','')\" style=\"position: relative; left:-22px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span id=\"|\">/ [ROOT]</span> ".$fileAtts."</a>";
@@ -74,6 +74,7 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
if( $this_file != "." && $this_file != ".." && $bannedFile == false) {
if( is_dir("$directory/$this_file") ) {
// Directory
$dirCount++;
$dirRep = str_replace("\\","/",$directory);
$link = str_replace("[link]", "$dirRep/" . urlencode($this_file), $return_link);
$link = str_replace("//","/",$link);
@@ -88,17 +89,19 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
$fileAtts = "";
if ($serverType=="Linux") {
$chmodInfo = substr(sprintf('%o', fileperms($link)), -4);
$fileAtts = '<span style="color: #888888; font-size: 8px">'.$chmodInfo.'</span>';
$fileAtts = '<span style="color: #888; font-size: 8px">'.$chmodInfo.'</span>';
}
if ($_SESSION['userLevel'] == 10 || ($_SESSION['userLevel'] < 10 && $restrictedFile==false)) {
$fileManager .= "<li class=\"pft-directory\"><a href=\"#\" onMouseOver=\"top.ICEcoder.overFileFolder('folder','$link')\" onMouseOut=\"top.ICEcoder.overFileFolder('folder','')\" style=\"position: relative; left:-22px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span id=\"".str_replace("/","|",str_replace($docRoot,"",$link))."\">" . htmlspecialchars($this_file) . "</span> ".$fileAtts."</a>";
$fileManager .= fileManager_dir("$directory/$this_file", $return_link , false);
$fileManager .= "</li>";
} else {
$fileManager .= "<li class=\"pft-directory\" style=\"cursor: pointer\"><span style=\"position: relative; left:-22px; color: #888888\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [HIDDEN] ".$fileAtts."</span></li>";
$fileManager .= "<li class=\"pft-directory\" style=\"cursor: pointer\"><span style=\"position: relative; left:-22px; color: #888\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [HIDDEN] ".$fileAtts."</span></li>";
}
} else {
// File
$fileCount++;
$fileBytes+=filesize($link);
// Get extension (prefix 'ext-' to prevent invalid classes from extensions that begin with numbers)
$ext = "ext-" . substr($this_file, strrpos($this_file, ".") + 1);
$dirRep = str_replace("\\","/",$directory);
@@ -115,19 +118,24 @@ function fileManager_dir($directory, $return_link, $first_call=true) {
$fileAtts = "";
if ($serverType=="Linux") {
$chmodInfo = substr(sprintf('%o', fileperms($link)), -4);
$fileAtts = '<span style="color: #888888; font-size: 8px">'.$chmodInfo.'</span>';
$fileAtts = '<span style="color: #888; font-size: 8px">'.$chmodInfo.'</span>';
}
$fileManager .= "<li class=\"pft-file " . strtolower($ext) . "\"><a nohref onMouseOver=\"top.ICEcoder.overFileFolder('file','$link')\" onMouseOut=\"top.ICEcoder.overFileFolder('file','')\" style=\"position: relative; left:-22px; cursor: pointer\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span id=\"".str_replace("/","|",str_replace($docRoot,"",$link))."\">" . htmlspecialchars($this_file) . "</span> ".$fileAtts."</a></li>";
} else {
$fileAtts = "<img src=\"images/file-manager-icons/padlock.png\" style=\"cursor: pointer\" onClick=\"alert('Sorry, you need higher admin level rights to view.')\">";
$fileManager .= "<li class=\"pft-file " . strtolower($ext) . "\" style=\"cursor: default\"><span style=\"position: relative; left:-22px; color: #888888\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [HIDDEN] ".$fileAtts."</span></li>";
$fileAtts = "<img src=\"images/padlock.png\" style=\"cursor: pointer\" onClick=\"alert('Sorry, you need higher admin level rights to view.')\">";
$fileManager .= "<li class=\"pft-file " . strtolower($ext) . "\" style=\"cursor: default\"><span style=\"position: relative; left:-22px; color: #888\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [HIDDEN] ".$fileAtts."</span></li>";
}
}
}
}
$fileManager .= "</ul>";
}
return $fileManager;
$varOutput = "";
if ($dirCount) {$varOutput .= "top.ICEcoder.dirCount+=".$dirCount.";".PHP_EOL;};
if ($fileCount) {$varOutput .= "top.ICEcoder.fileCount+=".$fileCount.";".PHP_EOL;};
if ($fileBytes) {$varOutput .= "top.ICEcoder.fileBytes+=".$fileBytes.";".PHP_EOL;};
// After outputting the fileManager, output the JS vars, but only the first time
return $fileManager."<script>if (top.ICEcoder.dirCount==0) {".PHP_EOL.$varOutput."}</script>";
}
// For PHP4 compatibility
@@ -142,15 +150,23 @@ 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">
<script src="lib/coder.js" type="text/javascript"></script>
</head>
<body onLoad="top.ICEcoder.fileManager()" onDblClick="top.ICEcoder.openFile()" onKeyDown="return top.ICEcoder.interceptKeys('files', event);" onKeyUp="top.ICEcoder.resetKeys(event);">
<div onClick="top.ICEcoder.refreshFileManager()" class="refresh"><img src="images/refresh.png"></div>
<script>
top.ICEcoder.dirCount = 0;
top.ICEcoder.fileCount = 0;
top.ICEcoder.fileBytes = 0;
</script>
<?php
echo fileManager($_SERVER['DOCUMENT_ROOT'], "[link]");
?>

Binary file not shown.

BIN
images/blank.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 651 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 734 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 633 B

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 591 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

BIN
images/full-screen.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 B

BIN
images/ice-coder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

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

BIN
images/padlock-disabled.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 752 B

After

Width:  |  Height:  |  Size: 752 B

BIN
images/refresh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
images/restored-screen.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 B

109
index.php
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;
}
}
@@ -24,25 +24,39 @@ if ($testcMVersion) {
<html>
<head>
<title>ICE Coder - <?php echo $versionNo;?></title>
<meta name="robots" content="noindex, nofollow">
<link rel="stylesheet" type="text/css" href="lib/coder.css">
<script>
shortURLStarts = "<?php echo $shortURLStarts;?>";
theme = "<?php if ($theme=="default") {echo 'icecoder';} else {echo $theme;};?>";
tabsIndent = <?php if ($tabsIndent) {echo 'true';} else {echo 'false';};?>;
<?
$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.";
}
}
}
previousFiles = [<?php
if ($previousFiles!="" && $_SESSION['userLevel'] == 10) {
$openFilesArray = explode(",",$previousFiles);
for ($i=0;$i<count($openFilesArray);$i++) {
echo "'".$openFilesArray[$i]."'";
if ($i<count($openFilesArray)-1) {echo ",";};
}
}
?>];
</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,55 +71,51 @@ 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">
<div class="version"><?php echo $versionNo;?></div><img src="images/full-screen.gif" id="screenMode" class="screenModeIcon" onClick="top.ICEcoder.fullScreenSwitcher()">
<img src="images/ice-coder.png" class="logo" onClick="ICEcoder.helpScreen('show')" onContextMenu="ICEcoder.settingsScreen('show')">
</div>
<div id="files" class="files" onMouseOver="ICEcoder.changeFilesW('expand')" onMouseOut="ICEcoder.changeFilesW('contract'); top.document.getElementById('fileMenu').style.display='none';">
<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>
<a nohref title="New Folder" onClick="ICEcoder.fMIcon('newFolder')"><img src="images/new-folder.png" alt="New Folder" id="fMNewFolder" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
<a nohref title="Delete" onClick="ICEcoder.fMIcon('delete')"><img src="images/delete.png" alt="Delete" id="fMDelete" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
<a nohref title="Rename" onClick="ICEcoder.fMIcon('rename')"><img src="images/rename.png" alt="Rename" id="fMRename" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
<a nohref title="View" onClick="ICEcoder.fMIcon('view')"><img src="images/view.png" alt="View" id="fMView" style="margin: 9px 0px 0px 5px; opacity: 0.3"></a>
</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>
<a nohref title="New File" onClick="ICEcoder.fMIcon('newFile')"><img src="images/new-file.png" alt="New File" id="fMNewFile" style="margin: 8px 0 0 10px; opacity: 0.3"></a>
<a nohref title="New Folder" onClick="ICEcoder.fMIcon('newFolder')"><img src="images/new-folder.png" alt="New Folder" id="fMNewFolder" style="margin: 9px 0 0 5px; opacity: 0.3"></a>
<a nohref title="Delete" onClick="ICEcoder.fMIcon('delete')"><img src="images/delete.png" alt="Delete" id="fMDelete" style="margin: 9px 0 0 5px; opacity: 0.3"></a>
<a nohref title="Rename" onClick="ICEcoder.fMIcon('rename')"><img src="images/rename.png" alt="Rename" id="fMRename" style="margin: 9px 0 0 5px; opacity: 0.3"></a>
<a nohref title="View" onClick="ICEcoder.fMIcon('view')"><img src="images/view.png" alt="View" id="fMView" style="margin: 9px 0 0 5px; opacity: 0.3"></a>
</div>
<a nohref style="cursor: pointer" onClick="ICEcoder.lockUnlockNav()"><img src="images/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 +133,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>
@@ -159,6 +175,7 @@ echo 'fullPath = "'.$docRoot.'";'.PHP_EOL;
</div>
<script>
ICEcoder.initAliases();
ICEcoder.setLayout('dontSetEditor');
</script>

View File

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

View File

@@ -1,9 +1,3 @@
// ICE coder by Matt Pass
// Free to use it for your own purposes, commercial or not, just let me know of any cool uses or customisations. :)
// No warranty or liability accepted for anything, all responsibility of use is your own.
// Latest version: https://github.com/mattpass/ICEcoder
// Twitter: @mattpass
var ICEcoder = {
// Define settings
filesW: 250, // Initial width of the files pane
@@ -16,6 +10,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,24 +20,36 @@ 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"];
// Set our aliases
initAliases: function() {
var aliasArray = ["header","files","account","accountLogin","fmLock","filesFrame","editor","tabsBar","findBar","content","footer","nestValid","nestDisplay","charDisplay"];
// Create our ID aliases
for (var i=0;i<aliasArray.length;i++) {
ICEcoder[aliasArray[i]] = top.document.getElementById(aliasArray[i]);
}
},
// On load, set the layout and get the nest location
init: function(login) {
// Set layout & the nest location
ICEcoder.setLayout();
// 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
@@ -55,15 +62,15 @@ var ICEcoder = {
// Apply sizes to various elements of the page
headerH = 40, footerH = 30, accountH = 50, tabsBarH = 21, findBarH = 28;
header.style.width = tabsBar.style.width = findBar.style.width = winW + "px";
files.style.width = editor.style.left = this.filesW + "px";
account.style.height = accountH + "px";
fmLock.style.marginLeft = (this.filesW-27) + "px";
filesFrame.style.height = (winH-headerH-accountH-footerH) + "px";
this.header.style.width = this.tabsBar.style.width = this.findBar.style.width = winW + "px";
this.files.style.width = this.accountLogin.style.width = this.editor.style.left = this.filesW + "px";
this.account.style.height = this.accountH + "px";
this.fmLock.style.marginLeft = (this.filesW-27) + "px";
this.filesFrame.style.height = (winH-headerH-accountH-footerH) + "px";
// If we need to set the editor sizes
if (!dontSetEditor) {
editor.style.width = ICEcoder.content.style.width = (winW-this.filesW) + "px";
this.editor.style.width = ICEcoder.content.style.width = (winW-this.filesW) + "px";
ICEcoder.content.style.height = (winH-headerH-footerH-tabsBarH-findBarH) + "px";
// Resize the CodeMirror instances to match the window size
@@ -79,12 +86,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, CoffeeScript 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(".coffee")<0 && fileName.indexOf(".rb")<0 && 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 +119,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 +162,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 +175,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(".coffee")<0 && fileName.indexOf(".rb")<0 && fileName.indexOf(".css")<0&&
(nestCheck.indexOf("include(")==-1)&&(nestCheck.indexOf("include_once(")==-1)&&
(nestCheck.indexOf("<html")>-1||nestCheck.indexOf("<body")>-1)) {
// Then for all the array items, output as the nest display
for (var i=0;i<ICEcoder.htmlTagArray.length;i++) {
@@ -237,12 +245,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 +281,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 +289,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,31 +340,50 @@ 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);
// Finally, update the cursor display
top.ICEcoder.getCaretPosition();
top.ICEcoder.updateCharDisplay();
}
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 cM, bgVPos, tColor, fileLink;
cM = ICEcoder.getcMInstance();
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;
document.getElementById('tab'+i).style.backgroundPosition = "0px "+bgVPos+"px";
if (document.getElementById('closeTabButton'+i)) {
ICEcoder.changedContent[i-1]==1 && cM.historySize().undo>0 ? document.getElementById('closeTabButton'+i).style.backgroundColor = "#b00" : document.getElementById('closeTabButton'+i).style.backgroundColor = "rgba(255,255,255,0.3)";
}
i==selectedTab ? tColor = "#000" : tColor = "#fff";
if ("undefined" != typeof top.ICEcoder.openFiles[i-1] && top.ICEcoder.openFiles[i-1] != "/[NEW]") {
fileLink = top.ICEcoder.filesFrame.contentWindow.document.getElementById(top.ICEcoder.openFiles[i-1].replace(/\//g,"|"));
i==selectedTab ? fileLink.style.backgroundColor = "#4499dd" : fileLink.style.backgroundColor = "rgba(255,255,255,0.15)";
}
document.getElementById('tab'+i).style.color = tColor;
i==selectedTab ? bgVPos = -22 : bgVPos = 0;
document.getElementById('tab'+i).style.backgroundPosition = "0 "+bgVPos+"px";
}
ICEcoder.changedContent[selectedTab-1]==1 ? top.ICEcoder.fMIconVis('fMSave',1) : top.ICEcoder.fMIconVis('fMSave',0.3);
},
@@ -370,7 +402,6 @@ var ICEcoder = {
cM = ICEcoder.getcMInstance('new');
ICEcoder.switchTab(ICEcoder.openFiles.length);
ICEcoder.content.style.visibility='visible';
cM.setLineClass(ICEcoder['cMActiveLine'+ICEcoder.selectedTab], null);
ICEcoder['cMActiveLine'+ICEcoder.selectedTab] = cM.setLineClass(0, "cm-s-activeLine");
@@ -385,7 +416,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 +426,8 @@ var ICEcoder = {
// Add a new value ready to indicate if this content has been changed
top.ICEcoder.changedContent.push(0);
top.ICEcoder.setPreviousFiles();
},
// Create a new tab for a file
@@ -405,7 +438,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,12 +450,12 @@ 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) {
ICEcoder.nestValid.style.backgroundColor="#00bb00";
// 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(".coffee")>0||fileName.indexOf(".rb")>0||fileName.indexOf(".css")>0) {
ICEcoder.nestValid.style.backgroundColor="#0b0";
ICEcoder.nestValid.innerHTML = "Nesting OK";
} else {
ICEcoder.nestValid.style.backgroundColor="#ff0000";
ICEcoder.nestValid.style.backgroundColor="#f00";
ICEcoder.nestValid.innerHTML = "Nesting Broken";
}
},
@@ -462,17 +495,20 @@ 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(".coffee")>0) {caretLocType="CoffeeScript"};
if (fileName.indexOf(".rb")>0) {caretLocType="Ruby"};
if (fileName.indexOf(".css")>0) {caretLocType="CSS"};
ICEcoder.caretLocType = caretLocType;
// If we're in a JS or PHP code block, add that to the nest display
if (caretLocType=="JavaScript"||caretLocType=="PHP") {
// If we're in a JS, CoffeeScript PHP or Ruby code block, add that to the nest display
if (caretLocType=="JavaScript"||caretLocType=="CoffeeScript"||caretLocType=="PHP"||caretLocType=="Ruby") {
ICEcoder.nestDisplay.innerHTML += " &gt; " + caretLocType;
}
},
@@ -480,7 +516,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,36 +542,35 @@ 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
if (ICEcoder.openFiles.length==0) {
top.document.getElementById('content').style.visibility = "hidden";
top.ICEcoder.fMIconVis('fMView',0.3);
} else {
// Switch the mode & the tab
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.setPreviousFiles();
}
// Lastly, stop it from trying to also switch tab
top.ICEcoder.canSwitchTabs=false;
@@ -558,7 +593,7 @@ var ICEcoder = {
while (1) {
if (node != null) {
if (node.tagName == "UL") {
var d = (node.style.display == "none")
var d = (node.style.display == "none");
node.style.display = (d) ? "block" : "none";
this.className = (d) ? "open" : "closed";
return false;
@@ -578,6 +613,8 @@ var ICEcoder = {
}
}
}
aMenus[0].childNodes[0].className = "open";
aMenus[0].childNodes[1].style.display = "block";
return false;
},
@@ -649,19 +686,32 @@ 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";
var isOpen;
top.ICEcoder.openFiles.indexOf(file.id.replace(/\|/g,"/")) > -1 ? isOpen = true : isOpen = false;
if (top.ICEcoder.openFiles[top.ICEcoder.selectedTab-1] == file.id.replace(/\|/g,"/")) {
file.style.backgroundColor="#4499dd";
} else {
if (action=="select") {
file.style.backgroundColor="#888";
} else {
isOpen ? file.style.backgroundColor = "rgba(255,255,255,0.15)" : file.style.backgroundColor="transparent";
}
}
action == "select" ? file.style.color="#fff" : file.style.color="#eee";
},
// Create a new file (start & instant save)
@@ -733,8 +783,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 +799,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.setPreviousFiles();
}
},
@@ -777,12 +829,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 +868,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 +928,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 +943,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 +965,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 +992,18 @@ 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('.coffee')>0) {
cM.setOption("mode","coffeescript");
} 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");
}
}
},
@@ -923,7 +1013,7 @@ var ICEcoder = {
lockIcon = top.document.getElementById('fmLock');
ICEcoder.lockedNav ? ICEcoder.lockedNav = false : ICEcoder.lockedNav = true;
ICEcoder.lockedNav ? lockIcon.src="images/file-manager-icons/padlock.png" : lockIcon.src="images/file-manager-icons/padlock-disabled.png";
ICEcoder.lockedNav ? lockIcon.src="images/padlock.png" : lockIcon.src="images/padlock-disabled.png";
},
// Determine the CodeMirror instance we're using on demand
@@ -939,24 +1029,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 +1058,28 @@ var ICEcoder = {
lCLen = lineContent.length;
adjustCursor = 3;
if (ICEcoder.caretLocType=="JavaScript"||ICEcoder.caretLocType=="PHP"||ICEcoder.caretLocType=="CSS") {
if (ICEcoder.caretLocType=="JavaScript"||ICEcoder.caretLocType=="CoffeeScript"||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") {
if (ICEcoder.caretLocType=="CSS"||ICEcoder.caretLocType=="CoffeeScript") {
lineContent.slice(0,3)!="/* " ? cM.setLine(linePos, "/* " + lineContent + " */") : cM.setLine(linePos, lineContent.slice(3,lCLen).slice(0,lCLen-5));
if (lineContent.slice(0,3)=="/* ") {adjustCursor = -adjustCursor};
} else if (ICEcoder.caretLocType=="Ruby") {
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};
@@ -1001,11 +1105,11 @@ var ICEcoder = {
var tempX, tempY, scrollTop, IE;
IE = document.all ? true : false;
if (!IE) {document.captureEvents(Event.MOUSEMOVE)};
if (IE) {
top.ICEcoder.mouseX = event.clientX + document.body.scrollLeft;
top.ICEcoder.mouseY = event.clientY + document.body.scrollTop;
top.ICEcoder.mouseX = e.clientX + document.body.scrollLeft;
top.ICEcoder.mouseY = e.clientY + document.body.scrollTop;
} else {
document.captureEvents(Event.MOUSEMOVE);
top.ICEcoder.mouseX = e.pageX;
top.ICEcoder.mouseY = e.pageY;
}
@@ -1034,7 +1138,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 +1310,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]);
}
@@ -1236,13 +1343,13 @@ var ICEcoder = {
ICEcoder.serverQueueItems.splice(1,ICEcoder.serverQueueItems.length);
}
top.document.getElementById('loadingMask').style.visibility = "hidden";
top.ICEcoder.serverMessage('<b style="color: #dd0000">Cancelled tasks</b>');
top.ICEcoder.serverMessage('<b style="color: #d00">Cancelled tasks</b>');
setTimeout(function() {top.ICEcoder.serverMessage();},2000);
},
// 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 +1392,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 +1401,160 @@ 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 previousFiles in the settings file
setPreviousFiles: function() {
var previousFiles;
previousFiles = "";
// Generate a comma seperated list
for (var i=0;i<top.ICEcoder.openFiles.length;i++) {
if (top.ICEcoder.openFiles[i]!="" && top.ICEcoder.openFiles[i].indexOf("[NEW]")==-1) {
previousFiles += top.ICEcoder.openFiles[i].replace(/\//g,"|");
if (i<top.ICEcoder.openFiles.length-1) {previousFiles += ","};
}
}
if (previousFiles=="") {previousFiles="CLEAR"};
// Then send through to the settings page to update setting
top.ICEcoder.serverQueue("add","lib/settings.php?saveFiles="+previousFiles);
},
// Opens the last files we had open
autoOpenFiles: function() {
for (var i=0;i<=top.previousFiles.length-1;i++) {
top.ICEcoder.rightClickedFile=top.ICEcoder.thisFileFolderLink=top.fullPath+top.previousFiles[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") {
if (top.ICEcoder.openFiles.length==0) {
top.ICEcoder.content.style.visibility='visible';
top.ICEcoder.content.src = "editor.php";
}
top.document.getElementById('accountLogin').style.top = "-50px";
setTimeout(function() {top.document.getElementById('accountLoginContainer').style.display = "none";},300);
} else {
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';
},
// Show file & folder count in server info screen
updateFileFolderCount: function() {
var fileText, dirText, unitSize, unitText, dContainer;
top.ICEcoder.dirCount > 1 ? dirText = "folders" : dirText = "folder";
top.ICEcoder.fileCount > 1 ? fileText = "files" : fileText = "file";
// Change into kilobytes
unitSize = Math.ceil(top.ICEcoder.fileBytes/1024);
unitText = "kb";
// Maybe we should show in megabytes?
if (unitSize >= 1024) {
unitSize = unitSize / 1024;
unitText = "mb";
}
// Update the display
dContainer = top.ICEcoder.content.contentWindow.document.getElementById('fileFolderCounts');
if (dContainer) {
dContainer.innerHTML = top.ICEcoder.fileCount+" "+fileText+", "+top.ICEcoder.dirCount+" "+dirText+"<br>~ "+unitSize+" "+unitText;
}
},
// Toggle full screen on/off
fullScreenSwitcher: function() {
var screenIcon;
screenIcon = top.document.getElementById('screenMode');
// Future use
if ("undefined" != typeof document.cancelFullScreen) {
document.fullScreen ? document.cancelFullScreen() : document.body.requestFullScreen();
// Moz specific
} else if ("undefined" != typeof document.mozCancelFullScreen) {
document.mozFullScreen ? document.mozCancelFullScreen() : document.body.mozRequestFullScreen();
// Chrome specific
} else if ("undefined" != typeof document.webkitCancelFullScreen) {
document.webkitIsFullScreen ? document.webkitCancelFullScreen() : document.body.webkitRequestFullScreen();
}
screenIcon.src.indexOf("images/full-screen.gif") > -1 ? screenIcon.src = "images/restored-screen.gif" : screenIcon.src = "images/full-screen.gif";
}
};

24
lib/config.php Normal file
View File

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

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,52 @@ 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 {
$loadedFile = file_get_contents($saveFile);
echo '<textarea name="loadedFile" id="loadedFile">'.str_replace("</textarea>","<ICEcoder:/:textarea>",$loadedFile).'</textarea>';
echo '<textarea name="userVersionFile" id="userVersionFile"></textarea>';
?>
<script>
var refreshFile = confirm('Sorry, this file has changed, cannot save\n<?php echo $file;?>\n\nReload this file and copy your version to a new document?');
if (refreshFile) {
var cM = top.ICEcoder.getcMInstance();
var thisTab = top.ICEcoder.selectedTab;
document.getElementById('userVersionFile').value = cM.getValue();
// Revert back to original
cM.setValue(document.getElementById('loadedFile').value);
top.ICEcoder.changedContent[thisTab-1] = 0;
top.ICEcoder.openFileMDTs[top.ICEcoder.selectedTab-1] = "<?php echo filemtime($saveFile); ?>";
cM.clearHistory();
// Now for the new file
top.ICEcoder.newTab();
cM = top.ICEcoder.getcMInstance();
cM.setValue(document.getElementById('userVersionFile').value);
cM.clearHistory();
// Finally, switch back to original tab
top.ICEcoder.switchTab(thisTab);
}
</script>
<?php
echo '<script>top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);action="nothing";</script>';
}
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 +224,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 #fff; max-width: 700px; max-height: 500px\" onClick=\"return false\"><br><span class=\"whiteGlow\" style=\"border: solid 10px #fff; color: #000; background-color: #fff\" onClick=\"return false\"><?php echo str_replace($docRoot,"",$file);?></span>";
}
top.ICEcoder.serverMessage();
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>
@@ -228,7 +263,7 @@ if (action=="save") {
if ("undefined" != typeof newFileName) {
top.ICEcoder.serverMessage('<b>Saving</b><br>'+newFileName);
}
document.saveFile.contents.innerHTML = top.document.getElementById('saveTemp1').value;
document.saveFile.contents.value = top.document.getElementById('saveTemp1').value;
document.saveFile.submit();
} else {
top.ICEcoder.serverMessage();top.ICEcoder.serverQueue("del",0);

View File

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

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: 0;
margin: 0;
padding: 0;
outline: 0;
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: #888; margin-bottom: 20px}
.help {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #fff; padding: 20px}
.help .key {display: inline-block; width: 175px; text-align: right; margin-right: 5px; float: left}
.help .key .plus {color: #888}
.help .shortcut {display: inline-block; width: 175px; color: #888; 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: 0;
margin: 0;
padding: 0;
outline: 0;
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: #888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #fff}
hr {border: 0; height: 1px; background-color: #888}
.results {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #fff}
.results .resultsPane {position: relative; width: 660px; height: 560px; font-size: 10px; padding: 20px; float: left}
.results .resultsPane a {color: rgba(0,198,255,0.7); text-decoration: none}
.results .resultsPane a:hover {text-decoration: underline}
.replace {position: absolute; margin-top: -28px; right: 20px; padding: 5px 10px; font-size: 14px; background-color: rgba(0,198,255,0.7); cursor: pointer}
.replaceAll {position: absolute; bottom: 0; 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: 0;
margin: 0;
padding: 0;
outline: 0;
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: #888; margin-bottom: 20px}
h2 {font-size: 18px; font-weight: normal; color: #fff}
.settings {font-family: arial, verdana, helvetica, sans-serif; background-color: #1c1c19; color: #fff}
.settings .infoPane {position: relative; width: 230px; height: 560px; font-size: 10px; color: #bbb; background-color: #fff; padding: 20px; float: left}
.settings .infoPane a {color: #888; text-decoration: none}
.settings .infoPane a:hover {text-decoration: underline}
.settings .logo {position: relative; margin-top: 2px}
.settings .version {position: relative; display: block; margin-top: 5px; margin-bottom: 10px; font-size: 10px; color: #bbb}
.settings .settingsColumn1 {width: 220px; height: 560px; padding: 20px; float: left}
.settings .settingsColumn2 {width: 420px; height: 560px; padding: 20px 20px 20px 0; float: left}
.settings input, .settings textarea {border: 1px solid #555; background-color: #444; color: #fff}
.settings input:focus, .settings textarea:focus {
outline: none;
-webkit-box-shadow: 0 0 10px 1px rgba(0,198,255,0.7);
-moz-box-shadow: 0 0 10px 1px rgba(0,198,255,0.7);
box-shadow: 0 0 10px 1px rgba(0,198,255,0.7);
}
.settings .plugins {font-family: arial, verdana, helvetica, sans-serif; width: 410px; height: 123px; overflow: hidden}
.settings .update {position: absolute; bottom: 0; right: 20px; padding: 5px 10px; font-size: 18px; background-color: rgba(0,198,255,0.7); opacity: 0.1; cursor: pointer}

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

@@ -0,0 +1,208 @@
<?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: 0; background-color: #fff; font-family: monospace}
.CodeMirror-scroll {height: 220px; width: 420px; overflow: hidden}
.cm-s-visible {display: block; top: 0}
.cm-s-hidden {display: none; top: 4000px}
.cm-s-activeLine {background: #002 !important;}
// Make sure this next one remains the 5th item, updated with JS
.cm-tab:after {position: relative; display: inline-block; width: 0; left: -1.4em; overflow: visible; color: #aaa; content: "<?php if($visibleTabs) {echo '\21e5';};?>";}
span.CodeMirror-matchhighlight {background: #555}
.CodeMirror-focused span.CodeMirror-matchhighlight {color: #000; background: #555; !important}
</style>
<link rel="stylesheet" href="editor.css">
<?php
$themeArray = array("ambiance","blackboard","cobalt","eclipse","elegant","erlang-dark","lesser-dark","monokai","neat","night","rubyblue","xq-dark");
for ($i=0;$i<count($themeArray)-1;$i++) {
echo '<link rel="stylesheet" href="../'.$codeMirrorDir.'/theme/'.$themeArray[$i].'.css">'.PHP_EOL;
}
?>
</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>
when finding in files, exclude:<br>
<input type="text" onkeydown="showButton()" name="findFilesExclude" value="<?php for($i=0;$i<=count($findFilesExclude)-1;$i++) {echo $findFilesExclude[$i]; if ($i<count($findFilesExclude)-1) {echo ', ';};}; ?>"><br>
<br>
<h2>assisting</h2>
<input type="checkbox" onclick="showButton()" name="codeAssist" value="true"<?php if($codeAssist) {echo ' checked';};?>> code assist<br>
<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: #888">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: #888">name, img src, style, url, target, setInterval (mins)</span><br>
<textarea name="plugins" class="plugins" onkeydown="showButton()"><?php
for($i=0;$i<count($plugins);$i++) {
for($j=0;$j<count($plugins[$i]);$j++) {
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>

Some files were not shown because too many files have changed in this diff Show More