Vertical JavaScript Menu - Not All Subsections Displaying - javascript

Currently, I'm helping to build a website for a family member as part of a modeling club they have.
The website is at http://testindyamps.weebly.com/ .
It's a website on a host that utilizes various templates for themes (I haven't had much help so far from people on said site).
I'm not 100% sure if this ist he best place to post the question, but I thought I'd give it a shot.
The main issue is that it's utilizing a sidebar navigation where when you click the menus, it expands downward to show the subpages. In this case, not all the subpages are showing. (For example, clicking on "Articles" and then "Books" shows only the first few of a dozen or so pages.
I've tried editing the JS code itself, which so far has had no affect. I've tried editing some of the CSS, however, it doesn't seem to have an affect either.
If it helps, I can share osme of the CSS code or JS code for the site itself. Any help would be appreciated.
Thank you.
UPDATE: Added the code as requested.
Update 2: Added HTML: fixed to correct URL (using a test site instead of the "actual" site for the navigation).
jQuery(function($) {
// Mobile sidebars
$.fn.expandableSidebar = function(expandedClass) {
var $me = this;
$me.on('click', function() {
if(!$me.hasClass(expandedClass)) {
$me.addClass(expandedClass);
} else {
$me.removeClass(expandedClass);
}
});
}
// Interval loop
$.fn.intervalLoop = function(condition, action, duration, limit) {
var counter = 0;
var looper = setInterval(function(){
if (counter >= limit || $.fn.checkIfElementExists(condition)) {
clearInterval(looper);
} else {
action();
counter++;
}
}, duration);
}
// Check if element exists
$.fn.checkIfElementExists = function(selector) {
return $(selector).length;
}
// Check if desktop display
$.fn.isDesktop = function() {
return $(window).width() > 1024;
}
var briskController = {
init: function(opts) {
var base = this;
base._addClasses();
setTimeout(function(){
base._attachEvents();
}, 1000);
},
_addClasses: function() {
var base = this;
// Add fade in class to nav + logo + banner
$('body').addClass('fade-in');
// Keep subnav open if submenu item is active
$('.sidebar-nav .active').parents('.has-submenu').children('.dropdown').addClass('open');
// Add placeholder text to inputs
$('.wsite-form-sublabel').each(function(){
var sublabel = $(this).text();
$(this).prev('.wsite-form-input').attr('placeholder', sublabel);
});
},
_cloneLogin: function() {
var loginDetach = $('#member-login').clone(true);
$('.mobile-nav .wsite-menu-default > li:last-child').after(loginDetach);
},
_stickyNav: function() {
var sticky,
collapse,
uncollapse,
desktopsticky = $('body.nav-position-top.sticky-nav-on:not(.wsite-checkout-page):not(.wsite-native-mobile-editor), body.nav-position-top-right.sticky-nav-on:not(.wsite-checkout-page):not(.wsite-native-mobile-editor)').length,
mobilesticky = $('body.sticky-nav-on:not(.wsite-checkout-page):not(.wsite-native-mobile-editor)').length;
var stickyInit = function() {
if (!$.fn.isDesktop() || desktopsticky) {
// Add sticky desktop nav
sticky = new Waypoint.Sticky({
element: $('.header')[0]
});
}
if ($.fn.isDesktop() && desktopsticky) {
// Collapse header on scroll
collapse = new Waypoint({
element: $('body.nav-position-top.sticky-nav-on:not(.wsite-checkout-page):not(.wsite-native-mobile-editor)')[0],
handler: function(direction) {
$('body').addClass('collapse');
},
offset: -10
});
uncollapse = new Waypoint({
element: $('body.nav-position-top'),
handler: function(direction) {
$('body').removeClass('collapse');
},
offset: -5
});
}
}
stickyInit();
$(window).resize(function() {
if (sticky) { sticky.destroy() }
if (collapse) { collapse.destroy() }
if (uncollapse) { uncollapse.destroy() }
stickyInit();
});
},
_sidebarNav: function() {
// Fixed sidebar nav unless menu height exceeds viewport height
var sidebarCheck = function() {
if ($.fn.isDesktop() && $('body').hasClass('sticky-nav-on') && $('.header .container').height() + $('.header .contact').height() <= $(window).height() - 45) {
$('body.nav-position-sidebar .header').addClass('stuck');
}
else {
$('body.nav-position-sidebar .header').removeClass('stuck');
}
}
sidebarCheck();
$(window).resize(function() {
sidebarCheck();
});
},
_sidebarCart: function(){
$('#wsite-mini-cart').addClass('cart-init');
$('.wsite-nav-cart a').click(function() {
$('.cart-init').toggleClass('cart-visible');
});
$('.wrapper, .header').click(function() {
$('.cart-init').removeClass('cart-visible');
});
},
_attachEvents: function() {
var base = this;
// Hamburger nav toggle
$('.hamburger').on('click', function(e) {
e.preventDefault();
$('body').toggleClass('nav-open');
});
// Initialize sticky nav
base._stickyNav();
// Initialize sidebar nav
base._sidebarNav();
// Copy login
$.fn.intervalLoop('.mobile-nav #member-login', base._cloneLogin, 800, 5);
// Subnav toggle
$('li.has-submenu span.icon-caret, .dropdown-link').on('click', function() {
var $me = $(this);
if ($me.parent().hasClass('open')) {
$me.parent().removeClass('open');
$me.find('.open').removeClass('open');
}
else {
$('.open').removeClass('open');
$me.parents('.has-submenu').children('.dropdown').addClass('open');
}
setTimeout(function(){
base._sidebarNav();
}, 800);
});
// Sidebar Cart Link
$.fn.intervalLoop('.cart-init', base._sidebarCart, 1000, 5);
// Store category dropdown
$('.wsite-com-sidebar').expandableSidebar('sidebar-expanded');
// Search filters dropdown
$('#wsite-search-sidebar').expandableSidebar('sidebar-expanded');
// Init fancybox swipe on mobile
if ('ontouchstart' in window) {
$('body').on('click', 'a.w-fancybox', function() {
base._initSwipeGallery();
});
}
},
_initSwipeGallery: function() {
var base = this;
setTimeout(function(){
var touchGallery = document.getElementsByClassName('fancybox-wrap')[0];
var mc = new Hammer(touchGallery);
mc.on("panleft panright", function(ev) {
if (ev.type == "panleft") {
$("a.fancybox-next").trigger("click");
} else if (ev.type == "panright") {
$("a.fancybox-prev").trigger("click");
}
base._initSwipeGallery();
});
}, 500);
}
}
$(document).ready(function(){
briskController.init();
});
});
/* Header */
.header {
position: relative;
width: 100%;
color: #fill;
background: #bg;
border-bottom: 1px solid fade(#fill, 5);
box-sizing: border-box;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
z-index: 12;
.hamburger,
.contact,
.desktop-nav,
.sidebar-nav {
display: none;
}
}
body.nav-open {
overflow: hidden;
#media #tablet-up {
overflow: auto;
}
}
body:not(.nav-position-sidebar),
body.nav-position-top,
body.nav-position-top-right {
#media #tablet-up {
.header {
position: relative;
padding: 10px 40px;
border-bottom: none;
.transition(~'padding 280ms ease');
.container {
display: table;
overflow-y: hidden;
width: 100%;
height: 80px;
.transition(~'height 280ms ease');
}
.logo {
display: table-cell;
text-align: left;
vertical-align: middle;
max-height: 80px;
overflow: hidden;
a {
padding: 5px 20px 5px 0;
}
}
.desktop-nav {
display: table-cell;
}
.nav {
li {
display: inline-block;
}
a {
padding: 10px 20px;
}
}
.membership-cart {
display: table-cell;
width: 5%;
text-align: right;
white-space: nowrap;
span {
display: inline-block;
}
}
}
&.collapse {
.header {
padding: 5px 40px;
border-bottom: 1px solid fade(#fill, 5);
.container {
height: 40px;
}
}
}
&.full-width-nav-off .header .container {
max-width: 1200px;
margin: 0 auto;
padding: 0 40px;
box-sizing: border-box;
}
}
}
body.nav-position-top-right {
.desktop-nav {
text-align: right;
}
}
.stuck {
position: fixed !important;
top: 0;
}
body.nav-position-sidebar {
#media #tablet-up {
.header {
position: absolute;
top: 0;
left: 0;
width: 260px;
min-height: 100vh;
padding: 40px;
border-bottom: none;
display: flex;
flex-direction: row;
> .nav-wrap {
width: 100%;
min-height: calc(~'100vh - 80px');
display: flex;
flex-direction: column;
> .container {
flex: 1 0 auto;
}
}
.sidebar-nav {
display: block;
}
.nav {
li {
display: block;
}
a {
display: block;
padding: 10px 0;
}
}
.logo {
margin: 0 auto 30px;
}
.membership-cart > span {
display: block;
}
}
.contact {
display: block;
}
.wsite-phone {
display: block;
font-size: 15px;
color: fade(#fill, 40);
padding: 40px 0 0;
text-align: left;
&:before {
content: '';
display: block;
width: 60%;
padding-bottom: 40px;
border-top: 1px solid fade(#fill, 20);
}
}
.wrapper {
background: #bg;
padding-left: 260px;
box-sizing: border-box;
}
}
}
.logo {
* {
display: block;
}
a {
color: #primary;
&:hover {
opacity: 0.6;
background: transparent;
.transition(opacity 200ms ease);
}
}
#wsite-title {
font-family: #font1;
font-size: 30px;
font-weight: 500;
line-height: 1;
text-transform: uppercase;
letter-spacing: 0.08em;
}
img {
overflow: hidden;
max-width: 300px;
max-height: 70px;
}
.wsite-logo {
overflow: hidden;
max-width: 100%;
max-height: 70px;
}
}
/* Nav */
.nav {
vertical-align: middle;
a {
display: block;
color: #fill;
font-family: #font1;
font-size: 15px;
font-weight: 500;
line-height: 1;
letter-spacing: 0.05em;
text-transform: lowercase;
&:hover {
opacity: 0.6;
background: transparent;
.transition(opacity 200ms ease);
}
}
.active {
color: darken(#primary, 10%) !important;
}
#wsite-nav-cart-a {
padding-right: 0;
}
#wsite-nav-cart-num {
position: relative;
display: inline-block;
background: mix(#primary, #bg, 60%);
color: #fill;
min-width: 25px;
padding: 7px 2px;
text-align: center;
border-radius: 100%;
z-index: 2;
#media #tablet-up {
margin: 0 -6px;
}
}
}
.mobile-nav {
display: none;
}
/* Subnav */
#wsite-menus {
> .wsite-menu-wrap {
margin-top: 10px;
}
> .wsite-menu-wrap > .wsite-menu .wsite-menu {
margin: 0 -1px;
}
.wsite-menu {
position: relative;
background: #bg;
.box-shadow(inset 0px 0px 0px 1px fade(#fill, 3));
li a {
padding: 12px 20px;
background: transparent;
color: #fill;
font-family: #font1;
font-size: 14px;
font-weight: normal;
line-height: normal;
text-transform: lowercase;
letter-spacing: 0.05em;
border: none;
&:hover {
opacity: 0.6;
background: transparent;
.transition(opacity 200ms ease);
}
}
}
.wsite-menu-arrow {
display: none;
}
}
/* Sidebar and Mobile Subnav */
.sidebar-nav,
.mobile-nav {
li {
position: relative;
border-color: fade(#fill, 80);
}
.wsite-menu {
padding-left: 5px;
color: fade(#fill, 50);
border-color: fade(#fill, 50);
a {
color: fade(#fill, 50);
}
}
.wsite-menu-wrap {
display: block !important;
overflow: hidden;
max-height: 0;
.transition(all 600ms ease-in-out);
}
.wsite-menu-wrap li.wsite-nav-current > a.wsite-menu-subitem {
background: rgba(0, 0, 0, 0.95);
border: none;
}
.wsite-menu-wrap .wsite-menu-arrow {
display: none;
}
.dropdown {
display: table;
width: 100%;
&:hover {
.icon-caret {
opacity: 0.6;
background: transparent;
}
}
> .icon-caret,
> .dropdown-link {
display: table-cell !important;
vertical-align: top;
a {
display: inline-block !important;
}
}
.icon-caret {
width: 15px;
cursor: pointer;
.transition(all 200ms ease-in-out);
&:before {
content: '';
position: relative;
display: block;
width: 5px;
height: 5px;
border: solid transparent;
border-width: 0 1px 1px 0;
border-color: inherit;
.transform(~'rotate(45deg)');
}
}
&.open span.icon-caret:before {
top: 5px;
.transform(~'rotate(-135deg)');
}
&.open + .wsite-menu-wrap {
width: 100%;
max-height: 1000px;
}
}
}
.sidebar-nav {
.has-submenu > .dropdown span.icon-caret {
padding: 12px 0 8px 10px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body class="no-header-page">
<div class="header">
<div class="nav-wrap">
<div class="container">
<a class="hamburger" aria-label="Menu" href="#"><span></span></a>
<div class="logo">{logo}</div>
<div class="nav desktop-nav">{menu}</div>
<div class="nav sidebar-nav"><div class="nav-wrap">{menu}</div></div>
<div class="nav membership-cart">{membership}{minicart}</div>
</div>
<div class="nav contact">{phone:text}</div>
</div>
</div>
<div class="wrapper">
<div class="main-wrap">
{{#sections}}
<div class="container">{content}</div>
{{/sections}}
</div>
<div class="footer-wrap">
<div class="footer">{footer}</div>
</div>
</div>
<div class="nav mobile-nav">
<a class="hamburger" aria-label="Menu" href="#"><span></span></a>
{menu}
</div>
<script type="text/javascript" src="/files/theme/plugins.js"></script>
<script type="text/javascript" src="/files/theme/custom.js"></script>
</body>
</html>

The reason not all elements are showing is because of this:
.sidebar-nav .dropdown.open + .wsite-menu-wrap, .mobile-nav .dropdown.open + .wsite-menu-wrap {
width: 100%;
max-height: 1000px;
}
The element is expanded by changing the max-height from 0px to 1000px. The elements in your menu exceed 1000px and they get cut off.
This is actually a pretty comman problem when using CSS transitions to expand elements. CSS transitions only work on height if height is set to an exact value. You can read more about it here: https://css-tricks.com/using-css-transitions-auto-dimensions/
The max-height trick offers a work-around. But it has its draw-back - if the elements expands beyond the value of max-height it gets cut off.
The simplest solution is to simply increase the value of max-height, until all your elements show. This will work, but it' s not ideal if in the future the element expands even more.
More sophisticated (and arguably better) solutions can be found in the css-tricks web page above.
Still, are you sure it's a good idea do display such an enormous amount of of links in an accordion menu? Wouldn't it be better to rethink the navigation, perhaps have a separate page with all the books?

Related

Typing and saving notes on every device

I am working on notes page. I want to be able to write notes and save them. Everything works perfectly except that I only see notes in one browser. For example if I open my website on Safari, I can save my notes and I'll be able to see them forever. But if I open my website on Chrome or my phone, the notes are empty. So I need to rewrite everything and save it. So every time I want to save something, I need to rewrite the same notes on every device which is ridiculous. So what I want to do is to make my notes visible on every device. I hope it makes sense.
What I have now:
<div class="logo">
<h1>
Notes
</h1>
<img src="icon.svg">
</div>
<main contenteditable="" autocorrect="off"></main>
<div class="icon">
<img src="icon-2-01.svg">
</div>
<button>Save</button>
<script src="main.js"></script>
html {
height: 100%;
}
body {
font-size: 14px;
font-family: Times New Roman;
height: 100%;
width: 100%;
overflow: hidden;
padding: 30px;
background-color: #50554f;
color: #FFF;
}
html {
margin: 0;
}
h1 {
top: 30px;
right: -65px;
font-size: 20px;
position: relative;
}
a {
text-transform: none;
color: #FFF;
text-decoration: none;
}
.logo {
top: 10px;
right: 10px;
float: right;
}
.logo img {
width: 220px;
margin-top: -20px;
}
main {
color: #FFF;
display: block;
height: calc(100% - 6.3em);
overflow: scroll;
outline: none;
}
.icon {
position: absolute;
bottom: 30px;
left: 30px;
}
.icon img {
width: 50px;
height: 50px;
}
button {
font-size: 1em;
margin-top: 80px;
font-size: 14px;
font-family: Times New Roman;
color: #FFF;
right: 30px;
float: right;
}
button, input[type="submit"], input[type="reset"] {
background: none;
color: inherit;
border: none;
padding: 0;
font: inherit;
cursor: pointer;
outline: inherit;
}
html {
overflow: scroll;
}
::-webkit-scrollbar {
width: 0px;
height: 0px;
background: transparent; /* make scrollbar transparent */
}
#media (max-width:600px) {
body {
position: fixed;
}
.logo {
display: block;
align-items: center;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 100%;
margin-bottom: 50px;
}
h1 {
margin-left: -130px;
}
main {
width: 80%;
height: calc(100% - 15em);
}
.icon {
display: none;
}
button {
position: relative;
left: 1px;
float: left;
}
}
var button = document.querySelector('button');
var main = document.querySelector('main');
if (localStorage['note'] === undefined ) {
localStorage['note'] = 'Save your note by typing in here and clicking the Save Button.<br>You can also press CMD + S / CTRL + S'
}
function siteLoad () {
main.innerHTML = localStorage['note'];
}
function buttonSave () {
localStorage['note'] = main.innerHTML;
}
function keySave (e) {
if (e.keyCode === 83 && e.metaKey || e.keyCode === 83 && e.ctrlKey) {
e.preventDefault();
localStorage['note'] = main.innerHTML;
}
}
if (window.addEventListener) {
window.addEventListener('load', siteLoad, false);
button.addEventListener('click', buttonSave, false);
main.addEventListener('keydown', keySave, false);
} else if (window.attachEvent) {
window.attachEvent('onload', siteLoad);
button.attachEvent('onclick', buttonSave);
main.attachEvent('keydown', keySave);
} else {
window.onload = siteLoad;
button.onclick = buttonSave;
main.onkeydown = keySave;
}

How to add inline CSS to dynamically created elements with Javascript?

I would like to add inline CSS to the left and right messages that are generated, for example the left text is red and the right text is blue. (I know it's best to style in the CSS, but I'm testing something else). So I will have this HTML:
<ul class="messages">
<li class="message left appeared">
<div class="text_wrapper">
<p class="text" style="color:red;">blabla</p>
</div>
</li>
<li class="message right appeared">
<div class="text_wrapper">
<p class="text" style="color:blue;">blabla</p>
</div>
</li>
</ul>
Please see the code as reference for the functionality. Many thanks for your help.
(function() {
var Message;
Message = function({
text: text1,
message_side: message_side1
}) {
this.text = text1;
this.message_side = message_side1;
this.draw = () => {
var $message;
$message = $($('.message_template').clone().html());
$message.addClass(this.message_side).find('.text').html(this.text);
$('.messages').append($message);
return setTimeout(function() {
return $message.addClass('appeared');
}, 0);
};
return this;
};
$(function() {
var getMessageText, message_side, sendMessage;
message_side = 'right';
getMessageText = function() {
var $message_input;
$message_input = $('.message_input');
return $message_input.val();
};
sendMessage = function(text) {
var $messages, message;
if (text.trim() === '') {
return;
}
$('.message_input').val('');
$messages = $('.messages');
message_side = message_side === 'left' ? 'right' : 'left';
message = new Message({text, message_side});
message.draw();
return $messages.animate({
scrollTop: $messages.prop('scrollHeight')
}, 300);
};
$('.send_message').click(function(e) {
return sendMessage(getMessageText());
});
$('.message_input').keyup(function(e) {
if (e.which === 13) { // enter key
return sendMessage(getMessageText());
}
});
});
}).call(this);
* {
box-sizing: border-box;
}
.chat_window {
position: absolute;
width: calc(100% - 20px);
max-width: 600px;
height: 440px;
background-color: #fff;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
border: 1px solid #ddd;
overflow: hidden;
}
.messages {
position: relative;
list-style: none;
padding: 20px 10px 0 10px;
margin: 0;
height: 347px;
overflow: scroll;
}
.messages .message {
clear: both;
overflow: hidden;
margin-bottom: 20px;
transition: all 0.5s linear;
opacity: 0;
}
.messages .message.left .text_wrapper {
background-color: #ddd;
margin-left: 20px;
}
.messages .message.left .text_wrapper::after, .messages .message.left .text_wrapper::before {
right: 100%;
border-right-color: #ddd;
}
.messages .message.left .text,
.messages .message.right .text {
color: #000;
margin: 0;
}
.messages .message.right .text_wrapper {
background-color: #ddd;
margin-right: 20px;
float: right;
}
.messages .message.right .text_wrapper::after, .messages .message.right .text_wrapper::before {
left: 100%;
border-left-color: #ddd;
}
.messages .message.appeared {
opacity: 1;
}
.messages .message .text_wrapper {
display: inline-block;
padding: 20px;
width: calc(100% - 85px);
min-width: 100px;
position: relative;
}
.messages .message .text_wrapper::after, .messages .message .text_wrapper:before {
top: 18px;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.messages .message .text_wrapper::after {
border-width: 13px;
margin-top: 0px;
}
.messages .message .text_wrapper::before {
border-width: 15px;
margin-top: -2px;
}
.messages .message .text_wrapper .text {
font-size: 18px;
font-weight: 300;
}
.bottom_wrapper {
position: relative;
width: 100%;
background-color: #fff;
padding: 20px 20px;
position: absolute;
bottom: 0;
}
.bottom_wrapper .message_input_wrapper {
display: inline-block;
height: 50px;
border: 1px solid #bcbdc0;
width: calc(100% - 160px);
position: relative;
padding: 0 20px;
}
.bottom_wrapper .message_input_wrapper .message_input {
border: none;
height: 100%;
box-sizing: border-box;
width: calc(100% - 40px);
position: absolute;
outline-width: 0;
color: gray;
}
.bottom_wrapper .send_message {
width: 140px;
height: 50px;
display: inline-block;
background-color: #ddd;
border: 2px solid #ddd;
color: #000;
cursor: pointer;
transition: all 0.2s linear;
text-align: center;
float: right;
}
.bottom_wrapper .send_message:hover {
color: #000;
background-color: #fff;
}
.bottom_wrapper .send_message .text {
font-size: 18px;
font-weight: 300;
display: inline-block;
line-height: 48px;
}
.message_template {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chat_window">
<ul class="messages"></ul>
<div class="bottom_wrapper clearfix">
<div class="message_input_wrapper">
<input class="message_input" placeholder="Type here..." />
</div>
<div class="send_message">
<div class="icon"></div>
<div class="text">
Send
</div>
</div>
</div>
</div>
<div class="message_template">
<li class="message">
<div class="text_wrapper">
<p class="text"></p>
</div>
</li>
</div>
You can also add:
$(".left").css("color", "yellow");
$(".right").css("color", "blue");
$("li.message.left > div.text_wrapper > p").css('color', 'red');
$("li.message.right > div.text_wrapper > p").css('color', 'blue');
Using jQuery you can add inline style to an element
$(".left").attr("style","whatever");
$(".right").attr("style","whatever");
You can use the classList of every HTML component. Simply, select the DOM element with class left (or right) and use the add method to assign whatever class:
var elementLeft = $('.left')
elementLeft.classList.add('yourClass')
You can also use the methods remove to remove any class, or toggle to toggle some class..
elementLeft.classList.remove('yourClass')
elementLeft.classList.toggle('yourClass')
The Element.classList contains more examples. This solution works without jQuery or others javascript library, but use the standard API.

Add line numbers to text area using javascript

I wanted to add line numbering to a textarea.
I get the number of lines by using
textAreaElement.value.split("\n").length;
and maintain a div with span elements that use the count as content on before to add line numbers.
.line-number {
width: 100%;
display: block;
text-align: right;
line-height:1.5em;
border-bottom: thin;
font-family:'CascadiaCode Nerd Font', monospace;
font-size: 2rem;
color: #fff;
opacity: 0.8;
padding: 0 0.4em;
}
.line-number::before {
counter-increment: line;
content: counter(line);
font-size: 1em;
user-select: none;
}
However this has a fixed height, I want to implement this for a text area with word wrap (no horizontal scrollbar), where every line can technically have multiple lines terminated by a "\n".
My line of thought was to prepare an array of heights for each lines but I have no idea how to get the height of each separate line.
update:
I switched to an editable div, but i want my line number to be of the same height as its corresponding div.
const lineEnum = {
state: false,
count: 0,
gutter: document.getElementsByClassName("line-numbers")[0],
update: (box) => {
let delta = box.children.length - lineEnum.count;
if (box.children.length == 0) delta++;
console.log({
delta: delta,
count: lineEnum.count,
length: box.children.length,
});
if (delta > 0 && lineEnum.state) {
const frag = document.createDocumentFragment();
while (delta > 0) {
const line_number = document.createElement("span");
line_number.className = "line-num";
frag.appendChild(line_number);
lineEnum.count++;
delta--;
}
lineEnum.gutter.appendChild(frag);
} else {
if (lineEnum.count + delta === 0) delta++;
while (delta < 0 && lineEnum.gutter.lastChild) {
lineEnum.gutter.removeChild(lineEnum.gutter.lastChild);
lineEnum.count--;
delta++;
}
}
},
init: (box) => {
if (lineEnum.state) return;
lineEnum.state = true;
lineEnum.update(box);
},
remove: (box) => {
if (!lineEnum.state || !lineEnum.gutter.firstChild) return;
lineEnum.gutter.innerHtml = "";
lineEnum.state = false;
},
};
const callback = (mutationList, observer) => {
let mutation = mutationList[mutationList.length - 1];
if (mutation.type === "childList") {
console.log(mutation);
lineEnum.update(mutation.target);
}
};
const observer = new MutationObserver(callback);
const config = { childList: true };
const editor = document.getElementsByClassName("code-input")[0];
observer.observe(editor, config);
lineEnum.init(editor);
.window-body{
position: fixed;
height: 100%;
top: 25px;
width: 100%;
display: flex;
}
.line-numbers {
width: 5em;
padding: 0;
height: 100%;
word-break: break-all;
overflow: hidden;
display: inline-block;
counter-reset: line;
background-color: gray;
opacity: 0.8;
}
.line-num {
width: 100%;
display: block;
text-align: middle;
line-height:1.5em;
border-bottom: thin;
font-family:'Arial', monospace;
font-size: 2rem;
color: #fff;
opacity: 0.8;
padding: 0 1em;
}
.line-num::before {
counter-increment: line;
content: counter(line);
font-size: 1em;
user-select: none;
}
.code-input{
margin: 0;
border: 0;
padding: 0;
outline: 0;
list-style: none;
display: inline-block;
flex-grow: 1;
height: 100%;
word-break: break-all;
overflow: hidden;
border:none;
font-family:'Arial', monospace;
font-size:2rem;
background: white;
white-space:pre-wrap;
line-height:1.5em;
word-wrap: break-word;
resize:none;
}
<div class="window-body">
<div class="line-numbers"></div>
<div class="code-input" contenteditable="true"></div>
</div>
Man I wasted so much time on using javascript when css magic would just have done the trick.
Here is how I did it,
body {
background-color: #000;
height: 100vh;
width: 100vw;
margin: 0px;
}
.editor-wrapper {
height: 100vh;
width: 100vw;
overflow-y: auto;
counter-reset: line;
}
.editor{
margin: 0;
border: 0;
padding: 0;
outline: 0;
list-style: none;
height: 100%;
width: 100%;
word-wrap: break-word;
word-break: break-all;
font-size:2rem;
line-height: 1.5em;
font-feature-settings: common-ligatures;
-ms-font-feature-settings: common-ligatures;
color:rgba(255, 255, 255, 0.7);
resize:none;
}
.editor div {
padding-left: 5rem;
position: relative;
}
.editor div::before {
counter-increment: line;
content: counter(line);
font-size: 1em;
user-select: none;
width: 5rem;
text-align: right;
left: 0;
position: absolute;
}
<div class="editor-wrapper">
<div class="editor" contenteditable="true">
<div></div>
</div>
</div>
You can use a background image like so:
.lined-textarea {
background: url(http://i.imgur.com/2cOaJ.png);
background-attachment: local;
background-repeat: no-repeat;
padding-left: 35px;
padding-top: 10px;
border-color: #ccc;
font-size: 13px;
line-height: 16px;
resize: none;
}
<textarea rows="8" cols="30" class="lined-textarea"></textarea>
If it's a code block with line numbers you want then https://www.prowaretech.com/Computer/JavaScript/AddLineNumbersToPre demonstrates this well.
function addLineClass (pre) {
var lines = pre.innerText.split("\n"); // can use innerHTML also
while(pre.childNodes.length > 0) {
pre.removeChild(pre.childNodes[0]);
}
for(var i = 0; i < lines.length; i++) {
var span = document.createElement("span");
span.className = "line";
span.innerText = lines[i]; // can use innerHTML also
pre.appendChild(span);
pre.appendChild(document.createTextNode("\n"));
}
}
Along with the CSS using the essential part:
pre span.line::before {
content: counter(linecounter);
See https://jsfiddle.net/Abeeee/12cx5ruf/6/ for a running example

echo on button class

I'm trying to build a multi step selector which has multiple combinations in every slide. for example hou have btn1, btn2 and btn3. Every button will display other content in the next slide.
It's an inpage multistep slider so I can't use onClick, submit input or something like that.
as you can see in the code below, I'm trying to get an echo on the name or value of the button who has been clicked in the slide before.
var currentSlide = 0,
$slideContainer = $('.slide-container'),
$slide = $('.slide'),
slideCount = $slide.length,
animationTime = 300;
function setSlideDimensions () {
var windowWidth = $(window).width();
$slideContainer.width(windowWidth * slideCount);
$slide.width(windowWidth);
}
function generatePagination () {
var $pagination = $('.pagination');
for(var i = 0; i < slideCount; i ++){
var $indicator = $('<div>').addClass('indicator'),
$progressBarContainer = $('<div>').addClass('progress-bar-container'),
$progressBar = $('<div>').addClass('progress-bar'),
indicatorTagText = $slide.eq(i).attr('data-tag'),
$tag = $('<div>').addClass('tag').text(indicatorTagText);
$indicator.append($tag);
$progressBarContainer.append($progressBar);
$pagination.append($indicator).append($progressBarContainer);
}
$pagination.find('.indicator').eq(0).addClass('active');
}
function goToNextSlide () {
if(currentSlide >= slideCount - 1) return;
var windowWidth = $(window).width();
currentSlide++;
$slideContainer.animate({
left: -(windowWidth * currentSlide)
});
setActiveIndicator();
$('.progress-bar').eq(currentSlide - 1).animate({
width: '100%'
}, animationTime);
}
function goToPreviousSlide () {
if(currentSlide <= 0) return;
var windowWidth = $(window).width();
currentSlide--;
$slideContainer.animate({
left: -(windowWidth * currentSlide)
}, animationTime);
setActiveIndicator();
$('.progress-bar').eq(currentSlide).animate({
width: '0%'
}, animationTime);
}
function postitionSlides () {
var windowWidth = $(window).width();
setSlideDimensions();
$slideContainer.css({
left: -(windowWidth * currentSlide)
}, animationTime);
}
function setActiveIndicator () {
var $indicator = $('.indicator');
$indicator.removeClass('active').removeClass('complete');
$indicator.eq(currentSlide).addClass('active');
for(var i = 0; i < currentSlide; i++){
$indicator.eq(i).addClass('complete');
}
}
setSlideDimensions();
generatePagination();
$(window).resize(postitionSlides);
$('.next').on('click', goToNextSlide);
$('.previous').on('click', goToPreviousSlide);
#charset "UTF-8";
*, html, body {
font-family: "TrebuchetMS", trebuchet, sans-serif;
}
* {
box-sizing: border-box;
}
h1, h2 {
text-align: center;
}
h1 {
font-size: 24px;
line-height: 30px;
font-weight: bold;
}
h2 {
font-size: 18px;
line-height: 25px;
margin-top: 20px;
}
button {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: 0;
padding: 14px 50px;
border-radius: 4px;
background-color: #37B595;
color: #FFFFFF;
text-transform: capitalize;
font-size: 18px;
line-height: 22px;
outline: none;
cursor: pointer;
transition: all 0.2s;
}
button:hover {
background-color: #1A7F75;
}
button.previous {
background-color: #A2ACAF;
}
button.previous:hover {
background-color: #5A5F61;
}
.full-width-container {
width: 100%;
min-width: 320px;
}
.sized-container {
max-width: 900px;
width: 100%;
margin: 0 auto;
}
.slide-container {
position: relative;
left: 0;
overflow: hidden;
}
.slide {
float: left;
}
.slide .sized-container {
padding: 75px 25px;
}
.button-container {
border-top: 1px solid black;
overflow: hidden;
padding-top: 30px;
}
.button-container button {
float: right;
margin-left: 30px;
}
.pagination-container {
margin-top: 120px;
}
.pagination {
width: 100%;
text-align: center;
padding: 0 25px;
}
.indicator {
width: 25px;
height: 25px;
border: 4px solid lightgray;
border-radius: 50%;
display: inline-block;
transition: all 0.3s;
position: relative;
}
.indicator .tag {
position: absolute;
top: -30px;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
color: lightgray;
white-space: nowrap;
}
.indicator.active, .indicator.complete {
border-color: #37B595;
}
.indicator.active .tag, .indicator.complete .tag {
color: #37B595;
}
.indicator.complete:after {
content: "✓";
position: absolute;
color: #37B595;
left: 4px;
top: 3px;
font-size: 14px;
}
.progress-bar-container {
width: 10%;
height: 4px;
display: inline-block;
background-color: lightgray;
position: relative;
top: -10px;
}
.progress-bar-container:last-of-type {
display: none;
}
.progress-bar-container .progress-bar {
width: 0;
height: 100%;
background-color: #37B595;
}
<div class="pagination-container full-width-container">
<div class="sized-container">
<div class="pagination"></div>
</div>
</div>
<div class="viewport full-width-container">
<ul class="slide-container">
<li class="slide" data-tag="Basic Info">
<div class="sized-container">
<h1>Slide1.</h1>
<input class="next" name="next" type="button" value="next" />
</div>
</li>
<li class="slide" data-tag="Expertise">
<div class="sized-container">
<h1>Slide2.</h1>
</div>
</li>
</ul>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
Can someone please help me out!

How to make text appear and disappear when a div is clicked on?

Hi I am very new to web development and was practicing some of the things I learned.
I built a basic program to toggle day and night. When you click the sun the moon appears and vise versa. You can see that the text "Good Afternoon!" and "Good Night!" appear as a default. I would like to be able to have "Good Afternoon!" appear only when the sun is present and "Good Night!" to appear only when the moon is present. Any help would be appreciated.
Here is the fiddle.
I tried something along the lines of this to mimic the other code but I know it is incorrect.
/*toggle text*/
if ($('#daytext').hasClass('visible')) {
$('#daytext').removeClass('visible');
} else {
$('#daytext').removeClass('visible');
}
You can use CSS properties to achieve that.
Look at visibility : hidden; and display : none;.
From here, "Another common display value is none. Some specialized elements such as script use this as their default. It is commonly used with JavaScript to hide and show elements without really deleting and recreating them.
This is different from visibility. Setting display to none will render the page as though the element does not exist. visibility: hidden; will hide the element, but the element will still take up the space it would if it was fully visible."
Updated fiddle.
You've just to hide the Good Night! by default then toggle the visibility when you click using the jQuery methods show()/hide():
if ($('#orb').hasClass('sun')) {
$('#daytext').hide();
$('#nighttext').show();
$('#orb').removeClass('sun').addClass('moon');
} else {
$('#daytext').show();
$('#nighttext').hide();
$('#orb').removeClass('moon').addClass('sun');
}
Hope this helps.
$(document).ready(function() {
$('#orb').click(function() {
/*Day and night toggle*/
if ($('#orb').hasClass('sun')) {
$('#daytext').hide();
$('#nighttext').show();
$('#orb').removeClass('sun').addClass('moon');
} else {
$('#daytext').show();
$('#nighttext').hide();
$('#orb').removeClass('moon').addClass('sun');
}
if ($('#sky').hasClass('day')) {
$('#sky').removeClass('day').addClass('night');
} else {
$('#sky').removeClass('night').addClass('day');
}
/*toggle visible moonspots*/
if ($('#moonspot1').hasClass('visible')) {
$('#moonspot1').removeClass('visible');
} else {
$('#moonspot1').addClass('visible');
}
if ($('#moonspot2').hasClass('visible')) {
$('#moonspot2').removeClass('visible');
} else {
$('#moonspot2').addClass('visible');
}
if ($('#moonspot3').hasClass('visible')) {
$('#moonspot3').removeClass('visible');
} else {
$('#moonspot3').addClass('visible');
}
/*toggle text*/
if ($('#daytext').hasClass('visible')) {
$('#daytext').removeClass('visible');
} else {
$('#daytext').removeClass('visible');
}
});
});
#orb {
height: 300px;
width: 300px;
border-radius: 100%;
padding: 20px;
margin: auto;
position: absolute;
top: 0;
left: 0;
botton 0;
right: 0;
}
#sky {
height: 100%;
width: 100%;
}
.sun {
background-color: #ffdd00;
border: 10px solid #f1c40f;
}
.sun:hover {
border: 20px solid #f1c40f;
}
.moon {
background-color: #bdc3c7;
border: 10px solid #eaeff2;
}
.moon:hover {
border: 20px solid #eaeff2;
}
.night {
background-color: #2c3e50;
}
.day {
background-color: #aaecf2;
}
#moonspot1 {
height: 50px;
width: 50px;
border-radius: 100%;
float: right;
margin: 20px;
}
#moonspot2 {
height: 80px;
width: 80px;
border-radius: 100%;
float: right;
margin: 20px;
}
#moonspot3 {
height: 150px;
width: 150px;
border-radius: 100%;
float: right;
margin: 20px;
}
.visible {
background-color: #eaeff2;
}
#daytext {
font-size: 50px;
font-family: Optima;
}
#nighttext {
font-size: 50px;
font-family: Optima;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body id="sky" class="day">
<div id="orb" class="sun">
<div id="moonspot1"></div>
<div id="moonspot2"></div>
<div id="moonspot3"></div>
</div>
<div id = "daytext">Good Afternoon!</div>
<div id = "nighttext" style='display:none'>Good Night!</div>
</body>
No need for so many classes to be toggled. I cleaned up your code to show you how to accomplish the same thing with only toggling between the .day and .night class. I'm using display: none to hide irrelevant elements depending on that state.
$(document).ready(function() {
$('#orb').click(function() {
/*Day and night toggle*/
if ($('#sky').hasClass('day')) {
$('#sky').removeClass('day').addClass('night');
} else {
$('#sky').removeClass('night').addClass('day');
}
});
});
#sky {
height: 100%;
width: 100%;
}
.night {
background-color: #2c3e50;
}
.day {
background-color: #aaecf2;
}
#orb {
height: 300px;
width: 300px;
border-radius: 50%;
padding: 20px;
margin: auto;
position: absolute;
top: 0;
left: 0;
botton 0;
right: 0;
}
.sun {
background-color: #ffdd00;
border: 10px solid #f1c40f;
}
.sun:hover {
border: 20px solid #f1c40f;
}
/* styling the #sky.night .sun to be the moon */
.night .sun {
background-color: #bdc3c7;
border: 10px solid #eaeff2;
}
.night .sun:hover {
border: 20px solid #eaeff2;
}
/* common styles for the 3 moonspots */
.moonspot {
background-color: #eaeff2;
border-radius: 50%;
float: right;
margin: 20px;
}
/* hide moonspots during day */
.day .moonspot {
display: none;
}
#moonspot1 {
height: 50px;
width: 50px;
}
#moonspot2 {
height: 80px;
width: 80px;
}
#moonspot3 {
height: 150px;
width: 150px;
}
.text {
font-size: 50px;
font-family: Optima;
/* position & z-index to put text above other elements */
position: relative;
z-index: 1;
}
/* hide the irrelevant text based on day/night */
.day #nighttext {
display: none;
}
.night #daytext {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body id="sky" class="day">
<div id="orb" class="sun">
<div class="moonspot" id="moonspot1"></div>
<div class="moonspot" id="moonspot2"></div>
<div class="moonspot" id="moonspot3"></div>
</div>
<div class="text" id="daytext">Good Afternoon!</div>
<div class="text" id="nighttext">Good Night!</div>
</body>
You can do several things. Since you are using jQuery, the following is an option.
On $(document).ready() you can add the following.
$('#nighttext').toggle();
Then in you click function you can do the following:
$('#daytext').toggle();
$('#nighttext').toggle();
You could also create a single div for the text and change the text on click, together with it's class.

Categories

Resources