sorting data using dropdown ajax in codeigniter - ajax

i want to sorting data and display the result in the view. I'm using codeigniter framework. What i want is to sorting data using ajax when dropdown values change.
Can someone give me the example code ?
my ajax
<script>
$(document).ready(function() {
$("#selectBerdasar").change(function() {
var key = $(this).val();
console.log(key);
var postdata = {key: key};
var url = '<?php echo site_url('produk/filter/GetFilterJson');?>';
$.post(url, postdata, function(result) {
console.log(result);
if (result) {
var obj = JSON.parse(result);
$('.col-item').empty();
$.each(obj, function(key, line) {
});
} else {
}
});
});
});
my controller
public function doFilter($key) {
$this->load->helper('url');
$this->load->model('filter_model', 'filter');
if ($key == 'termahal') {
$data = $this->filter->getDataMahal($key);
} elseif ($key == 'termurah') {
$data = $this->filter->getDataMurah($key);
} else {
$data = $this->filter->getDataAlfabet($key);
}
return $data;
}
public function GetFilterJson() {
$key = $this->input->post('key');
$data = $this->doFilter($key);
echo json_encode($data);
}
my model
public function getDataMahal($key) {
$this->db->select("*");
$this->db->from("produk");
$this->db->order_by("harga_produk", "desc");
$data = $this->db->get();
return $data->result_array();
}
public function getDataMurah($key) {
$this->db->select("*");
$this->db->from("produk");
$this->db->order_by("harga_produk", "asc");
$data = $this->db->get();
return $data->result_array();
}
public function getDataAlfabet($key) {
$this->db->select("*");
$this->db->from("produk");
$this->db->order_by("nama_produk", "asc");
$data = $this->db->get();
return $data->result_array();
}

here is a simple example. hope this helps..
Ajax
var phone_number = $(this).find('div.number').text();
$("#recipentno").val(phone_number);
$.ajax({
type:"POST",
dataType: 'json',
url:"<?php echo base_url('administrator/get_all_sms/'); ?>",
data: {number: phone_number},
success: function(data) {
//console.log(data);
$(".smsmessage").html("");
console.log(data.total);
for (var i = 0; i < data.total.length; i++) {
if(data.total[i].message_type==1){
$('<div class="col-lg-8 col-lg">'+
'<div class="media">'+
'<div class="" style="border-radius: 25px; background: #4CC1ED; padding: 1px; width: 100%; margin-top: 10px;">'+
'<p style="color: #000000; padding-top: 10px; padding-left: 10px;padding-right: 10px; font-size: 18px;">'+ data.total[i].body+'<i style="font-size: 9px;">'+data.total[i].date_time+'</i></p>'+
'</div>'+
'</div>'+
'</div>').appendTo (".smsmessage");
} else{
$('<div class="col-lg-offset-4 col-lg-8">'+
'<div class="media">'+
'<div class="" style="border-radius: 25px; background: #65CFBF; padding: 1px; width: 100%; height: 50px; margin-top: 10px;">'+
'<p class="sender-img pull-right" style="color: #000000; padding-top: 10px; padding-left: 10px;padding-right: 10px; font-size: 18px;">'+data.total[i].body+'<i style="font-size: 9px;">'+data.total[i].date_time+'</i></p>'+
'</div>'+
'</div>'+
'</div>').appendTo (".smsmessage");
}
}
}
});
Controller
function get_all_sms(){
$pon_number = $this->input->post('number');
$single_sms= $this->admin->get_all_sms_for_number($pon_number);
echo json_encode(array( 'total'=> $single_sms));
}

Related

Toggle Button doesn't work inside datatable in laravel

The InActive button in the top of the picture, gets displayed properly when it is outside the datatable but doesn't work inside the datatable.
I have added the same code for status column inside the datatable but it displays only a checkbox. How do I get the InActive button inside datatable?
<script type="text/javascript">
$(document).ready(function() {
$.noConflict();
fill_datatable();
function fill_datatable(collegeID = '') {
var table = $('.user_datatable1').DataTable({
order: [
[0, 'desc']
],
processing: true,
serverSide: true,
ajax: {
url: "{{ route('alumni.datatable1') }}",
data: {
collegeID: collegeID
}
},
columns: [{
data: 'id',
name: 'id'
},
{
data: 'name',
name: 'name'
},
{
data: 'status',
name: 'status',
mRender: function(data) {
return ' <input data-id="{{$colleges->id}}" class="toggle-class" type="checkbox" data-onstyle="success" data-offstyle="danger" data-toggle="toggle" data-on="Active" data-off="InActive" {{ $colleges->status ? "checked" : "" }}>'
}
}
},
{
data: 'action',
name: 'action',
orderable: false,
searchable: false
},
]
});
}
});
$(function() {
$('.toggle-class').change(function() {
var status = $(this).prop('checked') == true ? 1 : 0;
var user_id = $(this).data('id');
$.ajax({
type: "GET",
dataType: "json",
url: '/changeStatus',
data: {'status': status, 'id': id},
success: function(data){
console.log(data.success)
}
});
})
})
</script>
Please Add css.....
CSS
<style>
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
</style>
You can simple put after status....
Toggle switch
{
"data": "id",
render: function(data, type, row, meta) {
$html = '<label class="switch"> <input type="checkbox">
<span class="slider round"></span></label>';
return $html;
}
},

Autosave Status in CKEditor 5

I have gotten stuck on a rather simple aspect of the autosave feature and that is the current status of the action like found on the overview page: https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/saving-data.html#demo. But it doesn't look like they actually reference it anywhere (example below).
My html is just:
<textarea class="form-control" name="notes" id="notes">{!! $shipmentShortage->notes !!}</textarea>
My create script is below, the autosave feature works just fine, but the status just isn't there:
<script>
ClassicEditor
.create( document.querySelector( '#notes' ), {
toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote', 'undo', 'redo' ],
image: {
toolbar: [ 'imageStyle:full', 'imageStyle:side', '|', 'imageTextAlternative' ],
},
autosave: {
save( editor ) {
console.log(editor.getData());
// The saveData() function must return a promise
// which should be resolved when the data is successfully saved.
return saveData( editor.getData() );
}
}
} );
// Save the data to a fake HTTP server (emulated here with a setTimeout()).
function saveData( data ) {
return new Promise( resolve => {
setTimeout( () => {
console.log( 'Saved', data );
$.ajax({
url: '/osd/shortages/update',
type: 'POST',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
data: {
'shortage_id':'{{$shipmentShortage->id}}',
'notes': data,
},
dataType: 'json',
success: function (response) {
console.log('saved');
}
});
resolve();
}, 5000 );
} );
}
// Update the "Status: Saving..." info.
function displayStatus( editor ) {
const pendingActions = editor.plugins.get( 'PendingActions' );
const statusIndicator = document.querySelector( '#editor-status' );
pendingActions.on( 'change:hasAny', ( evt, propertyName, newValue ) => {
if ( newValue ) {
statusIndicator.classList.add( 'busy' );
} else {
statusIndicator.classList.remove( 'busy' );
}
} );
}
</script>
You are absolutely correct. They show us a sexy status updater but don't give us the code for it. Here is what I extracted from the demo page by looking at the page source. This should give you the Status updates as you asked. Let me know if you have any questions.
HTML:
<div id="snippet-autosave">
<textarea name="content" id="CKeditor_Notes">
Sample text
</textarea>
</div>
<!-- This will show the save status -->
<div id="snippet-autosave-header">
<div id="snippet-autosave-status" class="">
<div id="snippet-autosave-status_label">Status:</div>
<div id="snippet-autosave-status_spinner">
<span id="snippet-autosave-status_spinner-label"></span>
<span id="snippet-autosave-status_spinner-loader"></span>
</div>
</div>
</div>
CSS:
<style>
#snippet-autosave-header{
display: flex;
justify-content: space-between;
align-items: center;
background: var(--ck-color-toolbar-background);
border: 1px solid var(--ck-color-toolbar-border);
padding: 10px;
border-radius: var(--ck-border-radius);
/*margin-top: -1.5em;*/
margin-bottom: 1.5em;
border-top: 0;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
#snippet-autosave-status_spinner {
display: flex;
align-items: center;
position: relative;
}
#snippet-autosave-status_spinner-label {
position: relative;
}
#snippet-autosave-status_spinner-label::after {
content: 'Saved!';
color: green;
display: inline-block;
margin-right: var(--ck-spacing-medium);
}
/* During "Saving" display spinner and change content of label. */
#snippet-autosave-status.busy #snippet-autosave-status_spinner-label::after {
content: 'Saving...';
color: red;
}
#snippet-autosave-status.busy #snippet-autosave-status_spinner-loader {
display: block;
width: 16px;
height: 16px;
border-radius: 50%;
border-top: 3px solid hsl(0, 0%, 70%);
border-right: 2px solid transparent;
animation: autosave-status-spinner 1s linear infinite;
}
#snippet-autosave-status,
#snippet-autosave-server {
display: flex;
align-items: center;
}
#snippet-autosave-server_label,
#snippet-autosave-status_label {
font-weight: bold;
margin-right: var(--ck-spacing-medium);
}
#snippet-autosave + .ck.ck-editor .ck-editor__editable {
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
#snippet-autosave-lag {
padding: 4px;
}
#snippet-autosave-console {
max-height: 300px;
overflow: auto;
white-space: normal;
background: #2b2c26;
transition: background-color 500ms;
}
#snippet-autosave-console.updated {
background: green;
}
#keyframes autosave-status-spinner {
to {
transform: rotate( 360deg );
}
}
</style>
The rest is just initializing the Editor just like on the demo page here.
ClassicEditor
.create(document.querySelector('#CKeditor_Notes'), {
autosave: {
save(editor) {
return saveData(editor.getData());
}
}
})
.then(editor => {
window.editor = editor;
displayStatus(editor);
})
.catch(err => {
console.error(err.stack);
});
// Save the data to Server Side DB.
function saveData(data) {
return new Promise(resolve => {
setTimeout(() => {
console.log('Saved', data);
SaveDataToDB(data)
resolve();
});
});
}
// Update the "Status: Saving..." info.
function displayStatus(editor) {
const pendingActions = editor.plugins.get('PendingActions');
const statusIndicator = document.querySelector('#snippet-autosave-status');
pendingActions.on('change:hasAny', (evt, propertyName, newValue) => {
if (newValue) {
statusIndicator.classList.add('busy');
} else {
statusIndicator.classList.remove('busy');
}
});
}

Dropzone : Unprocessable entity Laravel 5

I have the following code. It is suppossed to send the formData of title ,tag and description to the controller for uploading.But I keep recieving this error.
Error :
Failed to load resource: the server responded with a status of 422 (Unprocessable Entity)
Here is my code:
<!DOCTYPE html>
<html>
<head>
<title>Laravel Multiple Images Upload Using Dropzone</title>
<meta name="_token" content="{{csrf_token()}}" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.4.0/min/dropzone.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.4.0/dropzone.js"></script>
<style>
.data{
display:none;
}
.dropzone {
width: 98%;
margin: 1%;
border: 2px dashed #3498db !important;
border-radius: 5px;
transition: 0.2s;
}
.dropzone.dz-drag-hover {
border: 2px solid #3498db !important;
}
.dz-message.needsclick img {
width: 50px;
display: block;
margin: auto;
opacity: 0.6;
margin-bottom: 15px;
}
span.plus {
display: none;
}
.dropzone.dz-started .dz-message {
display: inline-block !important;
width: 120px;
float: right;
border: 1px solid rgba(238, 238, 238, 0.36);
border-radius: 30px;
height: 120px;
margin: 16px;
transition: 0.2s;
}
.dropzone.dz-started .dz-message span.text {
display: none;
}
.dropzone.dz-started .dz-message span.plus {
display: block;
font-size: 70px;
color: #AAA;
line-height: 110px;
}
</style>
</head>
<body>
<div class="container">
<form method="GET" enctype="multipart/form-data" class="dropzone" id="dropzone">
<button id='upload'>Upload</button>
#csrf
</form>
<div class='data' ></div>
</div>
<script type="text/javascript">
var title = $('#title').val();
var description = $('#description').val();
max=2
var thumbnail;
Dropzone.options.dropzone = {
maxFiles: max,
autoProcessQueue: false,
uploadMultiple: true,
method:"get",
maxFilesize: 12,
url: '/upload',
init: function() {
var myDropzone = this;
$("#upload").click(function(e) {
// First change the button to actually tell Dropzone to process the queue.
// Make sure that the form isn't actually being sent.
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
this.on("maxfilesexceeded", function(file) {
alert('Max of '+ max + ' files');
this.removeFile(file);
});
this.on("addedfile", function() {
this.on('thumbnail', function(file, thumbnail) {
thumbnail = file.thumbnail;
});
this.on('sending', function (file, xhr, formData) {
// Append all form inputs to the formData Dropzone will POST
var data = $('.dropzone').serializeArray();
$.each(data, function (key, el) {
formData.append(el.title, el.description, el.tags);
});
console.log(formData);
});
var myvar = '<div class="form-group">'+
'<img class="media-object thumbnail" src="'+ thumbnail +'" />'+
'<label for="title">Title</label>'+
'<input type="text" class="form-control" id="title" aria-describedby="title" placeholder="Give your image a title"><br>'+
'<label for="Description">Description</label>'+
'<input type="text" class="form-control" id="description" aria-describedby="Description" placeholder="Describe your image"><br>'+
'<label for="Tags">Tags</label>'+
'<input type="text" class="form-control" id="Tags" aria-describedby="Tags" placeholder="Give your image tags"><br>'+
'<small>Tags are important to let people easily find your image</small><br><br>'+
''
;
$('.data').show();
$('.data').append(myvar);
});
},
acceptedFiles: ".jpeg,.jpg,.png,.gif",
addRemoveLinks: true,
timeout: 50000,
processQueue: function(file) {
var name = file.upload.filename;
$.ajax({
headers:
{
'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
},
type: 'POSTg',
url: '{{ url("image/delete") }}',
data: {
title: title,
description:description,
type:"image",
body:"upploaded/img"+filename
},
success: function(data) {
console.log("File has been successfully removed!!");
},
error: function(e) {
console.log(e);
}
});
var fileRef;
return (fileRef = file.previewElement) != null ?
fileRef.parentNode.removeChild(file.previewElement) : void 0;
},
success: function(file, response) {
console.log(response);
},
error: function(file, response) {
return false;
}
};
</script>
</body>
</html>
And here is MyController:
public function upload(StorePostRequest $request)
{
$title= Post::where('title', $request->input('title'))->first();
if (!$title == null) {
return redirect()->back()->withErrors(['Title Already Exists', 'Title already exists']);
return response()->json(["message" => "Failed","reason" => "Title Already Exists"]);
}
$post = Post::create([
'title' => $request->input('title'),
'body' => $request->input('body'),
'description' => $request->input('description'),
'type' => $request->input('type'),
'user_id' => auth()->id(),
'published_at' => $request->has('draft') ? null : \Carbon\Carbon::now()
]);
}
StorePostRequest.php:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
class StorePostRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return Auth::check();
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'title' => 'required|max:255',
'body' => 'required',
'tags' => 'nullable',
'image' => 'nullable|image|max:2048'
];
}
}
Thanks in advance

Google Place API: how to autocomplete API for custom search?

I am new to Google Api....Can Anyone please provide me code for PLACE Autocomplete if I only want to have autocomplete search-results related to hospitals only such that in search bar,it should display only hospitals name and nothing else.
Here Is My Code.It's Just Showing City Names in Search Field. I want Hospital's Name To be Searched.
<!DOCTYPE html>
<html>
<head>
<title>Place Autocomplete Hotel Search</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<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;
}
table {
font-size: 12px;
}
#map {
width: 440px;
}
#listing {
position: absolute;
width: 200px;
height: 470px;
overflow: auto;
left: 442px;
top: 0px;
cursor: pointer;
overflow-x: hidden;
}
#findhotels {
position: absolute;
text-align: right;
width: 100px;
font-size: 14px;
padding: 4px;
z-index: 5;
background-color: #fff;
}
#locationField {
position: absolute;
width: 190px;
height: 25px;
left: 108px;
top: 0px;
z-index: 5;
background-color: #fff;
}
#controls {
position: absolute;
left: 300px;
width: 140px;
top: 0px;
z-index: 5;
background-color: #fff;
}
#autocomplete {
width: 100%;
}
#country {
width: 100%;
}
.placeIcon {
width: 20px;
height: 34px;
margin: 4px;
}
.hotelIcon {
width: 24px;
height: 24px;
}
#resultsTable {
border-collapse: collapse;
width: 240px;
}
#rating {
font-size: 13px;
font-family: Arial Unicode MS;
}
.iw_table_row {
height: 18px;
}
.iw_attribute_name {
font-weight: bold;
text-align: right;
}
.iw_table_icon {
text-align: right;
}
</style>
</head>
<body>
<div id="findhotels">
Find hotels in:
</div>
<div id="locationField">
<input id="autocomplete" placeholder="Enter a city" type="text" />
</div>
<div id="controls">
<select id="country">
<option value="all">All</option>
<option value="au">Australia</option>
<option value="br">Brazil</option>
<option value="ca">Canada</option>
<option value="fr">France</option>
<option value="de">Germany</option>
<option value="mx">Mexico</option>
<option value="nz">New Zealand</option>
<option value="it">Italy</option>
<option value="za">South Africa</option>
<option value="es">Spain</option>
<option value="pt">Portugal</option>
<option value="us" selected>U.S.A.</option>
<option value="uk">United Kingdom</option>
</select>
</div>
<div id="map"></div>
<div id="listing">
<table id="resultsTable">
<tbody id="results"></tbody>
</table>
</div>
<div style="display: none">
<div id="info-content">
<table>
<tr id="iw-url-row" class="iw_table_row">
<td id="iw-icon" class="iw_table_icon"></td>
<td id="iw-url"></td>
</tr>
<tr id="iw-address-row" class="iw_table_row">
<td class="iw_attribute_name">Address:</td>
<td id="iw-address"></td>
</tr>
<tr id="iw-phone-row" class="iw_table_row">
<td class="iw_attribute_name">Telephone:</td>
<td id="iw-phone"></td>
</tr>
<tr id="iw-rating-row" class="iw_table_row">
<td class="iw_attribute_name">Rating:</td>
<td id="iw-rating"></td>
</tr>
<tr id="iw-website-row" class="iw_table_row">
<td class="iw_attribute_name">Website:</td>
<td id="iw-website"></td>
</tr>
</table>
</div>
</div>
<script>
// This example uses the autocomplete feature of the Google Places API.
// It allows the user to find all hotels in a given place, within a given
// country. It then displays markers for all the hotels returned,
// with on-click details for each hotel.
// This example requires the Places library. Include the libraries=places
// parameter when you first load the API. For example:
// <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places">
var map, places, infoWindow;
var markers = [];
var autocomplete;
var countryRestrict = {'country': 'us'};
var MARKER_PATH = 'https://developers.google.com/maps/documentation/javascript/images/marker_green';
var hostnameRegexp = new RegExp('^https?://.+?/');
var countries = {
'au': {
center: {lat: -25.3, lng: 133.8},
zoom: 4
},
'br': {
center: {lat: -14.2, lng: -51.9},
zoom: 3
},
'ca': {
center: {lat: 62, lng: -110.0},
zoom: 3
},
'fr': {
center: {lat: 46.2, lng: 2.2},
zoom: 5
},
'de': {
center: {lat: 51.2, lng: 10.4},
zoom: 5
},
'mx': {
center: {lat: 23.6, lng: -102.5},
zoom: 4
},
'nz': {
center: {lat: -40.9, lng: 174.9},
zoom: 5
},
'it': {
center: {lat: 41.9, lng: 12.6},
zoom: 5
},
'za': {
center: {lat: -30.6, lng: 22.9},
zoom: 5
},
'es': {
center: {lat: 40.5, lng: -3.7},
zoom: 5
},
'pt': {
center: {lat: 39.4, lng: -8.2},
zoom: 6
},
'us': {
center: {lat: 37.1, lng: -95.7},
zoom: 3
},
'uk': {
center: {lat: 54.8, lng: -4.6},
zoom: 5
}
};
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: countries['us'].zoom,
center: countries['us'].center,
mapTypeControl: false,
panControl: false,
zoomControl: false,
streetViewControl: false
});
infoWindow = new google.maps.InfoWindow({
content: document.getElementById('info-content')
});
// Create the autocomplete object and associate it with the UI input control.
// Restrict the search to the default country, and to place type "cities".
autocomplete = new google.maps.places.Autocomplete(
/** #type {!HTMLInputElement} */ (
document.getElementById('autocomplete')), {
types: ['(cities)'],
componentRestrictions: countryRestrict
});
places = new google.maps.places.PlacesService(map);
autocomplete.addListener('place_changed', onPlaceChanged);
// Add a DOM event listener to react when the user selects a country.
document.getElementById('country').addEventListener(
'change', setAutocompleteCountry);
}
// When the user selects a city, get the place details for the city and
// zoom the map in on the city.
function onPlaceChanged() {
var place = autocomplete.getPlace();
if (place.geometry) {
map.panTo(place.geometry.location);
map.setZoom(15);
search();
} else {
document.getElementById('autocomplete').placeholder = 'Enter a city';
}
}
// Search for hotels in the selected city, within the viewport of the map.
function search() {
var search = {
bounds: map.getBounds(),
types: ['lodging']
};
places.nearbySearch(search, function(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
clearResults();
clearMarkers();
// Create a marker for each hotel found, and
// assign a letter of the alphabetic to each marker icon.
for (var i = 0; i < results.length; i++) {
var markerLetter = String.fromCharCode('A'.charCodeAt(0) + (i % 26));
var markerIcon = MARKER_PATH + markerLetter + '.png';
// Use marker animation to drop the icons incrementally on the map.
markers[i] = new google.maps.Marker({
position: results[i].geometry.location,
animation: google.maps.Animation.DROP,
icon: markerIcon
});
// If the user clicks a hotel marker, show the details of that hotel
// in an info window.
markers[i].placeResult = results[i];
google.maps.event.addListener(markers[i], 'click', showInfoWindow);
setTimeout(dropMarker(i), i * 100);
addResult(results[i], i);
}
}
});
}
function clearMarkers() {
for (var i = 0; i < markers.length; i++) {
if (markers[i]) {
markers[i].setMap(null);
}
}
markers = [];
}
// Set the country restriction based on user input.
// Also center and zoom the map on the given country.
function setAutocompleteCountry() {
var country = document.getElementById('country').value;
if (country == 'all') {
autocomplete.setComponentRestrictions({'country': []});
map.setCenter({lat: 15, lng: 0});
map.setZoom(2);
} else {
autocomplete.setComponentRestrictions({'country': country});
map.setCenter(countries[country].center);
map.setZoom(countries[country].zoom);
}
clearResults();
clearMarkers();
}
function dropMarker(i) {
return function() {
markers[i].setMap(map);
};
}
function addResult(result, i) {
var results = document.getElementById('results');
var markerLetter = String.fromCharCode('A'.charCodeAt(0) + (i % 26));
var markerIcon = MARKER_PATH + markerLetter + '.png';
var tr = document.createElement('tr');
tr.style.backgroundColor = (i % 2 === 0 ? '#F0F0F0' : '#FFFFFF');
tr.onclick = function() {
google.maps.event.trigger(markers[i], 'click');
};
var iconTd = document.createElement('td');
var nameTd = document.createElement('td');
var icon = document.createElement('img');
icon.src = markerIcon;
icon.setAttribute('class', 'placeIcon');
icon.setAttribute('className', 'placeIcon');
var name = document.createTextNode(result.name);
iconTd.appendChild(icon);
nameTd.appendChild(name);
tr.appendChild(iconTd);
tr.appendChild(nameTd);
results.appendChild(tr);
}
function clearResults() {
var results = document.getElementById('results');
while (results.childNodes[0]) {
results.removeChild(results.childNodes[0]);
}
}
// Get the place details for a hotel. Show the information in an info window,
// anchored on the marker for the hotel that the user selected.
function showInfoWindow() {
var marker = this;
places.getDetails({placeId: marker.placeResult.place_id},
function(place, status) {
if (status !== google.maps.places.PlacesServiceStatus.OK) {
return;
}
infoWindow.open(map, marker);
buildIWContent(place);
});
}
// Load the place information into the HTML elements used by the info window.
function buildIWContent(place) {
document.getElementById('iw-icon').innerHTML = '<img class="hotelIcon" ' +
'src="' + place.icon + '"/>';
document.getElementById('iw-url').innerHTML = '<b><a href="' + place.url +
'">' + place.name + '</a></b>';
document.getElementById('iw-address').textContent = place.vicinity;
if (place.formatted_phone_number) {
document.getElementById('iw-phone-row').style.display = '';
document.getElementById('iw-phone').textContent =
place.formatted_phone_number;
} else {
document.getElementById('iw-phone-row').style.display = 'none';
}
// Assign a five-star rating to the hotel, using a black star ('✭')
// to indicate the rating the hotel has earned, and a white star ('✩')
// for the rating points not achieved.
if (place.rating) {
var ratingHtml = '';
for (var i = 0; i < 5; i++) {
if (place.rating < (i + 0.5)) {
ratingHtml += '✩';
} else {
ratingHtml += '✭';
}
document.getElementById('iw-rating-row').style.display = '';
document.getElementById('iw-rating').innerHTML = ratingHtml;
}
} else {
document.getElementById('iw-rating-row').style.display = 'none';
}
// The regexp isolates the first part of the URL (domain plus subdomain)
// to give a short URL for displaying in the info window.
if (place.website) {
var fullUrl = place.website;
var website = hostnameRegexp.exec(place.website);
if (website === null) {
website = 'http://' + place.website + '/';
fullUrl = website;
}
document.getElementById('iw-website-row').style.display = '';
document.getElementById('iw-website').textContent = website;
} else {
document.getElementById('iw-website-row').style.display = 'none';
}
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=My_Api_Key&libraries=places&callback=initMap"
async defer></script>
</body>
</html>
To be very clear for rookies like me (because I wasted a lot of time on this) you cannot set an Autocomplete request to return specific types of places.
For example, if you want Autocomplete to return just hospitals, or just restaurants, or just parks, as of April 2022, you can't.
This issue requesting that ability was opened in 2011 and hasn't been handled yet. https://issuetracker.google.com/issues/35820774
You can only set Autocomplete to return classes of places, by setting the type to something in Table 3 here - https://developers.google.com/maps/documentation/places/web-service/supported_types
Table 3 options are:
geocode
address
establishment
regions
cities
in the Search Function, in variable search change types field to hospital like:
var search = {
bounds: map.getBounds(),
types: ['hospital']
};
and in the Autocomplete predictions so far only "country" restriction is supported as stated in the documentation:
"componentRestrictions can be used to restrict results to specific groups. Currently, you can use componentRestrictions to filter by up to 5 countries. Countries must be passed as as a two-character, ISO 3166-1 Alpha-2 compatible country code. Multiple countries must be passed as a list of country codes."
https://developers.google.com/maps/documentation/javascript/places-autocomplete
If you would like to add this feature for Autocomplete, there is already a case in the issue tracker where you can add your vote to support this request in:
https://issuetracker.google.com/issues/35820774

Magnific Popup with upload image preview

I'm using Magnific popup to display an upload form where the user can select multiple images to upload and preview them before submitting the form, I let the user preview the images plus add a from inputs underneath the image when he clicks on it to enter the caption and alt for it, here's the code that I have ...
(function() {
if ($("a.uploadMediaImageForm").length) {
$("a.uploadMediaImageForm").magnificPopup({
type: 'inline',
preloader: false,
closeOnBgClick: false,
enableEscapeKey: false,
focus: '#name',
removalDelay: 500, //delay removal by X to allow out-animation
// When elemened is focused, some mobile browsers in some cases zoom in
// It looks not nice, so we disable it:
callbacks: {
beforeOpen: function() {
if ($(window).width() < 700) {
this.st.focus = false;
} else {
this.st.focus = '#name';
}
this.st.mainClass = this.st.el.attr('data-effect');
},
open: function() {
if ($("input#imageUpload").length) {
$("input#imageUpload").on('change', function() {
//Get count of selected files
var countFiles = $(this)[0].files.length;
var imgPath = $(this)[0].value;
var extension = imgPath.substring(imgPath.lastIndexOf('.') + 1).toLowerCase();
var previewHolder = $("ul.imagePreview");
previewHolder.empty();
if (extension == "gif" || extension == "png" || extension == "jpg" || extension == "jpeg") {
if (typeof(FileReader) != "undefined") {
//loop for each file selected for uploaded.
for (var i = 0; i < countFiles; i++) {
var reader = new FileReader();
reader.onload = function(e) {
$("<li><img src='" + e.target.result +"'></li>").appendTo(previewHolder);
}
previewHolder.show();
reader.readAsDataURL($(this)[0].files[i]);
}
} else {
alert("This browser does not support FileReader.");
}
} else {
alert("Please select only images");
}
});
} //Image upload preview
if($("ul.imagePreview").length) {
$("ul.imagePreview").on("click", "li", function(event) {
if($(this).hasClass("selected")) {
$(this).removeClass("selected");
$(this).find("div").remove();
} else {
$(this).addClass("selected");
$(this).append("<div><label><span>Image Alt</span><input type='text'></label><label><span>Image Caption</span><input type='text'></label></div>");
}
});
$("ul.imagePreview").on("click", "div", function(event) {
event.stopPropagation();
});
}//add form when clicked on an image
},
beforeClose: function() {
// $("ul.imagePreview").empty();
var countFiles = "";
var imgPath = "";
var extension = "";
var previewHolder = $("ul.imagePreview");
previewHolder.empty();
}
},
midClick: true // allow opening popup on middle mouse click. Always set
});
}
})(); //popup Forms and Uploads
div.uploadPopup {
width: 80%;
margin: auto;
background: white;
position: relative;
padding: 40px;
}
label {
width: 100%;
margin-bottom: 20px;
clear: both;
}
ul.imagePreview {
width: 100%;
clear: both;
display: block;
}
ul.imagePreview li {
width: 100%;
display: block;
margin-bottom: 20px;
max-height: 150px;
cursor: pointer;
}
ul.imagePreview li.selected {
max-height: auto;
}
ul.imagePreview li img {
max-height: 150px;
display: block;
margin: auto;
}
<link href="https://cdn.jsdelivr.net/jquery.magnific-popup/1.0.0/magnific-popup.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/magnific-popup.js/1.0.1/jquery.magnific-popup.min.js"></script>
Upload Media
<div id="uploadMediaImageForm" class="uploadPopup mfp-with-anim mfp-hide">
<form action="#">
<label class="upload">
<span>Upload Images</span>
<input id="imageUpload" type="file" multiple>
</label>
<ul class="imagePreview">
</ul>
</form>
</div>
Now everything works fine the first time, but when I close the popup and re-open it again, something wrong happens in the image previewer, it duplicates the images I choose and sometimes doesn't even show the image if it were the last image I choose before closing.
I tried to set all the variables before closing the popup and clear the image preview ul element, but that didn't help.
I need your help guys, what am I doing wrong here?
EDIT
I gave the form itself an id of "fileForm" and tried to reset the whole form and empty the ul.imagePreview before closing the popup with this code ...
$("#fileForm")[0].reset();
$("ul.imagePreview").empty();
But still no luck, it still duplicated any image I upload the second time after closing the popup and opening it again !!
need help here.
You are binding more and more listeners to the same event:
Your form always exists in your document even when the popup is closed, you just hide it most of the time (using the class mfp-hide).
Each time you open the popup, the callback "open" is called, which bind a function to the change event of your input, and this callback do the preview stuff.
But if you open the popup twice, it will bind again the same function to the same event on the same input. That's why you have duplicate: the code is called twice.
Move all your binding outside your callback so that they will be done once:
(function() {
if ($("input#imageUpload").length) {
$("input#imageUpload").on('change', function() {
//Get count of selected files
var countFiles = $(this)[0].files.length;
var imgPath = $(this)[0].value;
var extension = imgPath.substring(imgPath.lastIndexOf('.') + 1).toLowerCase();
var previewHolder = $("ul.imagePreview");
previewHolder.empty();
if (extension == "gif" || extension == "png" || extension == "jpg" || extension == "jpeg") {
if (typeof(FileReader) != "undefined") {
//loop for each file selected for uploaded.
for (var i = 0; i < countFiles; i++) {
var reader = new FileReader();
reader.onload = function(e) {
$("<li><img src='" + e.target.result +"'></li>").appendTo(previewHolder);
}
previewHolder.show();
reader.readAsDataURL($(this)[0].files[i]);
}
} else {
alert("This browser does not support FileReader.");
}
} else {
alert("Please select only images");
}
});
} //Image upload preview
if($("ul.imagePreview").length) {
$("ul.imagePreview").on("click", "li", function(event) {
if($(this).hasClass("selected")) {
$(this).removeClass("selected");
$(this).find("div").remove();
} else {
$(this).addClass("selected");
$(this).append("<div><label><span>Image Alt</span><input type='text'></label><label><span>Image Caption</span><input type='text'></label></div>");
}
});
$("ul.imagePreview").on("click", "div", function(event) {
event.stopPropagation();
});
}//add form when clicked on an image
if ($("a.uploadMediaImageForm").length) {
$("a.uploadMediaImageForm").magnificPopup({
type: 'inline',
preloader: false,
closeOnBgClick: false,
enableEscapeKey: false,
focus: '#name',
removalDelay: 500, //delay removal by X to allow out-animation
// When elemened is focused, some mobile browsers in some cases zoom in
// It looks not nice, so we disable it:
callbacks: {
beforeOpen: function() {
if ($(window).width() < 700) {
this.st.focus = false;
} else {
this.st.focus = '#name';
}
this.st.mainClass = this.st.el.attr('data-effect');
},
beforeClose: function() {
///$("ul.imagePreview").empty();
var countFiles = "";
var imgPath = "";
var extension = "";
var previewHolder = $("ul.imagePreview");
previewHolder.empty();
$("#fileForm")[0].reset();
}
},
midClick: true // allow opening popup on middle mouse click. Always set
});
}
})(); //popup Forms and Uploads
div.uploadPopup {
width: 80%;
margin: auto;
background: white;
position: relative;
padding: 40px;
}
label {
width: 100%;
margin-bottom: 20px;
clear: both;
}
ul.imagePreview {
width: 100%;
clear: both;
display: block;
}
ul.imagePreview li {
width: 100%;
display: block;
margin-bottom: 20px;
max-height: 150px;
cursor: pointer;
}
ul.imagePreview li.selected {
max-height: auto;
}
ul.imagePreview li img {
max-height: 150px;
display: block;
margin: auto;
}
<link href="https://cdn.jsdelivr.net/jquery.magnific-popup/1.0.0/magnific-popup.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/magnific-popup.js/1.0.1/jquery.magnific-popup.min.js"></script>
Upload Media
<div id="uploadMediaImageForm" class="uploadPopup mfp-with-anim mfp-hide">
<form action="#" id="fileForm">
<label class="upload">
<span>Upload Images</span>
<input id="imageUpload" type="file" multiple>
</label>
<ul class="imagePreview">
</ul>
</form>
</div>

Resources