Image size does not change when I configured as responsive design - css

What I want to do
I created the homepage that has some images. I would like to show up them by the responsive design. However, all image files' size are not changed when I show on the iPhone.
There are 3 types img files on HP.
The images are ...
files shows up by changing the 3 pics by each 2 seconds at the same place.
normal img files.
As the gallery, that the img file change to show up by clicking the thumbnail button.
All of them are not changed img size when responsive.
//const img = ["hoge.png", "foo.png", "bar.jpg"];
const img = ["https://lh3.googleusercontent.com/taykG37GWDgY-FGkdogDvsHSJMUGRMvkuVRT6yR-5UNkKvGRKeRlpGYXlslocOcS0txlfUdGW59JGtzADknxbMqnh6AtVCv9EXyB8nHp80YsRNA0Yw=w1024-h683-n-l50-sg-rj", "https://lh3.googleusercontent.com/fl-GT6w3Ls6RT4vYnbkuYUyLY3lZJH8VtZ7xzxiym9YYaoVRCnZehdz6Icd0oAf6i3H9-O5cCNs6eunlxWr_Csstgsb98DdzNdLFBOlhw9NUfHdyuQjI=w768-h1024-n-l50-sg-rj", "https://lh3.googleusercontent.com/9pPCK70Rw0k3wethMHb1qMaIB0VjeWLy57vYgSzKbF7oJuvO2nA0Nakk-95cvibWUDcEhYkfCKvdPKT03tXZd4M5jdhIEibLO9qw-XE=w1024-h683-n-l50-sg-rj"];
let count = -1;
const hoge = () => {
count++;
// カウントが最大になれば初期値に戻す
if (count == img.length) count = 0;
//画像選択
pic.src = img[count];
//1秒ごとに実行
setTimeout(() => {
hoge();
}, 2000);
}
window.onload = () => {
hoge();
}
//アルバムデータの作成
let album = [{
src: 'img/1.png',
msg: 'さまざまな形のパスタと自然の恵みを生かしたイタリアン'
},
{
src: 'img/2.png',
msg: 'パスタだけでなく軽食やスイーツも'
},
{
src: 'img/3.png',
msg: '肉料理やピザもイタリアン料理を彩ります'
},
{
src: 'img/4.png',
msg: '豊富な種類のピザ'
},
{
src: 'img/5.png',
msg: 'チーズが主役だったり生ハムが主役だったり、ピザの種類は豊富です'
}
];
//最初のデータを表示しておく
let mainImage = document.createElement('img');
mainImage.setAttribute('src', album[0].src);
mainImage.setAttribute('alt', album[0].msg);
let mainMsg = document.createElement('p');
mainMsg.innerText = mainImage.alt;
let mainFlame = document.querySelector('#gallery .main');
mainFlame.insertBefore(mainImage, null);
mainFlame.insertBefore(mainMsg, null);
//サムネイル写真の表示
let thumbFlame = document.querySelector('#gallery .thumb');
for (let i = 0; i < album.length; i++) {
let thumbImage = document.createElement('img');
thumbImage.setAttribute('src', album[i].src);
thumbImage.setAttribute('alt', album[i].msg);
thumbFlame.insertBefore(thumbImage, null);
}
//クリックした画像をメインにする
thumbFlame.addEventListener('click', function(event) {
if (event.target.src) {
mainImage.src = event.target.src;
mainMsg.innerText = event.target.alt;
}
});
.under {
border-bottom: dotted 2px #87cdfa
}
.fixed {
width: 300px;
height: auto;
}
img.calbo {
width: 100%;
height: auto;
}
img.pepe {
width: 100%;
height: auto;
}
#gallery {
margin: 0;
padding-top: 40px;
width: 700px;
}
#gallery .main img {
border: 4px solid #fff;
box-shadow: 0;
}
#gallery .main p {
color: #bbb;
font-size: 20px;
font-weight: bold;
}
#gallery .thumb img {
border: 4px solid #fff;
border-radius: 400px;
box-shadow: 0px 0px 10px #000;
height: 60px;
margin: 10px;
width: 60px;
cursor: pointer;
}
#media screen and (max-width: 480px) {
test {
float: none;
}
img {
width: 100%;
}
}
<h1>
<font color="#EEEEEE">レシピ ~ カルボナーラとペペロンチーノ</h1>
<br>
<hr width="700" align="left">
<!--- html ----->
<img id="pic" src="hoge.png" width="600" height=auto class="top">
<p>
<table>
<tr>
<th class="fixed"><img src="calbo150.png" class="calbo"></th>
<td style="background-color:#476072">
ちょっとしたひと工夫で普通の手作り<br> カルボからお店風本格カルボに。
<br> 失敗もしない簡単レシピ
<br><br>
カルボナーラのレシピ
</td>
</tr>
<tr>
<th class="fixed"><img src="pepe.jpg" class="pepe"></th>
<td style="background-color:#476072">
簡単だけど難しいペペロンチーノ。<br> 材料と水分調整がうまくいけば本格的な
<br> ペペロンチーノに仕上がります。
<br><br>
ペペロンチーノのレシピ
</td>
</tr>
</table>
</p>
<!-- JavaScript -->
<div id="gallery">
<div class="main">
</div>
<div class="thumb">
</div>
</div>

Although I didn’t paste the full HTML here, I used the double byte double quotation in the settings of the Viewport line. After I modified to single byte one, it started to work.

Related

How to Add a Space in Line Numbers in Textarea Word Wrap in Svelte

I have a text area with CSS generated line numbers for each new line.
Everything works great, except for when there is a word wrap. If I get a word wrap, it does not wrap the new line text. I would like to make my line numbers word wrap with the text.
Here is a notepad+ example:
And here is a GitHub example:
How can I automatically detect and add a word wrap to my line numbers as well? Here is my code:
<script lang="ts">
export let source = `jon
sup
me
fixin to do sumthin good`;
let numberOfLines = source.split('\n').length;
const KeyUp = (event: Event) => {
const textarea = event.target as HTMLInputElement;
numberOfLines = textarea.value.split('\n').length;
};
const KeyDown = (event: Event) => {
const textarea = event.target as HTMLInputElement;
if ((event as KeyboardEvent).key === 'Tab') {
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
if (start && end) {
textarea.value = textarea.value.substring(0, start) + '\t'
+ textarea.value.substring(end);
event.preventDefault();
}
}
};
</script>
<center>
<div class="editor">
<div class="line-numbers">
{#each Array(numberOfLines) as _}
<span class="new-line" />
{/each}
</div>
<textarea class="text-content"
on:keyup={KeyUp} on:keydown={KeyDown} value={source} rows="15" />
</div>
</center>
<style>
.editor {
display: inline-flex;
gap: 10px;
font-family: monospace;
line-height: 21px;
background: #282a3a;
border-radius: 2px;
padding: 20px 10px;
}
.line-numbers {
width: 20px;
text-align: right;
}
.line-numbers .new-line {
counter-increment: linenumber;
}
.line-numbers .new-line::before {
content: counter(linenumber);
display: block;
color: #506882 !important;
}
.text-content {
line-height: 21px;
overflow-y: hidden;
padding: 0;
border: 0;
background: #282a3a;
color: #fff;
min-width: 500px;
outline: none;
resize: none;
}
</style>
And here is the StackBlitz Link:
(right click - open in new window)
Thanks!
J
Image for responding to comment below:
An approach could be to read the width of one character of the monospace font from an invisible element and set the textarea width to a multiple to avoid rounding errors. It then can be calculated for each substring between the line breaks how often it is wrapped and a margin-bottom added to the corresponding line number accordingly
REPL
<script>
import {onMount} from 'svelte'
export let source = `jon\nsup there is some other text here that I want to go across the lines and not word wrap another line etc boy!\nme\nfixin to do sumthin good`;
let fontWidthElem
let fontWidth
let charactersPerLine = 60
$: areaWidth = charactersPerLine * fontWidth
onMount(() => {
fontWidth = fontWidthElem.getBoundingClientRect().width
})
function wrapped(str, timesWrapped) {
if(str.length > charactersPerLine) {
const firstLine = str.substring(0, charactersPerLine)
const spaceOrDashInFirstLine = /[ -]/.test(firstLine)
const lastCharFirstLine = str[charactersPerLine-1]
const firstCharNextLine = str[charactersPerLine]
const wordIsCut = lastCharFirstLine !== '-' && lastCharFirstLine !== ' ' && firstCharNextLine !== ' ' && firstCharNextLine !== '-'
const nextLine = str.substring(charactersPerLine)
const nextLineNotOnlySpaces = nextLine.replaceAll(' ', '').length > 0
if(wordIsCut && spaceOrDashInFirstLine){
const lastIndexOfDivider = Math.max(firstLine.lastIndexOf(' '), firstLine.lastIndexOf('-'))
return wrapped(str.substring(lastIndexOfDivider+1), timesWrapped+1)
}else if(nextLineNotOnlySpaces){
return wrapped(nextLine.trimStart(), timesWrapped+1)
}else {
return timesWrapped
}
}else {
return timesWrapped
}
}
</script>
<div class="editor">
<div class="line-numbers">
{#each source.split('\n') as subStr, index}
<div class="line-nr"
style:margin-bottom="calc(var(--line-height) * {wrapped(subStr, 0)})"
>
{index + 1}
</div>
{/each}
</div>
<textarea bind:value={source}
style:width="{areaWidth}px"
rows="15"
/>
<div id="font-width"
bind:this={fontWidthElem}
>
a
</div>
</div>
<style>
:global(body) {
padding: 0;
}
.editor {
--line-height: 21px;
position: relative;
display: inline-flex;
gap: 10px;
padding: 20px 10px;
font-family: monospace;
line-height: var(--line-height);
background: #282a3a;
border-radius: 2px;
}
.line-nr {
width: 20px;
text-align: right;
color: #506882 !important;
}
textarea {
line-height: var(--line-height);
overflow-y: hidden;
margin: 0;
padding: 0;
border: 0;
background: #282a3a;
color: #fff;
outline: none;
resize: none;
}
#font-width {
position: absolute;
top: -1000px;
left: -1000px;
visibility: hidden;
}
</style>
To make the width responsive
additional editor wrapper for padding
watch editor width and calculate maximal possible charactersPerLine for textarea besides line numbers element
charactersPerLine added as argument to wrapped() for recalculation on change
REPL
<script>
import {onMount} from 'svelte'
export let source = `jon\nsup there is some other text here that I want to go across the lines and not word wrap another line etc boy!\nme\nfixin to do sumthin good`;
let fontWidthElem
let fontWidth
let editorWidth
onMount(() => {
fontWidth = fontWidthElem.getBoundingClientRect().width
})
let lineNumbersWidth = 30
$: charactersPerLine = Math.floor((editorWidth - lineNumbersWidth) / fontWidth)
function wrapped(str, charactersPerLine, timesWrapped) {
if(str.length > charactersPerLine) {
const firstLine = str.substring(0, charactersPerLine)
const spaceOrDashInFirstLine = /[ -]/.test(firstLine)
const lastCharFirstLine = str[charactersPerLine-1]
const firstCharNextLine = str[charactersPerLine]
const wordIsCut = lastCharFirstLine !== '-' && lastCharFirstLine !== ' ' && firstCharNextLine !== ' ' && firstCharNextLine !== '-'
const nextLine = str.substring(charactersPerLine)
const nextLineNotOnlySpaces = nextLine.replaceAll(' ', '').length > 0
if(wordIsCut && spaceOrDashInFirstLine){
const lastIndexOfDivider = Math.max(firstLine.lastIndexOf(' '), firstLine.lastIndexOf('-'))
return wrapped(str.substring(lastIndexOfDivider+1), charactersPerLine, timesWrapped+1)
}else if(nextLineNotOnlySpaces){
return wrapped(nextLine.trimStart(), charactersPerLine, timesWrapped+1)
}else {
return timesWrapped
}
}else {
return timesWrapped
}
}
</script>
<div class="editor-wrapper">
<div class="editor"
bind:clientWidth={editorWidth}
>
<div class="line-numbers"
style:width="{lineNumbersWidth}px"
>
{#each source.split('\n') as subStr, index}
<div class="line-nr"
style:margin-bottom="calc(var(--line-height) * {wrapped(subStr, charactersPerLine, 0)})"
>
{index + 1}
</div>
{/each}
</div>
<textarea bind:value={source}
style:width="{charactersPerLine}ch"
rows="15"
/>
<div id="font-width"
bind:this={fontWidthElem}
>
a
</div>
</div>
</div>
<style>
:global(body) {
padding: 0;
}
:global(*) {
box-sizing: border-box;
}
.editor-wrapper {
--line-height: 21px;
padding: 20px 10px;
background: #282a3a;
border-radius: 2px;
}
.editor {
position: relative;
display: flex;
width: 100%;
font-family: monospace;
line-height: var(--line-height);
}
.line-numbers {
padding-right: 10px;
text-align: right;
color: #506882 !important;
}
textarea {
line-height: var(--line-height);
overflow-y: hidden;
margin: 0;
padding: 0;
border: 0;
background: #282a3a;
color: #fff;
outline: none;
resize: none;
/* border seems to falsify calculation! */
/* box-shadow: 0 0 0 1px grey; */
}
#font-width {
position: absolute;
top: -1000px;
left: -1000px;
visibility: hidden;
}
</style>

How to fix v-align styling for imgs with different sizes in Vue.js transition-group?

I prepared example of image slider what I need.
I encounter with styling issue when using images with various dimensions. When element leaving the array, its location is set as absolute value, what is necessary for smooth transition, tho, but the image is also moved up.
I would like to have nice vertical align into middle even leave or enter the array, but could not get on any way.
Another issue, what I would like to solve is when left the window and then went back after a while. The animation running all cycles at once to reach current state instead just stop animation and run after. Maybe it is my responsibility, but browsers doesn't offer nice event to catch blur window or am I wrong?
According to this discussion
Thank you for any ideas.
let numbers = [{key:1},{key:2},{key:3},{key:4},{key:5},{key:6},{key:7}]
let images = [
{ key:1,
src:"http://lorempixel.com/50/100/sports/"},
{ key:2,
src:"http://lorempixel.com/50/50/sports/"},
{ key:3,
src:"http://lorempixel.com/100/50/sports/"},
{ key:4,
src:"http://lorempixel.com/20/30/sports/"},
{ key:5,
src:"http://lorempixel.com/80/20/sports/"},
{ key:6,
src:"http://lorempixel.com/20/80/sports/"},
{ key:7,
src:"http://lorempixel.com/100/100/sports/"}
]
new Vue({
el: '#rotator',
data: {
items: images,
lastKey: 7,
direction: false
},
mounted () {
setInterval(() => {
if (this.direction) { this.prevr() } else { this.nextr() }
}, 1000)
},
methods: {
nextr () {
let it = this.items.shift()
it.key = ++this.lastKey
this.items.push(it)
},
prevr () {
let it = this.items.pop()
it.key = ++this.lastKey
this.items.unshift(it)
}
}
})
.litem {
transition: all 1s;
display: inline-block;
margin-right: 10px;
border: 1px solid green;
background-color: lightgreen;
padding: 10px 10px 10px 10px;
height: 100px;
}
.innerDiv {
border: 1px solid red;
}
.container {
overflow: hidden;
white-space: nowrap;
height: 250px;
border: 1px solid blue;
background-color: lightblue;
}
.list-enter {
opacity: 0;
transform: translateX(40px);
}
.list-leave-to {
opacity: 0;
transform: translateX(-40px);
}
.list-leave-active {
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.11/vue.js"></script>
<div id="rotator">
<button #click="direction = !direction">
change direction
</button>
<transition-group
name="list"
tag="div"
class="container">
<div
v-for="item in items"
:key="item.key" class="litem">
<!--
<div
class='innerDiv'>
{{ item.key }}
</div>
-->
<div class='innerDiv'>
<img :src='item.src'>
</div>
</div>
</transition-group>
</div>
It tooks a while but on the end I think that I have got better result for sliding animation with changing direction feature.
One annoying think is when I swithing the sliding direction so animation is for a 'microsecond' changed to next state and than return to correct one, after it the animation continue as expected. It is happening only in one direction and I don't know how to fix it. Also last box behave differently too only once. No clue at all.
So just 98% solution :-)
let images = [
{key:1, domKey:1, src:"http://lorempixel.com/50/100/sports/" },
{key:2, domKey:2, src:"http://lorempixel.com/50/50/sports/" },
{key:3, domKey:3, src:"http://lorempixel.com/100/50/sports/" },
{key:4, domKey:4, src:"http://lorempixel.com/20/30/sports/" },
{key:5, domKey:5, src:"http://lorempixel.com/80/20/sports/" },
{key:6, domKey:6, src:"http://lorempixel.com/20/80/sports/" },
{key:7, domKey:7, src:"http://lorempixel.com/100/100/sports/" }
]
let setPositionRelative = el => el.style.position = "relative"
new Vue({
el: '#rotator',
data: {
items: images,
lastKey: 7,
direction: true,
changeDirectionRequest: false
},
mounted () {
Array.from(this.$el.querySelectorAll("div[data-key]")).map(setPositionRelative)
setInterval(() => {
if(this.changeDirectionRequest) {
this.changeDirectionRequest = false
this.direction = !this.direction
if (this.direction)
Array.from(this.$el.querySelectorAll("div[data-key]")).map(setPositionRelative)
else
Array.from(this.$el.querySelectorAll("div[data-key]")).map(el => el.style.position = "")
}
if (this.direction) this.prevr()
else this.nextr()
}, 1000)
},
methods: {
nextr () {
let it = this.items.shift()
it.key = ++this.lastKey
this.items.push(it)
},
prevr () {
let it = this.items.pop()
it.key = ++this.lastKey
this.items.unshift(it)
setPositionRelative(this.$el.querySelector("div[data-domkey='"+it.domKey+"']"))
}
}
})
.container {
overflow: hidden;
white-space: nowrap;
height: 200px;
border: 1px solid blue;
background-color: lightblue;
display: flex;
align-items: center;
}
.innerDiv {
border: 1px solid red;
width: auto;
height: auto;
display:-moz-box;
-moz-box-pack:center;
-moz-box-align:center;
display:-webkit-box;
-webkit-box-pack:center;
-webkit-box-align:center;
display:box;
box-pack:center;
box-align:center;
}
.litem {
transition: all 1s;
margin-right: 10px;
border: 1px solid green;
background-color: lightgreen;
padding: 10px 10px 10px 10px;
}
.list2-enter, .list-enter {
opacity: 0;
transform: translateX(40px);
}
.list2-leave-to, .list-leave-to {
opacity: 0;
transform: translateX(-40px);
}
.list-leave-active {
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.11/vue.js"></script>
<div id="rotator">
<button #click="changeDirectionRequest = true">change direction</button>
<transition-group name="list" tag="div" class="container">
<div v-for="item in items"
:key="item.key"
:data-domkey="item.domKey"
class="litem">
<div class='innerDiv'>
<img :src='item.src'>
</div>
</div>
</transition-group>
</div>

Individually color code ToDo cells, not just change everything

I have created a basic to-do list. I want to add the option to color code, similar to Google Keep (this is an exercise). I have tried simply putting one HTML select in, as you can see in my jsfiddle but this changes the background of that entire section.
<p display="none">
<section class="main" style="display: block;" >
<div data-bind="visible:todos().length>0">
<input id="toggle-all" type="checkbox" data-bind="checked:markAll"/>
<label for="toggle-all">Mark all as complete</label>
<br /><br />
<select id="colorOptions" id="toggle-all"></select>
</div>
<ul id="mycell" class="todo-list" data-bind="template:{ name:'item-template',foreach: todos}">
</ul>
</section>
</p>
Question: How do I add an option to individually color code the to-do items?
Ok, I did it using the templates. First I added the selection for the colors inside the template in the li, so that every entry has a selection. Then I added an id for every selection (which is the order variable, the first <select> has the id="0" the second has the id="1" and so on) in order to differentiate them and to make each of them have different functions onchange. I also made the addColorsOptions function which adds the options on every selection when it is created using its unique id.
$(function(){
var Todo = function(id, title, done, order,callback) {
var self = this;
self.id = ko.observable(id);
self.title = ko.observable(title);
self.done = ko.observable(done);
self.order = order;
self.updateCallback = ko.computed(function(){
callback(self);
return true;
});
}
var viewModel = function(){
var self = this;
self.todos = ko.observableArray([]);
self.inputTitle = ko.observable("");
self.doneTodos = ko.observable(0);
self.markAll = ko.observable(false);
self.addOne = function() {
var order = self.todos().length;
var t = new Todo(order, self.inputTitle(),false,order,self.countUpdate);
self.todos.push(t);
self.addColorsOptions(order);
};
self.createOnEnter = function(item,event){
if (event.keyCode == 13 && self.inputTitle()){
self.addOne();
self.inputTitle("");
}else{
return true;
};
}
self.toggleEditMode = function(item,event){
$(event.target).closest('li').toggleClass('editing');
}
self.editOnEnter = function(item,event){
if (event.keyCode == 13 && item.title){
item.updateCallback();
self.toggleEditMode(item,event);
}else{
return true;
};
}
self.markAll.subscribe(function(newValue){
ko.utils.arrayForEach(self.todos(), function(item) {
return item.done(newValue);
});
});
self.countUpdate = function(item){
var doneArray = ko.utils.arrayFilter(self.todos(), function(it) {
return it.done();
});
self.doneTodos(doneArray.length);
return true;
};
self.countDoneText = function(bool){
var cntAll = self.todos().length;
var cnt = (bool ? self.doneTodos() : cntAll - self.doneTodos());
var text = "<span class='count'>" + cnt.toString() + "</span>";
text += (bool ? " completed" : " remaining");
text += (self.doneTodos() > 1 ? " items" : " item");
return text;
}
self.clear = function(){
self.todos.remove(function(item){ return item.done(); });
}
self.addColorsOptions = function(id){
var colors = [{
display: "light yellow",
value: "ffffcc"
}, {
display: "light blue",
value: "ccffff"
}, {
display: "light green",
value: "ccffcc"
}, {
display: "gray",
value: "cccccc"
}, {
display: "white",
value: "ffffff"
}];
var options = ['<option value="">Select color</option>'];
for(var i = 0; i < colors.length; i++){
options.push('<option value="');
options.push(colors[i].value);
options.push('">');
options.push(colors[i].display);
options.push('</option>');
}
$("#" + id).html(options.join('')).change(function(){
var val = $(this).val();
if(val){
$("#" + id).closest('li').css('backgroundColor', '#' + val);
}
});
}
};
ko.applyBindings(new viewModel());
})
body {
font-size: 14px;
background-color: #3c6dc5;
color: #333333;
width: 520px;
margin: 0 auto;
}
#todoapp {
background-color: #3c6dc4;
padding: 20px;
margin-bottom: 40px;
}
#todoapp h1 {
font-size: 36px;
text-align: center;
color:white;
}
#todoapp input[type="text"] {
width: 466px;
font-size: 24px;
line-height: 1.4em;
padding: 6px;
color:#000033;
}
.main {
display: none;
}
.todo-list {
margin: 10px 0;
padding: 0;
list-style: none;
color: #E0E0EF;
}
.todo-list li {
padding: 18px 20px 18px 0;
position: relative;
font-size: 24px;
border-bottom: 1px solid #cccccc;
}
.todo-list li:last-child {
border-bottom: none;
}
.todo-list li .edit {
display: none;
}
.todo-list li.editing {
border-bottom: 1px solid #778899;
}
.todo-list li.editing .view {
display: none;
}
.todo-list li.editing .edit {
display: block;
width: 444px;
padding: 13px 15px 14px 20px;
margin: 0;
}
.todo-list li.done label {
color: #777777;
text-decoration: line-through;
}
.todo-list .destroy {
position: absolute;
right: 5px;
top: 20px;
display: none;
cursor: pointer;
width: 20px;
height: 20px;
}
#todoapp footer {
display: none;
margin: 0 -20px -20px -20px;
overflow: hidden;
color: #555555;
background: #f4fce8;
border-top: 1px solid #ededed;
padding: 0 20px;
line-height: 37px;
}
.todo-count {
float:left;
}
.todo-count .count{
font-weight:bold;
}
#clear-completed {
float: right;
line-height: 20px;
text-decoration: none;
background: rgba(0, 0, 0, 0.1);
color: #555555;
font-size: 11px;
margin-top: 8px;
margin-bottom: 8px;
padding: 0 10px 1px;
cursor: pointer;
}
label{color:white;}
<script src="http://knockoutjs.com/downloads/knockout-2.3.0.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="todoapp">
<header>
<h1>Fun To Do!</h1>
<input id="new-todo" type="text" placeholder="Finish Homework..." data-bind="value:inputTitle,event: { keyup: createOnEnter}"/>
</header>
<section class="main" style="display: block;" >
<div data-bind="visible:todos().length>0">
<input id="toggle-all" type="checkbox" data-bind="checked:markAll"/>
<label for="toggle-all">Mark all as complete</label> <br /><br />
</div>
<ul id="mycell" class="todo-list" data-bind="template:{ name:'item-template',foreach: todos}">
</ul>
</section>
<footer style="display: block;">
<div data-bind="visible:todos().length>0">
<div class="todo-count"><b data-bind="text:todos().length"></b> items left</div>
<!-- ko if: doneTodos() > 0 -->
<a id="clear-completed" data-bind="click:clear">
Clear <span data-bind="html:countDoneText(true)"></span>.
</a>
<!-- /ko -->
<br style="clear:both"/>
</div>
</footer>
</div>
<script type="text/template" id="item-template">
<li data-bind="event:{ dblclick :$root.toggleEditMode},css : {done:done() }">
<div class="view" >
<input class="toggle" type="checkbox" data-bind="checked:done"/>
<label data-bind="text:title"></label>
<a class="destroy"></a>
</div>
<input class="edit" type="text" data-bind="value:title,event: { keyup: $root.editOnEnter}" />
<select data-bind="attr: {'id': id}"></select>
</li>
</script>
You can also see the JSFiddle here.
For any question feel free to comment. I hope this was helpful :)
EDIT
See this JSFiddle for the <input type="color"> addition.
I tested your fiddle code. There is some unwanted code (that i did not find) that fade out your div databind="..... So to remove this problem you can add this at the end of jquery codes before last }); to see some thing like this:
$('div').show(); //adding code
});
Now the select works and you can see the changes in page inspector, But you can not see that here because your ul is empty. To see the result change that ul with an static data ul like this:
<ul id="mycell" class="todo-list">
<li>first</li>
<li>second</li>
</ul>

Double scrollbar with shrinking toolbar

I am working on a photo gallery in AngularJS using Angular Material (run the snippet in fullscreen to see my problem).
var app = angular.module('app', ['ngMaterial']);
app.controller('TitleController', function($scope) {
$scope.title = 'Gallery';
});
app.controller('GalleryCtrl', function($scope, $http, $q, $mdMedia, $mdDialog) {
//https://material.angularjs.org/latest/demo/virtualRepeat
$scope.Images = [],
//add more images
$scope.LoadMore = function() {
for (i = 0; i < 25; i++) {
var randomWidth = Math.round(Math.random() * (800 - 400) + 400);
var randomHeight = Math.round(Math.random() * (800 - 400) + 400);
$scope.Images.push({
src: "http://placehold.it/" + randomWidth + "x" + randomHeight + "/",
id: Math.round(Math.random() * 10000)
});
};
}
$scope.ShowDetails = function(ev, number) {
var useFullScreen = ($mdMedia('sm') || $mdMedia('xs')) && $scope.customFullscreen;
$mdDialog.show({
controller: DialogController,
templateUrl: 'Home/GetInfo?id=' + number,
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose: true,
fullscreen: useFullScreen
})
$scope.$watch(function() {
return $mdMedia('xs') || $mdMedia('sm');
}, function(wantsFullScreen) {
$scope.customFullscreen = (wantsFullScreen === true);
});
};
function DialogController($scope, $mdDialog) {
$scope.hide = function() {
$mdDialog.hide();
};
$scope.cancel = function() {
$mdDialog.cancel();
};
$scope.answer = function(answer) {
$mdDialog.hide(answer);
};
}
//initial loading
$scope.LoadMore();
});
body {
background: #eeeeee;
}
html {
background: #eeeeee;
}
.gridListdemoBasicUsage md-grid-list {
margin: 8px;
}
.gridListdemoBasicUsage .green {
background: #b9f6ca;
}
.gridListdemoBasicUsage md-grid-tile {
transition: all 400ms ease-out 50ms;
}
.responsiveImage {
max-width: 100%;
max-height: 100%;
}
md-content {
background: #eeeeee;
position: relative;
}
.fit {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.toolbardemoScrollShrink .face {
width: 48px;
margin: 16px;
border-radius: 48px;
border: 1px solid #ddd;
}
.md-toolbar-tools {
background-color: #259b24;
}
.dialogdemoBasicUsage #popupContainer {
position: relative;
}
.dialogdemoBasicUsage .footer {
width: 100%;
text-align: center;
margin-left: 20px;
}
.dialogdemoBasicUsage .footer,
.dialogdemoBasicUsage .footer > code {
font-size: 0.8em;
margin-top: 50px;
}
.dialogdemoBasicUsage button {
width: 200px;
}
.dialogdemoBasicUsage div#status {
color: #c60008;
}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.7/angular-material.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular-animate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular-aria.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.0.7/angular-material.min.js"></script>
<body ng-app="app" ng-controller="GalleryCtrl as gc" ng-cloak="" id="popupContainer" class="gridListdemoBasicUsage dialogdemoBasicUsage">
<md-toolbar md-scroll-shrink="" ng-if="true" ng-controller="TitleController">
<div class="md-toolbar-tools">
<h3><span>{{title}}</span></h3>
</div>
</md-toolbar>
<md-content style="height:100vh" />
<md-grid-list md-cols-xs="1" md-cols-sm="2" md-cols-md="4" md-cols-gt-md="6" md-row-height-gt-md="1:1" md-row-height="2:2" md-gutter="12px" md-gutter-gt-sm="8px">
<md-grid-tile ng-click="ShowDetails($event, n.id)" ng-repeat="n in Images" class="green">
<img class="responsiveImage" src="{{n.src}}">
<md-grid-tile-footer>
<h3>Photo number {{n.id}}</h3>
</md-grid-tile-footer>
</md-grid-tile>
</md-grid-list>
<section layout="row" layout-sm="column" layout-align="center center" layout-wrap="">
<md-button class="md-raised md-primary" ng-click="LoadMore()">Primary</md-button>
</section>
</body>
Go fullscreen, scroll to the bottom of the page, and press a button to load more images. The problem I'm having: I am trying to get the toolbar at the top of the screen to disappear when scrolling down, and appear again when scrolling up. However, 2 scrollbars appear, and only the right one affects the toolbar.The left scrollbar actually scrolls all the way down on the page.
My desired situation: only 1 visible scrollbar to scroll down the entire gallery, that also makes the toolbar appear and disappear. How do I do this?
try adding overflow-y: hidden; to the body css rule.

Turn cell content to editable input box

When creating a fluid layout, where content can be dragged around and edited inside a table I ran into a problem.
After clicking on any of the <a></a> hyperlinks the cell content should be replaced by an editable input box.
This gets done, but the cell changes its size and wrecks the original layout.
The cell size should not change after click. It should be possible to achieve this by editing the CSS and adding Bootstrap classes.
var viewModel = function() {
var self = this;
self.gridItems = ko.observableArray(
[{
"rowItems": [{
"name": "Item 1"
}, {
"name": "Item 2"
}, {
"name": "Item 3"
}]
}, {
"rowItems": [{
"name": "Item 4"
}, {
"name": "Item 5"
}]
}]
);
self.selectedRowItem = ko.observable();
};
//connect items with observableArrays
ko.bindingHandlers.sortableList = {
init: function(element, valueAccessor, allBindingsAccessor, context) {
$(element).data("sortList", valueAccessor()); //attach meta-data
$(element).sortable({
update: function(event, ui) {
var item = ui.item.data("sortItem");
if (item) {
//identify parents
var originalParent = ui.item.data("parentList");
var newParent = ui.item.parent().data("sortList");
//figure out its new position
var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]);
if (position >= 0) {
originalParent.remove(item);
newParent.splice(position, 0, item);
}
ui.item.remove();
}
},
connectWith: '.sortable-container'
});
}
};
//attach meta-data
ko.bindingHandlers.sortableItem = {
init: function(element, valueAccessor) {
var options = valueAccessor();
$(element).data("sortItem", options.item);
$(element).data("parentList", options.parentList);
}
};
//control visibility, give element focus, and select the contents (in order)
ko.bindingHandlers.visibleAndSelect = {
update: function(element, valueAccessor) {
ko.bindingHandlers.visible.update(element, valueAccessor);
if (valueAccessor()) {
setTimeout(function() {
$(element).focus().select();
}, 0); //new RowItems are not in DOM yet
}
}
}
ko.applyBindings(new viewModel());
//$(".sortable").sortable({});
.sortable {
list-style-type: none;
margin: 0;
padding: 0;
width:100%;
}
.sortable li {
margin: 0 3px 3px 3px;
padding: 0.4em;
padding-left: 1.5em;
font-size: 1.4em;
height: 18px;
cursor: move;
}
.sortable li span {
position: absolute;
margin-left: -1.3em;
}
.sortable li.fixed {
cursor: default;
color: #959595;
opacity: 0.5;
}
.sortable-grid {
width: 100% !important;
}
.sortable-row {
height: 100% !important;
padding: 0 !important;
margin: 0 !important;
display: block !important;
}
.sortable-item {
border: 1px solid black;
margin: 0 !important;
}
.sortable-item > a {
display: block;
margin: 0 !important;
}
.sortable-item input {
display: block;
margin: 0 !important;
}
.sortable-container {
margin: 0 !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.0-beta.1/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet" />
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul class="sortable sortable-grid" data-bind="template: { name: 'gridTmpl', foreach: gridItems, templateOptions: { parentList: gridItems} }, sortableList: gridItems">
</ul>
<script id="gridTmpl" type="text/html">
<li class="sortable-row">
<table style="width:100%">
<tbody>
<tr class="sortable sortable-container" data-bind="template: { name: 'rowTmpl', foreach: rowItems, templateOptions: { parentList: rowItems} }, sortableList: rowItems">
</tr>
</tbody>
</table>
</li>
</script>
<script id="rowTmpl" type="text/html">
<td class="sortable-item" data-bind="sortableItem: { item: $data, parentList: $data.parentList }">
<input data-bind="value: name, visibleAndSelect: $data === $root.selectedRowItem()" />
</td>
</script>
On your table, set table-layout to fixed. Another improvement would be to make the inputs take up the entire space of the cell.
Here are the css changes to make:
.sortable-item input {
display: block;
margin: 0 !important;
width: 100%; /* Added this property */
}
/* Added this rule */
.sortable-row > table {
table-layout: fixed;
}

Resources