Jquery load file and auto select the option after files load - javascript

$(document).ready(function(){
$("#country").load("country.php",function(){
//Select the option from DB
$('#country').val("<?PHP echo $country;?>");
//Load state option list
switch($("#country").val()){
case "aus":$("#state").load("aus_state.php",function(){
$('#state').val("<?PHP echo $state;?>");
switch($("#state").val()){
case "aus_ACT":$("#location").load("aus_ACT.php",function(){
$('#location').val("<?PHP echo $location;?>");
...
});break
case "aus_NSW":$("#location").load("aus_NSW.php");break
case "aus_NT":$("#location").load("aus_NT.php");break
case "aus_QLD":$("#location").load("aus_QLD.php");break
case "aus_SA":$("#location").load("aus_SA.php");break
case "aus_TAS":$("#location").load("aus_TAS.php");break
case "aus_VIC":$("#location").load("aus_VIC.php");break
case "aus_WA":$("#location").load("aus_WA.php");break
}
});break
case "eng":$("#state").load("eng_countie.php",function(){
...
});break
case "usa":$("#state").load("us_state.php",function(){
...
});break
}
});
});
I hava a dynamic drop down select option.
[country]->[state]->[location]
I use jquery load the option list. However I need to auto select the option list for user to update. ex. [usa]->[CA]->[LA]
I put a function after the files load, .load(file.php, function(){...})
$('country').val("<?PHP echo data from DB; ?>")
switch state option list depend what value from DB...
Since I have a lots of sub list, this will be very hard to editing. Is any better way to do this?
something like
$("#country").val("<?PHP echo $country;?>").change(function(){
switch($("#country").val()){
case "aus":$("#state").load("aus_state.php");break
case "eng":$("#state").load("eng_countie.php");break
case "usa":$("#state").load("us_state.php");break
}
});
$("#state").val("<?PHP echo $state;?>").change(function(){
switch($("#state").val()){
case "aus_ACT":$("#location").load("aus_ACT.php");break
//...Put all countries's states here
}
});
it's complex, I try my best to explain

You can build maps to identify state page (aus_state.php) from country code (aus), location page from state code, and some necessary deeper mappings. These maps can be constructed either from database or your project structure.
var mapping = {
country_state: {
aus: 'aus_state.php',
eng: 'eng_countie.php',
usa: 'us_state.php'
},
state_location: {
aus_ACT: 'aus_ACT.php',
aus_NSW: 'aus_NSW.php',
...
// it seems that the state code has a country prefix
// so you can merge all countries' locations in a map.
usa_CA: 'usa_CA.php',
}
};
Rather than create all the JS code dynamically, you can write the static part in functions in a separate JS file and only use PHP to generate the changing part. And here only country/state/location changes. You can put the code at the bottom of your HTML page so that it get evaluated and initialized before the $(document).ready handler.
var selection_state = {
country: "<?PHP echo $country;?>",
state: "<?PHP echo $state;?>",
location: "<?PHP echo $location;?>"
};
Rewrite the loading/selecting logic in a separate JS file and load it in the HTML page with <script src="..."></script> tag.
$(function () {
$('#country').load('country.php', function () {
$('#country').val(selection_state.country);
if (! mapping.country_state[selection_state.country])
return;
$('#state').load(mapping.country_state[selection_state.country], function () {
$('#state').val(selection_state.state);
if (! mapping.state_location[selection_state.state])
return;
$('#location').load(mapping.state_location[selection_state.state], function () {
$('#location').val(selection_state.location);
});
});
});
});
It seems that it's unnecessary that the loading of country/state/location to be sequential. You can perform the loading in parallel. (The code bellow has better performance but would have different behavior with the former one when some list failed to load.)
$(function () {
$('#country').load('country.php', function () {
$('#country').val(selection_state.country);
});
if (mapping.country_state[selection_state.country]) {
$('#state').load(mapping.country_state[selection_state.country], function () {
$('#state').val(selection_state.state);
});
}
if (mapping.state_location[selection_state.state]) {
$('#location').load(mapping.state_location[selection_state.state], function () {
$('#location').val(selection_state.location);
});
}
});
PS. For step 1, rather than requesting different page for different country/state, I think it's better to request only two pages to fetch the states/locations and pass the country code / state code as parameters. E.g. request country_state.php?country=aus for all the states in Australia(?). This will simplify the logic at both server and client side, and you will get cleaner project structure. With mod_rewrite, you can bind request of aus_state.php to country_state.php?country=aus, if necessary.

Related

How to update innerhtml of multiple divs from C# code behind?

I managed to execute C# functions which returns a serialized string for a div's InnerHtml using unobtrusive approach.
<script>
$("#btnSubmit").click(function(){
bal.innerHTML = <%=ToInternalHTML()%>;
</scrtipt>
But there are multiple divs that needs innerhtml to be written based on the database data from code behind C#. So I want to use the same server-side function ToInternalHTML(). It's currently returning a string. But what I need is to write innerHtml to the specific divs from server-side in this function and execute this function from javascript.
foreach (DataRow row in table.Rows)
{
string rType = row[0].ToString();
sbhtml.Append(#"<div><a href=""#""class=""item""><p>");
sbhtml.Append(row[1].ToString());
sbhtml.Append("</p></a></div>");
switch (rType)
{
case "Clinical":
bal.InnerHtml = (new JavaScriptSerializer()).Serialize(sbhtml);
break;
case "Rehab":
rom.InnerHtml = (new JavaScriptSerializer()).Serialize(sbhtml);
break;
}
}
Can this be done? If so how to do so?
You cannot use server-side function to affect your page when it is already complete. Simply said, ASP.NET generates a page, sends it to your browsers and forgets about it.
If you want to fill a data in ASP.NET view's divs, you can do this in several ways.
During ASP.NET View generation
You don't need a StringBuilder or something else to form HTML elements. Use the following approach:
foreach (DataRow row in table.Rows)
{
<div>
<a href="#" class="item">
<p>row[1].ToString()</p>
</a>
</div>
/* Generate any divs here. Add any data from your table.Rows etc. */
}
Here is one, already generated. If you run this page you will as many divs with data as you have rows in table.Rows
Using Ajax.
// C# controller
public class MyController : Controller
{
public ActionResult Index()
{
return View();
}
public JsonResult GetData()
{
YourEntity[] data = GetFromSomewhere();
return new JsonResult(Data = data, JsonRequestBehaviour = JsonRequestBehaviour.AllowGet);
}
}
// JS script
$(document).ready(function()
{
$.ajax({
url: '#Url.Action("GetData")',
type: 'GET'
}).done(function(data){
$.each(data, function()
{
var yourEntity = this;
// Manipulate with DOM here. Change inner HTML of div or append it
var div = $("<div></div>");
$(div).text(yourEntity.Id);
$("body").append(div);
});
});

use jquery variable in # block razor

I'm strugling with a jquery script inside a cshtml page. For short my question is how to use a var inside a # statement in a cshtml page?
below an example of what I'm trying:
<select id="DefaultText">
<option value="-1">-- select --</option>
#foreach( var d in Model.DefaultTexts )
{
<option value="#d.Id" >#d.Name</option>
}
</select>
<script type="text/javascript">
$('#DefaultText').change(function () {
var id = parseInt($('#DefaultText :selected').val());
var text = #Model.DefaultTexts.First( t => t.Id == id );
$('#CustomProductText').val(text);
});
</script>
I can't reach the var id. It's out of scope. I've also tryed it with a for loop and a if statement. But in the if statement I get the same error: out of scope.
The full story is this:
On my page I've a dropdown list. The items to select are short names for default text parts. Based on the id or name, I want to show the default text part in a textbox.
#CustomProductText is my textbox where the content should be placed (code not posted).
I've also tryed it with #: and statement but that did not work.
What am I doing wrong or maybe its not even possible what I'm trying to do.
As an alternative I've added a action to my controller to get the text form there. Below the code:
<script type="text/javascript">
$('#DefaultText').change(function () {
var id = parseInt($('#DefaultText :selected').val());
$.post("Categories/GetDefaultText", { Id: id }, function (data) {
alert(data);
});
//$('#CustomProductText').val(text);
});
</script>
controller code:
[HttpPost]
public ActionResult GetDefaultText(int id)
{
using( var context = new MyContext() )
{
var text = context.DefaultText.First( d => d.Id == id ).Text;
return this.Content( text );
}
}
This doesn't work. The action doesn't get hit in debug mode.
regards,
Daniel
The $.post that is not working for you, you should prefix the url with / sign and it will be hit as expected:
$.post("/Categories/GetDefaultText", { Id: id }, function (data) {
alert(data);
});
As for the razor solution, you can't use javascript variables in the razor code as it's not a scripting language. What razor does is simply rendering the strings (be it html or javascript or anything) into the page.
To do what you want you either need to request the server to pass the text to your page or render all the texts you have in the page and then access this rendered content in your javascript.

Zend forms working with ajax/javascript onchange event

I am writing a code to use onchange in my application this is my code so far
.Phtml
<script type="text/javascript">
function submit()
{
$id = intval($_GET['id']);
$satellite = intval($_GET['satellite_id']);
if ($id == 0)
{
echo "Please select a Region";
}
else
{
$query = "select * from satellites where region_id = '".$id."'";
$query = mysql_query($query);
echo "<select name='satellite_id'><option value=''>-- select one --</option>";
while ($row = mysql_fetch_assoc($query))
{
echo "<option value='".$row['satellite_id']."'".($row['satellite_id']==$satellite?" selected":"").">".$row['satellite_name']."</option>";
}
echo "</select>";
//DisplayFormRow ("Satellite", FormDropDownBox ("satellite_id", $SatelliteARY, $Result['satellite_id']));
}
}
</script
//zend code Form
$region_name = new Zend_Form_Element_Select('region_name');
$region_name->setAttribs(array('style' => 'width: 150px;'));
$region_name ->setLabel('Region')
->onchange('this.form.submit();') //tried this code ->onchange('javascript:submit();')
->addMultiOption('--Select One--', '--Select One--');
$mdlRegions = new Model_Regions();
$regions = $mdlRegions->getRegions();
foreach ($regions as $region)
{
$region_name->addMultiOption($region->region_id, $region->region_name, $region->region_short_name);
}
//model
<?php
class Model_Regions extends Zend_Db_Table_Abstract
{
protected $_name = 'regions';
//protected $_name = 'smmedetails';
public function getregion($region_id)
{
$region_id = (int)$region_id;
$row = $this->fetchRow('region_id = ' . $region_id);
if (!$row) {
throw new Exception("Could not find row $region_id");
}
return $row->toArray();
}
public function smmedetails2region($region_name)
{
$data = array(
'region_name'=> $region_name
);
return $this->insert($data);
}
public function getRegions()
{
$select = $this->select();
return $this->fetchAll($select);
}
}
//controller
public function registerAction()
{
$this->view->headScript()->appendFile('/js/ui/jquery.ui.autocomplete.js');
$form = new Form_SmmeDetails();
$this->view->form = $form;
if ($this->getRequest()->isPost()) {
$formData = $this->getRequest()->getPost();
if ($form->isValid($formData)) {
$companyname = $form->getValue('companyname');
$companytradingname = $form->getValue('companytradingname');
$region_name = $form->getValue('region_name');
$satellite_name = $form->getValue('satellite_name');
$city = $form->getValue('city');
$companyaddress = $form->getValue('companyaddress');
$addresscode = $form->getValue('addresscode');
$companypostaladdress = $form->getValue('companypostaladdress');
$postalcode = $form->getValue('postalcode');
$companyphonenumber = $form->getValue('companyphonenumber');
$companyfaxnumber = $form->getValue('companyfaxnumber');
$companycellnumber = $form->getValue('companycellnumber');
$businessemailaddress = $form->getValue('businessemailaddress');
$businesswebsite = $form->getValue('businesswebsite');
$smmedetails = new Application_Model_DbTable_SmmeDetails();
$smmeid = $smmedetails ->smmedetailsSmmeDetails($companyname, $companytradingname, $region_name, $satellite_name, $city, $companyaddress, $addresscode, $companypostaladdress, $postalcode, $companyphonenumber, $companyfaxnumber,
$companycellnumber, $businessemailaddress, $businesswebsite);
// $region = new Application_Model_DbTable_Region();
//$region ->smmedetails2region($formData, $smmedetails->smmeid);
$this->_redirect('/admin/smme/register2/smmeid/'.$smmeid);
} else {
$form->populate($formData);
}
}
}
The code is suppose to view a hidden input select, called satellite when you select a feild option from regions, the satellite should view certain options based on the region selected. In short the region selected should correspond with what the user selected. eg Province is Gauteng, so cites would be, Johannseburg,Pretoria etc. Take note the region and satellite options are called from the database table according to they names and id. The code above keeps giving me and error Message: Method onchange does not exist. Was told not to use onchange method should I be using ajax and can I use javascript and sqlquery in the view or should I call it as an action? If so how? Here is a slight picture example.
Please be of help
Thanks in advance
I'd make a few suggestions to what you have there.
Firstly, for simplicity, I'd not use the onChange function, because I don't see it in the API, plus JavaScript or jQuery written in that way can become difficult to maintain and write properly. It is a lot simpler to instead include an external JavaScript file. By doing this, you can also test and debug the JavaScript separately, as well as reuse it.
Have a look at the excellent document for onChange, and getJson. I've used these and others and they're quite straight-forward. For testing, I recommend QUnit for starters. It makes testing a breeze.
Secondly, if you're using the Zend libraries for Model_Regions and $region_name, then I'd suggest using them instead of the direct mysql calls as well. This will allow you to build a good library which you can continue to expand as needed, plus it makes composing SQL quicker and safer.
For the controller, I'd suggest a RestController with a Restful Route. Here's an excellent tutorial.
I hope this helps you out with the problem. If you need anything more, let me know.
Thanks for emailing me about this.
The way I go about this is as follows:
Firstly I set up the form, and then an action in a controller.
Lets say getmajorgroupAction()
which in that action I would then disable layout, and just get the relevent results based on the id.
Then in the view file, loop through the
so the output from that call would be
<option value="1">1</option>
<option value="2">2</option>
etc
Personally I use jquery now, whereas the post you referenced when you emailed me, I was using another method.
trying to use something like this
jQuery(document).ready(function() {
jQuery("#division").change(function () {var division = jQuery("#division").val();
jQuery("#major_group").load("/module/getmajorgroup/", {division_id: division} );});
});
Hope that makes sense.
Thanks that was useful but i found a way to do it using this formula below, but everytime I click on the first select the while still in the session the second select appears all the time, eg if a person choose the wrong selection and re tried it brings up another field instead of fixing the field. I think its in a countinous loop . heres my script
<script type="text/javascript">
$(document).ready(function() {
$("#region_name").on('change', function () {
ajaxAddField();
}
);
}
);
// Retrieve new element's html from controller
function ajaxAddField()
{
$.ajax(
{
type: "POST",
url: '<?php echo $this->baseURL()?>/admin/ajax/get-cities/city/' + encodeURIComponent($('#region_name').val()),
success: function(newElement) {
// Insert new element before the Add button
//$(this).prev().remove().end().before('#city-label');
$("#city-label").before(newElement);
}
}
);
}
</script>

Grails chain selects without domains

I'm trying to chain two, possibly three <g:select ...> statements together using Ajax like is shown here Populate dropdown list using ajax In grails but all the examples I find have two big differences from what I'm using. 1. I'm using the jQuery library, not prototype. And 2. I don't have domain objects for my select values, they are pulled from an Oracle table via a service call.
My problem looks like this:
<g:select name="degreeSubject" from="${majors}" noSelection="${['':'-Choose Subject-']}" value="${degreeInstance?.degreeSubject }"/>
<g:select name="degreeConcentration" from="${concentrations}" noSelection="${['':'']}" value="${degreeInstance?.degreeConcentration }"/>
Where the majors, and concentrations come through the controller but are populated in a service class.
I was thinking the controller method would look something like
def updateSelect = {
def concentrations = degreeService.getConcentrations(params.selectedValue)
render (template:"selectConcentration", model : ['concentrations' : concentrations])
}
But, I can't get it to work.
Thoughts? Or someone have an example of doing this with jQuery and no domain objects using Grails 2.2.4?
You can really do it without being javascript-library specific. If you use the grails built-in remoteFunction it will handle the jQuery portion for you. What you would then want for your degreeSubject select is:
<g:select name="degreeSubject"
from="${majors}"
noSelection="${['':'-Choose Subject-']}"
value="${degreeInstance?.degreeSubject }"
onChange="${remoteFunction(
controller: 'yourControllerName',
action: 'updateSelect',
params: '\'value=\' + escape(this.value),
onSuccess: 'updateConcentration(data)')}/>
The key being the onChange event calling the remoteFunction. The remote function will make an ajax call to whatever controller action you want, but you'll need to call a javascript function to take in the results of your controller action and populate the other select. If you wanted to do this with simple js you could do this:
function updateConcentration(items) {
var control = document.getElementById('degreeConcentration')
// Clear all previous options
var i = control.length
while (i > 0) {
i--
control.remove(i)
}
// Rebuild the select
for (i=0; i < items.length; i++) {
var optItem = items[i]
var opt = document.createElement('option');
opt.text = optItem.value
opt.value = optItem.id
try {
control.add(opt, null) // doesn't work in IE
}
catch(ex) {
control.add(opt) // IE only
}
}
}
and finally your controller action should look like this:
def updateSelect(value) = {
def concentrations = degreeService.getConcentrations(value)
render concentrations as JSON // or use respond concentrations if you upgrade to 2.3
}

Mixing JavaScript and Scala in a Play template

I'm not sure how this is done. I could hard code the route I'm trying to use, but I'd like to do this the right way.
I have a dropdown that needs to load a new page on change. Here's basically how I'm trying to do it (I've tried a few variations of this):
#getRoute(value: String) = #{
routes.Accounts.transactions(Long.valueOf(value))
}
<script type="text/javascript">
$(function() {
$("select[name='product']").change(function() {
location.href = #getRoute($(this).val());
}).focus();
$('a.view.summary').attr('href', "#routes.Accounts.index()" + "?selectedAccountKey=" + $('select[name=product]').val());
});
</script>
This produces a identifier expected but 'val' found exception. I also tried surrounding it in quotes, but that causes a [NumberFormatException: For input string: "$(this).val()"]
So how the heck do I insert a value from JavaScript into a Scala function?
Edit
Here's my solution, inspired by the accepted answer. This dropdown is defined in a tag that's made for reuse by different components, and the base URL is different for each component. The way to achieve this was to pass a function that generates a URL based on an account key into the dropdown:
#(accountList: List[models.MemberAccount],
selectedAccountKey: Long,
urlGenerator: (Long) => Html
)
<select name="product">
#for(account <- accountList) {
#if(account.accountKey == selectedAccountKey) {
<option selected="selected" value="#urlGenerator(account.accountKey)">#account.description (#account.startDate)</option>
} else {
<option value="#urlGenerator(account.accountKey)">#account.description (#account.startDate)</option>
}
}
</select>
<script type="text/javascript">
$(function() {
$('select[name=product]').change(function() {
location.href = $(this).val();
});
});
</script>
Then you can define a function like this to pass in:
#transactionsUrl(memberAccountKey: Long) = {
#routes.Accounts.transactions(memberAccountKey)
}
#accountsDropdown(transactionDetails.getMemberAccounts(), transactionDetails.getMemberAccountKey(), transactionsUrl)
You need a way of storing all URLs in the page, e.g.
<option value="#routes.Accounts.transactions(id)">Display</option>
Then onChange, you can:
$("select[name='product']").change(function() {
location.href = $(this).val();
});

Categories