diff --git a/.gitignore b/.gitignore index 0bda6b1..294e34a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ node_modules -app/components -components +bower_components .idea diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 8c21bba..d7cadc5 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -5,46 +5,22 @@ module.exports = (grunt) -> grunt.initConfig pkg: grunt.file.readJSON 'package.json' meta: - src: 'src' test: 'test' - target: '<%= pkg.name %>.js' - banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' + - '<%= grunt.template.today("yyyy-mm-dd") %>\n' + - '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + - '* Copyright (c) <%= grunt.template.today("yyyy") %>' + - ' <%= pkg.author.name %>;' + - ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n' - clean: target: src: ['<%= pkg.title %>.js'] - coffeelint: - src: - files: src: ['<%= meta.src %>/**/*.coffee'] - options: max_line_length: level: 'warn' - test: - files: src: ['<%= meta.src %>/**/*.coffee'] - options: max_line_length: level: 'warn' - gruntfile: - files: src: ['Gruntfile.coffee'] - coffee: src: - files: - '<%= meta.target %>': [ - '<%= meta.src %>/**/*.coffee' - ] karma: - unit: configFile: 'test/config-unit.coffee' - e2e: configFile: 'test/config-e2e.coffee' + unit: configFile: 'test/unit.karma.coffee' + e2e: configFile: 'test/e2e.karma.coffee' unit_ci: - configFile: 'test/config-unit.coffee' + configFile: 'test/unit.karma.coffee' singleRun: true browsers: ['PhantomJS'] e2e_ci: - configFile: 'test/config-e2e.coffee' + configFile: 'test/e2e.karma.coffee' singleRun: true browsers: ['PhantomJS'] - jshint: target: ['<%= meta.target %>'] + jshint: src: ['angular-contenteditable.js'] require('matchdep').filterDev('grunt-*').forEach grunt.loadNpmTasks grunt.registerTask 'test', ['karma:e2e_ci'] - grunt.registerTask 'lint', ['coffeelint'] - grunt.registerTask 'build', ['clean', 'coffee'] - grunt.registerTask 'default', ['lint' , 'test', 'build', 'jshint'] + grunt.registerTask 'lint', ['jshint'] + grunt.registerTask 'default', ['lint' , 'test'] diff --git a/angular-contenteditable.js b/angular-contenteditable.js index 89248a1..57653e4 100644 --- a/angular-contenteditable.js +++ b/angular-contenteditable.js @@ -1,70 +1,72 @@ -(function() { - angular.module('contenteditable', []).directive('contenteditable', function() { - return { - require: 'ngModel', - link: function(scope, elmt, attrs, ngModel) { - var old_render; - elmt.bind('input', function(e) { - return scope.$apply(function() { - var html, html2, rerender; - html = elmt.html(); - rerender = false; - if (attrs.stripBr && attrs.stripBr !== "false") { - html = html.replace(/
$/, ''); - } - if (attrs.noLineBreaks && attrs.noLineBreaks !== "false") { - html2 = html.replace(/
/g, '').replace(/
/g, '').replace(/<\/div>/g, ''); - if (html2 !== html) { - rerender = true; - html = html2; - } - } - ngModel.$setViewValue(html); - if (rerender) { - ngModel.$render(); - } - if (html === '') { - elmt.blur(); - return elmt.focus(); - } - }); - }); - old_render = ngModel.$render; - ngModel.$render = function() { - var el, el2, range, sel; - if (old_render != null) { - old_render(); - } - elmt.html(ngModel.$viewValue || ''); - el = elmt.get(0); - range = document.createRange(); - sel = window.getSelection(); - if (el.childNodes.length > 0) { - el2 = el.childNodes[el.childNodes.length - 1]; - range.setStartAfter(el2); - } else { - range.setStartAfter(el); - } - range.collapse(true); - sel.removeAllRanges(); - return sel.addRange(range); - }; - if (attrs.selectNonEditable && attrs.selectNonEditable !== "false") { - return elmt.click(function(e) { - var range, sel, target; - target = e.toElement; - if (target !== this && angular.element(target).attr('contenteditable') === 'false') { - range = document.createRange(); - sel = window.getSelection(); - range.setStartBefore(target); - range.setEndAfter(target); - sel.removeAllRanges(); - return sel.addRange(range); +angular.module('contenteditable', []) + .directive('contenteditable', function() { return { + require: 'ngModel', + link: function($scope, $element, attrs, ngModel) { + var old_render; + // view -> model + $element.bind('input', function(e) { + $scope.$apply(function() { + var html, html2, rerender; + html = $element.html(); + rerender = false; + if (attrs.stripBr && attrs.stripBr !== "false") { + html = html.replace(/
$/, ''); + } + if (attrs.noLineBreaks && attrs.noLineBreaks !== "false") { + html2 = html.replace(/
/g, '').replace(/
/g, '').replace(/<\/div>/g, ''); + if (html2 !== html) { + rerender = true; + html = html2; + } + } + ngModel.$setViewValue(html); + if (rerender) { + ngModel.$render(); + } + if (html === '') { + // the cursor disappears if the contents is empty + // so we need to refocus + $element.blur(); + $element.focus(); + } + }); + }); + + // model -> view + old_render = ngModel.$render; + ngModel.$render = function() { + var el, el2, range, sel; + if (!!old_render) { + old_render(); + } + $element.html(ngModel.$viewValue || ''); + el = $element.get(0); + range = document.createRange(); + sel = window.getSelection(); + if (el.childNodes.length > 0) { + el2 = el.childNodes[el.childNodes.length - 1]; + range.setStartAfter(el2); + } else { + range.setStartAfter(el); + } + range.collapse(true); + sel.removeAllRanges(); + sel.addRange(range); + }; + if (attrs.selectNonEditable && attrs.selectNonEditable !== "false") { + $element.click(function(e) { + var range, sel, target; + target = e.toElement; + if (target !== this && angular.element(target).attr('contenteditable') === 'false') { + range = document.createRange(); + sel = window.getSelection(); + range.setStartBefore(target); + range.setEndAfter(target); + sel.removeAllRanges(); + sel.addRange(range); + } + }); } - }); } - } - }; - }); + };}); -}).call(this); diff --git a/bower.json b/bower.json index c239338..4a7f653 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-contenteditable", - "version": "0.3.1", + "version": "0.3.2", "main": "angular-contenteditable.js", "ignore": [ ".*", diff --git a/package.json b/package.json index 485dc21..ce647fe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-contenteditable", - "version": "0.3.1", + "version": "0.3.2", "description": "angular extensions", "main": "angular-contenteditable.js", "directories": { @@ -19,20 +19,11 @@ "devDependencies": { "matchdep": "~0.1.2", "grunt": "~0.4.1", - "grunt-contrib-concat": "~0.3.0", - "grunt-mocha-cli": "~1.0.6", - "should": "~1.2.2", - "grunt-coffee-redux": "~0.2.3", - "grunt-contrib-coffee": "~0.7.0", - "grunt-contrib-clean": "~0.5.0", - "grunt-contrib-watch": "~0.4.4", "grunt-contrib-jshint": "~0.6.0", - "grunt-coffeelint": "0.0.7", - "coffee-script": "~1.6.3", - "karma": "~0.9.4", "grunt-karma": "~0.5.0", + "karma": "~0.9.4", "karma-ng-scenario": "0.0.2", - "karma-coffee-preprocessor": "0.0.2", - "karma-mocha": "0.0.3" + "karma-mocha": "~0.0.3", + "karma-coffee-preprocessor": "0.0.2" } } diff --git a/src/contenteditable.coffee b/src/contenteditable.coffee deleted file mode 100644 index 6b8ece7..0000000 --- a/src/contenteditable.coffee +++ /dev/null @@ -1,52 +0,0 @@ -angular.module('contenteditable', []) -.directive('contenteditable', -> - require: 'ngModel', - link: (scope, elmt, attrs, ngModel) -> - # view -> model - elmt.bind 'input', (e) -> - scope.$apply -> - html = elmt.html() - rerender = false - if attrs.stripBr && attrs.stripBr != "false" - html = html.replace /
$/, '' - if attrs.noLineBreaks && attrs.noLineBreaks != "false" - html2 = html.replace(/
/g, '').replace(/
/g, '').replace(/<\/div>/g, '') - if html2 != html - rerender = true - html = html2 - ngModel.$setViewValue(html) - ngModel.$render() if rerender - if html == '' # the cursor if the contents is emty, so need to refocus - elmt.blur() - elmt.focus() - - # model -> view - old_render = ngModel.$render # save for later - ngModel.$render = -> - old_render() if old_render? - elmt.html(ngModel.$viewValue || '') - # move cursor to the end - el = elmt.get(0) - range = document.createRange() - sel = window.getSelection() - if el.childNodes.length > 0 - el2 = el.childNodes[el.childNodes.length - 1] - range.setStartAfter(el2) - else - range.setStartAfter(el) - range.collapse(true) - sel.removeAllRanges() - sel.addRange(range) - - # select whole sub-span if it has contenteditable="false" - if attrs.selectNonEditable && attrs.selectNonEditable != "false" - elmt.click (e) -> - target = e.toElement - if target != @ && angular.element(target).attr('contenteditable') == 'false' - range = document.createRange() - sel = window.getSelection() - range.setStartBefore(target) - range.setEndAfter(target) - sel.removeAllRanges() - sel.addRange(range) -) diff --git a/test/config-e2e.coffee b/test/config-e2e.coffee deleted file mode 100644 index 822565e..0000000 --- a/test/config-e2e.coffee +++ /dev/null @@ -1,52 +0,0 @@ -module.exports = (config) -> - toServe = for file in [ - 'components/bootstrap-css/css/bootstrap.css' - 'components/jquery/jquery.js' - 'components/angular-unstable/angular.js' - 'components/angular-bootstrap/ui-bootstrap.js' - 'components/angular-bootstrap/ui-bootstrap-tpls.js' - 'angular-contenteditable.js' - 'test/fixtures/simple.html' - 'test/fixtures/typeahead1.html' - 'test/fixtures/typeahead2.html' - 'test/fixtures/typeahead3.html' - 'test/fixtures/states.json' - 'test/fixtures/img/ru.gif' - 'test/fixtures/img/gb.gif' - 'test/fixtures/img/us.gif' - ] - pattern: file - watched: false - included: false - served: true - - config.set - basePath: '..' - - frameworks: ['ng-scenario'] - - preprocessors: '**/*.coffee': 'coffee' - - files: [ - 'test/e2e/**/*.coffee' - ].concat toServe - - exclude: [] - - reporters: ['progress'] - - port: 9876 - - runnerPort: 9100 - - colors: true - - logLevel: config.LOG_INFO - - autoWatch: true - - browsers: ['Chrome'] - - captureTimeout: 60000 - - singleRun: false diff --git a/test/e2e.karma.coffee b/test/e2e.karma.coffee new file mode 100644 index 0000000..d7617fb --- /dev/null +++ b/test/e2e.karma.coffee @@ -0,0 +1,42 @@ +module.exports = (karma) -> + toServe = for file in [ + 'bower_components/**/*.css' + 'bower_components/*/*.js' + 'test/fixtures/**/*' + ] + pattern: file + watched: false + included: false + served: true + + karma.set + basePath: '..' + + frameworks: ['ng-scenario'] + + preprocessors: '**/*.coffee': 'coffee' + + files: [ + 'test/e2e/**/*.coffee' + 'angular-contenteditable.js' + ].concat toServe + + exclude: [] + + reporters: ['progress'] + + port: 9876 + + runnerPort: 9100 + + colors: true + + logLevel: karma.LOG_INFO + + autoWatch: true + + browsers: ['Chrome'] + + captureTimeout: 60000 + + singleRun: false diff --git a/test/fixtures/no-line-breaks.html b/test/fixtures/no-line-breaks.html index dd2fca4..0091be8 100644 --- a/test/fixtures/no-line-breaks.html +++ b/test/fixtures/no-line-breaks.html @@ -3,8 +3,8 @@ Simple - - + + - + + - + + - + + - - - + + + + + - - - + + + + + - - - + + + + +