Brief
I'm working on my jQuery Syntax Highlight Script and I want to implement a beautifier which minifies the code then beautifies it by adding new lines and tab spaces where needed.
I'm working on the CSS section at the moment and I'm having trouble adding the tab spaces to each line between the { and }.
Live Examples:
> View On CodePen
> View Below
code = $(".input").html().trim();
if (code) {
code = code
// REMOVE TAB SPACES
.replace(/( )/gi,'')
// REMOVE NEW LINES
.replace(/[\n\r]/g,'')
// REMOVE SPACES BETWEEN SECTIONS
.replace(/(;|{|})(\s+)([^ \s+])/g,'$1$3')
.replace(/(;|{|})(\s+)([^ \s+])/g,'$1$3')
.replace(/(\*\/)(\s+)([^ \s+])/g,'$1$3');
}
$('.minified').text(code);
minified = $('.minified').html();
if (minified) {
minified = minified
.replace(/(\;|\}|\{)/gi,'$1\n\r')
.replace(/((\/\*)(| )([^"'\s\n]+)(| )(\*\/))/gi,'\n\r$1\n\r');
var level = 0;
var lines = minified.split("\n");
$.each(lines, function(n, elem) {
last = elem[elem.length -1]
if (last === "{") { level = level + 1; }
else if (last === "}") { level = level - 1; }
else {
var tab = " ".repeat(level);
elem = tab + elem;
}
});
}
$('.beautified').text(minified);
.wrap {
float:left;
width: 400px;
margin: 20px;
}
.wrap > h1 {
text-align: center;
}
pre {
float: left;
width:100%;;
height: 400px;
border: 1px solid #000000;
overflow: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="wrap">
<h1>INPUT</H1>
<pre class="input">
div.highlight {
background:#FFFFFF;
border:1px solid #E0E0E0;
font-family:"Courier New",Courier,monospace;
overflow: hidden;
}
div.highlight pre{
width: 100%;
overflow: auto;
padding:0;
margin:0;
font-size:13px;
clear: both;
}
/* tabs */
div.highlight ul.tabs {
overflow: hidden;
padding: 5px 0 5px 0;
margin: 0;
list-style: none;
border-bottom: 1px solid #E0E0E0;
width: 100%;
}
div.highlight ul.tabs li {
padding: 0;
margin: 0 5px;
float: left;
background: none;
border-bottom: 1px dashed #CCC;
line-height:1.0em;
color: #CCC;
cursor: pointer;
}
div.highlight ul.tabs li.active {
border-bottom: none;
cursor: default;
}
div.element {
flex-direction: row;
flex-wrap: nowrap;
flex-flow: column-reverse wrap;
}
</pre>
</div>
<div class="wrap">
<h1>MINIFIED</H1>
<pre class="minified"></pre>
</div>
<div class="wrap">
<h1>BEAUTIFIED</H1>
<pre class="beautified"></pre>
</div>
Questions
How do I correctly loop through each line and if the line doesn't end with an opening ( { ) or closing ( } ) curly bracket, indent the code to the with either a tab our four white spaces timed by the level?
UPDATE 1). A Working Version Via Regex For CSS One Indent Only
This version will only work for one indent and for CSS only, however
I'd like to get my other version working to use for other languages
and to indent further for #media queries, indenting the code further
within:
> Example on CodePen
> Example Below
>
> code = $(".input").html().trim();
>
> if (code) {
> code = code
> // REMOVE TAB SPACES
> .replace(/( )/gi,'')
> // REMOVE NEW LINES
> .replace(/[\n\r]/g,'')
> // REMOVE SPACES BETWEEN SECTIONS
> .replace(/(;|{|})(\s+)([^ \s+])/g,'$1$3')
> .replace(/(;|{|})(\s+)([^ \s+])/g,'$1$3')
> .replace(/(\*\/)(\s+)([^ \s+])/g,'$1$3');
> }
> $('.minified').text(code);
>
> minified = $('.minified').html();
>
> if (minified) {
> minified = minified
> .replace(/(\;|\}|\{)/gi,'$1\n\r')
> .replace(/((\/\*)(| )([^"'\s\n]+)(| )(\*\/))/gi,'\n\r$1\n\r')
> .replace(/(([a-zA-Z0-9 -]+)(:)([a-zA-Z0-9 -#%"-., ]+)(;))/g,' $1');
> }
> $('.beautified').text(minified);
>
>
>
> .wrap {
> float:left;
> width: 400px;
> margin: 20px;
> }
> .wrap > h1 {
> text-align: center;
> }
> pre {
> float: left;
> width:100%;;
> height: 400px;
> border: 1px solid #000000;
> overflow: auto;
> }
>
> pre.minified {
> height: 50px;
> }
>
>
>
> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
> <div class="wrap">
> <h1>INPUT</H1>
> <pre class="input">
> div.highlight {
> background:#FFFFFF;
> border:1px solid #E0E0E0;
> font-family:"Courier New",Courier,monospace;
> overflow: hidden;
> }
> div.highlight pre{
> width: 100%;
> overflow: auto;
> padding:0;
> margin:0;
> font-size:13px;
> clear: both;
> }
>
> /* tabs */
> div.highlight ul.tabs {
> overflow: hidden;
> padding: 5px 0 5px 0;
> margin: 0;
> list-style: none;
> border-bottom: 1px solid #E0E0E0;
> width: 100%;
> }
> div.highlight ul.tabs li {
> padding: 0;
> margin: 0 5px;
> float: left;
> background: none;
> border-bottom: 1px dashed #CCC;
> line-height:1.0em;
> color: #CCC;
> cursor: pointer;
> }
> div.highlight ul.tabs li.active {
> border-bottom: none;
> cursor: default;
> }
> div.element {
> flex-direction: row;
> flex-wrap: nowrap;
> flex-flow: column-reverse wrap;
> }
> </pre>
> </div>
> <div class="wrap">
> <h1>MINIFIED</H1>
> <pre class="minified"></pre>
> </div>
> <div class="wrap">
> <h1>BEAUTIFIED</H1>
> <pre class="beautified"></pre>
> </div>
>
>
You're close. In the code you have, elem is a local variable inside the function you pass to each. You modify it to be indented, but then the program forgets about it when the function returns at the end of the iteration. You'll want to assign it back to lines, probably with lines[n] = elem. Edit: $.map may be more appropriate.
Then, another variant of the same problem occurs. lines is updated, but minified is still the same. You can use minified = lines.join('\n') to glue the pieces back together and update minified.
Your indentation algorithm isn't working for various reasons.
1) You need to write in the lines array like so: lines[n] = tab + elem;
2) You mistakenly assigned minified instead of lines to $('.beautified')
3) Your code was not indenting deeper than 1 level. I modified it to indent at any depth, and added a codepen example to demonstrate this.
$.each(lines, function(n, elem) {
var last = elem[elem.length -1];
if (last === "}") {
level--;
}
var tab = " ".repeat(level);
lines[n] = tab + elem + "\n";
if (last === "{") {
level++;
}
});
lines = lines.join('');
$('.beautified').text(lines);
http://codepen.io/anon/pen/NdezxM
Related
I have a nav which contains letters and sections which are associated to letters in the nav.
When a user scrolls to a section, I want to addClass active to that letter. For example:
User scrolls to section with the id of a, the anchor with the data-letter with a will be active.
Currently, on scroll, all my letters in the nav become active and this is because it's always thinking it's on section A.
Demo:
$(function() {
$(window).scroll(function() {
// step 1: get id of section
var visible_section = $('section:visible'), id = visible_section.attr('id');
console.log(id);
// step 2: add class where id and data-letter match
$("nav a").removeClass("active");
$("nav a[data-letter='"+id+"']").addClass("active");
});
});
.nav {
background: grey;
padding: 30px 15px;
position: fixed;
top: 0;
width: 100%;
}
.nav a {
padding: 0 15px;
text-decoration: none;
}
.nav a:hover {
background: black;
color: white;
}
.nav a.active {
background: black;
color: white;
}
.sections {
margin-top: 100px;
}
section {
padding: 200px 0;
color: red;
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
}
section:nth-child(odd) {
background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<main>
<nav class="nav">
A
B
C
D
</nav>
<div class="sections">
<section id="a">A</section>
<section id="b">B</section>
<section id="c">C</section>
<section id="d">D</section>
</div>
</main>
FYI: https://stackoverflow.com/a/5354536/4571790
function isVisible(elm) {
var rect = elm.getBoundingClientRect();
var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
return !(rect.bottom < 0 || rect.top - viewHeight >= 0);
}
$(function() {
$(window).scroll(function() {
// step 1: get id of section
var visible_section = $('section:visible'), id="";
// this code will find which section is the first visible
$(".sections").find("section").each((i,a)=>id==""?(isVisible(a)?id=$(a).attr("id"):id):id);
$("#result").html(id +" is visible now");
//console.log(id);
// step 2: add class where id and data-letter match
$("nav a").removeClass("active");
$("nav a[data-letter='"+id+"']").addClass("active");
});
});
.nav {
background: grey;
padding: 30px 15px;
position: fixed;
top: 0;
width: 100%;
}
.nav a {
padding: 0 15px;
text-decoration: none;
}
.nav a:hover {
background: black;
color: white;
}
.nav a.active {
background: black;
color: white;
}
.sections {
margin-top: 100px;
}
section {
padding: 200px 0;
color: red;
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
}
section:nth-child(odd) {
background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<main>
<nav class="nav">
A
B
C
D
<span id="result"></span>
</nav>
<div class="sections">
<section id="a">A</section>
<section id="b">B</section>
<section id="c">C</section>
<section id="d">D</section>
</div>
</main>
You should differentiate the nav tabs by setting their data-letter as you described to a, b, c and d:
<nav class="nav">
A
B
C
D
</nav>
All your nav become active not because it always thinks it's on a, but because all data-letter are set to a.
You can change ratio from 0.1 to 1:
$(function () {
let ratio = 0.6; // From 0.1 to 1
$(window).scroll(function () {
let sections = $('.sections section');
let scrollTop = $(window).scrollTop();
let screen_height = $(window).height();
$.each(sections, function () {
let top = $(this).offset().top;
let calc = (top - scrollTop) / screen_height;
if (calc >= (ratio * -1) && calc <= ratio) {
let id = $(this).attr('id');
$("nav a").removeClass("active");
$("nav a[data-letter='" + id + "']").addClass("active");
//console.log(`${id} is Active`);
}
});
});
});
.nav {
background: grey;
padding: 30px 15px;
position: fixed;
top: 0;
width: 100%;
}
.nav a {
padding: 0 15px;
text-decoration: none;
}
.nav a:hover {
background: black;
color: white;
}
.nav a.active {
background: black;
color: white;
}
.sections {
margin-top: 100px;
}
section {
padding: 200px 0;
color: red;
display: flex;
align-items: center;
justify-content: center;
font-size: 50px;
}
section:nth-child(odd) {
background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<main>
<nav class="nav">
A
B
C
D
</nav>
<div class="sections">
<section id="a">A</section>
<section id="b">B</section>
<section id="c">C</section>
<section id="d">D</section>
</div>
</main>
Your confusion seems to stem from the fact that you have an inaccurate understanding of what :visible selector in jQuery selects. From documentation: "Elements are considered visible if they consume space in the document. Visible elements have a width or height that is greater than zero." By this definition, all of the sections are "visible".
To achieve your use case you need to calculate coordinates of individual sections and compare them with scroll position in the document. The following appears to do what you are looking for (try it out here):
$(function () {
$(window).scroll(function () {
// determine element that is fully in the viewport
const fullyVisibleSection = Array.from(document.querySelectorAll('section')).find((section) => {
const topY = section.offsetTop;
const bottomY = topY + section.offsetHeight;
return (topY >= window.scrollY) && (bottomY <= (window.scrollY + window.innerHeight));
});
// only update classes if the section is fully visible
if (fullyVisibleSection) {
$("nav a").removeClass("active");
// add class where id and data-letter match
$("nav a[data-letter='" + fullyVisibleSection.id + "']").addClass("active");
}
});
});
See my demo below. When you click the buttons, the font size changes and this is making the div box grow and shrink. I don't want the box size to change.
How do I prevent this?
$('#button-plus').click(() => {
var currentFontSize = parseInt($('.main > span').css('font-size'));
$('.main > span').css('font-size', currentFontSize + 5 + 'px');
});
$('#button-minus').click(() => {
var currentFontSize = parseInt($('.main > span').css('font-size'));
$('.main > span').css('font-size', (currentFontSize - 5) + 'px');
})
.main {
text-align: center;
width: 200px;
max-width: 200px;
overflow: overflow;
padding: 10px 5px;
border: 2px solid #bbb;
}
.main > span {
font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
<span>Some Text</span>
</div>
<button id="button-plus">+</button>
<button id="button-minus">-</button>
It seems you are trying to create a fixed width and height for your div box. You can simply fix this by including a height to your .main class.
.main {
text-align: center;
width: 200px;
height: 20px; // <-- specify a height.
max-width: 200px;
overflow: overflow;
padding: 10px 5px;
border: 2px solid #bbb;
}
.main > span {
font-size: 12px;
}
Not totally clear what behavior you are expecting.
One approach might be take the current height on page load and apply it inline so it becomes fixed height using:
$('.main').height((_,curr) => curr)
Another alternative is using css flex box rules
$('#button-plus').click(() => {
var currentFontSize = parseInt($('.main > span').css('font-size'));
$('.main > span').css('font-size', currentFontSize + 5 + 'px');
});
$('#button-minus').click(() => {
var currentFontSize = parseInt($('.main > span').css('font-size'));
$('.main > span').css('font-size', (currentFontSize - 5) + 'px');
});
$('.main').height((_,curr) => curr)
.main {
text-align: center;
width: 200px;
max-width: 200px;
overflow: auto;
padding: 10px 5px;
border: 2px solid #bbb;
}
.main > span {
font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
<span>Some Text</span>
</div>
<button id="button-plus">+</button>
<button id="button-minus">-</button>
$('#button-plus').click(() => {
var currentFontSize = parseInt($('.main > span').css('font-size'));
$('.main > span').css('font-size', currentFontSize + 5 + 'px');
});
$('#button-minus').click(() => {
var currentFontSize = parseInt($('.main > span').css('font-size'));
$('.main > span').css('font-size', (currentFontSize - 5) + 'px');
})
.main {
text-align: center;
width: 200px;
height: 400px;
overflow: overflow;
padding: 10px 5px;
border: 2px solid #bbb;
}
.main > span {
font-size: 12px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
<span>Some Text</span>
</div>
<button id="button-plus">+</button>
<button id="button-minus">-</button>
I'm following this tutorial on building a javascript calculator to learn a little more about web development. The CSS code below adds styling when pressing an operator (+, -, *, /) key. When an operator key is pressed, it should darken until another key is pressed to show that the operator is "active". However, when pressing the same operator key over and over again, there should still be some visual indication of the repeated clicking.
const calculator = document.querySelector(".calculator");
const keys = calculator.querySelector(".calculator__keys");
const display = document.querySelector(".calculator__display");
keys.addEventListener('click', e => {
if (e.target.matches('button')) {
const key = e.target;
const action = key.dataset.action;
const keyValue = key.textContent;
const displayNum = display.textContent;
Array.from(key.parentNode.children).forEach(k=>k.classList.remove('is-depressed'));
if (!action) {
if (displayNum === "0" || calculator.dataset.previousKeyType === "operator") {
display.textContent = keyValue;
calculator.dataset.previousKeyType = null;
} else {
display.textContent = displayNum + keyValue;
}
calculator.dataset.previousKeyType = "number";
console.log("Number key")
}
if (action === "decimal") {
if (calculator.dataset.previousKeyType === "operator") {
display.textContent = "0.";
calculator.dataset.previousKeyType = "decimal";
} else if (!displayNum.includes(".")) {
display.textContent += ".";
}
}
if (
action === 'add' ||
action === 'subtract' ||
action === 'multiply' ||
action === 'divide'
) {
calculator.dataset.previousKeyType = "operator";
calculator.dataset.previousNum = displayNum;
calculator.dataset.operator = action;
key.classList.add("is-depressed");
}
if (action === "clear") {
calculator.dataset.previousKeyType = "clear";
console.log("AC key");
}
if (action === "calculate") {
calculator.dataset.previousKeyType = "calculate";
const secondVal = displayNum;
const firstVal = calculator.dataset.previousNum;
const operator = calculator.dataset.operator;
display.textContent = calculate(firstVal, secondVal, operator);
}
}
});
function calculate(firstVal, secondVal, operator) {
let num1 = +firstVal;
let num2 = +secondVal;
if (operator === "add") {
return num1 + num2;
} else if (operator === "subtract") {
return num1 - num2;
} else if (operator === "multiply") {
return num1 * num2;
} else {
return num1 / num2;
}
}
// NOTE: You don't need to mess around with
// CSS to follow the tutorial. Focus on the
// JavaScript instead!
// =========================
// Some personal resets
html {
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
body {
margin: 0;
}
/* Responsive Images */
embed,
iframe,
img,
object,
video {
max-width: 100%;
}
h1,
h2,
h3,
h4,
h5,
h6,
ul,
ol,
li,
p,
pre,
blockquote,
figure,
hr {
margin: 0;
padding-right: 0;
padding-left: 0;
}
a {
text-decoration: none;
}
a:focus {
outline: none;
}
h1,
h2,
h3,
h4,
h5,
h6 {
display: block;
}
/* Removes all decimals and discs from lists */
ol,
ul {
list-style: none;
}
/*
* Completely resets form items
* ----------------------------
* Super hard reset that removes all borders
* and radiuses of all form items (including
* checkboxes and radios)
*/
input,
textarea,
button {
border: 0;
border-radius: 0;
background-color: transparent;
font-size: inherit;
font-family: inherit;
font-weight: inherit;
outline: none;
appearance: none;
text-align: left;
}
input:hover,
input:active,
input:focus,
textarea:hover,
textarea:active,
textarea:focus,
button:hover,
button:active,
button:focus {
outline: none;
}
:root {
font-family: Helvetica, Arial, sans-serif;
}
html {
font-size: 175%;
font-weight: 300;
line-height: 1.3;
}
body {
align-items: center;
background-image: linear-gradient(236deg, #74ebd5, #acb6e5);
display: flex;
height: 100vh;
justify-content: center;
}
.container {
max-width: 20em;
}
.container > p {
text-align: center;
}
.calculator {
border-radius: 12px;
box-shadow: 0 0 40px 0px rgba(0, 0, 0, 0.15);
margin-left: auto;
margin-right: auto;
margin-top: 2em;
max-width: 15em;
overflow: hidden;
}
.calculator__display {
background-color: #222222;
color: #fff;
font-size: 1.714285714em;
padding: 0.5em 0.75em;
text-align: right;
}
.calculator__keys {
background-color: #999;
display: grid;
grid-gap: 1px;
grid-template-columns: repeat(4, 1fr);
}
.calculator__keys > * {
background-color: #fff;
padding: 0.5em 1.25em;
position: relative;
text-align: center;
}
.calculator__keys > *:active::after,
.calculator__keys > .is-depressed::before {
background-color: rgba(0, 0, 0, 0.2);
bottom: 0;
box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.5) inset;
content: "";
left: 0;
opacity: 0.3;
position: absolute;
right: 0;
top: 0;
z-index: 1;
}
.key--operator {
background-color: #eee;
}
.key--equal {
background-image: linear-gradient(to bottom, #fe886a, #ff7033);
grid-column: -2;
grid-row: 2 / span 4;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Calculator</title>
<link rel="stylesheet" href="calculator.css" type="text/css">
<script type="text/javascript" src="calculator.js" defer></script>
</head>
<body>
<div class="container">
<p>
This component works exactly like the calculator you know. Click any number to start calculating!
</p>
<div class="calculator">
<div class="calculator__display">0</div>
<div class="calculator__keys">
<button class="key--operator" data-action="add">+</button>
<button class="key--operator" data-action="subtract">-</button>
<button class="key--operator" data-action="multiply">×</button>
<button class="key--operator" data-action="divide">÷</button>
<button>7</button>
<button>8</button>
<button>9</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>1</button>
<button>2</button>
<button>3</button>
<button>0</button>
<button data-action="decimal">.</button>
<button data-action="clear">AC</button>
<button class="key--equal" data-action="calculate">=</button>
</div>
</div>
</div>
</body>
</html>
The is-depressed class is a class I add to the operator key element when it is clicked. The code above doesn't give the visual indicator of multiple clicks, but when I change *:active::before to *:active::after, the code does what I want. Why is that?
.calculator__keys > *:active::after,
.calculator__keys > .is-depressed::before {
background-color: rgba(0, 0, 0, 0.2);
bottom: 0;
box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.5) inset;
content: "";
left: 0;
opacity: 0.3;
position: absolute;
right: 0;
top: 0;
z-index: 1;
}
The answer is simple. Having :active::after and .is-depressed::before means that when your element is pressed you will change the before element AND when you click again you will change the after element so two different elements.
When having both of them as before then it's one element and it is already updated via .is-depressed so the active state will do nothing.
To illustrate this with a more simple example:
.box {
border:1px solid;
width:150px;
height:150px;
display:inline-block;
position:relative;
}
.box:hover::before,
.box.active::before{
content:"";
display:block;
height:50%;
background:red;
}
<div class="box"></div>
<div class="box active"></div>
In the above, nothing will happen when you hover on the second element because active already did the job:
.box {
border:1px solid;
width:150px;
height:150px;
display:inline-block;
position:relative;
}
.box:hover::after,
.box.active::before{
content:"";
display:block;
height:50%;
background:red;
}
<div class="box"></div>
<div class="box active"></div>
In the last exmple the active will add the before element and the hover will add the after element. As simple as that.
The problem with your code is that ::before has position: absolute but the buttons don't, so it's position is relative to the body. Add position: relative or absolute to the buttons.
Regarding your question, they are the same, they're virtual elements (pseudo-elements) (they don't belong to the DOM but they are rendered as if they were regular elements if they have a content property), the difference between them is that ::before is placed at the beginning of the element and ::after at the end.
When I click inside of the dropdown menus, they close.
This occurs at Login menu and nav bar.
Im not too awfully experienced at webdeveloping but I know that its probably just some dumb error Ive overlooked a million times today.
I believe the error is in this part of the code (expanded bellow):
if (e.isDefaultPrevented()) return
$this.attr('aria-expanded', 'false')
$parent.removeClass('open').trigger('ontouchstart', relatedTarget)
Can be seen at zunelex.com
var backdrop = '.dropdown-backdrop'
var toggle = '[data-toggle="dropdown"]'
var Dropdown = function (element) {
$(element).on('click.bs.dropdown', this.toggle)
}
Dropdown.VERSION = '3.3.4'
Dropdown.prototype.toggle = function (e) {
var $this = $(this)
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
clearMenus()
if (!isActive) {
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
// if mobile we use a backdrop because click events don't delegate
$('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
}
var relatedTarget = { relatedTarget: this }
$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this
.trigger('focus')
.attr('aria-expanded', 'true')
$parent
.toggleClass('open')
.trigger('shown.bs.dropdown', relatedTarget)
}
return false
}
Dropdown.prototype.keydown = function (e) {
if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
var $this = $(this)
e.preventDefault()
e.stopPropagation()
if ($this.is('.disabled, :disabled')) return
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
var desc = ' li:not(.disabled):visible a'
var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
if (!$items.length) return
var index = $items.index(e.target)
if (e.which == 38 && index > 0) index-- // up
if (e.which == 40 && index < $items.length - 1) index++ // down
if (!~index) index = 0
$items.eq(index).trigger('focus')
}
function clearMenus(e) {
if (e && e.which === 3) return
$(backdrop).remove()
$(toggle).each(function () {
var $this = $(this)
var $parent = getParent($this)
var relatedTarget = { relatedTarget: this }
if (!$parent.hasClass('open')) return
$parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
if (e.isDefaultPrevented()) return
$this.attr('aria-expanded', 'false')
$parent.removeClass('open').trigger('ontouchstart', relatedTarget)
})
}
function getParent($this) {
var selector = $this.attr('data-target')
if (!selector) {
selector = $this.attr('href')
selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
}
var $parent = selector && $(selector)
return $parent && $parent.length ? $parent : $this.parent()
}
// DROPDOWN PLUGIN DEFINITION
// ==========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.dropdown')
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
if (typeof option == 'string') data[option].call($this)
})
}
var old = $.fn.dropdown
$.fn.dropdown = Plugin
$.fn.dropdown.Constructor = Dropdown
// DROPDOWN NO CONFLICT
// ====================
$.fn.dropdown.noConflict = function () {
$.fn.dropdown = old
return this
}
// APPLY TO STANDARD DROPDOWN ELEMENTS
// ===================================
$(document)
.on('click.bs.dropdown.data-api', clearMenus)
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
.on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
.on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
.dropdown {
position: relative;
}
.dropdown-toggle:focus {
outline: 0;
}
.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: none;
float: left;
min-width: 160px;
padding: 5px 0;
margin: 2px 0 0;
font-size: 14px;
text-align: left;
list-style: none;
background-color: #fff;
-webkit-background-clip: padding-box;
background-clip: padding-box;
border: 1px solid #ccc;
border: 1px solid rgba(0, 0, 0, .15);
border-radius: 4px;
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
}
.dropdown-menu.pull-right {
right: 0;
left: auto;
}
.dropdown-menu .divider {
height: 1px;
margin: 9px 0;
overflow: hidden;
background-color: #e5e5e5;
}
.dropdown-menu > li > a {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: 1.42857143;
color: #333;
white-space: nowrap;
}
.dropdown-menu > li > a:hover,
.dropdown-menu > li > a:focus {
color: #262626;
text-decoration: none;
background-color: #f5f5f5;
}
.dropdown-menu > .active > a,
.dropdown-menu > .active > a:hover,
.dropdown-menu > .active > a:focus {
color: #fff;
text-decoration: none;
background-color: #337ab7;
outline: 0;
}
.dropdown-menu > .disabled > a,
.dropdown-menu > .disabled > a:hover,
.dropdown-menu > .disabled > a:focus {
color: #777;
}
.dropdown-menu > .disabled > a:hover,
.dropdown-menu > .disabled > a:focus {
text-decoration: none;
cursor: not-allowed;
background-color: transparent;
background-image: none;
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
}
.open > .dropdown-menu {
display: block !important;
visibility: visible;
}
.open > a {
outline: 0;
}
.dropdown-menu-right {
right: 0;
left: auto;
}
.dropdown-menu-left {
right: auto;
left: 0;
}
.dropdown-header {
display: block;
padding: 3px 20px;
font-size: 12px;
line-height: 1.42857143;
color: #777;
white-space: nowrap;
}
.dropdown-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 990;
}
.pull-right > .dropdown-menu {
right: 0;
left: auto;
}
.dropup .caret,
.navbar-fixed-bottom .dropdown .caret {
content: "";
border-top: 0;
border-bottom: 4px solid;
}
.dropup .dropdown-menu,
.navbar-fixed-bottom .dropdown .dropdown-menu {
top: auto;
bottom: 100%;
margin-bottom: 2px;
}
#media (min-width: 768px) {
.navbar-right .dropdown-menu {
right: 0;
left: auto;
}
.navbar-right .dropdown-menu-left {
right: auto;
left: 0;
}
}
<div class="dropdown-menu" style="padding: 15px;>
<form class="form-horizontal" method="post" accept-charset="UTF-8">
<input id="sp_uname" class="form-control login" type="text" name="sp_uname" placeholder="Username.." />
<input id="sp_pass" class="form-control login" type="password" name="sp_pass" placeholder="Password.."/>
<input class="btn btn-primary" type="submit" name="submit" value="login" />
</form>
</li>
</ul>
</ul>
</div>
Your html is invalid, the style attribute requires an opening AND closing quotation mark to be valid.
Essentially your style attribute keeps reading characters until it decides it has a reason to stop so:
padding: 15px;>
And then everything after that just gets really messed up.
first of all i'll explain the situation:
I can ONLY write in the body of an html, this is because of some limitations.
I need to replace the website (a profile) for a new one.
The issue is: the menu should show or hide sections on click... and isn't.
I don't really know much of javascript, just a bit of python and because of that i'm getting some issues with the code, but i won't learn javascript much either since this will probably be just a once in a lifetime for me.
I don't want to add jQuery code.
So... i tried this code in http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_style_background, (copy and pasty so you can also check) but it doesnt works as expected, the function for the menu isn't working.
<!DOCTYPE html><html><head></head><body><script>
function comandos()
{
var visibilidaddecomandos = document.getElementById("comandos").style.display;
if (visibilidaddecomandos == "hidden")
{
document.getElementById("comandos").style.visibility = "visible";
}
else if (visibilidaddecomandos == "visible")
{
document.getElementById("comandos").style.visibility = "hidden";
}
return false;
}
document.write('<style> #navcontainer { margin: 10px 0 0 30px; padding: 0; height: 20px; } #navcontainer ul { border: 0; margin: 0; padding: 0; list-style-type: none; text-align: center; } #navcontainer ul li { display: block; float: left; text-align: center; padding: 0; margin: 0; } #navcontainer ul li a { background: #fff; width: 78px; height: 18px; border-top: 1px solid #ddd; border-left: 1px solid #ddd; border-bottom: 1px solid #ddd; border-right: 1px solid #ddd; padding: 0; margin: 0 0 5px 0; color: #666; text-decoration: none; display: block; text-align: center; font: normal 10px/18px verdana; } #navcontainer ul li a:hover { color: #6659A7; background: #eeeeee; } #navcontainer a:active { background: #c60; color: #fff; } #navcontainer li#active a { background: #c60; border: 1px solid #c60; color: #fff; } </style> <div id="navcontainer"> <ul> <li><span>Comandos</span></li><li><span>Estadisticas</span></li><li><span>Juegos</span></li><li><span>Sobre mi</span></li><li><span>Saelyth</span></li></ul> </div>');
document.write('<br><table id="global" style="background-color:#ffffff; width:460px; height:600px"><tr><td style="vertical-align:top"><table id="comandos" border="2" style="background-color:#000000; float:center"><tr><td><p style="color:red">Testing the ID table "comandos"</p></td></tr></table></td></tr></table>');
document.body.style.background="#66ffff url('http://images.wikia.com/xenosaga/images/8/86/KOSMOSWikiBG.jpg') no-repeat left top"
document.title = "¡My not working menu!";
window.stop();
</script>
</body></html>
Although tables are not best practice..for multiple reasons.. one being that the entire table has to load before your data is shown.
Divs are your best friend.
Anyways, here is the fix I believe you are looking for.
function comandos()
{
var visibilidaddecomandos = document.getElementById("comandos").style.visibility;
if (visibilidaddecomandos == "hidden")
{
document.getElementById("comandos").style.visibility = "visible";
}
else if (visibilidaddecomandos == "visible")
{
document.getElementById("comandos").style.visibility = "hidden";
}
return false;
}
Also you have to add a default visibility to your table in order for it to work.
<table id="comandos" border="2" style="visibility:visible;background-color:#000000; float:center">
var visibilidaddecomandos = document.getElementById("comandos");
if (visibilidaddecomandos.style.visibility == 'hidden')
{
visibilidaddecomandos.style.visibility = "visible";
}
else if (visibilidaddecomandos.style.visibility == "visible")
{
visibilidaddecomandos.style.visibility = "hidden";
}
This will work....
if (document.getElementById("comandos").style.visibility == "hidden"){document.getElementById("comandos").style.visibility == "visible";}else if (document.getElementById("comandos").style.visibility == "visible")
{document.getElementById("comandos").style.visibility == "hidden";}
Hope this will help.