TinyMCE Select text area by parent form ID - ruby-on-rails-4

I was looking at http://archive.tinymce.com/wiki.php/Configuration3x:editor_selector
Is there a way to select a textbox only if it is under a <form> with a specific id?
For example:
<form id="edit_page">
<textarea></textarea>
<form>
I know I can add a class to the text area to get it to work, but I'm hoping for this solution for my use case. As I'm using Active_admin and I don't want to have to redefine all the default forms for it.

If you are okay with using the tinyMCE jquery plugin, you can select the elements using the jquery selector($) and then call the tinymce function over that.
Codepen example is here.
JS Part:
$(function() {
$('#edit_page2 textarea').tinymce({
script_url : 'https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.3.4/tinymce.min.js',
theme : "modern",
mode : "textareas"
});
});
HTML Part :
<form id="edit_page1">
<textarea></textarea>
</form>
<form id="edit_page2">
<textarea></textarea>
</form>
<form id="edit_page3">
<textarea></textarea>
</form>
This will select based on the parent's id. You can use any type of css selector.
You will need to include jquery and tinyMce's jquery file
//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js
https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.3.4/jquery.tinymce.min.js

Related

Stylized HTML fields in Django admin

I Have TextField to store HTML text. I want to colorize HTML tags. I use TinyMCE but didn't need an HTML editor like WordPress just simple to colorize like IDE, Search a lot but didn't find anything useful, So if you can help I appreciate it.
My field:
I want output like this but changeable:
Using a code editor in Django admin Textarea
The following is implemented with CodeMirror but you can use any other library (Monaco, etc).
Final result:
For all the libraries, we need to add some library specific javascript and stylesheet plus some custom code for integration.
Django has pretty flexible templating to enable this. We can override the entire template or specific blocks. Detailed documentation can be fond here.
To integration CodeMirror, we can override the admin/base.html 's extrahead block. We will include the required js/css, one extra css for theming and some js to find and apply CodeMirror.
Here, I have create a admin/base.html inside my project's configured template directory. This will apply to all the apps and models. There are ways to target an app or model individually - check the office docs.
This works for JSONField data. You will have to tweak a bit to format
html or any other language.
Inspect the page and find id of the textarea you want to target
<!-- tested with Django 3.2.9 -->
{% extends "admin/base.html" %}
{% block extrahead %}
{{ block.super }}
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/codemirror.min.js" crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/codemirror.min.css"
crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/theme/oceanic-next.min.css"
crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/mode/javascript/javascript.min.js"
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript">
window.addEventListener('load', (event) => {
const target = document.getElementById("id_data");
target.value = JSON.stringify(JSON.parse(target.value), null, ' ');
const config = {
mode: 'javascript',
theme: 'oceanic-next',
lineNumbers: true,
lineWrapping: true
}
const jsonCodeMirror = CodeMirror.fromTextArea(target, config);
jsonCodeMirror.setSize("100%", 600);
});
</script>
{% endblock %}
Multiple textarea inputs can be targeted as well with get element with classname and then looping over the result set and applying the same logic.
For html formatting,
you can use this https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.0/mode/htmlmixed/htmlmixed.min.js instead of javascript. Delete the json stringify statement. Change mode to htmlmixed.
Don't need to override any template
solved by integrating django-ace field and in this we have support for CSS, python, HTML etc also.
Simply use this in django forms and provide the form in django model admin class
admin file
from appname import forms
#admin.register(models.Table)
class TableModelAdmin(admin.ModelAdmin):
form = forms.TableModelForm
form file
from django import forms
from django_ace import AceWidget
class TableModelForm(forms.ModelForm):
class Meta:
model = models.Table
fields = '__all__'
widgets = {
'columns': AceWidget(
mode='json',
theme='None',
width='1200px',
height='500px',
fontsize='18px',
showprintmargin=False,
),
}

How to preselect an option in an embedded HTML form?

I try to preselect an option of a select in an embedded HTML form in Camunda Tasklist, but always the first option is preselected.
I followed Binding to a Process Variable:
Binding to a Process Variable
A select box can be bound to a process variable using the cam-variable-name directive:
<select cam-variable-name="foo" cam-variable-type="String">
<option>bar</option>
<option>zar</option>
</select>
Research
I read also CAM-3173:
select box doesn't show the correct option
If I set the value of variable by a select box on the start form, the next task form didn't show the option that has been choosen in the start form. It uses the same select box.
but I use Camunda 7.9 and the problem is fixed since version 7.2.3.
HTML
<form>
<select cam-variable-name="variable" cam-variable-type="String">
<option value="option1">option1</option>
<option value="option2">option2</option>
</select>
</form>
Result
option1 is preselected. I checked the process variable before entering the user task and it contains option2.
What did I wrong? If the bug still exists, is there any work-around?
I found a work-around, see Camunda Reference:
Implementing Custom Fields
The following is a small usage example which combines some of the features explained so far. It uses custom JavaScript to implement a custom interaction with a form field which does not use any cam-variable-* directives.
It shows how custom scripting can be used for
declaring a variable to be fetched from the backend,
writing the variable’s value to a form field,
reading the value upon submit.
[...]
The above example uses jQuery for interacting with the HTML controls. If you use AngularJS, you can also populate the $scope in the variables-fetched callback and read the values from the $scope in the submit callback:
My changed HTML:
<form>
<script cam-script type="text/form-script">
camForm.on('form-loaded', function() {
camForm.variableManager.fetchVariable('variable');
});
camForm.on('variables-fetched', function() {
$scope.variable = camForm.variableManager.variable('variable');
});
camForm.on('submit', function() {
camForm.variableManager.variableValue('variable', $scope.variable);
});
</script>
<select data-ng-model="variable">
<option value="option1">option1</option>
<option value="option2">option2</option>
</select>
</form>

Inner renderings not displaying

In a page, I have a rendering with a placeholder, Offcanvas.cshtml
<div data-ads-offcanvas-id="#Model.Id" class="ads-offcanvas #Html.GetCssStyles()">
#{
<a data-ads-offcanvas-trigger-id="#Model.Id" class="ads-close-button" href="#0">X</a>
#Html.Sitecore().Placeholder(LayoutHelper.GetPlaceholder(Placeholders.AccordionSection, Model.Id))
}
and inside that rendering, I plan to put another rendering with a placeholder named Modal.cshtml
<div data-ads-modal-container="#Model.Id" class="ads-modal-container">
<div class="ads-modal-dialog">
<div class="ads-close-box">
<a data-ads-modal-id="#Model.Id" href="#0">X</a>
</div>
<div class="ads-modal-content">
#Html.Sitecore().Placeholder(LayoutHelper.GetPlaceholder(Placeholders.AccordionSection, Model.Id))
</div>
</div>
So it looks like:
-Offcanvas
+-Modal
++-Text content
When I put text content inside the Modal rendering, the content is not rendered. I'm guessing that it only renders that first few renderings and fail to do so when the renderings became highly nested.
Is there a solution to render components to the very-most child?
Thanks guys!
EDIT:
Here's the code for GetPlaceholder:
public static string GetPlaceholder(string name, Guid id)
{
return $"{name}_{id}";
}
Dynamic placeholders are a bit more complicated than generating a unique placeholder key. The generated key still needs to resolve back to a real placeholder that is defined in Sitecore.
Check out the Integrated Dynamic Placeholder module.
This will provide an Html helper similar to your current implementation:
#Html.Sitecore().DynamicPlaceholder("[Placeholder Name]")

Using Bootstrap wysiwyg text editor in Django Form

I am using Django and Bootrap 2.32. I want to include this wysiwyg-bootrap-themed text editor: http://mindmup.github.io/bootstrap-wysiwyg/. The usage of this editor is fairly simple, including
$('#editor').wysiwyg();
in the JS-declaration will render each
<div class=editor></div>
into a beatiful wysiwyg text-editor.
Now the problem: I want to include this editor into one of my django form field. I have the single form:
class Article_Form(ModelForm):
Article_text = CharField(widget=Textarea(attrs = {'id' : 'editor'}))
class Meta:
model= Article
, whereas the Article model includes one simple CharField . Is there any chance, to get the editor work inside the Article_text form-field? With the above-mentioned widget, the created textarea cannot be controlled by the wysiwyg-editor-control buttons. Wrapping the form-template-tag like this
<div id="editor">
{{ Article_Form.Article_text }}
</div>
doesn't work either. The problem thus is that Django creates a textarea, wheras the editor would need a <div> to render correctly. Do you guys have any idea how to get this to work (without refering to django-wysiwyg).
Thanks!
I don't know enough about Django but I wrote the editor you're referring to, so here's a suggestion. Assuming the other answer on this page is correct and you can't generate a div directly, you can generate a text area using whatever Django templates you would normally do, then assign two events:
1) page onload event that would copy the textarea contents into the div, something like
$('#editor').html($('#textarea').val())
2) form onsubmit event that would reverse copy the current div contents into the textarea before it gets submitted
$('#textarea').val($('#editor').html())
Take a look at this.
Summernote is a simple WYSIWYG editor based on Twitter's Bootstrap.
django-summernote plugin allows you to embed Summernote into your Django admin page very handy.
https://github.com/lqez/django-summernote
Are you sure that this "plugin" doesn't work with textarea?
{{ Article_Form.Article_text }}
will be rendered to something like:
<textarea cols="40" id="id_Article_text" name="Article_text" rows="10"></textarea>
So there is a chance that you can initialize the wysiwyg editor like:
$('#id_Article_text').wysiwyg();
However after checking the plugin, I doubt that would be possible since it is using contenteditable="true" attribute of HTML5 and probably the plugin works with div only.
So there is no way you can make it work natively with Django form. The solution should be display other fields of your form manually, hide the one with textarea and display the editor instead:
<form action="" method="POST">
{{ Article_Form.field1 }}
{{ Article_Form.field2 }}
<div class=editor></div>
{% csrf_token %}
<input type="submit" value="Submit" id="submit-btn" />
</form>
Then you can use JS to submit your form:
$('#submit-btn').click(function (e) {
e.preventDefault();
$.ajax({
// do your magic here.
// note that you can get the content of the editor with: $('#editor').cleanHtml();
})
});
This way is hackish I agree so I don't recommend you go for it, just find other plugin then. Also please read PEP 8 carefully.
Hope it helps.
Take a look at this repo: https://github.com/rochapps/django-secure-input
I think it solves most of your problems.

twitter bootstrap date picker not working

I have been extensively searching for the answer but i cant seem to find one that works. I am using Django 1.4, with twitter boostrap 2.0.4 and i am trying to use date picker (eyecon) with no success. When i click on the input box no date box shows up.
<div id="due_date">
<input type="text" value="02/16/12" data-date-format="mm/dd/yy" id="datepicker" >
</div>
At the end of my base.html i have (right before closing the body):
<script src="/site_media/js/jquery.script.js"></script>
<script src="/site_media/js/bootstrap-datepicker.js"></script>
Finally on me jquery.script.js i have:
$(document).ready(function(){ $('.datepicker').datepicker()});
You have selected all elements who have the class "datepicker", while your input element definition does not have such a class but rather has datepicker as id attribute set.
Either select the id field $("#datepicker") or add a class ".datepicker" to your input field.
Do this: $(document).ready(function(){ $('#datepicker').datepicker()});
As you have set id="datepicker"
'.' is used for class and '#' is used for id