Live HTML/CSS preview from a div tag and not a text area tag - javascript

I want to create a live HTML/CSS preview on a page.
But the code will not be given using textareas. The code is going to be fixed in the page (div).
I want the user to be able to alter the code and that will reflect on the live preview box.I have created the page where you can change parts of the script text (for amateurs). You can preview that here :
http://apolosiskos.co.uk/HTML-CSS-EDITOR/index3.html
01) The live preview does not work if I replace the textarea with a div.
02) Even if I use the textareas, the live preview does not work because in my HTML script I am using the codeand the xmp tags.
--> Snippet that works with a textarea but not with a div :
var wpcomment = document.getElementById('WPComment');
wpcomment.blur = wpcomment.onkeypress = function(){
document.getElementById('prevCom').innerHTML = this.value;
}
#prevCom
{
background:#124;
color:#fff;
min-width:20px;
min-height:50px;
font-size:25pt;
}
<textarea name="WPcomment" id="WPComment" placeholder="Add comments:">aaaaa</textarea>
<div id="prevCom"></div>

with no success. Is there any other addEventListener() method I can replace keyup with?
Yes, blur
If you would like to add keydown events on a <div> element, you can do the following:
First, you need to set the tabindex attribute:
<div id="a-div" tabindex="1" />
Then,
(2) Bind to keydown:
$('#mydiv').bind('keydown', function(event) {
//console.log(event.keyCode);
});
If you would like your div to be "focused" from the start:
$(function() {
$('#mydiv').focus();
});

You should place your preview code it within a function, then you can simply call it once the document has loaded.
https://jsfiddle.net/michaelvinall/4053oL1x/1/
The separate issue of your preview only rendering when you press the enter key, is because of the following if statement:
if(e.which == 13 && $(this).val().length > 0)
The e.which == 13 within your if is specifying that the code within the block should only be ran if the key pressed by the user was the enter key (code 13). By removing this portion of each if statement, any key pressed will execute the code within the block:
if($(this).val().length > 0)

Your function is call when keyup is trigger, but no after page load.
You must do it : Define function to call them when 2 different event are fired.
$(function() {
function GetHtml(){
var html = $('.html').val();
return html;
}
function GetCss(){
var Css = $('.css').val();
return Css;
}
var previewRendering = function(){
console.log('kikou');
var targetp = $('#previewTarget')[0].contentWindow.document;
targetp.open();
targetp.close();
var html = GetHtml();
var css = GetCss();
$('body',targetp).append(html);
$('head', targetp).append('<style>' + css + '</style>');
};
$('.innerbox').on("keyup",function(){
previewRendering();
});
$(document).ready(function() {
previewRendering();
});
});
This code can not work because load event is only compatible with this list of HTML tags: body, frame, iframe, img, input type="image", link, script, style
$('.innerbox').load(function()

Related

Use XPath or onClick or onblur to select an element and use jQuery to blur this element

*UPDATE:I am new to jQuery, as well as using XPath, and I am struggling with getting a proper working solution that will blur a dynamically created HTML element. I have an .onblur event hooked up (doesn't work as expected), and have tried using the $(document.activeElement), but my implementation might be incorrect. I would appreciate any help in creating a working solution, that will blur this element (jqInput) when a user clicks anywhere outside the active element. I have added the HTML and jQuery/JavaScript below.
Some ideas I have had:
(1) Use XPath to select a dynamic HTML element (jqInput), and then use jQuery's .onClick method to blur a this element, when a user clicks anywhere outside of the area of the XPath selected element.
(2) Use the $(document.activeElement) to determine where the .onblur should fire:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
I am open to all working solutions. And hopefully this will answer someone else's question in the future.
My challenge: Multiple elements are active, and the .onblur does not fire. See the image below:
NOTE: The <input /> field has focus, as well as the <div> to the left of the (the blue outline). If a user clicks anywhere outside that <input />, the blur must be applied to that element.
My Code: jQuery and JavaScript
This is a code snippet where the variable jqInput and input0 is created:
var jqInput = null;
if (jqHeaderText.next().hasClass("inline-editable"))
{
//Use existing input if it already exists
jqInput = jqHeaderText.next();
}
else
{
//Creaet a new editable header text input
jqInput = $("<input class=\"inline-editable\" type=\"text\"/>").insertAfter(jqHeaderText);
}
var input0 = jqInput.get(0);
//Assign key down event for the input when user preses enter to complete entering of the text
input0.onkeydown = function (e)
{
if (e.keyCode === 13)
{
jqInput.trigger("blur");
e.preventDefault();
e.stopPropagation();
}
};
This is my .onblur event, and my helper method to blur the element:
input0.onblur = function ()
{
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
};
inputOnBlurHandler: function (canvasObj, jqHeaderText, jqInput)
{
// Hide input textbox
jqInput.hide();
// Store the value in the canvas
canvasObj.headingText = jqInput.val();
_layout.updateCanvasControlProperty(canvasObj.instanceid, "Title", canvasObj.headingText, canvasObj.headingText);
// Show header element
jqHeaderText.show();
_layout.$propertiesContent.find(".propertyGridEditWrapper").filter(function ()
{
return $(this).data("propertyName") === "Title";
}).find("input[type=text]").val(canvasObj.headingText); // Update the property grid title input element
}
I have tried using the active element, but I don't think the implementation is correct:
var thisTitle = input0;
var activeElement = $(document.activeElement);
if (thisTitle != activeElement) {
jqInput.hide();
_layout.viewHeaderTextInput.inputOnBlurHandler(canvasObj, jqHeaderText, jqInput);
}
My HTML code:
<div class="panel-header-c">
<div class="panel-header-wrapper">
<div class="panel-header-text" style="display: none;">(Enter View Title)</div><input class="inline-editable" type="text" style="display: block;"><div class="panel-header-controls">
<span></span>
</div>
</div>
</div>
I thank you all in advance.

jQuery slideDown not working on element with dynamically assigned id

EDIT: I cleaned up the code a bit and narrowed down the problem.
So I'm working on a Wordpress site, and I'm trying to incorporate drop-downs into my menu on mobile, which means I have to use jQuery to assign classes and id's to my already existing elements. I have this code that already works on premade HTML, but fails on dynamically created id's.
Here is the code:
...
var menuCount = 0;
var contentCount = 0;
//find the mobile menu items
var submenus = $('[title="submenu"]');
if (submenus.length && submenus.parent('.fusion-mobile-nav-item')) {
console.log(submenus);
submenus.addClass('dropdown-title').append('<i id="dropdown-angle" class="fa fa-angle-down" aria-hidden="true"></i>');
submenus.each(function() {
$(this).attr("href", "#m" + menuCount++);
})
var content = submenus.parent().find('ul.sub-menu');
content.addClass('dropdown-content');
content.each(function() {
$(this).attr("id", "m" + contentCount++);
})
}
$(document).on('click', '.dropdown-title', function(e) {
var currentAttrValue = $(this).attr('href');
if ($(e.target).is('.d-active') || $(e.target).parent('.dropdown-title').is('.d-active')) {
$(this).removeClass('d-active');
$(currentAttrValue).slideUp(300).removeClass('d-open');
} else {
$('.dropdown-title').removeClass('d-active');
$('.dropdown-content').slideUp(300).removeClass('d-open');
$(this).addClass('d-active');
console.log($(currentAttrValue));
//THIS LINE FAILS
$(currentAttrValue).slideDown(300).addClass('d-open');
}
e.preventDefault();
});
I've registered the elements with the class dropdown-title using $(document).on(...) but I can't figure out what I need to do to register the elements with the custom ID's. I've tried putting the event callback inside the .each functions, I've tried making custom events to trigger, but none of them will get the 2nd to last line of code to trigger. There's no errors in the console, and when I console log the selector I get this:
[ul#m0.sub-menu.dropdown-content, context: document, selector: "#m0"]
0
:
ul#m0.sub-menu.dropdown-content
context
:
document
length
:
1
selector
:
"#m0"
proto
:
Object[0]
So jQuery knows the element is there, I just can't figure out how to register it...or maybe it's something I'm not thinking of, I don't know.
If you are creating your elements dynamically, you should be assigning the .on 'click' after creating those elements. Just declare the 'on click' callback code you posted after adding the ids and classes instead of when the page loads, so it gets attached to the elements with .dropdown-title class.
Check this jsFiddle: https://jsfiddle.net/6zayouxc/
EDIT: Your edited JS code works... There also might be some problem with your HTML or CSS, are you hiding your submenus? Make sure you are not making them transparent.
You're trying to call a function for a attribute, instead of the element. You probably want $(this).slideDown(300).addClass('d-active'); (also then you don't need $(this).addClass('d-active'); before)
Inside submenus.each loop add your callback listener.
As you are adding the class dropdown-title dynamically, it was not available at dom loading time, that is why event listener was not attached with those elemnts.
var menuCount = 0;
var contentCount = 0;
//find the mobile menu items
var submenus = $('[title="submenu"]');
if (submenus.length && submenus.parent('.fusion-mobile-nav-item')) {
console.log(submenus);
submenus.addClass('dropdown-title').append('<i id="dropdown-angle" class="fa fa-angle-down" aria-hidden="true"></i>');
submenus.each(function() {
$(this).attr("href", "#m" + menuCount++);
// add callback here
$(this).click( function(e) {
var currentAttrValue = $(this).attr('href');
if ($(e.target).is('.d-active') || $(e.target).parent('.dropdown-title').is('.d-active')) {
$(this).removeClass('d-active');
$(currentAttrValue).slideUp(300).removeClass('d-open');
} else {
$('.dropdown-title').removeClass('d-active');
$('.dropdown-content').slideUp(300).removeClass('d-open');
$(this).addClass('d-active');
console.log($(currentAttrValue));
$(currentAttrValue).slideDown(300).addClass('d-active');
}
e.preventDefault();
});
})
var content = submenus.parent().find('ul.sub-menu');
content.addClass('dropdown-content');
content.each(function() {
$(this).attr("id", "m" + contentCount++);
})
}
Turns out my problem is that jQuery is adding to both the mobile menu and the desktop menu, where the desktop menu is being loaded first when I search for that ID that's the one that jQuery finds. So it turns out I was completely wrong about my suspicions.

jQuery highlight plugin cancels text selection, making copy impossible while also rendering links unclickable

I'm using the jQuery Highlight plugin to select some text on a web page.
I've hooked up selecting and deselecting with mouse events:
document.addEventListener('mouseup', doSelect);
document.addEventListener('mousedown', doDeselect);
The functions are:
function doSelect() {
var selectionRange = window.getSelection();
var selection = selectionRange.toString();
if (selection.trim().length > 0) {
$('body').highlight(selection);
}
}
function doDeselect() {
$('body').unhighlight();
}
Short and easy. The library searches for the selected text and wraps each occurrence in a <span> and so the text stands out.
It's working great, but I have two issues with how it behaves.
The problem is that once the span elements are applied, I cannot click hyperlinks (the ones that were found/selected), they don't react to clicks (I have to deselect the text first).
Once the span elements are added, the original selection is somehow lost, i.e. I cannot copy what I selected with CTRL+C.
These issues can be seen in this jsfiddle.
Why is this happening?
The code
The working demo is available here: jsfiddle
JavaScript
var $body = $('body');
var $copyArea = $('#copyArea');
document.addEventListener('mouseup', doSelect);
document.addEventListener('mousedown', doDeselect);
document.addEventListener('keydown', keyPressHandler);
function keyPressHandler(e) {
if(e.ctrlKey && e.keyCode == 67) {
$copyArea.focus().select();
}
}
function doSelect() {
var selectionRange = window.getSelection();
var selection = selectionRange.toString();
if (selection.trim().length > 0) {
$copyArea.val(selection);
$body.highlight(selection);
}
}
function doDeselect(e) {
var elem = $(e.target).parents('a');
if(elem.length == 0) {
$copyArea.val('');
$body.unhighlight();
}
}
HTML
Sample text to select.
<br/>Sample text to select.
<br/>Sample text to select.
<br/>google.com
google.com
<a href="http://google.com" target="_blank">
<span>
<span>google.com</span>
</span>
</a>
<textarea id="copyArea"></textarea>
CSS
.highlight {
background-color: #FFFF88;
}
#copyArea {
position:fixed;
top:-999px;
height:0px;
}
Part 1 - Clicking through the selection
Presumably, the reason clicking on a highlighted link doesn't work is because the process that disables the highlighting kicks in first and cancels the click.
To bypass that, we implement a condition that checks if the target element of the mousedown event has an a element as ancestor. If that is true, we simply do not execute $body.unhighlight();, allowing the click to pass through and open the link.
function doDeselect(e) {
var elem = $(e.target).parents('a');
if(elem.length == 0) {
$copyArea.val('');
$body.unhighlight();
}
}
Part 2 - Copying the selection
Presumably, again, the reason the selection is lost is because the document is modified by the highlighting, which introduces elements into the DOM.
My first idea was to reapply the selection after the modification was done. This became annoying and I went in a different direction, which allowed me to stumble upon this:
The Definitive Guide to Copying and Pasting in JavaScript
This offered a simple and efficient idea: using an hidden element that could contain selectable text.
Therefore, to allow copying the selected text that we highlighted despite having lost the original selection:
We add a hidden textarea element to our document.
<textarea id="copyArea"></textarea>
We get a reference to that element.
var $copyArea = $('#copyArea');
We add an event handler for the keydown event.
document.addEventListener('keydown', keyPressHandler);
We add the event handler.
function keyPressHandler(e) {
if(e.ctrlKey && e.keyCode == 67) {
$copyArea.focus().select();
}
}
We modify doSelect() to add some logic that will set the selection as the value of the textarea element, in the form of $copyArea.val(selection);.
function doSelect() {
var selectionRange = window.getSelection();
var selection = selectionRange.toString();
if (selection.trim().length > 0) {
$copyArea.val(selection);
$body.highlight(selection);
}
}
What does the handler do ? it captures the combination CTRL+C and focuses on the text in the hidden textarea, which ends up being copied by the keyboard command we just issued.

Getting siblings value with javascript

I create a textarea and a button on a loop based on a certain condition:
while($row_c= mysqli_fetch_array($result_comments))
{
//some code goes here
<textarea type="text" id="pm_text" name="text"></textarea><br>
<button name="send_comment" id="post_comment" class="button" onClick="post_pm_comment()">Post</button>
}
Now in my function "post_pm_comment" I would like to access the text written in the textarea when the post button is clicked.
I tried this, but it only gives me the text of the first textarea and button created:
function post_pm_comment(thidid, pm_id, path, pm,getter)
{
var pm_text = document.getElementById("pm_text").value;
}
What should I do?
Thank you
Your code is outputting an invalid DOM structure, because id values must be unique on the page. You cannot have the same id on more than one element. Remove the id values entirely, you don't need them.
Having done that, the minimal-changes answer is to pass this into your handler:
onClick="post_pm_comment(this)"
...and then in your handler, do the navigation:
function post_pm_comment(postButton)
{
var pm_text;
var textarea = postButton.previousSibling;
while (textarea && textarea.nodeName.toUpperCase() !== "TEXTAREA") {
textarea = textarea.previousSibling;
}
if (textarea) {
pm_text = textarea.value; // Or you may want .innerHTML instead
// Do something with it
}
}
Live Example | Source

CKEditor 4 (replace by class name) get text area value

I am trying to create a preview function in a CKEditor instance.
I'm using CKEditor 4 and am replacing textareas by class name, the only issue I am facing is that I cannot get the value of the textarea using JavaScript, this is what I've tried so far:
function prev()
{
html=document.forms["1_form"]["editor1"].value;
document.getElementById("prev").innerHTML = html;
}
and the CKEditor textarea:
<textarea class="ckeditor" onkeydown="prev()"></textarea>
Why doesn't this work? If I disable CKEditor, the script functions as expected, but not with ckeditor enabled. What am I supposed to do?
Thanks!
Edit:
I am now trying to do it with replace and this is the code I'm using:
CKEDITOR.replace('editor1'); //new ckeditor instance
var editor = CKEDITOR.instances.editor1; //reference to instance
//on `key` event
editor.on('key', function(){
var data = editor.getData(); //reference to ckeditor data
$('#prev').html(data); //update `div` html
});
it works but the only this is, it updates only after the next key is pressed so say the value of the editor is hello world it will show the preview as hello worl what can I do to this code to fix it, please ignore the first set of code.
This is because CKEDITOR replace your <textarea> into <div> with contenteditable="true" attribute and there is no value property in DOM for <div> element.
You need to add event listener to CKEDITOR instance, not to DOM element, for example:
// check if editor is ready
CKEDITOR.on( 'instanceCreated', function( e ) {
// check if DOM is ready
e.editor.on( 'contentDom', function() {
// bind "keydown" event to CKEDITOR
e.editor.document.on('keydown', function( event ) {
// write editor content into "prev" element
document.getElementById( "prev" ).innerHTML = e.editor.getData();
}
);
});
});
For anyone who needs it, here's one way to get the TEXT value of an HTML field (used in this case for a dynamic character counter):
JS ...
CKEDITOR.replace( 'myDoc', {
width: 605,
height: 500
});
setInterval("updateCount()", 500);
function updateCount() {
var str = CKEDITOR.instances.myDoc.getData();
if (str) {
var element = CKEDITOR.dom.element.createFromHtml( str );
var no_html = element.getText();
$('#myDoc_length').html( no_html.length );
}
}
... with HTML ...
<textarea id="myDoc"></textarea>
<span id="myDoc_length">0</span> characters

Categories

Resources