Im creating a floating label , i manage to make a floating label on textbox but
in my dropdown it doesn't work. hope you can help me.
/** GLOBAL OBJECT **/
var $ = {
addClass: function(elem, name) {
var classes = elem.className.split(' '),
cIndex = classes.indexOf(name);
if (cIndex === -1) {
classes.push(name);
}
elem.className = classes.join(' ');
return this;
}, // END addClass
removeClass: function(elem, name) {
var classes = elem.className.split(' '),
cIndex = undefined;
function recursive() {
// use a recursive function to remove all instances
// of the class name
cIndex = classes.indexOf(name);
if (cIndex >= 0) {
classes.splice(cIndex, 1);
recursive();
}
}
recursive();
elem.className = classes.join(' ');
return this;
}, // END removeClass
hasClass: function(elem, name) {
var classes = elem.className.split(' '),
cIndex = classes.indexOf(name);
if (cIndex >= 0) {
return true;
} else {
return false;
}
}, // END hasClass
selectCreate: function(select, label) {
var _this = this;
id = '_' + select.id,
input = document.createElement('input'),
div = document.createElement('div'),
ul = document.createElement('ul'),
val = {
value: select.value,
text: select.options[select.selectedIndex].text
};
select.style.display = 'none';
ul.id = 'ul' + id;
ul.className = 'ddown-list';
ul.setAttribute('aria-live', 'polite');
input.setAttribute('type', 'text');
input.setAttribute('aria-autocomplete', 'list');
input.setAttribute('aria-haspopup', 'true');
input.setAttribute('aria-owns', ul.id);
input.className = 'dynamic-dropdown';
input.id = id;
if (select.getAttribute('data-required') === 'true') {
input.setAttribute('required', 'true');
}
label.setAttribute('for', id);
div.className = 'selectRegion';
div.appendChild(label);
div.appendChild(input);
div.appendChild(ul);
select.parentNode.insertBefore(div, select);
input.value = val.text;
if (input.value !== '') {
this.addClass(label, 'active');
} else {
this.addClass(label, 'inactive');
}
input.addEventListener('focus', function() {
_this.addClass(label, 'active')
.addClass(label, 'transition')
.removeClass(label, 'inactive');
if (this.setSelectionRange) {
this.setSelectionRange(0, this.value.length);
}
populateList(this, select, document.getElementById('ul' + this.id), -1, true);
}); // END focus
input.addEventListener('blur', function() {
var input = this;
setTimeout(function() {
if (input.value === '') {
_this.addClass(label, 'inactive')
.addClass(label, 'transition')
.removeClass(label, 'active');
} else {
var list = getList(input.value, select, false);
select.value = list.value[0];
input.value = list.text[0];
}
document.getElementById('ul' + input.id).innerHTML = '';
}, 250);
}); // END blur
input.addEventListener('keyup', function(e) {
var list = document.getElementById('ul' + this.id).getElementsByTagName('li'),
index = -1,
kC = e.keyCode;
for (var i = 0, x = list.length; i < x; i++) {
if (_this.hasClass(list[i], 'active')) {
index = i;
break;
}
}
if (kC !== 9 && kC !== 16) { // SHIFT && TAB
if (kC === 13) { // ENTER
var list = getList(this.value, select, false);
select.value = list.value[index];
this.value = list.text[index];
document.getElementById('ul' + this.id).innerHTML = '';
} else {
switch (kC) {
case 38: // ARROW UP
index--;
if (index < 0) {
index = 0;
}
break;
case 40: // ARROW DOWN
index++;
if (index >= list.length) {
index = list.length - 1;
}
break;
default:
index = -1;
break;
}
populateList(this, select, document.getElementById('ul' + this.id), index, false);
}
}
}); // END keyup
function populateList(input, select, target, index, focus) {
var list = getList(input.value, select, focus),
counter = 0,
output;
if (focus) {
index = select.selectedIndex - 1;
}
target.innerHTML = '';
for (var i = 0, x = list.value.length; i < x; i++) {
output = document.createElement('li');
if (counter === index) {
output.className = 'active';
}
output.appendChild(document.createTextNode(list.text[i]));
output.addEventListener('click', function() {
console.log('test');
input.value = this.innerHTML;
});
target.appendChild(output);
counter++;
}
if (index >= 0) {
var lis = target.getElementsByTagName('li'),
sTop = 0;
for (var i = 0, x = lis.length; i < x; i++) {
if (i >= index) {
break;
}
sTop += lis[i].clientHeight;
}
target.scrollTop = sTop;
}
} // END populateList
function getList(val, list, focus) {
var value = [],
text = [],
vLength = val.length;
if (focus) {
vLength = 0;
val = '';
}
for (var i = 0, x = list.length; i < x; i++) {
if (list[i].text !== '' &&
(list[i].text.toUpperCase().substring(0, vLength) === val.toUpperCase() ||
list[i].value.toUpperCase().substring(0, vLength) === val.toUpperCase())) {
value.push(list[i].value);
text.push(list[i].text);
}
}
return {
value: value,
text: text
};
} // END function getList
}, // END selectCreate()
}; // END $
window.onload = function() {
var labels = document.getElementsByTagName('label'),
id = '',
label = undefined,
input = undefined,
type = undefined;
for (var i = 0, x = labels.length; i < x; i++) {
label = labels[i];
id = label.getAttribute('for') || '';
input = document.getElementById(id);
if (input) {
type = input.getAttribute('type') || input.tagName;
type = type.toLowerCase();
if (input && (type === 'select')) {
$.selectCreate(input, label);
} // END if( input && select )
}
} // END for( labels )
}();
var demo = function() {
setTimeout(function() {
document.getElementById('_s').focus();
setTimeout(function() {
document.getElementById('_s').blur();
}, 750);
}, 500);
}();
body {
background-color: #F7F7F7;
font-family: Arial;
padding-top: 10%;
}
input,
label,
select {
width: 280px;
padding: 10px;
font-size: 16px;
}
input {
border: solid 1px #CCCCCC;
border: none;
overflow: visible;
outline: none;
background-color: transparent;
border-bottom: solid 1px #999;
}
label {
position: absolute;
}
label.active {
color: #3784BB;
margin-top: -20px;
font-size: 12px;
}
label.inactive {
color: #999999;
}
li.active {
background-color: rgba( 255, 0, 0, 0.1);
}
.transition {
transition: all linear 0.1s;
}
.input {
width: 300px;
margin: auto;
}
.input:first-child {
margin-bottom: 5%
}
.selectRegion {
width: 100%;
}
.selectRegion ul {
margin: 0;
padding: 0;
position: absolute;
width: 300px;
max-height: 200px;
overflow: auto;
box-shadow: 0 2px 3px rgba( 0, 0, 0, 0.1);
background-color: #FFFFFF;
z-index: 2;
}
.selectRegion ul li {
padding: 10px;
}
.selectRegion ul li:hover {
cursor: pointer;
}
.inputbox {
position: relative;
background: none;
margin-right: 50px;
}
.inputbox input {
width: 120%;
padding: 10px 0;
font-size: 19px;
color: #21a1e;
margin-bottom: 50px;
overflow: visible;
outline: none;
background-color: transparent;
border: none;
border-bottom: solid 1px #999;
margin-left: -10px;
margin-top: -15px;
}
.inputbox label {
display: block;
position: absolute;
top: 0;
left: 0;
padding: 10px 0;
font-size: 16px;
color: #999;
pointer-events: none;
transition: top 0.7s ease, opacity 0.7s ease;
border-radius: .25rem;
margin-left: -10px;
margin-top: -10px;
}
.inputbox input:focus+label,
.inputbox input:valid+label {
top: -18px;
left: 0;
color: #4285f4;
font-size: 12px;
cursor: pointer;
}
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="col-sm-5">
<button type="button" class="button2 " data-toggle="modal" data-target="#exampleModal1">Login</button>
</div>
<div class="modal fade" id="exampleModal1" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg " role="document">
<div class="modal-content">
<div class="modal-header ">
<h5 class="modal-title" id="exampleModalLabel" style=" color: #404E67;">Form</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form>
<div class="form-row ">
<div class="inputbox">
<input type="text" required>
<label>First Name </label>
</div>
<div class="inputbox">
<input type="text" required>
<label>Last Name</label>
</div>
</div>
<div class="form-row">
<div class="input">
<label for="s">Sample 1:</label>
<select id="s">
<option value=""></option>
<option value="1">Assignment</option>
<option value="2">Reading</option>
</select>
</div>
</div>
<div class="clear"></div>
<div class="input">
<label for="state">Sample 2</label>
<select id="state">
<option value=""></option>
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
</select>
</div>
</form>
</div>
</div>
</body>
</html>
here is my current output:
As you can see on my output the two dropdown is not working any idea how ca i make it a floating label like at my textbox?
Related
Just wanted to know easiest way to achieve this
Perhaps something like this:
(()=>
{
const formEls = document.querySelectorAll(".input-tags");
for(let i = 0; i < formEls.length; i++)
{
const formEl = formEls[i],
inputEl = document.createElement("input"),
tagsEl = document.createElement("span"),
listEl = document.createElement("datalist");
formEl.tags = [];
Object.defineProperties(formEl, {
list: {
get(){return getData(this, "list")},
set(val){this.dataset.list = val}
},
tags: {
get(){return getData(this, "tags")},
set(val){this.dataset.tags = val}
},
value:
{
get(){return this.dataset.value || ""},
set(val){this.dataset.value = val}
}
});
const list = formEl.list;
listEl.id = "input-tags-datalist" + i;
inputEl.setAttribute("list", listEl.id);
inputEl.type = "text";
tagsEl.className = "tags";
for(let i = 0, optionEl = document.createElement("option"); i < list.length; i++)
{
optionEl = optionEl.cloneNode(false);
optionEl.value = list[i];
listEl.appendChild(optionEl);
}
formEl.appendChild(tagsEl);
formEl.appendChild(inputEl);
formEl.appendChild(listEl);
inputEl._isClicked = true;
inputEl.addEventListener("keydown", e => inputEl._isClicked = !e.keyCode || e.keyCode==13);
inputEl.addEventListener("keyup", e => inputEl._isClicked = true);
inputEl.addEventListener("input", e =>
{
formEl.value = inputEl.value;
if (!inputEl._isClicked && !inputEl.value.match(/(^[^"']+ $)|(^(["']).+\3$)/))
{
dispatchEvent(formEl, "input");
return inputWidth(formEl);
}
const val = inputEl.value.replace(/^\s*((["'])([^"']+)\2|([^"']+)\s+)$/, "$4$3").replace(/[^\w -_]+/g, "").replace(/[ ]{2,}/g, " ");
if (formEl.dataset.autotags !== undefined || formEl.list.indexOf(val) != -1)
{
inputEl.value = val;
addTag(inputEl);
}
formEl.value = inputEl.value;
dispatchEvent(formEl, "input");
inputWidth(formEl);
});//inputEl.oninput()
tagsEl.addEventListener("click", e =>
{
if (!e.target.parentNode.classList.contains("tag"))
return;
const tag = e.target.parentNode.textContent,
list = formEl.list,
tags = formEl.tags,
index = list.indexOf(tag),
optionEl = listEl.children[index];
if (optionEl.classList.contains("new"))
{
list.splice(index, 1);
optionEl.parentNode.removeChild(optionEl);
}
else
optionEl.disabled = false;
tags.splice(tags.indexOf(tag), 1);
formEl.tags = tags;
formEl.list = list;
e.target.parentNode.parentNode.removeChild(e.target.parentNode);
inputWidth(formEl);
e.stopPropagation();
formEl.click();
dispatchEvent(formEl, "input");
});//tagsEl.onclick()
formEl.addEventListener("click", e => inputEl.focus());
inputWidth(formEl);
}
function dispatchEvent(el, type, opts)
{
return el.dispatchEvent(new Event(type, opts));
}
function inputWidth(formEl)
{
const inputEl = formEl.querySelector("input");
inputEl.style.width = "1em"; //min width
const inputStyle = window.getComputedStyle(inputEl),
formStyle = window.getComputedStyle(inputEl.parentNode),
inputRect = inputEl.getBoundingClientRect(),
formRect = inputEl.parentNode.getBoundingClientRect(),
canvas = document.createElement('canvas'),
ctx = canvas.getContext("2d");
ctx.font = inputStyle.font;
const widthText = (ctx.measureText(inputEl.value).width
+ parseFloat(inputStyle.paddingLeft)
+ parseFloat(inputStyle.paddingRight)
+ parseFloat(inputStyle.textIndent)
+ parseFloat(inputStyle.borderLeftWidth)
+ parseFloat(inputStyle.borderRightWidth)
+ 1
),
widthBox = formRect.right - inputRect.left - parseFloat(formStyle.paddingLeft) - parseFloat(formStyle.paddingRight) - 1;
inputEl.style.width = Math.max(widthText, widthBox) + "px";
}
function getData(el, key)
{
return el.dataset[key] ? el.dataset[key].split(",") : [];
}
function addTag(input)
{
const formEl = input.parentNode,
tag = input.value.trim(),
list = formEl.list,
tags = formEl.tags;
if (tag === "" || tags.indexOf(tag) != -1)
return;
const tagsEl = formEl.querySelector(".tags"),
tagEl = document.createElement("span"),
datalistEl = formEl.querySelector("datalist");
if (formEl.dataset.autotags !== undefined && list.indexOf(tag) == -1)
{
const option = document.createElement("option");
option.value = tag;
option.className = "new";
datalistEl.appendChild(option);
list[list.length] = tag;
}
tags[tags.length] = tag;
formEl.list = list;
formEl.tags = tags;
const index = list.indexOf(tag);
datalistEl.children[index].disabled = true;
tagEl.className = "tag";
tagEl.textContent = tag;
tagEl.appendChild(document.createElement("span"));
tagsEl.appendChild(tagEl);
input.value = "";
}
})();
//example:
const test = document.getElementById("test");
test.addEventListener("input", e =>
{
if (e.target !== test)
return;
console.log('value:', test.value);
console.log("tags:", JSON.stringify(test.tags));
console.log("list:", JSON.stringify(test.list));
}, false);
.input-tags
{
display: inline-block;
border: 1px solid black;
font-size: 0.8em;
padding: 0.1em 0.1em 0.1em 0.05em;
width: 100%;
line-height: 1em;
}
.input-tags > input,
.input-tags > input:focus,
.input-tags > input:active
{
outline: none;
border: none;
margin: 0.15em 0;
vertical-align: middle;
max-width: 100%;
box-sizing: border-box;
}
.input-tags > input::-webkit-calendar-picker-indicator
{
display: none !important;
}
.input-tags > .tags
{
vertical-align: middle;
}
.input-tags .tags .tag
{
display: inline-block;
background-color: lightblue;
border: 1px solid blue;
border-radius: 2px;
font-family: "Segoe UI","Liberation Sans",sans-serif;
margin: 0.1em;
padding: 0 0.2em;
line-height: 1.3em;
}
.input-tags .tags .tag > span
{
margin: -0.05em -0.2em 0 0.05em;
cursor: pointer;
display: inline-block;
font-size: 1.3em;
transform: rotate(45deg);
border-radius: 2em;
line-height: 0.7em;
float: right;
}
.input-tags .tags .tag > span:before
{
content: "+";
position: relative;
top: -0.1em;
}
.input-tags .tags .tag > span:hover
{
background-color: #60B3CE;
}
<div style="display: grid; grid-template-columns: auto auto">
<span>Auto-add new tags, suggestions:</span>
<div style="display: inline-block; width: 50vw;">
<div id="test" class="input-tags" data-autotags data-list="test,sometag,SOMETAG,another tag,another tag2,another tag3,another,tag"></div>
</div>
<span>Auto-add new tags, no suggestions:</span>
<div style="display: inline-block; width: 50vw;">
<span class="input-tags" data-autotags></span>
</div>
<span>No new tags, suggestions:</span>
<div style="display: inline-block; min-width: 10em;">
<div class="input-tags" data-list="test,some tag,very long tag,blah"></div>
</div>
<div>
Using the tags() function, there is a parameter for maximum number of tags (maxTags) you can enter into each input.
I need to hide(); the tags-input when maxTags = 2 and then
show(); when the tag is removed / not at the max.
maxTags :1 isn't working but it should be. Only 2 or more is acceptable. I tried debugging the max tags parameter but couldn't find out why maxTags: 1 is
unacceptable.
How can I change the function to allow maxTags: 1 and also show/hide the tag-input when maxTags is reached?
// max tags in tags() function:
if (opts.maxTags) {
if ($self.val().split(",").length == opts.maxTags) {
otherCheck = false;
$input.val("");
$next.val("");
}
}
// Calling the tags() function:
$("#" + formId)
.find(".input--proj")
.tags({
unique: true,
maxTags: 2
})
.autofill({
data: autolist
});
(function($) {
$.fn.tags = function(opts) {
var selector = this.selector;
//console.log("selector",selector);
// updates the original input
function update($original) {
var all = [];
var list = $original.closest(".tags-wrapper").find("li.tag span").each(function() {
all.push($(this).text());
});
all = all.join(",");
$original.val(all);
}
return this.each(function() {
var self = this,
$self = $(this),
$wrapper = $("<div class='tags-wrapper'><ul></ul></div");
tags = $self.val(),
tagsArray = tags.split(","),
$ul = $wrapper.find("ul");
// make sure have opts
if (!opts) opts = {};
opts.maxSize = 50;
// add tags to start
tagsArray.forEach(function(tag) {
if (tag) {
$ul.append("<li class='tag'><span>" + tag + "</span><a href='#'>x</a></li>");
}
});
// get classes on this element
if (opts.classList) $wrapper.addClass(opts.classList);
// add input
$ul.append("<li class='tags-input'><input type='text' class='tags-secret'/></li>");
// set to dom
$self.after($wrapper);
// add the old element
$wrapper.append($self);
// size the text
var $input = $ul.find("input"),
size = parseInt($input.css("font-size")) - 4;
// delete a tag
$wrapper.on("click", "li.tag a", function(e) {
e.preventDefault();
$(this).closest("li").remove();
$self.trigger("tagRemove", $(this).closest("li").find("span").text());
update($self);
$("[data-search]").keyup();
});
// backspace needs to check before keyup
$wrapper.on("keydown", "li input", function(e) {
// backspace
if (e.keyCode == 8 && !$input.val()) {
var $li = $ul.find("li.tag:last").remove();
update($self);
$self.trigger("tagRemove", $li.find("span").text());
}
// prevent for tab
if (e.keyCode == 9) {
e.preventDefault();
}
});
// as we type
$wrapper.on("keyup", "li input", function(e) {
e.preventDefault();
$ul = $wrapper.find("ul");
var $next = $input.next(),
usingAutoFill = $next.hasClass("autofill-bg"),
$inputLi = $ul.find("li.tags-input");
// regular size adjust
$input.width($input.val().length * (size));
// if combined with autofill, check the bg for size
if (usingAutoFill) {
$next.width($next.val().length * (size));
$input.width($next.val().length * (size));
// make sure autofill doesn't get too big
if ($next.width() < opts.maxSize) $next.width(opts.maxSize);
var list = $next.data().data;
}
// make sure we don't get too high
if ($input.width() < opts.maxSize) $input.width(opts.maxSize);
// tab, comma, enter
if (!!~[9, 188, 13].indexOf(e.keyCode)) {
var val = $input.val().replace(",", "");
var otherCheck = true;
// requring a tag to be in autofill
if (opts.requireData && usingAutoFill) {
if (!~list.indexOf(val)) {
otherCheck = false;
$input.val("");
}
}
// unique
if (opts.unique) {
// found a match already there
if (!!~$self.val().split(",").indexOf(val)) {
otherCheck = false;
$input.val("");
$next.val("");
}
}
// max tags
if (opts.maxTags) {
if ($self.val().split(",").length == opts.maxTags) {
otherCheck = false;
$input.val("");
$next.val("");
}
}
// if we have a value, and other checks pass, add the tag
if (val && otherCheck) {
// place the new tag
$inputLi.before("<li class='tag'><span>" + val + "</span><a href='#'>x</a></li>");
// clear the values
$input.val("");
if (usingAutoFill) $next.val("");
update($self);
$self.trigger("tagAdd", val);
}
}
});
});
}
})(jQuery);
var uniqueId = 1;
$(function() {
$(".btn--new").click(function() {
var copy = $("#s_item").clone(true, true);
var formId = "item_" + uniqueId;
copy.attr("id", formId);
$("#s_list").append(copy);
$("#" + formId)
.find(".input--proj")
.each(function() {
var autolist = new Array();
$.each($(".studio__project"), function(index, value) {
if ($.inArray($(value).attr("data-proj"), autolist) < 1) {
autolist.push($(value).attr("data-proj").toLowerCase());
}
});
$("#" + formId)
.find(".input--proj")
.tags({
unique: true,
maxTags: 2
})
.autofill({
data: autolist
});
function placeholderproj() {
$(".search__label--proj")
.find(".tags-secret")
.attr("placeholder", "Enter Keyword");
}
$(document).ready(placeholderproj);
});
uniqueId++;
});
});
$(document).on("keyup , keypress", "li input", function(e) {
$.each($(".tag"), function(index, value) {
$.each($(".studio__project"), function(subIndex, subValue) {
if (
$(subValue).attr("data-proj").toLowerCase() ==
$(value).find("span").html()
) {
var itemColor = $(subValue).attr("data-color");
$(value).css("background-color", itemColor);
}
});
});
$("[data-search]").keyup();
});
$(document).on("click", ".tag a", function(e) {
$("[data-search]").keyup();
});
$(document).ready(function() {
$(".btn--new").trigger("click");
$(".btn--new").trigger("click");
$(".btn--new").trigger("click");
});
::-webkit-input-placeholder {
/* Chrome/Opera/Safari */
color: #8e8e8e;
}
::-moz-placeholder {
/* Firefox 19+ */
color: #8e8e8e;
}
:-ms-input-placeholder {
/* IE 10+ */
color: #8e8e8e;
}
:-moz-placeholder {
/* Firefox 18- */
color: #8e8e8e;
}
.tags-wrapper {
background: white;
display: flex;
position: relative;
width: 100%;
height: 50px;
top: -1px;
border: 1px solid whitesmoke;
overflow: hidden;
}
.tags-wrapper ul {
position: absolute;
display: flex;
flex: 1;
align-items: center;
top: 0;
bottom: 0;
right: 0;
left: 0;
list-style-type: none;
margin: 0;
padding: 0;
}
.tags-wrapper li {
flex-grow: 1;
margin-left: 5px;
}
.tags-wrapper li input {
display: block;
border: none;
width: 100% !important;
}
.tags-wrapper li.tag {
display: flex;
flex-grow: 0;
position: relative;
padding: 10px;
font-size: 14px;
align-items: center;
border-radius: 5px;
list-style: none;
background-image: none;
box-shadow: none;
color: white;
}
.tags-wrapper li a {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
text-decoration: none;
color: rgba(0, 0, 0, 0);
}
.tags-wrapper li a:hover {
background-color: rgba(0, 0, 0, 0.4);
border-radius: 5px;
color: rgba(0, 0, 0);
background-image: url("http://svgshare.com/i/3yv.svg");
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.tags-wrapper input {
display: none;
}
#s_item {
display: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.staticaly.com/gh/moofawsaw/donorport/master/auto-fill.min.js"></script>
<a id="btn_studio" href="#" class="btn btn--new ripple w-button">Create</a>
<div>keywords are: blue, red, green</div>
<div id="s_list">
<div id="s_item" data-item="studio" data-mode="none" class="post__item studio__item">
<div data-item="studio" class="post__itemwrap post__itemwrap--studio">
<div class="search search--proj w-embed"><label class="search__label--proj" data-color="">
<input type="text" class="input--proj" autocomplete="off" placeholder="">
</label></div>
<div class="w-dyn-list">
<div class="w-dyn-items">
<div class="w-dyn-item">
<div class="w-embed">
<div class="studio__project" data-proj="Blue" data-color="blue"></div>
</div>
</div>
<div class="w-dyn-item">
<div class="w-embed">
<div class="studio__project" data-proj="Green" data-color="green"></div>
</div>
</div>
<div class="w-dyn-item">
<div class="w-embed">
<div class="studio__project" data-proj="Red" data-color="red"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
I've added code to test maxTags value from 1 to 3. Just replace it.
Removed a tag. Show input.
$wrapper.on("click", "li.tag a", function(e) {
e.preventDefault();
$(this).closest("li").remove();
$self.trigger("tagRemove", $(this).closest("li").find("span").text());
update($self);
$("[data-search]").keyup();
$input.show(); // show input on remove
});
If string has no content, return 0. Else use split to find number of elements.
if (opts.maxTags) {
var len = $self.val();
len = len.trim().length > 0 ? len.split(',').length : 0;
(function($) {
$.fn.tags = function(opts) {
var selector = this.selector;
//console.log("selector",selector);
// updates the original input
function update($original) {
var all = [];
var list = $original.closest(".tags-wrapper").find("li.tag span").each(function() {
all.push($(this).text());
});
all = all.join(",");
$original.val(all);
}
return this.each(function() {
var self = this,
$self = $(this),
$wrapper = $("<div class='tags-wrapper'><ul></ul></div");
tags = $self.val(),
tagsArray = tags.split(","),
$ul = $wrapper.find("ul");
// make sure have opts
if (!opts) opts = {};
opts.maxSize = 50;
// add tags to start
tagsArray.forEach(function(tag) {
if (tag) {
$ul.append("<li class='tag'><span>" + tag + "</span><a href='#'>x</a></li>");
}
});
// get classes on this element
if (opts.classList) $wrapper.addClass(opts.classList);
// add input
$ul.append("<li class='tags-input'><input type='text' class='tags-secret'/></li>");
// set to dom
$self.after($wrapper);
// add the old element
$wrapper.append($self);
// size the text
var $input = $ul.find("input"),
size = parseInt($input.css("font-size")) - 4;
// delete a tag
$wrapper.on("click", "li.tag a", function(e) {
e.preventDefault();
$(this).closest("li").remove();
$self.trigger("tagRemove", $(this).closest("li").find("span").text());
update($self);
$("[data-search]").keyup();
$input.show(); // show input on remove
});
// backspace needs to check before keyup
$wrapper.on("keydown", "li input", function(e) {
// backspace
if (e.keyCode == 8 && !$input.val()) {
var $li = $ul.find("li.tag:last").remove();
update($self);
$self.trigger("tagRemove", $li.find("span").text());
}
// prevent for tab
if (e.keyCode == 9) {
e.preventDefault();
}
});
// as we type
$wrapper.on("keyup", "li input", function(e) {
e.preventDefault();
$ul = $wrapper.find("ul");
var $next = $input.next(),
usingAutoFill = $next.hasClass("autofill-bg"),
$inputLi = $ul.find("li.tags-input");
// regular size adjust
$input.width($input.val().length * (size));
// if combined with autofill, check the bg for size
if (usingAutoFill) {
$next.width($next.val().length * (size));
$input.width($next.val().length * (size));
// make sure autofill doesn't get too big
if ($next.width() < opts.maxSize) $next.width(opts.maxSize);
var list = $next.data().data;
}
// make sure we don't get too high
if ($input.width() < opts.maxSize) $input.width(opts.maxSize);
// tab, comma, enter
if (!!~[9, 188, 13].indexOf(e.keyCode)) {
var val = $input.val().replace(",", "");
var otherCheck = true;
// requring a tag to be in autofill
if (opts.requireData && usingAutoFill) {
if (!~list.indexOf(val)) {
otherCheck = false;
$input.val("");
}
}
// unique
if (opts.unique) {
// found a match already there
if (!!~$self.val().split(",").indexOf(val)) {
otherCheck = false;
$input.val("");
$next.val("");
}
}
// max tags
if (opts.maxTags) {
var len = $self.val();
len = len.trim().length > 0 ? len.split(',').length : 0;
if (len == opts.maxTags - 1) $input.hide();
if (len == opts.maxTags) {
otherCheck = false;
$input.val("");
$next.val("");
}
}
// if we have a value, and other checks pass, add the tag
if (val && otherCheck) {
// place the new tag
$inputLi.before("<li class='tag'><span>" + val + "</span><a href='#'>x</a></li>");
// clear the values
$input.val("");
if (usingAutoFill) $next.val("");
update($self);
$self.trigger("tagAdd", val);
}
}
});
});
}
})(jQuery);
var uniqueId = 1;
$(function() {
$(".btn--new").click(function() {
var copy = $("#s_item").clone(true, true);
var formId = "item_" + uniqueId;
copy.attr("id", formId);
$("#s_list").append(copy);
$("#" + formId)
.find(".input--proj")
.each(function() {
var autolist = new Array();
$.each($(".studio__project"), function(index, value) {
if ($.inArray($(value).attr("data-proj"), autolist) < 1) {
autolist.push($(value).attr("data-proj").toLowerCase());
}
});
$("#" + formId)
.find(".input--proj")
.tags({
unique: true,
maxTags: 1
})
.autofill({
data: autolist
});
function placeholderproj() {
$(".search__label--proj")
.find(".tags-secret")
.attr("placeholder", "Enter Keyword");
}
$(document).ready(placeholderproj);
});
uniqueId++;
});
});
$(document).on("keyup , keypress", "li input", function(e) {
$.each($(".tag"), function(index, value) {
$.each($(".studio__project"), function(subIndex, subValue) {
if (
$(subValue).attr("data-proj").toLowerCase() ==
$(value).find("span").html()
) {
var itemColor = $(subValue).attr("data-color");
$(value).css("background-color", itemColor);
}
});
});
$("[data-search]").keyup();
});
$(document).on("click", ".tag a", function(e) {
$("[data-search]").keyup();
});
$(document).ready(function() {
$(".btn--new").trigger("click");
$(".btn--new").trigger("click");
$(".btn--new").trigger("click");
});
::-webkit-input-placeholder {
/* Chrome/Opera/Safari */
color: #8e8e8e;
}
::-moz-placeholder {
/* Firefox 19+ */
color: #8e8e8e;
}
:-ms-input-placeholder {
/* IE 10+ */
color: #8e8e8e;
}
:-moz-placeholder {
/* Firefox 18- */
color: #8e8e8e;
}
.tags-wrapper {
background: white;
display: flex;
position: relative;
width: 100%;
height: 50px;
top: -1px;
border: 1px solid whitesmoke;
overflow: hidden;
}
.tags-wrapper ul {
position: absolute;
display: flex;
flex: 1;
align-items: center;
top: 0;
bottom: 0;
right: 0;
left: 0;
list-style-type: none;
margin: 0;
padding: 0;
}
.tags-wrapper li {
flex-grow: 1;
margin-left: 5px;
}
.tags-wrapper li input {
display: block;
border: none;
width: 100% !important;
}
.tags-wrapper li.tag {
display: flex;
flex-grow: 0;
position: relative;
padding: 10px;
font-size: 14px;
align-items: center;
border-radius: 5px;
list-style: none;
background-image: none;
box-shadow: none;
color: white;
}
.tags-wrapper li a {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
text-decoration: none;
color: rgba(0, 0, 0, 0);
}
.tags-wrapper li a:hover {
background-color: rgba(0, 0, 0, 0.4);
border-radius: 5px;
color: rgba(0, 0, 0);
background-image: url("http://svgshare.com/i/3yv.svg");
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.tags-wrapper input {
display: none;
}
#s_item {
display: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.staticaly.com/gh/moofawsaw/donorport/master/auto-fill.min.js"></script>
<a id="btn_studio" href="#" class="btn btn--new ripple w-button">Create</a>
<div>keywords are: blue, red, green</div>
<div id="s_list">
<div id="s_item" data-item="studio" data-mode="none" class="post__item studio__item">
<div data-item="studio" class="post__itemwrap post__itemwrap--studio">
<div class="search search--proj w-embed"><label class="search__label--proj" data-color="">
<input type="text" class="input--proj" autocomplete="off" placeholder="">
</label></div>
<div class="w-dyn-list">
<div class="w-dyn-items">
<div class="w-dyn-item">
<div class="w-embed">
<div class="studio__project" data-proj="Blue" data-color="blue"></div>
</div>
</div>
<div class="w-dyn-item">
<div class="w-embed">
<div class="studio__project" data-proj="Green" data-color="green"></div>
</div>
</div>
<div class="w-dyn-item">
<div class="w-embed">
<div class="studio__project" data-proj="Red" data-color="red"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
I have a simple project based on one variation of fullpage script. Everything works perfect except for one annoying thing - I can't understand how to make my right navigation bullets clickable (to an appropriate section). My js knowledge is not too good at the moment so I'd really appreciate any help, guys. Thanks!
$.fullPage = function(option) {
var defaultOpt = {
box: "#fullPageBox", // 滚屏页父元素
page: ".fullPage", // 滚屏页面
index: true, // 是否显示索引
duration: 1000, // 动画时间
direction: "vertical", // 滚屏方向 horizontal or vertical
loop: true // 是否循环
},
This = this,
index = 0,
over = true;
this.option = $.extend({}, defaultOpt, option || {});
this.box = $(this.option.box);
this.pages = $(this.option.page);
this.duration = this.option.duration;
// 绑定鼠标滚轮事件
$(document).on("mousewheel DOMMouseScroll", function(ev) {
var dir = ev.originalEvent.wheelDelta || -ev.originalEvent.detail;
if (over === false) return;
dir < 0 ? nextPage() : prevPage();
});
if (this.option.index) {
initPagination();
};
function initPagination() {
var oUl = $("<ul id='fullPageIndex'></ul>"),
liStr = "";
for (var i = 0, len = This.pages.length; i < len; i++) {
liStr += "<li></li>";
};
$(document.body).append(oUl.append($(liStr)));
$("#fullPageIndex li").eq(index).addClass("active").siblings().removeClass("active");
};
function nextPage() {
if (index < This.pages.length - 1) {
index++;
} else {
index = 0;
}
scrollPage(index, This.pages.eq(index).position());
};
function prevPage() {
if (index === 0) {
index = This.pages.length - 1;
} else {
index--;
}
scrollPage(index, This.pages.eq(index).position());
};
function scrollPage(index, position) {
over = false;
var cssStr = This.option.direction === "vertical" ? {
top: -position.top
} : {
left: -position.left
};
This.box.animate(cssStr, This.duration, function() {
over = true;
})
$("#fullPageIndex li").eq(index).addClass("active").siblings().removeClass("active");
};
}
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
overflow: hidden;
}
.pageBox {
position: relative;
height: 100%;
}
.main {
width: 100%;
height: 500%;
min-width: 1200px;
position: absolute;
left: 0;
top: 0;
color: #fff;
}
.main .fullPage {
height: 25%;
}
.bg1 {
background-color: #27AE60;
}
.bg2 {
background-color: #3498DB;
}
.bg3 {
background-color: #C0392B;
}
.bg4 {
background-color: #4FC2E5;
}
.bg5 {
background-color: #8E44AD;
}
#fullPageIndex {
position: absolute;
top: 50%;
right: 20px;
transform: translateY(-50%);
}
#fullPageIndex li {
width: 10px;
height: 10px;
list-style: none;
background-color: black;
margin: 6px 0;
border-radius: 50%;
}
#fullPageIndex li.active {
background-color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div class="pageBox">
<div class="main" id="fullPageBox">
<div class="fullPage bg1">jQuery fullPage.js</div>
<div class="fullPage bg2">Section 2</div>
<div class="fullPage bg3">Section 3</div>
<div class="fullPage bg4">Section 4</div>
<div class="fullPage bg5">Section 5</div>
</div>
</div>
<script>
$.fullPage();
</script>
</body>
Add an id attribute to you divs and add an anchor to the list elements that navigate to the desired sections. As follows:
<body>
<div class="pageBox">
<div class="main" id="fullPageBox">
<div id="section1" class="fullPage bg1">jQuery fullPage.js</div>
<div id="section2" class="fullPage bg2">Section 2</div>
<div id="section3" class="fullPage bg3">Section 3</div>
<div id="section4" class="fullPage bg4">Section 4</div>
<div id="section5" class="fullPage bg5">Section 5</div>
</div>
</div>
<script>
$.fullPage();
</script>
</body>
Update your js where you render the list items to look like this:
function initPagination() {
var oUl = $("<ul id='fullPageIndex'></ul>"),
liStr = "";
for (var i = 0, len = This.pages.length; i <= len; i++) {
var sectionNum = i + 1;
liStr += '<li></li>';
};
$(document.body).append(oUl.append($(liStr)));
$("#fullPageIndex li").eq(index).addClass("active").siblings().removeClass("active");
};
Read more here
EDIT:
Since you asked for a smooth scroll as well you could add this to your JS:
$('a[href*=#]:not([href=#])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'')
|| location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top
}, 1000);
return false;
}
}
});
Source for the snippet can be found on this page.
there is some mistake in your script.
First, remove below code from your HTML file:
<script>
fullPage();
</script>
Second is, you've created wrong function (method) define. I'am replace $.fullpage = function(option) { with var fullpage = function(options) {
and for the last is: since we have removed your fullpage() initiator, so we need to call this method again. for example at end line of your JS file,
P.S:
In Javascript you can create function in several ways. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions for more detail.
See fixed code below:
var fullPage = function(option) {
var defaultOpt = {
box: "#fullPageBox", // 滚屏页父元素
page: ".fullPage", // 滚屏页面
index: true, // 是否显示索引
duration: 1000, // 动画时间
direction: "vertical", // 滚屏方向 horizontal or vertical
loop: true // 是否循环
},
This = this,
index = 0,
over = true;
this.option = $.extend({}, defaultOpt, option || {});
this.box = $(this.option.box);
this.pages = $(this.option.page);
this.duration = this.option.duration;
// 绑定鼠标滚轮事件
$(document).on("mousewheel DOMMouseScroll", function(ev) {
var dir = ev.originalEvent.wheelDelta || -ev.originalEvent.detail;
if (over === false) return;
dir < 0 ? nextPage() : prevPage();
});
if (this.option.index) {
initPagination();
};
function initPagination() {
var oUl = $("<ul id='fullPageIndex'></ul>"),
liStr = "";
for (var i = 0, len = This.pages.length; i < len; i++) {
liStr += "<li></li>";
};
$(document.body).append(oUl.append($(liStr)));
$("#fullPageIndex li").eq(index).addClass("active").siblings().removeClass("active");
};
function nextPage() {
if (index < This.pages.length - 1) {
index++;
} else {
index = 0;
}
scrollPage(index, This.pages.eq(index).position());
};
function prevPage() {
if (index === 0) {
index = This.pages.length - 1;
} else {
index--;
}
scrollPage(index, This.pages.eq(index).position());
};
function scrollPage(index, position) {
over = false;
var cssStr = This.option.direction === "vertical" ? {
top: -position.top
} : {
left: -position.left
};
This.box.animate(cssStr, This.duration, function() {
over = true;
})
$("#fullPageIndex li").eq(index).addClass("active").siblings().removeClass("active");
};
}
fullPage();
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
overflow: hidden;
}
.pageBox {
position: relative;
height: 100%;
}
.main {
width: 100%;
height: 500%;
min-width: 1200px;
position: absolute;
left: 0;
top: 0;
color: #fff;
}
.main .fullPage {
height: 25%;
}
.bg1 {
background-color: #27AE60;
}
.bg2 {
background-color: #3498DB;
}
.bg3 {
background-color: #C0392B;
}
.bg4 {
background-color: #4FC2E5;
}
.bg5 {
background-color: #8E44AD;
}
#fullPageIndex {
position: absolute;
top: 50%;
right: 20px;
transform: translateY(-50%);
}
#fullPageIndex li {
width: 10px;
height: 10px;
list-style: none;
background-color: black;
margin: 6px 0;
border-radius: 50%;
}
#fullPageIndex li.active {
background-color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<body>
<div class="pageBox">
<div class="main" id="fullPageBox">
<div class="fullPage bg1">jQuery fullPage.js</div>
<div class="fullPage bg2">Section 2</div>
<div class="fullPage bg3">Section 3</div>
<div class="fullPage bg4">Section 4</div>
<div class="fullPage bg5">Section 5</div>
</div>
</div>
</body>
I want to create/use an add-remove box like this in HTML using angularJS where you have a list of some objects on the left and you select the objects to put them on under the headings listed on the right. Any idea what do we call such tables/lists and can I create/find them?
I don't know what is the accurate title to call it :)
but I tried to implement a sample of 'add/remove box' to achieve the concept you want with AngularJS!
the main part consists of three sections:
left section which is going to be added
middle section which contains the buttons
right section which is going to be removed
The code below applies the above section which aforesaid:
<div class="box leftBox">
<div>
<div id="{{left.name}}" ng-click="clicked($event, 0)" data-ng-repeat="left in lefts">{{left.name}}</div>
</div>
</div>
<div class="box button_holder">
<button ng-click="add()" class="button button-blue">ADD ></button>
<button ng-click="remove()" class="button button-red">< REMOVE</button>
<button ng-click="addAll()" class="button button-blue button-dark">ADD ALL >></button>
<button ng-click="removeAll()" class="button button-red button-dark"><< REMOVE ALL</button>
<button ng-click="deleteChoice()" class="button delete">X</button>
</div>
<div class="box rightBox">
<div>
<div ng-click="clicked($event, 1)" data-ng-repeat="right in rights">{{right.name}}</div>
</div>
</div>
by using angularjs directives including data-ng-repeat you can control the procedure of adding or removing
here is the implemented overview.
here is the completed code on the "codepen".
you can also check my github.
try to run the snippet in a fullscreen window!
/**
* Created by ALIREZA on 8/30/2017.
*/
var app = angular.module('Add_Remove_Box', []);
app.controller('Ctrl', function($scope) {
var i;
var isRepeated = false;
var actionLicense = true;
var prevElement = null;
var currentElement = null;
var positionSide = null;
$scope.choices = ["left", "right"];
$scope.lefts = [{
id: 'left1'
}, {
id: 'left2'
}, {
id: 'left3'
}, {
id: 'left4'
}];
for (i = 0; i < $scope.lefts.length; i++) {
$scope.lefts[i].name = "left" + (i + 1).toString();
}
$scope.rights = [{
id: 'right1'
}, {
id: 'right2'
}];
for (i = 0; i < $scope.rights.length; i++) {
$scope.rights[i].name = "right" + (i + 1).toString();
}
$scope.insert = function($event) {
var side = $scope.selectedSide;
if (side == null || side == "left") {
var leftItemNo = $scope.lefts.length + 1;
$scope.lefts.push({
'id': 'left' + leftItemNo
});
$scope.lefts[leftItemNo - 1].name = $scope.choice.name;
} else {
var rightItemNo = $scope.rights.length + 1;
$scope.rights.push({
'id': 'right' + rightItemNo
});
$scope.rights[rightItemNo - 1].name = $scope.choice.name;
}
};
$scope.deleteChoice = function() {
if (positionSide === 0) {
var ItemNo = -1;
$scope.lefts.forEach(function(i, j) {
if (i.name === currentElement.textContent) {
ItemNo = j;
return;
}
});
$scope.lefts.splice(ItemNo, 1);
}
};
$scope.add = function() {
if (actionLicense && positionSide === 0) {
actionLicense = false;
var leftItemNo = -1;
$scope.lefts.forEach(function(i, j) {
if (i.name === currentElement.textContent) {
leftItemNo = j;
return;
}
});
$scope.lefts.splice(leftItemNo, 1);
var rightItemNo = $scope.rights.length + 1;
$scope.rights.push({
'id': 'right' + rightItemNo
});
$scope.rights[rightItemNo - 1].name = currentElement.textContent;
}
};
$scope.remove = function() {
if (actionLicense && positionSide === 1) {
actionLicense = false;
var rightItemNo = -1;
$scope.rights.forEach(function(i, j) {
if (i.name === currentElement.textContent) {
rightItemNo = j;
return;
}
});
$scope.rights.splice(rightItemNo, 1);
var leftItemNo = $scope.lefts.length + 1;
$scope.lefts.push({
'id': 'left' + leftItemNo
});
$scope.lefts[leftItemNo - 1].name = currentElement.textContent;
}
};
$scope.addAll = function() {
$scope.lefts.forEach(function(i) {
var rightItemNo = $scope.rights.length + 1;
$scope.rights.push({
'id': 'right' + rightItemNo
});
$scope.rights[rightItemNo - 1].name = i.name;
});
$scope.lefts.splice(0, $scope.lefts.length);
};
$scope.removeAll = function() {
$scope.rights.forEach(function(i) {
var leftItemNo = $scope.lefts.length + 1;
$scope.lefts.push({
'id': 'left' + leftItemNo
});
$scope.lefts[leftItemNo - 1].name = i.name;
});
$scope.rights.splice(0, $scope.rights.length);
};
$scope.clicked = function($event, pos) {
actionLicense = true;
positionSide = pos;
currentElement = $event.currentTarget;
var deleteButton = document.getElementsByClassName("delete")[0];
if (pos === 1) {
if (deleteButton.className.indexOf("button-deactive") === -1) {
deleteButton.className += " button-deactive";
}
} else {
deleteButton.className = deleteButton.className.replace(" button-deactive", "");
}
if (prevElement === null) {
prevElement = currentElement;
} else {
if (prevElement === currentElement) {
isRepeated = !isRepeated;
} else {
if (isRepeated) {
isRepeated = false;
}
}
}
if (prevElement.className.indexOf("active") !== -1) {
prevElement.className = prevElement.className.replace(" active", "");
}
if (!isRepeated && currentElement.className.indexOf("active") === -1) {
currentElement.className += " active";
}
prevElement = currentElement;
};
});
* {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
.container {
display: inline-block;
width: 100%;
padding: 10px;
height: 100vh;
border: #E64A19 inset .7vh;
background: #616161;
/* fallback for old browsers */
background: -webkit-linear-gradient(to left, #9bc5c3, #616161);
/* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to left, #9bc5c3, #616161);
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
.addItems {
height: 10vh;
margin-bottom: 5vh;
}
.box {
float: left;
display: inline-block;
margin: 0;
padding: 10px;
height: 80vh;
border: #cfcfcf outset 2px;
color: #eee;
font-size: medium;
}
.box>div {
border: #FFF59D ridge 2px;
border-bottom: none;
border-radius: 5px;
}
.box>div>div {
padding: 7px;
border-bottom: #FFF59D ridge 2px;
}
.box>div>div:hover {
background-color: rgba(100, 150, 220, .5);
transition: background-color .4s ease;
}
.box>button {
display: inline-block;
width: 70%;
margin: 5% 15%;
}
.button {
padding: 10px 24px;
border-radius: 3px;
border: none;
box-shadow: 2px 5px 10px rgba(22, 22, 22, .1);
}
.button:hover {
transition: all 60ms ease;
opacity: .95;
box-shadow: #444 0 3px 3px 0;
}
.button-blue {
color: #FFFFFF;
background: #416dea;
}
.button-red {
color: #FFFFFF;
background: #F32C52;
}
.button-dark {
filter: brightness(85%) contrast(110%);
}
.leftBox {
width: 40%;
}
.button_holder {
width: 20%;
}
.rightBox {
width: 40%;
}
input[type="text"],
select {
padding: 5px;
}
.active {
transition: all .1s ease;
background-color: #888;
color: #000;
;
border: dotted 1px black;
box-shadow: 0 2px 2px 0 rgba(97, 97, 97, .5);
margin-bottom: 1px;
}
.button-deactive {
opacity: .5;
box-shadow: none;
}
.button-deactive:hover {
opacity: .5;
box-shadow: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AddRemoveBox</title>
<link rel="stylesheet" href="index.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<!--include angularJs-->
<script src="index.js"></script>
</head>
<body>
<div class="container" ng-app="Add_Remove_Box" ng-controller="Ctrl">
<fieldset class="addItems">
<legend>Insert Items</legend>
<select ng-model="selectedSide">
<option ng-repeat="choice in choices">{{choice}}</option>
</select>
<input type="text" ng-model="choice.name" name="" placeholder="Enter The Item Name">
<button class="button insert" value="insert" ng-click="insert($event)">Insert</button>
</fieldset>
<div class="box leftBox">
<div>
<div id="{{left.name}}" ng-click="clicked($event, 0)" data-ng-repeat="left in lefts">{{left.name}}</div>
</div>
</div>
<div class="box button_holder">
<button ng-click="add()" class="button button-blue">ADD ></button>
<button ng-click="remove()" class="button button-red">< REMOVE</button>
<button ng-click="addAll()" class="button button-blue button-dark">ADD ALL >></button>
<button ng-click="removeAll()" class="button button-red button-dark"><< REMOVE ALL</button>
<button ng-click="deleteChoice()" class="button delete">X</button>
</div>
<div class="box rightBox">
<div>
<div ng-click="clicked($event, 1)" data-ng-repeat="right in rights">{{right.name}}</div>
</div>
</div>
</div>
</body>
</html>
I'm trying to create list of suppliers (checkboxes + labels) and search field to filter suppliers. I managed to get list renderered and after first load it works fine, but after I search through supplier list first click on checkbox doesn't work. I need to click twice for checkbox to become checked.
screenshot
I need checkbox to become checked after first click when searching through supplier list. Please help.
I created this fiddle here
HTML:
<div class="col-sm-12">
<div class="infoBlock suppliersWrapper">
<div class="blockTitle">Supplier:</div>
<div class="blockContent">
<p class="checkedSupliersTitile">Supplier list:</p>
<div class="row">
<div class="col-sm-12 col-lg-8">
<input type="text" class="form-control stickTop" placeholder="Search..." id="SearchSupplierInput">
<ul class="supplierList scrollable" id="suppliers"></ul>
</div>
<div class="col-sm-12 col-lg-4">
<p class="checkedSupliersTitile">Checked suppliers:</p>
<p class="checkedSupliersText" id="checkedSuppliers">no suppliers selected</p>
</div>
</div>
</div>
</div>
</div>
CSS:
.supplierList label {
color: #575757;
display: block;
font-size: 15px;
font-weight: 400;
cursor:pointer;
font-family: 'Ubuntu', sans-serif;
}
.supplierList input[type="checkbox" ]{
width : 2em;
margin : 0;
padding : 0;
font-size : 1em;
opacity : 0;
}
.supplierList input[type="checkbox" ] + label{
display : inline-block;
margin-left : -1em;
line-height : 1.5em;
position:relative;
z-index: 33;
}
.supplierList input[type="checkbox"] + label::before {
border: 1px solid #d6d6d6;
border-radius: 1px;
content: "";
height: 20px;
left: -1.8em;
position: absolute;
top: 0.06em;
width: 20px;
-webkit-box-shadow: 3px 3px 0 0 rgba(25, 24, 25, 0.04) inset;
-moz-box-shadow: 3px 3px 0 0 rgba(25, 24, 25, 0.04) inset;
box-shadow: 3px 3px 0 0 rgba(25, 24, 25, 0.04) inset;
background: #ffffff;
}
.supplierList input[type="checkbox" ]:checked + label:before{
background:#46c87c;
}
.supplierList input[type="checkbox"]:checked + label::after {
color: #fff;
content: "";
font-family: "fontawesome";
left: -1.6em;
position: absolute;
top: 0;
}
JavaScript:
$(document).ready(function() {
var SupplierList = [{"name":"125","id":"1"},
{"name":"2Bit Telecom Corporation","id":"2"},
{"name":"Alleven Telecom Corp Standart","id":"3"}];
var selectedSuppliers = [];
// Собираем и фильтруем активных поставшиков
renderSupplierList(SupplierList);
$("#SearchSupplierInput").on("change paste keyup", function() {
var userInput = $(this).val();
var my_json = JSON.stringify(SupplierList);
var filtered_supplierList = find_in_object(JSON.parse(my_json), {name:userInput});
if (userInput.length >= 3) {
$("#suppliers").html("");
renderSupplierList(filtered_supplierList);
} else if(!userInput) {
$("#suppliers").html("");
renderSupplierList(SupplierList);
}
});
function renderSupplierList(array) {
array.forEach(function(item, i) {
if(typeof selectedSuppliers["id"+item.id] === 'undefined') {
var ifCheckd = "";
}
else {
var ifCheckd = "checked";
}
$("#suppliers").append('\
<li><span>\n\
<input class="supplierSelect" type="checkbox" id="supplier'+i+'" ' + ifCheckd + ' name="supplier" value="'+ item.id +'"> \n\
<label for="supplier'+i+'">'+ item.name +'</label>\n\
</span></li>');
});
}
function find_in_object(my_object, my_criteria) {
return my_object.filter(function(obj) {
//console.log(obj);
return Object.keys(my_criteria).every(function(c) {
//if (obj[c].search(/my_criteria[c]/i) == -1) {
if (obj[c].search(new RegExp(my_criteria[c], "i")) == -1) {
return false;
} else {
return true;
}
});
});
}
$('.supplierList').on('change', 'input[type=checkbox]', function() {
supplierCheckboxChange(this);
});
function sortSingle(array, key) {
return array.sort(function(a, b) {
var x = a[key]; var y = b[key];
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
}
function supplierCheckboxChange(currEl) {
var cText = $( currEl ).siblings("label").text();
var cID = "id" + currEl.value;
if(currEl.checked) {
selectedSuppliers[cID] = cText;
}
else {
delete selectedSuppliers[cID];
}
var tmpSuppl = [];
for (var key in selectedSuppliers) {
tmpSuppl.push(selectedSuppliers[key]);
}
tmpSuppl.sort(function(a, b) {
var x = a.toLowerCase(); var y = b.toLowerCase();
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
});
var suppliers = tmpSuppl.join(', ');
if (!suppliers) {
suppliers = "no suppliers selected";
}
$('#checkedSuppliers').text(suppliers);
}
});
This happens because your renderList function is being called more than once. First keyup is triggered when you press a key and then when text box looses focus(when you click on checkbox) change is triggered.
This causes your renderList method to get executed twice and the checked checkbox gets replace by a new checkbox.
To fix this, just change
$("#SearchSupplierInput").on("change paste keyup", function() { ... }
To
$("#SearchSupplierInput").on("paste keyup", function() { ... }
Have a look at this fiddle and check the console. https://jsfiddle.net/nh7u4Lck/2/