About the author

Miron Abramson
Me
Software Engineer,
CTO at PixeliT
and .NET addicted for long time.
Open source projects:
MbCompression - Compression library

Recent comments

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2014

Creative Commons License

Blog Flux Directory
Technology Blogs - Blog Top Sites

Cropping image using jQuery, Jcrop and ASP.NET

Letting the client cropping his images on the site was never an easy task. With jQuery and the plugin Jcrop by Deep Liquid it is easier than ever to do it in ASP.NET site. Here is how to do it:

First we need to include jQuery library,Jcrop script file & Jquery css file in the page. Then, we need to tell Jcrop wich element is our image to crop, and what method to be fire when we are changing the cropping area:

//
//  Initialize Jcrop
//
$(function() {
$('#theImage').Jcrop({
        onChange: showCoords,
        onSelect: showCoords
    });
});

//
//  Will fire every move of the cropping area
//
function showCoords(c) {
    $('#x1').val(c.x);
    $('#y1').val(c.y);
    $('#x2').val(c.x2);
    $('#y2').val(c.y2);
    $('#w').val(c.w);
    $('#h').val(c.h);
};

x1,y1,x2,y2 are inputs from where the code behind will read the values of the cropping area.

The code behind that will actualy crop the image:

 protected void btnCrop_Click(object sender, EventArgs e)
{
    int X1 = Convert.ToInt32(Request.Form["x1"]);
    int Y1 = Convert.ToInt32(Request["y1"]);
    int X2 = Convert.ToInt32(Request.Form["x2"]);
    int Y2 = Convert.ToInt32(Request.Form["y2"]);
    int X = System.Math.Min(X1, X2);
    int Y = System.Math.Min(Y1, Y2);
    int w = Convert.ToInt32(Request.Form["w"]);
    int h = Convert.ToInt32(Request.Form["h"]);

    // That can be any image (jpg,jpeg,png,gif) from anywhere in the server
    string originalFile = Server.MapPath("~/images/miautito.jpg");


    using (Image img = Image.FromFile(originalFile))
    {
        using (System.Drawing.Bitmap _bitmap = new System.Drawing.Bitmap(w, h))
        {
            _bitmap.SetResolution(img.HorizontalResolution, img.VerticalResolution);
            using (Graphics _graphic = Graphics.FromImage(_bitmap))
            {
                _graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                _graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                _graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                _graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                _graphic.DrawImage(img, 0, 0, w, h);
                _graphic.DrawImage(img, new Rectangle(0, 0, w, h), X, Y, w, h, GraphicsUnit.Pixel);

                string extension = Path.GetExtension(originalFile);
                string croppedFileName = Guid.NewGuid().ToString();
                string path = Server.MapPath("~/cropped/");


                // If the image is a gif file, change it into png
                if (extension.EndsWith("gif", StringComparison.OrdinalIgnoreCase))
                {
                    extension = ".png";
                }

                string newFullPathName = string.Concat(path, croppedFileName, extension);

                using (EncoderParameters encoderParameters = new EncoderParameters(1))
                {
                    encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
                    _bitmap.Save(newFullPathName, GetImageCodec(extension), encoderParameters);
                }
            }
        }
    }
}

Method to find the right codec to save the image in the maximum quality:

/// <summary>
/// Find the right codec
/// </summary>
/// <param name="extension"></param>
/// <returns></returns>
public static ImageCodecInfo GetImageCodec(string extension)
{
    extension = extension.ToUpperInvariant();
    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
    foreach (ImageCodecInfo codec in codecs)
    {
        if (codec.FilenameExtension.Contains(extension))
        {
            return codec;
        }
    }
    return codecs[1];
}

You can see some demos of the Jquery Here, and actual demo using the above code in here: ASP.NET Demo.

Complete working source is available in the link below:

Crop.zip (165.24 kb)

Currently rated 4.6 by 17 people

  • Currently 4.647059/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: ASP.NET | C# | Client side | Server side
Posted by Miron on Monday, April 20, 2009 8:17 AM
Permalink | Comments (5) | Post RSSRSS comment feed

High performance css minifier

It is known that minifying the JavaScript and CSS files can really reduce the files size and improve the general site performance. Lot of sites (BlogEngine.NET among them)  do it on run-time and not it the build time. At this point, I want to recommend the JavaScript minifier JSMIN by Douglas Crockford. It does the job very good, and by far, much faster than all the RegularExpression \ Replace minifiers. Because in my Compression project MbCompression I do the minifying on run-time, I decided to use jsmin minifier.

The Css minifier

All the Css minifiers I found are using Regular Expression\ Replace to remove the unneeded characters. This is working fine, but have a realy bad performance, special on run-time. The speed is slow (special using the Regular Expression), and another important thing is, every Replace creates a very big string in the memory! (Strings are immutable, remember?), so if you have several Replaces, it creates several big strings in the server memory!

To improve performance, I took  JSMIN idea, that are not using any strings in the memory, and perform the minifying much faster, and created a CSS minifier that produce a small CSS file, much faster, and with much less memory overhead.

This minifier was tested on several CSS files. Feel free to download it and use it. If there is any file that not been minify correctly, send it to me, and I will try to improve the minifier.

CssMinifier.cs (9.59 kb)

Currently rated 4.9 by 12 people

  • Currently 4.916667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: C# | Client side | Performance
Posted by Miron on Sunday, June 29, 2008 4:48 AM
Permalink | Comments (19) | Post RSSRSS comment feed

Prevent from the user to submit any 'not legal' input, using client side validation

We are all know that client validations are good way to validate input, of cource you must re validate in server side also, but the client side will save some wasted post backs. Usually, we validate each input separate (writing manually script, or a validator control). What if you have a rule that is for all inputs in the page, or in the site? for example, you want to prevent the user to submit any input that contains 'fuc*' , 'shi*' or what ever words that are not 'legal' for you, or input that is not valid for the ASP.NET such '<'or  '/>' ?

I wrote some JavaScript code, that validate all the TextBox and Textarea controls in the page, and prevent it to be submitted if one (or more) of the input/s is in your 'not legal words' list. What the script actualy does, is checking the values of all Textboxes in the page, and if one input value contains one of the 'bad' words that defined in the 'MachingWords' variable, it will pop an alert, and will cancel the submit.  Here we go:

 // List of 'bad' words.  Append here all the words you want from the user to submit as an input, seperates by '|' char.

var MachingWords = "<|/>|fuck|shit|ass";


function FormValidationController()
{
    this.IsValid = true;
    this._notValidValuesCollection = [];
    this._notValidValuesHash = new Array();
    this.AddNotValidValue = function(value){   
        if( !this._notValidValuesHash[value] ){
            this._notValidValuesHash[value] = 1;
            this._notValidValuesCollection.push(value);
        }
    }
    this.PopMessage = function() {
        var wordsList = '';
        for( var i = 0 ; i < this._notValidValuesCollection.length ; i++ ) {
            wordsList = wordsList.length < 1 ? "'" + this._notValidValuesCollection[i] + "'" : wordsList + ", '" + this._notValidValuesCollection[i] + "'";
        }
        var notValidMessage = "The input{0} {1} {2} not valid.";
        alert( String.Format(notValidMessage,(this._notValidValuesCollection.length > 1 ? "s" : ""),(wordsList),(this._notValidValuesCollection.length > 1 ? "are" : "is")) );
    }
    this.Validate = function(){
        this.IsValid = true;
        this._notValidValuesCollection = [];
        this._notValidValuesHash = new Array();
        var inputElementsCollection = document.getElementsByTagName("INPUT");
        if( inputElementsCollection ){
            for (var index=0; index<inputElementsCollection.length; index++) {
                var el=inputElementsCollection[index];
                if( el.type.toLowerCase() == 'text' )
                    this.ValidateInput(el);
            }
        }
        var textareaElementsCollection = document.getElementsByTagName("TEXTAREA");
        if( textareaElementsCollection ){
            for (var index=0; index<textareaElementsCollection.length; index++) {
                var el=textareaElementsCollection[index];
                this.ValidateInput(el);
            }
        }
    }
    this.ValidateInput = function (element) {
        if( element ){
            if( !this.IsValidString(element.value) ) {
                this.AddNotValidValue(element.value);
                if( this.IsValid ){
                    this.IsValid = false;
                    element.focus();
                    element.select();
                }
            }
        }
    }
}

FormValidationController.RegularExpression = new RegExp(MachingWords,"i","g");
// Validate the current input
FormValidationController.prototype.IsValidString = function(strInput)
{   
    if( !strInput || typeof( strInput ) == 'string' ){
          if( strInput.length < 1 )
            return true;
    }
    if( FormValidationController.RegularExpression.test ( strInput ) )
        return false;
    return true;
}
var c = new FormValidationController();

//
// String.Format implementation
//
String.Format = function(format,args){
    var result = format;
    for(var i = 1 ; i < arguments.length ; i++) {
        result = result.replace(new RegExp( '\\{' + (i-1) + '\\}', 'g' ),arguments[i]);
    }
    return result;
}

And the method that using it and excuting the validation:

 //
//  Excute the validation
//
function ValidatePage() {
    c.Validate();
    if( !c.IsValid ) {
           c.PopMessage();
           return false;
      }
    return true;
}

 The implementation is very simple. Add the script to your page, and add to  the OnLoad page event  the following line, and that's it.

ClientScript.RegisterOnSubmitStatement(this.GetType(), "ValidatePage", "return ValidatePage();");

Javascript file with the code available here: 

FormValidation.js (3.23 kb)

Currently rated 4.8 by 4 people

  • Currently 4.75/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: ASP.NET | Client side
Posted by Miron on Saturday, May 17, 2008 9:53 AM
Permalink | Comments (2) | Post RSSRSS comment feed

Some basic but useful C# methods implemented in JavaScript

While I was working on a full Ajax interface based on pure ajax calls and not on any framework,  I implemented some basic and simple methods that we use all the time in the server code, and just not exist in javascript. It's not big deal, but since I wrote them, I use them all the time.

Even it is very simple, I decided to share it here. Hope it will save other coders few minutes:

Cache object:

//
//  Cach object implementation
//
var Cache = new function()
{
    var _cache = new Array();
    this.Insert = function ( key, value ){
        _cache[key] = value;
        }
    this.Get = function ( key ){
        return _cache[key];
        }
    this.Contains = function ( key ){
        if( !_cache[key] || _cache[key] == null ) return false;
        else return true;
        }
};

The use of the cache is as simple as it is in the server side, and it is realy useful to save some calls to the server:

 Cache.Insert("myKey","MyValue");
 if( Cache.Contains("myKey") ) alert( "Yeee the value of my key is in the cache:" + Cache.Get("myKey") );  

String.Format(string,params)  &  String.IsNullOrEmpty(string) :

//
// String.Format implementation
//
String.Format = function(format,args){
    var result = format;
    for(var i = 1 ; i < arguments.length ; i++) {
        result = result.replace(new RegExp( '\\{' + (i-1) + '\\}', 'g' ),arguments[i]);
    }
    return result;
}

//
// String.IsNullOrEmpty implementation
//
String.IsNullOrEmpty = function(value){
    if(value){
        if( typeof( value ) == 'string' ){
             if( value.length > 0 )
                return false;
        }
       if( value != null )
           return false;
    }
    return true;
}

Again, the use is the same as server side:

alert( String.Format("Hello {0}. Yes, hello {0} again. My name is {1}","world","Miron") );
if( String.IsNullOrEmpty('') ) alert('Empty string');

StartsWith(string suffix,bool ignoreCase)EndsWith(string suffix,bool ignoreCase)  and Trim() :

//
// string.StartWith implementation
//
String.prototype.StartsWith = function(prefix,ignoreCase) {
    if( !prefix ) return false;
    if( prefix.length > this.length ) return false;
    if( ignoreCase ) {
        if( ignoreCase == true ) {
            return (this.substr(0, prefix.length).toUpperCase() == prefix.toUpperCase());
        }
    }
    return (this.substr(0, prefix.length) === prefix);
}

 //
// string.EndsWith implementation
//
String.prototype.EndsWith = function(suffix,ignoreCase) {
    if( !suffix ) return false;
    if( suffix.length > this.length ) return false;
    if( ignoreCase ) {
        if( ignoreCase == true ) {
            return (this.substr(this.length - suffix.length).toUpperCase() == suffix.toUpperCase());
        }
    }
    return (this.substr(this.length - suffix.length) === suffix);
}

 //
// string.Trim implementation
//
String.prototype.Trim = function() {
    return this.replace(/^\s+|\s+$/g, '');
}

The last three are working on an istance of a string:

var test = "Hello Words ";
test = test.Trim();
var end = test.EndsWith("ds",true);
var begin = test.BeginsWith("rr",false);

All the code can be downloaded here: 

Utils.js (1.94 kb)

Currently rated 4.8 by 8 people

  • Currently 4.75/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Client side
Posted by Miron on Sunday, May 04, 2008 4:43 PM
Permalink | Comments (3) | Post RSSRSS comment feed

A Custom Length Validator with server & client side validation

Almost evey TextBox input is going to be stored in Database (if it is not based on XML).  In the DB we need to define a maximum length for any characters field, so, we need to be sure that the input text in the TextBox in not longer then the maximum defined length in the DB where it going to be stored.

We all use Validators. I don't understand why MS didn't include in the built in controls a simple length validator (yes, I know it can be done by the RegularExpressionValidator, but why complicate things?) that simply validate maximum or minimum length of input text. Luckly, creating our custom validation control is much simplier then it sound. All we need to do is a class that inhirite from CustomValidator, override some methods, add some properties, create a JavaScript validation method, compile it into DLL and use it as any other Validator.

Override the ControlPropertiesValid() method:

private TextBox _textBox; 

 /// <summary>
 /// Check if the control is valid for validation
 /// </summary>
 /// <returns></returns>
  protected override bool ControlPropertiesValid()
  {
      Control ctrl = FindControl(ControlToValidate);
      if (ctrl != null)
      {
          _textBox = ctrl as TextBox;
          return (_textBox != null);
      }
      else
          return false;
  }

 override the EvaluateIsValid() method:

  /// <summary>
  /// Perform the validation
  /// </summary>
  /// <returns></returns>
  protected override bool EvaluateIsValid()
  {
      if ( string.IsNullOrEmpty(_textBox.Text) )
      {
          if (MinLength > 0)
              return false;
          else
              return true;
      }
      if (_textBox.Text.Length < MinLength || _textBox.Text.Length > MaxLength)
      {
          return false;
      }
      return true;
  }

 Override the AddAttributesToRender(HtmlTextWriter writer) method to support the client side validation:

  /// <summary>
  /// Add the maximum and minimum attribute for the control
  /// </summary>
  /// <param name="writer"></param>
  protected override void AddAttributesToRender(HtmlTextWriter writer)
  {
      base.AddAttributesToRender(writer);
      if (base.RenderUplevel)
      {
          writer.AddAttribute("MinLength", this.MinLength.ToString());
          writer.AddAttribute("MaxLength", this.MaxLength.ToString());
      }
  }

Register in the OnLoad event our client site script file:

  /// <summary>
  /// Add the controls script file to the page
  /// </summary>
  /// <param name="e"></param>
  protected override void OnLoad(EventArgs e)
  {
      if (Enabled && base.EnableClientScript)
      {
          Page.ClientScript.RegisterClientScriptResource(typeof(LengthValidator), "LengthValidator.LengthValidator.js");
      }
      base.OnLoad(e);
  }

 and ofcourse the client side validation method:

function ValidateLength(source, args) {
    var control = document.getElementById(source.controltovalidate);
    if( control )
    {
         args.IsValid = ( control.value.length >= source.getAttribute('MinLength') && control.value.length <= source.getAttribute('MaxLength') );
    }
}

The full class library project source  can be downloaded below. Just compile it, add it to the toolbox and use it as any other Validator

LengthValidator.zip (2.96 kb)

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by Miron on Saturday, December 08, 2007 7:52 AM
Permalink | Comments (2) | Post RSSRSS comment feed

Check all CheckBoxes in GridView in client side

'Lists' controls as GridView, DataList or Repeater sometimes have a column with CheckBoxes. It is very usefull to let the user 'Select all' or 'Un Select all'. One way to do it is to loop on the control in the code behind and check/un check the CheckBoxes, or faster way is to do it on the client side, using the same idea of my preview  post:

//
//  Select or unSelect checkboxes in grid view
//
function CheckAllCheckBoxes(aspxCheckBoxID, checkVal)
{
    var reg = new RegExp( aspxCheckBoxID + "$" );
    var pageElements = document.getElementsByTagName("*");
    for(i = 0; i < pageElements.length; i++) {
        elm = pageElements[i];
        if (elm.type == 'checkbox')
        {
            if (reg.test(elm.name))
            {  
                elm.checked = checkVal
            }
        }
    }
 }

Where 'aspxCheckBoxID' is the CheckBox server side name, and 'checkVal is value if to check all or uncheck all. So simple.

Happy coding 

Currently rated 4.8 by 5 people

  • Currently 4.8/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: ASP.NET | Client side
Posted by Miron on Saturday, September 01, 2007 5:55 PM
Permalink | Comments (1) | Post RSSRSS comment feed

Server side controls in client side

Long time ago, When I started to work with ASP.NET 2.0, I was very engry with MS because most of the Server-Side controls changed their names in the client side: 'imgbtnFind' in the code-behind became 'ctl00_cphMPContent_imgbtnFind' in the client side, etc... (as I remeber, it wasn't like this in ASP.NET 1.1) How the Fu-- we can write JavaScript code that works with those controls??? If the JS code is in the page,  we can use '<%= imgbtnFind.ClientID %>', but what if the JS code is in external .js file ?

'We have a problem Houston!'

I came up with the following function, and I can't write even single JS function without using it: 

//  Get element in the page ( the same as document.getElementById(), but can be use
//  for server-side controls that .NET change their names) 
function $getElement( elementID, elementIndex ){
    if( document.getElementById(elementID) )
        return document.getElementById(elementID);
    var reg = new RegExp(  elementID + "$" );
    var counter = 0;
    var pageElements = document.getElementsByTagName("*");
    for(i = 0; i < pageElements.length; i++) {
        elm = pageElements[i];
        if( elm.id ) {
            if ( reg.test(elm.id) ) {  
                if( typeof(elementIndex) == 'number' ) {
                    if( counter == elementIndex ) { return elm; }
                }else { return elm; }
                counter ++;
            }
        }
    }

Just place it in your javascript file that common to all your pages (as usualy web application have), and you can freely use $getElement(elementID) instead  of document.getElementById(elementID) - for client side controls and for server-side controls as well. The rendering process in the aspx page  concatenate all the parents containers names to the prefix of the control, So that function is checking for the suffix of the control name. The only  thing to take care is to don't have two controls that complete server name of one is the exact suffix of the other, Or if you must to, you can use the second parameter of the function to control duplicate names... So now, to use the server control 'imgbtnFind' in the client side, just use $getElement('imgbtnFind') ...

Happy coding ! 

Currently rated 4.4 by 5 people

  • Currently 4.4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: ASP.NET | Client side
Posted by Miron on Thursday, August 30, 2007 11:53 PM
Permalink | Comments (1) | Post RSSRSS comment feed