beef-admin_area 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +59 -0
- data/VERSION +1 -0
- data/admin_area.gemspec +168 -0
- data/app/controllers/admin/base_controller.rb +8 -0
- data/app/controllers/admin/settings_controller.rb +43 -0
- data/app/controllers/admin/users_controller.rb +74 -0
- data/app/helpers/admin/base_helper.rb +59 -0
- data/app/helpers/admin/settings_helper.rb +8 -0
- data/app/helpers/admin/users_helper.rb +2 -0
- data/app/models/settings.rb +92 -0
- data/app/views/admin/base/index.html.erb +2 -0
- data/app/views/admin/settings/_form.html.erb +31 -0
- data/app/views/admin/settings/update.js.rjs +1 -0
- data/app/views/admin/users/index.html.erb +39 -0
- data/app/views/admin/users/show.html.erb +37 -0
- data/app/views/layouts/admin.html.erb +68 -0
- data/config/routes.rb +8 -0
- data/generators/admin_area_files/USAGE +8 -0
- data/generators/admin_area_files/admin_area_files_generator.rb +114 -0
- data/generators/admin_area_files/lib/insert_commands.rb +47 -0
- data/generators/admin_area_files/templates/app/models/content_sweeper.rb +43 -0
- data/generators/admin_area_files/templates/app/views/admin/settings/show.html.erb +52 -0
- data/generators/admin_area_files/templates/config/initializers/admin_area.rb +2 -0
- data/generators/admin_area_files/templates/config/initializers/settings.rb +8 -0
- data/generators/admin_area_files/templates/lib/tasks/admin_area.rake +10 -0
- data/generators/admin_area_files/templates/migration.rb +21 -0
- data/generators/admin_area_files/templates/public/images/admin/accept_button.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/add.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/application_cascade.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/arrow_left.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/arrow_right.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/button_bg.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/cancel_button.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/cursor_arrow.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/delete_button.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/down_icon.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/edit_button.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/file-uploads.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/folder.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/folder_image.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/head_bg.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/image_add.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/images-pointer.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/info_bg.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/nav_bg.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/over_button_bg.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/page_bg.gif +0 -0
- data/generators/admin_area_files/templates/public/images/admin/page_white.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/page_white_get.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/page_white_link.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/page_white_stack.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/picture.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/picture_medium.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/picture_square.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/picture_thumb.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/pictures.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/unapproved.png +0 -0
- data/generators/admin_area_files/templates/public/images/admin/up_icon.gif +0 -0
- data/generators/admin_area_files/templates/public/images/lightwindow/Thumbs.db +0 -0
- data/generators/admin_area_files/templates/public/images/lightwindow/ajax-loading.gif +0 -0
- data/generators/admin_area_files/templates/public/images/lightwindow/arrow-down.gif +0 -0
- data/generators/admin_area_files/templates/public/images/lightwindow/arrow-up.gif +0 -0
- data/generators/admin_area_files/templates/public/images/lightwindow/black-70.png +0 -0
- data/generators/admin_area_files/templates/public/images/lightwindow/black.png +0 -0
- data/generators/admin_area_files/templates/public/images/lightwindow/nextlabel.gif +0 -0
- data/generators/admin_area_files/templates/public/images/lightwindow/pattern_148-70.png +0 -0
- data/generators/admin_area_files/templates/public/images/lightwindow/pattern_148.gif +0 -0
- data/generators/admin_area_files/templates/public/images/lightwindow/prevlabel.gif +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/background.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/blockquote.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/bold.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/center.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/h1.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/h2.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/h3.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/h4.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/h5.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/h6.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/indent.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/italic.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/justify.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/left.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/link.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/list_bullets.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/list_numbers.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/omega.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/outdent.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/paragraph.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/preview.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/right.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/strikethrough.png +0 -0
- data/generators/admin_area_files/templates/public/images/textile-editor/underline.png +0 -0
- data/generators/admin_area_files/templates/public/javascripts/admin/application.js +185 -0
- data/generators/admin_area_files/templates/public/javascripts/lightwindow.js +1921 -0
- data/generators/admin_area_files/templates/public/javascripts/textile-editor-config.js +107 -0
- data/generators/admin_area_files/templates/public/javascripts/textile-editor.js +788 -0
- data/generators/admin_area_files/templates/public/stylesheets/admin/handheld.css +6 -0
- data/generators/admin_area_files/templates/public/stylesheets/admin/ie.css +21 -0
- data/generators/admin_area_files/templates/public/stylesheets/admin/print.css +27 -0
- data/generators/admin_area_files/templates/public/stylesheets/admin/screen.css +996 -0
- data/generators/admin_area_files/templates/public/stylesheets/admin/theme-1.0.css +131 -0
- data/generators/admin_area_files/templates/public/stylesheets/lightwindow.css +376 -0
- data/generators/admin_area_files/templates/public/stylesheets/textile-editor.css +60 -0
- data/generators/admin_scaffold/USAGE +8 -0
- data/generators/admin_scaffold/admin_scaffold_generator.rb +53 -0
- data/generators/admin_scaffold/lib/insert_commands.rb +61 -0
- data/generators/admin_scaffold/templates/admin_controller.rb +83 -0
- data/generators/admin_scaffold/templates/admin_index.html.erb +38 -0
- data/generators/admin_scaffold/templates/admin_show.html.erb +16 -0
- data/generators/admin_scaffold/templates/helper.rb +2 -0
- data/generators/admin_scaffold/templates/helper_test.rb +4 -0
- data/generators/admin_scaffold/templates/layout.html.erb +17 -0
- data/generators/admin_scaffold/templates/style.css +54 -0
- data/generators/admin_scaffold/templates/view_controller.rb +14 -0
- data/generators/admin_scaffold/templates/view_index.html.erb +17 -0
- data/lib/admin_area.rb +82 -0
- data/rails/init.rb +4 -0
- data/test/admin_area_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +206 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
var teButtons = TextileEditor.buttons;
|
2
|
+
|
3
|
+
/*
|
4
|
+
Link button.
|
5
|
+
*/
|
6
|
+
link_button = TextileEditor.prepareButton(new TextileEditorButton('ed_link','link.png','"', '":', 'l', 'Link'));
|
7
|
+
link_button.onclick = function() {
|
8
|
+
this.standard = false;
|
9
|
+
if (!this.textile_editor.checkOpenTags(this)) {
|
10
|
+
this.tagEnd = '":' + prompt("Add your link", "");
|
11
|
+
}
|
12
|
+
this.textile_editor.insertTag(this);
|
13
|
+
return false;
|
14
|
+
};
|
15
|
+
// Preview button
|
16
|
+
// preview_button = TextileEditor.prepareButton(new TextileEditorButton('ed_preview','preview.png',null,null,null,'Preview'));
|
17
|
+
// preview_button.onclick = function() {
|
18
|
+
//
|
19
|
+
// var myField = this.textile_editor.canvas;
|
20
|
+
// var preview_id = myField.id + '-preview';
|
21
|
+
// var preview_div = $(preview_id);
|
22
|
+
// if (preview_div) {
|
23
|
+
// Effect.BlindUp(preview_div, {afterFinish:function() {
|
24
|
+
// myField.style.overflow = 'auto';
|
25
|
+
// preview_div.remove();
|
26
|
+
// }});
|
27
|
+
// } else {
|
28
|
+
//
|
29
|
+
// html = '<div id="'+preview_id+'" class="preview-area">';
|
30
|
+
// html += this.textile_editor.preview_text();
|
31
|
+
// html += '</div>';
|
32
|
+
//
|
33
|
+
// $(myField.parentNode).insert(html);
|
34
|
+
// preview_div = $(preview_id);
|
35
|
+
//
|
36
|
+
// preview_div.setStyle({
|
37
|
+
// position: 'absolute'
|
38
|
+
// });
|
39
|
+
//
|
40
|
+
// // Clone textarea's position
|
41
|
+
// preview_div.clonePosition(myField);
|
42
|
+
// // Fix top if textarea scrolled
|
43
|
+
// preview_div.style.top = $(myField).offsetTop + 'px';
|
44
|
+
//
|
45
|
+
// Effect.BlindDown(preview_div);
|
46
|
+
//
|
47
|
+
// myField.style.overflow = 'hidden';
|
48
|
+
//
|
49
|
+
// }
|
50
|
+
// return false;
|
51
|
+
// };
|
52
|
+
|
53
|
+
|
54
|
+
teButtons.push(new TextileEditorButton('ed_strong', 'bold.png', '*', '*', 'b', 'Bold','s'));
|
55
|
+
teButtons.push(new TextileEditorButton('ed_emphasis', 'italic.png', '_', '_', 'i', 'Italicize','s'));
|
56
|
+
teButtons.push(new TextileEditorButton('ed_underline', 'underline.png', '+', '+', 'u', 'Underline','s'));
|
57
|
+
teButtons.push(new TextileEditorButton('ed_strike', 'strikethrough.png', '-', '-', 's', 'Strikethrough','s'));
|
58
|
+
teButtons.push(link_button);
|
59
|
+
teButtons.push(new TextileEditorButton('ed_ol', 'list_numbers.png', '# ', '\n', ',', 'Numbered List'));
|
60
|
+
teButtons.push(new TextileEditorButton('ed_ul', 'list_bullets.png', '* ', '\n', '.', 'Bulleted List'));
|
61
|
+
teButtons.push(new TextileEditorButton('ed_p', 'paragraph.png', 'p', '\n', 'p', 'Paragraph'));
|
62
|
+
// teButtons.push(new TextileEditorButton('ed_h1', 'h1.png', 'h1', '\n', '1', 'Header 1'));
|
63
|
+
//teButtons.push(new TextileEditorButton('ed_h2', 'h2.png', 'h2', '\n', '2', 'Header 2'));
|
64
|
+
//teButtons.push(new TextileEditorButton('ed_h3', 'h3.png', 'h3', '\n', '3', 'Header 3'));
|
65
|
+
teButtons.push(new TextileEditorButton('ed_h4', 'h4.png', 'h4', '\n', '4', 'Header 4'));
|
66
|
+
//teButtons.push(new TextileEditorButton('ed_block', 'blockquote.png', 'bq', '\n', 'q', 'Blockquote'));
|
67
|
+
//teButtons.push(new TextileEditorButton('ed_outdent', 'outdent.png', ')', '\n', ']', 'Outdent'));
|
68
|
+
//teButtons.push(new TextileEditorButton('ed_indent', 'indent.png', '(', '\n', '[', 'Indent'));
|
69
|
+
//teButtons.push(new TextileEditorButton('ed_justifyl', 'left.png', '<', '\n', 'l', 'Left Justify'));
|
70
|
+
//teButtons.push(new TextileEditorButton('ed_justifyc', 'center.png', '=', '\n', 'e', 'Center Text'));
|
71
|
+
//teButtons.push(new TextileEditorButton('ed_justifyr', 'right.png', '>', '\n', 'r', 'Right Justify'));
|
72
|
+
//teButtons.push(new TextileEditorButton('ed_justify', 'justify.png', '<>', '\n', 'j', 'Justify'));
|
73
|
+
//teButtons.push(preview_button);
|
74
|
+
|
75
|
+
// teButtons.push(new TextileEditorButton('ed_code','code','@','@','c','Code'));
|
76
|
+
|
77
|
+
// Add image. insertAtCursor function in apllcation.js
|
78
|
+
addImage = function(imageurl,size) {
|
79
|
+
alt = alt.replace("(","").replace(")","");
|
80
|
+
insertAtCursor(TextileEditor.canvas, '\n\n!'+imageurl+'('+alt+')!\n\n');
|
81
|
+
};
|
82
|
+
|
83
|
+
addLinkedImage = function(imageurl,alt) {
|
84
|
+
alt = alt.replace("(","").replace(")","");
|
85
|
+
insertAtCursor(TextileEditor.canvas, '\n\n!'+imageurl+'('+alt+')!:'+imageurl+'\n\n');
|
86
|
+
};
|
87
|
+
|
88
|
+
addLink = function(text, url) {
|
89
|
+
insertAtCursor(TextileEditor.canvas, '"'+ text +'":'+ url + ' ');
|
90
|
+
};
|
91
|
+
|
92
|
+
addAsset = function(asset_id, size) {
|
93
|
+
if (size && size != 'fullsize') {
|
94
|
+
size = '|'+size;
|
95
|
+
} else {
|
96
|
+
size = ''
|
97
|
+
}
|
98
|
+
insertAtCursor(TextileEditor.canvas, '[asset('+asset_id+size+')]');
|
99
|
+
};
|
100
|
+
|
101
|
+
// Iittialise textile editor
|
102
|
+
document.observe('dom:loaded',function(){
|
103
|
+
$$('textarea.editor').each(function(ta){
|
104
|
+
// alert(ta.id);
|
105
|
+
TextileEditor.initialize(ta.id);
|
106
|
+
});
|
107
|
+
});
|
@@ -0,0 +1,788 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
Textile Editor v0.2
|
4
|
+
created by: dave olsen, wvu web services
|
5
|
+
created on: march 17, 2007
|
6
|
+
project page: slateinfo.blogs.wvu.edu
|
7
|
+
|
8
|
+
inspired by:
|
9
|
+
- Patrick Woods, http://www.hakjoon.com/code/38/textile-quicktags-redirect &
|
10
|
+
- Alex King, http://alexking.org/projects/js-quicktags
|
11
|
+
|
12
|
+
features:
|
13
|
+
- supports: IE7, FF2, Safari2
|
14
|
+
- ability to use "simple" vs. "extended" editor
|
15
|
+
- supports all block elements in textile except footnote
|
16
|
+
- supports all block modifier elements in textile
|
17
|
+
- supports simple ordered and unordered lists
|
18
|
+
- supports most of the phrase modifiers, very easy to add the missing ones
|
19
|
+
- supports multiple-paragraph modification
|
20
|
+
- can have multiple "editors" on one page, access key use in this environment is flaky
|
21
|
+
- access key support
|
22
|
+
- select text to add and remove tags, selection stays highlighted
|
23
|
+
- seamlessly change between tags and modifiers
|
24
|
+
- doesn't need to be in the body onload tag
|
25
|
+
- can supply your own, custom IDs for the editor to be drawn around
|
26
|
+
|
27
|
+
todo:
|
28
|
+
- a clean way of providing image and link inserts
|
29
|
+
- get the selection to properly show in IE
|
30
|
+
|
31
|
+
more on textile:
|
32
|
+
- Textism, http://www.textism.com/tools/textile/index.php
|
33
|
+
- Textile Reference, http://hobix.com/textile/
|
34
|
+
|
35
|
+
*/
|
36
|
+
|
37
|
+
// Define Button Object
|
38
|
+
function TextileEditorButton(id, display, tagStart, tagEnd, access, title, sve, open) {
|
39
|
+
this.id = id; // used to name the toolbar button
|
40
|
+
this.display = display; // label on button
|
41
|
+
this.tagStart = tagStart; // open tag
|
42
|
+
this.tagEnd = tagEnd; // close tag
|
43
|
+
this.access = access; // set to -1 if tag does not need to be closed
|
44
|
+
this.title = title; // sets the title attribute of the button to give 'tool tips'
|
45
|
+
this.sve = sve; // sve = simple vs. extended. add an 's' to make it show up in the simple toolbar
|
46
|
+
this.open = open; // set to -1 if tag does not need to be closed
|
47
|
+
this.standard = true; // this is a standard button
|
48
|
+
}
|
49
|
+
|
50
|
+
function TextileEditorButtonSeparator(sve) {
|
51
|
+
this.separator = true;
|
52
|
+
this.sve = sve;
|
53
|
+
}
|
54
|
+
|
55
|
+
var TextileEditor = Class.create();
|
56
|
+
TextileEditor.buttons = new Array();
|
57
|
+
TextileEditor.Methods = {
|
58
|
+
// class methods
|
59
|
+
|
60
|
+
// create the toolbar (edToolbar)
|
61
|
+
initialize: function(canvas, view) {
|
62
|
+
var toolbar = document.createElement("div");
|
63
|
+
toolbar.id = "textile-toolbar-" + canvas;
|
64
|
+
toolbar.className = 'textile-toolbar';
|
65
|
+
this.canvas = document.getElementById(canvas);
|
66
|
+
this.canvas.parentNode.insertBefore(toolbar, this.canvas);
|
67
|
+
this.openTags = new Array();
|
68
|
+
|
69
|
+
// Create the local Button array by assigning theButtons array to edButtons
|
70
|
+
var edButtons = new Array();
|
71
|
+
edButtons = this.buttons;
|
72
|
+
|
73
|
+
var standardButtons = new Array();
|
74
|
+
for(var i = 0; i < edButtons.length; i++) {
|
75
|
+
var thisButton = this.prepareButton(edButtons[i]);
|
76
|
+
if (view == 's') {
|
77
|
+
if (edButtons[i].sve == 's') {
|
78
|
+
toolbar.appendChild(thisButton);
|
79
|
+
standardButtons.push(thisButton);
|
80
|
+
}
|
81
|
+
} else {
|
82
|
+
if (typeof thisButton == 'string') {
|
83
|
+
toolbar.innerHTML += thisButton;
|
84
|
+
} else {
|
85
|
+
toolbar.appendChild(thisButton);
|
86
|
+
standardButtons.push(thisButton);
|
87
|
+
}
|
88
|
+
}
|
89
|
+
} // end for
|
90
|
+
|
91
|
+
var te = this;
|
92
|
+
$A(toolbar.getElementsByTagName('button')).each(function(button) {
|
93
|
+
if (!button.onclick) {
|
94
|
+
button.onclick = function() { te.insertTag(button); return false; };
|
95
|
+
} // end if
|
96
|
+
|
97
|
+
button.tagStart = button.getAttribute('tagStart');
|
98
|
+
button.tagEnd = button.getAttribute('tagEnd');
|
99
|
+
button.open = button.getAttribute('open');
|
100
|
+
button.textile_editor = te;
|
101
|
+
button.canvas = te.canvas;
|
102
|
+
});
|
103
|
+
}, // end initialize
|
104
|
+
|
105
|
+
// draw individual buttons (edShowButton)
|
106
|
+
prepareButton: function(button) {
|
107
|
+
if (button.separator) {
|
108
|
+
var theButton = document.createElement('span');
|
109
|
+
theButton.className = 'ed_sep';
|
110
|
+
return theButton;
|
111
|
+
}
|
112
|
+
|
113
|
+
if (button.standard) {
|
114
|
+
var theButton = document.createElement("button");
|
115
|
+
theButton.id = button.id;
|
116
|
+
theButton.setAttribute('class', 'standard');
|
117
|
+
theButton.setAttribute('tagStart', button.tagStart);
|
118
|
+
theButton.setAttribute('tagEnd', button.tagEnd);
|
119
|
+
theButton.setAttribute('open', button.open);
|
120
|
+
|
121
|
+
var img = document.createElement('img');
|
122
|
+
img.src = '/images/textile-editor/' + button.display;
|
123
|
+
theButton.appendChild(img);
|
124
|
+
} else {
|
125
|
+
return button;
|
126
|
+
} // end if !custom
|
127
|
+
|
128
|
+
theButton.accessKey = button.access;
|
129
|
+
theButton.title = button.title;
|
130
|
+
return theButton;
|
131
|
+
}, // end prepareButton
|
132
|
+
|
133
|
+
// if clicked, no selected text, tag not open highlight button
|
134
|
+
// (edAddTag)
|
135
|
+
addTag: function(button) {
|
136
|
+
if (button.tagEnd != '') {
|
137
|
+
this.openTags[this.openTags.length] = button;
|
138
|
+
//var el = document.getElementById(button.id);
|
139
|
+
//el.className = 'selected';
|
140
|
+
button.className = 'selected';
|
141
|
+
}
|
142
|
+
}, // end addTag
|
143
|
+
|
144
|
+
// if clicked, no selected text, tag open lowlight button
|
145
|
+
// (edRemoveTag)
|
146
|
+
removeTag: function(button) {
|
147
|
+
for (i = 0; i < this.openTags.length; i++) {
|
148
|
+
if (this.openTags[i] == button) {
|
149
|
+
this.openTags.splice(button, 1);
|
150
|
+
//var el = document.getElementById(button.id);
|
151
|
+
//el.className = 'unselected';
|
152
|
+
button.className = 'unselected';
|
153
|
+
}
|
154
|
+
}
|
155
|
+
}, // end removeTag
|
156
|
+
|
157
|
+
// see if there are open tags. for the remove tag bit...
|
158
|
+
// (edCheckOpenTags)
|
159
|
+
checkOpenTags: function(button) {
|
160
|
+
var tag = 0;
|
161
|
+
for (i = 0; i < this.openTags.length; i++) {
|
162
|
+
if (this.openTags[i] == button) {
|
163
|
+
tag++;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
if (tag > 0) {
|
167
|
+
return true; // tag found
|
168
|
+
}
|
169
|
+
else {
|
170
|
+
return false; // tag not found
|
171
|
+
}
|
172
|
+
}, // end checkOpenTags
|
173
|
+
|
174
|
+
// insert the tag. this is the bulk of the code.
|
175
|
+
// (edInsertTag)
|
176
|
+
insertTag: function(button, tagStart, tagEnd) {
|
177
|
+
var myField = button.canvas;
|
178
|
+
myField.focus();
|
179
|
+
|
180
|
+
if (tagStart) {
|
181
|
+
button.tagStart = tagStart;
|
182
|
+
button.tagEnd = tagEnd ? tagEnd : '\n';
|
183
|
+
}
|
184
|
+
|
185
|
+
var textSelected = false;
|
186
|
+
var finalText = '';
|
187
|
+
var FF = false;
|
188
|
+
|
189
|
+
// grab the text that's going to be manipulated, by browser
|
190
|
+
if (document.selection) { // IE support
|
191
|
+
sel = document.selection.createRange();
|
192
|
+
|
193
|
+
// set-up the text vars
|
194
|
+
var beginningText = '';
|
195
|
+
var followupText = '';
|
196
|
+
|
197
|
+
//remove any extra spaces caught on the end of the selection
|
198
|
+
var selectedText = sel.text.replace(/( +)$/, '');
|
199
|
+
var matches = sel.text.match(/( +)$/);
|
200
|
+
if(matches){
|
201
|
+
followupText += matches[1];
|
202
|
+
}
|
203
|
+
|
204
|
+
// check if text has been selected
|
205
|
+
if (sel.text.length > 0) {
|
206
|
+
textSelected = true;
|
207
|
+
}
|
208
|
+
|
209
|
+
// set-up newline regex's so we can swap tags across multiple paragraphs
|
210
|
+
var newlineReplaceRegexClean = /\r\n\s\n/g;
|
211
|
+
var newlineReplaceRegexDirty = '\\r\\n\\s\\n';
|
212
|
+
var newlineReplaceClean = '\r\n\n';
|
213
|
+
}
|
214
|
+
else if (myField.selectionStart || myField.selectionStart == '0') { // MOZ/FF/NS/S support
|
215
|
+
|
216
|
+
// figure out cursor and selection positions
|
217
|
+
var startPos = myField.selectionStart;
|
218
|
+
var endPos = myField.selectionEnd;
|
219
|
+
var cursorPos = endPos;
|
220
|
+
var scrollTop = myField.scrollTop;
|
221
|
+
FF = true; // note that is is a FF/MOZ/NS/S browser
|
222
|
+
|
223
|
+
// set-up the text vars
|
224
|
+
var beginningText = myField.value.substring(0, startPos);
|
225
|
+
var followupText = myField.value.substring(endPos, myField.value.length);
|
226
|
+
|
227
|
+
// check if text has been selected
|
228
|
+
if (startPos != endPos) {
|
229
|
+
textSelected = true;
|
230
|
+
var selectedText = myField.value.substring(startPos, endPos);
|
231
|
+
}
|
232
|
+
|
233
|
+
// set-up newline regex's so we can swap tags across multiple paragraphs
|
234
|
+
var newlineReplaceRegexClean = /\n\n/g;
|
235
|
+
var newlineReplaceRegexDirty = '\\n\\n';
|
236
|
+
var newlineReplaceClean = '\n\n';
|
237
|
+
}
|
238
|
+
|
239
|
+
|
240
|
+
// if there is text that has been highlighted...
|
241
|
+
if (textSelected) {
|
242
|
+
|
243
|
+
// set-up some defaults for how to handle bad new line characters
|
244
|
+
var newlineStart = '';
|
245
|
+
var newlineStartPos = 0;
|
246
|
+
var newlineEnd = '';
|
247
|
+
var newlineEndPos = 0;
|
248
|
+
var newlineFollowup = '';
|
249
|
+
|
250
|
+
// set-up some defaults for how to handle placing the beginning and end of selection
|
251
|
+
var posDiffPos = 0;
|
252
|
+
var posDiffNeg = 0;
|
253
|
+
var mplier = 1;
|
254
|
+
|
255
|
+
// remove newline from the beginning of the selectedText.
|
256
|
+
if (selectedText.match(/^\n/)) {
|
257
|
+
selectedText = selectedText.replace(/^\n/,'');
|
258
|
+
newlineStart = '\n';
|
259
|
+
newlineStartpos = 1;
|
260
|
+
}
|
261
|
+
|
262
|
+
// remove newline from the end of the selectedText.
|
263
|
+
if (selectedText.match(/\n$/g)) {
|
264
|
+
selectedText = selectedText.replace(/\n$/g,'');
|
265
|
+
newlineEnd = '\n';
|
266
|
+
newlineEndPos = 1;
|
267
|
+
}
|
268
|
+
|
269
|
+
// no clue, i'm sure it made sense at the time i wrote it
|
270
|
+
if (followupText.match(/^\n/)) {
|
271
|
+
newlineFollowup = '';
|
272
|
+
}
|
273
|
+
else {
|
274
|
+
newlineFollowup = '\n\n';
|
275
|
+
}
|
276
|
+
|
277
|
+
// first off let's check if the user is trying to mess with lists
|
278
|
+
if ((button.tagStart == '* ') || (button.tagStart == '# ')) {
|
279
|
+
|
280
|
+
listItems = 0; // sets up a default to be able to properly manipulate final selection
|
281
|
+
|
282
|
+
// set-up all of the regex's
|
283
|
+
re_start = new RegExp('^(\\*|\\#) ','g');
|
284
|
+
if (button.tagStart == '# ') {
|
285
|
+
re_tag = new RegExp('\\# ','g'); // because of JS regex stupidity i need an if/else to properly set it up, could have done it with a regex replace though
|
286
|
+
}
|
287
|
+
else {
|
288
|
+
re_tag = new RegExp('\\* ','g');
|
289
|
+
}
|
290
|
+
re_replace = new RegExp('(\\*|\\#) ','g');
|
291
|
+
|
292
|
+
// try to remove bullets in text copied from ms word **Mac Only!**
|
293
|
+
re_word_bullet_m_s = new RegExp('• ','g'); // mac/safari
|
294
|
+
re_word_bullet_m_f = new RegExp('∑ ','g'); // mac/firefox
|
295
|
+
selectedText = selectedText.replace(re_word_bullet_m_s,'').replace(re_word_bullet_m_f,'');
|
296
|
+
|
297
|
+
// if the selected text starts with one of the tags we're working with...
|
298
|
+
if (selectedText.match(re_start)) {
|
299
|
+
|
300
|
+
// if tag that begins the selection matches the one clicked, remove them all
|
301
|
+
if (selectedText.match(re_tag)) {
|
302
|
+
finalText = beginningText
|
303
|
+
+ newlineStart
|
304
|
+
+ selectedText.replace(re_replace,'')
|
305
|
+
+ newlineEnd
|
306
|
+
+ followupText;
|
307
|
+
if (matches = selectedText.match(/(\*|\#) /g)) {
|
308
|
+
listItems = matches.length;
|
309
|
+
}
|
310
|
+
posDiffNeg = (listItems*2); // how many list items were there because that's 3 spaces to remove from final selection
|
311
|
+
}
|
312
|
+
|
313
|
+
// else replace the current tag type with the selected tag type
|
314
|
+
else {
|
315
|
+
finalText = beginningText
|
316
|
+
+ newlineStart
|
317
|
+
+ selectedText.replace(re_replace,button.tagStart)
|
318
|
+
+ newlineEnd
|
319
|
+
+ followupText;
|
320
|
+
}
|
321
|
+
}
|
322
|
+
|
323
|
+
// else try to create the list type
|
324
|
+
// NOTE: the items in a list will only be replaced if a newline starts with some character, not a space
|
325
|
+
else {
|
326
|
+
finalText = beginningText
|
327
|
+
+ newlineStart
|
328
|
+
+ button.tagStart
|
329
|
+
+ selectedText.replace(newlineReplaceRegexClean,newlineReplaceClean + button.tagStart).replace(/\n(\S)/g,'\n' + button.tagStart + '$1')
|
330
|
+
+ newlineEnd
|
331
|
+
+ followupText;
|
332
|
+
if (matches = selectedText.match(/\n(\S)/g)) {
|
333
|
+
listItems = matches.length;
|
334
|
+
}
|
335
|
+
posDiffPos = (listItems*2) + 2;
|
336
|
+
}
|
337
|
+
}
|
338
|
+
|
339
|
+
// now lets look and see if the user is trying to muck with a block or block modifier
|
340
|
+
else if (button.tagStart.match(/^(h1|h2|h3|h4|h5|h6|bq|p|\>|\<\>|\<|\=|\(|\))/g)) {
|
341
|
+
|
342
|
+
var insertTag = '';
|
343
|
+
var insertModifier = '';
|
344
|
+
var tagPartBlock = '';
|
345
|
+
var tagPartModifier = '';
|
346
|
+
var tagPartModifierOrig = ''; // ugly hack but it's late
|
347
|
+
var drawSwitch = '';
|
348
|
+
var captureIndentStart = false;
|
349
|
+
var captureListStart = false;
|
350
|
+
var periodAddition = '\\. ';
|
351
|
+
var periodAdditionClean = '. ';
|
352
|
+
var listItemsAddition = 0;
|
353
|
+
|
354
|
+
var re_list_items = new RegExp('(\\*+|\\#+)','g'); // need this regex later on when checking indentation of lists
|
355
|
+
|
356
|
+
var re_block_modifier = new RegExp('^(h1|h2|h3|h4|h5|h6|bq|p| [\\*]{1,} | [\\#]{1,} |)(\\>|\\<\\>|\\<|\\=|[\\(]{1,}|[\\)]{1,6}|)','g');
|
357
|
+
if (tagPartMatches = re_block_modifier.exec(selectedText)) {
|
358
|
+
tagPartBlock = tagPartMatches[1];
|
359
|
+
tagPartModifier = tagPartMatches[2];
|
360
|
+
tagPartModifierOrig = tagPartMatches[2];
|
361
|
+
tagPartModifierOrig = tagPartModifierOrig.replace(/\(/g,"\\(");
|
362
|
+
}
|
363
|
+
|
364
|
+
// if tag already up is the same as the tag provided replace the whole tag
|
365
|
+
if (tagPartBlock == button.tagStart) {
|
366
|
+
insertTag = tagPartBlock + tagPartModifierOrig; // use Orig because it's escaped for regex
|
367
|
+
drawSwitch = 0;
|
368
|
+
}
|
369
|
+
// else if let's check to add/remove block modifier
|
370
|
+
else if ((tagPartModifier == button.tagStart) || (newm = tagPartModifier.match(/[\(]{2,}/g))) {
|
371
|
+
if ((button.tagStart == '(') || (button.tagStart == ')')) {
|
372
|
+
var indentLength = tagPartModifier.length;
|
373
|
+
if (button.tagStart == '(') {
|
374
|
+
indentLength = indentLength + 1;
|
375
|
+
}
|
376
|
+
else {
|
377
|
+
indentLength = indentLength - 1;
|
378
|
+
}
|
379
|
+
for (var i = 0; i < indentLength; i++) {
|
380
|
+
insertModifier = insertModifier + '(';
|
381
|
+
}
|
382
|
+
insertTag = tagPartBlock + insertModifier;
|
383
|
+
}
|
384
|
+
else {
|
385
|
+
if (button.tagStart == tagPartModifier) {
|
386
|
+
insertTag = tagPartBlock;
|
387
|
+
} // going to rely on the default empty insertModifier
|
388
|
+
else {
|
389
|
+
|
390
|
+
if (button.tagStart.match(/(\>|\<\>|\<|\=)/g)) {
|
391
|
+
insertTag = tagPartBlock + button.tagStart;
|
392
|
+
}
|
393
|
+
else {
|
394
|
+
insertTag = button.tagStart + tagPartModifier;
|
395
|
+
}
|
396
|
+
}
|
397
|
+
|
398
|
+
}
|
399
|
+
drawSwitch = 1;
|
400
|
+
}
|
401
|
+
// indentation of list items
|
402
|
+
else if (listPartMatches = re_list_items.exec(tagPartBlock)) {
|
403
|
+
var listTypeMatch = listPartMatches[1];
|
404
|
+
var indentLength = tagPartBlock.length - 2;
|
405
|
+
var listInsert = '';
|
406
|
+
if (button.tagStart == '(') {
|
407
|
+
indentLength = indentLength + 1;
|
408
|
+
}
|
409
|
+
else {
|
410
|
+
indentLength = indentLength - 1;
|
411
|
+
}
|
412
|
+
if (listTypeMatch.match(/[\*]{1,}/g)) {
|
413
|
+
var listType = '*';
|
414
|
+
var listReplace = '\\*';
|
415
|
+
}
|
416
|
+
else {
|
417
|
+
var listType = '#';
|
418
|
+
var listReplace = '\\#';
|
419
|
+
}
|
420
|
+
for (var i = 0; i < indentLength; i++) {
|
421
|
+
listInsert = listInsert + listType;
|
422
|
+
}
|
423
|
+
if (listInsert != '') {
|
424
|
+
insertTag = ' ' + listInsert + ' ';
|
425
|
+
}
|
426
|
+
else {
|
427
|
+
insertTag = '';
|
428
|
+
}
|
429
|
+
tagPartBlock = tagPartBlock.replace(/(\*|\#)/g,listReplace);
|
430
|
+
drawSwitch = 1;
|
431
|
+
captureListStart = true;
|
432
|
+
periodAddition = '';
|
433
|
+
periodAdditionClean = '';
|
434
|
+
if (matches = selectedText.match(/\n\s/g)) {
|
435
|
+
listItemsAddition = matches.length;
|
436
|
+
}
|
437
|
+
}
|
438
|
+
// must be a block modification e.g. p>. to p<.
|
439
|
+
else {
|
440
|
+
|
441
|
+
// if this is a block modification/addition
|
442
|
+
if (button.tagStart.match(/(h1|h2|h3|h4|h5|h6|bq|p)/g)) {
|
443
|
+
if (tagPartBlock == '') {
|
444
|
+
drawSwitch = 2;
|
445
|
+
}
|
446
|
+
else {
|
447
|
+
drawSwitch = 1;
|
448
|
+
}
|
449
|
+
|
450
|
+
insertTag = button.tagStart + tagPartModifier;
|
451
|
+
}
|
452
|
+
|
453
|
+
// else this is a modifier modification/addition
|
454
|
+
else {
|
455
|
+
if ((tagPartModifier == '') && (tagPartBlock != '')) {
|
456
|
+
drawSwitch = 1;
|
457
|
+
}
|
458
|
+
else if (tagPartModifier == '') {
|
459
|
+
drawSwitch = 2;
|
460
|
+
}
|
461
|
+
else {
|
462
|
+
drawSwitch = 1;
|
463
|
+
}
|
464
|
+
|
465
|
+
// if no tag part block but a modifier we need at least the p tag
|
466
|
+
if (tagPartBlock == '') {
|
467
|
+
tagPartBlock = 'p';
|
468
|
+
}
|
469
|
+
|
470
|
+
//make sure to swap out outdent
|
471
|
+
if (button.tagStart == ')') {
|
472
|
+
tagPartModifier = '';
|
473
|
+
}
|
474
|
+
else {
|
475
|
+
tagPartModifier = button.tagStart;
|
476
|
+
captureIndentStart = true; // ugly hack to fix issue with proper selection handling
|
477
|
+
}
|
478
|
+
|
479
|
+
insertTag = tagPartBlock + tagPartModifier;
|
480
|
+
}
|
481
|
+
}
|
482
|
+
|
483
|
+
mplier = 0;
|
484
|
+
if (captureListStart || (tagPartModifier.match(/[\(\)]{1,}/g))) {
|
485
|
+
re_start = new RegExp(insertTag.escape + periodAddition,'g'); // for tags that mimic regex properties, parens + list tags
|
486
|
+
}
|
487
|
+
else {
|
488
|
+
re_start = new RegExp(insertTag + periodAddition,'g'); // for tags that don't, why i can't just escape everything i have no clue
|
489
|
+
}
|
490
|
+
re_old = new RegExp(tagPartBlock + tagPartModifierOrig + periodAddition,'g');
|
491
|
+
re_middle = new RegExp(newlineReplaceRegexDirty + insertTag.escape + periodAddition.escape,'g');
|
492
|
+
re_tag = new RegExp(insertTag.escape + periodAddition.escape,'g');
|
493
|
+
|
494
|
+
// *************************************************************************************************************************
|
495
|
+
// this is where everything gets swapped around or inserted, bullets and single options have their own if/else statements
|
496
|
+
// *************************************************************************************************************************
|
497
|
+
if ((drawSwitch == 0) || (drawSwitch == 1)) {
|
498
|
+
if (drawSwitch == 0) { // completely removing a tag
|
499
|
+
finalText = beginningText
|
500
|
+
+ newlineStart
|
501
|
+
+ selectedText.replace(re_start,'').replace(re_middle,newlineReplaceClean)
|
502
|
+
+ newlineEnd
|
503
|
+
+ followupText;
|
504
|
+
if (matches = selectedText.match(newlineReplaceRegexClean)) {
|
505
|
+
mplier = mplier + matches.length;
|
506
|
+
}
|
507
|
+
posDiffNeg = insertTag.length + 2 + (mplier*4);
|
508
|
+
}
|
509
|
+
else { // modifying a tag, though we do delete bullets here
|
510
|
+
finalText = beginningText
|
511
|
+
+ newlineStart
|
512
|
+
+ selectedText.replace(re_old,insertTag + periodAdditionClean)
|
513
|
+
+ newlineEnd
|
514
|
+
+ followupText;
|
515
|
+
|
516
|
+
if (matches = selectedText.match(newlineReplaceRegexClean)) {
|
517
|
+
mplier = mplier + matches.length;
|
518
|
+
}
|
519
|
+
// figure out the length of various elements to modify the selection position
|
520
|
+
if (captureIndentStart) { // need to double-check that this wasn't the first indent
|
521
|
+
tagPreviousLength = tagPartBlock.length;
|
522
|
+
tagCurrentLength = insertTag.length;
|
523
|
+
}
|
524
|
+
else if (captureListStart) { // if this is a list we're manipulating
|
525
|
+
if (button.tagStart == '(') { // if indenting
|
526
|
+
tagPreviousLength = listTypeMatch.length + 2;
|
527
|
+
tagCurrentLength = insertTag.length + listItemsAddition;
|
528
|
+
}
|
529
|
+
else if (insertTag.match(/(\*|\#)/g)) { // if removing but still has bullets
|
530
|
+
tagPreviousLength = insertTag.length + listItemsAddition;
|
531
|
+
tagCurrentLength = listTypeMatch.length;
|
532
|
+
}
|
533
|
+
else { // if removing last bullet
|
534
|
+
tagPreviousLength = insertTag.length + listItemsAddition;
|
535
|
+
tagCurrentLength = listTypeMatch.length - (3*listItemsAddition) - 1;
|
536
|
+
}
|
537
|
+
}
|
538
|
+
else { // everything else
|
539
|
+
tagPreviousLength = tagPartBlock.length + tagPartModifier.length;
|
540
|
+
tagCurrentLength = insertTag.length;
|
541
|
+
}
|
542
|
+
if (tagCurrentLength > tagPreviousLength) {
|
543
|
+
posDiffPos = (tagCurrentLength - tagPreviousLength) + (mplier*(tagCurrentLength - tagPreviousLength));
|
544
|
+
}
|
545
|
+
else {
|
546
|
+
posDiffNeg = (tagPreviousLength - tagCurrentLength) + (mplier*(tagPreviousLength - tagCurrentLength));
|
547
|
+
}
|
548
|
+
}
|
549
|
+
}
|
550
|
+
else { // for adding tags other then bullets (have their own statement)
|
551
|
+
finalText = beginningText
|
552
|
+
+ newlineStart
|
553
|
+
+ insertTag + '. '
|
554
|
+
+ selectedText.replace(newlineReplaceRegexClean,button.tagEnd + '\n' + insertTag + '. ')
|
555
|
+
+ newlineFollowup
|
556
|
+
+ newlineEnd
|
557
|
+
+ followupText;
|
558
|
+
if (matches = selectedText.match(newlineReplaceRegexClean)) {
|
559
|
+
mplier = mplier + matches.length;
|
560
|
+
}
|
561
|
+
posDiffPos = insertTag.length + 2 + (mplier*4);
|
562
|
+
}
|
563
|
+
}
|
564
|
+
|
565
|
+
// swap in and out the simple tags around a selection like bold
|
566
|
+
else {
|
567
|
+
|
568
|
+
mplier = 1; // the multiplier for the tag length
|
569
|
+
re_start = new RegExp('^\\' + button.tagStart,'g');
|
570
|
+
re_end = new RegExp('\\' + button.tagEnd + '$','g');
|
571
|
+
re_middle = new RegExp('\\' + button.tagEnd + newlineReplaceRegexDirty + '\\' + button.tagStart,'g');
|
572
|
+
if (selectedText.match(re_start) && selectedText.match(re_end)) {
|
573
|
+
finalText = beginningText
|
574
|
+
+ newlineStart
|
575
|
+
+ selectedText.replace(re_start,'').replace(re_end,'').replace(re_middle,newlineReplaceClean)
|
576
|
+
+ newlineEnd
|
577
|
+
+ followupText;
|
578
|
+
if (matches = selectedText.match(newlineReplaceRegexClean)) {
|
579
|
+
mplier = mplier + matches.length;
|
580
|
+
}
|
581
|
+
posDiffNeg = button.tagStart.length*mplier + button.tagEnd.length*mplier;
|
582
|
+
}
|
583
|
+
else {
|
584
|
+
finalText = beginningText
|
585
|
+
+ newlineStart
|
586
|
+
+ button.tagStart
|
587
|
+
+ selectedText.replace(newlineReplaceRegexClean,button.tagEnd + newlineReplaceClean + button.tagStart)
|
588
|
+
+ button.tagEnd
|
589
|
+
+ newlineEnd
|
590
|
+
+ followupText;
|
591
|
+
if (matches = selectedText.match(newlineReplaceRegexClean)) {
|
592
|
+
mplier = mplier + matches.length;
|
593
|
+
}
|
594
|
+
posDiffPos = (button.tagStart.length*mplier) + (button.tagEnd.length*mplier);
|
595
|
+
}
|
596
|
+
}
|
597
|
+
|
598
|
+
cursorPos += button.tagStart.length + button.tagEnd.length;
|
599
|
+
|
600
|
+
}
|
601
|
+
|
602
|
+
// just swap in and out single values, e.g. someone clicks b they'll get a *
|
603
|
+
else {
|
604
|
+
var buttonStart = '';
|
605
|
+
var buttonEnd = '';
|
606
|
+
var re_p = new RegExp('(\\<|\\>|\\=|\\<\\>|\\(|\\))','g');
|
607
|
+
var re_h = new RegExp('^(h1|h2|h3|h4|h5|h6|p|bq)','g');
|
608
|
+
if (!this.checkOpenTags(button) || button.tagEnd == '') { // opening tag
|
609
|
+
|
610
|
+
if (button.tagStart.match(re_h)) {
|
611
|
+
buttonStart = button.tagStart + '. ';
|
612
|
+
}
|
613
|
+
else {
|
614
|
+
buttonStart = button.tagStart;
|
615
|
+
}
|
616
|
+
if (button.tagStart.match(re_p)) { // make sure that invoking block modifiers don't do anything
|
617
|
+
finalText = beginningText
|
618
|
+
+ followupText;
|
619
|
+
cursorPos = startPos;
|
620
|
+
}
|
621
|
+
else {
|
622
|
+
finalText = beginningText
|
623
|
+
+ buttonStart
|
624
|
+
+ followupText;
|
625
|
+
this.addTag(button);
|
626
|
+
cursorPos = startPos + buttonStart.length;
|
627
|
+
}
|
628
|
+
|
629
|
+
}
|
630
|
+
else { // closing tag
|
631
|
+
if (button.tagStart.match(re_p)) {
|
632
|
+
buttonEnd = '\n\n';
|
633
|
+
}
|
634
|
+
else if (button.tagStart.match(re_h)) {
|
635
|
+
buttonEnd = '\n\n';
|
636
|
+
}
|
637
|
+
else {
|
638
|
+
buttonEnd = button.tagEnd;
|
639
|
+
}
|
640
|
+
finalText = beginningText
|
641
|
+
+ button.tagEnd
|
642
|
+
+ followupText;
|
643
|
+
this.removeTag(button);
|
644
|
+
cursorPos = startPos + button.tagEnd.length;
|
645
|
+
}
|
646
|
+
}
|
647
|
+
|
648
|
+
// set the appropriate DOM value with the final text
|
649
|
+
if (FF == true) {
|
650
|
+
myField.value = finalText;
|
651
|
+
myField.scrollTop = scrollTop;
|
652
|
+
}
|
653
|
+
else {
|
654
|
+
sel.text = finalText;
|
655
|
+
}
|
656
|
+
|
657
|
+
// build up the selection capture, doesn't work in IE
|
658
|
+
if (textSelected) {
|
659
|
+
myField.selectionStart = startPos + newlineStartPos;
|
660
|
+
myField.selectionEnd = endPos + posDiffPos - posDiffNeg - newlineEndPos;
|
661
|
+
//alert('s: ' + myField.selectionStart + ' e: ' + myField.selectionEnd + ' sp: ' + startPos + ' ep: ' + endPos + ' pdp: ' + posDiffPos + ' pdn: ' + posDiffNeg)
|
662
|
+
}
|
663
|
+
else {
|
664
|
+
myField.selectionStart = cursorPos;
|
665
|
+
myField.selectionEnd = cursorPos;
|
666
|
+
}
|
667
|
+
}, // end insertTag
|
668
|
+
|
669
|
+
preview_text: function() {
|
670
|
+
|
671
|
+
var r = this.canvas.value;
|
672
|
+
|
673
|
+
// quick tags first
|
674
|
+
qtags = [['\\*', 'strong'],
|
675
|
+
['\\?\\?', 'cite'],
|
676
|
+
['\\+', 'ins'], //fixed
|
677
|
+
['~', 'sub'],
|
678
|
+
['\\^', 'sup'], // me
|
679
|
+
['@', 'code']];
|
680
|
+
for (var i=0;i<qtags.length;i++) {
|
681
|
+
ttag = qtags[i][0]; htag = qtags[i][1];
|
682
|
+
re = new RegExp(ttag+'\\b(.+?)\\b'+ttag,'g');
|
683
|
+
r = r.replace(re,'<'+htag+'>'+'$1'+'</'+htag+'>');
|
684
|
+
}
|
685
|
+
// underscores count as part of a word, so do them separately
|
686
|
+
re = new RegExp('\\b_(.+?)_\\b','g');
|
687
|
+
r = r.replace(re,'<em>$1</em>');
|
688
|
+
|
689
|
+
//jeff: so do dashes
|
690
|
+
re = new RegExp('[\s\n]-(.+?)-[\s\n]','g');
|
691
|
+
r = r.replace(re,'<del>$1</del>');
|
692
|
+
|
693
|
+
// links
|
694
|
+
re = new RegExp('"\\b(.+?)\\(\\b(.+?)\\b\\)":([^\\s]+)','g');
|
695
|
+
r = r.replace(re,'<a href="$3" title="$2">$1</a>');
|
696
|
+
re = new RegExp('"\\b(.+?)\\b":([^\\s]+)','g');
|
697
|
+
r = r.replace(re,'<a href="$2">$1</a>');
|
698
|
+
|
699
|
+
// BenL: Various special characters etc
|
700
|
+
re = new RegExp('\\(c\\)','g');
|
701
|
+
r = r.replace(re,'©');
|
702
|
+
re = new RegExp('\\(tm\\)','g');
|
703
|
+
r = r.replace(re,'™');
|
704
|
+
re = new RegExp('\\(r\\)','g');
|
705
|
+
r = r.replace(re,'®');
|
706
|
+
re = new RegExp('\\.\\.\\.','g');
|
707
|
+
r = r.replace(re,'…');
|
708
|
+
re = new RegExp('"(.+?)"([\\s:,;])','g');
|
709
|
+
r = r.replace(re,'“$1”$2');
|
710
|
+
re = new RegExp('\\-\\-','g');
|
711
|
+
r = r.replace(re,'—');
|
712
|
+
re = new RegExp(' \\- ','g');
|
713
|
+
r = r.replace(re,' — ');
|
714
|
+
|
715
|
+
// Beef: images with links
|
716
|
+
re = new RegExp('!\\b(.+?)\\(\\b(.+?)\\b\\)!:([^\\s]+)','g');
|
717
|
+
r = r.replace(re,'<a href="$3" title="$2"><img src="$1" alt="$2"/></a>');
|
718
|
+
re = new RegExp('!\\b(.+?)\\b!:([^\\s]+)','g');
|
719
|
+
r = r.replace(re,'<a href="$2"><img src="$1"/></a>');
|
720
|
+
|
721
|
+
|
722
|
+
// images
|
723
|
+
re = new RegExp('!\\b(.+?)\\(\\b(.+?)\\b\\)!','g');
|
724
|
+
r = r.replace(re,'<img src="$1" alt="$2"/>');
|
725
|
+
re = new RegExp('!\\b(.+?)\\b!','g');
|
726
|
+
r = r.replace(re,'<img src="$1"/>');
|
727
|
+
|
728
|
+
// block level formatting
|
729
|
+
|
730
|
+
// Jeff's hack to show single line breaks as they should.
|
731
|
+
// insert breaks - but you get some....stupid ones
|
732
|
+
re = new RegExp('(.*)\n([^#\*\n].*)','g');
|
733
|
+
r = r.replace(re,'$1<br />$2');
|
734
|
+
// remove the stupid breaks.
|
735
|
+
re = new RegExp('\n<br />','g');
|
736
|
+
r = r.replace(re,'\n');
|
737
|
+
|
738
|
+
lines = r.split('\n');
|
739
|
+
nr = '';
|
740
|
+
for (var i=0;i<lines.length;i++) {
|
741
|
+
line = lines[i].replace(/\s*$/,'');
|
742
|
+
changed = 0;
|
743
|
+
if (line.search(/^\s*bq\.\s+/) != -1) {
|
744
|
+
line = line.replace(/^\s*bq\.\s+/,'\t<blockquote>')+'</blockquote>';
|
745
|
+
changed = 1;
|
746
|
+
}
|
747
|
+
|
748
|
+
// jeff adds h#.
|
749
|
+
if (line.search(/^\s*h[1|2|3|4|5|6]\.\s+/) != -1) {
|
750
|
+
re = new RegExp('h([1|2|3|4|5|6])\.(.+)','g');
|
751
|
+
line = line.replace(re,'<h$1>$2</h$1>');
|
752
|
+
changed = 1;
|
753
|
+
}
|
754
|
+
|
755
|
+
if (line.search(/^\s*\*\s+/) != -1) { line = line.replace(/^\s*\*\s+/,'\t<liu>') + '</liu>'; changed = 1; } // * for bullet list; make up an liu tag to be fixed later
|
756
|
+
if (line.search(/^\s*#\s+/) != -1) { line = line.replace(/^\s*#\s+/,'\t<lio>') + '</lio>'; changed = 1; } // # for numeric list; make up an lio tag to be fixed later
|
757
|
+
if (!changed && (line.replace(/\s/g,'').length > 0)) line = '<p>'+line+'</p>';
|
758
|
+
lines[i] = line + '\n';
|
759
|
+
}
|
760
|
+
|
761
|
+
// Second pass to do lists
|
762
|
+
inlist = 0;
|
763
|
+
listtype = '';
|
764
|
+
for (var i=0;i<lines.length;i++) {
|
765
|
+
line = lines[i];
|
766
|
+
if (inlist && listtype == 'ul' && !line.match(/^\t<liu/)) { line = '</ul>\n' + line; inlist = 0; }
|
767
|
+
if (inlist && listtype == 'ol' && !line.match(/^\t<lio/)) { line = '</ol>\n' + line; inlist = 0; }
|
768
|
+
if (!inlist && line.match(/^\t<liu/)) { line = '<ul>' + line; inlist = 1; listtype = 'ul'; }
|
769
|
+
if (!inlist && line.match(/^\t<lio/)) { line = '<ol>' + line; inlist = 1; listtype = 'ol'; }
|
770
|
+
lines[i] = line;
|
771
|
+
}
|
772
|
+
|
773
|
+
r = lines.join('\n');
|
774
|
+
// jeff added : will correctly replace <li(o|u)> AND </li(o|u)>
|
775
|
+
r = r.replace(/li[o|u]>/g,'li>');
|
776
|
+
|
777
|
+
return r;
|
778
|
+
|
779
|
+
|
780
|
+
|
781
|
+
} // End preview text
|
782
|
+
|
783
|
+
|
784
|
+
}; // end class
|
785
|
+
|
786
|
+
// add class methods
|
787
|
+
Object.extend(TextileEditor, TextileEditor.Methods);
|
788
|
+
document.write('<script src="/javascripts/textile-editor-config.js" type="text/javascript"></script>');
|