I am trying to use JavaScript to manipulate and change font and font size from a page of text from a word processor (such as Google Docs or Word) inputted by a user, by an HTML word processor (CKEditor). However, after manipulation of font size, when displaying the text into an HTML text field, much of the document formatting is lost such as no indentation, spaces at the end of the line being deleted, titles are not centered.
Is there a way to correctly format a text document using purely HTML?
I have not found a function in CKEditor that allows me to change the font or font size on call within it, or any other HTML word processor for that matter.
Here's the code that manipulates the text, then pastes it into the HTML text area.
editor = CKEDITOR.instances.editor1;
var edata = editor.getData();
edata = CKEDITOR.instances.editor1.document.getBody().getText();
var sin = replaced_text;
var sout = "";
var i;
for(i = 0 ; i < sin.length; i++) {
if(sin.charAt(i) == ",")
{ sout += '<span class=ef>' + sin.charAt(i) + '</span>' }
else if(sin.charAt(i) == ".") { sout += '<span class=ef>' + sin.charAt(i) + '</span>' }
else if(sin.charAt(i) == " " && sin.charAt(i+1) == " ") { sout += 'span class = of>' + sin.charAt(i) + sin.charAt(i+1) + '</span>' }
else if(sin.charAt(i) == " "){ sout += '<span class=of>' + sin.charAt(i) + '</span>' }
else {sout+= '<span class=if>' + sin.charAt(i) + '</span>'}
}
var data = editor.dataProcessor.toDataFormat( sout );
document.getElementById("space").innerHTML = data;
editor.setData(data);
editor.updateElement();
it's helpful for you markedJS.
MarkedJS can parse markdown text, you can use it to marked your text so that keeps text formate
Related
Let's say I have some sentences in Google Docs. Just one sentences as an example:
"My house is on fire"
I actually changed the background color so that every verb is red and every noun blue.
Now I want to make a list with all the verbs and another one with the nouns. Unfortunately getBackgroundColor() only seems to work with paragraphs and not with single words.
My idea was, to do something like this (I didn't yet have the time to think about how to do the loop, but that's not the point here anyway):
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var paragraphs = body.getParagraphs();
var colorVar = paragraphs[0].getText().match(/\w+/).getBackgroundColor(); // The regEx matches the first word. Next I want to get the background color.
Logger.log(colorVar);
}
The error message I get goes something like this:
"The function getBackgroundColor in the text object couldn't be found"
Thx for any help, or hints or comments!
You want to retrieve the text from a paragraph.
You want to retrieve each word and the background color of each word from the retrieved the text.
In this case, the color is the background color which is not getForegroundColor().
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
At first, the reason of your error is that getBackgroundColor() is the method of Class Text. In your script, getBackgroundColor() is used for the string value. By this, the error occurs.
In this answer, for achieving your goal, each character of the text retrieved from the paragraph is scanned, and each word and the background color of each word can be retrieved.
Sample script:
function myFunction() {
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
var paragraphs = body.getParagraphs();
var textObj = paragraphs[0].editAsText();
var text = textObj.getText();
var res = [];
var temp = "";
for (var i = 0; i < text.length; i++) {
var c = text[i];
if (c != " ") {
temp += c;
} else {
if (temp != "") res.push({text: temp, color: textObj.getBackgroundColor(i - 1)});
temp = "";
}
}
Logger.log(res) // result
}
When you run the script, the text of 1st paragraph is parsed. And you can see the result with res as an object.
In this sample script, the 1st paragraph is used as a test case. So if you want to retrieve the value from other paragraph, please modify the script.
References:
getBackgroundColor()
getBackgroundColor(offset)
editAsText()
If I misunderstood your question and this was not the direction you want, I apologize.
Here's a script your welcome to take a look at. It highlights text that a user selects...even individual letters. I did it several years ago just to learn more about how documents work.
function highLightCurrentSelection() {
var conclusionStyle = {};
conclusionStyle[DocumentApp.Attribute.BACKGROUND_COLOR]='#ffffff';
conclusionStyle[DocumentApp.Attribute.FOREGROUND_COLOR]='#000000';
conclusionStyle[DocumentApp.Attribute.FONT_FAMILY]='Calibri';
conclusionStyle[DocumentApp.Attribute.FONT_SIZE]=20;
conclusionStyle[DocumentApp.Attribute.BOLD]=false;
conclusionStyle[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT]=DocumentApp.HorizontalAlignment.LEFT;
conclusionStyle[DocumentApp.Attribute.VERTICAL_ALIGNMENT]=DocumentApp.VerticalAlignment.BOTTOM;
conclusionStyle[DocumentApp.Attribute.LINE_SPACING]=1.5;
conclusionStyle[DocumentApp.Attribute.HEIGHT]=2;
conclusionStyle[DocumentApp.Attribute.LEFT_TO_RIGHT]=true;
var br = '<br />';
var selection = DocumentApp.getActiveDocument().getSelection();
var s='';
if(selection) {
s+=br + '<strong>Elements in Current Selection</strong>';
var selectedElements = selection.getRangeElements();
for(var i=0;i<selectedElements.length;i++) {
var selElem = selectedElements[i];
var el = selElem.getElement();
var isPartial = selElem.isPartial();
if(isPartial) {
var selStart = selElem.getStartOffset();
var selEnd = selElem.getEndOffsetInclusive();
s+=br + 'isPartial:true selStart=' + selStart + ' selEnd=' + selEnd ;
var bgcolor = (el.asText().getBackgroundColor(selStart)=='#ffff00')?'#ffffff':'#ffff00';
el.asText().setBackgroundColor(selStart, selEnd, bgcolor)
}else {
var selStart = selElem.getStartOffset();
var selEnd = selElem.getEndOffsetInclusive();
s+=br + 'isPartial:false selStart=' + selStart + ' selEnd=' + selEnd ;
var bgcolor = (el.asText().getBackgroundColor()=='#ffff00')?'#ffffff':'#ffff00';
el.asText().setBackgroundColor(bgcolor);
}
var elType=el.getType();
s+=br + 'selectedElement[' + i + '].getType()= ' + elType;
if(elType==DocumentApp.ElementType.TEXT) {
var txt = selElem.getElement().asText().getText().slice(selStart,selEnd+1);
var elattrs = el.getAttributes();
if(elattrs)
{
s+=br + 'Type:<strong>TEXT</strong>';
s+=br + 'Text:<span style="color:#ff0000">' + txt + '</span>';
s+=br + 'Length: ' + txt.length;
s+=br + '<div id="sel' + Number(i) + '" style="display:none;">';
for(var key in elattrs)
{
s+= br + '<strong>' + key + '</strong>' + ' = ' + elattrs[key];
s+=br + '<input type="text" value="' + elattrs[key] + '" id="elattr' + key + Number(i) + '" />';
s+=br + '<input id="elattrbtn' + Number(i) + '" type="button" value="Save Changes" onClick="setSelectedElementAttribute(\'' + key + '\',' + i + ');" />'
}
s+='</div>Show/Hide';
}
}
if(elType==DocumentApp.ElementType.PARAGRAPH) {
var txt = selElem.getElement().asParagraph().getText();
var elattrs = el.getAttributes();
if(elattrs)
{
s+=br + '<strong>PARAGRAPH Attributes</strong>';
s+=br + 'Text:<span style="color:#ff0000">' + txt + '</span> Text Length= ' + txt.length;
for(var key in elattrs)
{
s+= br + key + ' = ' + elattrs[key];
}
}
}
s+='<hr width="100%"/>';
}
//var finalP=DocumentApp.getActiveDocument().getBody().appendParagraph('Total Number of Elements: ' + Number(selectedElements.length));
//finalP.setAttributes(conclusionStyle);
}else {
s+= br + 'No Elements found in current selection';
}
s+='<input type="button" value="Toggle HighLight" onclick="google.script.run.highLightCurrentSelection();"/>';
//s+='<input type="button" value="Exit" onClick="google.script.host.close();" />';
DocumentApp.getUi().showSidebar(HtmlService.createHtmlOutputFromFile('htmlToBody').append(s).setWidth(800).setHeight(450).setTitle('Selected Elements'));
}
I want to add class to multiple SPAN (but not all SPAN). In this case i'm choosing to add class to last 2 SPAN's.
So currently my code is taking a string and then inserting each letter as SPAN in html.
So then i want the code to read the last 2 (or any other amount) of span to add another .class (in this case .blue)
I believe this is part of the code i need to use, but because i'm doing += it add another extra SPAN to html which is causing duplicates.
if (i >= 5) {
html += '<span class="blue blast">' + split[i] + '</span>';
}
Full code here and CodePen:
function myFunction() {
var string = document.querySelector('.title').innerHTML
var split = string.split('');
var html = '';
for (let i = 0; i < split.length; i++) {
html += '<span class="blast">' + split[i] + '</span>';
if (i >= 5) {
html += '<span class="blue blast">' + split[i] + '</span>';
}
}
document.querySelector('.title').innerHTML = html;
}
myFunction()
https://codepen.io/MariusZMM/pen/MZdpNb
I already have jQuery code that does this for me. But i want to learn Vanila JavaScript.
Update: with the help from tymeJV i have updated CodePen with a fix:
https://codepen.io/MariusZMM/pen/pqmwgL
You only want to write the blue letters when i > 5 - so wrap the other portion in an else block
if (i >= 5) {
html += '<span class="blue blast">' + split[i] + '</span>';
} else {
html += '<span class="blast">' + split[i] + '</span>';
}
This is my proposition:
function myFunction(num) {
const splitted = document.querySelector('.title').innerHTML.split('');
const newContent = splitted.map((letter, i) => {
const className = i >= splitted.length - num ? 'blue blast' : 'blast';
return '<span class="'+className+'">' + letter + '</span>';
}).join('');
document.querySelector('.title').innerHTML = newContent;
}
myFunction(3);
I'm trying to use my text input as a string variable and use that variable as a part of a URL to pull up JSON data but I can't seem to get it to work properly.
I don't know if I'm setting the variables incorrectly but any help would be appreciated. Thank you!
$(document).ready(function() {
var p = document.querySelector('p');
var input = document.getElementById('search').value;
$("#go").click(function() {
if (input === '') {
p.style.backgroundColor = 'transparent';
p.classList.add = 'hide';
p.innerHTML = '';
} else {
$.getJSON("https://en.wikipedia.org/w/api.php?action=opensearch&datatype=json&limit=5&search=" + input + "&callback=?", function(data) {
p.innerHTML = "<br> Click the links below";
p.classList.remove('hide');
var i = 0
for (i; i < 5; i++){
if (data[3][i] !== undefined){
p.innerHTML += '<h2> <a href ="' + data[3][i] + '" target = "_blank">' + data[1][i] + '<br>' + '<h3>' + data[2][i] + '</h3>' + '</h2>'
} else {
p.innerHTML = ' <h2> No matching result </h2>';
}
}
});
}
});
});
At the time you assign the variable value, it is empty because it is run when the site is loaded and there is probably no text in the search box yet. You want the content at the time #go is clicked, so just assign it inside the click event handler:
$(document).ready(function() {
var p = document.querySelector('p');
// the text field value is empty at this point
$("#go").click(function() {
// this is run when user clicks #go
var input = document.getElementById('search').value;
if (input === '') {
p.style.backgroundColor = 'transparent';
p.classList.add = 'hide';
p.innerHTML = '';
}
else {
// encode user input
$.getJSON("https://en.wikipedia.org/w/api.php?action=opensearch&datatype=json&limit=5&search=" + encodeURIComponent(input) + "&callback=?", function(data) {
p.innerHTML = "<br> Click the links below";
p.classList.remove('hide');
var i = 0
for (i; i < 5; i++){
if (data[3][i] !== undefined){
p.innerHTML += '<h2> <a href ="' + data[3][i] + '" target = "_blank">' + data[1][i] + '<br>' + '<h3>' + data[2][i] + '</h3>' + '</h2>'
}
else {
p.innerHTML = ' <h2> No matching result </h2>';
}
}
});
}
});
});
Additionally, you should always encode user input if you include it in a URI. Otherwise you'll experience unexpected behaviour when using any non alphanumerical character (including whitespace) in the search box. For a more detailed explanation of how and why, see the documentation.
I'm using a fantasy football website with this custom widget.
Site is here, css is here, though there's plenty of other CSS being inherited.
I'd like all the icons displayed horizontally within the top row of the table.
I have set up a row for the icons, but they're still forced within a narrow column, each icon appearing to own its own row. My best guess is that it's this "function createColumnLeft(fpid)" part of the widget code:
function createColumnLeft(fpid)
{
var htmlComponent_s = '<table>';
var htmlComponent_e = '</table>';
var temoComp = '';
for(var i=0;fpid!=null && i<fpid.length ;i++) {
if(!(middleFranchise!='' && fpid[i].id == middleFranchise)) {
var fdb = franchiseDatabase['fid_'+fpid[i].id];
if(fdb instanceof Franchise) {
temoComp += '<td class="left_m" id="left_menu_'+fdb.id+'">';
var displayName = '';
if(useIcons) {
temoComp+='<td>';
if(fdb.icon == null || fdb.icon.trim() == '') {
displayName = fdb.name;
}
else {
displayName = '<img src="' + fdb.icon + '"class="franchiseicon" title="' + fdb.name + '" />'
}
}
else {
temoComp+='<td class="teamname">';
displayName = fdb.name;
}
temoComp = temoComp + '' + displayName +'' ;
temoComp = temoComp + '</td></tr>';
}
}
}
return htmlComponent_s+temoComp+htmlComponent_e;
}
#roster_column_left table tbody tr {
display: inline;
float: left;
}
Actually, it doesn't seem like a CSS problem. It looks like the code above is creating a new row for each array element.
htmlComponent_s & htmlComponent_e are beginning and terminating tags, and because there's a terminating tag in this line:
temoComp = temoComp + '</td></tr>';
... that's causing the DOM parser to assume that you meant one row per icon. You really need to be explicitly creating a row, then creating a per icon.
I got a simple JavaScript based blog . First have a look at the below codes and I will ask my question.
Index.html have the following codes in its body
<script language="javascript" type="text/javascript" src="blog/config.js"> </script>
<script language="javascript" type="text/javascript" src="blog/single.js"> </script>
<script language="javascript" type="text/javascript" src="blog/posts.js"> </script>
config.js has
//This is the configuration file of the blog system.
//change these variables to suit your style and needs
var head = "h2"; //the heading style, ex. h1, h2, ect. use "h2" rather than "<h2>"
var text = "text"; //the text style, from your style sheet, it's in a <div> tag
var divider = "<hr>"; //the division between posts
var newer = "newer"; //the class for the link to the next newest page
var older = "older"; //the class for the link to the next oldest page
var pageclass = "page"; //the class for the text that displays the page number
var dateclass = "date"; //the class for the date
var pagesize = 4; //the number of posts on each page
var navclass = nav; //the configuration for the navigation`
posts.js
var posts = 1; //add 1 to this after adding a post. should be equal to the id of the newest post.
initblog(posts);
var id = 1; //make sure that this number is one greater than the one below it
var date = "mm/dd/yyyy"; //The date of the post
var heading = "Post 1"; //The title
var entry = ""; //reset the string
//don't worry about formatting and stuff like that, the system takes care of it all for us.
//VV your entry VV
entry += "<p>Wow, this post is on another page, If you have this many real posts, congratulations!</p>";
//^^ The most important part ^^
add_entry(id,date,heading,entry); //adds the entry to the blog
single.js
var maxpost;
function initblog(posts){
maxpost = posts;
var address = window.location.search;
if (address.substring(0, 1) == '?') {
page = address.substring(1);
} else{
window.location = "post.html?" + posts;
}
page = parseInt(page);
if (page > maxpost){
page = maxpost;
}
if (page < 1){
page = 1;
}
}
function add_entry(id,date,heading,entry) {
for (i=page;i>page - 1;i--){
if (id == i){
var entrytext = "";
entrytext += "<div class=" + text + ">";
entrytext += "<" + head + ">";
entrytext += "<a name=" + id + "></a>";
entrytext += "<span class='date'>[" + date + "]</span> ";
entrytext += heading;
entrytext += "</" + head + ">";
entrytext += entry;
entrytext += "</div>" + divider;
document.write(entrytext);
}
}
}
function pages(){
entrytext = ""
entrytext += "<table class=\"nav\"><tr>";
entrytext += "<td width=25% class = " + newer + "> ";
if (page < maxpost){
entrytext += "<A HREF=javascript:prev()>Newer Posts </A>";
}
entrytext += "</td><td width=50% class = " + pageclass + "><br><A HREF=javascript:newest()> Back to Index</A></td>";
entrytext += "<td width=25% class = " + older + "> ";
if (page-1 > 0){
entrytext += "<A HREF=javascript:next()>Older Posts</A>";
}
entrytext += "</td></table>";
entrytext += "";
document.write(entrytext);
}
function next(){
page = page - 1;
if (page < 1) {
page = page + 1;
}
window.location = "post.html?" + page;
}
function prev(){
page = page + 1;
if (page > maxpost) {
page = maxpost;
}
window.location = "post.html?" + page;
}
function newest(){
window.location = "index.html?" + maxpost;
}
Well , this is the whole blog script . I ain't added styles and you may see the comments on each lines for simplicity.
This blog doesn't have options to add title and meta description , keyword etc. Due to the style of applying it can do nothing outside the body tag.
1 . How to add an option to take/load titles?
2 . How to add the feature to load meta tag?
Don't tell me to edit and add titles on the template (index.HTML) , because that make no sense
As you see the heading block is for the title of the blog. All you need is just making it more visible.
var entrytext = "";
entrytext += "<div class=" + text + ">";
entrytext += "<h1>" + heading + "</h1>";
entrytext += "<" + head + ">";
entrytext += "<a name=" + id + "></a>";
entrytext += "<span class='date'>[" + date + "]</span> ";
entrytext += "</" + head + ">";
entrytext += entry;
entrytext += "</div>" + divider;
document.write(entrytext);
document.title = heading;
This will solve your problem about titles.
Regarding to meta tags, usually (actually by standard) meta tags are written betweeen <head> tags in HTML. To make it SEO compilant you need add them into these tags. More detailed: http://www.w3schools.com/tags/tag_meta.asp
But, if this code is generated on client-side. There is no meaning to generate it, because search engine will not parse on-fly generated meta tags. Because it's executed on browser.