How to hightlight source code using codemirror on a html page - javascript

I am currently highlighting the source on my website using google's prettyprint like below on my website.
<pre class="prettyprint css">
div {
background-color: lightgreen;
width: 300px;
padding: 25px;
border: 25px solid red;
margin: 25px;
}
</pre>
I will already have some code on file but I only want to hightlight that code.
How can I highlight the same using codemirror?

as it shown in codemirror.net
create an <textarea> element, which will replace yuor current <pre> tag. set textarea to readonly if you prefer no edit.
<textarea id="myTextarea" readonly>
... your code for highlighting goes here ...
</textarea>
<link rel="stylesheet" href="lib/codemirror.css">
<script src="lib/codemirror.js"></script>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("myTextarea"), {
lineNumbers: true
});
</script>
multiple instances selected by a common class name:
var areas = document.getElementsByClassName("myTextareaClass");
for(var i = 0; i < areas.length; i++) {
CodeMirror.fromTextArea(areas.item(i), {lineNumbers: true});
}

Related

Webcomponents is re-initializing every time while working with Vue js

I have created a webcomponent for a generic input boxes that i needed across multiple projects.
the design functionality remains same only i have to use switch themes on each projects.so i have decided to go on with webcomponents.One of the projects is based on Vue Js.In Vue js the DOM content is re-rendered while each update for enabling reactivity. That re-rendering of vue template is reinitializing my custom webcomponent which will result in loosing all my configurations i have assigned to the component using setters.
I know the below solutions. but i wanted to use a setter method.
pass data as Attributes
Event based passing of configurations.
Using Vue-directives.
using v-show instead of v-if
-- Above three solutions doesn't really match with what i am trying to create.
I have created a sample project in jsfiddle to display my issue.
Each time i an unchecking and checking the checkbox new instances of my component is creating. which causes loosing the theme i have selected. (please check he active boxes count)
For this particular example i want blue theme to be displayed. but it keep changing to red
JSFiddle direct Link
class InputBox extends HTMLElement {
constructor() {
super();
window.activeBoxes ? window.activeBoxes++ : window.activeBoxes = 1;
var shadow = this.attachShadow({
mode: 'open'
});
var template = `
<style>
.blue#iElem {
background: #00f !important;
color: #fff !important;
}
.green#iElem {
background: #0f0 !important;
color: #f00 !important;
}
#iElem {
background: #f00;
padding: 13px;
border-radius: 10px;
color: yellow;
border: 0;
outline: 0;
box-shadow: 0px 0px 14px -3px #000;
}
</style>
<input id="iElem" autocomplete="off" autocorrect="off" spellcheck="false" type="text" />
`;
shadow.innerHTML = template;
this._theme = 'red';
this.changeTheme = function(){
this.shadowRoot.querySelector('#iElem').className = '';
this.shadowRoot.querySelector('#iElem').classList.add(this._theme);
}
}
connectedCallback() {
this.changeTheme();
}
set theme(val){
this._theme = val;
this.changeTheme();
}
}
window.customElements.define('search-bar', InputBox);
<!DOCTYPE html>
<html>
<head>
<title>Wrapper Component</title>
<script src="https://unpkg.com/vue"></script>
<style>
html,
body {
font: 13px/18px sans-serif;
}
select {
min-width: 300px;
}
search-bar {
top: 100px;
position: absolute;
left: 300px;
}
input {
min-width: 20px;
padding: 25px;
top: 100px;
position: absolute;
}
</style>
</head>
<body>
<div id="el"></div>
<!-- using string template here to work around HTML <option> placement restriction -->
<script type="text/x-template" id="demo-template">
<div>
<div class='parent' contentEditable='true' v-if='visible'>
<search-bar ref='iBox'></search-bar>
</div>
<input type='checkbox' v-model='visible'>
</div>
</script>
<script type="text/x-template" id="select2-template">
<select>
<slot></slot>
</select>
</script>
<script>
var vm = new Vue({
el: "#el",
template: "#demo-template",
data: {
visible: true,
},
mounted(){
let self = this
setTimeout(()=>{
self.$refs.iBox.theme = 'blue';
} , 0)
}
});
</script>
</body>
</html>
<div class='parent' contentEditable='true' v-if='visible'>
<search-bar ref='iBox'></search-bar>
</div>
<input type='checkbox' v-model='visible'>
Vue's v-if will add/remove the whole DIV from the DOM
So <search-bar> is also added/removed on every checkbox click
If you want a state for <search-bar> you have to save it someplace outside the <search-bar> component:
JavaScript variable
localStorage
.getRootnode().host
CSS Properties I would go with this one, as they trickle into shadowDOM
...
...
Or change your checkbox code to not use v-if but hide the <div> with any CSS:
display: none
visibility: hidden
opacity: 0
move to off screen location
height: 0
...
and/or...
Managing multiple screen elements with Stylesheets
You can easily toggle styling using <style> elements:
<style id="SearchBox" onload="this.disabled=true">
... lots of CSS
... even more CSS
... and more CSS
</style>
The onload event makes sure the <style> is not applied on page load.
activate all CSS styles:
(this.shadowRoot || document).getElementById("SearchBox").disabled = false
remove all CSS styles:
(this.shadowRoot || document).getElementById("SearchBox").disabled = true
You do need CSS Properties for this to work in combo with shadowDOM Elements.
I prefer native over Frameworks. <style v-if='visible'/> will work.. by brutally removing/adding the stylesheet.

Tag object being changed dynamically by displaying html from a code editor

Hello stackoverflow community, I have a question regarding the use of the <object> html tag. Below is a description of what I want to do:
I am using the summernote editor, however I would like every change within the editor to be presented to the user as the html page will be. I am currently using the following code:
$('#summernote').summernote({
placeholder: 'Hello bootstrap 4',
tabsize: 2,
height: 300,
lang: 'pt-BR'
});
$("#summernote").on("summernote.change", function(e) { // callback as jquery custom event
console.log('it is changed');
myFunction();
});
var i = 0;
var dragging = false;
$('#dragbar').mousedown(function(e) {
e.preventDefault();
dragging = true;
var main = $('#main');
var ghostbar = $('<div>', {
id: 'ghostbar',
css: {
height: main.outerHeight(),
top: main.offset().top,
left: main.offset().left
}
}).appendTo('body');
$(document).mousemove(function(e) {
ghostbar.css("left", e.pageX + 2);
});
});
$(document).mouseup(function(e) {
if (dragging) {
var percentage = (e.pageX / window.innerWidth) * 100;
var mainPercentage = 100 - percentage;
$('#console').text("side:" + percentage + " main:" + mainPercentage);
$('#sidebar').css("width", percentage + "%");
$('#main').css("width", mainPercentage + "%");
$('#ghostbar').remove();
$(document).unbind('mousemove');
dragging = false;
}
});
function myFunction(data) {
var text = $('#summernote').summernote('code');
document.getElementById("demo").innerHTML = "<!DOCTYPE html><html><meta charset='UTF-8'>" + text + "</html>";
console.log(document.getElementById("demo"));
console.log(text);
}
.clearfix:after {
content: '';
display: table;
clear: both;
}
#main {
float: right;
width: 50%;
}
#sidebar {
width: 50%;
float: left;
overflow-y: hidden;
}
#dragbar {
/*background-color: #a9a9a9;*/
background: transparent;
height: 100%;
float: right;
width: 3px;
cursor: col-resize;
}
#ghostbar {
width: 3px;
background-color: #a9a9a9;
opacity: 0.5;
position: absolute;
cursor: col-resize;
z-index: 999
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Summernote Editor</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.9/summernote-bs4.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/summernote/0.8.9/summernote-bs4.js"></script>
<script src="summernote-pt-BR.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<!--<div id="summernote"></div>-->
<div id="sidebar" class="col">
<span id="position"></span>
<div id="dragbar">
</div>
sidebar
<form method="post">
<textarea id="summernote" name="editordata"></textarea>
<button type="submit" class="btn btn-primary">Salvar</button>
</form>
</div>
<div id="main">main
<p id="demo"></p>
</div>
</div>
</div>
</body>
</html>
But instead of using the <p> tag along with innerHtml, I'd like to use the <object> tag, and its contents being changed daily.
If you have other better solutions, feel free to make suggestions.
Note: I have already tried using the tag but somehow using this tag hinders the resize that I need to perform between the editor and html viewer.
Note 2: I'm a beginner, and my English is not good. So sorry if something went wrong without making sense. I used Google translate to explain the issue.
Hi Rafael — thanks for clarifying.
The reason your code looks different in the iframe or object tags is due to the differing CSS. When you use an iframe and set the source dynamically, the CSS comes from the User Agent Stylesheet. The tag does not inherit the parent's styles. Currently, your CSS in the p tag is from Bootstrap 4.
Option 1: You could customize the CSS on this element to make it appear consistent in a non-Bootstrap context.
Option 2: If you still want to change tags, I think you are better off using an iframe instead of an object tag, per the MDN docs and the discussion on this SO thread.
Change <p id="demo"></p> to <iframe id="demo"></iframe>, and your myFunction to:
function myFunction(data) {
var text = $('#summernote').summernote('code');
var frame=document.getElementById("demo");
frame.srcdoc="<!DOCTYPE html><html><meta charset='UTF-8'>" + text + "</html>";
}
If you support IE11, Edge, and Opera Mini (srcdoc is not supported there) you can use a polyfill.
One final consideration with this route is performance — I couldn't find much on this, but I suspect that setting the innerHTML of your p tag is far less expensive than re-rendering an iframe. You might want to investigate and consider reducing the update interval if this becomes a problem.

Javascript button ceases to write to texarea once user has added text

I am trying to make a simple text editing box so that I can eventually post text to another section of a website. I'm attempting to make buttons to make text bold, italicized, add a code box etc, (hence insertAdjacentHTML not insertAdjacentText) but I decided to just start making sure I could get plain text to print to a textarea.
I have achieved this easily but now my question becomes how do I make it so that the button still affects the text area after a user has added text to it? the code below will happily type out "hello"'s up until you click on the textarea, and from that point on it refuses to and I can't figure out why.
window.hello = function(textarea) {
var obj = document.getElementById("text");
obj.insertAdjacentHTML('beforeend', 'hello');
}
<body>
<button onclick="hello()">hello</button>
<form>
<p></p>
<textarea id="text"></textarea>
</form>
</body>
As you can read from MDN a textarea can contain only Character data.
This is the reason because you cannot use insertAdjacentHTML and instead you can use the value.
If you need to add text in bold or ... you can use a contenteditable div element.
The snippet:
window.helloDiv = function() {
var obj = document.getElementById("textDiv");
obj.insertAdjacentHTML('beforeend', 'hello');
};
window.helloTxtArea = function() {
var obj = document.getElementById("textTxtArea");
obj.value += 'hello';
}
div {
width: 300px;
height: 100px;
border: 1px;
border-style: solid;
}
textarea {
width: 300px;
height: 100px;
margin-top: 10px;
}
<button onclick="helloDiv()">helloDiv</button>
<button onclick="helloTxtArea()">helloTextArea</button>
<form>
<p></p>
<div id="textDiv" contenteditable="true"></div>
<textarea id="textTxtArea" contenteditable="true"></textarea>
</form>

Javascript: how to modify my code to add back disappeared placeholder after topic post

I use a plug in to handmade a placeholder for conteditable div.
showed in demo below. If user puts in some text then click the post button, the placeholder disappeared.I wondered how to get the placeholder back after posting.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<div id="topic_content_input" contenteditable="true" autocomplete="off" spellcheck="false" data-placeholder="placeholder text" ></div>
<button id="post">Post topic</button>
<style>
#topic_content_input[data-placeholder]:not([data-div-placeholder-content]):before {
content: attr(data-placeholder);
float: left;
cursor:text;
margin-left: 2px;
color: rgba(134,134,134,0.6);
}
#topic_content_input{
width:521px;
padding: 10px;
border: 1px solid orange;
}
#topic_content_input:focus{
outline-style:solid;
outline-color:orange;
outline-width:0px;
line-height:normal;
}
</style>
<script>
(function ($) {
$(document).on('change keydown keypress input', '#topic_content_input[data-placeholder]', function() {
if (this.textContent) {
this.dataset.divPlaceholderContent = 'true';
}
else {
delete(this.dataset.divPlaceholderContent);
}
});
})(jQuery);
</script>
<script>
$("#post").click(function(){
$("#topic_content_input").text("");
var obj=$("#topic_content_input");
// $("#topic_content_input").add(obj.dataset.divPlaceholderContent); //my attempt, not working
})
</script>
In the CSS, rather than having #topic_content_input[data-placeholder]:not([data-div-placeholder-content]):before, you can instead put in #topic_content_input:empty:before, which will put in the placeholder whenever the div is empty, as seen in this jsfiddle.
$("#topic_content_input").add(obj.dataset.divPlaceholderContent);
why ".add" ?
you shoul use:
obj.val(obj.dataset.divPlaceholderContent)
or
obj.attr('placeholder', obj.dataset.divPlaceholderContent)

Override TAB inside a Browser

If I'm typing text in a input field and press ENTER the default behavior of all the browsers I know is to submit the form, however if I press ENTER inside a textarea a new line is added.
Is there any way to mimic this behavior (indent, not submit the form) whenever I press TAB inside a textarea? Bespin seems to do it, but in a canvas element.
I haven't done it myself, but it seems to be possible to override the event handler and catch the key. See e.g. here.
Oh and for the JQuery crowd there even is a plugin.
Of course there's a way. Do you use any js library? If not, the idea is just to add a keydown event handler on the textarea element, check in the handler if the keyCode of the event equals 9, and if so append a "\t" to the content of the textarea. Prototype snippet:
textarea.observe('keydown', function (e) {
if(e.keyCode==9) {
e.element().insert("\t");
e.stop();
}
}
This code should work.
//'index.js' File
var textarea = document.getElementById('note');
textarea.addEventListener('keydown', function (e) {
if(e.keyCode==9) {
e.element().insert("\t");
e.stop();
}
});
If you get a 'cannot read property of null' error do this:
//'index.js' File v2
function tab() {
var textarea = document.getElementById('note');
if(event.keyCode===9) {
textarea.innerHTML += "\t";
}
}
The HTML should follow suit and look like this:
<!DOCTYPE html>
<!-- index.html -->
<!-- Don't Mind the other parts like the style and button tags -->
<!-- If you don't get the error mentioned just remove the 'onkeydown="tab()"'. -->
<html onkeydown="tab()">
<head>
<title>Calender</title>
<script src="./index.js"></script>
<style>
* {
background-color: darkgoldenrod;
color: white;
}
textarea {
background-color: white;
color: black;
}
.newNote {
background-color: olivedrab;
color: white;
border: 1px solid #000000;
box-shadow: none;
border-radius: 7.5px;
}
</style>
</head>
<body>
<button class="newNote" id="newNote" onclick="Note()">New Note</button>
<br/>
<br/>
<textarea wrap="soft" rows="30" cols="100" id="note"
placeholder="Type a Note Here!" title="Note Box"></textarea>
</body>
</html>

Categories