I am working on a WYSIWYG editor. As it has to include just some basic functions I want to do it myself and avoid problems. Now it is working perfectly but I want to add a functionality in order to unbold, unitalic...
I know that with execCommand it is an automatic thing, but it does not work in the same way in all browsers so... my idea was the next: When pressing BOLD button, check the environment of the string, and...
If the selection is Between the open and close <b> tags, like <b>ab||selected||cd</b> replace selected with </b>selected<b>.
If the selection starts or finishes with the <b> tag, like <b>ab||selected||</b> replace it by </b>selected<b> (and then strip out all <b></b> groups.)
If the selection starts and finishes with the <b> tag, like <b>||selected||</b> replace it by </b>selected<b> (and then strip out all <b></b> groups.)
But... how can I get into a var the <b>content</b> string when just having the caret/selection IN content? It might be possible...
UPDATE
It is curious that the replacement is always the same. So, should I really get what I am asking for, or just replace it in this way, always?
I am working on a WYSIWYG editor. As it has to include just some basic
functions I want to do it myself and avoid problems. Now it is working
perfectly but I want to add a functionality in order to unbold,
unitalic...
Do not write your own WYSIWYG editor.
Do you really want to "avoid problems"? Then use one of existing good editors (there're only 2... maybe 3 in fact). Creating editor is extremely hard task for which you need a lot of time (I mean... few years), a lot of knowledge and patience (a lot of too :P).
I can myself write that "I am working on a WYSIWYG editor". For more than half of the year I'm a core developer of one of these "good editors". And during this period I implemented only one feature - very important and very complex, but one of tens/hundreds of them.
That problem you have... I don't even want to start answering. It sounds like a piece of cake, but it isn't. It's a piece of brick that can kill you when fall on your head :). I'll only start enumerating important parts of the impl: Selection + range implementations, because native differ and are buggy (~5k LOC + min Nk LOC for tests). Then you need the proper styles handling (applying and removing) impl (min 1k LOC + tests), because you have to take care about styles spanning on many blocks (like entire table bolded) and different selections containing parts or entire styles etc. And you have to avoid native execCommand, because they will break your content. Then you should also think about updating toolbar buttons states and, to make your impl bullet proof, handling different style tags (e.g. pasted). And that's only the tip of an iceberg - you'll have styles handling, but hundreds of other things broken. Things that big editors have fixed.
Anyway - learn config options for one of main editors and customize it as you want. This will take you a few hours, not a few years.
Related
I'm working on a force directed graph for a university project. We have to create a 'research archive' that presents all our research material – I've started mine here as a digital garden using Maxime Vaillancourt's Jekyll digital garden template (which uses d3). You can view it here.
Part of the reason I started with this was I was using obsidian for a while, but wanted a) it in a website format, c) something I could easily share with my tutors etc, and c) more customisable options than obsidian). Maybe it's a bit of an obsidian hang-up, but I really want to be able to add 'tags' to entry, e.g. by theme, or by entry type (so different tags for images, journal articles, primary research, etc). I'm struggling to find answers relating to this, and think maybe I'm too stuck on the idea of 'tags' and not thinking through other ways people might be expressing/phrasing something which achieves the same thing.
Ideally, I'd like these to be a toggleable feature, e.g. click a sidebar button to view all entries tagged with XYZ.
However, I was also thinking it could work through different styled/coloured lines that show connections by tag (so an entry would have, say, bold black lines to other entries they're linked to; a dashed grey line to ones that are also tagged with 'photograph'; a dotted blue ones to ones that are also tagged with 'health'; etc). Or, giving each entry only one tag, and that tag denoting the colour of the node.
The reason I am keen on this, is I would like to be able to show different 'levels' of connections, but at the moment am struggling with the 'difinitiveness' of the single line. I know for some people who use Obsidian as a zettelkasten tool they're into using links effectively as tags (e.g. having a list of 'tags' at the bottom which are in effect links), but a) I don't think this really works in the same way, and b) it requires creating full entries for themes or tags that might not naturally need one (going back to the photograph example - this work around would require creating a separate .md file titled 'photograph' which people would be able to navigate to, which would either mean I'd have to write some forced entry for this, or people would inevitably stumble on lots of dead pages.
I'm not expecting someone to come and fix my problem, but more ideas on what sort of features could work. I am self taught at a lot of this stuff, and so in particular often struggle with knowing what it is I am looking for/asking for – like I lack the language, even though I'm often able to actually work out how to do things once I've got on the right track.
In case anyone is ever stuck in a similar position –
I was managing to do a lot of the things I wanted on fiddles, but not via the template above. For some reason, I could get it to there being no errors/problems in the console log, but it just wouldn't actually 'work' (ie, there was a search bar, but typing into it wasn't performing the right functions, etc). I'm sure a more technologically capable person could work out what was the clash between the template and my edits that was causing this. But, after lots of trying, I stumbled upon https://github.com/jackyzha0/quartz – which so far already has a lot of things I wanted semi built in, and so far seems a bit more receptive to edits in this way.
I have a web app that displays and passes around user-editable semantic markup. For a variety of reasons, including security, the markup consists entirely of custom elements (plus the i, b, and u tags). For regular rendering, I simply have styles for all the tags and stick them straight in the DOM. This looks and works great.
Now I'm doing screen-reader testing, and things aren't great. I have a bunch of graphical symbols I want to add labels for. I've got divs that I want to make into landmarks. I've got custom input fields and buttons.
It would be easy enough to just add role= to all the different tag instances. But part of the reason for the custom markup is to eliminate all the redundant information from the strings that get passed around (note: they're also compressed). My <ns-math> tag should always have role="math", and adding 11 bytes to what might be tags around a single character is an actual problem when multiplied out over a whole article. I know this because the app started with a bunch of <span class="... type elements instead of custom.
For the fields and buttons, I've used a shadow DOM approach. This was necessary anyway to get focus/keyboard semantics correct without polluting the semantic markup with a bunch of redundant attributes, so it's easy to also slap the ARIA stuff on the shadow elements. Especially since the inputs are all leaf nodes. But most of my custom tags amount to fancy spans, and are mostly not leaf nodes, so I don't really want to shadow them all when they're working so well in the light DOM.
After a bunch of searching, it seems like the internals.role property from "4.13.7.4 Accessibility semantics" of the HTML standard is maybe what I want. I may well be using it incorrectly (I'm a novice at front-end), but I can't seem to get this to work in recent versions of Firefox or Chrome. I don't get an error, but it seems to have no effect on the accessibility tree. My elements are not form-associated, but my reading is that the ARIAMixin should be functional anyway. This is maybe a working draft? If this is supposed to work in current browsers, does anybody have a code snippet or example?
Is there some other straight-forward way to achieve my goal of accessibility-annotating my custom elements without adding a bunch of explicit attributes to the element instances?
So you want the benefit of adding a role or an aria-attribute without actually adding those attributes? The concept of an "accessibility object model" (AOM) has been bantering around a bit that would let you access and modify the accessibility tree directly but it's still in the works. Here's an article from a couple years ago that talks about it. Nothing official. Just one person's thoughts.
Further research shows that, as of this time, the abstracted accessibility options I'm asking for are not yet implemented.
For the time being: eliminating a number of page-owned enclosing divs from the accessibility hierarchy via role="presentation" significantly improved my overall tree. With those out of the way, the majority of my custom tags seem to be simply semantically ignored. This is mostly fine as the majority of my content is plain text.
Since I already mark up the vast majority of even single-character symbols, I've simply added all my symbols to the markup generator. Since everything is already in custom tags, I then use a shadow DOM span with role="img" and a character-specific aria-label to present the symbolic character.
My solution is still incomplete. I wish that I could convey the full richness of the semantic content I have available.
I need to build a wysiwyg editor for a project I am working on and need some guidance. Some of my key points of confusion are the following:
iframe docs vs. contenteditable divs: which one should I use and why? I hate iframes, is there a clear advantage to using iframes?
cross browser styling: execCommand seems to apply different styles in different browsers. Are there any tricks to making this cross-browser compatible? Should I not use execCommand at all and instead apply my own styles?.
adding items to the undo chain: how can run my own script, such as inserting an image, and allow cntrl+z (undo) to remove it? Is there an array of undo/redo items for contenteditable that I can push items into?
keeping the text selection: how I can maintain text selection while making operations such as selecting the font style, where the focus will leave and remove my selection. Rangy? Google closure? Are there other range/selection libraries worth looking at?
Any tips on these items or anything else related to building a rich text editor would be greatly appreciated!
From personal experience, I recommend against doing this unless your aim is to provide a very limited amount of functionality. The sheer number of browser differences and the complexity of their workarounds makes this a very tricky and time-consuming task if you want to do it well.
If that hasn't put you off, here's my thoughts on your individual questions:
iframe docs vs. contenteditable divs
I recommend the iframe approach, for two main reasons:
You have complete control over the document type, CSS and script within the iframe. This is essential if you want consistent behaviour and appearance and want to use your editor within different pages.
Firefox in particular is quite buggy with contenteditable elements, which they only introduced relatively recently (version 3.0) while designMode has existed on documents for many years (since pre-1.0; around 0.6, if memory serves) and works pretty well.
cross browser styling
If it's important for you to have uniform results from applying styles in different browsers then in general you will need to write your own styling code. However, doing this will break the built-in undo stack and you will need to implement your own undo/redo system.
adding items to the undo chain
There's no programmatic way to interact with the built-in browser undo stack. You'll need to write your own.
Update November 2012
There is a spec in the works for custom undo/redo so this is likely to be possible eventually. Here are the relevant bugs for Mozilla and WebKit.
keeping the text selection
I have to declare my interests here, since I wrote Rangy. I don't think there's a better library out there that does a similar job; Google Closure does have a range/selection API but I think it uses their own proprietary interface rather than emulating DOM Range and common browser Selection objects. IERange is another library that is similar in idea to Rangy but much less fully realized and seemingly abandoned immediately after release by its author.
Don't, seriously don't.
What you are suggesting is a major undertaking. You really should be looking at TinyMCE, http://tinymce.moxiecode.com/, or CKEditor, http://ckeditor.com/. Getting what you are after is a massive amount of effort to get working for one version of one browser, to make it portable will take man-years of investment.
A better solution is to look at things like TinyMCE's plugins, http://tinymce.moxiecode.com/plugins.php. You can get your basics the basics (and portability for free) and concentrate on adding the specific value-add items you need to.
by simple I mean, having buttons:
bold,
italic,
numbered list
bullet point list
indent left
indent right
spell check (obviously supported by ready made js component)
by custom I mean: having custom icons - so really just custom design
no frameworks, written from scratch, lightweight, compatible with major browsers
this is one of the main components of the webapp, so it has to be super lightweight, that's why I don't want frameworks
Unless you are targeting one browser, editors are immensely complicated components to get to work cross browser. There's no reason to do it yourself, unless you want to learn.
Use one of the many available that allow customization:
tinymce,
fckeditor,
wysihat,
others
Writing an editor that works cross-platform can be difficult, but, you should create your own framework as you do it, as it is a large project.
If you just want custom icons, that will depend on how long it takes you to make them, but, to get some basic functionality isn't that hard, probably less than 40 hrs of work if you know what you are doing.
In Unix writing your own shell used to be a rite of passage, in javascript it may be writing your own editor. :)
Where it gets tricky is if I have
<b>some text</b><i>more text</i>
and I decide to remove the tags from this text, then how to fix it will get tricky.
If you want to use only css then it gets to be more of a problem as you are grouping text from span tags, and fixing css classes, while the user is continuing to make changes.
I am dealing with this currently as I want an editor that works in XHTML2.0, and it is not a trivial issue, much harder than it is to do in a desktop application.
I would suggest getting it to work on Firefox 3 and Safari first, then, once it is working, go back and add in the code to get it to work on IE8, and if you want IE7, since MS is pushing IE8 out as a critical update now.
Don't.
Go get something else (any of those Jason mentioned, or e.g. what SO itself uses, WMD). Swap out its images. The end.
Seriously you don't want to write your own editor unless you have a very good reason for it functionally, not just what it looks like.
Read through the first chapters of the emacs tutorial, and you will see that there is not anything like a "simple" editor. But google will give you lots of easy customizable editors.
I am aware that Javascript WYSIWYG editors use the inbuilt editor mode of the browser to function, but that comes up with various problems and issues.
Can an editor be built from scratch in JS, something like what Buzzword people have done with flash/flex? I came across this blog post recently and I am just wondering if this can be built (atleast to a moderate extent) using Javascript?
It depends what you mean by "from scratch". Google Docs provides a pretty good text editor in JS. Is that what you mean ?
Of course you can do it and it is not very difficult.
But before reinventing the wheel please take a look at all the existing ones.
Many of them are really very well written and open source.
Almost anything can be done with JavaScript. You have the basic building tools right there - you can intercept all mouse events and nearly all keyboard events. You can use a GIF animation for simulating the caret. The trickier part might be measuring the size of text so that you can position your caret where you need to. I'm not exactly sure how you could do that. But if you figure that out, the rest is doable. Although it will really require tons of wheel-reinventing code.
Reminds me of a little experiment I did sometime back... I basically tried to create a primitive editor by simply listening to keypresses on a DIV and to insert them into the DIV as a new node. So imagine, each character would be wrapped in a tag! It actually worked. But, once it reaches a couple of paragraphs, node insertion and deletion becomes rather slow. You will type a character, and it would only appear after a slight delay, and this simply unacceptable, and eventually I just gave up. Anyway it was just a random thing I wanted to try out..
Coming back to your question, I wonder if this can be replicated in JS alone as frankly the flash has superior raw processing power compared to JS. Even if it's technically feasible, I doubt whether it will be fast enough to actually work well. My two cents!
Atwood's Law:
Any application that can be written in JavaScript, will eventually be
written in JavaScript.