HTML, CSS, JS in separate area not affecting entire website - javascript

I want to put up tutorials on my website. In order for the user to see some examples I want to output the code (HTML, CSS, JavaScript) plus the result.
So my markup for a the code box, including a little example, looks like the following:
<div class="code-box">
<code class="code-section lang-html">
<!-- Example HTML code -->
<div> <span>This</span> is an example </div>
</code>
<code class="code-section lang-css">
/* Example CSS code */
div{
font-size: 120%;
}
div span{
font-size: 130%;
}
</code>
<code class="code-section lang-js">
/* Example jQuery code */
$("div").hover(function(){
$(this).find("span").css("fontSize", "140%");
}, function(){
$(this).find("span").css("fontSize", "130%");
});
</code>
<code class="code-section lang-result">
<!-- Example result -->
</code>
</div>
Via JavaScript/jQuery I escape necessary characters like "<" that are inside the code tags, so that the actual code is printed as text, and not evaluated as eg HTML.
No problems so far.
My problem arises when it comes to the "result" part, where I actually want the written code to be evaluated as code. So far I got it to work with jQuery:
Unescaping the HTML characters, putting the css stuff inside a tag, and the JS inside a tag. The problem now being that the "new" Css and JS will also apply to the rest of the website <-- definitely not what I want. But whats the solution?
I found an article about "scoped css":
Putting your css inside a tag will make the css apply to only the parent and its children elements. But support is low and this would only help the CSS, not the JS.
Givng my example code an id or class is simple, but not something desirable for each tutorial I wanna put up there, neither for writing nor for reading.
I would need to wrap that tutorial-code in a bubble, separated from my website's code. Kind of like an iframe or such. I would really appreciate any ideas or comments on this.
Thanks in advance.

Seems to me you are tryingf to achieve something like this.
var parent = $(".code-box.example-1"),
parentC = parent.attr("class").match(/example-\d+/),
htmlSnip = parent.find(".lang-html > pre").text().replace("<", "<").replace(">", ">"),
cssSnip = parent.find(".lang-css > pre").html().replace(/(\/\*.*\*\/\n)|(^\s*)/gm, "").replace(/^([^{\n]+)(?={$)/gm, "." + parentC + " .lang-result " + "$1"),
jsSnip = parent.find(".lang-js > pre").html().replace(/(\/\*.*\*\/\n)|(^\s*)/gm, "").replace(/(\$\(")([^"]+)("\))/gm, "$1." + parentC + " .lang-result " + "$2 $3");
parent.find(".lang-result").html(htmlSnip).prepend("<style>" + cssSnip + "</style>" + "<script>" + jsSnip + "<\/script>");
If this is what you are looking for and you require additiional information, let me know. The key is to add a class per code example you are using, here .example-1.
For some regex explanations, I refer you to regex101. It's a great tool with a very good explanation of all code in the right window. As you may know, you can use RegEx to match, but also to substitute. In the tool, at the bottom of the window, there's "Substitution". Click on it, to open the window. The Regex at the top of the page will evaluate the "Test string", and substitute that string with your input in "Substitution". The result is in the bottom most field.
CSS substitution:
First, let's remove the CSS comment AND all spatial characters that might be in our way (removing means "replace by an empty string") - example: https://regex101.com/r/cL0hL3/2
The result will be something like this:
div{
font-size: 120%;
}
div span{
font-size: 130%;
}
But we want to make this style more specific. We want it to only apply to the div that's inside .lang-result which, in turn, is part of the parent container .example-1. Therefore we need to add some things to the CSS. A useful thing to use is the dollar sign $1 which in substitution will return the captured group (which in regex is in parentheses). $1 returns the first captured group, $2 the second one and so on. Here's an example: https://regex101.com/r/cL0hL3/3. The result will then look how we want:
.parent-class .lang-result div{
font-size: 120%;
}
.parent-class .lang-result div span{
font-size: 130%;
}
JS substitution: the first part is identical to the CSS regex: remove the comment (doesn't work with // comments only with /*...*/). That will lead to:
$("div").hover(function(){
$(this).find("span").css("fontSize", "140%");
}, function(){
$(this).find("span").css("fontSize", "130%");
});
Then we'll have to change the base selector (the div) the only the div in our result (smilar to what we did in the case for CSS). This is a good time to show what capturing groups do (you can do this without using three groups, but it's a good way to illustrate its possibilities:
We replace this
(\$\(")([^"]+)("\))
with this
$1.parent-class $2$3
It's crucial to see how $1 is the first group (\$\(") (literally $(", $2 is whichever selector was already there, and $3 is literally "). Put that all together, and you have a new jQuery object.
See it in action here. https://regex101.com/r/cL0hL3/4
Again there are many other ways to do that in regex, probably more efficient as well, but it's a good showcase. I didn't go into too much detail, but you can take the right window of the website as an explanation for what your regular expression does.
If you want to apply this to multiple elements without manually added classes, you can do it like so: http://jsfiddle.net/0c1np9uL/2/
$(".code-box").each(function () {
var parent = $(this);
parent.addClass("example-" + parent.index());
var parentC = parent.attr("class").match(/example-\d+/),
htmlSnip = parent.find(".lang-html > pre").text().replace("<", "<").replace(">", ">"),
cssSnip = parent.find(".lang-css > pre").html().replace(/(\/\*.*\*\/\n)|(^\s*)/gm, "").replace(/^([^{\n]+)(?={$)/gm, "." + parentC + " .lang-result " + "$1"),
jsSnip = parent.find(".lang-js > pre").html().replace(/(\/\*.*\*\/\n)|(^\s*)/gm, "").replace(/(\$\(")([^"]+)("\))/gm, "$1." + parentC + " .lang-result " + "$2 $3");
parent.find(".lang-result").html(htmlSnip).prepend("<style>" + cssSnip + "</style>" + "<script>" + jsSnip + "<\/script>");
});

Be more specific with your selections, instead of having $("div") use $("#result div"), also a nice thing you can do with jQuery instead of wraping it, you can use if so: if($("#result div").attr("on") == "on") {//do stuff}

You can use textareas to display your code. As for the "results" section, an iframe is probably your best bet.
.code{
border:0;
resize: none;
height:100px;
width:300px;
overflow:hidden;
}
<textarea class="code">
<!-- Example HTML code -->
<div> <span>This</span> is an example </div>
</textarea><br>
<textarea class="code">
/* Example CSS code */
div{
font-size: 120%;
}
div span{
font-size: 130%;
}
</textarea><br>
<textarea class="code">
/* Example jQuery code */
$("div").hover(function(){
$(this).find("span").css("fontSize", "140%");
}, function(){
$(this).find("span").css("fontSize", "130%");
});
</textarea>

Related

Adding Line Numbers To Pre-formatted Text

I have a body of text that I show in a web page within some <pre> tags. I would like to add a column to the left of this text body to show the line number of the text.
The body of text is retrieved by using [PHP] file_get_contents() so I am just echo-ing a string within the <pre> tags.
I imagine this can be accomplished with JavaScript but I have yet to find a solution.
Solutions I have seen on here usually use a library or CSS. The CSS method would be great but this method seems to require that each line of the body text have its own corresponding tag (eg <p> or <span>).
// Example of CSS Solution
p:not(:first-child):before {
counter-increment: custom-counter+1;
content: counter(custom-counter)". ";
display: table-cell;
}
p:first-child:before {
display: table-cell;
content: '1. '
}
I would like to avoid having to create a DOM element (before load) line by line. That said, if that is the best solution I simply want to know the "preferred" way to go about this.
How could I accomplish this using JavaScript / jQuery?
One simple solution would be to split the string on "\n" with javascript to get each line append the line numbers then re-join them together. This will only work if you are using <pre> tags where newlines are literal newlines.
JsFiddle
let text = document.getElementById("test").innerHTML;
let lines = text.split("\n");
for (let i=0;i<lines.length;i++) {
lines[i] = (i+1)+" "+lines[i];
}
text = lines.join("\n");
document.getElementById("test").innerHTML = text;

How do I add a default text to the beginning of an html text area?

Im building a personal little social network. As part of the design, all statuses should begin with a default text that shouldn't change, similar to "Hi, my name is…" and then the user finishes the rest. Kind of like an HTML5 placeholder that doesn't go away. What would be the best way to accomplish this?
Please refer this fiddle
If it serves the purpose, then please find the code below.
Markup:
<textarea id='status'>
Hi, my name is...
</textarea>
JavaScript:
document.querySelector('#status').addEventListener('input', function(e){
var defaultText = 'Hi, my name is...',
defaultTextLength = defaultText.length;
if(this.selectionStart === this.selectionEnd && this.selectionStart defaultTextLength {
this.value = defaultText;
}
});
Note: For some dumb reason, I assumed jQuery (note that you do not need jQuery for this, but makes it a little easier).
Here is one solution uses a combination of text-indent and an absolutely positioned <span> (for the prefix part).
Demo: http://jsfiddle.net/4YzZy/
$('textarea.withprefix').each(function() {
var prefix = $('<span/>')
.text($(this).data('prefix'))
.addClass('prefix')
.appendTo('body')
.css({
left: $(this).position().left + 'px',
top: $(this).position().top + 'px',
});
$(this).css({textIndent: prefix.outerWidth() + 'px'});
});
textarea, span.prefix {
font-family: arial; /* change these as needed, but ensure that the textarea and the span use the same font */
font-size: 1em;
font-weight: normal;
padding: 2px;
border-width: 1px;
}
span.prefix {
position:absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="withprefix" data-prefix="Hi There, "></textarea>
If you want to use javascript to perform your task, you can set up some event listeners and then when the user makes a change, check to see if that change affected the text you want changed. Sarbbottam's new code does this, but it will replace any text you have already typed if you modify the original text. I have fixed this by saving the previous value of the textarea.
HTML:
<textarea id="text">Hello, my name is </textarea>
Javascript:
var defaultText = "Hello, my name is ";
var valueOnKeyDown = new Array();
document.getElementById("text").addEventListener("keydown", function() {
valueOnKeyDown.push(this.value);
}, false);
document.getElementById("text").addEventListener("keyup", function(e) {
if(valueOnKeyDown[0].substring(0, defaultText.length) != this.value.substring(0, defaultText.length)) {
this.value = valueOnKeyDown[0];
}
valueOnKeyDown = new Array();
}, false);
And of course a working demo.
Another option that may work that is not mentioned in the other answers is to set up a keydown/keypress event listener and get the caret position in the textarea using javascript. If it is less than the length of your default text, you just call event.preventDefault(). The main disadvantage to this is that it may not be possible to make this completely cross-browser compatible.
If the goal is that the user cannot change this text then you can do a couple of things:
add the text outside of the textarea (above it for instance)
Add the text outside of the textarea but place it behind the textarea using css. You can make the textarea transparent so the user can see the text. The problem there would be that the text the user types can fall over the text you placed in the background
Put it in a background image of the textarea
Place the text inside the textarea (<textarea>Hi, my name is </textarea>) and use JavaScript to test for what has been typed and change the text if it changes into something that you do not want. There are masking plugins that you can use to do this.
The best options would be the first option and the forth. I'd go the first as it is by far the easiest

HTML DOM manipulation : properly replace tag by heading tag

I want to replace some tag-inside-a-paragraph-tag by a heading-tag-enclosed-by-a-paragraph tag. This would result in proper W3C coding, but it seems that jQuery is not able to manipulate the DOM in the right way!? I tried several ways of (jQuery) coding, but i can't get it to work ..
Original code:
<p>some text <span>replace me</span> some more text</p>
Desired code:
<p>some text</p><h2>my heading</h2><p>some more text</p>
Resulting code by jQuery replaceWith():
<p>some text<p></p><h2>my heading</h2><p></p>some more text</p>
Demo: http://jsfiddle.net/foleox/J43rN/4/
In this demo, look at "make H2 custom" : i expect this to work (it's a logical replace statement), but it results in adding two empty p-tags .. The other 2 functions ("make code" and "make H2 pure") are for reference.
Officially the W3C definition states that any heading tag should not be inside a paragraph tag - you can check this by doing a W3C validation. So, why does jQuery add empty paragraph tags? Does anybody know a way to achieve this? Am i mistaken somehow?
You can achieve this with this code. However it's pretty ugly:
$('.replaceMe').each(function() {
var $parent = $(this).parent(),
$h2 = $(this).before('$sep$').wrap('<h2>').parent().insertAfter($parent);
var split = $parent.html().split('$sep$');
$parent.before('<p>' + split[0] + '</p>');
$h2.after('<p>' + split[1] + '</p>');
$parent.remove();
});
http://jsfiddle.net/J43rN/5/
If you read the jQuery docs, you will find:
When the parameter has a single tag (with optional closing tag or
quick-closing) — $("<img />") or $("<img>"), $("<a></a>") or $("<a>")
— jQuery creates the element using the native JavaScript
createElement() function.
So that is exactly what it is doing. And as I said in my comment, you can't change a parent node from a child node, you're altering the DOM here, not HTML code. So you'll need to either use replaceWith on the parent node and replace everything or use something like remove and append to split it up in multiple elements which you append after each other.
Try this:
var temp = "<p>some text <span>replace me</span> some more text</p>";
temp.replace(/(\<span\>replace me\<\/span\>)/gi, '</p><h2>my heading</h2><p>');
This will do a case insensitive replace for multiple occurences as well.
Read more about capturing groups here
Original credit to this question!
Please try this I have updated the http://jsfiddle.net/J43rN/6/ example by the below java script function please check I hope it will work for you
function fnMakeCode() {
$('#myP #replaceMe').html("<code id='replaceMe'>My Code</code>");
}
function fnMakeH2pure() {
$('#myP #replaceMe').html("<h2 id='replaceMe'>My H2 pure</h2>");
}
function fnMakeH2custom() {
$('#replaceMe').html("<p></p>").html("<h2>My H2 custom</h2>");
}

How To Display only First Word of H2 Heading With JavaScript or CSS

I Just wanted to know, is there any way though which we can display only First Word from h2 Heading.
For Example:
In the source code it should look like this
<h2> Stackoverflow is an Ideal Place</h2>
However, on live website it should look like this
Stackoverflow
Basically, we want to display the FIRST WORD from the whole heading. However, Search engine should read the complete title.
Try this way
$(document).ready(function(){
var ac = $("#ac").text().split(' ');
$("#ac").text(ac[0])
})
You cannot do this with just CSS. You have pseudo-element selector for first letter, first line, but not first word.
You can set a width so that only the first word is visible (and use overflow:hidden of course), but that's not foolproof for all font families and sizes.
Finally you can do it with plain JavaScript or jQuery.
Plain JS:
var el = document.getElementById("ac");
el.innerHTML = el.innerHTML.split(/\s/)[0];
jQuery:
$("#ac").html(function(i, h) { return h.split(/\s/)[0];});
This will do what you want it to...
<h2 id="ac">Stackoverflow is an Ideal Place</h2>​
$('#ac').html( function(i, h) {
var words = h.split(/\s/);
return ' <h2>' + words[0] + '</h2>';
});​

jquery replace string from html()

I am trying to replace a CSS style in the following code:
var theHTML = this.html();
theHTML.replace("style=\"display:none;\"", "style=\"display:inline;\"");
alert(theHTML);
The html looks like this:
<IMG SRC="picturesFromServer.asp?PhotoId=365481" style="display:none;">
However once i check to see if it changed it or not it keeps displaying none instead of inline. I'm just trying to make it visible before i print it.
You could use JQuery's .css() method:
$("img").css("display","inline");
EDIT : If what you are trying to accomplish is, get the img tag inside this and append it somewhere else, with display:none; do this.
http://jsfiddle.net/tL3Uf/
HTML
​<div id="mainContainer">
<img src="http://imgh.us/business-online.jpg" style="display:none;" /> </div>
​<div id="destination"></div>​​​​​​​​​​​​​​​​​​
Javascript
​$(function(){
var $img = $("#mainContainer img").clone();
$img.show(0).appendTo('#destination');
});​
CSS
#incase image doesnt load
img{
padding: 10px;
background: #f00;
}​
I'm really not a jQuery master, but in Javascript are strings immutable? Should you try something like
theHtml = theHtml.replace(...)
replace the first two lines of the given code with this line :
$(this).find("img").css("display","inline");
The string .replace() method doesn't update the string you call it on, it returns a new string - so that's why your alert(theHTML) continues to display the original string. If you said this:
theHTML = theHTML.replace("style=\"display:none;\"", "style=\"display:inline;\"")
Then alert(theHTML) would show the replaced version.
However, that still won't have any effect on the actual img element, because it is still just a manipulation of a string variable that has no connection to your element. To actually make the img element visible you'd have to replace it with a new element generated from your string, which is a hassle, or you can just set the display property directly:
$(this).css("display", "inline");
Note also that your original code said this.html() - it seems unlikely that this would be a jQuery object that you can call the jQuery .html() method on, it is more likely to be the DOM element itself in which case you'd need to say $(this).html(). So if any of the answers don't work it might be related to how you are getting the this reference to the img element in the first place - might be helpful if you could update your question to show that.
Note also that if the idea here is for the img element to appear in printed output but not otherwise you can do that with CSS:
#media all {
img.printOnly { display: none; }
}
#media print {
img.printOnly { display: inline; }
}
Give the "printOnly" class (or whatever classname you want to use) to any elements that should appear for print only. Or specify by id. Whatever.

Categories