I'm trying to use some javascript on a page layout, and I'm encountering a strange issue where the ClientID of a Sharepoint.WebControls.TextField seems to change between OnLoad and the page being displayed.
In the OnLoad event, TextField3.ClientID resolves to "ctl00_PlaceHolderMain_TextField3", but if look to see why my js doesn't work, the page source reveals that the control id to be "ctl00_PlaceHolderMain_TextField3_ctl00_TextField".
Any ideas what's going on?
Here's the code I'm using:
public class PostingTemplate : Microsoft.SharePoint.Publishing.PublishingLayoutPage
{
protected DropDownList author;
protected TextField TextField3;
private List<string> _authorNames;
public List<string> AuthorName
{
get { return _authorNames; }
set { _authorNames = value; }
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
author.AutoPostBack = false;
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(),
"fillInAuthorText", getQuery(), true);
author.Attributes.Add("onChange", "fillInAuthorText()");
if (!Page.IsPostBack)
{
_authorNames = new List<string>();
_authorNames = Utilities.GetAuthorList(SPContext.Current.Site);
author.DataSource = _authorNames;
author.DataBind();
}
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (author.Items.Count > 0)
{
author.SelectedIndex = 0;
TextField3.Text = ((ListItem)author.Items[author.SelectedIndex]).Text;
}
}
private string getQuery()
{
string query = #" function fillInAuthorText() {
var IndexValue = document.getElementById('";
query += author.ClientID;
query += #"').selectedIndex;
var SelectedVal = document.getElementById('";
query += author.ClientID;
query += #"').options[IndexValue].value;
document.getElementById('";
query += TextField3.ClientID;
query += #"').value = SelectedVal;
}";
return query;
}
}
You need to include the client ID of the parent control as well.
// Replace:
query += author.ClientID;
// With:
query += base.ClientID + "_" + author.ClientID;
(Note that I've only ever done this with a web part so there may be some tweaking you need to do for it to work in a page layout.)
Another option is to resolve this client side. See Eric Shupp's blog for most info.
With help form Alex Angas, Here is what I discovered:
The TexField renders out some literals that end up surrounding a textbox, and it's really the textbox that you're interested in. Here's the modified section of code:
private string getQuery()
{
string query = #" function fillInAuthorText() {
var IndexValue = document.getElementById('";
query += author.ClientID;
query += #"').selectedIndex;
var SelectedVal = document.getElementById('";
query += author.ClientID;
query += #"').options[IndexValue].value;
document.getElementById('";
query += getTextFieldID(TextField3);
query += #"').value = SelectedVal;
}";
return query;
}
private string getTextFieldID(Control txt)
{
foreach (Control c in txt.Controls)
{
if (c.HasControls())
{
foreach (Control con in c.Controls)
if (con is TextBox)
return con.ClientID;
}
}
return "";
}
Keep in mind, this is specific to my application, your mileage my vary.
Related
i am use asp.net core code for popup and append html and js file in main view but i get error like $ not found if anyone know how to solve please help
My ActionFilter Code:-
private readonly IStoreContext _storeContext;
private readonly ISettingService _settingService;
private readonly ILogger _logger;
private readonly ILocalizationService _localizationService;
private readonly IWorkContext _workContext;
private readonly ITopicService _topicService;
private readonly INewsLetterSubscriptionService _newsLetterSubscriptionService;
#endregion
#region const
public PopupEngageFilterAttribute()
{
this._storeContext = EngineContext.Current.Resolve<IStoreContext>();
this._settingService = EngineContext.Current.Resolve<ISettingService>();
this._logger = EngineContext.Current.Resolve<ILogger>();
this._localizationService = EngineContext.Current.Resolve<ILocalizationService>();
this._workContext = EngineContext.Current.Resolve<IWorkContext>();
this._topicService = EngineContext.Current.Resolve<ITopicService>();
this._newsLetterSubscriptionService = EngineContext.Current.Resolve<INewsLetterSubscriptionService>();
}
#endregion
#region methods
public void PopupEngageOnResultExecuted(ActionExecutedContext filterContext)
{
var storeId = _storeContext.CurrentStore.Id;
LicenseImplementer licenseImplementer = new LicenseImplementer();
// load plugin settings
var _setting = _settingService.LoadSetting<PopupEngageSetting>(storeId);
var allStoreSettings = _settingService.LoadSetting<PopupEngageSetting>(0);
//check plugin is enabled or not
if (_setting.PopupEngageEnabled)
{
// check license
//if (!licenseImplementer.IsLicenseActive(allStoreSettings.LicenseKey, allStoreSettings.OtherLicenseSettings))
// return;
StringBuilder sb = new StringBuilder();
string bioepEngageScript = string.Empty;
string popupEngageView = string.Empty;
string popupEngageScript = string.Empty;
string newsLetterScript = string.Empty;
// get current customer
var customer = _workContext.CurrentCustomer;
// check customer cart
string customerCart = Convert.ToString(customer.HasShoppingCartItems);
// set cookie for customer cart
filterContext.HttpContext.Response.Cookies.Append("CustomerCart", customerCart, new CookieOptions() { Path = "/", HttpOnly = false, Secure = false });
if(customerCart == "True")
{
// get bioep script file
Stream bioepScriptFile = Assembly.GetExecutingAssembly().GetManifestResourceStream("Nop.Plugin.XcellenceIt.PopupEngage.Script.bioep.min.js");
if (bioepScriptFile != null)
using (StreamReader reader = new StreamReader(bioepScriptFile))
{
bioepEngageScript = reader.ReadToEnd();
}
// get PopupEngage script
string path = Path.Combine(Path.Combine(Path.Combine(Path.Combine(Environment.CurrentDirectory.ToString(), "Plugins"), "XcellenceIt.PopupEngage"), "Script"), "PopupEngage.js");
if (File.Exists(path))
{
popupEngageScript = File.ReadAllText(path);
}
// check current customers role
var customerRole = customer.CustomerRoles.Where(x => x.Name == "Guests").FirstOrDefault();
if (customerRole != null)
{
// get Popup View file
string popupEngageViewFile = Path.Combine(Path.Combine(Path.Combine(Path.Combine(Path.Combine(Environment.CurrentDirectory.ToString(), "Plugins"), "XcellenceIt.PopupEngage"), "Views"), "PopupEngage"), "PopupEngageNewsLetter.html");
if (File.Exists(popupEngageViewFile))
{
popupEngageView = File.ReadAllText(popupEngageViewFile);
}
// get NewsLetter Script file
Stream newsLetterScriptFile = Assembly.GetExecutingAssembly().GetManifestResourceStream("Nop.Plugin.XcellenceIt.PopupEngage.Script.NewsLetter.js");
if (newsLetterScriptFile != null)
using (StreamReader reader = new StreamReader(newsLetterScriptFile))
{
newsLetterScript = reader.ReadToEnd();
}
}
else
{
// get Popup View file
string popupEngageViewFile = Path.Combine(Path.Combine(Path.Combine(Path.Combine(Path.Combine(Environment.CurrentDirectory.ToString(), "Plugins"), "XcellenceIt.PopupEngage"), "Views"), "PopupEngage"), "PopupEngage.html");
if (File.Exists(popupEngageViewFile))
{
popupEngageView = File.ReadAllText(popupEngageViewFile);
}
}
var topicBody=string.Empty;
// get topic from settings
var topic = _setting.TopicName;
if (!string.IsNullOrEmpty(topic))
{
// get topic by system name
var topicRecord = _topicService.GetTopicBySystemName(topic);
if(topicRecord != null)
{
topicBody = topicRecord.Body;
}
}
// replace new line with slash and double coute with single coute
popupEngageView = popupEngageView.Replace(Environment.NewLine, String.Empty).Replace("\"", "'");
topicBody = topicBody.Replace(Environment.NewLine, String.Empty).Replace("\"", "'");
// append script
sb.Append("<script type=\"text/javascript\" src=\"/wwwroot/lib/jquery-1.10.2.min.js\">\n\t");
sb.Append(bioepEngageScript);
sb.Append(popupEngageScript);
sb.Append("$(\"" + popupEngageView + "\").insertAfter(\".newsletter\");");
sb.Append("$('.popupengage_popupmsg').html(\"" + topicBody + "\");");
sb.Append(newsLetterScript);
sb.Append("</script>\n");
var bytes = Encoding.ASCII.GetBytes(sb.ToString());
filterContext.HttpContext.Response.Body.WriteAsync(bytes,0, bytes.Length);
}
}
}
#endregion
file append in perfect way but it append script in top of the page before jquery. and that script append by string builder.Popup js example
if u are using jquery, make sure it is included before the script files that use jquery functionality;
For ex: if u have a js file named 'main.js' which has includes a line like $().forEach then your order of inclusion in the html file should be
<script>jquery.js </scrpt>
<script>main.js </scrpt>
I've been tasked with including asynchronous calls to my webpage and I'm not sure where to start. Currently, my webpage takes user input from a drop down list, converts it into a list of CodeDesc objects, serializes it all into JSON and then deserializes it back so it can be displayed in a GridView on the screen. (I could just make it spit out the CodeDesc object back to the GridView but this is the way my manager wanted it so..).
In any case, now I need the results to be displayed without reloading the page and after some research I read that AJAX was a good way to do it. Unfortunately, I'm confused how I can connect it all and actually use it. My attempts are below but I could really use some guidance on the matter.
HTML (partial):
<script>
$("#Button1").on("click", function () {
$.ajax({
type: ??'GET'??,
contentType: ??
success: function (?? Call deserializeJSONResults function ??) {
$('#GridView2').html("");
for (var i = 0; i < deserializedProduct.length; i++) {
$("#GridView2").append(deserializedProduct.id, deserializedProduct.code, deserializedProduct.);
}
}
});
});</script>
Without using AJAX my code is below:
CS:
protected void Button1_Click(object sender, EventArgs e)
{
DataConnector dc = new DataConnector();
GridView2.DataSource = dc.deserializeJSONResults(DropDownList1.SelectedValue);
GridView2.DataBind();
}
Backend:
//Return results to GridView2 as list of CodeDesc objects
public List<CodeDesc> getQueryResults(string searchTerm)
{
try
{
List<CodeDesc> L = new List<CodeDesc>();
string query = "select id, code, descr from code_desc where code_type_id = (select id from code_desc where descr = :searchTerm)";
// Create the OracleCommand
using (OracleCommand cmd = new OracleCommand(query, con))
{
cmd.Parameters.Add(new OracleParameter("searchTerm", searchTerm));
con.Open();
// Execute command, create OracleDataReader object
using (OracleDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
CodeDesc c = new CodeDesc
{
id = reader.GetInt32(0),
code = reader.GetString(1),
description = reader.GetString(2)
};
L.Add(c);
}
}
}
return L;
}
//catch clause here
}
//Convert to JSON and parse
public List<CodeDesc> deserializeJSONResults(string searchTerm)
{
List<CodeDesc> L = getQueryResults(searchTerm);
string json = JsonConvert.SerializeObject(L, Formatting.Indented);
//deserialize object
List<CodeDesc> deserializedProduct = JsonConvert.DeserializeObject<List<CodeDesc>>(json);
return deserializedProduct;
}
}
Any help would be appreciated. I have little development experience and this is my first time with web/.NET development
I have created the following chart using google organisation chart but I have some problems. When I open the page or when I refresh the page it shows up the full chart like in picture below. But I want only the items that are in red square to be shown how can I do this.
I do not want to get a few items from the list but when I open the page it shows the whole chart with its all list item and instead when it opens I want to display only 5 items and let user to expand others do you understand me?
This is the picture of chart how it looks like and how I want it to be!
And here is my full c# code:
namespace OrganizationChartUsingGoogleAPI.OrganizationChart
{
public static class ConvertTo
{
/// <summary>
/// Convert the object type in the given type and handle the DBNULL.
/// </summary>
/// <typeparam name="T">Type to convert</typeparam>
/// <param name="value">value</param>
/// <returns>converted value and if DBNULL then return the type's default value i.e. string = string.Empty, Int16=0 </returns>
public static T CastIn<T>(this object value) where T : IConvertible
{
if (value == DBNull.Value)
if (typeof(T) == typeof(string))
{
return (T)Convert.ChangeType(string.Empty, typeof(T));
}
else
{
return default(T);
}
if (typeof(T) == typeof(bool))
return (T)Convert.ChangeType(Convert.ToInt32(value), typeof(T));
return (T)Convert.ChangeType(value, typeof(T));
}
}
public partial class OrganizationChartUserControl : UserControl
{
//Get the List name to fetch the data from
string listName = "OrgChart_Demo";
int iRowCounter = 0;
string sAllNewRows = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
//Fetch the data (recursively) from the list
GetNode(string.Empty);
//Generate the Client Script and Register
GenerateClientScript(sAllNewRows);
}
private void GenerateClientScript(string sAllNewRows)
{
string csName1 = "OrgChartScript";
Type csType = this.GetType();
ClientScriptManager cs = Page.ClientScript;
// Check to see if the startup script is already registered.
if (!cs.IsStartupScriptRegistered(csType, csName1))
{
StringBuilder cstext = new StringBuilder();
cstext.Append("<script type='text/javascript' src='https://www.google.com/jsapi'></script>");
cstext.Append("<script type='text/javascript'>");
cstext.Append("google.load('visualization', '1', { packages: ['orgchart'] });");
cstext.Append("google.setOnLoadCallback(drawChart);");
cstext.Append("function drawChart() {");
cstext.Append("var data = new google.visualization.DataTable();");
cstext.Append("data.addColumn('string', 'Name');");
cstext.Append("data.addColumn('string', 'Manager');");
cstext.Append("data.addColumn('string', 'ToolTip');");
cstext.Append("var rowArr = new Array();");
cstext.Append(sAllNewRows);
cstext.Append("data.addRows(rowArr);");
cstext.Append("var chart = new google.visualization.OrgChart(document.getElementById('chart_div'));");
cstext.Append("chart.draw(data, { allowHtml: true, allowCollapse: true });");
cstext.Append("}");
cstext.Append("</script>");
cs.RegisterClientScriptBlock(csType, csName1, cstext.ToString(), false);
}
}
private void GetNode(string reportsTo)
{
SPListItemCollection itemCol = GetListItems(listName, reportsTo);
foreach (SPListItem item in itemCol)
{
//create a new row
sAllNewRows += createNewRow(item);
//Recursion
GetNode(item["Name"].ToString());
}
}
private string createNewRow(SPListItem listItem)
{
//Converting list items to strings.
string sName = ConvertTo.CastIn<string>(listItem["Name"]);
string sTitle = ConvertTo.CastIn<string>(listItem["Title"]);
string sMoreInfo = ConvertTo.CastIn<string>(listItem["MoreInfo"]);
string sReportsTo = ConvertTo.CastIn<string>(listItem["ReportsTo"]);
//Checking if image field ref is empty or null (if it does't provide any img source link!)
ImageFieldValue pageImage = listItem["Pageimage"] as ImageFieldValue;
string sPicture = string.IsNullOrEmpty(pageImage.ImageUrl) ? "#" : pageImage.ImageUrl;
StringBuilder sText = new StringBuilder();
sText.Append("var NewRow = new Array();");
//this row shows the image and everything else what chart needs
sText.Append(String.Format("NewRow.push({{ v: '{0}', f: '<img src =\"{1}\" style=\"width:57px; height:57px; float:left;\" />{2}<div style=\"color:white; font-style:Arial\">{3}</div>' }});", sName, sPicture, sName, sTitle));
sText.Append(String.Format("NewRow.push('{0}');", sReportsTo));
sText.Append(String.Format("NewRow.push('{0}');", sMoreInfo));
//sText.Append(String.Format("NewRow.push('{0}');", sPicture));
sText.Append(String.Format("rowArr[{0}] = NewRow;", iRowCounter));
//Pageimage
iRowCounter++;
return sText.ToString();
}
private SPListItemCollection GetListItems(string destList, string reportsTo)
{
SPListItemCollection ResultListItems = null;
using (SPSite oSite = new SPSite(SPContext.Current.Web.Url))
{
using (SPWeb oWeb = oSite.OpenWeb())
{
SPList list = oWeb.Lists.TryGetList(destList);
if (null == list)
return ResultListItems;
string selected = DropDownList2.SelectedValue;
// Label1.Text = selected;
//Check if the item already exist.
StringBuilder sCAMLQuery = new StringBuilder(string.Empty);
sCAMLQuery.Append("<Where>");
sCAMLQuery.Append("<And>");
if (reportsTo != string.Empty)
{
sCAMLQuery.Append("<Eq>");
sCAMLQuery.Append("<FieldRef Name='ReportsTo' />");
//sCAMLQuery.Append("<Value Type='Lookup'>" + reportsTo + "</Value>");
sCAMLQuery.Append("<Value Type='Text'>" + reportsTo + "</Value>");
sCAMLQuery.Append("</Eq>");
}
else
{
sCAMLQuery.Append("<IsNull>");
sCAMLQuery.Append("<FieldRef Name='ReportsTo' />");
sCAMLQuery.Append("</IsNull>");
}
sCAMLQuery.Append("<Eq>");
sCAMLQuery.Append("<FieldRef Name='Kompania' />");
//sCAMLQuery.Append("<Value Type='Lookup'>" + reportsTo + "</Value>");
sCAMLQuery.Append("<Value Type='Text'>" + selected + "</Value>");
sCAMLQuery.Append("</Eq>");
sCAMLQuery.Append("</And>");
sCAMLQuery.Append("</Where>");
SPQuery QueryResult = new SPQuery();
QueryResult.Query = sCAMLQuery.ToString();
ResultListItems = list.GetItems(QueryResult);
}
}
return ResultListItems;
}
}
}
Thanks all of you
I see you have a GetNode(string reportsTo).
could you pass the level you're in and return if the level gets higher than you want?
private void GetNode(string reportsTo, int level)
{
// maybe have some config or value you can set for the max level you want.
if (level >= 2) return;
SPListItemCollection itemCol = GetListItems(listName, reportsTo);
foreach (SPListItem item in itemCol)
{
//create a new row
sAllNewRows += createNewRow(item);
//Recursion
GetNode(item["Name"].ToString(). ++level);
}
}
I'm developing a game on cordova that uses facebook integration. I have a facebook game canvas running on a secure site.
The friend request works fine on the web site version (returns more than 25 results, as I'm iterating the paging.next url that is also returned).
However, on the cordova build (android) it only ever returns the first result set of 25. It does still have the page.next url JSON field but it just returns a response object with a type=website.
Has anyone else come across this?
After quite a lot of digging I found an issue with the way requests are handled in the FacebookLib for Android. The current version of the com.phonegap.plugins.facebookconnect plugin uses Android FacebookSDK 3.21.1 so I'm not sure if this will still be an issue with v4.
A graph result with a paging url is used to request the next page however using the entire url, which includes the https://graph.facebook.com/ as well as the usual graphAction causes an incorrect result set to be returned. However I determined that if you remove the schema and host parts it will be correct.
I modified the ConnectPlugin.java to check that any schema and host is removed from the graphAction. Seems to work well now.
ConnectPlugin.java before:
private void makeGraphCall() {
Session session = Session.getActiveSession();
Request.Callback graphCallback = new Request.Callback() {
#Override
public void onCompleted(Response response) {
if (graphContext != null) {
if (response.getError() != null) {
graphContext.error(getFacebookRequestErrorResponse(response.getError()));
} else {
GraphObject graphObject = response.getGraphObject();
JSONObject innerObject = graphObject.getInnerJSONObject();
graphContext.success(innerObject);
}
graphPath = null;
graphContext = null;
}
}
};
//If you're using the paging URLs they will be URLEncoded, let's decode them.
try {
graphPath = URLDecoder.decode(graphPath, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String[] urlParts = graphPath.split("\\?");
String graphAction = urlParts[0];
Request graphRequest = Request.newGraphPathRequest(null, graphAction, graphCallback);
Bundle params = graphRequest.getParameters();
if (urlParts.length > 1) {
String[] queries = urlParts[1].split("&");
for (String query : queries) {
int splitPoint = query.indexOf("=");
if (splitPoint > 0) {
String key = query.substring(0, splitPoint);
String value = query.substring(splitPoint + 1, query.length());
params.putString(key, value);
if (key.equals("access_token")) {
if (value.equals(session.getAccessToken())) {
Log.d(TAG, "access_token URL: " + value);
Log.d(TAG, "access_token SESSION: " + session.getAccessToken());
}
}
}
}
}
params.putString("access_token", session.getAccessToken());
graphRequest.setParameters(params);
graphRequest.executeAsync();
}
ConnectPlugin.java after:
private void makeGraphCall() {
Session session = Session.getActiveSession();
Request.Callback graphCallback = new Request.Callback() {
#Override
public void onCompleted(Response response) {
if (graphContext != null) {
if (response.getError() != null) {
graphContext.error(getFacebookRequestErrorResponse(response.getError()));
} else {
GraphObject graphObject = response.getGraphObject();
JSONObject innerObject = graphObject.getInnerJSONObject();
graphContext.success(innerObject);
}
graphPath = null;
graphContext = null;
}
}
};
//If you're using the paging URLs they will be URLEncoded, let's decode them.
try {
graphPath = URLDecoder.decode(graphPath, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String[] urlParts = graphPath.split("\\?");
String graphAction = urlParts[0];
///////////////////////
// SECTION ADDED
///////////////////////
final String GRAPH_BASE_URL = "https://graph.facebook.com/";
if(graphAction.indexOf(GRAPH_BASE_URL)==0) {
URL graphUrl = null;
try {
graphUrl = new URL(graphAction);
} catch (MalformedURLException e) {
e.printStackTrace();
}
graphAction = graphUrl.getPath();
}
///////////////////////
// END SECTION ADDED
///////////////////////
Request graphRequest = Request.newGraphPathRequest(null, graphAction, graphCallback);
Bundle params = graphRequest.getParameters();
if (urlParts.length > 1) {
String[] queries = urlParts[1].split("&");
for (String query : queries) {
int splitPoint = query.indexOf("=");
if (splitPoint > 0) {
String key = query.substring(0, splitPoint);
String value = query.substring(splitPoint + 1, query.length());
params.putString(key, value);
if (key.equals("access_token")) {
if (value.equals(session.getAccessToken())) {
Log.d(TAG, "access_token URL: " + value);
Log.d(TAG, "access_token SESSION: " + session.getAccessToken());
}
}
}
}
}
params.putString("access_token", session.getAccessToken());
graphRequest.setParameters(params);
graphRequest.executeAsync();
}
There's no way to know that you call their api from cordova vs website, so it's some problem on your side, maybe you use some different implementation of the api on corodva and website, so that cordova sends a pagination request or send to other api version which does pagination.
I am calling a web method from a JavaScript function
function loadstatecity() {
alert(document.getElementById("CountryList").value);
// PageMethods.username_availability(document.getElementById("CountryList").value, OnSuccess, OnFailure);
PageMethods.loadstatecity(document.getElementById("CountryList").value, OnSuccess,OnFailure);
}
Web method is returning a list of strings:
[System.Web.Services.WebMethod]
public static List<string> loadstatecity(string countrycode)
{
utilityFunc.loadstatecity(countrycode);
return utilityFunc.state;
}
loadstatecity function Code:
public static void loadstatecity(string CountryCode)
{
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["Mag_SDK"].ConnectionString))
{
con.Open();
using (SqlCommand com = con.CreateCommand())
{
com.CommandText = "Select ProvinceName from Province where CountryCode=#Country ;";
com.Parameters.AddWithValue("#country", CountryCode);
SqlDataReader dr = com.ExecuteReader();
while (!dr.Read())
{
state.Add(dr["ProvinceName"].ToString());
}
com.Connection.Close();
com.Connection.Dispose();
}
con.Close();
}
}
Now I want to bind this list to a DropDownList.
How can I do this?
Thank you for your help.
The List of strings type returned in your C# method will be serialized into a JavaScript array and will be accessible in a JavaScript callback. You'll then need to loop through all of the strings in the serialized array converting each one to an HTML 'option' element and then attach each element to the HTML 'state' select element produced by your ASP.NET. Here's some code which should accomplish that:
// The function to run on success, adds options to the state select.
function success(response) {
var select = document.getElementById('id-of-your-state-select-element'),
index = 0,
option = ''
value = '';
if (select) {
for (index; index < response.length; index++) {
value = response[index];
option = '<option>' + value + '</option>';
select.insertAdjacentHTML('beforeend', option);
}
}
}
// Shows an error in an alert box, should be improved before
// production deployment.
function error(response) {
alert(response);
}
These two functions are then used in your 'loadstatecity' method as success / failure callbacks.
PageMethods.loadstatecity(document.getElementById("CountryList").value, success, error);