Summernote: set focus after initialization - javascript

Summernote gives you the option of giving focus to the editor when you create it, passing this options:
$('#summernote').summernote({
focus: true
});
But after initialization, it seems you can't give focus to the textarea by clicking a button or similar. I've tried several ways, without success.
Anyone did that?

$('.summernote').summernote('focus')
ps. i want to find an angular way out .. and it works

After coming back to this problem and trying a lot of solutions, I came to one that works:
$('.note-editable').trigger('focus');
Triggering the event through jQuery works, but using the focus() function doesn't.

$(document).ready(function () {
$.fn.extend({
placeCursorAtEnd: function () {
// Places the cursor at the end of a contenteditable container (should also work for textarea / input)
if (this.length === 0) {
throw new Error("Cannot manipulate an element if there is no element!");
}
var el = this[0];
var range = document.createRange();
var sel = window.getSelection();
var childLength = el.childNodes.length;
if (childLength > 0) {
var lastNode = el.childNodes[childLength - 1];
var lastNodeChildren = lastNode.childNodes.length;
range.setStart(lastNode, lastNodeChildren);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
return this;
}
});
});
then:
$('.note-editable').click(function(){
//$('#summernote').summernote('focus');
$(this).placeCursorAtEnd();
});
①focus on click or tap
②focus at the end of content
it works on mobile device too

please refer codepen
for this problem
/* Summernote Validation */
$(function () {
var summernoteForm = $('.form-validate-summernote');
var summernoteElement = $('.summernote');
var summernoteValidator = summernoteForm.validate({
errorElement: "div",
errorClass: 'is-invalid',
validClass: 'is-valid',
ignore: ':hidden:not(.summernote),.note-editable.card-block',
errorPlacement: function (error, element) {
// Add the `help-block` class to the error element
error.addClass("invalid-feedback");
console.log(element);
if (element.prop("type") === "checkbox") {
error.insertAfter(element.siblings("label"));
} else if (element.hasClass("summernote")) {
error.insertAfter(element.siblings(".note-editor"));
} else {
error.insertAfter(element);
}
}
});
summernoteElement.summernote({
height: 300,
callbacks: {
onChange: function (contents, $editable) {
// Note that at this point, the value of the `textarea` is not the same as the one
// you entered into the summernote editor, so you have to set it yourself to make
// the validation consistent and in sync with the value.
summernoteElement.val(summernoteElement.summernote('isEmpty') ? "" : contents);
// You should re-validate your element after change, because the plugin will have
// no way to know that the value of your `textarea` has been changed if the change
// was done programmatically.
summernoteValidator.element(summernoteElement);
}
}
});
});

This works for Summernote v0.8.18:
$(`div.note-editing-area div.note-editable`).focus();

You can set the focus by putting the focus on the editable div used by Summernote:
document.querySelectorAll(".note-editable").focus();
or using JQuery
$('#summernote').find('.note-editable').focus();

<div class="col-lg-12 col-md-6 col-xs-12">
<div class="form-group">
<label> Skills</label>
<span ng-messages="EditForm.Skills.$error" ng-if="EditForm.Skills.$dirty || isEditFormSubmitted ">
<span class="text-danger" ng-message="required" ng-bind="error msg"></span>
</span>
<text-angular id="Skills" name="Skills" ng-model="EditVacancyModel.Skills" ta-toolbar="[['bold','underline','italics','ul','ol']]"ng-required="true"></text-angular>
</div>
</div>

Related

How to trigger an event when there is selection inside a contentEditable div?

I want to trigger an event when the user selects some text/element in a contentEditable div. Accordingly I want to inactivate certain buttons in a Rich Text Editor.
There are some events which can be triggered based upon change of content. I only want an event when the user selects some content.
A relatively simplified version could look like this, depending on your needs you might need to handle browsers like old IE's etc. that do not support window.getSelection()!
const handleSelection = function() {
const btn = document.querySelector('#btn');
let selection = window.getSelection().anchorNode.textContent
.substring(
window.getSelection().extentOffset,
window.getSelection().anchorOffset
);
if (selection.length !== 0) {
btn.setAttribute('disabled', true);
} else {
btn.removeAttribute('disabled');
}
};
['mouseup', 'keyup', 'selectionchange'].forEach((e) => {
document.querySelector('#editable').addEventListener(e, handleSelection);
});
#btn[disabled] {
cursor: default;
opacity: 0.3;
}
<button type="button" id="btn">Button (disabled when something is selected)</button>
<div id="editable" contenteditable>
<p>I'm some content that is editable!</p>
</div>
You can add event listener to the element for mouseup event and get the selection from window after that:
<div contenteditable="true" id="editableDiv">Some content</div>
And the js:
document.getElementById("editableDiv").addEventListener("mouseup", function() {
var s = window.getSelection();
if(s == "something"){
//do your thing
}
}, false);

How to close div when div loses focus?

I made a simple plunkr here http://plnkr.co/edit/zNb65ErYH5HXgAQPOSM0?p=preview
I created a little datepicker I would like this to close itself when you focus out of it (focusout of datepicker) if I put blur on input I'm unable to use the datepicker, if I put focusout event on datepicker it doesn't works
I also tried:
angular.element(theCalendar).bind('blur', function () {
$scope.hideCalendar();
});
but it doesn't work.
Any clue?
this is because you are removing the item before you get a chance to do anything, here is a working example:
http://plnkr.co/edit/mDfV9NLAQCP4l7wHdlfi?p=preview
just add a timeout:
thisInput.bind('blur', function () {
$timeout(function(){
$scope.hideCalendar();
}, 200);
});
have you considered using existing datepickers? like angularUI or angular-strap: http://mgcrea.github.io/angular-strap/##datepickers
Update:
Not a complete solution, but should get you quite closer:
angular.element($document[0].body).bind('click', function(e){
console.log(angular.element(e.target), e.target.nodeName)
var classNamed = angular.element(e.target).attr('class');
var inThing = (classNamed.indexOf('datepicker-calendar') > -1);
if (inThing || e.target.nodeName === "INPUT") {
console.log('in');
} else {
console.log('out');
$timeout(function(){
$scope.hideCalendar();
}, 200);
}
});
http://plnkr.co/edit/EbQl5xsCnG837rAEhBZh?p=preview
What you want to do then is to listen for a click on the page, and if the click is outside of the calendar, then close it, otherwise do nothing. The above only takes into account that you are clicking on something that has a class name which includes datepicker-calendar, you will need to adjust it so that clicking within the calendar doesn't close it as well.
How about closing on mouseout?
You need to cancel the close if you move to another div in the calendar though:
//get the calendar as element
theCalendar = element[0].children[1];
// hide the calendar on mouseout
var closeCalendarTimeout = null;
angular.element(theCalendar).bind('mouseout', function () {
if ( closeCalendarTimeout !== null )
$timeout.cancel(closeCalendarTimeout);
closeCalendarTimeout = $timeout(function () {
$scope.hideCalendar();
},250)
});
angular.element(theCalendar).bind('mouseover', function () {
if ( closeCalendarTimeout === null ) return
$timeout.cancel(closeCalendarTimeout);
closeCalendarTimeout = null;
});
EDIT
Adding a tabindex attribute to a div causes it to fire focus and blur events.
, htmlTemplate = '<div class="datepicker-calendar" tabindex="0">' +
angular.element(theCalendar).bind('blur', function () {
$scope.hideCalendar();
});
So, i know it probably is not the best practice or the best way to do this, but at the end i fixed and got what i need using this:
thisInput.bind('focus click', function bindingFunction() {
isMouseOnInput = true;
$scope.showCalendar();
angular.element(theCalendar).triggerHandler('focus');
});
thisInput.bind('blur focusout', function bindingFunction() {
isMouseOnInput = false;
});
angular.element(theCalendar).bind('mouseenter', function () {
isMouseOn = true;
});
angular.element(theCalendar).bind('mouseleave', function () {
isMouseOn = false;
});
angular.element($window).bind('click', function () {
if (!isMouseOn && !isMouseOnInput) {
$scope.hideCalendar();
}
});
I setted up some boolean vars to check where mouse is when you click the page and it works like a charm if you have some better solution that works , please let me know, but this actually fixed all.
I accept this as the answer but i thank all the guys on this page!

removing an appended element using javascript/closure?

I currently have a click event in place that when selected appends a search box to .header, this is done using google closure. My problem now is if I click a close button I want to remove this appended element. I know using jQuery requires only .remove() but Im unsure how to achieve this in closure or vanilla js. Can anyone advise how I can do this?
Current code:
if(goog.dom.getElementsByClass('pe')){
var searchCtn = goog.dom.getElementsByClass('search');
var headerWrapper = goog.dom.getElementByClass('header');
goog.dom.append(headerWrapper,searchCtn);
}
var closeButton = goog.dom.getElement('close');
goog.events.listen(closeButton, goog.events.EventType.CLICK, function() {
console.log('Remove appended');
}, false, this);
The function is this:
goog.dom.removeNode = function(node) {
return node && node.parentNode ? node.parentNode.removeChild(node) : null;
};
So the code is like below(assume the search box is the parent of the close button):
goog.events.listen(closeButton, goog.events.EventType.CLICK, function() {
goog.dom.removeNode(this.parentNode);
}, false, this);
Just use element.removeChild(y)
$(function() {
$('span').click(function() {
this.parentNode.removeChild(this);
});
});
That's jquery, but very easy to translate over to plain old javascript, or whatever framework you are in.

jquery validator checkbox "element is undefined"

I'm trying to use the jQuery Validation plugin to make a multistep form with tabs, but I keep getting an "element is undefined" error when I attempt to loop through all the inputs. Any suggestions? I don't understand what's wrong. I've tried placing the checkbox in multiple places, and it seems to happen everywhere (i.e. not just at the 2nd last tab).
var tabs = $("#tabs").tabs({
disabled: [1,2,3,4,5],
select: function(event, ui) {
var valid = true;
var current = $(this).tabs("option", "selected");
var panelId = $("#tabs ul a").eq(current).attr("href");
$(panelId).find("input").each(function(index, element) {
if (!validator.element(this) && valid) {
if(ui.index > current) {
valid = false;
}
else
{
//re-disable the next tab
}
}
});
return valid;
}
});
$(".nexttab").click(function() {
var selected = $("#tabs").tabs("option", "selected");
$("#tabs").tabs("enable", selected+1);
$("#tabs").tabs("option", "selected", selected + 1);
});
HTML Part:
<div id="general">
</div>
<div id="problemtab">
<p>
<input type="checkbox" name"response" id="response" value="agree" class="required"><label for="response">I Agree</label>
</p>
<p>
<a class="prevtab navbutton"><span>Prev</span></a>
<a class="nexttab navbutton"><span>Next</span></a>
</p
</div>
<div id="lasttab">
</div>
Thanks for any help!
Edit:
It's giving me an error in jquery-validate.js:787
staticRules: function(element) {
var rules = {};
var validator = $.data(element.form, 'validator'); // <---- Error here
if (validator.settings.rules) {
rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
}
return rules;
},
Edit#2: element/this is defined as [object HTMLInputElement]
Here is my validator:
var validator = $("#myForm").validate({
ignore : ['#tabs .inactive input'], // tells the validator to only validate elements on your current tab
errorElement: "div",
wrapper: "div", // a wrapper around the error message
errorPlacement: function(error, element) {
if (element.parent().hasClass('group')){
element = element.parent();
}
offset = element.position();
error.insertBefore(element)
error.addClass('message'); // add a class to the wrapper
error.css('position', 'absolute');
error.css('left', offset.left + element.outerWidth());
error.css('top', offset.top);
}
});
You forgot an equal sign for the name attribute of your checkbox, so the name attribute is not set.
name"response" should be name="response"
I noticed yesterday that jquery.validate needs a name on elements to work, or it will throw this error.
Make sure you have just one form in your page. I used to have two forms in the same page and that was causing the problem you mention.
This error also might be related to this issue of JQuery with hidden chekcboxes (or radioboxes). This issue hasn't been addressed but it could be solved by setting (temporarily) validatorInstance.settings.ignore =''.
I faced that issue with checkboxes & hidden inputs on the form in MVC 5 Jquery 3.3.1, nothing worked so I had to disable the default validation and do some custom validation.
<button type="submit" id="btnSubmit" formnovalidate="formnovalidate" class="btn">Submit</button>
It started coming when I added
$.validator.methods.date = function (value, element) { .....

Detect which form input has focus using JavaScript or jQuery

How do you detect which form input has focus using JavaScript or jQuery?
From within a function I want to be able to determine which form input has focus. I'd like to be able to do this in straight JavaScript and/or jQuery.
document.activeElement, it's been supported in IE for a long time and the latest versions of FF and chrome support it also. If nothing has focus, it returns the document.body object.
I am not sure if this is the most efficient way, but you could try:
var selectedInput = null;
$(function() {
$('input, textarea, select').focus(function() {
selectedInput = this;
}).blur(function(){
selectedInput = null;
});
});
If all you want to do is change the CSS for a particular form field when it gets focus, you could use the CSS ":focus" selector. For compatibility with IE6 which doesn't support this, you could use the IE7 library.
Otherwise, you could use the onfocus and onblur events.
something like:
<input type="text" onfocus="txtfocus=1" onblur="txtfocus=0" />
and then have something like this in your javascript
if (txtfocus==1)
{
//Whatever code you want to run
}
if (txtfocus==0)
{
//Something else here
}
But that would just be my way of doing it, and it might not be extremely practical if you have, say 10 inputs :)
I would do it this way: I used a function that would return a 1 if the ID of the element it was sent was one that would trigger my event, and all others would return a 0, and the "if" statement would then just fall-through and not do anything:
function getSender(field) {
switch (field.id) {
case "someID":
case "someOtherID":
return 1;
break;
default:
return 0;
}
}
function doSomething(elem) {
if (getSender(elem) == 1) {
// do your stuff
}
/* else {
// do something else
} */
}
HTML Markup:
<input id="someID" onfocus="doSomething(this)" />
<input id="someOtherID" onfocus="doSomething(this)" />
<input id="someOtherGodForsakenID" onfocus="doSomething(this)" />
The first two will do the event in doSomething, the last one won't (or will do the else clause if uncommented).
-Tom
Here's a solution for text/password/textarea (not sure if I forgot others that can get focus, but they could be easily added by modifying the if clauses... an improvement could be made on the design by putting the if's body in it's own function to determine suitable inputs that can get focus).
Assuming that you can rely on the user sporting a browser that is not pre-historic (http://www.caniuse.com/#feat=dataset):
<script>
//The selector to get the text/password/textarea input that has focus is: jQuery('[data-selected=true]')
jQuery(document).ready(function() {
jQuery('body').bind({'focusin': function(Event){
var Target = jQuery(Event.target);
if(Target.is(':text')||Target.is(':password')||Target.is('textarea'))
{
Target.attr('data-selected', 'true');
}
}, 'focusout': function(Event){
var Target = jQuery(Event.target);
if(Target.is(':text')||Target.is(':password')||Target.is('textarea'))
{
Target.attr('data-selected', 'false');
}
}});
});
</script>
For pre-historic browsers, you can use the uglier:
<script>
//The selector to get the text/password/textarea input that has focus is: jQuery('[name='+jQuery('body').data('Selected_input')+']')
jQuery(document).ready(function() {
jQuery('body').bind({'focusin': function(Event){
var Target = jQuery(Event.target);
if(Target.is(':text')||Target.is(':password')||target.is('textarea'))
{
jQuery('body').data('Selected_input', Target.attr('name'));
}
}, 'focusout': function(Event){
var Target = jQuery(Event.target);
if(Target.is(':text')||Target.is(':password')||target.is('textarea'))
{
jQuery('body').data('Selected_input', null);
}
}});
});
</script>
You only need one listener if you use event bubbling (and bind it to the document); one per form is reasonable, though:
var selectedInput = null;
$(function() {
$('form').on('focus', 'input, textarea, select', function() {
selectedInput = this;
}).on('blur', 'input, textarea, select', function() {
selectedInput = null;
});
});
(Maybe you should move the selectedInput variable to the form.)
You can use this
<input type="text" onfocus="myFunction()">
It triggers the function when the input is focused.
Try
window.getSelection().getRangeAt(0).startContainer

Categories