├── .gitignore
├── .gitmodules
├── CHANGELOG.markdown
├── Info.plist
├── Jakefile
├── LICENSE
├── README.markdown
├── Resources
└── WKTextView
│ └── editor.html
├── WKTextView.j
├── auxiliary
├── build.sh
└── closure-editor-requirements.js
├── sample
├── .gitignore
├── AppController.j
├── Info.plist
├── Jakefile
├── Resources
│ ├── WKTextView
│ ├── silk
│ │ ├── comment.png
│ │ ├── comments.png
│ │ ├── link.png
│ │ ├── link_break.png
│ │ ├── page.png
│ │ ├── page_add.png
│ │ ├── page_edit.png
│ │ ├── page_white.png
│ │ ├── page_white_add.png
│ │ ├── page_white_edit.png
│ │ ├── page_white_text.png
│ │ ├── page_white_world.png
│ │ ├── picture.png
│ │ ├── text_align_center.png
│ │ ├── text_align_justify.png
│ │ ├── text_align_left.png
│ │ ├── text_align_right.png
│ │ ├── text_bold.png
│ │ ├── text_italic.png
│ │ ├── text_list_bullets.png
│ │ ├── text_list_numbers.png
│ │ ├── text_strikethrough.png
│ │ ├── text_underline.png
│ │ └── world_link.png
│ └── spinner.gif
├── index-debug.html
├── index.html
└── main.j
└── samplify.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | .DS_Store
3 | sample.dist
4 | Resources/WKTextView/closure-editor.js
5 | Build
6 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "auxiliary/google-closure-library"]
2 | path = auxiliary/google-closure-library
3 | url = git://github.com/aljungberg/google-closure-library.git
4 |
--------------------------------------------------------------------------------
/CHANGELOG.markdown:
--------------------------------------------------------------------------------
1 | WKTextView Changelog
2 | ====================
3 |
4 | # Version 0.5 (February 22nd, 2012)
5 |
6 | ## New Features
7 | * Switched to Google Closure editor.
8 | * New scrolling method: use native scrollbars so that the browser does all the work tracking the cursor position and scrolling to follow it. This makes for a very native like scrollbar experience. A faux Cappuccino scrollbar is rendered on top to maintain the Cappuccino look and feel.
9 | * Allow any background colour.
10 | * Option to auto-hide scrollbars.
11 |
12 | ## Changes and Fixes
13 | * Fixed: in Firefox, setting the view value would fire a "cursor did move" event but getSelection would return null leading to an exception.
14 | * Editor padding and margin support has been added back in. (The 0.4 solution to add padding around the whole editor made the scrollbar appear inside of the margin.)
15 | * Fixed get method for font and added getter for font size and color.
16 | * Improved "cursor did move" and scrolling updates, which sometimes would get one step behind.
17 | * Fixed some scrollbar flickering when animating text view resizes.
18 | * Expand text area to at least fill the height of the editor frame to allow a click anywhere to start editing. Also made fontName safe to call before full initialisation.
19 | * textViewDidBeginEditing and textViewDidEndEditing support.
20 | * Fixed: 'field is already uneditable' error and an error caused by a premature resize before the editor fully loaded.
21 | * Explicitly place the cursor at the start of the content when the editor activates after a reset or text change. This allows the editor to be activated by tabbing to it, something which before would result in the editor activating but not showing any cursor.
22 | * Fixed: various Firefox crashes when trying to manipulate a hidden editor.
23 | * Fixed: with Firefox, clicking the editor did not make it the first responder.
24 | * Fixed: the checkLoad timer would keep firing when a text view was hidden, burning CPU needlessly. Now only fire the check once and only repeat it if the view is actually visible and hence has a chance of loading any time soon.
25 | * Fixed: `editor.html` had to be placed in the main Resources folder of an app including WKTextView. It is now properly loaded from the WKTextView Framework folder.
26 | * Fixed: "unknown variable CPTimer" error.
27 | * Fixed: failure if the user sets the editor alue immediately after intialising an off-screen view.
28 | * IE specific fixes.
29 |
30 | # Version 0.4 (May 1st, 2010)
31 |
32 | ## New Features
33 | * Upgraded WysiHat. This version ups the minimum requirements to IE 7, Firefox 3, Safari 4 or Chrome 4. WKTextView was updated to use WysiHat as a contentEditable div instead of an iframe.
34 | * Implemented setEnabled/isEnabled. When disabled the editor does not display a text edit cursor; it does not listen to mouse events, etc.
35 | * Support for editor padding was removed since it too was a source of jumping bugs, although on a smaller scale. If you need padding just add it around the editor instead.
36 | * Jakefile to create debug and release builds (`jake debug` and `jake release`).
37 | * setFontSizeForSelection.
38 | * setColorForSelection.
39 |
40 | ## Changes and Fixes
41 | * WKTextView can now become the first responder. Tabbing out of the field is possible with Shift-Tab, the standard key for tabbing backwards. Tab forward is not possible to allow the tab character to be written.
42 | * Fixed: clicking on a WKTextView would cause it to gain focus without requesting first responder status. The most visible artifact of this was that tabbing out of the view if it was activated by mouse didn't work as expected because Cappuccino didn't know the view was selected to begin with.
43 | * Activating an editor by clicking on it now makes its window the key window.
44 | * Backgrounds underneath WKTextView now shine through.
45 | * Fixed: some variables leaking into the global scope.
46 | * Fixed: uninitialized height could cause a race condition in Webkit.
47 | * Fixed: in Firefox, clicking on the WKTextView did not make it the first responder, and shift tab did not back tab out of the editor.
48 | * Renamed setFont to setFontNameForSelection.
49 | * Content height calculations are much improved and it looks like most of the jumping bugs (hitting enter to insert a new row while at the last row in a text taller than the view height) are resolved. Performance might also be improved.
50 | * Removed some left over logging.
51 |
52 | # Version 0.3 (January 13th, 2010)
53 |
54 | ## New Features
55 | * New delegate method textViewDidChange.
56 |
57 | ## Changes and Fixes
58 | * Fixed: text views with a vertical scrollbar would have 15 of their rightmost pixels missing until the window was first resized.
59 | * Fixed: sometimes a text select would be followed by an immediate deselect; clicking with Safari could result in text being reflowed; moving the cursor in Opera back and forth lead to spaces being inserted at the cursor position.
60 | * Fixed: the wysihat submodule pointed to the non public github repository.
61 |
62 | # Version 0.2 (December 2nd, 2009)
63 |
64 | ## New Features
65 | * Support for insert image, bullets, ordered lists, font selection, link, unlink, strikethrough and text alignment.
66 | * The current font can now be read from the editor with the font method.
67 | * New delegate method textViewCursorDidMove:.
68 | * Added a setTextValue: method.
69 |
70 | ## Changes and Fixes
71 | * Fixed: editor height calculation didn't work in Firefox. The replacement code is also more elegant and could be more efficient for large amounts of text.
72 | * Fixed: deleting or inserting text would not cause the scrollbar to update without first mousing over it.
73 | * Workaround for focus lost when the toolbar is clicked: the new option setShouldFocusAfterAction: makes the editor automatically focus after actions such as boldSelection.
74 | * Fixed: textViewDidLoad is not sent until the WysiHat ready flag is set. This resolves some problems where content could not be set in Firefox immediately in a textViewDidLoad callback.
75 | * Wysihat now available as a submodule, making it easier to grab the right hacked version.
76 | * Basic support for the editor scrolling automatically to follow the cursor.
77 | * Wyzihat is now correctly spelled Wysihat in most places.
78 |
79 | # Version 0.1 (November 27)
80 |
81 | * First release.
82 |
--------------------------------------------------------------------------------
/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CPBundleIdentifier
6 | net.wireload.WKTextView
7 | CPBundleInfoDictionaryVersion
8 | 6.0
9 | CPBundleName
10 | WKTextView
11 | CPBundlePackageType
12 | FMWK
13 | CPBundleVersion
14 | 0.1
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Jakefile:
--------------------------------------------------------------------------------
1 | /*
2 | * Jakefile
3 | * WKTextView
4 | *
5 | * Created by Alexander Ljungberg on April 14, 2010.
6 | * Copyright 2010, WireLoad, LLC All rights reserved.
7 | */
8 |
9 | var ENV = require("system").env,
10 | FILE = require("file"),
11 | JAKE = require("jake"),
12 | task = JAKE.task,
13 | FileList = JAKE.FileList,
14 | app = require("cappuccino/jake").app,
15 | configuration = ENV["CONFIG"] || ENV["CONFIGURATION"] || ENV["c"] || "Debug",
16 | OS = require("os");
17 |
18 | app ("wyzihatkit", function(task)
19 | {
20 | task.setBuildIntermediatesPath(FILE.join("Build", "wyzihatkit.build", configuration));
21 | task.setBuildPath(FILE.join("Build", configuration));
22 |
23 | task.setProductName("WKTextView");
24 | task.setIdentifier("wyzihatkit");
25 | task.setVersion("1.0");
26 | task.setAuthor("Alexander Ljungberg");
27 | task.setEmail("aljungberg@wireload.net");
28 | task.setSummary("WKTextView");
29 | task.setSources((new FileList("**/*.j")).exclude(FILE.join("Build", "**")).exclude(FILE.join("sample", "**")).exclude(FILE.join("sample.dist", "**")));
30 | task.setResources(new FileList("Resources/**"));
31 | task.setInfoPlistPath("Info.plist");
32 |
33 | if (configuration === "Debug")
34 | task.setCompilerFlags("-DDEBUG -g");
35 | else
36 | task.setCompilerFlags("-O");
37 | });
38 |
39 | function printResults(configuration)
40 | {
41 | print("----------------------------");
42 | print(configuration+" app built at path: "+FILE.join("Build", configuration, "WKTextView"));
43 | print("----------------------------");
44 | }
45 |
46 | task ("default", ["wyzihatkit"], function()
47 | {
48 | printResults(configuration);
49 | });
50 |
51 | task ("build", ["default"]);
52 |
53 | task ("debug", function()
54 | {
55 | ENV["CONFIGURATION"] = "Debug";
56 | JAKE.subjake(["."], "build", ENV);
57 | });
58 |
59 | task ("release", function()
60 | {
61 | ENV["CONFIGURATION"] = "Release";
62 | JAKE.subjake(["."], "build", ENV);
63 | });
64 |
65 | task ("run", ["debug"], function()
66 | {
67 | OS.system(["open", FILE.join("Build", "Debug", "wyzihatkit", "index.html")]);
68 | });
69 |
70 | task ("run-release", ["release"], function()
71 | {
72 | OS.system(["open", FILE.join("Build", "Release", "wyzihatkit", "index.html")]);
73 | });
74 |
75 | task ("deploy", ["release"], function()
76 | {
77 | FILE.mkdirs(FILE.join("Build", "Deployment", "wyzihatkit"));
78 | OS.system(["press", "-f", FILE.join("Build", "Release", "wyzihatkit"), FILE.join("Build", "Deployment", "wyzihatkit")]);
79 | printResults("Deployment")
80 | });
81 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2009 Alexander Ljungberg and Harry Vangberg
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | WKTextView
2 | ==========
3 |
4 | A [Cappuccino](http://cappuccino.org/) control providing rich text editing through use of a browser driving content editable field. Under the hood, the [Google Closure Library](http://code.google.com/closure/library/) editor is used.
5 |
6 | Until a proper `CPTextView` is written this will probably be one of the most full featured rich text editor for Cappuccino.
7 |
8 | You can view an online demo [here](http://wireload.net/open_source/wktextview-sample/index.html).
9 |
10 | ## Features
11 |
12 | * Bold, italics, underline, strike through.
13 | * Left, right, center and justify alignment.
14 | * Bulleted and numbered lists.
15 | * Links.
16 | * Images.
17 | * Fonts.
18 | * Outputs regular HTML.
19 | * Vaguely resembles a proper CPTextView in its API.
20 |
21 | ## Installation
22 |
23 | Link the `WKTextView` folder into your `Frameworks` folder.
24 |
25 | Create and combine the `Resources/WKTextView/closure-editor.js` file using the WKTextView modified version of the Closure editor:
26 |
27 | git submodule init
28 | git submodule update
29 | cd auxiliary
30 | # Edit build.sh to provide the correct path to closure.jar.
31 | sh build.sh
32 |
33 | ## Usage
34 |
35 | textView = [[WKTextView alloc] initWithFrame:effectiveFrame];
36 | [textView setAutoresizingMask:CPViewWidthSizable | CPViewHeightSizable];
37 | [textView setDelegate:self];
38 |
39 | The view needs to load resources such as `editor.html` and `closure-editor.js`. Wait for the `textViewDidLoad:` delegate call before using.
40 |
41 | ## Sample
42 |
43 | A sample program is provided in the `sample` folder. To compile and view, run the `samplify.sh` script, then open up `index-debug.html` in a browser:
44 |
45 | sh samplify.sh
46 | open sample.dist/index-debug.html
47 |
48 | # License
49 |
50 | WKTextView is released under the Apache License 2.0. The sample incorporates Creative Commons icons from [FamFamFam](http://www.famfamfam.com/lab/icons/silk/).
51 |
52 | # Authors
53 |
54 | * Alexander Ljungberg, [WireLoad Inc](http://wireload.net)
55 | * Evadne Wu
56 | * Klaas Pieter Annema
57 | * Paul Baumgart
58 | * xanados
59 |
60 | ## Thanks to
61 |
62 | * Harry Vangberg
63 |
--------------------------------------------------------------------------------
/Resources/WKTextView/editor.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
Mauris ac tellus orci. Aenean egestas porta ornare. Cras nisl lorem, vulputate ac pellentesque eu, aliquet ac leo. Proin eros libero, tincidunt sed sodales eget, elementum non augue. Praesent convallis auctor venenatis. Suspendisse id urna quam. Aliquam sagittis, leo commodo laoreet interdum, arcu felis dictum velit, a sodales justo tortor a erat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis nibh magna, consequat et congue eu, bibendum id nisi. Cras gravida risus in nulla pharetra sagittis. Cras neque eros, consectetur nec bibendum eget, bibendum dictum libero. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nam rutrum dictum neque vel eleifend. Vivamus tempus, lorem vel ultricies ullamcorper, ante risus imperdiet massa, nec aliquam orci ipsum ut nisl. Aliquam id justo eu lorem dapibus tincidunt. Donec suscipit consequat metus, sed venenatis lorem malesuada sit amet. Ut at risus ut ligula vulputate auctor. Vivamus rutrum elementum porttitor. Fusce quam arcu, tristique eget consectetur eu, iaculis in urna.
Donec a metus ac elit faucibus sagittis non a ligula. In aliquet, lectus sed pulvinar bibendum, justo ligula faucibus sem, vestibulum eleifend lacus augue a eros. Suspendisse potenti. Phasellus vehicula blandit ultrices. Donec tortor nulla, fermentum nec viverra id, consequat non metus. Fusce nunc urna, aliquet sit amet varius ut, dapibus a sem. Aliquam erat volutpat. Vestibulum at enim et magna lacinia sollicitudin id nec dolor. Sed ultricies urna ut justo blandit tincidunt. Sed sit amet orci et justo pellentesque iaculis accumsan ac quam.
Nunc tristique felis quis leo blandit eget iaculis lacus hendrerit. Maecenas euismod consequat lacus quis porttitor. Quisque consequat, metus eu interdum vulputate, quam dolor porttitor dui, non faucibus quam nibh nec erat. Integer sit amet gravida quam. Proin nunc eros, tincidunt sit amet accumsan laoreet, dictum vel sapien. Praesent at fringilla orci. Etiam vehicula lacinia nisi, et molestie justo congue molestie. Maecenas tempus, quam nec placerat suscipit, lorem sapien feugiat augue, id pharetra augue enim eu nisl. Morbi ullamcorper lacus ac dolor ultricies vel pellentesque odio consequat. Maecenas a pellentesque nunc. Phasellus a varius massa. Vestibulum eget tortor eget ante iaculis molestie. Pellentesque eu augue metus, ut pellentesque purus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Curabitur consequat feugiat tincidunt. Proin tellus tortor, pharetra vel rhoncus ac, varius eget nisi. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras et nunc metus. Pellentesque tincidunt iaculis erat id porta. Curabitur eget magna et velit eleifend tempor.
Vestibulum ultricies leo at augue malesuada congue. Maecenas laoreet metus et nunc consectetur placerat. Nulla facilisi. Duis iaculis tristique feugiat. Ut quis consectetur justo. Praesent condimentum sagittis dui, in lobortis tellus accumsan quis. In aliquam lacus non dolor accumsan rutrum. Etiam sed urna dolor. Donec consectetur lacus eu ante sodales feugiat. Aliquam aliquet nibh vel massa mattis pellentesque. Curabitur et tortor nisl, ut consequat felis. Mauris non orci at tortor ultrices condimentum. Aliquam erat volutpat. Mauris porttitor, diam convallis semper hendrerit, erat mi tempor dolor, id semper augue justo fermentum odio. Sed vitae nulla eu augue fringilla pellentesque vel ac neque. Nullam arcu nibh, auctor ut accumsan ac, ullamcorper eu velit. Integer in ligula nec felis auctor viverra. In commodo malesuada volutpat. Etiam justo elit, tincidunt ac semper sed, eleifend eu odio. Cras ac nulla eget lorem tempor venenatis.