From 376b4f8b352d04e6a4d93758c54d6ca21c074e9a Mon Sep 17 00:00:00 2001 From: henning-krause Date: Mon, 6 Jun 2016 10:28:41 +0200 Subject: [PATCH] Initial checkin --- .tfignore | 4 + build/paths.js | 21 +++++ build/tasks/build.js | 43 +++++++++ build/tasks/watch.js | 16 ++++ dist/aurelia-froala.html | 3 + dist/aurelia-froala.js | 194 +++++++++++++++++++++++++++++++++++++++ dist/index.js | 41 +++++++++ gulpfile.js | 6 ++ package.json | 47 ++++++++++ readme.md | 97 ++++++++++++++++++++ src/aurelia-froala.html | 3 + src/aurelia-froala.js | 87 ++++++++++++++++++ src/index.js | 28 ++++++ 13 files changed, 590 insertions(+) create mode 100644 .tfignore create mode 100644 build/paths.js create mode 100644 build/tasks/build.js create mode 100644 build/tasks/watch.js create mode 100644 dist/aurelia-froala.html create mode 100644 dist/aurelia-froala.js create mode 100644 dist/index.js create mode 100644 gulpfile.js create mode 100644 package.json create mode 100644 readme.md create mode 100644 src/aurelia-froala.html create mode 100644 src/aurelia-froala.js create mode 100644 src/index.js diff --git a/.tfignore b/.tfignore new file mode 100644 index 0000000..0d3d9e3 --- /dev/null +++ b/.tfignore @@ -0,0 +1,4 @@ +build\* +dist\* +jspm_packages\* +node_modules\* \ No newline at end of file diff --git a/build/paths.js b/build/paths.js new file mode 100644 index 0000000..563c0d9 --- /dev/null +++ b/build/paths.js @@ -0,0 +1,21 @@ +var appRoot = 'src/'; +var outputRoot = 'dist/'; +var exporSrvtRoot = 'export/'; +var jspmPackages = 'jspm_packages/'; +var typings = 'typings/'; + +module.exports = { + root: appRoot, + source: appRoot + '**/*.js', + sourceMaps: "../maps", + html: appRoot + '**/*.html', + css: appRoot + '**/*.css', + sass: 'styles/**/*.scss', + cssOutput: outputRoot, + style: 'styles/**/*.css', + output: outputRoot, + exportSrv: exporSrvtRoot, + doc: './doc', + e2eSpecsSrc: 'test/e2e/src/*.js', + e2eSpecsDist: 'test/e2e/dist/', +}; diff --git a/build/tasks/build.js b/build/tasks/build.js new file mode 100644 index 0000000..0780489 --- /dev/null +++ b/build/tasks/build.js @@ -0,0 +1,43 @@ +'use strict' + +var gulp = require('gulp'); +var bump = require('gulp-bump') +var babel = require('gulp-babel'); +var sourcemaps = require('gulp-sourcemaps'); +var changed = require('gulp-changed'); +var runSequence = require('run-sequence'); +var paths = require("../paths") + +var compilerOptions = { + moduleIds: false, + comments: false, + compact: false, + presets: ["es2015", "stage-0"], + plugins: ["transform-es2015-modules-systemjs", "transform-decorators-legacy", "transform-decorators", ] +}; + +gulp.task('build-html', function() { + return gulp.src(paths.html) + .pipe(gulp.dest(paths.output)); +}); + +gulp.task('build-js', function() { + return gulp.src(paths.source) + .pipe(changed(paths.output), {extension: '.js'}) +// .pipe(sourcemaps.init({loadMaps: true})) + .pipe(babel(compilerOptions)) +// .pipe(sourcemaps.write({includeContent: true})) + .pipe(gulp.dest(paths.output)); +}); + +gulp.task('bump-version', function() { + return gulp.src('./package.json') + .pipe(bump({type: 'patch'})) + .pipe(gulp.dest('./')); + +}) + gulp.task('build', function(callback) { + return runSequence( + ['build-html', 'build-js'], + callback + )}); diff --git a/build/tasks/watch.js b/build/tasks/watch.js new file mode 100644 index 0000000..c60c2a9 --- /dev/null +++ b/build/tasks/watch.js @@ -0,0 +1,16 @@ +var gulp = require('gulp'); +var paths = require('../paths'); + +// outputs changes to files to the console +function reportChange(event) { + console.log('File ' + event.path + ' was ' + event.type + ', running tasks...'); +} + +// this task wil watch for changes +// to js, html, and css files and call the +// reportChange method. Also, by depending on the +// serve task, it will instantiate a browserSync session +gulp.task('watch', ['build'], function() { + gulp.watch(paths.source, ['build-js']).on('change', reportChange); + gulp.watch(paths.html, ['build-html']).on('change', reportChange); +}); diff --git a/dist/aurelia-froala.html b/dist/aurelia-froala.html new file mode 100644 index 0000000..6c57829 --- /dev/null +++ b/dist/aurelia-froala.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/dist/aurelia-froala.js b/dist/aurelia-froala.js new file mode 100644 index 0000000..1abf0d9 --- /dev/null +++ b/dist/aurelia-froala.js @@ -0,0 +1,194 @@ +'use strict'; + +System.register(['aurelia-framework', 'aurelia-binding', 'aurelia-i18n', 'jquery', 'aurelia-event-aggregator'], function (_export, _context) { + "use strict"; + + var customElement, bindable, inject, ObserverLocator, I18N, $, EventAggregator, _createClass, _dec, _dec2, _class, _desc, _value, _class2, _descriptor, _descriptor2, _descriptor3, AureliaFroala; + + function _initDefineProp(target, property, descriptor, context) { + if (!descriptor) return; + Object.defineProperty(target, property, { + enumerable: descriptor.enumerable, + configurable: descriptor.configurable, + writable: descriptor.writable, + value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 + }); + } + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { + var desc = {}; + Object['ke' + 'ys'](descriptor).forEach(function (key) { + desc[key] = descriptor[key]; + }); + desc.enumerable = !!desc.enumerable; + desc.configurable = !!desc.configurable; + + if ('value' in desc || desc.initializer) { + desc.writable = true; + } + + desc = decorators.slice().reverse().reduce(function (desc, decorator) { + return decorator(target, property, desc) || desc; + }, desc); + + if (context && desc.initializer !== void 0) { + desc.value = desc.initializer ? desc.initializer.call(context) : void 0; + desc.initializer = undefined; + } + + if (desc.initializer === void 0) { + Object['define' + 'Property'](target, property, desc); + desc = null; + } + + return desc; + } + + function _initializerWarningHelper(descriptor, context) { + throw new Error('Decorating class property failed. Please ensure that transform-class-properties is enabled.'); + } + + return { + setters: [function (_aureliaFramework) { + customElement = _aureliaFramework.customElement; + bindable = _aureliaFramework.bindable; + inject = _aureliaFramework.inject; + }, function (_aureliaBinding) { + ObserverLocator = _aureliaBinding.ObserverLocator; + }, function (_aureliaI18n) { + I18N = _aureliaI18n.I18N; + }, function (_jquery) { + $ = _jquery.default; + }, function (_aureliaEventAggregator) { + EventAggregator = _aureliaEventAggregator.EventAggregator; + }], + execute: function () { + _createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + _export('AureliaFroala', AureliaFroala = (_dec = customElement('aurelia-froala'), _dec2 = inject(Element, ObserverLocator, I18N, EventAggregator), _dec(_class = _dec2(_class = (_class2 = function () { + function AureliaFroala(element, observerLocator, i18n, eventAggregator) { + var _this = this; + + _classCallCheck(this, AureliaFroala); + + _initDefineProp(this, 'value', _descriptor, this); + + _initDefineProp(this, 'config', _descriptor2, this); + + _initDefineProp(this, 'eventHandlers', _descriptor3, this); + + this.i18nInitialized = false; + + this.element = element; + this.subscriptions = [observerLocator.getObserver(this, 'value').subscribe(function (newValue, oldValue) { + if (_this.instance && _this.instance.froalaEditor('html.get') != newValue) { + _this.instance.froalaEditor('html.set', newValue); + _this.updateEmptyStatus(); + } + })]; + this.i18n = i18n; + eventAggregator.subscribe('i18n:locale:changed', function (payload) { + _this.processLanguageChanged(); + }); + } + + _createClass(AureliaFroala, [{ + key: 'processLanguageChanged', + value: function processLanguageChanged() { + this.tearDownFroala(); + this.setupFroala(); + } + }, { + key: 'setupFroala', + value: function setupFroala() { + var _this2 = this; + + this.instance = $(this.element.getElementsByTagName("div")[0]); + + if (this.instance.data('froala.editor')) { + return; + } + var c = {}; + c.language = this.i18n.getLocale(); + Object.assign(c, this.config); + this.instance.froalaEditor(c); + this.instance.froalaEditor('html.set', this.value); + if (this.eventHandlers && this.eventHandlers.length != 0) { + var _loop = function _loop(eventHandlerName) { + var handler = _this2.eventHandlers[eventHandlerName]; + _this2.instance.on('froalaEditor.' + eventHandlerName, function () { + var p = arguments; + return handler.apply(this, p); + }); + }; + + for (var eventHandlerName in this.eventHandlers) { + _loop(eventHandlerName); + } + } + } + }, { + key: 'updateEmptyStatus', + value: function updateEmptyStatus() {} + }, { + key: 'tearDownFroala', + value: function tearDownFroala() { + if (this.instance && this.instance.data('froala.editor')) { + this.instance.froalaEditor('destroy'); + } + this.instance = null; + } + }, { + key: 'attached', + value: function attached() { + this.setupFroala(); + } + }, { + key: 'detached', + value: function detached() { + this.tearDownFroala(); + } + }]); + + return AureliaFroala; + }(), (_descriptor = _applyDecoratedDescriptor(_class2.prototype, 'value', [bindable], { + enumerable: true, + initializer: null + }), _descriptor2 = _applyDecoratedDescriptor(_class2.prototype, 'config', [bindable], { + enumerable: true, + initializer: function initializer() { + return {}; + } + }), _descriptor3 = _applyDecoratedDescriptor(_class2.prototype, 'eventHandlers', [bindable], { + enumerable: true, + initializer: function initializer() { + return {}; + } + })), _class2)) || _class) || _class)); + + _export('AureliaFroala', AureliaFroala); + } + }; +}); \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..2290f0c --- /dev/null +++ b/dist/index.js @@ -0,0 +1,41 @@ +"use strict"; + +System.register(["font-awesome/./css/font-awesome.min.css!", "jquery", "froala-editor/./js/froala_editor.min", "froala-editor/css/froala_editor.min.css!", "froala-editor/css/froala_style.min.css!"], function (_export, _context) { + "use strict"; + + var $, froala; + return { + setters: [function (_fontAwesomeCssFontAwesomeMinCss) {}, function (_jquery) { + $ = _jquery.default; + }, function (_froalaEditorJsFroala_editorMin) { + froala = _froalaEditorJsFroala_editorMin; + }, function (_froalaEditorCssFroala_editorMinCss) {}, function (_froalaEditorCssFroala_styleMinCss) {}], + execute: function () { + function configure(aurelia, config) { + aurelia.globalResources('./aurelia-froala'); + var c = { + addPlugin: function addPlugin(name) { + return Promise.all([System.import("froala-editor/js/plugins/" + name + ".min", _context.id).then(function (m) { + return m(); + }), System.import("froala-editor/css/plugins/" + name + ".css!", _context.id).catch(function (e) {})]); + }, + global: function global(callback) { + callback($.FroalaEditor); + }, + addDefaltOptions: function addDefaltOptions(options) { + $.FroalaEditor.DEFAULTS = $.extend($.FroalaEditor.DEFAULTS, options); + }, + addLanguage: function addLanguage(language, additionalTranslations) { + return System.import("froala-editor/js/languages/" + language, _context.id).then(function () { + return additionalTranslations && Object.assign($.FE.LANGUAGE[language].translation, additionalTranslations); + }); + } + }; + froala.default(); + config(c); + } + + _export("configure", configure); + } + }; +}); \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..23a366a --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,6 @@ +/// +// all gulp tasks are located in the ./build/tasks directory +// gulp configuration is in files in ./build directory +//require('require-dir')('build/tasks'); + +require('require-dir')('build/tasks'); diff --git a/package.json b/package.json new file mode 100644 index 0000000..56dc516 --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "name": "aurelia-froala", + "version": "1.0.3", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "directories": { + "lib": "dist", + "src": "src" + }, + "author": "Net at Work GmbH", + "license": "MIT", + "devDependencies": { + "babel": "^6.3.26", + "babel-plugin-transform-decorators": "^6.8.0", + "babel-plugin-transform-decorators-legacy": "^1.3.4", + "babel-plugin-transform-es2015-modules-systemjs": "^6.9.0", + "babel-preset-es2015": "^6.9.0", + "babel-preset-stage-0": "^6.3.13", + "babel-runtime": "^6.9.0", + "core-js": "^2.4.0", + "gulp": "^3.9.0", + "gulp-babel": "^6.1.1", + "gulp-bump": "^2.1.0", + "gulp-changed": "^1.3.0", + "gulp-sourcemaps": "^1.6.0", + "require-dir": "^0.3.0", + "run-sequence": "^1.2.1" + }, + "dependencies": { + "aurelia-binding": "^1.0.0-beta.1.0.1", + "aurelia-framework": "^1.0.0-beta.1.1.1", + "font-awesome": "^4.6.3", + "froala-editor": "^2.3.0", + "jquery": "^2.2.4" + }, + "jspm": { + "dependencies": { + "css": "jspm:css", + "froala-editor": "npm:froala-editor", + "jquery": "npm:jquery", + "font-awesome": "npm:font-awesome" + } + } +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..5a6da96 --- /dev/null +++ b/readme.md @@ -0,0 +1,97 @@ +aurelia-froala +=== +[![NPM version][npm-image]][npm-url] + +This package provides a custom element for the (Froala editor)[https://www.froala.com/wysiwyg-editor] in [Aurelia](http://aurelia.io/). + +##Version 2 +This repository contains bindings for the latest version of the Froala Editor (version 2). Version 1 of Froala is not supported. + + +##Install + +Run +`` + jspm install aurelia-froala +`` + +In your main.js or main.ts, extend the code + +``` + aurelia.use + .standardConfiguration() +``` + +with +``` + .plugin('aurelia-froala', config => {} +``` + +In an Aurelia template, just use the aurelia-froala custom element to instantiate an editor. All (configuration options)[https://www.froala.com/wysiwyg-editor/docs/options] can be set via the config attribute. + +``` + + +``` + +All the (event handlers)[https://www.froala.com/wysiwyg-editor/docs/events] are also available: +``` + { + // Load plugins + config.addPlugin("colors"); + config.addPlugin("align"); + config.addPlugin("code_beautifier"); + config.addPlugin("image") // The image_manager plugin depends on the image plugin, so the former needs to loaded after the latter. + .then(() => config.addPlugin("image_manager")); + + // Create a custom button + config.global(editor => { + // Define an icon + editor.DefineIcon("insertFromServerIcon", {NAME: "folder"}) + // Register the new command. It can now be added to a toolbar using the command 'insertFromServer' + editor.RegisterCommand('insertFromServer', { + title: 'Insert from server', + icon: 'insertFromServerIcon', + undo: true, + focus: true, + refreshAfterCallback: true, + callback: function () { + console.log("Insert from server"); + } + }); + }); + + // Add another language + config.addLanguage("de", { + "Insert from server": "Vom Server einfügen", + }) + }) + } +``` +If you add custom plugins or commands you might want to localize them. This is done by providing the localized strings in the second parameter of the addLanguage method. + +The languages of all editors on a page are automatically adjusted when the global aurelia language is changed. You don't have to perform any additional magic. + +#Licencing +While this package is licenced under the Apache licence, the Froala editor itself is not. Check out the (Froala Website)[https://www.froala.com/wysiwyg-editor] for details. \ No newline at end of file diff --git a/src/aurelia-froala.html b/src/aurelia-froala.html new file mode 100644 index 0000000..6c57829 --- /dev/null +++ b/src/aurelia-froala.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/src/aurelia-froala.js b/src/aurelia-froala.js new file mode 100644 index 0000000..d76d95f --- /dev/null +++ b/src/aurelia-froala.js @@ -0,0 +1,87 @@ +'use strict' +import {customElement, bindable, inject} from 'aurelia-framework'; +import {ObserverLocator} from "aurelia-binding"; +import {I18N} from "aurelia-i18n"; +import $ from "jquery"; +import {EventAggregator} from 'aurelia-event-aggregator'; + +@customElement('aurelia-froala') +@inject(Element, ObserverLocator, I18N, EventAggregator) +export class AureliaFroala { + @bindable value; + @bindable config = {} + @bindable eventHandlers = {} + + element; + instance; + i18n; + i18nInitialized = false; + + constructor(element, observerLocator, i18n, eventAggregator) { + this.element = element; + this.subscriptions = [ + observerLocator + .getObserver(this, 'value') + .subscribe((newValue, oldValue) => { + if (this.instance && this.instance.froalaEditor('html.get') != newValue) { + this.instance.froalaEditor('html.set', newValue); + this.updateEmptyStatus(); + } + }) + ]; + this.i18n = i18n; + eventAggregator.subscribe('i18n:locale:changed', payload => { + this.processLanguageChanged(); + }); + } + + processLanguageChanged() { + this.tearDownFroala(); + this.setupFroala(); + } + + + setupFroala() { + this.instance = $(this.element.getElementsByTagName("div")[0]); + + if (this.instance.data('froala.editor')) { + return; + } + let c = {} + c.language = this.i18n.getLocale(); + Object.assign(c, this.config); + this.instance.froalaEditor(c); + this.instance.froalaEditor('html.set', this.value); + if (this.eventHandlers && this.eventHandlers.length != 0) { + for(let eventHandlerName in this.eventHandlers) { + let handler = this.eventHandlers[eventHandlerName]; + this.instance.on(`froalaEditor.${eventHandlerName}`, function() { + let p = arguments; + return handler.apply(this, p) + }); + + } + } + } + + updateEmptyStatus() { + + } + + tearDownFroala() { + if (this.instance && this.instance.data('froala.editor')) { + this.instance.froalaEditor('destroy'); + } + this.instance = null; + } + + attached() { + this.setupFroala(); + } + + + + detached() { + this.tearDownFroala(); + } +} \ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..a940d16 --- /dev/null +++ b/src/index.js @@ -0,0 +1,28 @@ + +import "font-awesome/./css/font-awesome.min.css!"; +import $ from "jquery"; +import * as froala from "froala-editor/./js/froala_editor.min"; +import "froala-editor/css/froala_editor.min.css!"; +import "froala-editor/css/froala_style.min.css!"; + +export function configure(aurelia, config) { + aurelia.globalResources('./aurelia-froala'); + let c = { + addPlugin: name => Promise.all( + [System.import(`froala-editor/js/plugins/${name}.min`, __moduleName).then(m=> m()), + System.import(`froala-editor/css/plugins/${name}.css!`, __moduleName).catch(e => {})]), + global: callback => { + callback($.FroalaEditor); + }, + addDefaltOptions: options => { + $.FroalaEditor.DEFAULTS = $.extend($.FroalaEditor.DEFAULTS, options); + }, + addLanguage: (language, additionalTranslations) => { + return System + .import(`froala-editor/js/languages/${language}`, __moduleName) + .then(() => additionalTranslations && Object.assign($.FE.LANGUAGE[language].translation, additionalTranslations)) + } + }; + froala.default(); + config(c); +} \ No newline at end of file