Bing map cannot display - html

I want to upload a Bing map on my project(MVC3 and Razor engine). I have Create and Edit Views to deal with dinner as well as display bing map. The problem is that only Edit view can display the map while Create view cannot. But both of the views render the same particial view called "DinnerForm". I am wondering why cause this problem.
The Create view
#model NerdDinner.Models.DinnerFormViewModel
#{
ViewBag.Title = "Create";
}
<h2>Host a dinner</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#{Html.RenderPartial("DinnerForm");}
The Edite view
#model NerdDinner.Models.DinnerFormViewModel
ViewBag.Title = #Html.Encode(Model.Dinner.Title);
<h2>Edit</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#{Html.RenderPartial("DinnerForm");}
The DinnerForm View
#model NerdDinner.Models.DinnerFormViewModel
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<div class="editor-label">
#Html.LabelFor(model => model.Dinner.Title)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Dinner.Title)
#Html.ValidationMessageFor(model => model.Dinner.Title)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Dinner.Latitude)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Dinner.Latitude)
#Html.ValidationMessageFor(model => model.Dinner.Latitude)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Dinner.Longitude)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Dinner.Longitude)
#Html.ValidationMessageFor(model => model.Dinner.Longitude)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Dinner.EventDate)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Dinner.EventDate)
#Html.ValidationMessageFor(model => model.Dinner.EventDate)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Dinner.ContactPhone)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Dinner.ContactPhone)
#Html.ValidationMessageFor(model => model.Dinner.ContactPhone)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Dinner.Address)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Dinner.Address)
#Html.ValidationMessageFor(model => model.Dinner.Address)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Dinner.Country)
</div>
<div class="editor-field">
#Html.DropDownList("Country", #Model.Countries)
#Html.ValidationMessageFor(model => model.Countries)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Dinner.HostedBy)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Dinner.HostedBy)
#Html.ValidationMessageFor(model => model.Dinner.HostedBy)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Dinner.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Dinner.Description)
#Html.ValidationMessageFor(model => model.Dinner.Description)
</div>
<p>
<input type="submit" value="Save" />
</p>
<div id="mapDiv">
#{Html.RenderPartial("Map", Model.Dinner);}
</div>
</fieldset>
<script type="text/javascript">
$(document).ready(function () {
$("#Address").blur(function (evt) {
$("#Latitude").val("");
$("#Longitude").val("");
var address = jQuery.trim($("#Address").val());
if (address.length < 1)
return;
FindAddressOnMap(address);
});
});
</script>
}
The Map view is fine because it appears on the page of Edit.
I have a js file called NerdDinner to reach the map function. FindAddressOnMap() function is defined there.
function NerdDinner() { }
NerdDinner.MapDivId = 'theMap';
NerdDinner._map = null;
NerdDinner._points = [];
NerdDinner._shapes = [];
NerdDinner.LoadMap = function (latitude, longitude, onMapLoaded) {
NerdDinner._map = new VEMap(NerdDinner.MapDivId);
var options = new VEMapOptions();
options.EnableBirdseye = false
// Makes the control bar less obtrusize.
this._map.SetDashboardSize(VEDashboardSize.Small);
if (onMapLoaded != null)
NerdDinner._map.onLoadMap = onMapLoaded;
if (latitude != null && longitude != null) {
var center = new VELatLong(latitude, longitude);
}
NerdDinner._map.LoadMap(center, null, null, null, null, null, null, options);
}
NerdDinner.ClearMap = function () {
NerdDinner._map.Clear();
NerdDinner._points = [];
NerdDinner._shapes = [];
}
NerdDinner.LoadPin = function (LL, name, description) {
var shape = new VEShape(VEShapeType.Pushpin, LL);
//Make a nice Pushpin shape with a title and description
shape.SetTitle("<span class=\"pinTitle\"> " + escape(name) + "</span>");
if (description !== undefined) {
shape.SetDescription("<p class=\"pinDetails\">" + escape(description) + "</p>");
}
NerdDinner._map.AddShape(shape);
NerdDinner._points.push(LL);
NerdDinner._shapes.push(shape);
}
NerdDinner.FindAddressOnMap = function (where) {
var numberOfResults = 1;
var setBestMapView = true;
var showResults = true;
var defaultDisambiguation = true;
NerdDinner._map.Find("", where, null, null, null,
numberOfResults, showResults, true, defaultDisambiguation,
setBestMapView, NerdDinner._callbackForLocation);
}
NerdDinner._callbackForLocation = function (layer, resultsArray, places, hasMore, VEErrorMessage) {
NerdDinner.ClearMap();
if (places == null) {
NerdDinner._map.ShowMessage(VEErrorMessage);
return;
}
//Make a pushpin for each place we find
$.each(places, function (i, item) {
var description = "";
if (item.Description !== undefined) {
description = item.Description;
}
var LL = new VELatLong(item.LatLong.Latitude,
item.LatLong.Longitude);
NerdDinner.LoadPin(LL, item.Name, description);
});
//Make sure all pushpins are visible
if (NerdDinner._points.length > 1) {
NerdDinner._map.SetMapView(NerdDinner._points);
}
//If we've found exactly one place, that's our address.
//lat/long precision was getting lost here with toLocaleString, changed to toString
if (NerdDinner._points.length === 1) {
$("#Latitude").val(NerdDinner._points[0].Latitude.toString());
$("#Longitude").val(NerdDinner._points[0].Longitude.toString());
}
}
NerdDinner.FindDinnersGivenLocation = function (where) {
NerdDinner._map.Find("", where, null, null, null, null, null, false,
null, null, NerdDinner._callbackUpdateMapDinners);
}
NerdDinner.FindMostPopularDinners = function (limit) {
$.post("/Search/GetMostPopularDinners", { "limit": limit }, NerdDinner._renderDinners, "json");
}
NerdDinner._callbackUpdateMapDinners = function (layer, resultsArray, places, hasMore, VEErrorMessage) {
var center = NerdDinner._map.GetCenter();
$.post("/Search/SearchByLocation",
{ latitude: center.Latitude, longitude: center.Longitude },
NerdDinner._renderDinners,
"json");
}
NerdDinner._renderDinners = function (dinners) {
$("#dinnerList").empty();
NerdDinner.ClearMap();
$.each(dinners, function (i, dinner) {
var LL = new VELatLong(dinner.Latitude, dinner.Longitude, 0, null);
// Add Pin to Map
NerdDinner.LoadPin(LL, _getDinnerLinkHTML(dinner), _getDinnerDescriptionHTML(dinner));
//Add a dinner to the <ul> dinnerList on the right
$('#dinnerList').append($('<li/>')
.attr("class", "dinnerItem")
.append(_getDinnerLinkHTML(dinner))
.append($('<br/>'))
.append(_getDinnerDate(dinner, "mmm d"))
.append(" with " + _getRSVPMessage(dinner.RSVPCount)));
});
// Adjust zoom to display all the pins we just added.
if (NerdDinner._points.length > 1) {
NerdDinner._map.SetMapView(NerdDinner._points);
}
// Display the event's pin-bubble on hover.
$(".dinnerItem").each(function (i, dinner) {
$(dinner).hover(
function () { NerdDinner._map.ShowInfoBox(NerdDinner._shapes[i]); },
function () { NerdDinner._map.HideInfoBox(NerdDinner._shapes[i]); }
);
});
function _getDinnerDate(dinner, formatStr) {
return '<strong>' + _dateDeserialize(dinner.EventDate).format(formatStr) + '</strong>';
}
function _getDinnerLinkHTML(dinner) {
return '' + dinner.Title + '';
}
function _getDinnerDescriptionHTML(dinner) {
return '<p>' + _getDinnerDate(dinner, "mmmm d, yyyy") + '</p><p>' + dinner.Description + '</p>' + _getRSVPMessage(dinner.RSVPCount);
}
function _dateDeserialize(dateStr) {
return eval('new' + dateStr.replace(/\//g, ' '));
}
function _getRSVPMessage(RSVPCount) {
var rsvpMessage = "" + RSVPCount + " RSVP";
if (RSVPCount > 1)
rsvpMessage += "s";
return rsvpMessage;
}
}
NerdDinner.dragShape = null;
NerdDinner.dragPixel = null;
NerdDinner.EnableMapMouseClickCallback = function () {
NerdDinner._map.AttachEvent("onmousedown", NerdDinner.onMouseDown);
NerdDinner._map.AttachEvent("onmouseup", NerdDinner.onMouseUp);
NerdDinner._map.AttachEvent("onmousemove", NerdDinner.onMouseMove);
}
NerdDinner.onMouseDown = function (e) {
if (e.elementID != null) {
NerdDinner.dragShape = NerdDinner._map.GetShapeByID(e.elementID);
return true;
}
}
NerdDinner.onMouseUp = function (e) {
if (NerdDinner.dragShape != null) {
var x = e.mapX;
var y = e.mapY;
NerdDinner.dragPixel = new VEPixel(x, y);
var LatLong = NerdDinner._map.PixelToLatLong(NerdDinner.dragPixel);
$("#Latitude").val(LatLong.Latitude.toString());
$("#Longitude").val(LatLong.Longitude.toString());
NerdDinner.dragShape = null;
NerdDinner._map.FindLocations(LatLong, NerdDinner.getLocationResults);
}
}
NerdDinner.onMouseMove = function (e) {
if (NerdDinner.dragShape != null) {
var x = e.mapX;
var y = e.mapY;
NerdDinner.dragPixel = new VEPixel(x, y);
var LatLong = NerdDinner._map.PixelToLatLong(NerdDinner.dragPixel);
NerdDinner.dragShape.SetPoints(LatLong);
return true;
}
}
NerdDinner.getLocationResults = function (locations) {
if (locations) {
var currentAddress = $("#Dinner_Address").val();
if (locations[0].Name != currentAddress) {
var answer = confirm("Bing Maps returned the address '" + locations[0].Name + "' for the pin location. Click 'OK' to use this address for the event, or 'Cancel' to use the current address of '" + currentAddress + "'");
if (answer) {
$("#Dinner_Address").val(locations[0].Name);
}
}
}
}

Related

Drag and drop only image upload

Not the file, I want just drag the image with drag and drop.
I thought I would do it according to the extension of the picture but
I have no idea how to do it
example:
*ngIf="list.file.name.split('.').pop() == 'png'"
Can you tell me if there's another way? can you tell us how?
html code:
<div method="post" >
<div (drop)="ondrop($event)" (dragover)="ondragover($event)" (dragend)="ondragend($event)" id="holder1">
<div class="scrollbar style-1">
<div id="fileDragName" class="input-div-image">
<input name="dragAndDrop" (change)="handleFileSelect($event)" id="filesMain" type="file" required="required" multiple="multiple" />
<h3 class="yazi"> Drag and drop or <h3 class="turuncu-renk"> selected file </h3>
</h3>
<li *ngFor="let list of deneme; let i = index">
<div >
{{list.file.name.split('.').slice(0, -1).join('.')}}
</div>
<div id="progress" class="progress-style" >
<p-progressBar *ngIf="list.progressDurumu" [value]="list.percantage"></p-progressBar>
</div>
</div>
</li>
</div>
</div>
</div>
</div>
.ts code:
ondragover(ev) {
const holder = document.getElementById('holder1');
holder.className = 'hover'
return false;
}
ondragend(ev) {
const holder = document.getElementById('holder1');
holder.className = ''
return false;
}
ondrop(e) {
const holder = document.getElementById('holder1');
holder.className = ''
e.preventDefault();
this.readfiles(e.dataTransfer.files);
this.imageUpload();
}
readfiles(files) {
this.files = files;
}
handleFileSelect(evt) {
this.files = evt.target.files;
this.imageUpload();
}
imageUpload() {
setTimeout(() => {
this.progress.percentage = 0;
this.sonuc = this.files;
for (let i = 0; i < this.sonuc.length; i++) {
this.deneme.push({file: this.sonuc[i] , percantage: 0 , output: null });
this.currentFileUpload = this.sonuc[i];
const reader = new FileReader();
reader.onload = (event: any) => {
this.deneme[this.deneme.length - this.sonuc.length + i].output = event.target.result;
};
reader.readAsDataURL(this.sonuc[i]);
this.userService.imageCreate(this.currentFileUpload).subscribe(event => {
if (event.type === HttpEventType.UploadProgress ) {
this.deneme[this.deneme.length - this.sonuc.length + i].percantage = Math.round(event.loaded / event.total * 100 );
} else if (event instanceof HttpResponse ) {
setTimeout(() => {
this.deneme[this.deneme.length - this.sonuc.length + i].progressDurumu = false;
console.log('Upload images!');
}, 500); }
});
}
}, 51);
}

Calling Javascript from dynamic form button in yii2

In Yii2 Dynamic form, I have add-item and remove-item button to add a new row or remove a particular row. What I want is to call a javascript function on click of the remove item button.
Dynamic Form Code -
<?= $form->field($modelsProductsales, "[{$i}]productname")->widget(Select2::classname(), [
'data' => ArrayHelper::map(Productbatch::find()->orderBy('productname')->all(),'productname','productname'),
'language' => 'en',
'options' => ['placeholder' => 'Select Product', 'onchange' => 'getHsndetails($(this))'],
'pluginOptions' => [
'allowClear' => true
],
])->label(false);
?>
<?= $form->field($modelsProductsales, "[{$i}]batchno")->widget(DepDrop::classname(), [
'options' => ['onload' => 'getProdValues($(this))','onchange' => 'getItemID($(this))'],
'pluginOptions'=>[
'depends'=> [Html::getInputID($modelsProductsales, "[{$i}]productname")],
'placeholder'=>'Batch',
'url'=>Url::to(['/invoice/bills/subcat'])
]
])->label(false); ?>
<?= $form->field($modelsProductsales, "[{$i}]expdate")->label(false)->textInput(['maxlength' => true,'placeholder' => 'ExpDate','readOnly'=>true]) ?>
<?= $form->field($modelsProductsales, "[{$i}]mrp")->label(false)->textInput(['maxlength' => true,'class' => 'mrp','placeholder' => 'MRP']) ?>
<?= $form->field($modelsProductsales, "[{$i}]rate")->label(false)->textInput(['maxlength' => true,'class' => 'rate','placeholder' => 'Rate']) ?>
<?= $form->field($modelsProductsales, "[{$i}]qty")->label(false)->textInput(['maxlength' => true,'class' => 'qty','placeholder' => 'Qty']) ?>
<?= $form->field($modelsProductsales, "[{$i}]free")->label(false)->textInput(['maxlength' => true,'class' => 'free','placeholder' => 'Free']) ?>
<?= $form->field($modelsProductsales, "[{$i}]discount")->label(false)->textInput(['maxlength' => true,'class' => 'disc','placeholder' => 'Discount']) ?>
<div class="pull-right">
<button type="button" class="add-item btn btn-success btn-xs"><i class="glyphicon glyphicon-plus"></i></button>
<button type="button" class="remove-item btn btn-danger btn-xs"><i class="glyphicon glyphicon-minus"></i></button>
</div>
Javascript function
<?php
/* start getting the total amount */
$this->registerJs('
function getSum() {
var retailPrice = 0;
var stockistPrice = 0;
var sum = 0;
var totalDiscount = 0;
var totalMrp = 0;
var totalCst = 0;
var totalWbst = 0;
var totalCstonamount = 0;
var totalWbstonamount = 0;
var totalCstonmrp = 0;
var totalWbstonmrp = 0;
var totalTaxonmrp = 0;
var totalTaxonamount = 0;
var totalAmountonmrp = 0;
var totalAmountonrate = 0;
var totalBillamountonmrp = 0;
var totalBillamountonrate = 0;
var igstAmount = 0;
var cgstAmount = 0;
var sgstAmount = 0;
var cstperValue = $(".cstPercent").val();
var wbstperValue = $(".wbstPercent").val();
var selectedValue = $("input[name=taxon]:checked").val();
//alert(selectedValue);
var items = $(".item");
items.each(function (index, elem) {
var qtyValue = $(elem).find(".qty").val();
var rateValue = $(elem).find(".rate").val();
var discValue = $(elem).find(".disc").val();
var mrpValue = $(elem).find(".mrp").val();
var freeValue = $(elem).find(".free").val();
var igstPercent = $(elem).find(".igstrate").val();
var cgstPercent = $(elem).find(".cgstrate").val();
var sgstPercent = $(elem).find(".sgstrate").val();
cgstAmount = (parseFloat(cgstAmount) + ((parseFloat(qtyValue)*parseFloat(rateValue) - (parseFloat(qtyValue)*parseFloat(rateValue)*parseFloat(discValue))/100)*parseFloat(cgstPercent))/100).toFixed(2);
sgstAmount = (parseFloat(sgstAmount) + ((parseFloat(qtyValue)*parseFloat(rateValue) - (parseFloat(qtyValue)*parseFloat(rateValue)*parseFloat(discValue))/100)*parseFloat(sgstPercent))/100).toFixed(2);
igstAmount = (parseFloat(igstAmount) + ((parseFloat(qtyValue)*parseFloat(rateValue) - (parseFloat(qtyValue)*parseFloat(rateValue)*parseFloat(discValue))/100)*parseFloat(igstPercent))/100).toFixed(2);
stockistPrice = (parseFloat(stockistPrice) + (parseFloat(rateValue)*parseFloat(qtyValue) - (parseFloat(rateValue)*parseFloat(qtyValue)*parseFloat(discValue))/100)).toFixed(2);
sum = Math.round(parseFloat(stockistPrice) + parseFloat(cgstAmount) + parseFloat(sgstAmount) + parseFloat(igstAmount));
});
if(isNaN(sum) || sum.length == 0) {
sum = 0;
}
if(isNaN(cgstAmount) || cgstAmount.length == 0) {
cgstAmount = 0;
}
if(isNaN(sgstAmount) || sgstAmount.length == 0) {
sgstAmount = 0;
}
if(isNaN(igstAmount) || igstAmount.length == 0) {
igstAmount = 0;
}
if(isNaN(stockistPrice) || stockistPrice.length == 0) {
stockistPrice = 0;
}
$(".sum").val(sum);
$(".cgstAmount").val(cgstAmount);
$(".sgstAmount").val(sgstAmount);
$(".igstAmount").val(igstAmount);
$(".totalAmount").val(stockistPrice);
$(".billAmount").val(sum);
$(".overdueAmount").val(sum);
}
$(".container-items").on("change", function() {
getSum();
});
$(".remove-item").on("click", function() {
getSum();
alert("This Onclick is working");
});
');
/*end getting the total amount */
?>
On Change of the items, the javascript is being called and I'm getting the value. But on Click of the remove-item button, the javascript is not getting called. Please let me know what to do to call the javascript onclick of the remove-item button.
There's no error in the console.
If the adding and removing the fields are the only functions that are only manipulating the form then you can use the new MutationObserver to track if any new elements were added or removed from the target container.
This new DOM Api is available in Firefox and Webkit nightly builds, as well as Chrome 18.
The key advantage to this new specification over the deprecated DOM
Mutation Events spec is one of efficiency. If you are observing a node
for changes, your callback will not be fired until the DOM has
finished changing. When the callback is triggered, it is supplied a
list of the changes to the DOM, which you can then loop through and
choose to react to.
This also means that any code you write will need to process the
observer results in order to react to the changes you are looking for.
Consider the following example which adds and removes divs inside a container div using the add and remove buttons, and i use MutationObserver to look for the changes in the target element #container and update the div count inside the callback function after checking the the Mutation Event is for the ChildList which is triggered when you add or remove the child elements from the target container.
function startObserver() {
// select the target node
var target = document.querySelector('#container');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type == 'childList') {
$('.counter').html($("#container>div").length + ' div(s) total');
}
});
});
// configuration of the observer:
var config = {
childList: true,
}
// pass in the target node, as well as the observer options
observer.observe(target, config);
}
jQuery(function($) {
$("#add-more").on("click", function() {
$("#container").append("<div>some thing " + Math.random() + "</div>")
})
$("#remove").on("click", function() {
$("#container>div:eq(0)").remove()
});
startObserver();
});
.counter {
float: right;
font-size: 2em;
color: red;
margin-right: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="section"><button id="add-more">add more</button>
<button id="remove">Remove</button>
<div class="counter">0 div(s) total</div>
<div id='container'>
</div>
What you need to do is to wrap the form inside a div and provide it an id say container and add the call to the function getSum() inside the callback function you can copy the below code.
$this->registerJs("// select the target node
var target = document.querySelector('#container');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type == 'childList') {
getSum();
}
});
});
// configuration of the observer:
var config = { childList: true};
// pass in the target node, as well as the observer options
observer.observe(target, config);
", yii\web\View::POS_READY);
NOTE: Remove any other calls to the getSum() function if you have added it to any other event like below
$(".remove-item").on("click", function() {
getSum();
alert("This Onclick is working");
});
Hope this helps you sort the problem.

Works on IE but Chrome & Firefox not

My JavaScript:
var bossId = $('#BossId');
var date = $('#divDate');
var headDate = $('#HeadShipDate');
var select = '-- Select --';
bossId.change(function () {
if ( bossId.find(':selected').text() != select )
date.show();
else {
date.hide();
headDate.val('');
}
});
My View:
#Html.DropDownList(
"BossId", null, "-- Select --",
htmlAttributes: new { #class = "form-control" }
)
<div id="divDate" class="form-group" style="display:none">
#Html.EditorFor(
model => model.HeadShipDate,
new { htmlAttributes = new { #class = "form-control" } }
)
Per the title, this script works fine on Internet Explorer, but not in Chrome & Firefox. How can I Solve this?

Google places api not returning postal code for some places

I have a form which would collect location information from the user. I'm using Google places api to autocomplete the location information. It works great. Everything got filled out nicely however there are some places (e.g. my workplace which is a building), Google does not return a postal code for it.
I followed this example from Google address autocomplete. It also doesn't return postal code for my workplace. So I'm not entire sure what I did wrong.
Below is my code:
HTML
<div id="location-autocomplete" style="display: none;">
<div class="half-formfield">
#Html.LabelFor(x => x.Address)
#Html.TextBoxFor(x => x.Address, new { #class = "two-third-field", id = "street_number", required = "required" })
</div>
<div>
#Html.LabelFor(x => x.UnitNumber, new { value = "Unit Number" })
#Html.TextBoxFor(x => x.UnitNumber, new { #class = "one-third-field" })
</div>
<div class="half-formfield">
#Html.LabelFor(x => x.City)
#Html.TextBoxFor(x => x.City, new { #class = "half-field", required = "required", id = "locality" })
</div>
<div>
#Html.LabelFor(x => x.ProvinceOrState)
#Html.TextBoxFor(x => x.ProvinceOrState, new { #class = "half-field", required = "required", id = "administrative_area_level_1" })
</div>
<div class="half-formfield">
#Html.LabelFor(x => x.ZipOrPostalCode)
#Html.TextBoxFor(x => x.ZipOrPostalCode, new { #class = "half-field", required = "required", id = "postal_code" })
</div>
<div>
#Html.LabelFor(x => x.Country)
#Html.TextBoxFor(x => x.Country, new { #class = "half-field", required = "required", id = "country" })
</div>
<input type="button" value="Clear Address" onclick="clearAddress()" id="clear-btn" class="service-form-btn"/>
JS
var placeSearch, autocomplete;
var componentForm = {
street_number: 'short_name',
route: 'long_name',
locality: 'long_name',
administrative_area_level_1: 'short_name',
country: 'long_name',
postal_code: 'short_name'
};
function initialize() {
// Create the autocomplete object, restricting the search
// to geographical location types.
autocomplete = new google.maps.places.Autocomplete(
/** #type {HTMLInputElement} */(document.getElementById('autocomplete')),
{ types: ['geocode'] });
// When the user selects an address from the dropdown,
// populate the address fields in the form.
google.maps.event.addListener(autocomplete, 'place_changed', function () {
fillInAddress();
showAddressComponent();
setTimeout(hideAddressSearch, 800);
});
}
function fillInAddress() {
// Get the place details from the autocomplete object.
var place = autocomplete.getPlace();
for (var component in componentForm) {
if (component != "route") {
document.getElementById(component).value = '';
document.getElementById(component).disabled = false;
}
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (var i = 0; i < place.address_components.length; i++) {
var addressType = place.address_components[i].types[0];
if (componentForm[addressType]) {
var val = place.address_components[i][componentForm[addressType]];
console.log(val);
if (addressType != "route") document.getElementById(addressType).value = val;
else if (addressType == "route") document.getElementById("street_number").value = document.getElementById("street_number").value + " " + val;
}
}
}
// Bias the autocomplete object to the user's geographical location,
// as supplied by the browser's 'navigator.geolocation' object.
function geolocate() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
var geolocation = new google.maps.LatLng(
position.coords.latitude, position.coords.longitude);
autocomplete.setBounds(new google.maps.LatLngBounds(geolocation,
geolocation));
});
}
}
Screenshot
I wonder if this is a bug or simply Google doesn't know the postal code of the building. In that case, is there simply any work around this?
Thanks in advance.
There is a postal code for this address, but only a part (I guess it's called FSA-code).
The function didn't recognize this part, because for this address the returned types-array is:
["postal_code_prefix", "postal_code"]
...but the function only checks the first item of the types-array.
possible fix:
function fillInAddress() {
// Get the place details from the autocomplete object.
var place = autocomplete.getPlace();
for (var component in componentForm) {
document.getElementById(component).value = '';
document.getElementById(component).disabled = false;
}
// Get each component of the address from the place details
// and fill the corresponding field on the form.
for (var i = 0; i < place.address_components.length; i++) {
var addressTypes = place.address_components[i].types,addressType,val;
for(var j=0;j<addressTypes.length;++j){
addressType=addressTypes[j];
if (componentForm[addressType]) {
val = place.address_components[i][componentForm[addressType]];
document.getElementById(addressType).value = val;
break;
}
}
}
}
Hope this will explore more ideas.
function initDefaultAutoCompleteFunction() {
var objAddress = document.getElementsByClassName('autocomplete-address');
$(objAddress).each(function (index, address) {
if (typeof (address) != 'undefined' && address != null) {
let options = {
types: ['address'],
Fields: ['address_component', 'formatted_address'],
componentRestrictions: { country: ['us', 'ca'] }
};
let autocomplete = new google.maps.places.Autocomplete(address, options);
autocomplete.addListener('place_changed', function () {
debugger;
let place = autocomplete.getPlace();
if (place) {
let zipOrPostalCode = null; // or set empty etc.
$.each(place.address_components, function (index, value) {
let addressType = value.types[0];
if (addressType == 'street_number') {
// value.short_name; //this is your street number
}
if (addressType == 'route') {
// value.short_name; //this is your route
}
if (addressType == 'postal_code' || addressType == "postal_code_prefix") {
// value.short_name; //this is your postal_code
}
});
}
});
}
});
}
var location = place.geometry.location;
var lat = location.lat();
var lng = location.lng();
var latlng = {lat: lat, lng: lng};
geocoder.geocode({'location': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (results[0]) {
for (var i = 0; i < results[0].address_components.length; i++) {
var types = results[0].address_components[i].types;
for (var typeIdx = 0; typeIdx < types.length; typeIdx++) {
if (types[typeIdx] == 'postal_code') {
//console.log(results[0].address_components[i].long_name);
var pincode = results[0].address_components[i].short_name;
alert('pin'+pincode);
}
}
}
$('#pac-input2').val(results[0].formatted_address);
infowindow.setContent(results[0].formatted_address);
//infowindow.open(map, marker);
}
}
});

Add search filter inside the select dropdown in AngularJS

I want to add a search filter inside a select dropdown in angularJS.
I have used ng-options to list down the options and used filter to filter out the data in the search box , but the problem is that the search box is not coming inside(or under) select dropdown. (When I click the select dropdown, it shows a search filter and below it has all the options)
Below is the code for your reference :
<div class="rowMargin">
<label class="control-label" for="entitySel">Entity:</label>
<div class="controls">
<select id="entityId" class="input-medium" type="text" name="entityId" ng-model="payment.entityId" ng-options="entityOpt for entityOpt in paymentEntityOptions">
<option value="">Select</option>
</select>
<span ng-show=" submitted && addPayment.entityId.$error.required">
<label class="error">Please provide entity Id </label>
</span>
<div ng-show="payment.entityId == \'Individual\'">
<span>
<select ng-model="payment.entity.individual" ng-options = "individual for individual in individualEntities | filter : filterEntity">
<option value="">Select Individual Entity</option>
<option>
<input type="search" placeholder="Search" ng-model="filterEntity"></input>
</option>
</select>
</span>
</div>
<div ng-show="payment.entityId == \'Group\'">
<span>
<select ng-model="payment.entity.group" ng-options = "group for group in groupEntities | filter : filterEntity">
<option value="">Select Group Entity</option>
<input type="search" placeholder="Search" ng-model="filterEntity"></input>
</select>
</span>
</div>
</div>
I have used the bootstrap button with class 'dropdown-toggle' and on click of the button I have appended an input search box as following :
<div class="dropdown pull-right makePaymentDropdownMainDiv" auto-close="outsideClick">
<button class="btn btn-default dropdown-toggle makePaymentDropdownBtn" type="button" id="individualDrop" data-toggle="dropdown">{{payment.entity}}<span class="caret pull-right"></span></button>
<span ng-show="submitted"><label class="error">Select an Individual</label></span>
<ul class="dropdown-menu makePaymentDropdownUlStyle" role="menu" aria-labelledby="individualDrop">
<input disable-auto-close type="search" ng-model="serchFilter" class="makePaymentDropdownSearchBox" placeholder="Search"></input>
<li role="presentation" ng-repeat="indi in individuals | filter: serchFilter"><a role="menuitem" ng-click="selectEntity(indi)">{{indi}}</a></li>
</ul>
</div>
Showing the 'li' using ng-repeat.
Remember to add auto-close="outsideClick" to your dropdown so that it doesn't close on filtering attempt.
Sorry, I'm rather late to the party, but to me it sounds like you need acute-select, an open source extension (MIT license) to Angular that does exactly this, without further dependencies.
They also have a demo page, which shows what it can do nicely.
you can use easy and best way to search filter inside the select dropdown in AngularJS
Working Demo : http://plnkr.co/edit/o767Mg6fQoyc7jKq77If?p=preview
(function (angular, undefined) {
'use strict';
// TODO: Move to polyfill?
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g, '');
};
}
/**
* A replacement utility for internationalization very similar to sprintf.
*
* #param replace {mixed} The tokens to replace depends on type
* string: all instances of $0 will be replaced
* array: each instance of $0, $1, $2 etc. will be placed with each array item in corresponding order
* object: all attributes will be iterated through, with :key being replaced with its corresponding value
* #return string
*
* #example: 'Hello :name, how are you :day'.format({ name:'John', day:'Today' })
* #example: 'Records $0 to $1 out of $2 total'.format(['10', '20', '3000'])
* #example: '$0 agrees to all mentions $0 makes in the event that $0 hits a tree while $0 is driving drunk'.format('Bob')
*/
function format(value, replace) {
if (!value) {
return value;
}
var target = value.toString();
if (replace === undefined) {
return target;
}
if (!angular.isArray(replace) && !angular.isObject(replace)) {
return target.split('$0').join(replace);
}
var token = angular.isArray(replace) && '$' || ':';
angular.forEach(replace, function (value, key) {
target = target.split(token + key).join(value);
});
return target;
}
var module = angular.module('AxelSoft', []);
module.value('customSelectDefaults', {
displayText: 'Select...',
emptyListText: 'There are no items to display',
emptySearchResultText: 'No results match "$0"',
addText: 'Add',
searchDelay: 300
});
module.directive('customSelect', ['$parse', '$compile', '$timeout', '$q', 'customSelectDefaults', function ($parse, $compile, $timeout, $q, baseOptions) {
var CS_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, elem, attrs, controller) {
var customSelect = attrs.customSelect;
if (!customSelect) {
throw new Error('Expected custom-select attribute value.');
}
var match = customSelect.match(CS_OPTIONS_REGEXP);
if (!match) {
throw new Error("Expected expression in form of " +
"'_select_ (as _label_)? for _value_ in _collection_[ track by _id_]'" +
" but got '" + customSelect + "'.");
}
elem.addClass('dropdown custom-select');
// Ng-Options break down
var displayFn = $parse(match[2] || match[1]),
valueName = match[3],
valueFn = $parse(match[2] ? match[1] : valueName),
values = match[4],
valuesFn = $parse(values),
track = match[5],
trackByExpr = track ? " track by " + track : "",
dependsOn = attrs.csDependsOn;
var options = getOptions(),
timeoutHandle,
lastSearch = '',
focusedIndex = -1,
matchMap = {};
var itemTemplate = elem.html().trim() || '{{' + (match[2] || match[1]) + '}}',
dropdownTemplate =
'<a class="dropdown-toggle" data-toggle="dropdown" href ng-class="{ disabled: disabled }">' +
'<span>{{displayText}}</span>' +
'<b></b>' +
'</a>' +
'<div class="dropdown-menu">' +
'<div stop-propagation="click" class="custom-select-search">' +
'<input class="' + attrs.selectClass + '" type="text" autocomplete="off" ng-model="searchTerm" />' +
'</div>' +
'<ul role="menu">' +
'<li role="presentation" ng-repeat="' + valueName + ' in matches' + trackByExpr + '">' +
'<a role="menuitem" tabindex="-1" href ng-click="select(' + valueName + ')">' +
itemTemplate +
'</a>' +
'</li>' +
'<li ng-hide="matches.length" class="empty-result" stop-propagation="click">' +
'<em class="muted">' +
'<span ng-hide="searchTerm">{{emptyListText}}</span>' +
'<span class="word-break" ng-show="searchTerm">{{ format(emptySearchResultText, searchTerm) }}</span>' +
'</em>' +
'</li>' +
'</ul>' +
'<div class="custom-select-action">' +
(typeof options.onAdd === "function" ?
'<button type="button" class="btn btn-primary btn-block add-button" ng-click="add()">{{addText}}</button>' : '') +
'</div>' +
'</div>';
// Clear element contents
elem.empty();
// Create dropdown element
var dropdownElement = angular.element(dropdownTemplate),
anchorElement = dropdownElement.eq(0).dropdown(),
inputElement = dropdownElement.eq(1).find(':text'),
ulElement = dropdownElement.eq(1).find('ul');
// Create child scope for input and dropdown
var childScope = scope.$new(true);
configChildScope();
// Click event handler to set initial values and focus when the dropdown is shown
anchorElement.on('click', function (event) {
if (childScope.disabled) {
return;
}
childScope.$apply(function () {
lastSearch = '';
childScope.searchTerm = '';
});
focusedIndex = -1;
inputElement.focus();
// If filter is not async, perform search in case model changed
if (!options.async) {
getMatches('');
}
});
if (dependsOn) {
scope.$watch(dependsOn, function (newVal, oldVal) {
if (newVal !== oldVal) {
childScope.matches = [];
childScope.select(undefined);
}
});
}
// Event handler for key press (when the user types a character while focus is on the anchor element)
anchorElement.on('keypress', function (event) {
if (!(event.altKey || event.ctrlKey)) {
anchorElement.click();
}
});
// Event handler for Esc, Enter, Tab and Down keys on input search
inputElement.on('keydown', function (event) {
if (!/(13|27|40|^9$)/.test(event.keyCode)) return;
event.preventDefault();
event.stopPropagation();
switch (event.keyCode) {
case 27: // Esc
anchorElement.dropdown('toggle');
break;
case 13: // Enter
selectFromInput();
break;
case 40: // Down
focusFirst();
break;
case 9:// Tab
anchorElement.dropdown('toggle');
break;
}
});
// Event handler for Up and Down keys on dropdown menu
ulElement.on('keydown', function (event) {
if (!/(38|40)/.test(event.keyCode)) return;
event.preventDefault();
event.stopPropagation();
var items = ulElement.find('li > a');
if (!items.length) return;
if (event.keyCode == 38) focusedIndex--; // up
if (event.keyCode == 40 && focusedIndex < items.length - 1) focusedIndex++; // down
//if (!~focusedIndex) focusedIndex = 0;
if (focusedIndex >= 0) {
items.eq(focusedIndex)
.focus();
} else {
focusedIndex = -1;
inputElement.focus();
}
});
resetMatches();
// Compile template against child scope
$compile(dropdownElement)(childScope);
elem.append(dropdownElement);
// When model changes outside of the control, update the display text
controller.$render = function () {
setDisplayText();
};
// Watch for changes in the default display text
childScope.$watch(getDisplayText, setDisplayText);
childScope.$watch(function () { return elem.attr('disabled'); }, function (value) {
childScope.disabled = value;
});
childScope.$watch('searchTerm', function (newValue) {
if (timeoutHandle) {
$timeout.cancel(timeoutHandle);
}
var term = (newValue || '').trim();
timeoutHandle = $timeout(function () {
getMatches(term);
},
// If empty string, do not delay
(term && options.searchDelay) || 0);
});
// Support for autofocus
if ('autofocus' in attrs) {
anchorElement.focus();
}
var needsDisplayText;
function setDisplayText() {
var locals = { };
locals[valueName] = controller.$modelValue;
var text = displayFn(scope, locals);
if (text === undefined) {
var map = matchMap[hashKey(controller.$modelValue)];
if (map) {
text = map.label;
}
}
needsDisplayText = !text;
childScope.displayText = text || options.displayText;
}
function getOptions() {
return angular.extend({}, baseOptions, scope.$eval(attrs.customSelectOptions));
}
function getDisplayText() {
options = getOptions();
return options.displayText;
}
function focusFirst() {
var opts = ulElement.find('li > a');
if (opts.length > 0) {
focusedIndex = 0;
opts.eq(0).focus();
}
}
// Selects the first element on the list when the user presses Enter inside the search input
function selectFromInput() {
var opts = ulElement.find('li > a');
if (opts.length > 0) {
var ngRepeatItem = opts.eq(0).scope();
var item = ngRepeatItem[valueName];
childScope.$apply(function () {
childScope.select(item);
});
anchorElement.dropdown('toggle');
}
}
function getMatches(searchTerm) {
var locals = { $searchTerm: searchTerm }
$q.when(valuesFn(scope, locals)).then(function (matches) {
if (!matches) return;
if (searchTerm === inputElement.val().trim()/* && hasFocus*/) {
matchMap = {};
childScope.matches.length = 0;
for (var i = 0; i < matches.length; i++) {
locals[valueName] = matches[i];
var value = valueFn(scope, locals),
label = displayFn(scope, locals);
matchMap[hashKey(value)] = {
value: value,
label: label/*,
model: matches[i]*/
};
childScope.matches.push(matches[i]);
}
//childScope.matches = matches;
}
if (needsDisplayText) setDisplayText();
}, function() {
resetMatches();
});
}
function resetMatches() {
childScope.matches = [];
focusedIndex = -1;
};
function configChildScope() {
childScope.addText = options.addText;
childScope.emptySearchResultText = options.emptySearchResultText;
childScope.emptyListText = options.emptyListText;
childScope.select = function (item) {
var locals = {};
locals[valueName] = item;
var value = valueFn(childScope, locals);
//setDisplayText(displayFn(scope, locals));
childScope.displayText = displayFn(childScope, locals) || options.displayText;
controller.$setViewValue(value);
anchorElement.focus();
typeof options.onSelect === "function" && options.onSelect(item);
};
childScope.add = function () {
$q.when(options.onAdd(), function (item) {
if (!item) return;
var locals = {};
locals[valueName] = item;
var value = valueFn(scope, locals),
label = displayFn(scope, locals);
matchMap[hashKey(value)] = {
value: value,
label: label/*,
model: matches[i]*/
};
childScope.matches.push(item);
childScope.select(item);
});
};
childScope.format = format;
setDisplayText();
}
var current = 0;
function hashKey(obj) {
if (obj === undefined) return 'undefined';
var objType = typeof obj,
key;
if (objType == 'object' && obj !== null) {
if (typeof (key = obj.$$hashKey) == 'function') {
// must invoke on object to keep the right this
key = obj.$$hashKey();
} else if (key === undefined) {
key = obj.$$hashKey = 'cs-' + (current++);
}
} else {
key = obj;
}
return objType + ':' + key;
}
}
};
}]);
module.directive('stopPropagation', function () {
return {
restrict: 'A',
link: function (scope, elem, attrs, ctrl) {
var events = attrs['stopPropagation'];
elem.bind(events, function (event) {
event.stopPropagation();
});
}
};
});
})(angular);
<body ng-app="Demo">
<div class="container" ng-controller="DemoController">
<label>Level 1</label>
<div custom-select="g for g in nestedItemsLevel1 | filter: $searchTerm" custom-select-options="level1Options" ng-model="level1"></div>
<label>Level 2</label>
<div custom-select="g for g in nestedItemsLevel2 | filter: $searchTerm" ng-model="level2" cs-depends-on="level1"></div>
</div>
<!-- basic scripts -->
<!--[if !IE]> -->
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<!-- <![endif]-->
<!--[if IE]>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<![endif]-->
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="js/customSelect.js"></script>
<script>
(function () {
var app = angular.module('Demo', ['AxelSoft']);
app.controller('DemoController', ['$scope', '$timeout', '$q', function ($scope, $timeout, $q) {
$scope.searchAsync = function (term) {
// No search term: return initial items
if (!term) {
return ['Item 1', 'Item 2', 'Item 3'];
}
var deferred = $q.defer();
$timeout(function () {
var result = [];
for (var i = 1; i <= 3; i++)
{
result.push(term + ' ' + i);
}
deferred.resolve(result);
}, 300);
return deferred.promise;
};
$scope.nestedItemsLevel1 = ['Item 1', 'Item 2', 'Item 3'];
$scope.level1 = $scope.nestedItemsLevel1[0];
$scope.level1Options = {
onSelect: function (item) {
var items = [];
for (var i = 1; i <= 5; i++) {
items.push(item + ': ' + 'Nested ' + i);
}
$scope.nestedItemsLevel2 = items;
}
};
$scope.nestedItemsLevel2 = [];
$scope.level1Options.onSelect($scope.nestedItemsLevel1[0]);
}]);
})();
</script>
</body>
https://docs.angularjs.org/api/ng/directive/select
There can be only one hard coded in a ngOption.