Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Friday, October 26, 2018

ASP.NET Prevent double-clicking of buttons

If you have a button that causes a record to be inserted into a table, you can sometimes run into duplicate records if the user happens to click the button twice (double-click).  This can be prevented by using javascript to disable the button as soon as the button is clicked the first time.  Use the following code:

<script>

    function disableButton() {
        document.getElementById("ID_OF_BUTTON").disabled = true;
    }

</script>


Then, use the OnClientClick property of the button to call this code:

<asp:Button ID="ID_OF_BUTTON" runat="server" Text="Click Me" OnClientClick="disableButton();" UseSubmitBehavior="false" />


NOTE: I have not used this on a form that has client validation, so I'm not sure how of if this would work in that situation.

Wednesday, October 14, 2015

Regular Expression Primer

I feel like I've finally cracked the code on regular expressions.  This is my attempt to document the essentials of regular expressions using JavaScript.  A regular expression essentially describes a pattern of text.

Generally, you use a regular expression (regex) in one of two ways:

  1. Test to see whether a specified string matches a regex exactly.  This is mainly used for validating input.
  2. Extract all instances of the pattern from a larger string of text.  The main use here is to replace the instances of the pattern with something else.
The easiest way to perform the first use is to define the regular express on the fly and then call the test method like so:

/^[0-9]+$/.test(inputToTest)

The test method returns true or false, based on whether the input string was a match.  The forward slashes simply delimit the regular expression.  The ^ indicates the beginning of the string, and the $ indicates the end of the string.  [0-9] says to match any number, and the plus means any number 1 or more times.  So, only numbers with one or more digits will match the regex.

The second use often involves replacing the matching text.  You can use a regex as a parameter when calling the string.replace method.  Let's say you want to replace all numbers in a string with the letter x.  Here is how you do it:

var results = inputString.replace(/[0-9]+/g, "x");

What's the "g" for?

That's the global flag.  That says to replace every matching text in the string with "x".

Now, let's talk about parenthesis.  A parenthesis in a regex means you can extract just the part in the parentheses.  Let's say you want to find everything with curly braces, and replace it all with just the text inside the curly braces.

var results = inputString.replace(/\{([A-Za-z]+)\}/g, "$1");

The &1 refers to the text matched by the first parenthesis.  So we would replace "{test}" with just "test".  Notice that the backslash is used to escape the curly brace character.

Sometimes a parenthesis is just a parenthesis and doesn't have to be referred to later.  You can just use it to group stuff.

These are really dumb examples to keep things simple, but these techniques are very powerful.  The best reference I've found for dealing with regex is here.


Friday, July 31, 2015

Close connections to your IndexedDB databases

Recently, I was attempting to run the deleteDatabase method of the IDBFactory interface of the IndexedDB API.  I noticed that occasionally the method would just hang there like it was stuck.  I slowly began to realize that it would hang if a connection was currently open.  This led me to researching how to close connections.

When you open a connection using the open method of IDBFactory, you get an object of type IDBDatabase.  In my experience, the only thing you do with the IDBDatabase object is to create the transaction object from it.  After you create the transaction, you should then immediately close the IDBDatabase object which closes the connection you opened.  At first, I wondered if you had to wait until you were done with the transaction before closing the connection, but apparently the close method knows to wait until all transactions created from it are completed.  This is from the specification:
Wait for all transactions created using connection to complete. Once they are complete, connection is closed.
Your code should look something like what is shown below. In this case, request is the IDBOpenDBRequest object.

request.onsuccess = function() {
    var db = event.target.result;

    var tx = db.transaction(['TableName'], 'readwrite');

    db.close();
}

Thursday, September 4, 2014

Use SoapUI to test your web services

Recently, I created a web service that external organizations would use as an API to access our data.  I decided to use WCF and the SOAP architecture to achieve this.  I also created a little .NET console app to test the web service.  Everything worked great.  However, I was a little concerned that I might have unintentionally wrote some code that was only supported by the Microsoft stack.  How could I be sure that my web service could be used by someone using a different platform?

My first idea was to try to access the web service using jQuery.  I felt that if I could successfully invoke the web service using jQuery or JavaScript, this would demonstrate that Microsoft technology wasn't necessary to use my service.  However, I found that calling a SOAP based web service from client side scripting is not an easy task.  In fact, I never got this to work, and there is not a lot of information out there about how to do this.  One problem is that browsers have security measures to stop cross site scripting.  So the web service has to be part of the same site.  If you can get past that, you also have to manually build the SOAP envelope in your javascript which is tedious.  On top of that you have to figure out how to specify your logon credentials within the request.  I concluded that it is just not practical to call a SOAP service from the client.  I think this is where the advantages of using a REST style web service really pay off.

I discovered a widely used application called SoapUI.  It is a free download, and you can use it to invoke the methods of your web service for testing purposes.  This is a way to independently test your web service operations without being bound to Microsoft.

Installation is straight forward and instructions can be found on the site.  Note that you do not need to install Hermes if you're not testing a Java service.

Here is how to test a web service operation.

  1. Open SoapUI and right click on Projects, New SOAP Project.
  2. Name the project and specify the address of the WSDL of your service.
  3. Check the box that says Create Sample Requests.
  4. In the navigator, you'll see each operation of the service.  If you click the plus sign next to each operation you will see the sample request that was created for you.
  5. Click on the request and find the request properties.
  6. If the web service security is set up for TransportWithMessageCredential, then set the username and password properties to something that works.  Also set the WSS-Password Type to PasswordText.
  7. Double-click the request.
  8. In the request window, you'll see the SOAP envelope.  You can see where the parameters go, and can set these here.
  9. Then, click the green arrow which sends the request to the web service.
  10. The results will be shown in the right-hand pane.

Thursday, June 12, 2014

jQuery Plugins

Sometimes you will come across some bit of functionality that jQuery doesn't handle natively and jQuery UI doesn't offer up a solution.  For example, let's say you need to implement a mask on a text box for a phone number.  You could use the Ajax Control Toolkit, but I've had issues getting this to work so I don't recommend it.  I love jQuery and jQuery UI, but you can't do this "out of the box".

A jQuery plugin is an extension of jQuery that "some guy" has written to accomplish something that jQuery doesn't do by itself.  In fact, jQuery UI is basically a "plugin".  The only difference is that jQuery UI is official and a plugin is not.  And this is what makes me a little hesitant to use plugins.  But, in the case of our phone number mask example, I think it's probably the best fit.

First go to the jQuery Plugins page and find something you think will work.  The inputmask seemed to work well for me.  Download all the files, and stick them all in a folder in your project folder.  There should be some documentation either on the plugin page or downloaded into your folder.  It will tell you how to use the plugin in your code.  As an example, here is how I used the inputmask.

First add this script to your page.

    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="InputMask/dist/jquery.inputmask.bundle.js" type="text/javascript"></script>

Note that I'm using a content provider (google) to host the "out of the box" jQuery code.  This is simply for brevity.

Then your jQuery would look like this:

        $(document).ready(function () {
            $("#txtPhoneNum").inputmask("999-999-9999");
        });

Tuesday, March 25, 2014

Add a Bootstrap jQuery widget to an MVC view.

Bootstrap is an awesome open source UI framework that uses both CSS and jQuery to provide a great user experience.  Besides straight up CSS, they offer some "widgets" that offer some functionality that jQuery UI does not provide.  The process for getting a widget on your view is almost exactly the same as using jQuery UI.

You have to render both the jQuery and Bootstrap bundles in your layout view.  If you don't have a Bootstrap bundle, you just need Bootstrap.js.  Also ensure Bootstrap.css is in your CSS bundle.

This markup will render a button that will produce the popover widget when clicked.

<button type="button" id="Example" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="top" data-content="Phone:  555-5555">
   Popover on top
</button>

Then, add a jQuery file with the following:

$(document).ready(function () {
    $("#Example").popover();
});

Monday, October 28, 2013

Ignore the route when adding a web service to an MVC project

You may want to add a web service to an MVC project in order to to implement AJAX call backs.  Remember that MVC is always trying to interpret URLs using it's routing configuration.  So, if the routing configuration encounters a URL referring to your web service, the framework won't know what to do with it.

You could just put it into another web project.  This works fine with IE 10, but Chrome will blow up.  I think it has something to do with cross domain configuration (and lack thereof).  Do yourself a favor, and stick it in the MVC project, and remember to add this to your RegisterRoutes method:

routes.IgnoreRoute("YourAjaxEnabledService.svc/DoWork")

Wednesday, September 25, 2013

Using a jQuery UI widget in on an MVC view

First, you need to add references to the appropriate jQuery libraries. The recommended way to do this is to use NuGet. Right click your project, and click on Manage NuGet Packages. Search online and install jQuery and jQuery UI. This will add the .js files as well as .css files that are used by the widgets. Bundles will be created in your BundleConfig file and these bundles will be rendered in your default layout file. Essentially, rendering a bundle is equivalent to using a <script> tag to reference the .js files. If you use another layout file, you must copy these statements over.

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryui")

This example will add the functionality of the datepicker widget to a text box. First create a textbox and make sure it has the id attribute:

@Html.TextBoxFor(Function(x) x.ProposedStartDate, New With {.id = "ProposedStartDate"})

I recommend a separate jQuery file for each page that you add jQuery functionality. Create the file, and include a link to this file in your view:

<script type="text/javascript" src="~/Scripts/ViewjQuery/SampleView.js"></script>

In your jQuery files, associate your textbox with the widget by using the following code:

$(document).ready(function () {

    $("#ProposedStartDate").datepicker();

});

Finally, you're not going to like the look of the datepicker, so go to Theme Roller and download a jQuery theme .css file or two. Then reference this css file in the head tag of your layout file thusly:

<link href="~/Content/themes/lightness/jquery-ui-1.10.3.custom.css" rel="stylesheet" type="text/css" />

Finally, you will be satisfied with the look of your datepicker, but you may want to size it down a bit. This has to be done through the font-size css style of a particular class. I don't recommend changing the theme .css that you downloaded. Rather, I would just create a new .css file for these types of tweaks and load it after you load the theme roller css. Put this in there:

.ui-datepicker { font-size:9pt !important}

Tuesday, July 23, 2013

Call a WCF web service using jQuery

First, add an AJAX-enabled WCF Service to your project.  There is a Visual Studio template for this.  Add a web method like the following:

    <OperationContract(), WebGet()>
    Public Function GetFood(inputId As String) As Food()
        Dim ReturnFood As New List(Of Food)
        If inputId = 1 Then
            ReturnFood.Add(New Food With {.Id = "1", .Name = "Bananas", .Color = "Yellow"})
        ElseIf inputId = 2 Then
            ReturnFood.Add(New Food With {.Id = "2", .Name = "Apples", .Color = "Red"})
        Else
            ReturnFood.Add(New Food With {.Id = "1", .Name = "Bananas", .Color = "Yellow"})
            ReturnFood.Add(New Food With {.Id = "2", .Name = "Apples", .Color = "Red"})
        End If
        Return ReturnFood.ToArray
    End Function

Notice the WebGet attribute.  This allows your web method to be called using a GET operation.  Very important.  Won't work without this.  What this means is if you browse to http://yourserver/AjaxGetResultsService.svc/GetFood, you will get Json back in return.

Also notice that I'm returning an array of Food which is a class I made up.  The .net framework will automatically turn this into Json for you.

So, if you had a button with an id of buttonPopulateFood, the following jQuery code would call this method and display the results.

    $("#buttonPopulateFood").click(function () {
        $.ajax({
            url: "AjaxGetResultsService.svc/GetFood",
            type: "GET",
            dataType: "json",
            data: {
                inputId: "1"
            },
            success: function (json) {
                displayJson(json);
            },
            error: function () { alert("You have failed.") }
        });
    });

Here is the displayJson function I'm calling.  I'm using the each function to iterate through the json array.

function displayJson(jsonData) {
    $.each(jsonData.d, function (index, value) {
        $("#food").append(index + ": " + value.Name + ", ");
    });
};

jQuery Basics

JavaScript

JavaScript is a programming language that runs inside a browser.  Because it runs inside a browser, it runs on the user's machine instead of on the web server.  JavaScript code will respond much quicker to events like button clicks than code that runs on the server.  JavaScript also uses a technology known as AJAX to call server code without a time consuming post back.  Incorporating more JavaScript into your web site can speed up and improve the user experience.  However, JavaScript is ugly.  You sometimes have to jump through a lot of hoops to do simple things, including AJAX calls.

jQuery

jQuery is simply a JavaScript library.  It is literally just one file that you download at jquery.com.  It's free and open source (you can't compile JavaScript anyway).  The library contains a bunch of functions that you can call.  The functions do pretty much everything you would want to do with JavaScript, so every line of code you write is just a call to a jQuery function.

To use jQuery, you just need to reference the jQuery library with a line like the following in the head tag of your html page:

    <script type="text/javascript" src="jquery-1.10.2.js"></script>  

You should definitely keep your own JavaScript in a separate file as well:

    <script src="StevesJScript.js" type="text/javascript"></script>

Let's dive into an example to demonstrate how this all works.

Clicking buttons

First, add a text box, a few buttons, and a paragraph to display some results to your page:

   <input type="text" id="textBoxNumber" />  
   <button id="buttonPressMe">Press Me</button>  
   <button id="buttonClear">Clear</button>  
   <p id="results">results</p>

Instead of setting the event attribute on the actual tag, you can associate a click event in your JavaScript file by calling a jQuery function.  This almost feels like a "code-behind" page like you see with ASP WebForms.

$(document).ready(function () {

    $("#buttonPressMe").click(function () {
        $("#results").text($("#textBoxNumber").val())
    });

    $("#buttonClear").click(function () {
        $("#textBoxNumber").val("");
    });

});

The $ function selects an element.  In this case, we select the whole document.  Then we call the ready function for that element.  So this means, after the document loads, whatever is sent to the ready function will execute.  You can see we have selected both buttons by id (using the # symbol) and have called the click function which specifies what to execute when the selected button is clicked.  Here I am simply displaying the contents of the text box and clearing out the text box.

Tuesday, July 9, 2013

LinkButton redirect to a page in a new browser window

Let's say you have a LinkButton control.  If you do a Response.Redirect in the code behind, the page will be opened in the same browser window.  But what if you want the page to open in a new browser window?  Unfortunately, Response.Redirect can't do this.  Javascript on the client or a plain html hyperlink (with target="_blank") is the only way to do this.  The simplest way to do this is to set the OnClientClick code to execute some javascript to make this happen.  Like this:

LinkButton1.OnClientClick = "window.open('http://www.blogger.com', '_blank')"

Then, when the user clicks the button, the javascript will open the link in the new window.  (The server side click event will also fire)

Javascript and ASP.NET

Many ASP.NET server controls provide a property or two for specifying javascript to execute.  For example, a Button control will expose a OnClientClick property where you can specify javascript.  A CustomValidator control exposes a ClientValidationFunction where you can specify a javascript function.

The first thing you need to do is write the javascript function.  The javascript must be enclosed in <script> tags, and can be placed anywhere in the markup.  For example:

<script type="text/javascript">
     function SayHello() {
          alert('Hello');
     }
</script>

Now, you can refer to this function in those properties.  You can set these properties in either the markup or the code-behind.  For example in code-behind, you could write:

Button1.OnClientClick = "SayHello()"

Or, if your javascript is just a one or two liner, you could put the lines of code directly into the property like this:

Button1.OnClientClick = "alert('Hello')"

Sometimes, a server control will not expose a property to execute the script when you want it to.  For example, let's say you want javascript to execute when you change the value of a TextBox control.  A TextBox control will actually render as an html input tag.  The input tag has an attribute of "onchange" which is part of a group of attributes called "intrinsic events".  We can actually stick some javascript in these events with the following code:

TextBox1.Attributes.Add("onchange", "SayHello()")

Now when the TextBox's contents are changed and user tabs off, your script will execute.

One final note.  There is no way to directly call a javascript function from your code behind.  However, by using the above methods, and "injecting" the javascript at run-time, you can effectively accomplish this.