Strange "nth-of-type" behavior - javascript

Here is just another approach for table-style layout using <ul> and <li>.
Each <ul> is a row, and each <li> is a cell.
The 1st <ul> is a header row, so it has a special styling which works fine.
For the widths of each columns, I would like to add "individual styling", using the advantage of "nth-of-child" instead of class.
Here is the HTML&CSS content:
var D, T, R;
function I() {
D = document.getElementById("D");
R = document.getElementById("R");
// To keep 1st row always visible.
D.onscroll = function() {
R.style.top = D.scrollTop + "px";
}
// This is just arbitrary content
var k = ["Va", "Vb"];
for (var i = 0; i < 500; i++) {
var e = document.createElement("ul");
D.appendChild(e);
for (var j = 0; j < 3; j++) {
var d = document.createElement("li");
e.appendChild(d);
d.innerHTML = (!j) ? i : k[j - 1];
}
}
}
I();
#D {
position: absolute;
left: 250px;
right: 50px;
top: 50px;
bottom: 50px;
background-color: #ff8;
overflow: auto;
white-space: nowrap;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
ul li {
display: table-cell;
}
ul:nth-child(odd) {
background: #eee;
}
ul:nth-child(even) {
background: #ddd;
}
ul:first-of-type {
background: #888;
color: #00f;
position: relative;
}
#D ul li:nth-of-type(1) {
width: 100px;
}
#D ul li:nth-of-type(2) {
width: 200px;
}
#D ul li:nth-of-type(3) {
width: 300px;
}
<div id="D">
<ul id="R">
<!-- 假行 Fake row -->
<li>请不要说谎:</li>
<li>这个不是表格 (table)!!!<br>
<div style="position:relative; left:0; right:0;"><select style="width:100%;">
<option>全部</option>
</select></div>
</li>
<li>这是2D目录(ul和li)!!!</li>
</ul>
</div>
NOTE: This is a test content and not production part, so please don't comment on the <style> to be in the <div> element or why I am not just using <table>.
NOTE: The use of "nth-of-type(1)" and not "first-of-type" here is just for convenience.
THE RESULT: columns 2 and 3 works perfect. Column one remains "auto" - not 100px wide
What I am doing wrong?

Related

JS todo list item checked, and add item

I am aiming to create a JS todo list similar to https://www.w3schools.com/howto/howto_js_todolist.asp
I have created the basic structure of my todo list application and the function of the close buttons.
These are working well, but I have a problem with adding new todo list items and checking and unchecking todo items.
I'm not sure if I'm using the classlist toggle property well, and also cannot figure why the add button doesn't work at all.
var todoitemlist = document.getElementsByClassName('todo-item');
var i;
for (i = 0; i < todoitemlist.length; i++) {
var span = document.createElement("SPAN");
span.innerHTML = "Close";
span.className = "closebutton";
todoitemlist[i].appendChild(span);
}
var close = document.getElementsByClassName("closebutton");
var i;
for (i = 0; i < close.length; i++) {
close[i].onclick = function() {
var listitem = this.parentElement;
listitem.style.display = "none";
}
}
var todoitemlistx = document.getElementsByClassName('todo-item');
//checked element
var i;
for (i = 0; i < todoitemlistx.length; i++) {
todoitemlistx[i].onclick = function(ev) {
ev.style.backgroundColor = "red";
ev.classList.toggle("todo-item-checked");
}
}
//add another list item
function add() {
var listitem = document.createElement("LI");
listitem.className = "todo-item";
var text = document.getElementById('todoinput').value;
var myul = getElementById('todo-list');
var t = document.createTextNode(text);
listitem.appendChild(t);
myul.appendChild(listitem);
var span = document.createElement("SPAN");
span.innerHTML = "Close";
span.className = "closebutton";
listitem[i].appendChild(span);
for (i = 0; i < close.length; i++) {
close[i].onclick = function() {
var div = this.parentElement;
div.style.display = "none";
}
}
}
* {
box-sizing: border-box;
}
body {
text-align: center;
margin: 0;
padding: 0;
background-color: #dbf9fc;
font-family: Arial, Helvetica, sans-serif;
color: rgba(0, 27, 39);
}
#todoinput {
margin: 5px;
padding: 5px;
width: 65%;
}
#add-button {
padding: 5px;
margin: 5px;
width: 5%;
background-color: rgba(0, 27, 39);
color: #dbf9fc;
border: none;
border-radius: 5px;
height: 1fr;
cursor: pointer;
}
#add-button:hover {
background-color: black;
}
#todo-list {
display: inline-block;
margin: 0;
padding: 0;
list-style: none;
width: 70%;
}
.todo-item {
position: relative;
display: flex;
justify-content: flex-start;
background-color: white;
border: 2px solid black;
padding: 5px;
margin: 5px;
}
.closebutton {
cursor: pointer;
justify-self: flex-end;
background-color: #e6772d;
position: absolute;
right: 0;
top: 0;
color: white;
float: right;
padding: 5px;
width: 30%;
margin: 0;
}
.closebutton:hover {
background-color: #c46526;
}
.todo-item-checked {
position: relative;
display: flex;
justify-content: flex-start;
background-color: rgb(187, 187, 187);
border: 2px solid black;
padding: 5px;
margin: 5px;
text-decoration: line-through;
}
.black {
background-color: black;
}
<main class="centered">
<h1>ToDo List JS</h1>
<h3>js project</h3>
<form action="">
<input type="text" name="" id="todoinput" placeholder="Enter the activity you've wented to do">
<input type="button" value="Add" id="add-button" onclick="add()">
</form>
<ul id="todo-list">
<li class="todo-item">
Hit the lights
</li>
<li class="todo-item">
Hit the lights
</li>
<li class="todo-item">
Hit the lights
</li>
<li class="todo-item-checked todo-item">
Hit the lights
</li>
</ul>
</main>
I remember what it was like starting development and how hard it could be, so I persevered with this.
I thought it would be a few small changes but it turned into a massive rewrite.
Una grande padulo, as the Italians like to say.
I hope you can or try to understand what I did here.
The big lesson would be, don't write the same code twice, put it in a separate function.
So this seems to work.
Let me know if it doesn't.
var todoitemlist=document.getElementsByClassName('todo-item');
for(var i=0;i<todoitemlist.length;i++)
{
myawesomeclosebutton(todoitemlist[i]);
todoitemlist[i].addEventListener('click',myawesomebackground);
}
function myawesomeclosebutton(myawesomeitem)
{
var span=document.createElement('span');
span.innerHTML='Close';
span.className='closebutton';
span.addEventListener('click',myawesomecloseevent);
myawesomeitem.appendChild(span);
}
function myawesomebackground(ev)
{
if(ev.target.style.backgroundColor!='red')
{
ev.target.style.backgroundColor='red';
}
else
{
ev.target.style.backgroundColor='transparent';
}
}
function myawesomecloseevent(event)
{
var div=event.target.parentElement;
div.style.display='none';
}
function add()
{
var listitem=document.createElement('li');
listitem.className='todo-item';
var myawesomeinput=document.getElementById('todoinput');
var text=myawesomeinput.value;
var myul=document.getElementById('todo-list');
var t=document.createTextNode(text);
listitem.appendChild(t);
myul.appendChild(listitem);
listitem.addEventListener('click',myawesomebackground);
myawesomeclosebutton(listitem);
myawesomeinput.value='';
}

CSS transition not working for right most div on offsetLeft

I have five divs. Four of those divs you can click, which will run a function that moves the div you clicked on to the coordinate of the fifth div using div.offsetLeft and div.offsetTop. The first three divs all work fine, but if you click the right most div first, the transition effect isn't applied while moving to the coordinates. If you click any of the other divs first, and then the right most div, the transition will apply.
If you make it so there are only two or three divs, the problem still persists. (You must remove the corresponding id from the parties array, as well as the html element).
jsfiddle: https://jsfiddle.net/zjystr2u/
Apologies for the javascript in the html. Have never used jsfiddle, and couldn't figure out how to make it load the javascript after the html.
Something janky is going on when you getCurrentPosAll() changes position from the default static to absolute
You could run getCurrentPosAll() before changing the top and left to set their default values correctly.
var selected = document.getElementById("selected");
var selectedX = selected.offsetLeft;
var selectedY = selected.offsetTop;
parties = ['opt1', 'opt2', 'opt3', 'opt4'];
getCurrentPosAll(); // (NEW) Make sure their defaults are set.
function moreTest(e) {
var party = e.target
party.style.left = selectedX + "px";
party.style.top = selectedY + "px";
}
function getCurrentPosAll() {
for (var idx = 0; idx < parties.length; idx++) {
var currentDiv = document.getElementById(parties[idx]);
var x = currentDiv.offsetLeft;
var y = currentDiv.offsetTop;
currentDiv.style.left = x + "px";
currentDiv.style.top = y + "px";
}
for (var idx = 0; idx < parties.length; idx++) {
var currentDiv = document.getElementById(parties[idx]);
currentDiv.style.position = "absolute";
}
}
.wrapper {
display: flex;
justify-content: space-around;
width: 75%;
margin: 0 auto;
}
.selected {
width: 100px;
height: 150px;
position: absolute;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
background-color: black;
opacity: 0.6;
z-index: 1;
}
.opt {
width: 100px;
height: 150px;
cursor: pointer;
transition: top 0.7s, left 0.7s;
}
.opt1 {
background-color: red;
}
.opt2 {
background-color: blue;
}
.opt3 {
background-color: orange;
}
.opt4 {
background-color: green;
}
<div class="wrapper">
<div class="selected" id="selected"></div>
<div class="opt opt1" id="opt1" onclick="moreTest(event)"></div>
<div class="opt opt2" id="opt2" onclick="moreTest(event)"></div>
<div class="opt opt3" id="opt3" onclick="moreTest(event)"></div>
<div class="opt opt4" id="opt4" onclick="moreTest(event)"></div>
</div>
I'm not sure why it behaves like this. I figure it has to do with how and when the browser calculates the initial value for the transition. where last elements CSS changes get batched into 1 update.
therefor it will immediately receive the updated top and left values, whereas the other elements will receive 2 updates, one with the default top and left and then one with the updated values. causing their transition to work properly.
Most likely because the the last elements CSS is changed, their css updates are applied in 2 updates instead of 1.
var selected = document.getElementById("selected");
var selectedX = selected.offsetLeft;
var selectedY = selected.offsetTop;
parties = ['opt1', 'opt2', 'opt3', 'opt4', 'opt5','opt6'];
function moreTest(e) {
var party = e.target
getCurrentPosAll();
party.style.left = selectedX + "px";
party.style.top = selectedY + "px";
}
function getCurrentPosAll() {
for (var idx = 0; idx < parties.length; idx++) {
var currentDiv = document.getElementById(parties[idx]);
var x = currentDiv.offsetLeft;
var y = currentDiv.offsetTop;
currentDiv.style.left = x + "px";
currentDiv.style.top = y + "px";
}
for (var idx = 0; idx < parties.length; idx++) {
var currentDiv = document.getElementById(parties[idx]);
currentDiv.style.position = "absolute";
}
}
.wrapper {
display: flex;
justify-content: space-around;
width: 100%;
margin: 0 auto;
}
.selected {
width: 100px;
height: 150px;
position: absolute;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
background-color: black;
opacity: 0.6;
z-index: 1;
}
.opt {
width: 100px;
height: 150px;
cursor: pointer;
transition: 0.7s;
}
.opt1 {
background-color: red;
}
.opt2 {
background-color: blue;
}
.opt3 {
background-color: orange;
}
.opt4 {
background-color: green;
}
.opt5 {
background-color: violet;
}
.opt6 {
background-color: black;
}
<div class="wrapper">
<div class="selected" id="selected"></div>
<div class="opt opt1" id="opt1" onclick="moreTest(event)"></div>
<div class="opt opt2" id="opt2" onclick="moreTest(event)"></div>
<div class="opt opt3" id="opt3" onclick="moreTest(event)"></div>
<div class="opt opt4" id="opt4" onclick="moreTest(event)"></div>
<div class="opt opt5" id="opt5" onclick="moreTest(event)"></div>
<div class="opt opt6" id="opt6" onclick="moreTest(event)"></div>
</div>

How to modify divs generated by jQuery?

Complete noob question here:
I have this 16x16 grid of divs generated by jQuery
var rows = 16;
var columns = 16;
var $row = $("<div />", {
class: 'row'
});
var $square = $("<div />", {
class: 'square'
});
$(document).ready(function() {
for (var i = 0; i < columns; i++) {
$row.append($square.clone());
}
for (var x = 0; x < rows; x++) {
$(".box_main").append($row.clone());
}
});
.row {
width: auto;
height: 40px;
background: #313131;
}
.square {
width: 40px;
height: 40px;
border-radius: 10px;
margin: 0;
display: inline-block;
background: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Can I somehow use the addClass and removeClass (or anything else) in order to change the background-color of each div one by one upon hovering/mouseenter over them?
I tried work something out but I'm not even sure whether it's possible or not to do this.
addClass()/removeClass() (or even JS) is not needed for this - you can achieve it using the :hover pseduo selector of CSS alone. Try this:
.square:hover {
background: #C00; /* amend colour as needed */
}
Working example:
var rows = 16;
var columns = 16;
var $row = $("<div />", {
class: 'row'
}).appendTo('body');
var $square = $("<div />", {
class: 'square'
});
$(document).ready(function() {
for (var i = 0; i < columns; i++) {
$row.append($square.clone());
}
for (var x = 0; x < rows; x++) {
$(".box_main").append($row.clone());
}
});
body {
background: #313131;
}
.row {
width: auto;
height: 40px;
background: #313131;
}
.square {
width: 40px;
height: 40px;
border-radius: 10px;
margin: 0;
display: inline-block;
background: #fff;
}
.square:hover {
background: #C00;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
beside the :hover pseduo selector, you might need to add an actual class to it with JS (perhaps it would make more sense if triggered by other event), nevertheless, here is an example using JS (addClass/removeClass)
var rows = 16;
var columns = 16;
var $row = $("<div />", {
class: 'row'
});
var $square = $("<div />", {
class: 'square'
});
$row.appendTo('body');
$(document).ready(function() {
for (var i = 0; i < columns; i++) {
$row.append($square.clone());
}
for (var x = 0; x < rows; x++) {
$(".box_main").append($row.clone());
}
$('.square').hover(function() { $(this).addClass('hovering'); }, function() { $(this).removeClass('hovering'); });
});
.row {
width: auto;
height: 40px;
background-color: #313131;
}
.square {
width: 40px;
height: 40px;
border-radius: 10px;
margin: 0;
display: inline-block;
background-color: #fff;
}
.hovering {
background-color: cyan;
border: 3px dashed blue;
width: 34px;
height: 34px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

AngularJs, set "100, 4, 9, 14 " element display none?

In my project, the red Number div is a button, I need to hide the number, 100, 4, 9,14 because the opacity:0"button` can click, so I use the "display none."
How to judge the number 100 div and hide it? I don't know how to use ng-class or ng-hide to hide the number 4,9,14div.
This is my code:
.bigDiv {
width: 500px;
height: 500px;
margin: 400px auto;
background-color: black;
}
ul {
font-size: 0px;
padding-left: 0px;
}
.circle {
width: 20px;
height: 20px;
border-radius: 10px;
background-color: green;
position: relative;
}
.todo-last {
position: absolute;
width: 33px;
height: 33px;
background-color: red;
left: 25px;
top: 25px;
font-size: 25px;
color: white;
}
.bigDiv li {
display: inline-block;
width: 100px;
height: 100px;
background-color: purple;
}
<body ng-app="app" ng-controller="controller">
<div class="bigDiv">
<ul>
<li ng-repeat="todo in todoArray">
<div class="circle">
<div class="todo-last">
{{todo.text}}
</div>
</div>
</li>
</ul>
</div>
</body>
<script>
var app = angular.module('app',[]);
app.controller('controller',["$scope",function ($scope) {
var randomNum = Math.ceil(Math.random() * 15 + 1);
var array = [];
for(var i = 0 ; i < randomNum; i++){
if((randomNum -2)===i ){
array.push({
text: 100
});
continue;
}
array.push(
{text: i}
)
}
$scope.todoArray = array;
}])
</script>
One more thing only hides the reddiv.
Seems you want to hide on the basis of array values
First write a function on scope to check if value is in array or not
$scope.display = function(val){
if($scope.todoArray.indexOf(val) < 0)
return true;
else
return false;
};
your html to show hide by ng-if, inside your ng-repeat:
<div ng-if="display(todo.text)">
// your other code
</div>

Implement nav dots to my slider?

I've been messing around with my slider and I got it to slide by itself. The problem is, there is no way you can manually view the slides. I would like to add navigation dots on the bottom so you can skim through the slides without having to view them as the slider goes along. If you could help me with this it would be greatly appreciated.
My slider html:
<div id="slider-container">
<div style="position: relative">
<div class="slide"><img id="slide_1" src="images/slide_1.jpg"/></div>
<div class="slide"><img id="slide_2" src="images/slide_2.jpg"/></div>
<div class="slide"><img id="slide_3" src="images/slide_3.jpg"/></div>
<div class="slide"><img id="slide_4" src="images/slide_4.jpg"/></div>
<div class="slide"><img id="slide_5" src="images/slide_5.jpg"/></div>
<div class="slide"><img id="slide_6" src="images/slide_6.jpg"/></div>
</div>
</div>
My slider css:
.slide-container {
display:block;
}
.slide {
top:0;
width:760px;
height:420px;
display:block;
position:absolute;
transform:scale(0);
transition:all .7s;
}
.slide img {
width:100%;
height:100%;
border-radius:6px;
border:1px solid #95ca1a;
}
My slider javascript:
$(document).ready(function() {
(function (){
var count = $(".slide > img").length;
var current = 1;
var sliderNext = 2;
$("img[id^='slide_']").fadeOut(0);
$("#slide_" + current).fadeIn(300);
var loop = setInterval(function() {
$("#slide_" + current).fadeOut(300);
$("#slide_" + sliderNext).fadeIn(300);
(sliderNext >= count) ? sliderNext = 1 : sliderNext++;
(current >= count) ? current = 1 : current++;
}, 3000)
})()
});
Here's an example of what I mean by nav dots:
CSS Slider - Codepen
First create list of dots, you can do it manually by creating list of "li" tags or can create it via jQuery.
here is code
<ol>
<li></li>
<li></li>
<li></li>
</ol>
number of "li" element should match with number of images
then have following css
#slider-container {
position:relative;
overflow:hidden;
width:100%;
height:380px;
display:inline-block;
}
.slide {
top:0;
width:100%;
display:inline-block;
}
.slide img {
width:100%;
height:100%;
border-radius:6px;
border:1px solid #95ca1a;
}
/******* css of dots ****/
ol{
list-style= none;
width:100%;
}
ol li{
background: #888;
border-radius: 50%;
display: inline-block;
width:20px;
height:20px;
cursor: pointer;
}
then add following jQuery stuff
$('ol li').bind('click', function(){
var index = $(this).index() + 1;
$(".active").fadeOut(300);
$("#slide_" + index).fadeIn(300);
$(".slide").removeClass("active");
$("#slide_" + index).addClass("active");
});
this code will hide active image and shows selected image
here is Fiddle example
hope it will help you
Here is a carousel script I wrote for a project. This allows you to click forward and backward and also on the dots. It's also dynamic so if you have 1 image, there are no dots or scroll bars, if you have 2 images there are the bars to go right and left but no dots, once you have three or more images the dots will be applied.
JsFiddle
HTML
<div class="carousel-container">
<div class="left-arrow"></div>
<div class="right-arrow"></div>
<div class="carousel-image-holder">
<img src="http://digitaljournal.com/img/8/7/8/4/4/i/1/1/7/o/ulingan_kids.jpg" />
<img src="http://freethoughtblogs.com/taslima/files/2012/06/22-funny2.jpg" />
<img src="http://blog.metrotrends.org/wp-content/uploads/2013/09/childPoverty.jpg" />
<img src="http://www.chinadaily.com.cn/china/images/2010WenUN/attachement/jpg/site1/20100921/0013729ece6b0e01d9691a.jpg" />
</div>
</div>
<div class="clear"></div>
<div class="carousel-buttons-container">
<ul></ul>
</div>
CSS
.clear{clear:both;}
.carousel-container{
width: 600px;
height: 360px;
float: left;
margin: 0;
padding: 0;
position: relative;
overflow: hidden;
}
.right-arrow{
width: 60px;
height: 100%;
background-color: rgba(0,0,0,.5);
position: absolute;
right: 0;
margin: 0;
padding: 0;
z-index: 2;
}
.left-arrow{
width: 60px;
height: 100%;
background-color: rgba(0,0,0,.5);
position: absolute;
left: 0;
margin: 0;
padding: 0;
z-index: 2;
}
.carousel-image-holder{
height:360px;
width: 2400px;
margin: 0;
padding: 0;
position: absolute;
z-index: 1;
}
.carousel-image-holder img{
width: 600px;
float: left;
margin: 0;
padding: 0;
display: inline-block;
}
.carousel-buttons-container{
width: 600px;
text-align: center;
margin: 15px 0 0 0;
padding: 0;
}
.carousel-buttons-container ul{
list-style-type: none;
margin: 0;
padding: 0;
}
.carousel-buttons{
background-color: #dddddd;
height: 18px;
width: 18px;
border-radius: 50%;
display: inline-block;
margin: 0 10px 0 0;
padding: 0;
cursor: pointer;
}
.carousel-buttons:last-of-type{
margin: 0;
}
.active{
background-color: #e67e22;
}
JQUERY
$(".left-arrow").hide();
var numImgs = $('div.carousel-image-holder img').length;
var addId = numImgs;
if(numImgs == 2){
var clicked = 0;
imgCount = numImgs-2;
}else if(numImgs <= 1){
$(".right-arrow").hide();
}else{
var clicked = 1;
imgCount = numImgs-1;
}
if(numImgs > 2){
for (var i=0; i<numImgs; i++){
$("ul").prepend('<li class="carousel-buttons" id="carousel'+addId+'"></li>');
var addId = addId - 1;
}
}else{
}
$(".carousel-buttons").click(function(){
var findIdClicked = $(this).attr("id");
var splitString = findIdClicked.split("carousel")
var findTheNumb = splitString[1];
$(".carousel-buttons").removeClass("active");
$(this).addClass("active");
clicked = parseInt(findTheNumb);
var adjustNumberforSlide = findTheNumb-1;
$(".carousel-image-holder").animate({"left": -(600*adjustNumberforSlide)+"px"});
console.log(clicked);
if(findTheNumb == 1){
$(".left-arrow").hide();
$(".right-arrow").show();
}else if (findTheNumb == numImgs){
$(".right-arrow").hide();
$(".left-arrow").show();
}else{
$(".right-arrow").show();
$(".left-arrow").show();
}
});
$(".carousel-buttons-container").find("li").first().addClass("active");
$(".right-arrow").click(function(){
if (clicked < imgCount){
$(".carousel-image-holder").animate({"left": "-=600px"});
console.log(clicked);
}else{
$(".carousel-image-holder").animate({"left": "-=600px"});
$(".right-arrow").hide();
console.log(clicked);
}
clicked = clicked+1;
$(".left-arrow").show();
$(".carousel-buttons").removeClass("active");
$("#carousel"+clicked).addClass("active");
});
$(".left-arrow").click(function(){
if (clicked > 2){
$(".carousel-image-holder").animate({"left": "+=600px"});
console.log(clicked);
}else{
$(".carousel-image-holder").animate({"left": "+=600px"});
$(".left-arrow").hide();
console.log(clicked);
}
$(".right-arrow").show();
clicked = clicked-1;
$(".carousel-buttons").removeClass("active");
$("#carousel"+clicked).addClass("active");
});
I'll clean up the spacing, just wanted to get this posted

Categories

Resources