Comments (2)
I try to fix it by naively add the following script after page loaded
<script>
// Wait for the DOM to be ready
document.addEventListener("DOMContentLoaded", function () {
// Get all forms with an ID starting with "martor-"
var martorForms = document.querySelectorAll('[id^="martor-"]');
console.log('I am runing')
console.log(martorForms)
// Loop through each form and add the specified classes
martorForms.forEach(function (form) {
form.classList.add("ace_editor", "ace_hidpi", "ace-github", "resizable");
// Insert the specified content between div tags in the form
if (form.innerHTML == null) {
form.innerHTML = '<div style="position: absolute;"></div><textarea class="ace_text-input" wrap="off" autocorrect="off" autocapitalize="none" spellcheck="false" style="opacity: 0; font-size: 1px;" aria-haspopup="false" aria-autocomplete="both" role="textbox"></textarea><div class="ace_gutter" aria-hidden="true"><div class="ace_layer ace_gutter-layer ace_folding-enabled" style="height: 1000000px;"></div></div><div class="ace_scroller" style="line-height: 0px;"><div class="ace_content"><div class="ace_layer ace_print-margin-layer"><div class="ace_print-margin" style="left: 4px; visibility: hidden;"></div></div><div class="ace_layer ace_marker-layer"></div><div class="ace_layer ace_text-layer" style="height: 1000000px; margin: 0px 4px;"></div><div class="ace_layer ace_marker-layer"></div><div class="ace_layer ace_cursor-layer ace_hidden-cursors"><div class="ace_cursor"></div></div></div></div><div class="ace_scrollbar ace_scrollbar-v" style="display: none; width: 20px;"><div class="ace_scrollbar-inner" style="width: 20px;"> </div></div><div class="ace_scrollbar ace_scrollbar-h" style="display: none; height: 20px;"><div class="ace_scrollbar-inner" style="height: 20px;"> </div></div><div style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; font: inherit; overflow: hidden;"><div style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; font: inherit; overflow: visible;"></div><div style="height: auto; width: auto; top: 0px; left: 0px; visibility: hidden; position: absolute; white-space: pre; font: inherit; overflow: visible;">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</div></div><div class="resizable-handle resizable-b"></div>' + form.innerHTML;
}
});
});
</script>
It didn't work of course. I also tried to change the line 33 of the templates/martor/editor.html
from
<div id="martor-{{ field_name }}" class="martor-field martor-field-{{ field_name }}"></div>
to
<div id="martor-{{ field_name }}-test" class="martor-field martor-field-{{ field_name }}"></div>
And, everything goes wrong.
From these tests, I feel the process to render a proper markdown editor is controlled by some js
in plugins, but without an overview of how an editor is generated, I am afraid that I am not able to solve this bug.
from django-markdown-editor.
I attempted two approaches to address this bug. The first one, which I considered more robust, unfortunately, did not succeed. Let me begin by presenting the code that was successful. If authors acknowledged this approach. I can push my version to brench.
Succesful way
class MartorWidget(forms.Textarea):
def render(self, name, value, attrs=None, renderer=None, **kwargs):
import random, string
random_string = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(10))
attrs['id'] = attrs['id'] + '-' + random_string
# Make the settings the default attributes to pass
attributes_to_pass = {
"data-enable-configs": MARTOR_ENABLE_CONFIGS,
"data-markdownfy-url": reverse("martor_markdownfy"),
}
if MARTOR_UPLOAD_URL:
attributes_to_pass["data-upload-url"] = reverse("imgur_uploader")
if MARTOR_SEARCH_USERS_URL:
attributes_to_pass["data-search-users-url"] = reverse("search_user_json")
if MARTOR_SEARCH_USERS_URL:
attributes_to_pass["data-base-emoji-url"] = MARTOR_MARKDOWN_BASE_EMOJI_URL
# Make sure that the martor value is in the class attr passed in
if "class" in attrs:
attrs["class"] += " martor"
else:
attrs["class"] = "martor"
# Update and overwrite with the attributes passed in
attributes_to_pass.update(attrs)
# Update and overwrite with any attributes that are on the widget
# itself. This is also the only way we can push something in without
# being part of the render chain.
attributes_to_pass.update(self.attrs)
template = get_template("martor/%s/editor.html" % get_theme())
emoji_enabled = MARTOR_ENABLE_CONFIGS.get("emoji") == "true"
mentions_enabled = MARTOR_ENABLE_CONFIGS.get("mention") == "true"
widget = super().render(name + '-' + random_string, value, attributes_to_pass)
return template.render(
{
"martor": widget,
"field_name": name,
"random_string": random_string,
"emoji_enabled": emoji_enabled,
"mentions_enabled": mentions_enabled,
"toolbar_buttons": MARTOR_TOOLBAR_BUTTONS,
}
)
Lines that I added and changed:
- Line 3 and 4: I add
import random, string
random_string = ''.join(random.choice(string.ascii_letters + string.digits) for x in range(10))
- Line 37: I change
widget = super().render(name, value, attributes_to_pass)
towidget = super().render(name + '-' + random_string, value, attributes_to_pass)
- Line 43: I add
"random_string": random_string,
Then, in editor.html, we have to put -{{ random_string }}
after each {{ field_name }}
.
{% load i18n %}
<div class="main-martor main-martor-{{ field_name }}-{{random_string}}" data-field-name="{{ field_name }}-{{random_string}}">
<div class="section-martor">
<nav class="tab-martor-menu" style="position:relative">
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-link active" data-tab="editor-tab-{{ field_name }}-{{random_string}}" id="nav-editor-tab-{{ field_name }}-{{random_string}}" data-bs-toggle="tab" data-bs-target="#nav-editor-{{ field_name }}-{{random_string}}" type="button" role="tab" aria-controls="nav-editor-{{ field_name }}-{{random_string}}" aria-selected="true">
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-pencil-square" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456l-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z"/>
<path fill-rule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5v11z"/>
</svg>
<span>{% trans "Editor" %}</span>
</a>
<a class="nav-link" data-tab="preview-tab-{{ field_name }}-{{random_string}}" id="nav-preview-tab-{{ field_name }}-{{random_string}}" data-bs-toggle="tab" data-bs-target="#nav-preview-{{ field_name }}-{{random_string}}" type="button" role="tab" aria-controls="nav-preview-{{ field_name }}-{{random_string}}" aria-selected="false">
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-eye-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0z"/>
<path fill-rule="evenodd" d="M0 8s3-5.5 8-5.5S16 8 16 8s-3 5.5-8 5.5S0 8 0 8zm8 3.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z"/>
</svg>
<span>{% trans "Preview" %}</span>
</a>
{% include "martor/bootstrap/toolbar.html" %}
</div>
</nav>
<div class="tab-content" id="nav-tabContent">
<div class="tab-pane fade show active" id="nav-editor-{{ field_name }}-{{random_string}}" role="tabpanel" aria-labelledby="nav-editor-tab-{{ field_name }}-{{random_string}}">
<div class="text-center upload-progress" data-field-name="{{ field_name }}-{{random_string}}" style="display:none">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
<div>{% trans "Uploading... please wait..." %}</div>
</div>
<div id="martor-{{ field_name }}-{{random_string}}" class="martor-field martor-field-{{ field_name }}"></div>
{{ martor }}
<span class="icon expand-editor">
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-arrows-expand" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h13a.5.5 0 0 1 0 1h-13A.5.5 0 0 1 1 8zM7.646.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 1.707V5.5a.5.5 0 0 1-1 0V1.707L6.354 2.854a.5.5 0 1 1-.708-.708l2-2zM8 10a.5.5 0 0 1 .5.5v3.793l1.146-1.147a.5.5 0 0 1 .708.708l-2 2a.5.5 0 0 1-.708 0l-2-2a.5.5 0 0 1 .708-.708L7.5 14.293V10.5A.5.5 0 0 1 8 10z"/>
</svg>
</span>
</div>
<div class="tab-pane fade martor-preview" id="nav-preview-{{ field_name }}-{{random_string}}" role="tabpanel" aria-labelledby="nav-preview-tab-{{ field_name }}-{{random_string}}">
<p>{% trans "Nothing to preview" %}</p>
</div>
</div>
</div><!-- end /.section-martor -->
{% include 'martor/bootstrap/guide.html' %}
{% include 'martor/bootstrap/emoji.html' %}
</div>
Unsuccesful way
My original plan is to change all {{ field_name }}
to {{ model_name }}-{{ field_name }}-{{ instance_id }}
. It means that I have to input model_name
and instance_id
into MartorWidget and let it render. There is no problem I can put model_name
as a parameter of MartorWidget
. However, the trouble is instance_id
. It needs to be dynamic in Form's metaclass. After googling for hours, I found it was impossible to do so. Therefore, I discard this method.
from django-markdown-editor.
Related Issues (20)
- incompatibility with Python versions below 3.9 HOT 7
- After version 1.6.26 the setting MARTOR_UPLOAD_URL is ignored HOT 6
- The editor does not work when setting a Content Security Policy HOT 1
- Loosen restriction on importlib-metadata HOT 4
- Emoji url is done HOT 1
- toolbar nav style issue HOT 1
- Error with markdownify HOT 1
- Adding a new instance in an admin inline results in Uncaught TypeError HOT 1
- Losing text when (semi)colons follow links. HOT 2
- preview is not displaying correctly for “ordered” and “unordered” list items. HOT 1
- 📣 Call for Contributors: Help Needed to Maintain and Enhance django-markdown-editor! HOT 6
- Enable specifying the size of an image HOT 1
- Django 5 & Python 3.12 support HOT 2
- Updating Editor Content with Javascript HOT 1
- Django 4.2.11 support HOT 2
- Copy/Paste clipboard images HOT 1
- Dynamic MARTOR_UPLOAD_URL HOT 1
- Improve documentation for using html HOT 2
- Stop tagging Django with a less than version. HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from django-markdown-editor.