Having a hard time solving this. I've used TinyMCE to create a WYSIWYG editor so that staff can copy/paste from Word into this program to check for errors (ie multiple h1 headers).
The problem I am having is once they've corrected a highlighted error. How do I remove their the set attribute or style from this element? Here is my JS so far that does the check and creates a log. I am assuming I'll need to use the MutationObserver? I've never used it, and couldn't see to find a good explanation of it.
function styleGuide(){
var searchInput = tinyMCE.activeEditor.getContent();
document.getElementById('findAllErrors').innerHTML = searchInput;
var resultsLog = document.getElementById('passFailLog');
// search for h1
var h1 = document.querySelectorAll('h1');
var i = 0;
do {
if(h1.length == 0){
resultsLog.innerHTML = "<br /><span class='warning'>You do not have an H1 element.</span>";
}
else if(h1.length > 1){
resultsLog.innerHTML = "<br /><span class='error'>You have more than one H1 element.</span>";
}
else {
resultsLog.innerHTML = "<br /><span class='pass'>You have the correct amount of H1 headers.</span>";
}
//set style for errors
if(i > 0){
h1[i].style.color = "Red";
h1[i].setAttribute("class", "fixIt");
}
i++;
}
while (i < h1.length);
//Update Error Found to Original Editor
var outputUpdate = document.getElementById('findAllErrors').innerHTML;
var mceContent = tinyMCE.activeEditor.getContent();
var errorsFound = outputUpdate.replace(mceContent, outputUpdate);
tinymce.activeEditor.setContent(errorsFound);
}
The start of your function should reset/remove any previously set errors (removing the Red color and removing the fixIt class).
Then the function can perform its checking operation and re-apply errors if needed.
This lets you simply call the same function each time a user makes a change.
Related
I'm trying to check whether the length of characters typed into the text box is less than 6, and if it is, I want its background to be red. Unfortunately, I can't seem to figure out where I'm going wrong with this simple problem.
var textBox = getElementsByName('random');
function checkLength() {
if (textBox.value.length < 6) {
textBox.style.backgroundColor = "red";
}
}
<input type="text" name="random" onfocus="checkLength();">
A few issues in your code:
you need to put <script> code at the end, so that DOM is loaded and ready before you access elements in it.
getElementsByName('random') needs to document.getElementsByName('random'), which will actually return a list so you need to get first element from the list.
Also logically, you need to remove the red background once the text
length in input exceeds 6 and it would be better if you attach function to oninput event.
<input type="text" name="random" oninput="checkLength();">
<script type="text/javascript">
var textBox = document.getElementsByName('random')[0];
function checkLength() {
if (textBox.value.length < 6) {
textBox.style.backgroundColor = "red";
} else {
textBox.style.backgroundColor = "white";
}
}
</script>
When the page first loads, the element with a name of random doesn't exist.
You will need to initialise your textBox global after the page loads.
You can do this by replacing
var textBox = document.getElementsByName("random")[0]
with
var textBox;
window.onload = function() {
textBox = document.getElementsByName("random")[0]
}
Try this
// add an id of "random" to your input
function checkLength() {
const textBox = document.getElementById("random")
if (textBox.value.length < 6) {
textBox.style.backgroundColor = "red";
} else {
textBox.style.backgroundColor = "white";
}
}
Working example: http://jsbin.com/caseqekusi/1/edit?html,js,output
Note: If you want the box to be red right away, you'll have to modify it a bit, let me know if you have questions.
I would suggest to use oninput as well, so it updates as you type and marks the field as "valid" as soon as you have reached a certain length.
You could also get rid of var textbox = ... by using document.activeElement. It makes your function reusable for other input fields. And it no longer matters when your code is loaded.
function checkLength() {
// Get current focused element
const textBox = document.activeElement;
if ( !textBox.value || textBox.value.length < 6 ) {
textBox.style.backgroundColor = "red";
}
else {
textBox.style.backgroundColor = "#fff";
}
}
<input type="text" name="random" onfocus="checkLength()" oninput="checkLength()">
I am trying to hide or show divs based on the title of the page. This is only required because I can't figure out a better way of passing a value into the page.
Here's the current code in the HTML file:
function toggle(divId) {
var divArray = document.getElementsByTagName("div");
for(i = 0; i < divArray.length; i++){
if(divArray[i].id == divId){
if(divArray[i].style.display != 'none'){
divArray[i].style.display = 'none';
}else{
divArray[i].style.display = '';
}
}
}
}
function togglePayLink() {
var h1Array = document.getElementsByTagName("h1");
for(i = 0; i < h1Array.length; i++){
if(h1Array[i].id == 'Title'){
var title = h1Array[i].innerHTML;
title = title.slice(1);
title = title.slice(-4);
toggle('descr'+ title);
}
}
}
Also in the HTML file is a header with the page title. The %%GLOBAL_PageTitle%% is replaced in server side code that I don't have access to. However, the values will be "$100 Fee" (with different numbers).
<h1 id="Title" class="TitleHeading">%%GLOBAL_PageTitle%%</h1>
Finally, I have a set of hidden divs with id's in the format descr + a number, so if the page title is "$100 Fee" I want to show the div with the id "descr100".
<div id="descr100" style="display:none;width: 75%;"></div>
When the script above runs, I get no error (I'm using chrome's console), but the div does not show. I know the toggle function works because it was previously being used with only a single div on the page that had to be toggled. I wrote the togglePayLink function, which I assume is the issue, but I have no idea how to debug this. I was wondering if the dollar sign in the title could be causing issues, but I would think I would get an error if that were the case.
EDIT: Changed the togglePayLink function to use var instead of string, but I'm getting a typeError when slice() is called.
Going forward, you should probably just assign a unique class to the page using %%GLOBAL_PageTitle%%. This way you can show/hide elements using CSS.
<div class="page %%GLOBAL_PageTitle%%">
For pages that BigCommerce doesn't give access to the HTML of the h1 for each individual page (ex. Web Pages, Account, Cart), I usually run this script on page load to strip the page title of spaces and other characters, and assign a specific class to the page element.
var catName = $('.TitleHeading').text();
var catName = catName.replace(/ /g, '');
var catName = catName.replace(/'/g, '');
var catName = catName.replace(/&/g, '');
var catName = $.trim(catName);
$('.page').addClass(''+catName+'');
The way your doing it seems a bit over the top, but if it was setup this way by someone else, I understand.
The problem is here:
String title = h1Array[i].innerHTML;
In Javascript, all variables are set with var (except for functions, which can be set other ways). So it would be:
var title = h1Array[i].innerHTML;
Additionally, you probably have to define it outside the for loop, in which case you would omit the "var" when you are setting it in the for loop:
<script language="javascript">
var title;
function togglePayLink() {
var h1Array = document.getElementsByTagName("h1");
for(i = 0; i < h1Array.length; i++){
if(h1Array[i].id == 'Title'){
title = h1Array[i].innerHTML;
title = title.slice(1);
title = title.slice(-4);
toggle('descr'+ title);
}
}
}
</script>
Edit: If you only use it in the for loop, but use it in different iterations, then I'm not sure if it can be defined locally. I'd still define it globally, though.
title.slice(-4) was giving me the last four digits of the string instead of everything before the last four digits like I thought it would. toggling the non-existent 'descrFee' div was not doing anything.
I've made this tinymce fiddle to show what I say.
Highlight text in the editor, then click on the input text, highlight in tinyMCE is lost (obviously).
Now, I know it's not easy since both, the inline editor and the input text are in the same document, thus, the focus is only one. But is there any tinymce way to get like an "unfocused" highlight (gray color) whenever I click in an input text?
I'm saying this because I have a customized color picker, this color picker has an input where you can type in the HEX value, when clicking OK it would execCommand a color change on the selected text, but it looks ugly because the highlight is lost.
I don't want to use an iframe, I know that by using the non-inline editor (iframe) is one of the solutions, but for a few reasons, i can't use an iframe text editor.
Any suggestion here? Thanks.
P.S: Out of topic, does any of you guys know why I can't access to tinymce object in the tinyMCE Fiddle ? looks like the tinyMCE global var was overwritten by the tinymce select dom element of the page itself. I can't execute a tinyMCE command lol.
Another solution:
http://fiddle.tinymce.com/sBeaab/5
P.S: Out of topic, does any of you guys know why I can't access to
tinymce object in the tinyMCE Fiddle ? looks like the tinyMCE global
var was overwritten by the tinymce select dom element of the page
itself. I can't execute a tinyMCE command lol.
Well, you can access the tinyMCE variable and even execute commands.
this line is wrong
var colorHex = document.getElementById("colorHex")
colorHex contains input element, not value.
var colorHex = document.getElementById("colorHex").value
now it works ( neolist couldn't load, so I removed it )
http://fiddle.tinymce.com/DBeaab/1
I had to do something similar recently.
First off, you can't really have two different elements "selected" simultaneously. So in order to accomplish this you're going to need to mimic the browser's built-in 'selected text highlight'. To do this, you're going to have to insert spans into the text to simulate highlighting, and then capture the mousedown and mouseup events.
Here's a fiddle from StackOverflow user "fullpipe" which illustrates the technique I used.
http://jsfiddle.net/fullpipe/DpP7w/light/
$(document).ready(function() {
var keylist = "abcdefghijklmnopqrstuvwxyz123456789";
function randWord(length) {
var temp = '';
for (var i=0; i < length; i++)
temp += keylist.charAt(Math.floor(Math.random()*keylist.length));
return temp;
}
for(var i = 0; i < 500; i++) {
var len = Math.round(Math.random() * 5 + 3);
document.body.innerHTML += '<span id="'+ i +'">' + randWord(len) + '</span> ';
}
var start = null;
var end = null;
$('body').on('mousedown', function(event) {
start = null;
end = null;
$('span.s').removeClass('s');
start = $(event.target);
start.addClass('s');
});
$('body').on('mouseup', function(event) {
end = $(event.target);
end.addClass('s');
if(start && end) {
var between = getAllBetween(start,end);
for(var i=0, len=between.length; i<len;i++)
between[i].addClass('s');
alert('You select ' + (len) + ' words');
}
});
});
function getAllBetween(firstEl,lastEl) {
var firstIdx = $('span').index($(firstEl));
var lastIdx = $('span').index($(lastEl));
if(lastIdx == firstIdx)
return [$(firstEl)];
if(lastIdx > firstIdx) {
var firstElement = $(firstEl);
var lastElement = $(lastEl);
} else {
var lastElement = $(firstEl);
var firstElement = $(lastEl);
}
var collection = new Array();
collection.push(firstElement);
firstElement.nextAll().each(function(){
var siblingID = $(this).attr("id");
if (siblingID != $(lastElement).attr("id")) {
collection.push($(this));
} else {
return false;
}
});
collection.push(lastElement);
return collection;
}
As you can see in the fiddle, the gibberish text in the right pane stays highlighted regardless of focus elsewhere on the page.
At that point, you're going to have to apply your color changes to all matching spans.
I have three divs and I want to execute a command on a div that happens to be on top of the other divs in a container without referencing it's name or id.I am randomizing the position of the divs and I basically want the div whose height is equal to 10px to change it's color attribute to red when a specific number is generated, whilst the other divs maintain their default color. I have tried the following but I can't think of any way to do this without using the div's id.
var current = 0;
current++;
var topArrtcard = document.getElementById("card-answer");
var topArrtcard1 = document.getElementById("card-answer1");
var topArrtcard2 = document.getElementById("card-answer2");
if(current === 0 ){
topArrtcard.style.color = "red"; // is it possible not use the id in order to make the change
topArrtcard1.style.color = " #996600";
topArrtcard2.style.color = " #996600";
}else if(current === 1 )
{
topArrtcard.style.color = "#996600";
topArrtcard1.style.color = "red";
topArrtcard2.style.color = " #996600";
}else if(current === 2){
topArrtcard.style.color = "#996600";
topArrtcard1.style.color = " #996600";
topArrtcard2.style.color = "red";
}else {
topArrtcard.style.color = "#996600";
topArrtcard1.style.color = " #996600";
topArrtcard2.style.color = "#996600";
}
the variable current increments by 1 each time the page is loaded. I hope this is clear. Thank you in advance.
If you are not opposed to using jQuery (and why would you be? In many ways it's simpler than javascript with much less to type)...
I cannot see from your code (at this moment) what will trigger an event that you can use to do the testing that you want.
However, if something does happen to the DIV, then perhaps you can use that event to make the changes you want. You would reference the changed DIV as this.
Here is an example that looks somewhat similar
When I use appendChild() and createElement() in my code, the subsequent styles for the defined CSS IDs are not applied. Can someone tell me why? Here's my code:
function searchDone(results) {
var result = null;
var parent = document.getElementById('postWrap');
var child = null;
parent.innerHTML = '';
var insertHTML =" ";
//Paginating Results Links
resultNum = results.SearchResponse.Web.Total;
resultNum = resultNum/10;
child = document.createElement('div');
child.id = "paging";
if(results.SearchResponse.Web.Offset != 0){
insertHTML ='<span><a class="jsonp b" href="#" rev="'+(results.SearchResponse.Web.Offset-10)+'"><</a></span>';
}
if(results.SearchResponse.Web.Offset == 0){
insertHTML += '<span>1</span>';
}else{
insertHTML +='<span><a class="jsonp" href="#" rev="0">1</a></span>';
}
for(var i = 1; i <= resultNum; i++){
if((results.SearchResponse.Web.Offset/10) == i){
insertHTML += '<span>'+(i+1)+'</span>';
}else{
insertHTML += '<span><a class="jsonp b" href="#" rev="'+i*10+'">'+(i+1)+'</a></span>';
}
}
if(results.SearchResponse.Web.Total - results.SearchResponse.Web.Offset > 10){
insertHTML += '<span><a class="jsonp b" href="#" rev="'+(results.SearchResponse.Web.Offset+10)+'">></a></span>';
}
child.innerHTML = insertHTML;
parent.appendChild(child);
I then have some other code which processes my search query via API to Bing (only because Google now charges... )
Next, I use the same methods to insert another div:
//Insert Paginating results again
child = null;
child = document.createElement('div');
child.innerHTML = insertHTML;
child.id = "searchResultsPages";
parent.appendChild(child);
Now I'd like to apply some styles to these numbers. However, when I apply a style to searchResultsPage, like
#searchResultsPages{
float: right;
}
I don't get the style being passed on. The curious thing is that if I only insert one of these two elements, everything goes as planned and the style shows up fine. The problem is that I'd like pages displayed at the top and bottom of the search.
Any ideas why this is happening? I think it might have something to do with an element being used twice, but I don't know why this would effect anything if the objects are different.
Thanks.
child.id = "searchResultsPages";
#searchResultsPage{
See anything wrong there? :)
Like an s
IDs should be unique within the page so if you have two elements with id="searchResultsPage" the behaviour can get a bit screwy and the HTML is invalid. Instead, use a class="searchResultsPage" if there will be multiple elements.
The issue of the missing 's' the other commenters point out is also quite important though hopefully that was just a typo in the question.