AngularJS use image/icon as filter option - angularjs

I have to filter a gallery by clicking on icons, i.e. the male icon should filter only male images (as the dropdown above does) and the same for the females.
so the dropdown shows what i'm trying to do with the icons, but the icons themselves don't work... what am I missing? Thanks a lot for your help!!
var galleryApp = angular.module('galleryApp', []);
galleryApp.controller('galleryController', function galleryController($scope) {
$scope.images = [
{
"source" : "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/jeremiah-wilson-1.jpg",
"altText" : "Person 1",
"type" : "female, all"
},
{
"source" : "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/jeremiah-wilson-2.jpg",
"altText" : "Person 2",
"type" : "malex, all"
},
{
"source" : "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/jeremiah-wilson-3.jpg",
"altText" : "Person 3",
"type" : "malex, all"
},
{
"source" : "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/jeremiah-wilson-4.jpg",
"altText" : "Person 4",
"type" : "malex, all"
},
{
"source" : "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/jeremiah-wilson-5.jpg",
"altText" : "Person 5",
"type" : "female, all"
}
];
});
body { margin: 0; background: #333; }
#mainGallery {
padding: .5vw;
font-size: 0;
display: -ms-flexbox;
-ms-flex-wrap: wrap;
-ms-flex-direction: column;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
display: -webkit-box;
display: flex;
}
#mainGallery .imgBlock {
-webkit-box-flex: auto;
-ms-flex: auto;
flex: auto;
width: 200px;
margin: .5vw;
}
#mainGallery .imgBlock img {
width: 100%;
height: auto;
}
#seperator {
width: 100%;
height: 1px;
display: block;
}
.search {
background: #222;
border: 1px solid black;
width: 500px;
padding: 10px 0;
margin: .5vw auto .5vw auto;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
.dropdown {
margin-left: 15px;
}
.filterImageWrapper {
position: relative;
width: 470px;
overflow: hidden;
margin: 15px;
}
.filterImage {
width: 470px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
-webkit-transform: translateX(0);
transform:translateX(0);
-webkit-transition: all 1s;
transition: all 1s;
}
#overlayFilter {
opacity:0;
position: absolute;
top: 0;
left: 0;
z-index: 100;
width: 470px;
-webkit-transition:all 1s;
transition:all 1s;
}
#overlayFilter.overlayOpacity {
opacity: 1;
}
#filterBar {
width: 100%;
height: 60px;
background: #666;
margin: .5vw;
-webkit-border-radius: 7px;
border-radius: 7px;
border: 1px solid black;
}
.selectedFarbig {
-webkit-transform: scale(4,4) translate(-40px, 50px);
transform: scale(4,4) translate(-40px, 50px);
}
.galleryItems {
-webkit-filter: grayscale(.9) sepia(.3);
filter: grayscale(.9) sepia(.3);
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
webkit-transition: all .4s;
transition: all .4s;
}
.galleryItems:hover {
-webkit-filter: grayscale(.1) sepia(.8);
}
#filterBar input:first-child {
height: 50px;
}
#filterBar input:nth-child(2) {
height: 50px;
}
#media screen and (max-width: 400px) {
#mainGallery .imgBlock { margin: 0; }
#mainGallery { padding: 0; }
}
<!doctype html>
<html ng-app="galleryApp">
<head>
<meta charset="UTF-8">
<title>Filter Gallery</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="controllers.js"></script>
<link href="main.css" rel="stylesheet" type="text/css">
</head>
<body>
<div ng-controller = "galleryController" id="mainGallery">
<div class="search">
<label class="dropdown">
<select id="selection" ng-model="query">
<option value="all">All</option>
<option value="malex">Male</option>
<option value="female">Female</option>
</select>
</label>
<div id="filterBar">
<input ng-model="query" type="image" src="http://findicons.com/files/icons/438/dating/256/male.png" name="malex" value="malex">
<input ng-model="query" type="image" src="https://cdn2.iconfinder.com/data/icons/social-productivity-line-art-2/128/sex-female-512.png" name="female" value="female">
</div>
<div id="seperator"></div>
<div class="imgBlock" ng-repeat="item in images | filter: query | orderBy: order">
<!-- images placed inside block elements to deal with a Firefox rendering bug affecting scaled flexbox images -->
<img class="galleryItems" src="{{item.source}}" alt="{{item.altText}}" title="{{item.altText}}">
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</body>
</html>

The input with type="image" is a graphical submit button, it doesn't have a meaningful value attribute, so that's probably it doesn't really work. Try to simply replace your inputs with something like
<img class="imgButton" src="http://findicons.com/files/icons/438/dating/256/male.png" name="malex" ng-click="query = 'malex'" />
<img class="imgButton" src="https://cdn2.iconfinder.com/data/icons/social-productivity-line-art-2/128/sex-female-512.png" name="female" ng-click="query = 'female'" />
See updated code:
var galleryApp = angular.module('galleryApp', []);
galleryApp.controller('galleryController', function galleryController($scope) {
$scope.images = [
{
"source" : "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/jeremiah-wilson-1.jpg",
"altText" : "Person 1",
"type" : "female, all"
},
{
"source" : "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/jeremiah-wilson-2.jpg",
"altText" : "Person 2",
"type" : "malex, all"
},
{
"source" : "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/jeremiah-wilson-3.jpg",
"altText" : "Person 3",
"type" : "malex, all"
},
{
"source" : "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/jeremiah-wilson-4.jpg",
"altText" : "Person 4",
"type" : "malex, all"
},
{
"source" : "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/jeremiah-wilson-5.jpg",
"altText" : "Person 5",
"type" : "female, all"
}
];
});
body { margin: 0; background: #333; }
#mainGallery {
padding: .5vw;
font-size: 0;
display: -ms-flexbox;
-ms-flex-wrap: wrap;
-ms-flex-direction: column;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
display: -webkit-box;
display: flex;
}
#mainGallery .imgBlock {
-webkit-box-flex: auto;
-ms-flex: auto;
flex: auto;
width: 200px;
margin: .5vw;
}
#mainGallery .imgBlock img {
width: 100%;
height: auto;
}
#seperator {
width: 100%;
height: 1px;
display: block;
}
.search {
background: #222;
border: 1px solid black;
width: 500px;
padding: 10px 0;
margin: .5vw auto .5vw auto;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
}
.dropdown {
margin-left: 15px;
}
.filterImageWrapper {
position: relative;
width: 470px;
overflow: hidden;
margin: 15px;
}
.filterImage {
width: 470px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
-webkit-transform: translateX(0);
transform:translateX(0);
-webkit-transition: all 1s;
transition: all 1s;
}
#overlayFilter {
opacity:0;
position: absolute;
top: 0;
left: 0;
z-index: 100;
width: 470px;
-webkit-transition:all 1s;
transition:all 1s;
}
#overlayFilter.overlayOpacity {
opacity: 1;
}
#filterBar {
width: 100%;
height: 60px;
background: #666;
margin: .5vw;
-webkit-border-radius: 7px;
border-radius: 7px;
border: 1px solid black;
}
.selectedFarbig {
-webkit-transform: scale(4,4) translate(-40px, 50px);
transform: scale(4,4) translate(-40px, 50px);
}
.galleryItems {
-webkit-filter: grayscale(.9) sepia(.3);
filter: grayscale(.9) sepia(.3);
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
webkit-transition: all .4s;
transition: all .4s;
}
.galleryItems:hover {
-webkit-filter: grayscale(.1) sepia(.8);
}
#filterBar input:first-child {
height: 50px;
}
#filterBar input:nth-child(2) {
height: 50px;
}
.imgButton {
width: 40px;
height: 40px;
cursor: pointer;
}
#media screen and (max-width: 400px) {
#mainGallery .imgBlock { margin: 0; }
#mainGallery { padding: 0; }
}
<!doctype html>
<html ng-app="galleryApp">
<head>
<meta charset="UTF-8">
<title>Filter Gallery</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="controllers.js"></script>
<link href="main.css" rel="stylesheet" type="text/css">
</head>
<body>
<div ng-controller = "galleryController" id="mainGallery">
<div class="search">
<label class="dropdown">
<select id="selection" ng-model="query">
<option value="all">All</option>
<option value="malex">Male</option>
<option value="female">Female</option>
</select>
</label>
<div id="filterBar">
<img class="imgButton" src="http://findicons.com/files/icons/438/dating/256/male.png" name="malex" ng-click="query = 'malex'" />
<img class="imgButton" src="https://cdn2.iconfinder.com/data/icons/social-productivity-line-art-2/128/sex-female-512.png" name="female" ng-click="query = 'female'" />
</div>
<div id="seperator"></div>
<div class="imgBlock" ng-repeat="item in images | filter: query | orderBy: order">
<!-- images placed inside block elements to deal with a Firefox rendering bug affecting scaled flexbox images -->
<img class="galleryItems" src="{{item.source}}" alt="{{item.altText}}" title="{{item.altText}}">
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</body>
</html>

Related

Lazy Loading Photos For A Smoother Mobile Website

Below are the HTML, CSS, and Javascript I use on my website. I'm using a MAMP server (via an apache) to get it online and have no problems getting it to run over wi-fi. However, when I try to access it via my mobile network the website crashes after viewing a few pages. I have port-forwarded my router.
I think (and please correct me if I'm wrong) that too much is loading on the page at once, which is what is making the website crash when testing it on a mobile network. How would I set up the page so that the photos lazy load? If anyone has any advice it'd be much appreciated.
<!DOCTYPE html>
<html lang="en">
<meta name="viewport" content="width=device-width, initial-scale=1.0;" charset="utf-8">
<body>
<style>html{visibility: hidden; opacity: 0;}</style>
<title>MORIKOBOSHI・</title>
<div class="page-wrap">
<div class="cp_cont">
<input id="cp_toggle03" type="checkbox"/>
<div class="cp_mobilebar">
<label for="cp_toggle03" class="cp_menuicon">
<span></span>
</label>
</div>
<label id="h-menu_black" class="cp_toggle03" for="cp_menuicon"></label>
<div id="body" class="noscroll"></div>
<header class="cp_offcm03">
<nav>
<ul style="text-align: center; margin-left: 210px; overflow: hidden;">
<li style="border-bottom: .05px solid lightgray;">Home</li>
<li style="border-bottom: .05px solid lightgray;">Blog</li>
<li style="border-bottom: .05px solid lightgray;">About This Website</li>
<li style="border-bottom: .05px solid lightgray;">Bibliography</li>
<div class="searchbar">
<form id="frmSearch" class="search2" method="get" action="default.html" style=" padding-right: 10px; padding-top: 20px; text-align: center; position: inline;">
<input class="search2" id="txtSearch" type="text" placeholder="Custom Google Search" name="serach_bar" size="31" maxlength="255" value="" style="top: 185px; width: 180px; height: 26px;">
<input class="search1" type="submit" name="submition" value="Search" style="padding-left: 5px; top: 153px; height: 25px; width: 50px; display: inline-flex; justify-content: center;">
<input class="search2" type="hidden" name="sitesearch" value="default.html">
</form>
</div>
<script type="text/javascript">
document.getElementById('frmSearch').onsubmit = function() {
window.location = 'http://www.google.com/search?q=site:morikoboshi.com' + document.getElementById('txtSearch').value;
return false;
}
</script>
<script>
document.getElementById('cp_toggle03').onchange = function() {
if (document.getElementById('cp_toggle03').checked) {
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "";
}
}
if(!!window.performance && window.performance.navigation.type == 2)
{
window.location.reload();
}
</script>
</ul>
</nav>
</header>
<div class="setsumei">
<br><br><h1 style="text-align: center; font-size: 40px;">◯◯◯◯</h1>
<br><p style="text-align: justify; font-size: 16px;"></p>
<p style="text-align: center; font-size: 13px;">Author: ◯◯◯◯</p>
<p style="text-align: center; font-size: 13px;">Photos/Videos Taken:◯◯◯◯/◯◯/◯◯</p>
<br><br><p style="text-align: justify; font-size: 16px;">
#
</p>
</div>
<br><br><div class="image">
<img src="#" alt="#" width="90%">
<br><br><img src="#" alt="#" width="90%">
<br><br><img src="#" alt="#" width="90%">
<br><br><img src="#" alt="#" width="90%">
<br><br><img src="#" alt="#" width="90%">
<br><br><img src="#" alt="#" width="90%">
<br><br><img src="#" alt="#" width="90%">
<br><br><img src="#" alt="#" width="90%">
<br><br><img src="#" alt="#" width="90%">
<br><br><img src="#" alt="#" width="90%">
</div>
<br><br><footer class="site-footer" style="font-size: 12px;">MORIKOBOSHI© | 日本語</footer>
</div>
</div>
<style>
html {visibility: visible;
opacity: 1;}
.body{background-color: white;
font-family: sans-serif;}
.searchbar{float: right;}
.image{text-align: center;}
.setsumei{margin-left: 20px;
margin-right: 20px;}
.footer{width: 100%;
height: 40px;
text-align: center;
border-top: 1px solid black;
position: absolute;
bottom: 0;
padding: 10px;}
.page-wrap {
min-height: 100%;
/* equal to footer height */
margin-bottom: -40px;
}
.page-wrap:after {
content: "";
display: block;
}
.site-footer, .page-wrap:after {
/* .push must be the same height as footer */
height: 20px;
}
.site-footer {
text-align: center;
border-top: 1px solid black;
padding: 10px;
}
*, *:before, *:after {
padding-left: 0;
margin: 0;
box-sizing: border-box;
}
ol, ul {
list-style: none;
}
a {
text-decoration: none;
color: black;
}
.cp_cont {
height: auto;
}
/* menu */
.cp_offcm03 {
position: relative;
z-index: 5000;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: auto;
width: 100%;
height: auto;
padding-top: 0;
-webkit-transition: transform 0.3s ease-in;
transition: transform 0.3s ease-in;
text-align: center;
color: black;
background-color: white;
}
.cp_offcm03 nav,
.cp_offcm03 ul {
height: 100%;
}
.cp_offcm03 li {
display: inline-block;
margin-right: -6px;
}
.cp_offcm03 a {
display: block;
padding: 15px 45px;
margin-bottom: -5px;
-webkit-transition: background-color .3s ease-in;
transition: background-color .3s ease-in;
}
.cp_offcm03 a:hover {
background-color: lightgray;
}
/* menu toggle */
#cp_toggle03 {
display: none;
}
#cp_toggle03:checked ~ .cp_offcm03 {
-webkit-transform: translateX(0);
transform: translateX(0);
}
#cp_toggle03:checked ~ .cp_container {
-webkit-transform: translateX(0);
transform: translateX(0);
}
.cp_mobilebar {
display: none;
}
/* content */
.cp_container {
position: relative;
top: 0;
padding: 35px auto;
-webkit-transition: transform .3s ease-in;
transition: transform .3s ease-in;
}
.cp_content {
margin: 0 auto;
padding: 20px;
height: 65vh;
text-align: center;
}
#media (max-width: 1130px)and (min-width: 280px) {
/* menu */
.cp_offcm03 {
position: fixed;
left: -250px;
overflow-y: hidden;
width: 250px;
height: 100%;
padding-top: 40px;
color: black;
background-color: white;
z-index: 1000;
}
.cp_offcm03 nav {
background: white;
border-right: 0.5px solid lightgray;
margin-left: -210px;
}
.cp_offcm03 li {
display: block;
margin-right: 0;}
.cp_offcm03 a {
padding: 20px;
}
/* menu toggle */
.cp_mobilebar {
display: block;
z-index: 2000;
position: relative;
top: 0;
left: 0;
padding: 0 25px;
width: 100%;
height: 40px;
background-color: white;
border-bottom: .05px solid lightgray;
}
.cp_menuicon {
display: block;
position: relative;
width: 25px;
height: 100%;
cursor: pointer;
-webkit-transition: transform .3s ease-in;
transition: transform .3s ease-in;
}
.cp_menuicon > span {
display: block;
position: absolute;
top: 55%;
margin-top: -0.3em;
width: 100%;
height: 0.2em;
border-radius: 1px;
background-color: black;
-webkit-transition: transform .3s ease;
transition: transform .3s ease;
}
.cp_menuicon > span:before,
.cp_menuicon > span:after {
content: "";
position: absolute;
width: 100%;
height: 100%;
border-radius: 1px;
background-color: black;
-webkit-transition: transform .3s ease-in;
transition: transform .3s ease-in;
}
.cp_menuicon > span:before {
-webkit-transform: translateY(-0.6em);
transform: translateY(-0.6em);
}
.cp_menuicon > span:after {
-webkit-transform: translateY(0.6em);
transform: translateY(0.6em);
}
#cp_toggle03:checked + .cp_mobilebar .cp_menuicon {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
#cp_toggle03:checked + .cp_mobilebar span:before,
#cp_toggle03:checked + .cp_mobilebar span:after {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
#cp_toggle03:checked ~ .cp_offcm03 {
-webkit-transform: translateX(100%);
transform: translateX(100%);
}
#cp_toggle03:checked ~ .cp_container {
-webkit-transform: translateX(250px);
transform: translateX(250px);
}
input:checked ~ #h-menu_black {
display: block;/*カバーを表示*/
opacity: .6;
}
#h-menu_black {
display: none;
position: fixed;
z-index: 999;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: black;
opacity: 0;
transition: .7s ease-in-out;
}
/* content */
.cp_container {
top: 60px;
height: 92vh;
text-align: center;
}
.noscroll{
overflow: hidden;
position: fixed;
}
</style>
</body>
</html>

Pushing Sign Up & Login buttons to bottom of sidebar

I am trying to recreate this design:
Click to view
However, the below is currently occurring.
Click to view
I am trying to push the SignUp and Login buttons to the bottom of the sidebar to match the first image. Am I missing a CSS class that would allow me to do so, or would this be a JS configuration? Hope I have not overlooked something basic that would allow me to achieve this state.
Sidebar.js
import React from "react";
import "../App.css";
import { SidebarData } from './SidebarData'
import Logo from './Logo.svg'
import { Login } from './Login'
import { SignUp } from './SignUp'
function Sidebar() {
return (
<div className="Sidebar">
<div className="Header">
<div><img src = {Logo} alt='Logo’ className='Logo’ /></div>
</div>
<div class="line-break" />
<ul className="SidebarList">
{SidebarData.map((val, key) => {
return (
<li
key={key}
className="row"
id={window.location.pathname == val.link ? "active" : ""}
onClick={() => {
window.location.pathname = val.link;
}}
>
<div id="icon">{val.icon}</div> <div id="title">{val.title}</div>
</li>
);
})}
</ul>
<div class="line-break" />
<div className="footer">
<ul className= "SidebarList">
{Login.map((val, key) => {
return (
<li
key={key}
className="Login"
id={window.location.pathname == val.link ? "active" : ""}
onClick={() => {
window.location.pathname = val.link;
}}
>
<div id="title">{val.title}</div>
</li>
)}
)}
</ul>
<ul className= "SidebarList">
{SignUp.map((val, key) => {
return (
<li
key={key}
className="SignUp"
id={window.location.pathname == val.link ? "active" : ""}
onClick={() => {
window.location.pathname = val.link;
}}
>
<div id="title">{val.title}</div>
</li>
)}
)}
</ul>
</div>
</div>
Here is CSS
.App {
width: 100vw;
height: 100vh;
}
body {
margin: 0;
padding: 0;
}
.Sidebar {
height: 100%;
width: 300px;
background-color: white;
border-right: 1px solid #F0F4FB;
padding-left: 15px;
box-sizing: border-box;
}
.SidebarList {
height: auto;
width: 100%;
padding-left: 15px;
font-size: 18px;
border: 2px #FD954E;
box-sizing: border-box
}
.SidebarList .row {
width: 100%;
height: 50px;
background-color: white;
list-style-type: none;
margin: 0%;
padding-bottom: 15px;
display: flex;
color: #A7ACB6;
justify-content: center;
align-items: center;
font-family: Arial, Helvetica, sans-serif;
}
.SidebarList .row:hover {
cursor: pointer;
background-color: #E7E7E7 ;
}
.SidebarList #active {
background-color: white;
color: #FD954E
}
.SidebarList .Login {
background-color: white;
color: #FD954E;
width: 90%;
height: 5vh;
right: 1596px;
top: 958px;
border: 1px solid #FD954E;
box-sizing: border-box;
border-radius: 19.5px;
text-align: center;
font-family: Arial, Helvetica, sans-serif
}
.SidebarList .SignUp {
width: 90%;
height: 5vh;
right: 1596px;
top: 1011px;
background: #FD954E;
border-radius: 19.5px;
border: none;
text-align: center;
font-family: Arial, Helvetica, sans-serif;
}
.row #icon {
flex: 30%;
display: grid;
place-items: center;
transform: scale(1.2)
}
.row #title {
flex: 70%;
}
.Logo {
padding-left: 25px;
padding-top: 25px;
padding-bottom: 30px;
width: 55%;
}
.line-break {
height: 1px;
width: 100%;
background-color: #F0F4FB;
}
ul.nav {
list-style-type: none;
padding: 20px 0 0 40px;
list-style-type: none;
}
ul.nav li {
margin-bottom: 14px;
list-style-type: none;
}
ul.nav li:last-child {
margin-bottom: 0;
list-style-type: none;
}
.footer {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px 0;
}
.footer button {
padding: 6px 0;
width: 80%;
margin-bottom: 14px;
}
.footer button:last-child {
margin-bottom: 0;
}
.header .Logo {
height: 40px;
width: 200px;
background-color: grey;
margin: 20px;
}
Without seeing the source for the entire page and not just a couple of the buttons, it is impossible to say for sure, but my guess would be the following is causing your problem:
.Sidebar {
height: 100%;
...
}
Setting height: 100% will only tell the sidebar to take up 100% of the space it needs for its content (or 100% of the height of its bounding container, depending on the display properties of both). I would recommend changing it to this to solve your problem:
.Sidebar {
min-height: 100vh;
...
}

Drag And Drop Directiv in AngularJS moving cards

I use this directiv : http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/types
I have problem to with moving cards, when i move cards higher is ok, if the cards give less the problem starts.
i did this feature :
if ($scope.movingItem.indeksList == index) {
console.log('qrwa')
$scope.lists[$scope.movingItem.indeksList].cards.splice($scope.movingItem.IndexCard +1, 1);
$scope.lists[index].cards = external[index].cards;
} else {
console.log('qrwa2')
$scope.lists[$scope.movingItem.indeksList].cards.splice($scope.movingItem.IndexCard, 1);
$scope.lists[index].cards = external[index].cards;
}
If I do the movement in the same list and i move card higher is ok then must be perform:
$scope.lists[$scope.movingItem.indeksList].cards.splice($scope.movingItem.IndexCard +1, 1);
When from up to down must be perform :
$scope.lists[$scope.movingItem.indeksList].cards.splice($scope.movingItem.IndexCard, 1);
And here is problem I cant get $index on which place I drop card to make If that I move card lower make this perform, If higer make this perform...
Here is whole project:
https://plnkr.co/edit/BVF0KxPrWiCeGDXVpQDV?p=preview
This code works:
$scope.dropCallback = function (index, item, external) {
$scope.lists[$scope.movingItem.indeksList].cards.splice($scope.movingItem.IndexCard, 1);
$scope.lists[index].cards = external[index].cards;
console.log($scope.lists[index].cards)
return item;
};
The watcher is not neccesary in this case, because you are getting informed of changes by the dropCallback function itself.
Your job is simply to remove the item at the index, like you did. Regardless of the moving direction.
EDIT
Here is the working plunker
Not sure why you need to use dropCallback just to move items around in the list. You can use dnd-moved="item.cards.splice($index, 1)" as shown in the demo.
Check out update version of your code:
angular.module("app", ["dndLists"]).controller("c1", function($scope){
$scope.title ="drag and drop";
$scope.lists = [
{
id: 2,
name: "list2",
cards: [
{ name: "card1"},
{ name: "card2"},
{ name: "card3"},
{ name: "card4"},
{ name: "card5"}
]
},
{
id: 3,
name: "list3",
cards: [
{ name: "card1"},
{ name: "card2"},
{ name: "card3"},
{ name: "card4"},
{ name: "card5"}
]
}
];
$scope.logEvent = function (indeksList, IndexCard) {
$scope.movingItem = {
indeksList: indeksList,
IndexCard: IndexCard
}
};
$scope.dropCallback = function (index, item, external) {
return item;
};
})
/* Styles go here */
.tilt {
transform: rotate(3deg);
-moz-transform: rotate(3deg);
-webkit-transform: rotate(3deg);
}
.column {
width: 170px;
float: left;
padding-bottom: 100px;
}
.portlet {
margin: 0 1em 1em 0;
padding: 0.3em;
}
.portlet-header {
padding: 0.2em 0.3em;
margin-bottom: 0.5em;
position: relative;
}
.portlet-toggle {
position: absolute;
top: 50%;
right: 0;
margin-top: -8px;
}
.portlet-content {
padding: 0.4em;
}
.portlet-placeholder {
border: 1px dotted black;
margin: 0 1em 1em 0;
height: 50px;
}
/* <BEGIN> For OS X */
*:focus {
outline: none;
}
html {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* <END> For OS X */
body {
font-family: 'Open Sans', sans-serif;
background-color: #0375AB;
}
#wrapper, #topbar-inner {
width: 95%;
margin: 0 auto;
}
#topbar {
background-color: #036492;
}
#topbar-inner {
height: 42px;
position: relative;
}
#topbar #nav {
float: left;
width: 25%;
background: yellow;
}
#topbar #logo {
width: 100%;
padding-top: 8px;
text-align: center;
}
#topbar #login {
position: absolute;
right: 0px;
bottom: 10px;
}
#topbar #logo h1 {
margin: 0;
display: inline;
font-size: 24px;
font-family: "Ubuntu", sans-serif;
color: rgba(255, 255, 255, 0.3);
}
#topbar #logo h1:hover {
color: rgba(255, 255, 255, 0.8);
cursor: pointer;
}
#wrapper {
margin-top: 30px;
}
#tasks {
width: 260px;
padding: 7px;
background-color: #E2E4E6;
border-radius: 3px;
}
#tasks h3 {
padding: 0;
margin: 0px 0px 5px 0px;
font-weight: 400;
font-size: 14px;
}
#tasks ul {
list-style-type: none;
margin: 0;
padding: 0;
}
#tasks li {
padding: 5px 8px;
margin-bottom: 4px;
background-color: #fff;
border-bottom: 1px #CCCCCC solid;
border-radius: 3px;
font-weight: 300;
}
#tasks li i {
float: right;
margin-top: 5px;
}
#tasks li i:hover {
cursor: pointer;
}
#tasks li i.fa-trash-o {
color: #888;
font-size: 14px;
}
#tasks input[type=text] {
margin: 0;
width: 244px;
padding: 5px 8px;
border-width: 0;
border-radius: 3px;
box-shadow: none;
}
.btn-login {
color: #fff;
background-color: #448DAF;
text-decoration: none;
border-radius: 3px;
padding: 5px 10px;
}
<script data-require="angular.js#1.6.5" data-semver="1.6.5" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.min.js"></script>
<script data-require="angular-drag-and-drop-lists#1.2.0" data-semver="1.2.0" src="https://marceljuenemann.github.io/angular-drag-and-drop-lists/angular-drag-and-drop-lists.js"></script>
<body ng-app="app">
<div ng-controller="c1">
<ul style="list-style-type: none;">
<li ng-repeat="item in lists">
<div style="float: left; margin-left: 5px;">
<div id="tasks">
{{item.name}}
<ul dnd-list="item.cards" dnd-drop="dropCallback($index, item, lists)">
<li ng-repeat="card in item.cards"
dnd-draggable="card"
dnd-dragstart="logEvent($parent.$index, $index)"
dnd-moved="item.cards.splice($index, 1)"
dnd-selected="models.selected = item"
ng-class="{'selected': models.selected === item}"
dnd-effect-allowed="move">
{{card.name}}
</li>
</ul>
<form ng-submit="addTask(item._id, newTask, $index)">
<input type="text" ng-model="newTask" placeholder="add a new task" required />
</form>
</div>
</div>
</li>
</ul>
</div>
</body>
You can find Plunker project here.

Can't get this simple ng-submit to work

I'm learning AngularJS by working through this on YouTube tutorial and I've hit a block on the 14th video with the ng-submit directive.
See code snipit below, when you fill in the form at the bottom and click submit it's supposed to add a new Ninja, but it's not working. There are no errors showing in the console. I placed a debugger breakpoint within the addNinja() function definition and it doesn't go into it when I click submit.
Any idea what I'm doing wrong?
var myNinjaApp = angular.module('myNinjaApp',[]);
myNinjaApp.controller('NinjaController', ['$scope',function($scope){
$scope.removeNinja = function(ninja){
var removeNinja = $scope.ninjas.indexOf(ninja);
$scope.ninjas.splice(removeNinja, 1);
};
$scope.addNinja = function(){
$scope.ninjas.push({
name: $scope.newninja.name,
belt: $scope.newninja.belt,
rate: parseInt($scope.newninja.rate),
available: true
});
};
// $scope.addNinja = function() {
// $scope.ninjas.push(this.newninja);
// $scope.newninja = '';
// };
$scope.ninjas = [
{
name: "Yoshi",
belt: "green",
rate: 50,
available: true
},
{
name: "Crystal",
belt: "yellow",
rate: 30,
available: true
},
{
name: "Ryu",
belt: "orange",
rate: 10,
available: false
},
{
name: "Shaun",
belt: "black",
rate: 1000,
available: true
}
];
}]);
body{
font-family: Helvetica;
margin: 0;
}
h1,h2,h3{
margin: 0;
}
.belt{
padding: 5px 10px;
border-radius: 10px;
margin-left: 5px;
color: #fff;
font-size: 15px;
text-transform: uppercase;
}
#menu-bar{
background: crimson;
color: #fff;
padding: 10px;
}
#menu-bar h1{
font-size: 24px;
font-weight: normal;
display: inline-block;
}
#menu-bar ul{
float: right;
list-style-type: none;
padding: 0;
margin: 6px 0;
}
#menu-bar li{
float: right;
margin-left: 20px;
}
#menu-bar a{
color: #fff
}
main{
background: #eee;
width: 80%;
margin: 30px auto;
border-radius: 10px;
}
.content{
padding: 20px;
}
.content button,
.content input[type="submit"]{
background: #fff;
padding: 10px;
border-radius: 10px;
cursor: pointer;
color: #777;
border: 0;
box-shadow: 2px 2px 2px rgba(20,20,20,0.1);
font-size: 16px;
}
.content button:nth-child(2){
float: right;
}
.content ul{
padding: 0;
list-style-type: none;
margin: 30px 0;
}
.content li{
padding: 15px 0;
border-top: 1px solid #e2e2e2;
color: #444;
}
.content li span{
float: right;
}
.content li h3{
display: inline-block;
font-weight: normal;
font-size: 22px;
}
.content input{
width: 90%;
padding: 10px 5%;
border-radius: 10px;
border: 2px solid #ddd;
margin: 10px 0;
}
.content input[type="submit"]:last-child{
width: 150px;
display: block;
margin: 15px auto;
}
.remove{
float: right;
padding: 5px;
background: #fff;
width: 18px;
text-align: center;
border-radius: 20px;
color: crimson;
cursor: pointer;
margin-left: 10px;
}
<!DOCTYPE html>
<html lang="en" ng-app="myNinjaApp">
<head>
<title>TheNetNinja Angular Playlist</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body>
<div class="content">
<div ng-controller="NinjaController">
<button ng-click="order = 'name'">Order by Name</button>
<button ng-click="order = 'belt'">Order by Belt</button>
<input type="text" ng-model="search" placeholder="Search for a ninja">
<ul>
<li ng-repeat="ninja in ninjas | orderBy: order | filter: search" ng-show="ninja.available">
<h3>{{ninja.name}} - {{ninja.rate | currency: '£'}}</h3>
<div class="remove" ng-click="removeNinja(ninja)">x</div>
<span class="belt" style="background: {{ninja.belt}}">{{ninja.belt}} belt</span>
</li>
</ul>
</div>
<form ng-submit="addNinja()">
<input type="text" placeholder="name" ng-model="newninja.name" />
<input type="text" placeholder="belt" ng-model="newninja.belt" />
<input type="text" placeholder="rate" ng-model="newninja.rate" />
<input type="submit" value="Add new ninja">
</form>
<p>{{newninja}}</p>
</div>
</body>
</html>
You have a div in the wrong place - move </div> above <form ng-submit="addNinja()"> to after <p>{{newninja}}</p>
bascially the ng-submit is not within the ninjacontroller div
see - https://plnkr.co/edit/pPucxMw0Yjr9OZoxl0vy?p=preview for a working version
myNinjaApp.controller('NinjaController', ['$scope', '$http', '$log', function ($scope, $http, $log) {
$http({
url: "data/ninjas.json",
method: "GET"
}).then(function (resp) {
//$log.log(resp.data);
$scope.ninjas = resp;
}, function (resp) {
$log.error("ERROR Occurred");
//debugger;
});
$scope.removeNinja = function (ninja) {
var removeNinja = $scope.ninjas.indexOf(ninja);
$scope.ninjas.splice(removeNinja, 1);
}
$scope.addNinja = function () {
$scope.ninjas.push({
name: $scope.newninja.name,
belt: $scope.newninja.belt,
rate: parseInt($scope.newninja.rate),
available: true
});
$scope.newninja.name = "";
$scope.newninja.belt = "";
$scope.newninja.rate = "";
};
$scope.removeAll = function () {
$scope.ninjas = [];
};
$scope.sort = function (keyname) {
$scope.sortKey = keyname;
$scope.reverse = !$scope.reverse;
}
}]);

React-Select, Multi Select and Text Overflow

I am using React-Select component with multi select. One of the problems I am facing is that if the user select 3 or 4 options the UI looks pretty bad because the text begins to overflow and that causes the component to grow either horizontally and vertically.
I want to have a behavior where the size of the component remains the same and if the user selects more options then it just shows "..." (ellipsis) rather than try to show the newly selected options.
The behavior I want is more inline with this component
http://instructure-react.github.io/react-select-box/
See how it handles multi-select.
I don't want to swap out components now because we have done lots of testing with React-Select.
Can you give me some guide lines on how to achieve this without removing react-select.
i've managed to achieve both the ellipsis effect and leaving the display at one row,
here is a working example
https://codesandbox.io/s/v638kx67w7
hope this helps
I solved this without losing the Input component like this;
import Select, { components as RSComponents } from "react-select";
const ValueContainer = ({ selectProps, children, ...props }) => {
let [values, input] = children;
if (Array.isArray(values)) {
values = selectProps.value.map((x) => x.label).join(', ');
}
return (
<RSComponents.ValueContainer {...props}>
<div style={{
maxWidth: "80%",
whiteSpace: "nowrap",
textOverflow: "ellipsis",
overflow: "hidden",
}}>
{values}
</div>
{input}
</RSComponents.ValueContainer>
);
};
const customStyles = useMemo(() => ({
valueContainer: (provided, state) => ({
...provided,
whiteSpace: "nowrap",
overflow: "hidden",
flexWrap: 'nowrap',
}),
input: (provided, state) => ({
...provided,
minWidth: '20%'
}),
}), []);
<Select
components={{ ValueContainer }}
isMulti
styles={customStyles}
...
/>
This is the generated Html for given react-select element
. react-select-box-container {
position: relative;
width: 240px;
display: inline-block;
background-color: #fff;
border-radius: 4px;
text-align: left;
box-shadow: 0 0 2px rgba(0, 0, 0, .3);
}
.react-select-box {
padding: 15px 0;
display: inline-block;
cursor: pointer;
border: none;
width: 100%;
text-align: left;
background-color: transparent;
}
.react-select-box:focus {
outline: 0;
box-shadow: 0 0 4px #0493D1;
}
.react-select-box:before {
content: ' ';
z-index: 1;
position: absolute;
height: 20px;
top: 15px;
right: 34px;
border-left: 1px solid #CBD2D7;
}
.react-select-box:after {
content: ' ';
position: absolute;
z-index: 1;
top: 23px;
right: 13px;
border-top: 6px solid #7B8E9B;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
}
.react-select-box-label,
.react-select-box-option {
line-height: 16px;
font-size: 12px;
font-weight: bold;
color: #7B8E9B;
}
.react-select-box-label {
padding: 0 40px 0 20px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #0493D1;
}
.react-select-box-empty .react-select-box-label {
color: #7B8E9B;
}
.react-select-box-click-outside-layer {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 2;
}
.react-select-box-clear {
position: absolute;
top: 15px;
right: 0;
width: 35px;
height: 20px;
background-color: #fff;
text-indent: -9999em;
z-index: 3;
border: none;
}
.react-select-box-clear:before {
content: '×';
position: absolute;
top: 2px;
left: 10px;
z-index: 1;
background-color: #7B8E9B;
border-radius: 100%;
font-size: 13px;
color: #fff;
line-height: 1;
width: 15px;
height: 15px;
text-indent: 0;
text-align: center;
}
.react-select-box-clear:hover,
.react-select-box-clear:focus {
outline: 0;
}
.react-select-box-clear:hover:before,
.react-select-box-clear:focus:before {
background-color: #0493D1;
}
.react-select-box-hidden {
display: none
}
.react-select-box-options {
margin: 2px 0 0;
position: absolute;
padding: 10px 0;
width: 240px;
top: 100%;
left: 0;
z-index: 4;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 0 2px rgba(0, 0, 0, .3);
}
.react-select-box-options-list {
list-style: none outside;
margin: 0;
padding: 0;
}
.react-select-box-option {
padding: 10px 20px;
margin: 0;
cursor: pointer;
display: block;
line-height: 1.2;
text-decoration: none;
}
.react-select-box-option:hover {
color: #0493D1;
background-color: #f4f4f4;
}
.react-select-box-option-selected {
color: #CBD2D7;
}
.react-select-box-multi .react-select-box-option {
padding-left: 42px;
position: relative;
}
.react-select-box-multi .react-select-box-option:before {
content: ' ';
position: absolute;
line-height: 1;
text-align: center;
left: 20px;
top: 9px;
border-radius: 3px;
height: 12px;
width: 12px;
margin-right: 10px;
border: 1px solid #7B8E9B;
background: #f9f9f9;
vertical-align: middle;
}
.react-select-box-multi .react-select-box-option-selected:before {
content: '✓';
}
.react-select-box-multi .react-select-box-option-selected {
color: #1F3344;
}
.react-select-box-option:focus,
.react-select-box-option-focused {
color: #0493D1;
outline: 0;
background-color: #DDE2E5;
}
.react-select-box-close {
color: #0493D1;
text-transform: uppercase;
background-color: transparent;
border: none;
padding: 5px 0;
display: block;
text-align: center;
width: 100%;
font-weight: bold;
cursor: pointer;
outline: none;
}
.react-select-box-close:hover,
.react-select-box-close:focus {
text-decoration: underline;
}
.react-select-box-empty .react-select-box-close {
color: #CBD2D7;
}
.react-select-box-native {
position: absolute;
left: -99999em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div class="react-select-box-container react-select-box-multi react-select-box-empty">
<button id="react-select-box-2" class="react-select-box" tabindex="0" aria-hidden="true">
<div class="react-select-box-label">
Favorite Colors
</div></button>
<div class="react-select-box-options react-select-box-hidden" aria-hidden="true" tabindex="0">
<div class="react-select-box-off-screen">
<a id="react-select-box-2-0" href="#" class="react-select-box-option" tabindex="-1">Red</a>
<a id="react-select-box-2-1" href="#" class="react-select-box-option" tabindex="-1">Green</a>
<a id="react-select-box-2-2" href="#" class="react-select-box-option" tabindex="-1">Blue</a>
</div>
<button class="react-select-box-close">Close</button>
</div>
<div class="react-select-box-native">
<label for="react-select-box-2-native-select">Favorite Colors</label>
<select id="react-select-box-2-native-select" multiple="multiple">
<option value="red">
Red
</option>
<option value="green">
Green
</option>
<option value="blue">
Blue
</option>
</select>
</div>
</div>

Resources