I want to create an input where users can write plain text only, but where I can get part of that text and replace it with some HTML.
So, for example, I want to convert a text like Lorem Ipsum {{dolor}}
to Lorem Ipsum <some html with data from JS object>
I have an object with some data.
var data = {
dolor: {
icon: 'https://placehold.it/16x16/',
text: 'Dolor text'
}
}
I want to use that to get the custom text and image, so
{{dolor}}
should convert to something like
<span class="image">
<img src="https://placehold.it/16x16/">
Dolor text
</span>
My approach was to use CodeMirror, define a new mode and detect the curly braces, but now I don't know how to get the content between those braces and I don't know how to modify the outputted HTML (as CodeMirror only adds a cm-NameOfMode
CSS class to the text).
This is what I have
var data = {
dolor: {
icon: 'https://placehold.it/16x16/',
text: 'Dolor text'
}
}
CodeMirror.defineMode( 'uoVariable', function( config, parserConfig ){
var uoVariable = {
token: function( stream, state ){
var character;
// console.log( state.inString );
if ( stream.match( '{{' ) ){
while ( ( character = stream.next() ) != null ){
if ( character == '}' && stream.next() == '}' ){
stream.eat( '}' );
return 'uoVariable';
}
}
}
while ( stream.next() != null && ! stream.match( '{{', false ) ){}
return null;
}
};
return CodeMirror.overlayMode( CodeMirror.getMode( config, parserConfig.backdrop ), uoVariable );
});
$(document).ready(function(){
// Do for each one
let form__variable_cd_mirror = document.getElementById( 'form-variable__cd-text' ),
form__variable_cd = document.getElementById( 'form-variable__cd' );
let editor = CodeMirror( form__variable_cd, {
mode: 'uoVariable',
value: form__variable_cd_mirror.innerText,
lineWrapping: true,
scrollbarStyle: null,
extraKeys: {
Tab: function( cm ){
return false;
},
},
}).on( 'beforeChange', function( cm, changeObj ){
// Typed new line
var typedNewLine = changeObj.origin == '+input' && typeof changeObj.text == 'object' && changeObj.text.join('') == '';
if ( typedNewLine ){
return changeObj.cancel();
}
// Pasted new line
var pastedNewLine = changeObj.origin == 'paste' && typeof changeObj.text == 'object' && changeObj.text.length > 1;
if ( pastedNewLine ) {
var newText = changeObj.text.join(' ');
return changeObj.update( null, null, [ newText ] );
}
return null;
});
});
body {
font-size: 15px;
font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* New CSS */
#form-variable__cd .CodeMirror {
padding: 8px 12px;
transition: all 150ms ease-in-out;
border-radius: 3px;
border: 1px solid #cdcdcd;
box-shadow: 0 2px 5px 0 rgba(0,0,0,.1);
outline: none;
height: auto;
font-size: 15px;
font-family: inherit !important;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
margin-top: 10px;
}
#form-variable__cd .cm-uoVariable {
background: #4f4f4f;
color: #fff;
padding: 2px 5px;
border-radius: 3px;
white-space: nowrap;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.38.0/codemirror.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/codemirror/5.38.0/codemirror.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.38.0/addon/mode/overlay.js"></script>
<div id="form-variable__cd-text" style="display: none">Lorem ipsum {{dolor}}</div>
<div id="form-variable__cd"></div>
So... any ideas about how can I archive this?
Thanks!
I am not a user of CodeMirror, but I already worked with templates in HTML.
Here is an approach:
{{key}}
with keys in your data
object to generate HTMLinnerHTML
directly in your templates, or into separate elements (if you want to regenerate from templates later)Here is how you could do it in a simple way:
var data = {
dolor: {
icon: 'https://placehold.it/16x16/',
text: 'Dolor text'
},
lorem: {
text: 'Lorem text'
}
};
function getHtmlFromData(dataitem) {
var html = '';
if ('icon' in dataitem)
// Image data type
html += '<span class="image">' +
'<img src="' + dataitem.icon + '">' +
dataitem.text +
'</span>';
else
// Text data type
html += '<span class="text">' +
dataitem.text +
'</span>';
return html;
}
setTimeout(
function () {
var templates = document.getElementsByClassName("template");
Array.prototype.forEach.call(templates, function (template) {
for (var key in data) {
template.innerHTML = template.innerHTML.replace(
new RegExp('{{'+key+'}}', 'g'),
getHtmlFromData(data[key])
);
}
});
},
1000
);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="index.jsx"></script>
</head>
<body>
<div class="template">
{{lorem}} Ipsum {{dolor}}
</div>
</body>
</html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With