I have added a button to TinyMCE using the following JS code:
(function() {
tinymce.PluginManager.add('button_span', function( editor, url ) {
editor.addButton('button_span', {
text: 'Test Button',
icon: false,
onclick : function() {
editor.selection.setContent('<em>' + editor.selection.getContent() + '</em>');
}
});
});
})();
So, when user clicks the button, it wraps any highlighted words into <em> tags.
My question is, how do I make it so that if the highlighted words are already in <em> tag, then it should remove the tag. I am guessing we need to adjust the onclick function.
Maybe give this a shot. I'm not very familiar with tinyMCE but this should work in general. Also, you'll want to expand this to check to see if there is also an '', and the replaces will vary based on that, this is just to get you started, but like I said, should be the basis of what your trying to do I think.
onclick : function() {
var contents = editor.selection.getContent();
if (contents.indexOf('<em>') >= 0) {
contents.replace('<em>', '');
contents.replace('</em>', '');
editor.selection.setContent(contents);
} else {
editor.selection.setContent('<em>' + editor.selection.getContent() + '</em>');
}
}
Related
I am trying to build a customized version of the commenting plugin available for tinyMCE.
I am using the Annotations API to achieve this. Below is the code snippet currently being used to create a comment on some text selected by the user.
editor.ui.registry.addButton('annotate-alpha', {
text: 'Annotate',
onAction: function () {
var comment = prompt('Comment with?');
editor.annotator.annotate('alpha', {
uid: `comment${commentId}`,
comment: comment
});
if (comment == null || comment == '') {
editor.annotator.remove('alpha');
}
editor.focus();
commentId++;
},
onSetup: function (btnApi) {
editor.annotator.annotationChanged('alpha', function (state, name, obj) {
if (state == true) {
commentsHandler('true');
} else {
commentsHandler('false');
}
btnApi.setDisabled(state);
});
}
});
editor.on('init', function () {
editor.annotator.register('alpha', {
persistent: true,
decorate: function (uid, data) {
return {
attributes: {
'data-mce-comment': data.comment ? data.comment : '',
'data-mce-author': data.author ? data.author : 'anonymous',
}
};
}
});
});
this annotates the selected text correctly.
For example, in the below text if the user highlighted the text "features" and added a comment, the annotation is added and this is what the HTML looks like:
<p>Please try out the <span class="mce-annotation" data-mce-annotation-uid="comment0" data-mce-annotation="alpha" data-mce-comment="Comment 1" data-mce-author="anonymous" data-mce-selected="inline-boundary">features</span> provided in this full featured example.</p>
Screenshot
Now suppose the user tries to highlight the entire sentence and adds a comment, the text "features" moves to the front of the sentence.
Screenshot
The updated HTML looks like:
<p><span class="mce-annotation" data-mce-annotation-uid="comment0" data-mce-annotation="alpha" data-mce-comment="Comment 1" data-mce-author="anonymous" data-mce-selected="inline-boundary">features</span><span class="mce-annotation" data-mce-annotation-uid="comment1" data-mce-annotation="alpha" data-mce-comment="Comment 2" data-mce-author="anonymous">Please try out the provided in this full featured example</span></p>
I believe the existing <span> tag from the 1st comment is causing problems. A workaround can be that I check if the selected text has a previous annotation(span tag) and remove it before adding the new annotation but tinyMCE is loaded within an iframe and I can't access the HTML for manipulation.
How can I overcome this?
I have been trying to get the tag of a deleted chip from the div in the Materialize chips class, but nothing is working.
Here is what I have already tried.
$('.chips').on('chip.delete', function(e, chip){
console.log(chip);
console.log(e);
console.log(chip.tag);
});
None of the above is working.
With just only console.log(chip), I get undefined error in JavaScript console, but the function is firing when I delete the chip. I am just not able to get the value of tag of deleted chip. I want to store the tag in a variable.
I am creating chips dynamically on Materialize date select:
$('#pm_date').change(function () {
var chipvalue = $(this).val();
if (chipvalue !== "") {
// checking if tag already exits
if ($("#date_chip_select:contains(" + chipvalue + ")").length > 0) {
alert('Date already selected');
} else {
var appendstring = "<div class='chip' id='date_chip_child_" + chip_id + "'>" + chipvalue + "<i class='material-icons close'>close</i></div>";
}
}
});
Here is the fiddle: https://jsfiddle.net/hq22mne4/1/
chips.js, which is part of materialize, doesn't seem to expose any methods for adding or removing chips programmatically. It seems to exclusively listen for an enter keydown event and then internally add the chip.
So, I stitched together a workaround that does just that. I set potential chip's value within your onchange event:
$("#datechips").find('input').val($(this).val());
And create the chip when date picker is closed:
$('.datepicker').pickadate({
selectMonths: true,
selectYears: 15,
onClose: function() {
// add chip via filling the input and simulating enter
$("#datechips").find('input').trigger({ type : 'keydown', which : 13 });
},
});
It may not be ideal, but you should be able to tailor this going forward.
https://jsfiddle.net/j3ej8240/
I've also had a lot of trouble working this out. This is how I capture the add and delete chip events without using jQuery:
function chipDeleted(e, data) {
console.log("Chip was deleted with text: " + data.childNodes[0].textContent);
}
function chipAdded(e, data) {
console.log("Chip was added with text: " + data.childNodes[0].textContent);
}
//
document.addEventListener("DOMContentLoaded", function (e) {
console.log("DOM fully loaded and parsed");
var firstTag = "Initial Tag";
var elems = document.querySelectorAll('.chips');
var instances = M.Chips.init(elems, {
data:[{
tag: firstTag
}],
autocompleteOptions: {
limit: Infinity,
minLength: 1
},
placeholder: "No search...",
onChipDelete: function (e, data) { chipDeleted(e, data) },
onChipAdd: function (e, data) { chipAdded(e, data) }
});
});
And my HTML part is like this:
<body>
<div class="chips search-history"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
</body>
I'm using the jQuery Select2 (v4) plugin for a tag selector.
I want to listen for when a new tag is created in the select element and fire an ajax request to store the new tag. I discovered there is the createTag event but this seems to fire every time a letter is entered into the select2 element. As shown in my fiddle: http://jsfiddle.net/3qkgagwk/1/
Is there a similar event that only fires when the new tag has finished being entered? I.e. it's enclosed by a grey box enclosing it.
I can't find any native method unfortunately. But if you're interested in simple "workarounds", maybe this get you closer:
$('.select2').select2({
tags: true,
tokenSeparators: [",", " "],
createTag: function (tag) {
return {
id: tag.term,
text: tag.term,
// add indicator:
isNew : true
};
}
}).on("select2:select", function(e) {
if(e.params.data.isNew){
// append the new option element prenamently:
$(this).find('[value="'+e.params.data.id+'"]').replaceWith('<option selected value="'+e.params.data.id+'">'+e.params.data.text+'</option>');
// store the new tag:
$.ajax({
// ...
});
}
});
DEMO
[EDIT]
(Small update: see #Alex comment below)
The above will work only if the tag is added with mouse. For tags added by hitting space or comma, use change event.
Then you can filter option with data-select2-tag="true" attribute (new added tag):
$('.select2').select2({
tags: true,
tokenSeparators: [",", " "]
}).on("change", function(e) {
var isNew = $(this).find('[data-select2-tag="true"]');
if(isNew.length && $.inArray(isNew.val(), $(this).val()) !== -1){
isNew.replaceWith('<option selected value="'+isNew.val()+'">'+isNew.val()+'</option>');
$.ajax({
// ... store tag ...
});
}
});
DEMO 2
The only event listener that worked for me when creating a new tag was:
.on("select2:close", function() {
(my code)
})
This was triggered for new tags and selecting from the list. change, select2:select, select2:selecting and any others did not work.
One more simple check will be this based on the difference in the args of the event .....
While I was dealing with this situation, I had seen this difference; that when the new element is created the event args data does not have an element object but it exists when selecting an already available option...
.on('select2:selecting', function (e) {
if (typeof e.params.args.data.element == 'undefined') {
// do a further check if the item created id is not empty..
if( e.params.args.data.id != "" ){
// code to be executed after new tag creation
}
}
})
Another workaround. Just insert it to the beginning:
}).on('select2:selecting', function (evt) {
var stringOriginal = (function (value) {
// creation of new tag
if (!_.isString(value)) {
return value.html();
}
// picking existing
return value;
})(evt.params.args.data.text);
........
It relies on underscore.js for checking if it's string or not. You can replace _.isString method with whatever you like.
It uses the fact that when new term is created it's always an object.
I have a problem with this piece of code:
$(document).ready(function() {
$('.notActiveId').change(function() {
if ($(this).attr('value').length === 0 ) {
$("#notActiveButton").html('');
} else {
$("#notActiveButton").html('<a href="javascript:void(0)" onClick="setStatus(' + $(this).attr('value') + ', activate)" class="operationUnlock" >Activate</a>');
}
});
});
I'm calling with $(this).attr('value') a value from a select list named notActiveId. But the problem is how to write $(this).attr('value') in setStatus() function, because value of my select is in this form: RZT_83848Rer (so it consists of characters, underline and numbers).
If I try to write it as above, then I get a JavaScript error.
Instead of using an old-school "onclick", why not add your element via jQuery?
$('#notActiveButton').empty().append($('<a/>', {
href: '#', // the "javascript:" thing is basically bogus and unnecessary
click: function () {
setStatus(this.value, activate);
},
class: 'operationUnlock',
text: 'Activate'
}));
Now, all this assumes that your "notActiveButton" element is some sort of legitimate container for your <a> tag. But anyway, doing it this way you get to write plain JavaScript without having to worry about the mess of quoting etc.
Adding a validator to my form:
jQuery.validator.addMethod('whatever', function(val, el) {
// whatever goes here
}, 'A maximum of ' + $('#my_id_here').val() + ' categories can be selected.');
This doesn't fly. I always get undefined. Is this a good, simple way to do this?
Thanks
Something like this:
$(document).ready(function()
{
jQuery.validator.addMethod("validateCountries", function(value, element) {
alert('s');
return this.optional(element) || /^\d{3}-\d{3}-\d{4}$/.test(value);
});
// add the validation rule
$("#form1").validate();
$("#lbCountries").rules("add", { validateCountries:true });
});
Inside the Add method you can perform your validation!
UPDATE 1:
With dynamic text you will loose the error messages displayed. Here is a way to tackle that issue:
// add the validation rule
$("#form1").validate(
{
messages: { lbCountries: "please specify the countries" }
}
);
The lbCountries is a ListBox control.
UPDATE 2:
You can attach another rule attribute with the rule as shown below:
$("#lbCountries").rules("add", { validateCountries:true, noOfSelectedItems:3 });
Now, you can check for the rule when the event is fired:
$("#lbCountries").rules().noOfSelectedItems; // this will return 3