Archive

Posts Tagged ‘jQuery’

SharePoint: Issue with calling an asmx web service in SharePoint 2010 through jQuery

November 20th, 2012 No comments

    After migration a SharePoint 2007 application to SharePoint 2010 my jQuery scripts communicating with asmx web services stopped working. The error I got was a 500 Internal Server Error. The scripts looks as follows:

$.ajax({
  type: "POST",
  url:  "http://someserver/someapp/_layouts/Services/Products.asmx/GetProductByCountry",

  data:        JSON.stringify({ countryCode: "USA" }),
  dataType:    "json",
  contentType: 'application/json; charset=utf-8',
  context:     this,

  success: function (data) {
		     alert(data.d);
           },
  error:   function (XMLHttpRequest, textStatus, errorThrown) {
		     alert(textStatus);
           }
});

Note: The JSON object mentioned in the script is defined in the json2.js available at http://www.json.org.

This issue can be solved by adding an appropriate <webServices> section to the SharePoint application’s web.config (in my case it’s located at C:\inetpub\wwwroot\wss\VirtualDirectories\80). So, find the global <system.web> section in your web.config and make changes so that the result would look like the following:

<system.web>
  <webServices>
    <protocols>
      <add name="HttpGet" />
      <add name="HttpPost" />
    </protocols>
  </webServices>
...
</system.web>

However, from the security point of view such solution is not ideal as it allows external access through the HTTP-GET and HTTP-POST messaging protocols to all your XML web services. So, it’s better to specify the access protocols for each web service separately, not affecting other ones. The <location> element added to the root <configuration> element provides us with this capability. The sample below defines the protocols for accessing the web service reachable by the specified path:

<configuration>
...
  <location path="_layouts/Services/Products.asmx">
    <system.web>
      <webServices>
        <protocols>
          <add name="HttpGet"/>
          <add name="HttpPost"/>
        </protocols>
      </webServices>
    </system.web>
  </location>
...
</configuration>

Note that the _layouts virtual directory is available as a subfolder of every SharePoint Web site. So if you want to limit the use of the web service by only one SharePoint Web site, specify the path like someapp/_layouts/Services/Products.asmx.

PS Here is a good article about how to create a custom web service in SharePoint 2010.

ASP.NET: How to trigger a validator on the client-side

August 27th, 2012 No comments

ValidatorValidate

The easiest way to trigger a validator on the client-side is to use the ValidatorValidate method provided by ASP.NET as a part of a Validation client-side API. You don’t need to include any js-files so as the all required scripts will be included automatically when you add a validator to your page. The typical use is something like this

var validator = document.getElementById('ctl00_PlaceHolderMain_info_textbox').Validators[0]; // Page_Validators[0];

ValidatorValidate(validator); // fire validation
ValidatorUpdateIsValid(); // update the global Page_IsValid flag

The ValidatorValidate makes the passed validator examine the input element bound to it and updates the validator‘s display (shows or hides its error message). I also recommend to call the ValidatorUpdateIsValid method, which updates the global variable Page_IsValid and by that may prevent the Html-form submit when the validator failed.

Below is a simple JavaScript function I use to force validation of a specified input. The function gets the input by the passed id, then goes through the all validators linked to the input and activates each of them. Finally, it updates the global Page_IsValid flag.

function ForceInputValidation(inputId) {
    var targetedControl = document.getElementById(inputId);    
    
    if (typeof(targetedControl.Validators) != "undefined") {        
        var i;
        for (i = 0; i < targetedControl.Validators.length; i++)
            ValidatorValidate(targetedControl.Validators[i]);
    }

    ValidatorUpdateIsValid();
}

ASP.Net places the initialization of validators at the end of the web page, so, it makes sense to handle the input‘s Validators-collection after the page has been loaded entirely. The following example demonstrates how to fire validation of the specified input right after the page has been loaded. jQuery is a best helper in that.

$(document).ready(function () {    
    ForceInputValidation('ctl00_PlaceHolderMain_info_textbox');
});

ValidatorEnable

As some blogs and forums recommend, you can also use another built-in function – ValidatorEnable, the code of which is shown below:

function ValidatorEnable(validator, enable) {
    validator.enabled = (enable != false);
    ValidatorValidate(validator);
    ValidatorUpdateIsValid();
}
// ...
// the typical use to fire validation is
var validator = document.getElementById('ctl00_PlaceHolderMain_info_textbox').Validators[0]; // Page_Validators[0];
ValidatorEnable(validator, true);

The ValidatorEnable calls sequentially the same ValidatorValidate and ValidatorUpdateIsValid functions we use above. Thus to activate one validator you can use, with no difference, either ValidatorEnable or combination of ValidatorValidate and ValidatorUpdateIsValid. But activating several validators (like in ForceInputValidation function) I advise employing the pair of the ValidatorValidate and ValidatorUpdateIsValid functions. That is because the ValidatorUpdateIsValid loops through all validators on the page. So, for best performance we should fire the all required validators and then call ValidatorUpdateIsValid once.

ps here is good source of information about the client-side validation.

jQuery: Disable hyperlink

July 1st, 2011 No comments

     The simplest way to disable/enable a link by using jQuery is:

function DisableLinks(links) {
    links.attr('disabled', 'true');
}
function EnableLinks(links) {
    links.removeAttr('disabled');
    // or links.attr('disabled', 'false');
}

However, the ‘disabled‘-attribute is supported only by IE, and the given example won’t work, for instance, in Firefox.

To circumvent this problem I’d like to suggest the following code:

<head>
    <script type="text/javascript" src="jquery-1.6.2.js"></script>
    <style type="text/css">
      .disabledLink
      {
  	        color: Gray;
  	        text-decoration: none;
      }
    </style>    
    <script type="text/javascript">
    
        function DisableLinks(links) {
            links.each(
                function(index, linkDomElement) {
                    var link = $(linkDomElement);            

                    // get the 'href' and 'onclick' attribute values
                    var linkHRef    = link.attr('href');
                    var linkOnClick = link.attr('onclick');

                    // set the dummy attribute values
                    link.attr('href', '#').attr('onclick', 'return false;');

                    // add a temporary attribute to keep the original 'href' value
                    if (linkHRef != undefined)
                        link.attr('tmphref', linkHRef);

                    // add a temporary attribute to keep the original 'onclick' value
                    if (linkOnClick != undefined)
                        link.attr('tmponclick', linkOnClick);

                    // add the class decorating disabled links
                    link.addClass('disabledLink');
                });
        }
        
        function EnableLinks(links) {
            links.each(
                function(index, linkDomElement) {
                    var link = $(linkDomElement);

                    // get the original values of 'href' and 'onclick' attributes from temporary attributes
                    var originalLinkHRef    = link.attr('tmphref');
                    var originalLinkOnClick = link.attr('tmponclick');

                    // restore the original 'href' value
                    if (originalLinkHRef != undefined)
                        link.attr('href', originalLinkHRef);

                    // restore the original 'onclick' value
                    if (originalLinkOnClick != undefined)
                        link.attr('onclick', originalLinkOnClick);

                    // remove temporary attributes
                    link.removeAttr('tmphref').removeAttr('tmponclick');

                    // remove the class decorating disabled links
                    link.removeClass('disabledLink');
                });
        }
    </script>
</head>

The methods DisableLinks and EnableLinks work successfully in different browsers. The css-class disabledLink allows to define the style of disabled link.

Below the sample of usage:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebForm1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    // the head is the same as it was in previous listing
</head>
<body>  
    <a id="disableLinks" href="#" onclick="DisableLinks($('#linkDiv a')); $('#enableLinks').show(); $('#disableLinks').hide(); return false;">Disable the rest of links</a>
    <a id="enableLinks" style="display:none" href="#" onclick="EnableLinks($('#linkDiv a')); $('#enableLinks').hide(); $('#disableLinks').show(); return false;">Enable the rest of links</a>
    <br />
    <br />
    <br />
    <div id="linkDiv">                
        <a href="http://google.com" onclick="alert('Transfer to www.google.com');">Goooogle</a>
        <br />
        <a href="#" onclick="alert('Hello!'); return false;">Hello, alert!</a>
        <br />
    </div>    
</body>
</html>

Links are enabled

Links are enabled

Links are disabled

Links are disabled

Related posts: