Refactored code, with an aim of allowing more than one HTMLarea on a page

This commit is contained in:
Martin Green 2022-06-26 18:29:20 +01:00
parent f1fcef2a6f
commit 4e5d8d1d76
6 changed files with 197 additions and 140 deletions

View File

@ -133,3 +133,11 @@ class NewWebImageForm(forms.Form):
class HTMLarea(forms.Textarea):
template_name = "widgets/HTMLarea.html"
def __init__(self, *args, **kwargs):
self.iframeattrs = kwargs.pop('iframeattrs')
super(forms.Textarea, self).__init__(*args, **kwargs)
def get_context(self, name, value, attrs):
c = super(forms.Textarea, self).get_context(name, value, attrs)
c["iframe"] = {"attrs": self.iframeattrs}
return c

View File

@ -382,5 +382,6 @@ class ExpoPageForm(forms.Form):
'''The form used by the editexpopage function
'''
title = forms.CharField(widget=forms.TextInput(attrs={'size':'60', 'placeholder': "Enter title (displayed in tab)"}))
html = forms.CharField(widget=HTMLarea(attrs={"cols":80, "rows":20, 'placeholder': "Enter page content (using HTML)"}))
html = forms.CharField(widget=HTMLarea(iframeattrs = {"height": "80%"},
attrs={"height":"80%", "rows":20, 'placeholder': "Enter page content (using HTML)"}))
change_message = forms.CharField(widget=forms.Textarea(attrs={"cols":80, "rows":3, 'placeholder': "Descibe the change made (for git)"}))

View File

@ -1,15 +1,18 @@
{% extends "expobase.html" %}
{% block title %}Edit {{ path }}{% endblock %}
{% block extrahead %}
{% include 'html_editor_scripts_css.html' %}
{% endblock %}
{% block body %}
<h1>Edit {{ path }}</h1>
<h1>Edit {{ path }}</h1>
{% include 'html_editor_pop_ups.html' %}
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<p><input type="submit" value="Submit" /></p>
</form>
{% include "menu.html" %}
{% include 'html_editor_scripts_css.html' %}
{% endblock %}

View File

@ -0,0 +1,19 @@
<!--Creates the add image popup-->
<div class="add-image-popup popup-overlay">
<div class="add-image-popup popup-content">
<h2>Select Image</h2>
<p id="image_popup_content"> Loading ...</p>
<button onclick="new_image_popup()">Upload Image</button>
<button class="close" onclick="$('.add-image-popup').removeClass('active');">Close</button>
</div>
</div>
<!--Creates the new image popup-->
<div class="new-image-popup popup-overlay">
<div class="new-image-popup popup-content">
<h2>New Image</h2>
<p id="new_image_popup_content"> Loading ...</p>
<button class="close" onclick="$('.new-image-popup').removeClass('active');">Close</button>
</div>
</div>

View File

@ -1,3 +1,5 @@
<script src="{{ settings.MEDIA_URL }}admin/js/vendor/jquery/jquery.js" type="text/javascript"></script>
<script src={{ settings.MEDIA_URL }}codemirror/codemirror.js></script>
@ -7,7 +9,64 @@
<script src={{ settings.MEDIA_URL }}codemirror/htmlmixed.js></script>
<link rel=stylesheet href={{ settings.MEDIA_URL }}codemirror/codemirror.css>
<link rel=stylesheet href={{ settings.MEDIA_URL }}codemirror/docs.css>
<style type=text/css>
html {
font-family: "Helvetica Neue", sans-serif;
width: 100%;
color: #666666;
text-align: center;
}
.popup-overlay {
/*Hides pop-up when there is no "active" class*/
visibility: hidden;
position: fixed;
top: 10%;
left: 10%;
background: #ffffff;
border: 3px solid #666666;
width: 80%;
height: 80%;
overflow: scroll;
left: 5%;
z-index: 20;
}
.popup-overlay.active {
/*displays pop-up when "active" class is present*/
visibility: visible;
text-align: center;
}
.popup-content {
/*Hides pop-up content when there is no "active" class */
visibility: hidden;
}
.popup-content.active {
/*Shows pop-up content when "active" class is present */
visibility: visible;
}
button {
display: inline-block;
vertical-align: middle;
border-radius: 30px;
margin: .20rem;
font-size: 1rem;
color: #666666;
background: #ffffff;
border: 1px solid #666666;
}
button:hover {
border: 1px solid #666666;
background: #666666;
color: #ffffff;
}
</style>
<style type=text/css>
.CodeMirror {
float: left;
width: 50%;
@ -33,120 +92,53 @@
height: 5%;
}
</style>
<style type=text/css>
html {
font-family: "Helvetica Neue", sans-serif;
width: 100%;
color: #666666;
text-align: center;
}
.popup-overlay {
/*Hides pop-up when there is no "active" class*/
visibility: hidden;
position: absolute;
background: #ffffff;
border: 3px solid #666666;
width: 90%;
height: 80%;
overflow: scroll;
left: 5%;
z-index: 20;
}
.popup-overlay.active {
/*displays pop-up when "active" class is present*/
visibility: visible;
text-align: center;
}
.popup-content {
/*Hides pop-up content when there is no "active" class */
visibility: hidden;
}
.popup-content.active {
/*Shows pop-up content when "active" class is present */
visibility: visible;
}
</style>
<script>
function add_image_popup() {
$('.add-image-popup').addClass('active');
$('#image_popup_content').load("{% url 'image_selector' path %}", function() {
$('.thumbnail').click(function(){
$(".add-image-popup").removeClass("active");
addStr($( this ).attr("data-html"))
});
})
}
function new_image_popup() {
$('.add-image-popup').removeClass('active');
$('.new-image-popup').addClass('active');
$.ajax({
type : "GET",
dataType: "json",
url: "{% url 'new_image_form' path %}",
success: function(data){handle_new_image(data)}
});
}
$(function() {
function handle_new_image(data) {
if (data.hasOwnProperty('form')) {
$('#new_image_popup_content').html(data.form);
$('#new_image_form').on('submit', function(e){
e.preventDefault();
data = $('#new_image_form').serialize();
$.ajax({
type : "POST",
dataType: "json",
url: "{% url 'new_image_form' path %}",
data: new FormData($('#new_image_form')[0]),
processData: false,
contentType: false,
success: function(data){
handle_new_image(data);
}
});
$(".HTMLarea").each(function(){
var HTMLarea = $(this).children("textarea")
HTMLarea.data("editor",
CodeMirror.fromTextArea(HTMLarea[0], {
mode: 'text/html',
tabMode: 'indent',
onChange: function() {
clearTimeout(HTMLarea.data("delay"));
HTMLarea.data("delay", setTimeout(updatePreview, 300, HTMLarea));
}
})
);
HTMLarea.data("preview", $('#preview'));
updatePreview(HTMLarea);
});
}
else if (data.hasOwnProperty('html')) {
$('.new-image-popup').removeClass('active');
addStr(data.html);
}
else {
alert(data.error);
}
}
</script>
<script>
var delay;
// Initialize CodeMirror editor with a nice html5 canvas demo.
var editor = CodeMirror.fromTextArea(document.getElementById('id_html'), {
mode: 'text/html',
tabMode: 'indent',
onChange: function() {
clearTimeout(delay);
delay = setTimeout(updatePreview, 300);
}
});
$(".addTag").click(function(){
addTag($(this).parents(".HTMLarea").children("textarea").data("editor"),
$(this).attr("data-tag"),
$(this).attr("data-attr") || ""
);
})
function updatePreview() {
var previewFrame = document.getElementById('preview');
var preview = previewFrame.contentDocument || previewFrame.contentWindow.document;
$(".addStr").click(function(){
addStr($(this).parents(".HTMLarea").children("textarea").data("editor"),
$(this).attr("data-str")
);
})
$(".addImage").click(function(){
add_image_popup($(this).parents(".HTMLarea").children("textarea").data("editor"));
})
});
function updatePreview(HTMLarea) {
var preview = $('#preview')[0].contentDocument || $('#preview')[0].contentWindow.document;
preview.open();
preview.write("<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8' /><link rel='stylesheet' type='text/css' href='/css/main2.css' /> <style type=text/css>body{max-width: none;margin-left: 15px;margin-right: 15px;}</style></head><body>");
preview.write(editor.getValue());
preview.write(HTMLarea.data("editor").getValue());
preview.write("</body></html>");
preview.close();
}
setTimeout(updatePreview, 300);
function addTag(tag, attr){
// For codemirror & center cursor
function addTag(editor, tag, attr){
var from = editor.getCursor(true);
var to = editor.getCursor(false);
editor.replaceRange("</"+tag+">", to);
@ -156,11 +148,62 @@ function handle_new_image(data) {
editor.setCursor({line: to.line , ch : to.ch + 2 + tag.length + attr.length });
}
function addStr(x){
function addStr(editor, x){
var to = editor.getCursor(false);
editor.replaceRange(x, to);
editor.focus();
editor.setCursor({line: to.line , ch : to.ch + x.length });
}
function add_image_popup(editor) {
$('.add-image-popup').addClass('active');
window.current_editor = editor;
$('#image_popup_content').load("{% url 'image_selector' path %}", function() {
$('.thumbnail').click(function(){
$(".add-image-popup").removeClass("active");
addStr(window.current_editor, $( this ).attr("data-html"))
});
})
}
function new_image_popup() {
$('.add-image-popup').removeClass('active');
$('.new-image-popup').addClass('active');
$.ajax({
type : "GET",
dataType: "json",
url: "{% url 'new_image_form' path %}",
success: function(data){handle_new_image(data)}
});
}
function handle_new_image(data) {
if (data.hasOwnProperty('form')) {
$('#new_image_popup_content').html(data.form);
$('#new_image_form').on('submit', function(e){
e.preventDefault();
data = $('#new_image_form').serialize();
$.ajax({
type : "POST",
dataType: "json",
url: "{% url 'new_image_form' path %}",
data: new FormData($('#new_image_form')[0]),
processData: false,
contentType: false,
success: function(data){
handle_new_image(data);
}
});
});
}
else if (data.hasOwnProperty('html')) {
$('.new-image-popup').removeClass('active');
addStr(window.current_editor, data.html);
}
else {
alert(data.error);
}
}
</script>

View File

@ -1,32 +1,15 @@
<!--Creates the add image popup-->
<div><div class="add-image-popup popup-overlay">
<div class="add-image-popup popup-content">
<h2>Select Image</h2>
<p id="image_popup_content"> Loading ...</p>
<button onclick="new_image_popup()">Upload Image</button>
<button class="close" onclick="$('.add-image-popup').removeClass('active');">Close</button>
</div>
</div>
<!--Creates the new image popup-->
<div class="new-image-popup popup-overlay">
<div class="new-image-popup popup-content">
<h2>New Image</h2>
<p id="new_image_popup_content"> Loading ...</p>
<button class="close" onclick="$('.new-image-popup').removeClass('active');">Close</button>
</div>
</div>
<div class="HTMLarea">
{% include "django/forms/widgets/textarea.html" %}
<iframe id=preview></iframe>
<button type="button" onclick="addTag('i', '')">italic</button>
<button type="button" onclick="addTag('b', '')">bold</button>
<button type="button" onclick="addTag('h2', 'id=&quot;tophead&quot;')">top heading</button>
<button type="button" onclick="addTag('h1', '')">heading 1</button>
<button type="button" onclick="addTag('h2', '')">heading 2</button>
<button type="button" onclick="addTag('h3', '')">heading 3</button>
<button type="button" onclick="addTag('h4', '')">heading 4</button>
<button type="button" onclick="addTag('a', 'href=&quot;&quot;')">hyperlink</button>
<button type="button" onclick="addTag('p', '')">paragraph</button>
<button type="button" onclick="add_image_popup()">image</button>
<button type="button" onclick="addStr('<hr/>')">horizontal line</button>
<iframe id=preview class="HTMLpreview" {% include "django/forms/widgets/attrs.html" with widget=iframe %}></iframe>
<button type="button" class="addTag" data-tag="i">italic</button>
<button type="button" class="addTag" data-tag="b">bold</button>
<button type="button" class="addTag" data-tag="h2" data-attr="id=&quot;tophead&quot;">top heading</button>
<button type="button" class="addTag" data-tag="h1">heading 1</button>
<button type="button" class="addTag" data-tag="h2">heading 2</button>
<button type="button" class="addTag" data-tag="h3">heading 3</button>
<button type="button" class="addTag" data-tag="h4">heading 4</button>
<button type="button" class="addTag" data-tag="a" data-attr='href=&quot;&quot;'>hyperlink</button>
<button type="button" class="addTag" data-tag="p">paragraph</button>
<button type="button" class="addImage">image</button>
<button type="button" class="addStr" data-str="</hr>">horizontal line</button>
</div>