Compare commits

...

17 Commits

Author SHA1 Message Date
Chakib Benziane 7571d66905 fixes #34 9 years ago
Dmitri Akatov 4cc8e467bd Merge pull request #32 from kathygit/master
add ";" at the end of the js file so that the minified version works
10 years ago
Kathy Laird 9eb48567ab add ; at the end of the js file so that the minified version works 10 years ago
Dmitri Akatov 9a1471d23c 0.3.7 10 years ago
Dmitri Akatov 18691f1441 don't need karma-mocha 10 years ago
Dmitri Akatov 06ae4fc77a simpler karma usage (there are no unit tests) 10 years ago
Dmitri Akatov d7771af3c7 move bower dependency on angular to development, and use angular instead of angular unstable 10 years ago
Dmitri Akatov 8a3ae75892 moved angular-unstable to development dependency 10 years ago
Dmitri Akatov 8c7ad58a05 bumped grunt and bower versions 10 years ago
Dmitri Akatov 543c491b5f commands are run from local bin directory anyways 10 years ago
Dmitri Akatov f8da2a127e use shields.io images 10 years ago
Dmitri Akatov ac284284ca added License 11 years ago
Dmitri Akatov 6197aca95c Merge pull request #18 from Narretz/patch-1
added note that directive is broken in IE and Opera < 15
11 years ago
Narretz 60dde289a3 added note that directive is broken in IE and Opera < 15
This might save some people some time that need to support IE, but that only test it when they are finished.
11 years ago
Dmitri Akatov 64fd235450 only move caret to end on model change when the corresponding attribute is set 11 years ago
Dmitri Akatov dd8ac4dc44 pull out options first 11 years ago
Dmitri Akatov 52d84c973e these variables aren't injections 11 years ago

@ -7,14 +7,9 @@ module.exports = (grunt) ->
meta:
test: 'test'
karma:
unit: configFile: 'test/unit.karma.coffee'
e2e: configFile: 'test/e2e.karma.coffee'
unit_ci:
configFile: 'test/unit.karma.coffee'
singleRun: true
browsers: ['PhantomJS']
e2e: configFile: 'karma.coffee'
e2e_ci:
configFile: 'test/e2e.karma.coffee'
configFile: 'karma.coffee'
singleRun: true
browsers: ['PhantomJS']
jshint:

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013 Dmitri Akatov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

@ -1,7 +1,6 @@
# angular-contenteditable
[![Build Status](https://travis-ci.org/akatov/angular-contenteditable.png)](https://travis-ci.org/akatov/angular-contenteditable)
[![Dependency Status](https://gemnasium.com/akatov/angular-contenteditable.png)](https://gemnasium.com/akatov/angular-contenteditable)
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/akatov/angular-contenteditable/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
[![Build Status](https://img.shields.io/travis/akatov/angular-contenteditable.svg)](https://travis-ci.org/akatov/angular-contenteditable)
[![Dependency Status](https://img.shields.io/gemnasium/akatov/angular-contenteditable.svg)](https://gemnasium.com/akatov/angular-contenteditable)
[![endorse](https://api.coderwall.com/akatov/endorsecount.png)](https://coderwall.com/akatov)
An AngularJS directive to bind html tags with the `contenteditable` attribute to models.
@ -33,10 +32,13 @@ angular.module('myapp', ['contenteditable'])
## Notice
The directive currently does not work in any version of Internet Explorer or Opera < 15.
Both browsers don't fire the `input` event for contenteditable fields.
In Chrome, when a contenteditable element X contains a non-contenteditable
element Y as the last element, then the behaviour of the caret is the following:
* When X has style `dislay` set to `block` or `inline-block`, then the caret
* When X has style `display` set to `block` or `inline-block`, then the caret
moves to the very far right edge of X when it is _immediately_ at the end of X
(inserting spaces moves the caret back).

@ -8,22 +8,34 @@ angular.module('contenteditable', [])
.directive('contenteditable', ['$timeout', function($timeout) { return {
restrict: 'A',
require: '?ngModel',
link: function($scope, $element, attrs, ngModel) {
link: function(scope, element, attrs, ngModel) {
// don't do anything unless this is actually bound to a model
if (!ngModel) {
return
}
// options
var opts = {}
angular.forEach([
'stripBr',
'noLineBreaks',
'selectNonEditable',
'moveCaretToEndOnChange',
], function(opt) {
var o = attrs[opt]
opts[opt] = o && o !== 'false'
})
// view -> model
$element.bind('input', function(e) {
$scope.$apply(function() {
element.bind('input', function(e) {
scope.$apply(function() {
var html, html2, rerender
html = $element.html()
html = element.text()
rerender = false
if (attrs.stripBr && attrs.stripBr !== "false") {
if (opts.stripBr) {
html = html.replace(/<br>$/, '')
}
if (attrs.noLineBreaks && attrs.noLineBreaks !== "false") {
if (opts.noLineBreaks) {
html2 = html.replace(/<div>/g, '').replace(/<br>/g, '').replace(/<\/div>/g, '')
if (html2 !== html) {
rerender = true
@ -38,8 +50,8 @@ angular.module('contenteditable', [])
// the cursor disappears if the contents is empty
// so we need to refocus
$timeout(function(){
$element[0].blur()
$element[0].focus()
element[0].blur()
element[0].focus()
})
}
})
@ -52,22 +64,24 @@ angular.module('contenteditable', [])
if (!!oldRender) {
oldRender()
}
$element.html(ngModel.$viewValue || '')
el = $element[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)
element.html(ngModel.$viewValue || '')
if (opts.moveCaretToEndOnChange) {
el = element[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)
}
range.collapse(true)
sel.removeAllRanges()
sel.addRange(range)
}
if (attrs.selectNonEditable && attrs.selectNonEditable !== "false") {
$element.bind('click', function(e) {
if (opts.selectNonEditable) {
element.bind('click', function(e) {
var range, sel, target
target = e.toElement
if (target !== this && angular.element(target).attr('contenteditable') === 'false') {
@ -81,4 +95,4 @@ angular.module('contenteditable', [])
})
}
}
}}])
}}]);

@ -1,6 +1,6 @@
{
"name": "angular-contenteditable",
"version": "0.3.6",
"version": "0.3.7",
"main": "angular-contenteditable.js",
"ignore": [
".*",
@ -12,10 +12,8 @@
"src",
"test"
],
"dependencies": {
"angular-unstable": "~1.1.5"
},
"devDependencies": {
"angular": "*",
"angular-mocks": "~1.0.5",
"angular-scenario": "~1.0.5",
"expect": "~0.2.0",

@ -10,8 +10,6 @@ module.exports = (karma) ->
served: true
karma.set
basePath: '..'
frameworks: ['ng-scenario']
preprocessors: '**/*.coffee': 'coffee'

@ -1,6 +1,6 @@
{
"name": "angular-contenteditable",
"version": "0.3.6",
"version": "0.3.7",
"description": "angular model for the 'contenteditable' html attribute",
"repository": {
"type": "git",
@ -11,8 +11,8 @@
"test": "test"
},
"scripts": {
"install": "node_modules/.bin/bower install",
"test": "node_modules/.bin/grunt test"
"install": "bower install",
"test": "grunt test"
},
"repository": "",
"keywords": [
@ -24,13 +24,12 @@
"devDependencies": {
"matchdep": "~0.3.0",
"grunt": "~0.4.1",
"grunt-cli": "~0.1.9",
"grunt-cli": "~0.1.13",
"grunt-contrib-jshint": "~0.7.1",
"grunt-karma": "~0.6.2",
"bower": "~1.2.7",
"bower": "~1.3.5",
"karma": "~0.10.2",
"karma-ng-scenario": "0.1.0",
"karma-mocha": "~0.1.0",
"karma-coffee-preprocessor": "0.1.0"
}
}

@ -4,7 +4,7 @@
<title>Simple</title>
<!-- we need jquery for e2e testing -->
<script src="../../bower_components/jquery/jquery.js"></script>
<script src="../../bower_components/angular-unstable/angular.js"></script>
<script src="../../bower_components/angular/angular.js"></script>
<script src="../../angular-contenteditable.js"></script>
<script>
angular.module('simple', ['contenteditable'])

@ -4,7 +4,7 @@
<title>Simple</title>
<!-- we need jquery for e2e testing -->
<script src="../../bower_components/jquery/jquery.js"></script>
<script src="../../bower_components/angular-unstable/angular.js"></script>
<script src="../../bower_components/angular/angular.js"></script>
<script src="../../angular-contenteditable.js"></script>
<script>
angular.module('simple', ['contenteditable'])

@ -2,7 +2,7 @@
<html ng-app="simple">
<head>
<title>Simple</title>
<script src="../../bower_components/angular-unstable/angular.js"></script>
<script src="../../bower_components/angular/angular.js"></script>
<script src="../../angular-contenteditable.js"></script>
<script>
angular.module('simple', ['contenteditable'])

@ -4,7 +4,7 @@
<title>Simple</title>
<!-- we need jquery for e2e testing -->
<script src="../../bower_components/jquery/jquery.js"></script>
<script src="../../bower_components/angular-unstable/angular.js"></script>
<script src="../../bower_components/angular/angular.js"></script>
<script src="../../angular-contenteditable.js"></script>
<script>
angular.module('simple', ['contenteditable'])

@ -4,7 +4,7 @@
<meta charset="utf-8">
<link href="../../bower_components/bootstrap-css/css/bootstrap.css" rel="stylesheet">
<script src="../../bower_components/jquery/jquery.js"></script>
<script src="../../bower_components/angular-unstable/angular.js"></script>
<script src="../../bower_components/angular/angular.js"></script>
<script src="../../bower_components/angular-bootstrap/ui-bootstrap.js"></script>
<script src="../../bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="../../angular-contenteditable.js"></script>

@ -4,7 +4,7 @@
<meta charset="utf-8">
<link href="../../bower_components/bootstrap-css/css/bootstrap.css" rel="stylesheet">
<script src="../../bower_components/jquery/jquery.js"></script>
<script src="../../bower_components/angular-unstable/angular.js"></script>
<script src="../../bower_components/angular/angular.js"></script>
<script src="../../bower_components/angular-bootstrap/ui-bootstrap.js"></script>
<script src="../../bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="../../angular-contenteditable.js"></script>

@ -4,7 +4,7 @@
<meta charset="utf-8">
<link href="../../bower_components/bootstrap-css/css/bootstrap.css" rel="stylesheet">
<script src="../../bower_components/jquery/jquery.js"></script>
<script src="../../bower_components/angular-unstable/angular.js"></script>
<script src="../../bower_components/angular/angular.js"></script>
<script src="../../bower_components/angular-bootstrap/ui-bootstrap.js"></script>
<script src="../../bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="../../angular-contenteditable.js"></script>

@ -1,33 +0,0 @@
module.exports = (karma) ->
karma.set
basePath: '..'
frameworks: ['mocha']
files: [
'bower_components/angular/angular.js'
'angular-contenteditable.js'
'test/unit/*.coffee'
]
preprocessors: '**/*.coffee': 'coffee'
exclude: []
reporters: ['progress']
port: 9876
runnerPort: 9100
colors: true
logLevel: karma.LOG_INFO
autoWatch: true
browsers: ['Chrome']
captureTimeout: 60000
singleRun: false

@ -1,3 +0,0 @@
describe 'radians', ->
describe 'contenteditable', ->
it 'passes', ->