Code Monkey home page Code Monkey logo

sir-trevor-js's Introduction

Sir Trevor

Build Status

Conceived by Andrew Sprinz. Maintained by Chris Bell & Andrew Walker.

Upgrade guide from v0.5

Quick start

The recomended way to install Sir Trevor in your project is using npm. This will install all the files required in the build directory for the module.

npm install sir-trevor

Note: Sir Trevor is distributed combined with its dependencies. If you wish to modify Sir Trevor you will want to clone the repository and use the Compiling instructions below.

HTML

<form><textarea class="js-st-instance"></textarea></form>

Javascript

import SirTrevor from "sir-trevor";

const editor = new SirTrevor.Editor({
  el: document.querySelector(".js-st-instance"),
  defaultType: "Text",
  iconUrl: "build/sir-trevor-icons.svg"
});

Full docs

[http://madebymany.github.io/sir-trevor-js/docs.html]

Plain JS

Implementations

  1. Sir Trevor Rails
  2. Umbraco 7, Umbraco 6
  3. CakePHP
  4. Wordpress, Wordpress
  5. Laravel
  6. Django
  7. Yii Framework
  8. Symfony2

Custom blocks

We are keeping a list of custom block repos here. See the documentation to find out more about adding your own block types.

Browser support

Sir Trevor is only tested on the following modern browsers:

ECMAScript 6 shims are bundled in by default; if the platform you wish to run on doesn't support ECMAScript 5 APIs you'll need to shim those yourself.

Sir Trevor uses The Guardian's scribe for rich text editing. Double check their browser support if your application relies on full RTE support.

Contributing

See the roadmap and read a little about the philosophy guiding development.

Customising the way it looks

We use Sass for our styles, if you'd like to change the default styling please fork the repository and make changes to the Sass before recompiling.

Customising blocks

Block Types can also easily be added to the SirTrevor.Blocks object. You can also override the default block types (Text, Image, Tweet, Video, Quote, Heading & List) at any time. See the documentation to find out more about adding your own block types.

Compiling

Tests are run as part of compilation process, which require chromedriver to be installed on the machine where you are running the compilation. If you're running Homebrew on OSX this can be installed via brew install chromedriver.

Before getting started please be sure to install the necessary dependencies via npm:

$ npm install

When completed, we have a couple of preset scripts:

$ npm run dev

This compiles for development, and watches source files to recompile when you change something.

$ npm test

Runs the linter and test suite, just like the CI server does.

$ npm run dist

Concatenates scripts, compiles the Sass, runs the Jasmine tests and minifies the project.

Please ensure any pull requests have relevant Jasmine tests (where applicable).

Current browser support tests

matrix:

  • BROWSER_NAME='chrome' BROWSER_VERSION='51' PLATFORM='OSX 10.10'
  • BROWSER_NAME='chrome' BROWSER_VERSION='51' PLATFORM='Windows 7'
  • BROWSER_NAME='firefox' BROWSER_VERSION='46' PLATFORM='OSX 10.10'
  • BROWSER_NAME='firefox' BROWSER_VERSION='46' PLATFORM='Windows 7'

Building gh-pages docs

cd website
npm install
bundle exec rake publish PROJECT_ROOT=./ ALLOW_DIRTY=true

License

Sir Trevor is released under the MIT license: opensource.org/licenses/MIT

sir-trevor-js's People

Contributors

andflett avatar arbarlow avatar bborn avatar borales avatar callum avatar callumlocke avatar caouecs avatar cjbell avatar dwb avatar higgis avatar ilyatulvio avatar jackbot avatar jackjennings avatar jbaiter avatar jeffling avatar jonduarte avatar lukaszsagol avatar marcstoecker avatar markwpearce avatar martinbean avatar morpheus-87 avatar motin avatar olvado avatar pfinkbeiner avatar rafaelbeckel avatar raffij avatar samueljmurray avatar sgtoddball avatar shinnc avatar simoniong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sir-trevor-js's Issues

Stop any unfinished uploads on deletion of a block

At the moment, we don't know if a block is uploading when it's deleted. Therefore, the forms are unable to be submitted even if an upload is then cancelled.

To do this properly, we should store references to promises of the async request in an array on the block, then have some convenience methods added to the Uploadable module, or maybe on the block itself to know if the block is uploading.

By keeping a reference to the promises we can at least wait until the upload completes before deleting the block completely.

Standardise Editor Triggers

At present we're using a variety of different styles when triggering events across the editor.

We should bring these inline with the following syntax:

sir-trevor:{component}:{method}

So for a block deletion:

sir-trevor:block:deleted

For any instance specific events the syntax should be:

sir-trevor:{instance_id}:{component}:{method}

However, we should favour using the internal instance events over using this too much.

How did you envisage Sir Trevor being extended and used?

How did you guys envisage an app being set up that extends Sir Trevor with new block types?

I've written three extra blocks that sit in their own folder and extend ALA Backbone style, however there are convenience methods in the Sir Trevor core that aren't exposed; halt, for example (even though it's a very simple helper). When I had an error thrown, it occurred to raise the issue with you guys.

What I'm asking, in essence, is did you envisage a Backbone-style extension model with new blocks being separate from the core, or did you imagine writing new blocks and compiling a new build with new blocks using the pre-existing Grunt task? The latter has been my assumption, given the structure of Sir Trevor as it stands.

Cheers!

Remove jQuery dependency

I understand that jQuery might be necessary to have it working on some browsers, but is there a way to remove the dependency on such a large piece of code?

A better way to provide custom validations for blocks

Currently this is quite difficult without squashing the original validate function. I had two ideas for improvement of the current validate function.

  1. Being able to add an array of validations and pass them to a validate function.
  2. Split out the validate function into at least two parts - validate() which is the main function to call (and still the one that ST calls); validate_field() which is called recursively by the validate function (so that you can override this rather than squash the entire validate function)

we could implement both so that the validator runs through all the custom validations in an array (if there are any) plus the standard ones.

Something like this:

validate_field : function(memo, field) {
  if (validation_failed) {
    field.addClass('st-error');
    return ++memo;
  }

  return memo;
},

validations : ["custom_validation_1", "custom_validation_2"],

custom_validation_1 : function() {
  return 0; // if validation passed
},

custom_validation_2 : function() {
  return 1; // or more if validation failed
},

run_validations : function(memo, validation) {
  return validation.call(this);
},

validate : function () {

  var fields = this.$(".st-required");

  var errors = _.reduce(fields, _.bind(this.validate_field, this), 0)
    + _.reduce(this.validations, _.bind(this.run_validations, this), errors);

  return errors === 0;
}

What do you think?

Twitter block should store entities for a tweet

To abide by the twitter display guidelines you have to display urls and media links correctly.

Probably best to follow the twitter api structure and copy the entities attribute from the twitter api directly to the tweet block for use later.

Update documentation

  • Add install guide for with and without Bower
  • Update Wiki
  • List breaking changes between 0.2 -> 0.3

Yet another broken WYSIWYG editor

Your minimal interfaces are pleasant to see and play with. But as long as you're using contenteditable="true" you are writing a broken WYSIWYG editor.

There's not a single contenteditable element that would have worked correctly just like the author intended it to work. It's the implicit piece of shit that makes these projects fail. I begun doing hard-editor since I saw the last project like this, and have taken a different approach. Although neither correct for web it's something different.

There's not a way around this by stripping the code into markdown. It's still going to be broken inside and you have to check that the outputted markup is correct if you're going to use this. That defeats the whole purpose of such editor, which is always supposed to be helpful tool for those who cannot or do not want to read HTML or markdown.

You shouldn't close this post, until you've gotten rid of contenteditable, or you have managed to get it work much better than it is doing.

Don't ask to confirm deletion of empty blocks

If I create a block and then immediately want to delete it (eg. if I realise I want a different block type), it probably shouldn't ask me for confirmation if I haven't added any content.

Required validation not working?

Hi -

I'm trying to set a block to be required, but even after content has been added I'm getting back an error that "A required block type [X] is empty". It seems to work fine for Headings, but Text, Quote and List blocks are throwing the error.

Here's how I'm setting up my ST:

new SirTrevor.Editor({ el: $('.trevor-editor'), blockTypes: ["Heading", "Text", "Quote", "List"], required: ["Heading", "Text"] });

This is occurring in Safari 6.0.5 and Chrome 30.0.1599.101, using Sir Trevor 0.3.0, jQuery 1.9.1, Underscore 1.4.4 and Eventable 1.0.2. This may very well be caused by my idiocy, but I'm stumped.

EDIT: When the required options are removed, the supposedly empty Text block data does show up in a POST dump. Very odd.

Un-parseable JSON removes box, breaks page

When sir trevor can't parse the current JSON in a text field, it might be nice to carry on but render something in it's place. As currently, the text area is removed and no message is given.

This can happen more frequently than you think due to having incorrect column sizes in MySQL etc..

add demo to your website

Add a demo of your editor to your website, this allows people to evaluate without having to download/run. First impressions count and if it's too hard to set-up a demo on your static website, people wonder if it's going to be difficult to integrate etc. :)

Migrate Twitter from API version 1.0 to 1.1

All requests to Twitter will need to be authenticated from now on, thus meaning that we will need some kind of config option in Sir Trevor to allow this for Twitter (access token).

Drag end event doesn't bring up contextual menu

Drag end event (I presume this is what's being used anyway) doesn't fire if user's mouse moves beyond the editable block when the drag stops. Therefore the contextual menu does not come up.

Strange custom block behavior

I'm seeing what appears to be a one or more bugs with custom blocks. First of all, if I take the just-updated markdown custom block:

SirTrevor.Blocks.Markdown = (function(){

  var md_template = _.template([
    '<div class="expanding-textarea">',
      '<pre><span></span><br></pre>',
      '<textarea class="st-markdown st-required"></textarea>',
    '</div>'
  ].join("\n"));

  return SirTrevor.Block.extend({

    type: "Markdown",

    editorHTML: function() {
      return md_template(this);
    },

    loadData: function(data){
      this.$('.st-markdown').html(data.text);
    },

    onBlockRender: function() {
      /* Make our expanding text area */
      var cont = this.$('.expanding-textarea'),
          area = cont.find('textarea'),
          span = cont.find('span');

      area.bind('input', function(){
        span.text(area.val());
      });

      cont.addClass('active');
    },

    toData: function() {
      var dataObj = {};

      dataObj.text = this.$('.st-markdown').val();
      this.setData(dataObj);
    }

  });

})();

And rename it from SirTrevor.Blocks.Markdown to anything else, it no longer shows as an option - even if I rename the type property to coincide with it.

Second, when I add the OrderedList custom block:

SirTrevor.Blocks.OrderedList = (function() {

  var template = '<div class="st-text-block" contenteditable="true"><ol><li></li></ol></div>';

  return SirTrevor.Block.extend({

    type: "OrderedList",

    editorHTML: function() {
      return _.template(template, this);
    },

    loadData: function(data){
      this.getTextBlock().html("<ol>" + SirTrevor.toHTML(data.text, this.type) + "<ol>");
    },

    onBlockRender: function() {
      this.checkForList = _.bind(this.checkForList, this);
      this.getTextBlock().on('click keyup', this.checkForList);
    },

    checkForList: function() {
      if (this.$('ol').length === 0) {
        document.execCommand("insertOrderedList", false, false);
      }
    },

    toMarkdown: function(markdown) {
      return markdown.replace(/<\/li>/mg,"\n")
                     .replace(/<\/?[^>]+(>|$)/g, "")
                     .replace(/^(.+)$/mg," 1. $1");
    },

    toHTML: function(html) {
      html = html.replace(/^ 1. (.+)$/mg,"<li>$1</li>")
                 .replace(/\n/mg, "");

      return html;
    }

  });

})();

It'll show in the list as an option, but when I click it, it does nothing; no new block is created.

Compiling to markdown/html

Is there a way to compile the JSON content to markdown or html? I see references in source code, but tried a few different combinations on, e.g. SirTrevor.toMarkdown and didn't get anything but errors.

Super block

Perhaps this goes against the design goals for this project, but would a 'super block' which groups standard blocks together be an option? For example a block which captures a title, image and text together as a unit, with each of those components consisting of a standard block. If there's a better way, I'm all ears!

Preload the block store?

I could not find any documentation on inputs to the editor, only outputs. Is there any way to load a json block into sir trevor? Thanks!

$$ not defined for custom blocks

I have the following code, which is a port of the markdown block in the sir-trevor-blocks repo to coffeescript:

MARKDOWN_TEMPLATE = '<div class="expanding-textarea"><pre><span></span><br></pre><textarea class="required <%= className %>"></textarea></div>'

SirTrevor.Blocks.Markdown = SirTrevor.Block.extend({
    title: "Markdown"
    className: "markdown"

    editorHTML: () -> _.template(MARKDOWN_TEMPLATE, this)

    onBlockRender: () ->
        cont = @$$('.expanding-textarea')
        area = cont.find('textarea')
        span = cont.find('span')
        area.bind('input', () -> span.text(area.val()))
        cont.addClass('active')

    loadData: (data) -> @$$('.markdown').html(data.text)

    toData: () ->
        @setData({
            "text": @$$('.markdown').val()
        })
})

When I add a markdown block, I get the error: Uncaught TypeError: Object [object Object] has no method '$$' from the reference to @$$ in toData (@ in coffeescript is short-hand for this). Has $$ been deprecated? If so, the documentation here should be updated: https://github.com/madebymany/sir-trevor-js/wiki/Creating%20your%20own%20Block%20types

Version mismatch on `bower.json`

Hi! I've found this when installing with bower:

$ bower install sir-trevor-js --save
bower caching git://github.com/madebymany/sir-trevor-js.git
bower cloning git://github.com/madebymany/sir-trevor-js.git
bower fetching sir-trevor-js
bower checking out sir-trevor-js#v0.3.0-rc.5
bower copying C:\Users\Daniela\AppData\Roaming\bower\cache\sir-trevor-js\d672c6af7fd18ce95ffc38855014ce8d
mismatch The version specified in the bower.json of package sir-trevor-js mismatches the tag (0.3.0-rc.5 vs 0.3.0-rc.4)
mismatch You should report this problem to the package author

jQuery 1.7.2

Hey guys,

Just a query: why does Sir Trevor have a dependency on such an old version of jQuery? I've been integrating it into a Rails 3.2 app with Active Admin and obviously there's a major version clash with Rails being on 1.9.1 now. I've included the jQuery Migrate plugin to polyfill for the moment.

Do you have any estimates as to how much would be involved to upgrade Trev to 1.9 compatibility?

Cheers!

Document complete examples of image uploading

I don't think the docs give a complete enough idea of how upload mechanisms need to be architected. It would be good to see a couple of tutorials on how to get image uploads working, for a couple of different technology stacks.

Personally I'd like to see:

  • One barebones, minimal-framework example (e.g. Node.js + Express), so it's easy to understand the basics of the contract between the server and the ST frontend – what the frontend sends, and what kind of responses it expects from the server... and how this all fits with the wider subject of filling and submitting the form
  • One framework-heavy example, using e.g. Rails + sir-trevor-rails + Paperclip + Amazon S3

I'm currently 60% through setting up a Rails/Paperclip/S3 upload system for a client's site – I could try and write that up when I'm done, if there's interest. In the meantime, if there are any existing tutorials I might have missed, let me know, I'm basically just muddling my way through at the moment...

Nested instances/block types

I've been trying to set up nested instances of Sir Trevor so that, in a textarea inside of a custom block, further selective block types can be inserted based of the block type of it's parent. However, this does not seem to work.

Issue: Sir Trevor doesn't recognise/deal with nested blocks and nested instances
To replicate: Insertion of a new instance of ST inside a textarea within a custom block
Actual result: ST does not return content from new instance, only a plain-text scrape
Expected result: ST returns content from nested instances

Remove formatting on pasted content

Not so much an 'issue' as something to think about.

As it stands, when something is pasted in we transform to Markdown then back to HTML, presumably this is to mirror, as closely as possible, the actions that are taken when saving, previewing, then editing to give as accurate as possible a representation of what it will look like to an end user.

Sadly, as discussed, this method will never really work smoothly due to the limitations and general cluster-fuckery of contentEditable.

The ideal solution is that, on paste, all formatting is removed using the native remove formatting methods, leaving plain text which is then transformed by direct user action (be it contentEditable methods or otherwise) to look as required, this can then be reliably transformed into clean Markdown.

While this works in theory, in practice I found it nearly impossible due to not being able to differentiate between content that had just been pasted into a block, and content that was already there - I didn't feel that removing formatting from the entire block every time someone pasted something into it was an acceptable solution.

Things I tried:

  1. Hijack paste, put it into a standard textarea, then take the content from said textarea (now that it's in plain text) and insert it into the contentEditable (didn't work, couldn't find a way to hijack it reliably)
  2. Detect caret position on paste, calculate paste length, select area then remove formatting. Again, couldn't make it work.

I'm sure there is a way that doesn't resort to endless reams of regex, but sadly I ran out of time experimenting with this

If anyone younger, hipper and smarter than me can work it out, please do.

Gemfile and Rake

Hello, I just forked and I was wondering, why is there included a Gemfile with Rake support? Is it to run the specs in the browser? Thanks and keep up the good work!

Drag video doesn't seem to have functionality

Great job with sir-trevor-js, it's really great.

I've been to drag video's on it, but it doesn't seem to have functionality. What is the porpose of this?

Do you want to upload video files in it (like the images) and then let them play using javascript-video-player?

I even could implement it myself and upload it to here. But i'd like to know what you're planning with it :)

Text formatting bar doesn't always render

If you select text then move the mouse cursor outside of a text area (while still holding down on the mouse button) and then release it will not render the text formatting controls (b, i, link, unlink).

This is somewhat of an edge case as it only really occurs when you are trying to select all text in a text block.

Improve keyboard navigation

You should be able to do everything using the keyboard - not having to rely on a mouse.

Some improvements off the top of my head:

  • Add/remove a content section
  • Highlighting the currently edited section
  • Rearrange sections
  • Add/remove a link
  • Tooltips for each button/item indicating the shortcut

how do you get the json?

the website docs say everything is stored in json, but nothing about what method you call ,on what I presume is the editor object, to get the json

Uncaught error causes 'save' to fail when form submitted

Using the latest build in master, I had a bug where SirTrevor wasn't saving anything. I would add some blocks and submit the form, but no data would arrive in my backend, i.e. ST didn't insert any JSON into the textarea when I submitted the form.

I haven't got time to work out the root cause and do a PR but thought I'd share what I know...

I found the problem was this line:

_.each(this.required, blockTypeIterator, this);

I added a console log just before this line, and it turned out this.required was false, which was causing an error (TypeError: Object.keys called on non-object). (It took a while to discover this because the form gets submitted anyway, so I didn't see the error in the console.) Wrapping that line in if (_.isArray(this.required)) {...} fixed it for me.

I was not using any custom settings - my instantiation code was just: new SirTrevor.Editor({el: $('.st-instance')});.

Hope this helps.

How do I save the input?

How do I actually save what I input with Sir Trevor?

I took a look at the example, added a submit button and removed the event listener that stopped submissions. Set the <form> tag’s action to a PHP script that dumps the contents of any POST requests, but when I submit the form the POST data is empty?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.