bootstrap-wysiwyg-rails 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bootstrap-wysiwyg.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Vladislav Bogomolov
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Bootstrap::Wysiwyg
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'bootstrap-wysiwyg'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install bootstrap-wysiwyg
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bootstrap/wysiwyg/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "bootstrap-wysiwyg-rails"
8
+ spec.version = Bootstrap::Wysiwyg::VERSION
9
+ spec.authors = ["Vladislav Bogomolov"]
10
+ spec.email = ["vladson4ik@gmail.com"]
11
+ spec.description = %q{Bootstrap wysiwyg gem for rails}
12
+ spec.summary = %q{Bootstrap wysiwyg gem for rails}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'railties', '>= 3.1'
22
+ spec.add_dependency 'actionpack', '>= 3.1'
23
+ spec.add_development_dependency 'rails', '>= 3.1'
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.3"
26
+ spec.add_development_dependency "rake"
27
+ end
@@ -0,0 +1,8 @@
1
+ require "bootstrap/wysiwyg/version"
2
+
3
+ module Bootstrap
4
+ module Wysiwyg
5
+ class Rails < ::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module Bootstrap
2
+ module Wysiwyg
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,195 @@
1
+ /* http://github.com/mindmup/bootstrap-wysiwyg */
2
+ /*global jQuery, $, FileReader*/
3
+ /*jslint browser:true*/
4
+ (function ($) {
5
+ 'use strict';
6
+ var readFileIntoDataUrl = function (fileInfo) {
7
+ var loader = $.Deferred(),
8
+ fReader = new FileReader();
9
+ fReader.onload = function (e) {
10
+ loader.resolve(e.target.result);
11
+ };
12
+ fReader.onerror = loader.reject;
13
+ fReader.onprogress = loader.notify;
14
+ fReader.readAsDataURL(fileInfo);
15
+ return loader.promise();
16
+ };
17
+ $.fn.cleanHtml = function () {
18
+ var html = $(this).html();
19
+ return html && html.replace(/(<br>|\s|<div><br><\/div>|&nbsp;)*$/, '');
20
+ };
21
+ $.fn.wysiwyg = function (userOptions) {
22
+ var editor = this,
23
+ selectedRange,
24
+ options,
25
+ updateToolbar = function () {
26
+ if (options.activeToolbarClass) {
27
+ $(options.toolbarSelector).find('.btn[data-' + options.commandRole + ']').each(function () {
28
+ var command = $(this).data(options.commandRole);
29
+ if (document.queryCommandState(command)) {
30
+ $(this).addClass(options.activeToolbarClass);
31
+ } else {
32
+ $(this).removeClass(options.activeToolbarClass);
33
+ }
34
+ });
35
+ }
36
+ },
37
+ execCommand = function (commandWithArgs, valueArg) {
38
+ var commandArr = commandWithArgs.split(' '),
39
+ command = commandArr.shift(),
40
+ args = commandArr.join(' ') + (valueArg || '');
41
+ document.execCommand(command, 0, args);
42
+ updateToolbar();
43
+ },
44
+ bindHotkeys = function (hotKeys) {
45
+ $.each(hotKeys, function (hotkey, command) {
46
+ editor.keydown(hotkey, function (e) {
47
+ if (editor.attr('contenteditable') && editor.is(':visible')) {
48
+ e.preventDefault();
49
+ e.stopPropagation();
50
+ execCommand(command);
51
+ }
52
+ }).keyup(hotkey, function (e) {
53
+ if (editor.attr('contenteditable') && editor.is(':visible')) {
54
+ e.preventDefault();
55
+ e.stopPropagation();
56
+ }
57
+ });
58
+ });
59
+ },
60
+ getCurrentRange = function () {
61
+ var sel = window.getSelection();
62
+ if (sel.getRangeAt && sel.rangeCount) {
63
+ return sel.getRangeAt(0);
64
+ }
65
+ },
66
+ saveSelection = function () {
67
+ selectedRange = getCurrentRange();
68
+ },
69
+ restoreSelection = function () {
70
+ var selection = window.getSelection();
71
+ if (selectedRange) {
72
+ try {
73
+ selection.removeAllRanges();
74
+ } catch (ex) {
75
+ document.body.createTextRange().select();
76
+ document.selection.empty();
77
+ }
78
+
79
+ selection.addRange(selectedRange);
80
+ }
81
+ },
82
+ insertFiles = function (files) {
83
+ editor.focus();
84
+ $.each(files, function (idx, fileInfo) {
85
+ if (/^image\//.test(fileInfo.type)) {
86
+ $.when(readFileIntoDataUrl(fileInfo)).done(function (dataUrl) {
87
+ execCommand('insertimage', dataUrl);
88
+ }).fail(function (e) {
89
+ options.fileUploadError("file-reader", e);
90
+ });
91
+ } else {
92
+ options.fileUploadError("unsupported-file-type", fileInfo.type);
93
+ }
94
+ });
95
+ },
96
+ markSelection = function (input, color) {
97
+ restoreSelection();
98
+ if (document.queryCommandSupported('hiliteColor')) {
99
+ document.execCommand('hiliteColor', 0, color || 'transparent');
100
+ }
101
+ saveSelection();
102
+ input.data(options.selectionMarker, color);
103
+ },
104
+ bindToolbar = function (toolbar, options) {
105
+ toolbar.find('a[data-' + options.commandRole + ']').click(function () {
106
+ restoreSelection();
107
+ editor.focus();
108
+ execCommand($(this).data(options.commandRole));
109
+ saveSelection();
110
+ });
111
+ toolbar.find('[data-toggle=dropdown]').click(restoreSelection);
112
+
113
+ toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () {
114
+ var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */
115
+ this.value = '';
116
+ restoreSelection();
117
+ if (newValue) {
118
+ editor.focus();
119
+ execCommand($(this).data(options.commandRole), newValue);
120
+ }
121
+ saveSelection();
122
+ }).on('focus', function () {
123
+ var input = $(this);
124
+ if (!input.data(options.selectionMarker)) {
125
+ markSelection(input, options.selectionColor);
126
+ input.focus();
127
+ }
128
+ }).on('blur', function () {
129
+ var input = $(this);
130
+ if (input.data(options.selectionMarker)) {
131
+ markSelection(input, false);
132
+ }
133
+ });
134
+ toolbar.find('input[type=file][data-' + options.commandRole + ']').change(function () {
135
+ restoreSelection();
136
+ if (this.type === 'file' && this.files && this.files.length > 0) {
137
+ insertFiles(this.files);
138
+ }
139
+ saveSelection();
140
+ this.value = '';
141
+ });
142
+ },
143
+ initFileDrops = function () {
144
+ editor.on('dragenter dragover', false)
145
+ .on('drop', function (e) {
146
+ var dataTransfer = e.originalEvent.dataTransfer;
147
+ e.stopPropagation();
148
+ e.preventDefault();
149
+ if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
150
+ insertFiles(dataTransfer.files);
151
+ }
152
+ });
153
+ };
154
+ options = $.extend({}, $.fn.wysiwyg.defaults, userOptions);
155
+ bindHotkeys(options.hotKeys);
156
+ initFileDrops();
157
+ bindToolbar($(options.toolbarSelector), options);
158
+ editor.attr('contenteditable', true)
159
+ .on('mouseup keyup mouseout', function () {
160
+ saveSelection();
161
+ updateToolbar();
162
+ });
163
+ $(window).bind('touchend', function (e) {
164
+ var isInside = (editor.is(e.target) || editor.has(e.target).length > 0),
165
+ currentRange = getCurrentRange(),
166
+ clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset);
167
+ if (!clear || isInside) {
168
+ saveSelection();
169
+ updateToolbar();
170
+ }
171
+ });
172
+ return this;
173
+ };
174
+ $.fn.wysiwyg.defaults = {
175
+ hotKeys: {
176
+ 'ctrl+b meta+b': 'bold',
177
+ 'ctrl+i meta+i': 'italic',
178
+ 'ctrl+u meta+u': 'underline',
179
+ 'ctrl+z meta+z': 'undo',
180
+ 'ctrl+y meta+y meta+shift+z': 'redo',
181
+ 'ctrl+l meta+l': 'justifyleft',
182
+ 'ctrl+r meta+r': 'justifyright',
183
+ 'ctrl+e meta+e': 'justifycenter',
184
+ 'ctrl+j meta+j': 'justifyfull',
185
+ 'shift+tab': 'outdent',
186
+ 'tab': 'indent'
187
+ },
188
+ toolbarSelector: '[data-role=editor-toolbar]',
189
+ commandRole: 'edit',
190
+ activeToolbarClass: 'btn-info',
191
+ selectionMarker: 'edit-focus-marker',
192
+ selectionColor: 'darkgrey',
193
+ fileUploadError: function (reason, detail) { console.log("File upload error", reason, detail); }
194
+ };
195
+ }(window.jQuery));
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bootstrap-wysiwyg-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Vladislav Bogomolov
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ prerelease: false
16
+ name: railties
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '3.1'
22
+ none: false
23
+ type: :runtime
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ! '>='
27
+ - !ruby/object:Gem::Version
28
+ version: '3.1'
29
+ none: false
30
+ - !ruby/object:Gem::Dependency
31
+ prerelease: false
32
+ name: actionpack
33
+ requirement: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '3.1'
38
+ none: false
39
+ type: :runtime
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '3.1'
45
+ none: false
46
+ - !ruby/object:Gem::Dependency
47
+ prerelease: false
48
+ name: rails
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '3.1'
54
+ none: false
55
+ type: :development
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '3.1'
61
+ none: false
62
+ - !ruby/object:Gem::Dependency
63
+ prerelease: false
64
+ name: bundler
65
+ requirement: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.3'
70
+ none: false
71
+ type: :development
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: '1.3'
77
+ none: false
78
+ - !ruby/object:Gem::Dependency
79
+ prerelease: false
80
+ name: rake
81
+ requirement: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ none: false
87
+ type: :development
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ none: false
94
+ description: Bootstrap wysiwyg gem for rails
95
+ email:
96
+ - vladson4ik@gmail.com
97
+ executables: []
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - .gitignore
102
+ - Gemfile
103
+ - LICENSE.txt
104
+ - README.md
105
+ - Rakefile
106
+ - bootstrap-wysiwyg.gemspec
107
+ - lib/bootstrap/wysiwyg.rb
108
+ - lib/bootstrap/wysiwyg/version.rb
109
+ - vendor/javascripts/bootstrap-wysiwyg.js
110
+ homepage: ''
111
+ licenses:
112
+ - MIT
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ segments:
122
+ - 0
123
+ version: '0'
124
+ hash: -172728002380215620
125
+ none: false
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ segments:
131
+ - 0
132
+ version: '0'
133
+ hash: -172728002380215620
134
+ none: false
135
+ requirements: []
136
+ rubyforge_project:
137
+ rubygems_version: 1.8.24
138
+ signing_key:
139
+ specification_version: 3
140
+ summary: Bootstrap wysiwyg gem for rails
141
+ test_files: []