ng-repeat is not working with custom directive - html

I have created a custom directive, it's a spinner. it's working out side the ng-repeat and it's not working inside the ng-repeat.
Here is my html
<body ng-controller="controller">
<div>
<div>Spinner</div>
<div spinner jump="jump"> </div>
Spinner Value:- <span>{{jump}}</span>
<div>inside ng-repeat</div>
<div ng-repeat="i in counter(4) track by $index" >{{$index+1}}_spinner{{$index.i}}
<spinner result="jump" ng-model="jump"></spinner>
</div>
</div>
JS
var app = angular.module('plunker', [])
.directive('spinner', function() {
return {
restrict: 'EA',
scope: {
result:'=jump'
},
link: function ($scope, $element, $attrs) {
$scope.result = 0;
$scope.spinning = function(action) {
if(($scope.txtbox === '' || $scope.txtbox === undefined) && action === "add"){
$scope.result= Number($scope.result) +1;
}
else if(($scope.txtbox === '' || $scope.txtbox === undefined) && action === "sub") {
$scope.result= Number($scope.result) - 1;
}
else if($scope.txtbox !== '' && action === "sub") {
$scope.result = Number($scope.result) - Number($scope.txtbox);
}
else{
$scope.result = Number($scope.txtbox) + Number($scope.result);
}
};
},
templateUrl: 'spinnerDirective.html',
};
})
.controller('controller', ['$scope', function($scope) {
$scope.counter = Array;
}]);
Directive
<body>
<div class="container">
<div> Jumps: <input type='text' id="jumps" ng-model='txtbox'/></div>
<div style="float: left; width:120px; margin-top:10px;" >
<div style="border-color: red; border-style: solid; border-width: 1px 1px 1px 1px; margin-left: 10px; text-align: center; height: 30px; line-height: 2px;" >
<label style="vertical-align: top;line-height: normal;" ng-click="spinning('add');" >+</label>
</div>
<div style="margin-top: -12px; text-align: center; height:12px;margin-left: 7px;">
<label id="spinn" style="background-color: #fff;font-size:18px;" >{{result}}</label>
</div>
<div style="border-color: red; border-style: solid; border-width: 0 1px 1px 1px; margin-left: 10px; text-align: center; height: 30px;line-height: 27px;">
<label style="vertical-align: bottom;line-height: normal;" ng-click="spinning('sub');">-</label>
</div>
</div>
</div>
</body>
http://plnkr.co/edit/KPHqes1baju70oSYRdRp?p=preview
I need my inside ng-repeat spinner should work same as the outside ng-repeat spinner and have to display the value of each spinner separately.

Related

How to do a function call in HTML with vueJS

For my dev lessons, I need to create a social network for a company.
One of the functionalities is to display the comment number linked to a publication (a bit like on Facebook).
To get the comments, I am using vueX to get all data from one source. So, to display the comment count number, here is my idea : for each publication contained in an array, I get all publication comments in another array. So, if I do a {{comments.length}}, for example, this should display "3 comments"
So I wrote the following code :
<div v-if="publications.length > 0">
<AddPostForm />
<section
v-for="post in publications"
:key="post.postId"
class="publications"
>
<div v-bind:data-id="post.postId" class="publications__card">
<div class="publications__author" :data-user-id="post.userId">
<img :src="post.avatarUrl" alt="Photo de profil" />
<span
class="publications__author-profile"
#click="goToProfile(post.userId)"
>
{{ post.firstName }} {{ post.lastName }}
</span>
</div>
<div
class="publications__content"
v-if="post.postContent !== null && post.postContent !== ''"
>
<p>{{ post.postContent }}</p>
</div>
<div
class="publications__content"
v-else-if="
post.postContent === null ||
(post.postContent === '' &&
(post.imageUrl !== null || post.imageUrl !== ''))
"
>
<img :src="post.imageUrl" alt="Image de publication" />
</div>
<div
class="publications__content"
v-else-if="
(post.postContent !== null || post.postContent !== '') &&
(post.imageUrl !== null || post.imageUrl !== '')
"
>
<p>{{ post.postContent }}</p>
<img :src="post.imageUrl" alt="Image de publication" />
</div>
<div class="publications__date-time">
<p>Publié le {{ post.post_date }}</p>
</div>
<div class="publications__delete" v-if="user.admin === 1">
<p class="publications__delete-txt" #click="deletePost(post.postId)">
Supprimer
</p>
</div>
<div
class="publications__like-comment-count"
v-if="post.comment_count > 0"
>
<div
class="publications__comment-count"
#click="goToComments(post.userId, post.postId)"
v-if="comments.length === 1"
>
{{ comments.length }} commentaire
</div>
<div
class="publications__comment-count"
#click="goToComments(post.userId, post.postId)"
v-else
>
{{ comments.length }} commentaires
</div>
</div>
<div class="publications__like-comment">
<div class="like-comment__like">
<FaSolidHeart />
<span class="icon__legend"> J'aime</span>
</div>
<div class="like-comment__comment" #click="comment = true">
<FaSolidComment />
<span
class="icon__legend"
#click="goToComments(post.userId, post.postId)"
> Commenter</span
>
</div>
</div>
</div>
</section>
</div>
<div v-else-if="publications.length === 0">
<p>Aucune publication pour le moment</p>
</div>
</template>
<script>
import axios from 'axios';
import { mapState } from 'vuex';
import FaSolidHeart from './Heart.vue';
import FaSolidComment from './CommentIcon.vue';
import AddPostForm from './AddPost.vue';
const userSessionData = JSON.parse(localStorage.getItem('userSession'));
const sessionToken = userSessionData.token;
if (sessionToken) {
axios.defaults.headers.common['Authorization'] = 'Bearer ' + sessionToken;
}
export default {
name: 'Wall',
components: {
FaSolidHeart,
FaSolidComment,
AddPostForm
},
data() {
return {
comment: false,
user: []
};
},
beforeMount() {
this.getResult();
this.getSession();
},
methods: {
getResult: function () {
this.$store.dispatch('setPublications');
},
goToProfile: function (userId) {
this.$router.push(`/profile/${userId}`);
},
goToComments: function (userId, postId) {
this.$router.push(`/comments/${userId}/${postId}`);
},
getSession: function () {
if (localStorage.userSession) {
this.user = JSON.parse(localStorage.userSession);
}
},
deletePost: function (postId) {
axios
.delete(`http://localhost:3000/api/publications/${postId}`)
.then(() => this.$router.go())
.catch((error) => console.log(error));
},
getComments: function (postId) {
// this.$store.dispatch('getPublicationComments', postId);
console.log(postId);
}
},
computed: {
...mapState(['publications', 'comments'])
}
};
</script>
<style scoped>
.publications {
width: 30%;
margin: 10px auto;
}
.publications__card {
width: 99%;
padding: 10px;
padding-left: 15px;
display: flex;
flex-direction: column;
justify-content: center;
background-color: rgba(138, 185, 241, 0.4);
}
.publications__card .publications__author:hover {
cursor: pointer;
}
.publications__card .publications__date-time {
margin-top: -20px;
font-size: 0.8rem;
color: grey;
}
.publications__card .publications__delete .publications__delete-txt {
margin-top: -5px;
font-size: 0.85rem;
}
.publications__card .publications__like-comment-count {
width: 92%;
height: fit-content;
margin: auto 0;
padding: 5px;
border-top: 1px solid white;
}
.publications__card .publications__comment-count {
margin-right: 15px;
text-align: right;
}
.publications__card .publications__like-comment {
width: 95%;
height: fit-content;
margin: auto 0;
padding-top: 10px;
display: flex;
justify-content: space-around;
border-top: 1px solid white;
}
.publications__card .like-comment__like:hover,
.publications__card .like-comment__comment:hover,
.publications__card .publications__comment-count:hover,
.publications__card .publications__delete .publications__delete-txt:hover {
cursor: pointer;
color: #4b77be;
}
.publications__card .publications__add-comment {
width: 95%;
padding-top: 5px;
border-top: 1px solid white;
}
.publications__card .publications__add-comment .add-comment__field {
width: 98%;
height: 25px;
margin-top: 5px;
padding-top: 0px;
padding: 13px;
border-radius: 50px;
resize: none;
font-family: 'poppins';
outline: none;
}
</style>
My question is how may I call the getComments function from the HTML so that I can display comment count number properly ?
Thank you so much for your help :)
You can simply do {{ getComments() }} in your markup.
I am not sure if this will work, but if you store the comments in vuex, you can use this:
<p>{{ this.$store.state.comments.length }}<p>
This only works if the comments is correctly stored in vuex, I hope this will work for you.

add color picker on top of an appended child

So I have a script that will add a text box and I want to add on top of that text box a color wheel
also I'm using electron if this helps. Any help is appreciated!
<input class="addcommandbtn" type="button" id="addCommand" style="width: 6.5%;" value="+ Command">
<select name="commandslist" id="commandslist" size="18%" style="height: 59%;width: 15%; display: block; border: 1px solid #dcdcdc; border-radius: 6px; margin-top: 5px;"></select>
<script>
function createCommandField() {
var input = document.createElement('option');
input.style.marginTop = "1%";
input.textContent = "command";
input.name = 'Commands[]';
input.style.display = 'block'
input.style.boxShadow = 'inset 0px 1px 0px 0px #ffffff';
input.style.border = '1px solid #dcdcdc';
input.style.borderRadius = '6px';
input.style.height = "2%";
input.style.padding = '5px 30px';
input.style.fontFamily = "Arial";
input.style.fontWeight = "bold";
input.style.fontSize = "17px";
return input;
}
var select = document.getElementById('commandslist');
document.getElementById('addCommand').addEventListener('click', function (e) {
select.appendChild(createCommandField());
});
</script>
here is a jquery script to get the color input changed on EDITED: selected option double click
added a function to apply selected color on the background of the same selection and un-select it to c the effect,
goodluck,
function createCommandField() {
var input = document.createElement('option');
input.style.marginTop = "1%";
input.textContent = "command";
input.name = 'Commands[]';
input.style.display = 'block'
input.style.boxShadow = 'inset 0px 1px 0px 0px #ffffff';
input.style.border = '1px solid #dcdcdc';
input.style.borderRadius = '6px';
input.style.height = "2%";
input.style.padding = '5px 30px';
input.style.fontFamily = "Arial";
input.style.fontWeight = "bold";
input.style.fontSize = "17px";
return input;
}
$(document).ready(function() {
var bgclr ='';
var parentopt = $('#pckrbg');
$('#commandslist').change(function() {
var crntslct = $('#commandslist').children('option:selected');
crntslct.dblclick(function() {
parentopt.click();
parentopt.change(function(){
bgclr = parentopt.val();
$('#commandslist').prop("selectedIndex", function(){
$(this).children('option:selected').css("background", bgclr); //set background
$(this).children('option:selected').prop("selected", false); //deselect option;
});
});
});
});
});
var select = document.getElementById('commandslist');
document.getElementById('addCommand').addEventListener('click', function(e) {
select.appendChild(createCommandField());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span><input type="color" value="#FFEE00" id="pckrbg" name="colorz" style="position:relative; display:none; float:left; margin-right:1rem; bottom:3px;"></span>
<form class="myformclass" style="font-family: sans-serif;font-size:20px;" id="myForm" onsubmit="return validateForm()">
<input class="addcommandbtn" type="button" id="addCommand" style="width: 6.5%;" value="+ Command">
<input class="addcommandbtn" type="button" id="removeCommand" style="width: 7.2%;" value="- Command" onclick="removeCommandFunc()">
<input class="savebtn" type="button" id="saveCommands" style="width: 4%; float: right;" value="Save" onclick="SaveToLocalStorage()">
<!-- Retrive Button <input class="Retrive" type="button" id="Callback" value="Retrive From LocalStorage" style="float:right;margin-right:3rem;" > -->
<select name="commandslist" id="commandslist" size="5%" style="width: 50%; display: block; border: 1px solid #dcdcdc; border-radius: 6px; margin-top: 5px;"></select>
<select name="resplist" id="resplist" size="18%" style="height: 20%;width: 59%; display: block; border: 1px solid #dcdcdc; border-radius: 6px; margin-top: 5px; margin-left: 20%;"></select>
</form>

Why does HTML <a> tag sometimes work and other times doesn't in a 2 level nested accordion?

I'm using Bootstrap and I'm trying to make an accordion of items nested inside an accordion. So it would be like top level is an accordion containing many physical quantities panels, and each physical quantity panel's content is an accordion containing a list of SI-conversion-factors panels whose content is a list of units of measurements.
Every a tag on the top level accordion works but in the 2nd level accordion some a tags work and some don't.
Download:
You can see for your self by downloading a zip containing minimum amount of code to replicate the problem:
minimal-code.html
collapse.js
jquery-2.2.4.min.js
css.css
Pictures:
I took some pictures before and after clicking one that don't work and one that do work. Pictures are not from the minimal code to replicate problem version.
I like the accordion style to present the data, what would I have to do to make it work? If not, I can try other styles such as collapse or a simple nested list.
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset='utf-8'>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- <script src="jquery-2.2.4.min.js"></script>
<script src="collapse.js"></script>
<link rel="stylesheet" href="css.css"> -->
</head>
<body>
<div aria-multiselectable="true" id="dimension-accordion" role="tablist" data-reactid=".0.3.0.0.1.0">
<div class="panel panel-info" data-reactid=".0.3.0.0.1.0.$79">
<div role="tab" id="heading-dimension-id-79" class="panel-heading" data-reactid=".0.3.0.0.1.0.$79.0">
<a data-toggle="collapse" data-parent="#dimension-accordion" href="#collapse-dimension-id-79" aria-expanded="false" aria-controls="collapse-dimension-id-79" data-reactid=".0.3.0.0.1.0.$79.0.0">
<h2 data-reactid=".0.3.0.0.1.0.$79.0.0.0"><span class="badge" data-reactid=".0.3.0.0.1.0.$79.0.0.0.0">31</span><span data-reactid=".0.3.0.0.1.0.$79.0.0.0.1">current = {"A" 1}</span></h2>
</a>
</div>
<div id="collapse-dimension-id-79" aria-labelledby="heading-dimension-id-79" role="tabpanel" class="panel-collapse collapse" data-reactid=".0.3.0.0.1.0.$79.1">
<div id="accordion-conversion-factor-for-79" role="tablist" aria-multiselectable="true" data-reactid=".0.3.0.0.1.0.$79.1.0">
<div class="panel panel-default" data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835">
<div role="tab" id="0.999835" class="panel-heading" data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.0">
<a data-toggle="collapse" data-parent="#accordion-conversion-factor-for-79" href="#collapse-id-0.999835" aria-expanded="false" aria-controls="collapse-id-0.999835" data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.0.0">
<h3 data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.0.0.0"><span class="badge" data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.0.0.0.0">4</span><span data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.0.0.0.1">0.999835</span></h3>
</a>
</div>
<div id="collapse-id-0.999835" aria-labelledby="0.999835" role="tabpanel" class="panel-collapse collapse" data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.1">
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.1.$4058">intamp</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.1.$3015">intampere</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.1.$4207">intamperes</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$0=1999835.1.$4175">intamps</h4>
</div>
</div>
<div class="panel panel-default" data-reactid=".0.3.0.0.1.0.$79.1.0.$1">
<div role="tab" id="1" class="panel-heading" data-reactid=".0.3.0.0.1.0.$79.1.0.$1.0">
<a data-toggle="collapse" data-parent="#accordion-conversion-factor-for-79" href="#collapse-id-1" aria-expanded="false" aria-controls="collapse-id-1" data-reactid=".0.3.0.0.1.0.$79.1.0.$1.0.0">
<h3 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.0.0.0"><span class="badge" data-reactid=".0.3.0.0.1.0.$79.1.0.$1.0.0.0.0">7</span><span data-reactid=".0.3.0.0.1.0.$79.1.0.$1.0.0.0.1">1</span></h3>
</a>
</div>
<div id="collapse-id-1" aria-labelledby="1" role="tabpanel" class="panel-collapse collapse" data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1">
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$3269">A</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$2566">amp</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$1900">ampere</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$1857">amperes</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$303">amps</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$4186">galvat</h4>
<h4 data-reactid=".0.3.0.0.1.0.$79.1.0.$1.1.$604">galvats</h4>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
CSS:
.panel {
margin-bottom: 20px;
background-color: #fff;
border: 1px solid transparent;
border-radius: 4px;
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
}
.panel-info {
border-color: #bce8f1;
}
.panel-info > .panel-heading {
color: #31708f;
background-color: #d9edf7;
border-color: #bce8f1;
}
.panel-info > .panel-heading + .panel-collapse > .panel-body {
border-top-color: #bce8f1;
}
.panel-info > .panel-heading .badge {
color: #d9edf7;
background-color: #31708f;
}
.panel-info > .panel-footer + .panel-collapse > .panel-body {
border-bottom-color: #bce8f1;
}
.panel-heading {
padding: 10px 15px;
border-bottom: 1px solid transparent;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.badge {
display: inline-block;
min-width: 10px;
padding: 3px 7px;
font-size: 12px;
font-weight: bold;
line-height: 1;
color: #fff;
text-align: center;
white-space: nowrap;
vertical-align: middle;
background-color: #777;
border-radius: 10px;
}
.collapse {
display: none;
}
.collapse.in {
display: block;
}
jquery-2.2.4.min.js:
https://code.jquery.com/jquery-2.2.4.min.js
collapse.js:
/* ========================================================================
* Bootstrap: collapse.js v3.3.6
* http://getbootstrap.com/javascript/#collapse
* ========================================================================
* Copyright 2011-2015 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// COLLAPSE PUBLIC CLASS DEFINITION
// ================================
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Collapse.DEFAULTS, options)
this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
'[data-toggle="collapse"][data-target="#' + element.id + '"]')
this.transitioning = null
if (this.options.parent) {
this.$parent = this.getParent()
} else {
this.addAriaAndCollapsedClass(this.$element, this.$trigger)
}
if (this.options.toggle) this.toggle()
}
Collapse.VERSION = '3.3.6'
Collapse.TRANSITION_DURATION = 350
Collapse.DEFAULTS = {
toggle: true
}
Collapse.prototype.dimension = function () {
var hasWidth = this.$element.hasClass('width')
return hasWidth ? 'width' : 'height'
}
Collapse.prototype.show = function () {
if (this.transitioning || this.$element.hasClass('in')) return
var activesData
var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
if (actives && actives.length) {
activesData = actives.data('bs.collapse')
if (activesData && activesData.transitioning) return
}
var startEvent = $.Event('show.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
if (actives && actives.length) {
Plugin.call(actives, 'hide')
activesData || actives.data('bs.collapse', null)
}
var dimension = this.dimension()
this.$element
.removeClass('collapse')
.addClass('collapsing')[dimension](0)
.attr('aria-expanded', true)
this.$trigger
.removeClass('collapsed')
.attr('aria-expanded', true)
this.transitioning = 1
var complete = function () {
this.$element
.removeClass('collapsing')
.addClass('collapse in')[dimension]('')
this.transitioning = 0
this.$element
.trigger('shown.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
var scrollSize = $.camelCase(['scroll', dimension].join('-'))
this.$element
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
}
Collapse.prototype.hide = function () {
if (this.transitioning || !this.$element.hasClass('in')) return
var startEvent = $.Event('hide.bs.collapse')
this.$element.trigger(startEvent)
if (startEvent.isDefaultPrevented()) return
var dimension = this.dimension()
this.$element[dimension](this.$element[dimension]())[0].offsetHeight
this.$element
.addClass('collapsing')
.removeClass('collapse in')
.attr('aria-expanded', false)
this.$trigger
.addClass('collapsed')
.attr('aria-expanded', false)
this.transitioning = 1
var complete = function () {
this.transitioning = 0
this.$element
.removeClass('collapsing')
.addClass('collapse')
.trigger('hidden.bs.collapse')
}
if (!$.support.transition) return complete.call(this)
this.$element
[dimension](0)
.one('bsTransitionEnd', $.proxy(complete, this))
.emulateTransitionEnd(Collapse.TRANSITION_DURATION)
}
Collapse.prototype.toggle = function () {
this[this.$element.hasClass('in') ? 'hide' : 'show']()
}
Collapse.prototype.getParent = function () {
return $(this.options.parent)
.find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
.each($.proxy(function (i, element) {
var $element = $(element)
this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
}, this))
.end()
}
Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
var isOpen = $element.hasClass('in')
$element.attr('aria-expanded', isOpen)
$trigger
.toggleClass('collapsed', !isOpen)
.attr('aria-expanded', isOpen)
}
function getTargetFromTrigger($trigger) {
var href
var target = $trigger.attr('data-target')
|| (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
return $(target)
}
// COLLAPSE PLUGIN DEFINITION
// ==========================
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.collapse')
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
}
var old = $.fn.collapse
$.fn.collapse = Plugin
$.fn.collapse.Constructor = Collapse
// COLLAPSE NO CONFLICT
// ====================
$.fn.collapse.noConflict = function () {
$.fn.collapse = old
return this
}
// COLLAPSE DATA-API
// =================
$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
var $this = $(this)
if (!$this.attr('data-target')) e.preventDefault()
var $target = getTargetFromTrigger($this)
var data = $target.data('bs.collapse')
var option = data ? 'toggle' : $this.data()
Plugin.call($target, option)
})
}(jQuery);

AngularJS / NgMap - Zoom to selected pins and center

I have an SPA that is displaying pins on a map that are filtered down by Region, State/Province and ultimately City. I have Lat/Lng in my locations, and I'm passing that to the map markup and filtering it on each select list selection. I'm running in to issues with getting the map to focus on each region as it's subsequently filtered down.
Is there a way to recenter when using the markup to display the markers, or to do that would I need to rework the code to handle displaying the markers in the JS instead of the markup?
See Plunkr: http://plnkr.co/edit/qaLFYD?p=preview
var app = angular.module('plunker', ['ngRoute', 'angular.filter', 'ngMap']);
app.controller('MainCtrl', function($scope, $anchorScroll, $location, $http) {
// GET data
$scope.dataObject = data.List;
$scope.locationObject = data.Locations;
$scope.cart = [];
$scope.addToCart = function(index) {
$scope.cart.push(index);
$scope.cartCount = $scope.cart.length;
}
$scope.activeRow = function(index) {
$scope.selectedRow = index;
$location.hash();
$anchorScroll('anchor-' + index);
}
$scope.gotoAnchor = function(x) {
var newHash = 'anchor' + x;
}
$scope.$on('mapInitialized', function(event, map) {
map.setOptions({
draggable: true
});
});
}).filter('byFilter', function() {
return function(items, location) {
var filtered = [];
if (!location || !items.length) {
return items;
}
items.forEach(function(itemElement, itemIndex) {
itemElement.Locations.forEach(function(locationElement, locationIndex) {
if (filterCountry(locationElement, location) || filterRegion(locationElement, location) || filterCity(locationElement, location))
filtered.push(itemElement);
});
});
return filtered;
};
function filterCountry(locationElement, location) {
var exist = false;
if (!location.Region) {
exist = true;
return exist;
} else exist = (locationElement.Region === location.Region);
return exist;
}
function filterRegion(locationElement, location) {
var exist = false;
if (!location.StateName) {
exist = true;
return exist;
}
locationElement.Sites.forEach(function(siteElement, siteIndex) {
if (siteElement.State === location.StateName) {
exist = true;
return false;
}
});
return exist;
}
function filterCity(locationElement, location) {
var exist = false;
if (!location.CityName) {
exist = true;
return exist;
}
locationElement.Sites.forEach(function(siteElement, siteIndex) {
if (siteElement.City === location.CityName) {
exist = true;
return false;
}
});
return exist;
}
}).filter('ForMap', function() {
return function(items, location) {
var filtered = [];
if (!items) {
return items;
}
var state = (location.state ? location.state.StateName : '');
var city = (location.city ? location.city.CityName : '');
var region = (location.region ? location.region.Region : '');
items.forEach(function(itemElement, itemIndex) {
itemElement.Locations.forEach(function(locationElement, locationIndex) {
if (locationElement.Region === region || !region) {
locationElement.Sites.forEach(function(siteElement, siteIndex) {
if ((siteElement.State == state && !city) || siteElement.City == city || (!state && !city)) {
filtered.push(siteElement);
return false;
}
});
}
});
});
return filtered;
};
});
/* Put your css in here */
body {
background: #eee;
}
div.cart {
display: block;
height: 70px;
background: silver;
margin-left: 20px;
width: 200px;
padding: 5px 10px;
margin-bottom: 20px;
margin-top: 20px;
}
.cart h1 {
color: #fff;
line-height: 20px;
}
.item-list-wrapper {
height: 400px;
width: 90%;
border: 1px solid #ddd;
overflow-y: scroll;
margin-left: 20px;
}
.item-list-wrapper table td {
padding: 10px;
vertical-align: middle;
margin-bottom: 10px;
font-size: 12px;
}
.item-list {
height: auto;
width: 100%;
margin-bottom: 10px;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
border: 1px solid #fff;
background: #efefe4;
}
.col-num {
width: 100px;
}
.col-compound {
width: 80px;
}
.filters {
width: 100%;
clear: both;
margin-left: 20px;
}
.filters select {
width: 200px;
}
.filters column {
height: 100px;
width: 200px;
display: inline-block;
margin: 0;
padding: 0;
}
.filters select {
display: inline-block;
}
.region {
font-weight: bolder;
}
.state {
font-weight: normal;
}
.map-wrapper {
width: 490px;
height: 490px;
}
map {
width: 490px;
height: 490px;
}
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link data-require="bootstrap#*" data-semver="3.3.5" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" />
<link data-require="bootstrap-css#*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<link rel="stylesheet" href="angular-ui.min.css" />
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script data-require="angular.js#1.4.x" data-semver="1.4.7" src="https://code.angularjs.org/1.4.7/angular-messages.js"></script>
<script data-require="ui-bootstrap#*" data-semver="0.13.3" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.1/ui-bootstrap.min.js"></script>
<script src="angular-filter.min.js"></script>
<script src="angular-route.min.js"></script>
<script src="ng-map.min.js"></script>
<script src="angular-ui.min.js"></script>
<script src="angular-scroll.min.js"></script>
<script src="app.js"></script>
<script src="http://zbl.me/test/103015.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-view=""></div>
<div class="filters">
<h2>Filter results</h2>
<column>
<select name="selectRegion" class="form-control" ng-model="selectRegion" ng-options="location as location.Region for location in locationObject | orderBy: location.Region:reverse">
<option value="">Select Region</option>
</select>
<select name="selectState" class="form-control" ng-disabled="!selectRegion" ng-model="selectState" ng-options="state as state.StateName for state in selectRegion.States">
<option value="">Select State/Province/Country</option>
</select>
<select name="selectCity" class="form-control" ng-disabled="!selectState" ng-model="selectCity" ng-options="city as city.CityName for city in selectState.Cities">
<option value="">Select City</option>
</select>
</column>
<column>
<select name="selectPhase" class="form-control" ng-model="selectPhase" ng-options="data.Phase as data.Phase for data in dataObject | unique: 'Phase' | orderBy: 'Phase' ">
<option value="">Select Phase</option>
</select>
<select name="selectNumber" class="form-control" ng-model="selectNumber" ng-options="data.Number as data.Number for data in dataObject | unique: 'Compound' | orderBy: 'Compound' ">
<option value="">Select Number</option>
</select>
</column>
</div>
<div map-lazy-load="http://maps.google.com/maps/api/js">
<map zoom="1" scrollwheel="false">
<span ng-repeat="site in (dataObject | ForMap : {region:selectRegion, state:selectState, city:selectCity}) track by $index" id="{{data.Id}}">
<marker position="[{{site.Latitude}},{{site.Longitude}}]"></marker>
</span>
</map>
</div>
<div class="cart">
<h1>Cart: {{cartCount}}</h1>
</div>
<div class="item-list-wrapper">
<table class="table table-condensed table-hover">
<tr ng-repeat="data in dataObject | byFilter | filterBy:['Phase']: selectPhase | filterBy:['Number']: selectNumber track by $index" ng-click="activeRow($index)">
<td class="column">{{data.Phase}}</td>
<td class="column col-num">{{data.Number}}</td>
<td class="column col-compound">{{data.Compound}}</td>
<td>
<span ng-repeat="location in data.Locations track by $index" class="region">{{ location.Region}}:
<span ng-repeat="site in location.Sites | unique: 'State'" class="state">{{site.State}}
</span>
</span>
</td>
<td>Add
</td>
</tr>
</table>
</div>
</body>
</html>
Looks like adding zoom-to-include-markers="true" to the map element achieves this.
<div map-lazy-load="http://maps.google.com/maps/api/js">
<map zoom="1" scrollwheel="false" zoom-to-include-markers="auto">
<span ng-repeat="site in (dataObject | ForMap : {region:selectRegion, state:selectState, city:selectCity}) track by $index" id="{{data.Id}}">
<marker position="[{{site.Latitude}},{{site.Longitude}}]"></marker>
</span>
</map>
</div>

How to customize <input type="file">?

Is it possible to change the appearance of <input type="file">?
You can’t modify much about the input[type=file] control itself.
Since clicking a label element correctly paired with an input will activate/focus it, we can use a label to trigger the OS browse dialog.
Here is how you can do it…
label {
cursor: pointer;
/* Style as you please, it will become the visible UI component. */
}
#upload-photo {
opacity: 0;
position: absolute;
z-index: -1;
}
<label for="upload-photo">Browse...</label>
<input type="file" name="photo" id="upload-photo" />
The CSS for the form control will make it appear invisible and not take up space in the document layout, but will still exist so it can be activated via the label.
If you want to display the user’s chosen path after selection, you can listen for the change event with JavaScript and then read the path that the browser makes available to you (for security reasons it can lie to you about the exact path). A way to make it pretty for the end user is to simply use the base name of the path that is returned (so the user simply sees the chosen filename).
There is a great guide by Tympanus for styling this.
Something like that maybe?
<form>
<input id="fileinput" type="file" style="display:none;"/>
</form>
<button id="falseinput">El Cucaratcha, for example</button>
<span id="selected_filename">No file selected</span>
<script>
$(document).ready( function() {
$('#falseinput').click(function(){
$("#fileinput").click();
});
});
$('#fileinput').change(function() {
$('#selected_filename').text($('#fileinput')[0].files[0].name);
});
</script>
<label for="fusk">dsfdsfsd</label>
<input id="fusk" type="file" name="photo" style="display: none;">
why not? ^_^
See the example here
If you're using Bootstrap here is a better solution:
<label class="btn btn-default btn-file">
Browse <input type="file" style="display: none;" required>
</label>
For IE8 and below: https://www.abeautifulsite.net/posts/whipping-file-inputs-into-shape-with-bootstrap-3/#legacy-approach-(ie8-and-below)
Source: https://stackoverflow.com/a/18164555/625952
Easiest way..
<label>
Upload
<input type="file" style="visibility: hidden;"/>
</label>
The trick is hide the input and customize the label.
HTML:
<div class="inputfile-box">
<input type="file" id="file" class="inputfile" onchange='uploadFile(this)'>
<label for="file">
<span id="file-name" class="file-box"></span>
<span class="file-button">
<i class="fa fa-upload" aria-hidden="true"></i>
Select File
</span>
</label>
</div>
CSS:
.inputfile-box {
position: relative;
}
.inputfile {
display: none;
}
.container {
display: inline-block;
width: 100%;
}
.file-box {
display: inline-block;
width: 100%;
border: 1px solid;
padding: 5px 0px 5px 5px;
box-sizing: border-box;
height: calc(2rem - 2px);
}
.file-button {
background: red;
padding: 5px;
position: absolute;
border: 1px solid;
top: 0px;
right: 0px;
}
JS:
function uploadFile(target) {
document.getElementById("file-name").innerHTML = target.files[0].name;
}
You can check this example: https://jsfiddle.net/rjurado/hnf0zhy1/4/
In webkit you can try this out...
input[type="file"]::-webkit-file-upload-button{
/* style goes here */
}
first of all it's a container:
<div class="upload_file_container">
Select file!
<input type="file" name="photo" />
</div>
The second, it's a CSS style, if you want to real more customization, just keeping your eyes is open :)
.upload_file_container{
width:100px;
height:40px;
position:relative;
background(your img);
}
.upload_file_container input{
width:100px;
height:40px;
position:absolute;
left:0;
top:0;
cursor:pointer;
}
This example hasn't style for text inside the button, it depends on font-size, just correct the height and padding-top values for container
It's much better if you just use a <label>, hide the <input>, and customize the label.
HTML:
<input type="file" id="input">
<label for="input" id="label">Choose File</label>
CSS:
input#input{
display: none;
}
label#label{
/* Customize your label here */
}
Bootstrap example
<label className="btn btn-info btn-lg">
Upload
<input type="file" style="display: none" />
</label>
Here is a quick pure CSS workaround (works on chrome and has a FireFox fallback included), including the file name,a label and an custom upload button, does what it should - no need for JavaScript at all! 🎉
Note: ☝ anyways, I would not use it on a real world website - if browser compatibility is a thing to you (what it should be). So it's more kind of experimental, otherwise while time goes by, it could be that this isn't an issue today.
.fileUploadInput {
display: grid;
grid-gap: 10px;
position: relative;
z-index: 1; }
.fileUploadInput label {
display: flex;
align-items: center;
color: setColor(primary, 0.5);
background: setColor(white);
transition: .4s ease;
font-family: arial, sans-serif;
font-size: .75em;
font-weight: regular; }
.fileUploadInput input {
position: relative;
z-index: 1;
padding: 0 gap(m);
width: 100%;
height: 50px;
border: 1px solid #323262;
border-radius: 3px;
font-family: arial, sans-serif;
font-size: 1rem;
user-select: none;
cursor: pointer;
font-weight: regular; }
.fileUploadInput input[type="file"] {
padding: 0 gap(m); }
.fileUploadInput input[type="file"]::-webkit-file-upload-button {
visibility: hidden;
margin-left: 10px;
padding: 0;
height: 50px;
width: 0; }
.fileUploadInput button {
position: absolute;
right: 0;
bottom: 0;
width: 50px;
height: 50px;
line-height: 0;
user-select: none;
color: white;
background-color: #323262;
border-radius: 0 3px 3px 0;
font-family: arial, sans-serif;
font-size: 1rem;
font-weight: 800; }
.fileUploadInput button svg {
width: auto;
height: 50%; }
* {
margin: 0px;
padding: 0px;
box-sizing: border-box;
border: 0px;
outline: 0;
background-repeat: no-repeat;
appearance: none;
border-radius: 0;
vertical-align: middle;
font-weight: inherit;
font-style: inherit;
font-family: inherit;
text-decoration: none;
list-style: none;
user-select: text;
line-height: 1.333em; }
body {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100vh;
background: rgba(66, 50, 98, 0.05); }
.container {
padding: 25px;
box-shadow: 0 0 20px rgba(66, 50, 98, 0.35);
border: 1px solid #eaeaea;
border-radius: 3px;
background: white; }
#-moz-document url-prefix() {
.fileUploadInput button{
display: none
}
}
<!-- Author: Ali Soueidan-->
<!-- Author URI: https//: www.alisoueidan.com-->
<div class="container">
<div class="fileUploadInput">
<label>✨ Upload File</label>
<input type="file" />
<button>+</button></div>
</div>
to show path of selected file you can try this
on html :
<div class="fileinputs">
<input type="file" class="file">
</div>
and in javascript :
var fakeFileUpload = document.createElement('div');
fakeFileUpload.className = 'fakefile';
var image = document.createElement('div');
image.className='fakebtn';
image.innerHTML = 'browse';
fakeFileUpload.appendChild(image);
fakeFileUpload.appendChild(document.createElement('input'));
var x = document.getElementsByTagName('input');
for (var i=0;i<x.length;i++) {
if (x[i].type != 'file') continue;
if (x[i].parentNode.className != 'fileinputs') continue;
x[i].className = 'file hidden';
var clone = fakeFileUpload.cloneNode(true);
x[i].parentNode.appendChild(clone);
x[i].relatedElement = clone.getElementsByTagName('input')[0];
x[i].onchange = x[i].onmouseout = function () {
this.relatedElement.value = this.value;
}
}
and style :
div.fileinputs {
position: relative;
height: 30px;
width: 370px;
}
input.file.hidden {
position: relative;
text-align: right;
-moz-opacity: 0;
filter: alpha(opacity: 0);
opacity: 0;
z-index: 2;
}
div.fakefile {
position: absolute;
top: 0px;
left: 0px;
right: 0;
width: 370px;
padding: 0;
margin: 0;
z-index: 1;
line-height: 90%;
}
div.fakefile input {
margin-bottom: 5px;
margin-left: 0;
border: none;
box-shadow: 0px 0px 2px 1px #ccc;
padding: 4px;
width: 241px;
height: 20px;
}
div.fakefile .fakebtn{
width: 150px;
background: #eb5a41;
z-index: 10;
font-family: roya-bold;
border: none;
padding: 5px 15px;
font-size: 18px;
text-align: center;
cursor: pointer;
-webkit-transition: all 0.4s ease;
-moz-transition: all 0.4s ease;
-o-transition: all 0.4s ease;
-ms-transition: all 0.4s ease;
transition: all 0.4s ease;
display: inline;
margin-left: 3px;
}
div.fileinputs input[type="file"]:hover + div .fakebtn{
background: #DA472E;
}
div.fileinputs input[type="file"] {
opacity: 0;
position: absolute;
top: -6px;
right: 0px;
z-index: 20;
width: 102px;
height: 40px;
cursor: pointer;
}
Here is one way which I like because it makes the input fill out the whole container. The trick is the "font-size: 100px", and it need to go with the "overflow: hidden" and the relative position.
<div id="upload-file-container" >
<input type="file" />
</div>
#upload-file-container {
width: 200px;
height: 50px;
position: relative;
border: dashed 1px black;
overflow: hidden;
}
#upload-file-container input[type="file"]
{
margin: 0;
opacity: 0;
font-size: 100px;
}
I went for this option which clarifies how to fully customize the browse button by including an handler of the uploaded file name, also customized.
It adds additional fields and client-side controls on them just to show how to include the browse in a "real" form, not just a standalone.
Here's the codepen: http://codepen.io/emiemi/pen/zxNXWR
JS:
//click on our custom btn triggers a click on the hidden actual file input
$("#btnup").click(function(){
$("#fileup").click();
});
//changes on the three fields (input, tit,and name) trigger a control which checks if the 3 fields are all filled and if file field is valid (an image is uploaded)
$('#fileup').change(function(){
var formDOMObj = document.upload;
//here we assign tu our text field #fileup the name of the selected file
var res=$('#fileup').val();
var arr = res.split("\\");
//if file is not valid we show the error icon and the red alert
if (formDOMObj.fileup.value.indexOf(".jpg") == -1 && formDOMObj.fileup.value.indexOf(".png") == -1 && formDOMObj.fileup.value.indexOf(".jpeg") == -1 && formDOMObj.fileup.value.indexOf(".bmp") == -1 && formDOMObj.fileup.value.indexOf(".JPG") == -1 && formDOMObj.fileup.value.indexOf(".PNG") == -1 && formDOMObj.fileup.value.indexOf(".JPEG") == -1 && formDOMObj.fileup.value.indexOf(".BMP") == -1){
$( ".imgupload" ).hide("slow");
$( ".imguploadok" ).hide("slow");
$( ".imguploadstop" ).show("slow");
$('#nomefile').css({"color":"red","font-weight":700});
$('#nomefile').html("The file "+arr.slice(-1)[0]+" is not an image!");
$( "#bottone" ).hide();
$( "#fakebtn" ).show();
}else{
//if file is valid we show the green alert
$( ".imgupload" ).hide("slow");
$( ".imguploadstop" ).hide("slow");
$( ".imguploadok" ).show("slow");
$('#nomefile').html(arr.slice(-1)[0]);
$('#nomefile').css({"color":"green","font-weight":700});
if (formDOMObj.nome.value!=""&&formDOMObj.tit.value!=""&&formDOMObj.fileup.value!=""){
//if all three fields are valid the fake input btn is hidden and the actual one i s finally hown
$( "#fakebtn" ).hide();
$( "#bottone" ).show();
}
}
});
$('#nome').change(function(){
//same as file change but on name field
var formDOMObj = document.upload;
if (formDOMObj.nome.value!=""&&formDOMObj.tit.value!=""&&formDOMObj.fileup.value!=""){
$( "#fakebtn" ).hide();
$( "#bottone" ).show();
}else{
$( "#bottone" ).hide();
$( "#fakebtn" ).show();
}
});
$('#tit').change(function(){
//same as file change but on tit field
var formDOMObj = document.upload;
if (formDOMObj.nome.value!=""&&formDOMObj.tit.value!=""&&formDOMObj.fileup.value!=""){
$( "#fakebtn" ).hide();
$( "#bottone" ).show();
}else{
$( "#bottone" ).hide();
$( "#fakebtn" ).show();
}
});
HTML:
<form name="upload" method="post" action="/" enctype="multipart/form-data" accept-charset="utf-8">
<div class="row">
<div class="col-md-6 center">
<!--this is the actual file input, s hidden beacause we wanna use our custom one-->
<input type="file" value="" class="hidden" name="fileup" id="fileup">
<div class="btn-container">
<!--the three icons: default, ok file (img), error file (not an img)-->
<h1 class="imgupload"><i class="fa fa-file-image-o"></i></h1>
<h1 class="imguploadok"><i class="fa fa-check"></i></h1>
<h1 class="imguploadstop"><i class="fa fa-times"></i></h1>
<!--this field changes dinamically displaying the filename we are trying to upload-->
<p id="nomefile">Only pics allowed! (jpg,jpeg,bmp,png)</p>
<!--our custom btn which triggers the actual hidden one-->
<button type="button" id="btnup" class="btn btn-primary btn-lg">Browse for your pic!</button>
</div>
</div>
<!--additional fields-->
<div class="col-md-6">
<div class="row">
<div class="form-group" id="top">
<div class="col-md-12">
<input type="text" maxlength="100" class="form-control" name="nome" id="nome" placeholder="Your Name">
</div>
</div>
</div>
<div class="row">
<div class="form-group">
<div class="col-md-12">
<input type="text" maxlength="50" class="form-control" name="tit" id="tit" placeholder="I am rubber, you are glue">
</div>
</div>
</div>
<div class="row">
<div class="col-md-8">
<p class="white">All fields are mandatory</p>
</div>
<div class="col-md-4">
<!--the defauld disabled btn and the actual one shown only if the three fields are valid-->
<input type="submit" value="Submit!" class="btn btn-primary" id="bottone" style="padding-left:50px; padding-right:50px; display:none;">
<button type="button" class="btn btn-default" disabled="disabled" id="fakebtn" style="padding-left:40px; padding-right:40px;">Submit! <i class="fa fa-minus-circle"></i></button>
</div>
</div>
</div>
</div>
$(document).ready(function () {
$(document).mousemove(function () {
$('#myList').css('display', 'block');
$("#seebtn").css('display', 'none');
$("#hidebtn").css('display', 'none');
$('#displayFileNames').html('');
$("#myList").html('');
var fileArray1 = document.getElementsByClassName('file-input');
for (var i = 0; i < fileArray1.length; i++) {
var files = fileArray1[i].files;
for (var j = 0; j < files.length; j++) {
$("#myList").append("<li style='color:black'>" + files[j].name + "</li>");
}
};
if (($("#myList").html()) != '') {
$('#unselect').css('display', 'block');
$('#divforfile').css('color', 'green');
$('#attach').css('color', 'green');
$('#displayFileNames').html($("#myList").children().length + ' ' + 'files selezionato');
};
if (($("#myList").html()) == '') {
$('#divforfile').css('color', 'black');
$('#attach').css('color', 'black');
$('#displayFileNames').append('Nessun File Selezionato');
};
});
});
function choosefiles(obj) {
$(obj).hide();
$('#myList').css('display', 'none');
$('#hidebtn').css('display', 'none');
$("#seebtn").css('display', 'none');
$('#unselect').css('display', 'none');
$("#upload-form").append("<input class='file-input inputs' type='file' onclick='choosefiles(this)' name='file[]' multiple='multiple' />");
$('#displayFileNames').html('');
}
$(document).ready(function () {
$('#unselect').click(function () {
$('#hidebtn').css('display', 'none');
$("#seebtn").css('display', 'none');
$('#displayFileNames').html('');
$("#myList").html('');
$('#myFileInput').val('');
document.getElementById('upload-form').reset();
$('#unselect').css('display', 'none');
$('#divforfile').css('color', 'black');
$('#attach').css('color', 'black');
});
});
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
.divs {
position: absolute;
display: inline-block;
background-color: #fff;
}
.inputs {
position: absolute;
left: 0px;
height: 2%;
width: 15%;
opacity: 0;
background: #00f;
z-index: 100;
}
.icons {
position: absolute;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<form id='upload-form' action='' method='post' enctype='multipart/form-data'>
<div class="divs" id="divforfile" style="color:black">
<input id='myFileInput' class='file-input inputs' type='file' name='file[]' onclick="choosefiles(this)" multiple='multiple' />
<i class="material-icons" id="attach" style="font-size:21px;color:black">attach_file</i><label>Allegati</label>
</div>
</form>
<br />
</div>
<br />
<div>
<button style="border:none; background-color:white; color:black; display:none" id="seebtn"><p>Files ▼</p></button>
<button style="border:none; background-color:white; color:black; display:none" id="hidebtn"><p>Files ▲</p></button>
<button type="button" class="close" aria-label="Close" id="unselect" style="display:none;float:left">
<span style="color:red">×</span>
</button>
<div id="displayFileNames">
</div>
<ul id="myList"></ul>
</div>
This is my fully functional customerized file upload/Attachment using jquery & javascript (Visual studio). This will be useful !
Code will be available at the comment section !
Link : https://youtu.be/It38OzMAeig
Enjoy :)
$(document).ready(function () {
$(document).mousemove(function () {
$('#myList').css('display', 'block');
$("#seebtn").css('display', 'none');
$("#hidebtn").css('display', 'none');
$('#displayFileNames').html('');
$("#myList").html('');
var fileArray1 = document.getElementsByClassName('file-input');
for (var i = 0; i < fileArray1.length; i++) {
var files = fileArray1[i].files;
for (var j = 0; j < files.length; j++) {
$("#myList").append("<li style='color:black'>" + files[j].name + "</li>");
}
};
if (($("#myList").html()) != '') {
$('#unselect').css('display', 'block');
$('#divforfile').css('color', 'green');
$('#attach').css('color', 'green');
$('#displayFileNames').html($("#myList").children().length + ' ' + 'files selezionato');
};
if (($("#myList").html()) == '') {
$('#divforfile').css('color', 'black');
$('#attach').css('color', 'black');
$('#displayFileNames').append('Nessun File Selezionato');
};
});
});
function choosefiles(obj) {
$(obj).hide();
$('#myList').css('display', 'none');
$('#hidebtn').css('display', 'none');
$("#seebtn").css('display', 'none');
$('#unselect').css('display', 'none');
$("#upload-form").append("<input class='file-input inputs' type='file' onclick='choosefiles(this)' name='file[]' multiple='multiple' />");
$('#displayFileNames').html('');
}
$(document).ready(function () {
$('#unselect').click(function () {
$('#hidebtn').css('display', 'none');
$("#seebtn").css('display', 'none');
$('#displayFileNames').html('');
$("#myList").html('');
$('#myFileInput').val('');
document.getElementById('upload-form').reset();
$('#unselect').css('display', 'none');
$('#divforfile').css('color', 'black');
$('#attach').css('color', 'black');
});
});
<style>
.divs {
position: absolute;
display: inline-block;
background-color: #fff;
}
.inputs {
position: absolute;
left: 0px;
height: 2%;
width: 15%;
opacity: 0;
background: #00f;
z-index: 100;
}
.icons {
position: absolute;
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<div>
<form id='upload-form' action='' method='post' enctype='multipart/form-data'>
<div class="divs" id="divforfile" style="color:black">
<input id='myFileInput' class='file-input inputs' type='file' name='file[]' onclick="choosefiles(this)" multiple='multiple' />
<i class="material-icons" id="attach" style="font-size:21px;color:black">attach_file</i><label>Allegati</label>
</div>
</form>
<br />
</div>
<br />
<div>
<button style="border:none; background-color:white; color:black; display:none" id="seebtn"><p>Files ▼</p></button>
<button style="border:none; background-color:white; color:black; display:none" id="hidebtn"><p>Files ▲</p></button>
<button type="button" class="close" aria-label="Close" id="unselect" style="display:none;float:left">
<span style="color:red">×</span>
</button>
<div id="displayFileNames">
</div>
<ul id="myList"></ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
$(document).ready(function () {
$(document).mousemove(function () {
$('#myList').css('display', 'block');
$("#seebtn").css('display', 'none');
$("#hidebtn").css('display', 'none');
$('#displayFileNames').html('');
$("#myList").html('');
var fileArray1 = document.getElementsByClassName('file-input');
for (var i = 0; i < fileArray1.length; i++) {
var files = fileArray1[i].files;
for (var j = 0; j < files.length; j++) {
$("#myList").append("<li style='color:black'>" + files[j].name + "</li>");
}
};
if (($("#myList").html()) != '') {
$('#unselect').css('display', 'block');
$('#divforfile').css('color', 'green');
$('#attach').css('color', 'green');
$('#displayFileNames').html($("#myList").children().length + ' ' + 'files selezionato');
};
if (($("#myList").html()) == '') {
$('#divforfile').css('color', 'black');
$('#attach').css('color', 'black');
$('#displayFileNames').append('Nessun File Selezionato');
};
});
});
function choosefiles(obj) {
$(obj).hide();
$('#myList').css('display', 'none');
$('#hidebtn').css('display', 'none');
$("#seebtn").css('display', 'none');
$('#unselect').css('display', 'none');
$("#upload-form").append("<input class='file-input inputs' type='file' onclick='choosefiles(this)' name='file[]' multiple='multiple' />");
$('#displayFileNames').html('');
}
$(document).ready(function () {
$('#unselect').click(function () {
$('#hidebtn').css('display', 'none');
$("#seebtn").css('display', 'none');
$('#displayFileNames').html('');
$("#myList").html('');
$('#myFileInput').val('');
document.getElementById('upload-form').reset();
$('#unselect').css('display', 'none');
$('#divforfile').css('color', 'black');
$('#attach').css('color', 'black');
});
});
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
.divs {
position: absolute;
display: inline-block;
background-color: #fff;
}
.inputs {
position: absolute;
left: 0px;
height: 2%;
width: 15%;
opacity: 0;
background: #00f;
z-index: 100;
}
.icons {
position: absolute;
}
</style>
<div>
<form id='upload-form' action='' method='post' enctype='multipart/form-data'>
<div class="divs" id="divforfile" style="color:black">
<input id='myFileInput' class='file-input inputs' type='file' name='file[]' onclick="choosefiles(this)" multiple='multiple' />
<i class="material-icons" id="attach" style="font-size:21px;color:black">attach_file</i><label>Allegati</label>
</div>
</form>
<br />
</div>
<br />
<div>
<button style="border:none; background-color:white; color:black; display:none" id="seebtn"><p>Files ▼</p></button>
<button style="border:none; background-color:white; color:black; display:none" id="hidebtn"><p>Files ▲</p></button>
<button type="button" class="close" aria-label="Close" id="unselect" style="display:none;float:left">
<span style="color:red">×</span>
</button>
<div id="displayFileNames">
</div>
<ul id="myList"></ul>
</div>
You can style them, but you can't remove the elements that are already there. If you're creative, you can work with that and do something like this:
input[type=file] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: #EEE;
background: linear-gradient(to top, #FFF, #DDD);
border: thin solid rgba(0,0,0, .5);
border-radius: .25em;
box-shadow: inset .25em .25em .25em rgba(255,255,255, .5), inset -.1em -.1em .1em rgba(0,0,0, 0.1);
cursor: text;
padding: .25em;
}
http://jsfiddle.net/zr1x1m2b/1/
I suggest you play around with this code, remove lines, add your own, do whatever until you get something that looks how you like!
Just style a normal button however you want, using your favorite CSS.
Then call a simple JS function to create and link a hidden input element to your styled button. Don't add browser-specific CSS to do the hiding part.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
button {
width : 160px;
height : 30px;
font-size : 13px;
border : none;
text-align : center;
background-color : #444;
color : #6f0;
}
button:active {
background-color : #779;
}
</style>
<button id="upload">Styled upload button!</button>
<script>
function Upload_On_Click(id, handler) {
var hidden_input = null;
document.getElementById(id).onclick = function() {hidden_input.click();}
function setup_hidden_input() {
hidden_input && hidden_input.parentNode.removeChild(hidden_input);
hidden_input = document.createElement("input");
hidden_input.setAttribute("type", "file");
hidden_input.style.visibility = "hidden";
document.querySelector("body").appendChild(hidden_input);
hidden_input.onchange = function() {
handler(hidden_input.files[0]);
setup_hidden_input();
};
}
setup_hidden_input();
}
Upload_On_Click("upload", function(file) {
console.log("GOT FILE: " + file.name);
});
</script>
Notice how the above code re-links it after every time the user chooses a file. This is important because "onchange" is only called if the user changes the filename. But you probably want to get the file every time the user provides it.
For more details, research DropZone and gmail uploads.
Here is one way I recently discovered, with a bit of jQuery
HTML Code:
<form action="">
<input type="file" name="file_upload" style="display:none" id="myFile">
<a onclick="fileUpload()"> Upload a file </a>
</form>
For the javascript/jQuery part :
<script>
function fileUpload() {
$("#myFile").click();
}
</script>
In this example, I have put an "anchor" tag to trigger the file upload. You can replace with anything you want, just remember to put the "onclick" attribute with the proper function.
Hope this helps!
P.S. : Do not forget to include jQuery from CDN or any other source