I am using codemirror 2 and its working fine except that the editor's set value doesn't load into the editor until I click the editor and it becomes focused.
I want the editor to show the content of itself without it having to be clicked. Any ideas?
All of the codemirror demos work as expected so I figured maybe the textarea isn't focused so I tried that too.
$("#editor").focus();
var editor = CodeMirror.fromTextArea(document.getElementById("editor"), {
mode: "text/html",
height: "197px",
lineNumbers: true
});
You must call refresh() after setValue(). However, you must use setTimeout to postpone the refresh() to after CodeMirror/Browser has updated the layout according to the new content:
codeMirrorRef.setValue(content);
setTimeout(function() {
codeMirrorRef.refresh();
},1);
It works well for me. I found the answer in here.
Just in case, and for everyone who doesn't read the documentation carefully enough (like me), but stumbles upon this.
There's an autorefresh addon just for that.
You need to add autorefresh.js in your file.
Now you can use it like this.
var editor = CodeMirror.fromTextArea(document.getElementById("id_commentsHint"), {
mode: "javascript",
autoRefresh:true,
lineNumbers: false,
lineWrapping: true,
});
works like a charm.
I expect you (or some script you loaded) is meddling with the DOM in such a way that the editor is hidden or otherwise in a strange position when created. It'll require a call to its refresh() method after it is made visible.
I happen to be using CodeMirror within a bootstrap tab. I suspected the bootstrap tabs were what was preventing it from showing up until clicked. I fixed this by simply calling the refresh() method on show.
var cmInstance = CodeMirror.fromTextArea(document.getElementById('cm'), {
lineNumbers: true,
lineWrapping: true,
indentUnit: 4,
mode: 'css'
});
// to fix code mirror not showing up until clicked
$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function() {
this.refresh();
}.bind(cmInstance));
Something worked for me.
$(document).ready(function(){
var editor = CodeMirror.fromTextArea(document.getElementById("code2"), {
//lineNumbers: true,
readOnly: true,
autofocus: true,
matchBrackets: true,
styleActiveLine: true
});
setTimeout(function() {
editor.refresh();
}, 100);
});
The 5.14.2 version of codemirror addresses this fully with an add on. See this answer for details.
I am working with react, and all these answers did not work with me...After reading the documentation it worked like this:
in the constructor, I initialized an instance of code Mirror:
this.mirrorInstance = null;
and on opening the tab that contains the codeEditor, I refreshed the instance after 1 millisecocnd:
toggleSubTab() {
setTimeout(() => {
this.mirrorInstance.refresh();
}, 1);
}
and here is the JSX code:
<CodeMirror
value={this.state.codeEditor}
options={{
mode: "htmlmixed",
theme: "default",
lineNumbers: true,
lineWrapping: true,
autoRefresh: true
}}
editorDidMount={editor => {
this.mirrorInstance = editor;
}}
/>
I just ran into a version of this problem myself this evening.
A number of other posts regard the visibility of the textarea parent as being important, if it's hidden then you can run into this problem.
In my situation the form itself and immediate surroundings were fine but my Backbone view manager higher up the rendering chain was the problem.
My view element isn't placed on the DOM until the view has rendered itself fully, so I guess an element not on the DOM is considered hidden or just not handled.
To get around it I added a post-render phase (pseudocode):
view.render();
$('body').html(view.el);
view.postRender();
In postRender the view can do what it needs knowing that all the content is now visible on the screen, this is where I moved the CodeMirror and it worked fine.
This might also go some of the way to explain also why one may run into problems with things like popups as in some cases they may try to build all content before displaying.
Hope that helps someone.
Toby
Yet another solution (which I also realised was because the editor needed to be visible to create properly) is to temporarily attach the parent element to the body element during construction, then reattach once complete.
This way, you don't need to meddle with elements, or worry about visibility in any existing hierarchies that your editor might be buried.
In my case, for processr.com, I have multiple, nested code editing elements, all of which need to be created on the fly as the user makes updates, so I do the following:
this.$elements.appendTo('body');
for (var i = 0; i < data.length; i++)
{
this.addElement(data[i]);
}
this.$elements.appendTo(this.$view);
It works great, and there's been no visible flicker or anything like that so far.
Try calling focus on the DOM element instead of the jQuery object.
var editor=$( '#editor' );
editor[0].focus();
// or
document.getElementById( 'editor' ).focus();
<div class="tabbable-line">
<ul class="nav nav-tabs">
<li class="active">
Xml 1
</li>
<li class="">
Xml 2
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tabXml1">
<textarea id="txtXml1" />
</div>
<div class="tab-pane" id="tabXml2">
<textarea id="txtXml2" />
</div>
</div>
</div>
<link rel="stylesheet" href="~/Content/codemirror.min.css">
<style type="text/css">
.CodeMirror {
border: 1px solid #eee;
max-width: 100%;
height: 400px;
}
</style>
<script src="~/Scripts/codemirror.min.js"></script>
<script src="~/Scripts/codemirror.xml.min.js"></script>
<script>
$(document).ready(function () {
var cmXml1;
var cmXml2;
cmXml1 = CodeMirror.fromTextArea(document.getElementById("txtXml1"), {
mode: "xml",
lineNumbers: true
});
cmXml2 = CodeMirror.fromTextArea(document.getElementById("txtXml2"), {
mode: "xml",
lineNumbers: true
});
// Refresh code mirror element when tab header is clicked.
$("#xmlTab2Header").click(function () {
setTimeout(function () {
cmXml2.refresh();
}, 10);
});
});
</script>
Something worked for me! :)
var sh = setInterval(function() {
agentConfigEditor.refresh();
}, 500);
setTimeout(function(){
clearInterval(sh);
},2000)
using refresh help solve this problem. But it seems not friendly
The reason:
CodeMirror won't update DOM content when it's DOM Node is unvisible.
For example:
when the CodeMirror's Dom is setted style to 'display: none'.
The way to fix:
when CodeMirror's Dom is visible, manual excute the cm.refresh() method.
For example in my application, the CodeMirror Dom will visible when the tab element clicked.
So the simple method is:
window.onclick = () => {
setTimeout(() => {
codeMirrorRef.refresh();
}, 10);
};
You can add event listener on more specific element to improve the performance.
chain this to the master codemirror object, make sure that nothing else is chained
.on('change', editor => {
globalContent = editor.getValue();
});;
Related
I have an HTML page with a hidden DIV (a modal popup), which is shown through a button. This popup contains multiple TinyMCE editors, referred by a class.
My old problem was that the editors were "disabled" (I couldn't click and write within) when popup would open up. I solved thanks to other Stack Overflow's threads by calling init() method when popup is opening.
modal.onOpen = function() {
editor.init({
selector: '.editor',
menubar: false
});
};
That solved my problem, but only the first time the popup opens! Second time the problem is the same (editor "freezed").
So i tried to add a switch, to have the init() called only the first time
var isInit = false;
modal.onOpen = function() {
if (!isInit) {
editor.init({
selector: '.editor',
menubar: false
});
isInit = true;
}
}
but nothing changed..
Any help?
Thank you
Solved removing editors every time the popup is closed. Even though I don't like such solution so much, and I don't understand why the problem arises either. More hints are welcome
modal.onClose = function() {
editor.remove(); /* destroy all editors istances */
};
Needed to use <br> tag in the summernote editor instead of <p> while user clicks on the Enter button, so here is my code:
var $this = $(this),
box = $('textarea.CommentsFields');
box.summernote({
height: 100,
focus: true,
toolbar: [
[ 'all', [ 'bold', 'strikethrough', 'ul', 'ol', 'link' ] ],
[ 'sided', [ 'fullscreen' ] ]
],
callbacks: {
onEnter: function(){
box.summernote('insertNode', document.createTextNode("<br>"));
console.log('uiwdbvuwecbweuiuinsjk');
}
}
});
I wrote a custom callback of the onEnter event, when the user hit the return button it raises a callback, and write the <br> tag which is not what I am looking for.
I read their documentation but can not understand how to stop the default action of the enter button and write <br> tag instead of wrapping the element in <p> tag.
Any idea? Thanks
This code worked for me:
$("#summernote").on("summernote.enter", function(we, e) {
$(this).summernote("pasteHTML", "<br><br>");
e.preventDefault();
});
This interceps the Enter press event and changes its default behaviour, inserting a <br> instead of a new paragraph.
If you don't want to change or fix the summernote library itself, you can use the shortcut keys for adding a line break.
Use Shift + Enter for giving a line break.
Use Enter for changing a paragraph, as summernote add a div/p to start a new line when you press Enter.
Hope this works.
There appear to be at least 10 or so bugs filed about this over at SummerNote, with no fix or plan to fix it unfortunately.
Fortunately you can fix it in a sneaky way, that is going to be pretty brittle to future versions - so upgrade carefully. You Monkey Patch it:
$.summernote.dom.emptyPara = "<div><br/></div>";
box.summernote(options);
The first line is the fix - the Monkey Patch. I included the second line, where SummerNote is initialized, just to demonstrate you MUST do your Monkey Patch before you start SummerNote - or the Monkey Patch will not make it in and you'll still get p tags on enter.
Guaranteed 2 liner & no plugin:
$.summernote.dom.emptyPara = "<div><br></div>"; // js
.note-editor .note-status-output{display:none;} /*css*/
Today summernote has no way to do what you want. You can check https://github.com/summernote/summernote/issues/702, so, the only way is to create your own pull-request with fixed logic for different paragraph style.
This worked for me
Replace (in Summernote.js line 3786)
if (event.keyCode === key.code.ENTER) {
context.triggerEvent('enter', event);
}
in
if (event.keyCode === key.code.ENTER) {
return;
}
I encountered this problem and the solution is below.
onKeydown function in callbacks solves your problems.
Example:
$('.textarea-editor').summernote({
height: 250, // set editor height
minHeight: null, // set minimum height of editor
maxHeight: null, // set maximum height of editor
focus: true, // set focus to editable area after initializing summernote
htmlMode: true,
lineNumbers: true,
codemirror: { // codemirror options
theme: 'monokai'
},
mode: 'text/html',
callbacks: {
onKeydown: function(e) {
e.stopPropagation();
}
}
});
So, I'm using this [Bootstrap DateTimePicker] plugin to allow the user to pick a date and time. The plugin works fine, except for one small problem, whenever the user clicks away or blurs the calendar box, the box itself and the input element disappear!
I have looked in the css and js files to find something that might lead me in the right path (focus, blur, etc), but I have not had any luck.
I would appreciate it if someone could point me in the right direction. Thank you!
This is the HTML creating the element:
<div id="eventstartdate" class="input-append date"><input type="text" data-format="dd/MM/yyyy hh:mm:ss" /><span class="add-on">
<i data-time-icon="icon-time" data-date-icon="icon-calendar"></i></span></div>
<script>
$(document).ready(function () {
$('#eventstartdate').datetimepicker({
language: 'en',
pick12HourFormat: true,
format: 'dd/MM/yyyy hh:mm:ss',
maskInput: true
});
});
</script>
I could not find the correct manner to do this, so for the moment being all I did was unbind the hiding of the div like this:
$('#eventstartdate').on('hide', function (e) { e.preventDefault(); });
This works until I find a better solution :/
Same thing happened to me and at last it turns out that , prototype.js was the culprit . The reason is that prototype has these methods called hide and show, that it attaches to every dom element and when bootstrap triggers methods with same name on its components(like dialog,dropdowns etc..), respective method of prototype acts on the dom element itself causing it to hide . As a workaround you can use below code after loading prototype.
if (Prototype.BrowserFeatures.ElementExtensions) {
var disablePrototypeJS = function (method, pluginsToDisable) {
var handler = function (event) {
event.target[method] = undefined;
setTimeout(function () {
delete event.target[method];
}, 0);
};
pluginsToDisable.each(function (plugin) {
jQuery(window).on(method + '.bs.' + plugin, handler);
});
},
pluginsToDisable = ['collapse', 'dropdown', 'modal', 'tooltip', 'popover', 'tab','datepicker'];
disablePrototypeJS('show', pluginsToDisable);
disablePrototypeJS('hide', pluginsToDisable); }
I am using bootstrap-popover to show a message beside an element.
If I want to show different text in the popover after the first time, the text does not change. Re instantiating the popover with new text does not overwrite.
See this js fiddle for a live example:
http://jsfiddle.net/RFzvp/1/
(The message in the alert and the message in the dom is inconsistent after the first click)
The documentation is a bit light on how to unbind: http://twitter.github.com/bootstrap/javascript.html#popovers
Am I using this wrong? The Any suggestions on how to work around?
Thanks
You can access the options directly using the jquery data closure dictionary like this:
$('a#test').data('bs.popover').options.content = 'new content';
This code should work fine even after first initializing the popover.
Hiya please see working demo here: http://jsfiddle.net/4g3Py/1/
I have made the changes to get your desired outcome. :)
I reckon you already know what you are doing but some example recommendations from my end as follows for sample: http://dl.dropbox.com/u/74874/test_scripts/popover/index.html# - sharing this link to give you idea for different link with different pop-over if you will see the source notice attribute data-content but what you wanted is working by the following changes.
Have a nice one and hope this helps. D'uh don't forget to up vote and accept the answer :)
Jquery Code
var i = 0;
$('a#test').click(function() {
i += 1;
$('a#test').popover({
trigger: 'manual',
placement: 'right',
content: function() {
var message = "Count is" + i;
return message;
}
});
$('a#test').popover("show");
});
HTML
<a id="test">Click me</a>
just in-case anyone's looking for a solution that doesn't involve re-instantiating the popover and just want to change the content html, have a look at this:
$('a#test').data('popover').$tip.find(".popover-content").html("<div>some new content yo</div>")
Update: At some point between this answer being written and Bootstrap 3.2.0 (I suspect at 3.0?) this changed a little, to:
$('a#test').data('bs.popover').tip().find ............
Old question, but since I notice that the no answer provides the correct way and this is a common question, I'd like to update it.
Use the $("a#test").popover("destroy");-method. Fiddle here.
This will destroy the old popover and enable you to connect a new one again the regular way.
Here's an example where you can click a button to set a new popover on an object that already has a popover attached. See fiddle for more detail.
$("button.setNewPopoverContent").on("click", function(e) {
e.preventDefault();
$(".popoverObject").popover("destroy").popover({
title: "New title"
content: "New content"
);
});
The question is more than one year old, but maybe this would be usefull for others.
If the content is only changed while the popover is hidden, the easiest way I've found is using a function and a bit of JS code.
Specifically, my HTML looks like:
<input id="test" data-toggle="popover"
data-placement="bottom" data-trigger="focus" />
<div id="popover-content" style="display: none">
<!-- Hidden div with the popover content -->
<p>This is the popover content</p>
</div>
Please note no data-content is specified. In JS, when the popover is created, a function is used for the content:
$('test').popover({
html: true,
content: function() { return $('#popover-content').html(); }
});
And now you can change anywhere the popover-content div and the popover will be updated the next time is shown:
$('#popover-content').html("<p>New content</p>");
I guess this idea will also work using plain text instead of HTML.
On Boostrap 4 it is just one line:
$("#your-element").attr("data-content", "your new popover content")
You can always directly modify the DOM:
$('a#test').next(".popover").find(".popover-content").html("Content");
For example, if you want a popover that will load some data from an API and display that in the popover's content on hover:
$("#myPopover").popover({
trigger: 'hover'
}).on('shown.bs.popover', function () {
var popover = $(this);
var contentEl = popover.next(".popover").find(".popover-content");
// Show spinner while waiting for data to be fetched
contentEl.html("<i class='fa fa-spinner fa-pulse fa-2x fa-fw'></i>");
var myParameter = popover.data('api-parameter');
$.getJSON("http://ipinfo.io/" + myParameter)
.done(function (data) {
var result = '';
if (data.org) {
result += data.org + '<br>';
}
if (data.city) {
result += data.city + ', ';
}
if (data.region) {
result += data.region + ' ';
}
if (data.country) {
result += data.country;
}
if (result == '') {
result = "No info found.";
}
contentEl.html(result);
}).fail(function (data) {
result = "No info found.";
contentEl.html(result);
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
Hover here for details on IP 151.101.1.69
This assumes that you trust the data supplied by the API. If not, you will need to escape the data returned to mitigate XSS attacks.
Learn't from previous answers
let popOverOptions = {
trigger: 'click',
...
};
// save popOver instance
let popOver = $(`#popover-unique-id`).popover(popOverOptions);
// get its data
let popOverData = popOver.data('bs.popover');
// load data dynamically (may be with AJAX call)
$(`#popover-unique-id`).on('shown.bs.popover', () => {
setTimeout(() => {
// set content, title etc...
popOverData.config.content = 'content/////////';
// updata the popup in realtime or else this will be shown next time opens
popOverData.setContent();
// Can add this if necessary for position correction:
popOver._popper.update();
}, 2000);
});
This way we can update popover content easily.
There's another way using destroy method.
http://jsfiddle.net/bj5ryvop/5/
Bootstrap 5.0 update
let popoverInstance = new bootstrap.Popover($('#element'));
And then:
popoverInstance._config.content = "Hello world";
popoverInstance.setContent();
(Caution: it will update popover content globally, so if you have multiple open popovers then they all will be updated with "Hello world")
I found Bootstrap popover content cannot changed dynamically which introduces the setContent function. My code (hopefully helpful to someone) is therefore:
(Noting that jquery data() isn't so good at setting as it is getting)
// Update basket
current = $('#basketPopover').data('content');
newbasket = current.replace(/\d+/i,parseInt(data));
$('#basketPopover').attr('data-content',newbasket);
$('#basketPopover').setContent();
$('#basketPopover').$tip.addClass(popover.options.placement);
if jQuery > 4.1 use
$("#popoverId").popover("dispose").popover({
title: "Your new title"
content: "Your new content"
);
Bootstrap 5.1
I tried about 8 different ways to change the content for my Bootstrap 5.1 project, but none worked. I could see the values in the underlying popover object and could change them, but they didn't show on the page.
I got it going by first using the Bootstrap Popover's selector option, which the docs don't explain that well, but basically amounts to putting a watch on the page, so if new popover elements are added to the page (with the selector) they will become popovers automatically.
$(function() {
// set up all popovers
new bootstrap.Popover(document.body, {selector: 'has-popover');
})
then in my ajax call where some different content has been fetched, I remove the existing popover div, change the attribute with the text, and add it again:
var $pop = $('#pop_id1234')
var html = $pop[0].outerHTML // save the HTML
$pop.remove()
var $new = $(html).attr('data-bs-content',popoverText) // data('bs-content') becomes bsContent which won't work
$('#pop-container').append($new)
This answer has been taken from this post:
Fancybox problem on iPhone
This was voted as best answer but I am new and still learning at js and I am having such a difficult time putting this all together, can someone help me with some more detailed instructions?
Fancybox attempts to auto resize and center itself everytime that the
browser window is resized, and this event gets triggered a lot on
iPads and iPhones. For fancy box 1.3.4, the code which controls this
is line 608: $(window).bind("resize.fb", $fancybox.resize);
To fix the issue, I modified this part of the fancybox JS, and added
another option called "resizeOnWindowResize", which you can set to
false for iPad and iPhone users, or just disable all together.
if(currentOpts.resizeOnWindowResize) { $(window).bind("resize.fb",
$fancybox.resize); } You must also add a default value for this
option in $.fn.fancybox.defaults hash map.
Then, when calling fancybox you can utilize this new option:
$('#fancybox_link').fancybox(${'scrolling': 'no',
width: 'auto',
height: 'auto',
centerOnScroll: false,
resizeOnWindowResize : false});
I got as far as go to line 608. I really do not know what to do next. What should the final product look like after you've added "resizeonwindowResize" and the if statement?
Add this:
if(currentOpts.resizeOnWindowResize) {
$(window).bind("resize.fb", $.fancybox.resize);
}
Where you find:
$(window).bind("resize.fb", $.fancybox.resize);
Near the bottom of:
$.fn.fancybox.defaults = { //blah blah blah options here.
onComplete : function(){},
onCleanup : function(){},
onClosed : function(){},
onError : function(){},
// Add this
resizeOnWindowResize: true
};
Then save and when you call the fancybox:
$('.photo_gallery a').fancybox({
resizeOnWindowResize: false
});
This is also an alternative. Just replace the $.fancybox.resize function to as follows. It's just adding a simple userAgent check to avoid the .center call for iPhones.
$.fancybox.resize = function() {
if (overlay.is(':visible')) {
overlay.css('height', $(document).height());
}
if(!(navigator.userAgent.match(/iPhone/i)) && !(navigator.userAgent.match(/iPod/i))) {
$.fancybox.center(true);
}
};