Huge Google Maps Controls (Possible Bug?) - css

I first noticed that my Google Maps Controls were disproportionally large on my own web app (seen below).
Initially I thought some of my CSS was playing with Google's CSS on the controls; however, visiting Google's own webpage told me this incident was not isolated to me...
Below is a map on their documentation: https://developers.google.com/maps/documentation/javascript/examples/control-positioning
The large controls appear on every page of their documentation for me as well. I tried different machines and different browsers (Chrome and Firefox).
I also tried other sites that used the Google Maps API and saw a similar phenomenon in some cases.
Is anyone else experiencing the same issues?

Looks like google have now acknowledged this and have provided a (currently un-documented) feature to change the UI scaling by passing in a "controlSize" when creating the map.
See comment from Google here.
JSFiddle here (from comment above).
Sample code:
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8,
controlSize: 32,
});
}
Note: 40 is the default currently (and corresponds to the large controls that this question is about). I've found 25 to be about the same as the previous controls.
Update:
As of v3.36 this is a documented feature, see here

Turns out this isn't a bug. See more here:
Aug 13, 2018 03:56PM Reported Issue Google Maps JavaScript API weekly
channel (3.34) will be using the larger control UI.
As we are seeing increases of touch operations on various devices, we
adjusted the control UI to fit for both finger touches and mouse
clicks.
It's possible to opt out of this by loading the API with v=quarterly,
v=3, v=3.33 or v=3.32. Note: requests to retired version will receive
the default channel, see 1.
If you have any requests or other issues concerning the new control UI
please let us know.
1 https://issuetracker.google.com/112519576
Use v=quarterly, v=3, v=3.33 or v=3.32 when loading the API to use smaller controls.
EDIT:
Refer to answer from #Jonny van Beek on how to scale Google map's controls to the size of your choosing.
Refer to answers from #garethdn and #Peter (below) to find out how to replace Google's large controls with your own custom controls.
Refer to #Dutchmanjonny's post (below) for latest and correct solution to this problem.

For those that are reluctant to opt out by specifying older versions of the API, creating custom controls is relatively straight forward. The following will create two button elements to zoom in and out.
defaultMapOptions: google.maps.MapOptions = {
// Hide Google's default zoom controls
zoomControl: false
};
initializeMap(el: HTMLElement, options?: google.maps.MapOptions): google.maps.Map {
let opts = Object.assign({}, this.defaultMapOptions, options);
let map = new google.maps.Map(el, opts);
let zoomControlsDiv = document.createElement('div');
// Add a class to the container to allow you to refine the position of the zoom controls
zoomControlsDiv.classList.add('google-map-custom-zoom-controls');
this.createCustomZoomControls(zoomControlsDiv, map);
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(zoomControlsDiv);
return map;
}
createCustomZoomControls(controlDiv: HTMLDivElement, map: google.maps.Map) {
let zoomInControlUI: HTMLButtonElement = document.createElement('button');
let zoomOutControlUI: HTMLButtonElement = document.createElement('button');
let zoomControls: HTMLButtonElement[] = [zoomInControlUI, zoomOutControlUI];
// List of classes to be applied to each zoom control
let buttonClasses: string[] = ['btn', 'btn-primary', 'btn-sm'];
zoomInControlUI.innerHTML = `+`;
zoomOutControlUI.innerHTML = `−`;
zoomControls.forEach(zc => {
zc.classList.add(...buttonClasses);
controlDiv.appendChild(zc);
});
google.maps.event.addDomListener(zoomInControlUI, 'click', () => map.setZoom(map.getZoom() + 1));
google.maps.event.addDomListener(zoomOutControlUI, 'click', () => map.setZoom(map.getZoom() - 1));
}
let map = this.initializeMap(myGoogleMapContainerElement);

After the backlash, Google has now published an example for how to replace the default (big) controls: https://developers.google.com/maps/documentation/javascript/examples/control-replacement
Here is the code as published by Google:
<!DOCTYPE html>
<html>
<head>
<title>Replacing Default Controls</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
.gm-style .controls {
font-size: 28px; /* this adjusts the size of all the controls */
background-color: white;
box-shadow: rgba(0, 0, 0, 0.3) 0px 1px 4px -1px;
box-sizing: border-box;
border-radius: 2px;
cursor: pointer;
font-weight: 300;
height: 1em;
margin: 6px;
text-align: center;
user-select: none;
padding: 2px;
width: 1em;
}
.gm-style .controls button {
border: 0;
background-color: white;
color: rgba(0, 0, 0, 0.6);
}
.gm-style .controls button:hover {
color: rgba(0, 0, 0, 0.9);
}
.gm-style .controls.zoom-control {
display: flex;
flex-direction: column;
height: auto;
}
.gm-style .controls.zoom-control button {
font: 0.85em Arial;
margin: 1px;
padding: 0;
}
.gm-style .controls.maptype-control {
display: flex;
flex-direction: row;
width: auto;
}
.gm-style .controls.maptype-control button {
display: inline-block;
font-size: 0.5em;
margin: 0 1px;
padding: 0 6px;
}
.gm-style .controls.maptype-control.maptype-control-is-map .maptype-control-map {
font-weight: 700;
}
.gm-style .controls.maptype-control.maptype-control-is-satellite .maptype-control-satellite {
font-weight: 700;
}
.gm-style .controls.fullscreen-control button {
display: block;
font-size: 1em;
height: 100%;
width: 100%
}
.gm-style .controls.fullscreen-control .fullscreen-control-icon {
border-style: solid;
height: 0.25em;
position:absolute;
width: 0.25em;
}
.gm-style .controls.fullscreen-control .fullscreen-control-icon.fullscreen- control-top-left {
border-width: 2px 0 0 2px;
left: 0.1em;
top: 0.1em;
}
.gm-style .controls.fullscreen-control.is-fullscreen .fullscreen-control-icon.fullscreen-control-top-left {
border-width: 0 2px 2px 0;
}
.gm-style .controls.fullscreen-control .fullscreen-control-icon.fullscreen-control-top-right {
border-width: 2px 2px 0 0;
right: 0.1em;
top: 0.1em;
}
.gm-style .controls.fullscreen-control.is-fullscreen .fullscreen-control-icon.fullscreen-control-top-right {
border-width: 0 0 2px 2px;
}
.gm-style .controls.fullscreen-control .fullscreen-control-icon.fullscreen-control-bottom-left {
border-width: 0 0 2px 2px;
left: 0.1em;
bottom: 0.1em;
}
.gm-style .controls.fullscreen-control.is-fullscreen .fullscreen-control-icon.fullscreen-control-bottom-left {
border-width: 2px 2px 0 0;
}
.gm-style .controls.fullscreen-control .fullscreen-control-icon.fullscreen-control-bottom-right {
border-width: 0 2px 2px 0;
right: 0.1em;
bottom: 0.1em;
}
.gm-style .controls.fullscreen-control.is-fullscreen .fullscreen-control-icon.fullscreen-control-bottom-right {
border-width: 2px 0 0 2px;
}
</style>
</head>
<body>
<div id="map"></div>
<!-- Hide controls until they are moved into the map. -->
<div style="display:none">
<div class="controls zoom-control">
<button class="zoom-control-in" title="Zoom In">+</button>
<button class="zoom-control-out" title="Zoom Out">−</button>
</div>
<div class="controls maptype-control maptype-control-is-map">
<button class="maptype-control-map"
title="Show road map">Map</button>
<button class="maptype-control-satellite"
title="Show satellite imagery">Satellite</button>
</div>
<div class="controls fullscreen-control">
<button title="Toggle Fullscreen">
<div class="fullscreen-control-icon fullscreen-control-top-left"></div>
<div class="fullscreen-control-icon fullscreen-control-top-right"></div>
<div class="fullscreen-control-icon fullscreen-control-bottom-left"></div>
<div class="fullscreen-control-icon fullscreen-control-bottom-right"></div>
</button>
</div>
</div>
<script>
var map;
function initMap() {
map = new google.maps.Map(document.querySelector('#map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8,
disableDefaultUI: true,
});
initZoomControl(map);
initMapTypeControl(map);
initFullscreenControl(map);
}
function initZoomControl(map) {
document.querySelector('.zoom-control-in').onclick = function() {
map.setZoom(map.getZoom() + 1);
};
document.querySelector('.zoom-control-out').onclick = function() {
map.setZoom(map.getZoom() - 1);
};
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(
document.querySelector('.zoom-control'));
}
function initMapTypeControl(map) {
var mapTypeControlDiv = document.querySelector('.maptype-control');
document.querySelector('.maptype-control-map').onclick = function() {
mapTypeControlDiv.classList.add('maptype-control-is-map');
mapTypeControlDiv.classList.remove('maptype-control-is-satellite');
map.setMapTypeId('roadmap');
};
document.querySelector('.maptype-control-satellite').onclick =
function() {
mapTypeControlDiv.classList.remove('maptype-control-is-map');
mapTypeControlDiv.classList.add('maptype-control-is-satellite');
map.setMapTypeId('hybrid');
};
map.controls[google.maps.ControlPosition.LEFT_TOP].push(
mapTypeControlDiv);
}
function initFullscreenControl(map) {
var elementToSendFullscreen = map.getDiv().firstChild;
var fullscreenControl = document.querySelector('.fullscreen-control');
map.controls[google.maps.ControlPosition.RIGHT_TOP].push(
fullscreenControl);
fullscreenControl.onclick = function() {
if (isFullscreen(elementToSendFullscreen)) {
exitFullscreen();
} else {
requestFullscreen(elementToSendFullscreen);
}
};
document.onwebkitfullscreenchange =
document.onmsfullscreenchange =
document.onmozfullscreenchange =
document.onfullscreenchange = function() {
if (isFullscreen(elementToSendFullscreen)) {
fullscreenControl.classList.add('is-fullscreen');
} else {
fullscreenControl.classList.remove('is-fullscreen');
}
};
}
function isFullscreen(element) {
return (document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement) == element;
}
function requestFullscreen(element) {
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.webkitRequestFullScreen) {
element.webkitRequestFullScreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.msRequestFullScreen) {
element.msRequestFullScreen();
}
}
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msCancelFullScreen) {
document.msCancelFullScreen();
}
}
</script>
<script src="https://maps.googleapis.com/maps/api/js? key=YOUR_API_KEY&callback=initMap"
async defer></script>
</body>
</html>

Here is what did it for me:
.gm-bundled-control
,.gm-style-mtc
,.gm-fullscreen-control{
transform: scale(.7);
}
Makes the controls 30% smaller.

I added some css and that's it.
/* Fix +/- zoom buttons design */
#map .gm-bundled-control-on-bottom {
right: 30px !important;
bottom: 116px !important;
}
#map .gm-bundled-control-on-bottom > div:first-child {
top: 44px !important;
}
#map .gmnoprint > .gmnoprint > div {
height: 60px !important;
width: 30px !important;
}
#map .gmnoprint > .gmnoprint > div > div { /* seperator */
width: 22.5px !important;
margin: 0px 3.75px !important;
}
#map .gmnoprint > .gmnoprint button {
width: 30px !important;
height: 30px !important;
}
#map .gmnoprint > .gmnoprint button img {
height: 13.5px !important;
width: 13.5px !important;
margin: 6.75px 8.25px 9.75px !important;
}
and this is for the yellow man button:
/* yellow person button design*/
#map .gm-svpc {
width: 30px !important;
height: 30px !important;
}
#map .gm-svpc img:nth-child(1), #map .gm-svpc img:nth-child(2){
width: 13.5px !important;
height: 22.5px !important;
left: -7px !important;
top: -12px !important;
}
#map .gm-svpc img:nth-child(3) {
width: 24px !important;
height: 30px !important;
}
and for last the MAP|Satellite buttons design
/* MAP|Satellite buttons design*/
#map .gm-style-mtc > div:nth-child(1) {
padding: 0px 9px !important;
height: 30px !important;
font-size: 15px !important;
}
#map .gm-style-mtc > div:nth-child(2) {
top: 30px !important;
}
#map .gm-style-mtc > div:nth-child(2) > div {
padding: 2px 4px 2px 2px !important;
font-size: 14px !important;
}

Related

How to make external events box dynamically extended and hollow circles aligned

This is what I'm trying to achieve
<pre>
CONTAINER External Events Box Shrink or Enlarge
<-------------------------------------------------------------------------------------------->
| Text LEFT(ED) internal CONTAINER |
| -------------- -------------------------------------------------- -------------- |
| | Info li | |Content li | | Info li | |
| | wrapped into | |shrink or enlarge to contents OR | | wrapped into | |
| | hollow circle1| |max size: (External container width - 2X(info li)| | hollow circle2| |
| -------------- |--------------------------------------------------- --------------- |
---------------------------------------------------------------------------------------------
</pre>
1- Hollow circles on the right side sould be all aligned (See picture)
2- Hollow circles on the left side sould be all aligned (See picture)
3- Extend(Enlarge or Schrink) dynamically the external
events box to wrap externally the hollow circles(One on the left + the
second on the right + Text container(holding the description name lines).
N.B:
If the first name line in bold reach the red Line
(see the following picture) it must not continue
on a second line( means the first line should be
always an inline bold block) and hence push
forward to extend the gray container.
If the second line written in smaller caracters reach the red Line
(see the following picture) it must break down into a thirth line fourth and
so on until it complets.
(each tuple(hollowCircle1,nameLines,hollowCircle2) is enclosed in its own
wrapper ul.
<body ng-controller="MainCtrl">
<div id='external-events'>
<h4 >Draggable books</h4>
<li style="display: inline;margin: 0;padding: 0;border: none;list-style-type: none;" ng-repeat="book in books track by $index"
id="book.id">
<ul style="margin: 0;padding: 0;border: none;list-style-type: none; display: flex;" class="fc-event" data-drag="true" data-jqyoui-options="{revert: 'invalid'}" jqyoui-draggable="{index {{$index}},placeholder:true,animate:true}">
<li style="margin: 0;padding: 0;border: none;list-style-type: none; display: inline;" class="circle" >
0</li><br><br><br><br>
<li style="margin: 0;padding: 0;border: none;list-style-type: none; display: inline;" ng-bind-html="book.content['name']"</li>
<li style="margin: 0;padding: 0;border: none;list-style-type: none; display: inline;" class="circle" >
2/10<br></li>
</ul>
</li>
</div>
<div id='calendar-container'>
<div id='calendar'></div>
</div>
</body>
CSS
ul {
list-style-type: none;}
ul.columns>li {
display: inline-block;
padding-right: 0cm;
margin-left: 0px;
}
ul.columns>li:before {
content:"";
display: list-item;
position: absolute;
}
h4 {
color: white;
display: inline;
border-bottom: 3px solid darken($fendersblue, 10);
padding-bottom: 8px;
line-height: 1.75em;
}
.fancy3 {
background-color: darken($fendersblue, 5);
}
#calendar
{
padding: 0 10px;
width: 650px;
float: right;
margin: 0px 0px 10px 55px;
}
#external-events {
width: 500px;
padding: 0 0px;
border: 0px solid #ccc;/* gray moyen*/
background: #eee;/* #5D6D7E;(Blue mat) */ /* #eee color gray*/
text-align: left;
}
#external-events h4 {
font-size: 30px;
margin-top: 0;
padding-top: 1em;
color:gray;
}
#external-events .fc-event {
cursor: pointer;
position:relative;
z-index: 100;
background: #eee;
}
#external-events p {
margin: 0 18em 0 0;
font-size: 14px;
font-weight: bold;
color: gray; /* color gray */
}
.circle {
position: relative;
display: inline-block;
width: 10%;
height: 25%;
padding: 0 0px;
border-radius: 360px;
/* Just making it pretty */
#shadow: rgba(0, 0, 0, .1);
#shadow-length: 4px;
-webkit-box-shadow: 0 #shadow-length 0 0 #shadow;
box-shadow: 0 #shadow-length 0 0 #shadow;
text-shadow: 0 #shadow-length 0 #shadow;
background: #FFFFFF;/*color white*/
color: #f05907;/* color red*/
font-family: Helvetica, Arial Black, sans;
font-size: 10;
text-align: center;
}
p span
{
display: block;
}
p:first-line {
color: gray;
font-size: 25px;
font-weight: bold italic;
}
p {
white-space: pre
}
Css is included in my CodePen
Many Thanks.
The content of your CodePen was a bit of a mess of invalid HTML, illogical use of markup, conflicting styles and seemingly arbitrary (and confusing) mixture of inline styles and CSS definitions.
There was too much to go into specifics. However, here is a version which gets you much closer to the layout you envisaged, I hope:
HTML:
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<script data-require="angular.js#1.0.x" src="https://code.angularjs.org/1.2.8/angular.min.js" data-semver="1.0.7"></script>
</head>
<body ng-controller="MainCtrl">
<div id='external-events'>
<h4 >Draggable books</h4>
<ul data-drag="true" data-jqyoui-options="{revert: 'invalid'}" jqyoui-draggable="{index {{$index}},placeholder:true,animate:true}">
<li class="fc-event" ng-repeat="book in books track by $index"
id="book.id">
<div class="circle">0</div>
<div class="left content" ng-bind-html="book.content['name']"></div>
<div class="left rating">2/10</div>
<div class="clear"></div>
</li>
</ul>
</div>
<div id='calendar-container'>
<div id='calendar'></div>
</div>
</body>
</html>
CSS:
ul {
list-style-type: none;
}
ul>li {
display:block;
padding-right: 0cm;
margin-left: 0px;
}
h4 {
color: gray;
display: inline;
border-bottom: 3px solid darken($fendersblue, 10);
padding-bottom: 8px;
font-size:600;
}
#calendar{
padding: 0 10px;
width: 650px;
float: right;
margin: 0px 0px 10px 55px;
}
#external-events {
width: 500px;
padding: 0 0px;
border: 0px solid #ccc;/* gray moyen*/
background: #eee;/* #5D6D7E;(Blue mat) */ /* #eee color gray*/
text-align: left;
}
#external-events .fc-event {
cursor: pointer;
z-index: 100;
background: #eee;
border: solid 1px black;
border-radius: 2px;
margin-bottom:5px;
}
.content span
{
color: gray;
}
.fc-event span:first-child
{
font-size: 25px;
font-weight: bold italic;
}
.fc-event div
{
padding:3px;
margin-right:5px;
height: 100%;
}
.content
{
float:left;
max-width:75%;
}
.clear
{
clear:both;
}
.circle {
float:left;
width: 10%;
height: 25%;
padding: 0 10px;
border-radius: 360px;
/* Just making it pretty */
#shadow: rgba(0, 0, 0, .1);
#shadow-length: 4px;
-webkit-box-shadow: 0 #shadow-length 0 0 #shadow;
box-shadow: 0 #shadow-length 0 0 #shadow;
text-shadow: 0 #shadow-length 0 #shadow;
background: #FFFFFF;/*color white*/
color: #f05907;/* color red*/
font-family: Helvetica, Arial Black, sans;
font-size: 10;
text-align: center;
}
.rating
{
float:right;
background: #FFFFFF;/*color white*/
color: #f05907;/* color red*/
font-family: Helvetica, Arial Black, sans;
font-size: 10;
text-align: center;
border-radius: 360px;
}
JS:
var app = angular.module("app", []);
app.controller("MainCtrl", ['$scope', '$sce', function($scope, $sce){
$scope.books = [
{
id: 'id1',
content: {
name: '<span>Alain du sceau france</span><br><span> Canada Madagascar philipine</span>',
price: 'price1',
date: 'd1'
}
},
{
id: 'id2',
content: {
name: '<span>Name zu Long zu Schreiben Bis Here ist Ein Beispiel</span><br><span>Maneschester Canada Madagascar philipine</span>',
price: 'price2',
date: 'd2'
}
},
{
id: 'id3',
content: {
name: '<span>name Aleatoire Schwer und zu Leicht Zu Schreiben</span><br><span>Mexico Canada USA France Uk Deutschland Schweiz Madagascar philipine</span>',
price: 'price3',
date: 'd3'
}
}
];
$scope.books.forEach(function(book) {
book.content.name = $sce.trustAsHtml(book.content.name);
})
// initialize the external events
// -----------------------------------------------------------------
$('#external-events .fc-event').each(function() {
// store data so the calendar knows to render an event upon drop
$(this).data('event', {
title: $.trim($(this).text()), // use the element's text as the event title
stick: true // maintain when user navigates (see docs on the renderEvent method)
});
// make the event draggable using jQuery UI
$(this).draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
});
// initialize the calendar
// -----------------------------------------------------------------
$('#calendar').fullCalendar({
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
editable: true,
droppable: true, // this allows things to be dropped onto the calendar
drop: function() {
// is the "remove after drop" checkbox checked?
if ($('#drop-remove').is(':checked')) {
// if so, remove the element from the "Draggable Events" list
$(this).remove();
}
},
eventDragStop: function(event, jsEvent, ui, view ) {
if(isEventOverDiv(jsEvent.clientX, jsEvent.clientY)) {
//////////
$('#calendar').fullCalendar('removeEvents', event._id);
var el = $( "<div class='fc-event'>" ).appendTo('#external- events').text(event.id);
}
}
});
var isEventOverDiv = function(x, y) {
var external_events = $( '#external-events' );
var offset = external_events.offset();
offset.right = external_events.width() + offset.left;
offset.bottom = external_events.height() + offset.top;
// Compare
if (x >= offset.left
&& y >= offset.top
&& x <= offset.right
&& y <= offset .bottom) { return true; }
return false;
}
}]);
CodePen demo: https://codepen.io/anon/pen/JwQOMQ?editors=1111

Progress bar when upload file in contact form 7 in wordpress error

I found this fantastic piece of code for enabling progress bar during uploading files in Contact Form 7 plugin for Wordpress. Original source: HERE
<script type="text/javascript">
jQuery(document).ready(function(){
var dropbox;
dropbox = document.getElementById("dropbox");
dropbox.addEventListener("dragenter", dragenter, false);
dropbox.addEventListener("dragleave", dragleave, false);
dropbox.addEventListener("dragover", dragover, false);
dropbox.addEventListener("drop", drop, false);
function defaults(e){
e.stopPropagation();
e.preventDefault();
}
function dragenter(e) {
jQuery(this).addClass("active");
defaults(e);
}
function dragover(e) {
defaults(e);
}
function dragleave(e) {
jQuery(this).removeClass("active");
defaults(e);
}
function drop(e) {
jQuery(this).removeClass("active");
defaults(e);
var dt = e.dataTransfer;
var files = dt.files;
handleFiles(files,e);
}
jQuery(document).on('change', '#fileElem', function(){
handleFiles(this.files)});
handleFiles = function (files,e){
var imageType = /image.*/;
var file = files[0];
var info = '<div class="preview active-win"><div class="preview-image"><img ></div><div class="progress-holder"><span id="progress"></span></div><span class="percents"></span><div style="float:left;">Uploaded <span class="up-done"></span> KB of '+parseInt(file.size / 1024)+' KB</div>';
jQuery(".upload-progress").show("fast",function(){
jQuery(".upload-progress").html(info);
uploadFile(file);
});
}
uploadFile = function(file){
// check if browser supports file reader object
if (typeof FileReader !== "undefined"){
//alert("uploading "+file.name);
reader = new FileReader();
reader.onload = function(e){
//alert(e.target.result);
jQuery('.preview img').attr('src',e.target.result).css("width","70px").css("height","70px");
}
reader.readAsDataURL(file);
xhr = new XMLHttpRequest();
xhr.open("post", "ajax_fileupload.php", true);
xhr.upload.addEventListener("progress", function (event) {
console.log(event);
if (event.lengthComputable) {
jQuery("#progress").css("width",(event.loaded / event.total) * 100 + "%");
jQuery(".percents").html(" "+((event.loaded / event.total) * 100).toFixed() + "%");
jQuery(".up-done").html((parseInt(event.loaded / 1024)).toFixed(0));
}
else {
alert("Failed to compute file upload length");
}
}, false);
xhr.onreadystatechange = function (oEvent) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
jQuery("#progress").css("width","100%");
jQuery(".percents").html("100%");
jQuery(".up-done").html((parseInt(file.size / 1024)).toFixed(0));
jQuery(".upload-progress").hide();
} else {
alert("Error"+ xhr.statusText);
}
}
};
// Set headers
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.setRequestHeader("X-File-Name", file.fileName);
xhr.setRequestHeader("X-File-Size", file.fileSize);
xhr.setRequestHeader("X-File-Type", file.type);
xhr.send(file);
}else{
alert("Your browser doesnt support FileReader object");
}
}
});
</script>
<style>
.active{ background : #B4F9AC; font-size: 15px; box-shadow : 0px 0px 5px 6px #ccc; }
.progress-holder{ width: 300px; padding: 2px; background: #CCCCCC; border-radius: 3px; float: left; margin-top: 4px; margin-right: 5px; }
#progress{ height: 6px; display:block; width: 0%; border-radius: 2px; background: -moz-linear-gradient(center top , #13DD13 20%, #209340 80%) repeat scroll 0 0 transparent; /* IE hack */ background: -ms-linear-gradient(bottom, #13DD13, #209340); /* chrome hack */ background-image: -webkit-gradient(linear, 20% 20%, 20% 100%, from(#13DD13), to(#209340)); /* safari hack */ background-image: -webkit-linear-gradient(top, #13DD13, #209340); /* opera hack */ background-image: -o-linear-gradient(#13DD13,#209340); box-shadow:3px 3px 3px #888888; }
.preview{ border: 1px solid #CDCDCD; width: 450px; padding: 10px; height:auto; overflow: auto; color: #4D4D4D; float: left; box-shadow:3px 3px 3px #888888; border-radius: 2px; }
.percents{ float: right; }
.preview-image{ box-shadow: 3px 3px 3px #888888; width: 70px; height: 70px; float: left; margin-right: 10px; }
.file-info{ height: 50px; float: left; width: auto; margin-bottom: 10px; border: 1px solid blue; }
.file-info span{ margin: 3px 2px; font-size: 12px; float:left; display: block; min-width: 100px; overflow: auto; border: 1px solid red; overflow: none; }
.upload-progress{ display: none; }</style>
<div id="dropbox">[file* fileElem id:fileElem limit:5000000]</div><div class="upload-progress"></div>
It is working for me however, i have contact form with 5 files to upload and when I'm uploading one progress bar and thumbnail are shown for all of them. See screnshot HERE.
I'm not really programer nor developer so I don't have enough knowledge to "fix it" myself. I was trying to give uniqe ID for every file in CF7 form, but no luck.
Original topic is closed so I can't contact developer with my issue. Can anybody take a look into code and give some clues?
Thank you in advance

Is there a CSS way to automatically set the width of an element based on the size of text strings?

I’m creating a styled select menu in which I’m styling an unordered list that is replacing my select element.
<div class="select">
<select name="distance" id="distance" class="select-hidden">
<option value="5.0 5"><font><font>5 mi</font></font></option>
<option value="6.0 4">6 km</option>
<option value="10.0 4" selected="selected"><font><font>10 km</font></font></option></select><div class="select-styled">10 km</div><ul class="select-options" style="display: none;"><li rel="5.0 5"><font><font>5 mi</font></font></li><li rel="6.0 4"><font><font>6 km</font></font></li><li rel="10.0 4"><font><font>10 km</font></font></li></ul>
</div>
I then have this style
.select {
cursor: pointer;
display: inline-block;
position: relative;
font-size: 16px;
color: #000000;
width: 220px;
height: 42px;
}
Right now I’m hard-coding the width (220px) and my question is can I build this in a less rigid way such that the width will automatically be the width of the longest element name? Here is the Fiddle that illustrates my dilemma — https://jsfiddle.net/n73ao02h/13/ .
How about that: https://jsfiddle.net/n73ao02h/14/
A select-box without any width will always style according to its options. So we use that...
First step is to remove the fixed width.
We get the width in JS before we add display:none to it.
We then generate a temporary element styled-select with zero width to automatically get the padding defined in CSS without hardcoding it.
We then have all we need to calculate the new width of your styled select-box:
/* ... */
var $paddingCalculator = $('<div />', {
'class' : "select-styled test"
}).css({
width : 0,
visibility : "hidden"
}).appendTo("body");
var paddingWidth = $paddingCalculator.outerWidth();
$paddingCalculator.remove();
var selectWidth = $this.width() + paddingWidth;
$this.addClass('select-hidden');
if ( !$this.parent().hasClass('select') ) {
var $wrapper = $("<div />", {
'class' : "select"
}).css({
width : selectWidth
});
$this.wrap( $wrapper );
} // if
/* ... */
 
little addendum:
Keep in mind that both - the original select box and your styled div - need to have the same font-size (and anything text-styling related, such as font-family, font-weight, letter-spacing, ...) so that the calculated dimensions will be correct.
Don't set the width and don't set display:none on the select, plus set white-space:nowrap on your div.select-styled :
$(function() {
$('select').each(function(){
styleSelectMenu($(this));
});
});
// This method applies the styles to our select menu
function styleSelectMenu(selectMenu)
{
var $this = $(selectMenu), numberOfOptions = $(selectMenu).children('option').length;
$this.addClass('select-hidden');
if ( !$this.parent().hasClass('select') ) {
$this.wrap('<div class="select"></div>');
} // if
if ( !$this.next().hasClass('select-styled') ) {
$this.after('<div class="select-styled"></div>');
} // if
var $styledSelect = $this.next('div.select-styled');
$styledSelect.text($this.children('option').eq(0).text());
if ( $styledSelect.parent().find('ul').length > 0 ) {
$styledSelect.parent().find('ul').remove();
} // if
var $list = $('<ul />', {
'class': 'select-options'
}).insertAfter($styledSelect);
for (var i = 0; i < numberOfOptions; i++) {
$('<li />', {
text: $this.children('option').eq(i).text(),
rel: $this.children('option').eq(i).val()
}).appendTo($list);
}
var $listItems = $list.children('li');
// This is the event when someone opens the list
$styledSelect.unbind('click')
$styledSelect.click(function(e) {
e.stopPropagation();
$('div.select-styled.active').each(function(){
$(this).removeClass('active').next('ul.select-options').hide();
});
$(this).toggleClass('active').next('ul.select-options').toggle();
});
// This is the event when someone actually selects something from the list
$listItems.unbind('click.selectStyledItem')
$listItems.bind('click.selectStyledItem', function(event) {
clickListItem($styledSelect, $this, $(this), $list);
});
$(document).click(function() {
$styledSelect.removeClass('active');
$list.hide();
});
var selectedIndex = $this[0].selectedIndex;
if (selectedIndex > 0) {
var name = $this.attr("name")
var selectedText = $( "select[name='" + name + "'] option:selected" ).text();
selectItemFromStyledList($styledSelect, $this, selectedText, $list);
} // if
}
// This is the method that will select an item from the styled list
function selectItemFromStyledList(styledSelect, selectMenu, selectedText, listToHide)
{
$(styledSelect).text(selectedText).removeClass('active');
$(selectMenu).val($(selectMenu).attr('rel'));
$(listToHide).hide();
// Select option in the underlying list so that the form gets submitted
// with the right values
selectedOption = $(selectMenu).find("option").filter(function () { return $(this).html() == selectedText; });
$(selectMenu).find("option[selected='selected']").removeAttr("selected");
$(selectedOption).attr("selected","selected");
} // selectItemFromStyledList
// Called when someone clicks an item from the styled list
// The event data should contain the following parameters:
// styledSelect - the <div> element that contains the styled menu
// selectMenu - the actual form element that contains the items
// listItemClicked - the item that was clicked.
// list - THe <UL> element containig the <li> options
function clickListItem(styledSelect, selectMenu, listItemClicked, list)
{
var $styledSelect = $(styledSelect);
var $selectMenu = $(selectMenu);
var $listItem = $(listItemClicked);
var $list = $(list);
event.stopPropagation();
var selectedText = $listItem.text();
selectItemFromStyledList($styledSelect, $selectMenu, selectedText, $list)
} // clickListItem
#statSearchFields {
vertical-align: top;
font-size: 90%;
}
.selectMenu {
font-family: 'Oxygen', sans-serif;
font-size: 20px;
height: 50px;
-webkit-appearance: menulist-button;
}
.select-hidden {
visibility: hidden;
padding-right: 10px;
}
.select {
cursor: pointer;
display: inline-block;
position: relative;
font-size: 16px;
color: black;
height: 42px;
}
.select-styled {
white-space: nowrap;
}
.select-styled {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: gray;
padding: 11px 12px;
#include transition(all 0.2s ease-in);
&:after {
content:"";
width: 0;
height: 0;
border: 7px solid transparent;
border-color: black transparent transparent transparent;
position: absolute;
top: 16px;
right: 10px;
}
&:hover {
background-color: darken(gray, 2);
}
&:active, &.active {
background-color: darken(gray, 5);
&:after {
top: 9px;
border-color: transparent transparent $select-color transparent;
}
}
}
.select-options {
display: none;
position: absolute;
top: 100%;
right: 0;
left: 0;
z-index: 999;
margin: 0;
padding: 0;
list-style: none;
background-color: darken(gray, 5);
overflow: scroll;
li {
margin: 0;
padding: 12px 0;
text-indent: 15px;
border-top: 1px solid darken(gray, 10);
#include transition(all 0.15s ease-in);
&:hover {
color: gray;
background: black;
}
&[rel="hide"] {
display: none;
}
}
}
#statSearchContainer {
padding: 10px;
font-family: "Calibre", "Helvetica Neue", "Helvetica", "Roboto", "Arial", sans-serif;
background-color: tan;
display: table;
}
#statSearchContainer h1 {
margin: 5px 0;
font-size: 1.0em;
}
#stat-search-form {
display: block;
padding: 0px;
}
#stat-search-form form input {
vertical-align: middle;
}
#statSearchFields {
vertical-align: top;
font-size: 90%;
}
.searchField {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="statSearchContainer">
<div class="searchField">
Distance<br/>
<select name="distance" id="distance"><option value="5.0 5">5 mi</option>
<option value="6.0 4">6 km</option>
<option selected="selected" value="10.0 4">10 km</option></select>
</div>
<input alt="Search" type="image" src="/assets/magnifying-glass-0220f37269f90a370c3bb60229240f2ef2a4e15b335cd42e64563ba65e4f22e4.png" class="search_button">
</div>
</div>

Why isn't my meteor {{#each}} working?

I have a meteor app at whensayfeed.meteor.com. It's supposed to repeat this div and it's contents for each document in a mongo collection, but it doesn't work. It used to. I can't seem to figure it out. My code is here on github. If you would mind looking it over that would be incredible.
HTML
<template name="FullFeed">
{{#each posts}}
<div class="post-contain">
<div class="chant">{{adjective}} {{noun}}</div>
<div class="author-box"><p>{{user}}</p></div>
</div>
{{/each}}
</template>
CSS
body {
background-color: #0F76D2;
margin: 0px;
font-family: sans-serif;
color: white;
}
.post-contain {
position: relative;
width: calc(100% - 20px);
height: 230px;
margin-top: 10px;
margin-left: 10px;
background-color: #0F76D2;
-webkit-box-shadow: 0px 0px 10px 0px rgba(0,0,0,0.19);
}
.author-box {
position: absolute;
bottom: 0px;
width: 100%;
background-color: rgba(0,0,0,0.42);
text-align: center;
font-size: 20px;
-webkit-box-shadow: 0px 1px 4px 0px rgba(0,0,0,0.5);
}
.author-box p {
position: relative;
}
.author-box > p { margin: 0 }
.author-box { padding: 10px 0 }
.chant {
font-size: 50px;
font-weight: 600;
-webkit-font-smoothing: antialiased;
}
.chant .varline {
color: #3f3f3f;
}
JS
posts = new Mongo.Collection("posts");
Router.route('/', function () {
this.render('FullFeed', {
data: function () { }
});
});
if (Meteor.isClient) {
// This code only runs on the client
Template.FullFeed.helpers({
posts: posts.find({}).fetch()
});
}
Your problem lies in the posts helper declaration, you're declaring it once and for all as an array (using Cursor.fetch) when your application code is first executed.
Your helper must be declared as a function if you want it to get reactively re-executed whenever the underlying cursor is modified, and you don't need to use fetch, Meteor {{#each}} block is optimized for cursors.
Template.FullFeed.helpers({
posts: function(){
return posts.find();
}
});

How to customize the HTML5 input range type looks using CSS?

I want to customize the looks of the range input type in HTML5 to look something like a progress bar. I've tried applying some common CSS attributes using CSS class but it seems that they are not working.
Can any one direct me how to customize it??
input[type='range'] {
-webkit-appearance: none !important;
background:red;
height:7px;
}
input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none !important;
background:blue;
height:10px;
width:10px;
}
If you're using HTML 5, why not use the progress tag?
<progress value="1534602" max="4603807">33%</progress>
EDIT: nowadays all major browser support both
<progress>
input[type='range']
Hence you should use one of these two, as explained in other answers, and this should not be the accepted answer anymore.
The <input type="range"> is pretty new and you are already attempting to customize it with CSS. :)
I wouldn't try that for two reasons:
there might be huge compatibility issues now and for the next few (or many) years.
Think that in nowadays a form control like <select> (available since the web started) is still problematic to be customized with CSS in a cross browser way. For instance if you set a padding for the select boxes, many browser (IE7, OPERA9, CHROME5, SAFARI4) will totally ignore the padding.
It works only IE8 and on FF 3.6. (all tests done with HTML5 DOCTYPE so in standard mode).
The <input type="range"> has been created to show a slider NOT a progress bar, attempting to cheat on it with CSS in order to transform a slider into progress bar it sounds bizarre. Like trying to use CSS to change a <textarea> into a table, but why don't you simply use a <table> to render tables?!
To show a progress bar in HTML5 you should follow the suggestion given by marcgg in his answer. Since no browser is currently rendereing it you could use a simple div with a p inside like this:
<div id="progress" style="position:relative; width:100px; height:20px; border:1px solid #cccccc;">
<p style="position:absolute; left:0; top:0; background-color:#0000ff; height:100%; width:30%; font-size:0px;"> </p>
</div>
Then simply update the style.width of inner P element in percent like:
width: 75%
FYI: if you want to do that in simple JS here is the code:
document.getElementById('progress').(getElementsByTagName('p')[0]).style.width = '75%';
I did a cross-browser solution (+IE9, FF, Chrome, Safari), only CSS.
[Updated 24.11.2016]
http://codepen.io/nlfonseca/pen/MwbovQ
#import 'bourbon';
$slider-width-number: 240;
$slider-width: #{$slider-width-number}px;
$slider-height: 2px;
$background-slider: #c7c7c7;
$background-filled-slider: #e33d44;
$thumb-width: 28px;
$thumb-height: 18px;
$thumb-radius: 8px;
$thumb-background: #fff;
$thumb-border: 1px solid #777;
$shadow-size: -8px;
$fit-thumb-in-slider: -8px;
#function makelongshadow($color, $size) {
$val: 5px 0 0 $size $color;
#for $i from 6 through $slider-width-number {
$val: #{$val}, #{$i}px 0 0 $size #{$color};
}
#return $val;
}
div {
height: 100px;
display: flex;
justify-content: center;
}
input {
align-items: center;
appearance: none;
background: none;
cursor: pointer;
display: flex;
height: 100%;
min-height: 50px;
overflow: hidden;
width: $slider-width;
&:focus {
box-shadow: none;
outline: none;
}
&::-webkit-slider-runnable-track {
background: $background-filled-slider;
content: '';
height: $slider-height;
pointer-events: none;
}
&::-webkit-slider-thumb {
#include size($thumb-width $thumb-height);
appearance: none;
background: $thumb-background;
border-radius: $thumb-radius;
box-shadow: makelongshadow($background-slider, $shadow-size);
margin-top: $fit-thumb-in-slider;
border: $thumb-border;
}
&::-moz-range-track {
width: $slider-width;
height: $slider-height;
}
&::-moz-range-thumb {
#include size($thumb-width $thumb-height);
background: $thumb-background;
border-radius: $thumb-radius;
border: $thumb-border;
position: relative;
}
&::-moz-range-progress {
height: $slider-height;
background: $background-filled-slider;
border: 0;
margin-top: 0;
}
&::-ms-track {
background: transparent;
border: 0;
border-color: transparent;
border-radius: 0;
border-width: 0;
color: transparent;
height: $slider-height;
margin-top: 10px;
width: $slider-width;
}
&::-ms-thumb {
#include size($thumb-width $thumb-height);
background: $thumb-background;
border-radius: $thumb-radius;
border: $thumb-border;
}
&::-ms-fill-lower {
background: $background-filled-slider;
border-radius: 0;
}
&::-ms-fill-upper {
background: $background-slider;
border-radius: 0;
}
&::-ms-tooltip {
display: none;
}
}
You can in Webkit, through the -webkit-slider-thumb pseudo-element: http://jsfiddle.net/leaverou/BNm8j/
input[type=range] {
-webkit-appearance: none;
background-color: silver;
width: 200px;
height:20px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
background-color: #666;
opacity: 0.5;
width: 10px;
height: 26px;
}
<input type="range" min="0" max="100" />
Although the others are right about input type="range" not being the right element for the job.
You should use the <progress> element and for browsers that don't support it, this polyfill: http://lea.verou.me/polyfills/progress/
You can edit the CSS of the range input, using input[type="range"]::-webkit-slider-thumb and input[type="range"].
Here is the example of it,
http://webstutorial.com/range-input-slider-html5-css3/html-5
I know this is already answered but just sharing it.
jQuery Tools provides a plug-in that creates stylable elements from a range input, and what's more, makes it still work as a slider in older browsers that don't support input[type=range].
Allows you to style:
the handle
the slider
optional progress fill
value output field
I've used it many times and it's a great tool.
WARNING: doesn't work on touch devices. I don't have as much experience with it, but you could try the jQuery mobile slider: http://view.jquerymobile.com/1.3.0/docs/widgets/sliders/
http://jquerytools.github.io/demos/rangeinput/index.html
When I looked at this question I needed something simple. There are already a number of framework answers on how to do this, but sometimes it is more lightweight and flexible just to create your own. Of course, you get a certain amount for free with a framework (and it is often the right choice if it is a good fit), but you then have to worry about framework compatibility, support and digging into the depths of the framework to go outside its boundaries.
Here is a simple javascript-only slider. Basically it is an img for the slider, an img for the button and a callback with a progress percent. Not an all-singing and dancing slider, but something simple to build on.
The demo
The HTML
<div id='bb_sliderContainer' ondragstart="return false;" ondrop="return false;">
<img id='bb_slider' src='slider.png'/>
<img id='bb_sliderButton' src='sliderbutton.png'/>
</div>
The script
Place in a javascript file:
(function(bb,undefined){
bb.Slider = function(buttonCssId,sliderCssId,initialPercentage,progressUpdate)
{
var halfButtonWidth = 5;
var sliderMoving = false;
var buttonElement = document.getElementById(buttonCssId);
var sliderElement = document.getElementById(sliderCssId);
var length = sliderElement.clientWidth;
var leftPos = 0;
var rightPos = leftPos + length;
length = rightPos - leftPos;
if( initialPercentage )
{
var buttonPos = leftPos + initialPercentage / 100 * length;
buttonElement.style.left = buttonPos - halfButtonWidth + 'px';
}
buttonElement.addEventListener( 'mousedown', function(){
sliderMoving = true;
} );
document.addEventListener( 'mousemove', function(event){
if( sliderMoving == true )
{
var rect = sliderElement.getBoundingClientRect();
var mouseX = event.clientX - rect.left;
var prop = mouseX / length;
if( prop < 0 )
{
prop = 0;
mouseX = 0;
}
if( prop > 1 )
{
prop = 1;
mouseX = length;
}
buttonElement.style.left = leftPos + prop * length - halfButtonWidth + 'px';
progressUpdate(prop * 100);
}
});
document.addEventListener( 'mouseup', function(){
sliderMoving = false;
});
}
}(window.bb = window.bb || {}));
Example use
HTML:
<img src='space.png' style='width:50%;position:relative;top:20px' id='bb_sliderSubject'>
Javascript:
function sliderUpdate(percentage)
{
var sliderSubject = document.getElementById('bb_sliderSubject');
sliderSubject.style.width = percentage + '%';
}
window.onload=function()
{
var slider = new bb.Slider('bb_sliderButton','bb_slider',50,sliderUpdate);
}
This is an example:
input[type='range'] {
-webkit-appearance: none;
border-radius: 5px;
box-shadow: inset 0 0 5px #333;
background-color: #999;
height: 10px;
vertical-align: middle;
}
input[type='range']::-moz-range-track {
-moz-appearance: none;
border-radius: 5px;
box-shadow: inset 0 0 5px #333;
background-color: #999;
height: 10px;
}
input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none !important;
border-radius: 20px;
background-color: #FFF;
box-shadow:inset 0 0 10px rgba(000,000,000,0.5);
border: 1px solid #999;
height: 20px;
width: 20px;
}
input[type='range']::-moz-range-thumb {
-moz-appearance: none;
border-radius: 20px;
background-color: #FFF;
box-shadow:inset 0 0 10px rgba(000,000,000,0.5);
border: 1px solid #999;
height: 20px;
width: 20px;
}
<input type="range">
See http://afarkas.github.io/webshim/demos/demos/webforms/styler/index.html?range
It's a tool that produces cross-browser code to style both native and webshims range inputs like you want.
.ws-range, input[type="range"] {
/* Range styles: width, height, border-radius, background */
-webkit-appearance: none;cursor: pointer;border: 0;outline: none;padding: 0;margin: 20.5px 0;
}
.ws-range .ws-range-thumb {
/* Thumb styles: width, height, border, border-radius, background */
}
.ws-range.ws-focus .ws-range-thumb {
/* Thumb focus styles: border-color, background */
}
.ws-range.ws-active .ws-range-thumb {
/* Thumb active styles: border-color, background */
}
.ws-range .ws-range-min {
/* Thumb progress styles: display, background */
border-radius: /* same as range */;
height: 100%;
}
input[type="range"]::-moz-range-track {
border: none;background: transparent;
}
input[type="range"]::-ms-tooltip {
display: none;
}
input[type="range"]::-webkit-slider-thumb {
/* Thumb styles: width, height, border, border-radius, background */
-webkit-appearance: none;
}
input[type="range"]::-ms-track {
/* Range styles: width, height, border-radius, background */
color: transparent;border: 0;
}
input[type="range"]::-moz-range-thumb {
/* Thumb styles: width, height, border, border-radius, background */
}
input[type="range"]::-ms-thumb {
/* Thumb styles: width, height, border, border-radius, background */
}
input[type="range"]:focus::-webkit-slider-thumb {
/* Thumb focus styles: border-color, background */
}
input[type="range"]:focus::-moz-range-thumb {
/* Thumb focus styles: border-color, background */
}
input[type="range"]:focus::-ms-thumb {
/* Thumb focus styles: border-color, background */
}
input[type="range"]:active::-webkit-slider-thumb {
/* Thumb active styles: border-color, background */
}
input[type="range"]:active::-moz-range-thumb {
/* Thumb active styles: border-color, background */
}
input[type="range"]:active::-ms-thumb {
/* Thumb active styles: border-color, background */
}
input[type="range"]::-moz-range-progress {
/* Thumb progress styles: display, background */
border-radius: /* same as range */;
height: 100%;
}
input[type="range"]::-ms-fill-lower {
/* Thumb progress styles: display, background */
border-radius: /* same as range */;
height: 100%;
}
.no-cssrangeinput input[type="range"] {
background: transparent;margin: 0;border: 0;min-height: 51px;
}

Resources